From 6294ecd7b4da38de98b24ddfb9f201cef98c1f41 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 20 Jul 2020 11:36:13 +0200 Subject: tdf#50879 PDF export: ensure only built-in fonts are used for forms Alternative would be to embed the whole font, which is unusual: PDF typically just embeds the used subset. Change-Id: Ic0b7e121b3ae38804c1a396ea36104ebcc0b9588 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99032 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- vcl/qa/cppunit/pdfexport/data/form-font-name.odt | Bin 0 -> 8548 bytes vcl/qa/cppunit/pdfexport/pdfexport.cxx | 46 +++++++++++++++++++++++ vcl/source/gdi/pdfwriter_impl.cxx | 13 +++++-- 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 vcl/qa/cppunit/pdfexport/data/form-font-name.odt (limited to 'vcl') diff --git a/vcl/qa/cppunit/pdfexport/data/form-font-name.odt b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt new file mode 100644 index 000000000000..a7430c9a8a6e Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index dc6c01fcf719..607d89f8b630 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -130,6 +130,7 @@ public: void testVersion15(); void testDefaultVersion(); void testMultiPagePDF(); + void testFormFontName(); CPPUNIT_TEST_SUITE(PdfExportTest); @@ -175,6 +176,7 @@ public: CPPUNIT_TEST(testVersion15); CPPUNIT_TEST(testDefaultVersion); CPPUNIT_TEST(testMultiPagePDF); + CPPUNIT_TEST(testFormFontName); CPPUNIT_TEST_SUITE_END(); }; @@ -2264,6 +2266,50 @@ void PdfExportTest::testMultiPagePDF() #endif } +void PdfExportTest::testFormFontName() +{ + // Import the bugdoc and export as PDF. + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "form-font-name.odt"; + mxComponent = loadFromDesktop(aURL); + + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result with pdfium. + SvFileStream aFile(maTempFile.GetURL(), StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFile); + ScopedFPDFDocument pPdfDocument( + FPDF_LoadMemDocument(aMemory.GetData(), aMemory.GetSize(), /*password=*/nullptr)); + CPPUNIT_ASSERT(pPdfDocument); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, FPDF_GetPageCount(pPdfDocument.get())); + ScopedFPDFPage pPdfPage(FPDF_LoadPage(pPdfDocument.get(), /*page_index=*/0)); + CPPUNIT_ASSERT(pPdfPage); + + // The page has one annotation. + CPPUNIT_ASSERT_EQUAL(1, FPDFPage_GetAnnotCount(pPdfPage.get())); + ScopedFPDFAnnotation pAnnot(FPDFPage_GetAnnot(pPdfPage.get(), 0)); + + // Examine the default appearance. + CPPUNIT_ASSERT(FPDFAnnot_HasKey(pAnnot.get(), "DA")); + CPPUNIT_ASSERT_EQUAL(FPDF_OBJECT_STRING, FPDFAnnot_GetValueType(pAnnot.get(), "DA")); + size_t nDALength = FPDFAnnot_GetStringValue(pAnnot.get(), "DA", nullptr, 0); + std::vector aDABuf(nDALength); + FPDFAnnot_GetStringValue(pAnnot.get(), "DA", aDABuf.data(), nDALength); + OUString aDA(reinterpret_cast(aDABuf.data())); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 0 0 rg /TiRo 12 Tf + // - Actual : 0 0 0 rg /F2 12 Tf + // i.e. Liberation Serif was exposed as a form font as-is, without picking the closest built-in + // font. + CPPUNIT_ASSERT_EQUAL(OUString("0 0 0 rg /TiRo 12 Tf"), aDA); +} + CPPUNIT_TEST_SUITE_REGISTRATION(PdfExportTest); } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 686635b5b5dc..e40cc7c00872 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -3602,6 +3602,13 @@ Font PDFWriterImpl::replaceFont( const vcl::Font& rControlFont, const vcl::Font& sal_Int32 PDFWriterImpl::getBestBuildinFont( const vcl::Font& rFont ) { sal_Int32 nBest = 4; // default to Helvetica + + if (rFont.GetFamilyType() == FAMILY_ROMAN) + { + // Serif: default to Times-Roman. + nBest = 8; + } + OUString aFontName( rFont.GetFamilyName() ); aFontName = aFontName.toAsciiLowerCase(); @@ -3748,14 +3755,14 @@ void PDFWriterImpl::createDefaultEditAppearance( PDFWidget& rEdit, const PDFWrit // prepare font to use, draw field border Font aFont = drawFieldBorder( rEdit, rWidget, rSettings ); - sal_Int32 nBest = getSystemFont( aFont ); + // Get the built-in font which is closest to aFont. + sal_Int32 nBest = getBestBuildinFont(aFont); // prepare DA string OStringBuffer aDA( 32 ); appendNonStrokingColor( replaceColor( rWidget.TextColor, rSettings.GetFieldTextColor() ), aDA ); aDA.append( ' ' ); - aDA.append( "/F" ); - aDA.append( nBest ); + aDA.append(pdf::BuildinFontFace::Get(nBest).getNameObject()); OStringBuffer aDR( 32 ); aDR.append( "/Font " ); -- cgit