[Libreoffice-commits] core.git: vcl/qa vcl/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Thu Apr 16 19:59:35 UTC 2020


 vcl/qa/cppunit/pdfexport/data/6m-wide.odg |binary
 vcl/qa/cppunit/pdfexport/pdfexport.cxx    |   23 +++++++++++++
 vcl/source/gdi/pdfwriter_impl.cxx         |   51 ++++++++++++++++++++++++++----
 vcl/source/gdi/pdfwriter_impl.hxx         |    7 +++-
 4 files changed, 74 insertions(+), 7 deletions(-)

New commits:
commit 4830592b780833cf5eee2aef30bc9c5d444dfb24
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Apr 16 18:13:01 2020 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Apr 16 21:59:00 2020 +0200

    PDF export: fix handling of page sizes larger than 508 cm
    
    The value of these coordinates are not allowed to be larger than 14 400,
    and Adobe Reader complains about them.
    
    Use UserUnit to declare in case we won't work with points anymore, but
    with a larger unit. This will mean UserUnit=2 in practice, since e.g.
    Draw has is page size limited to 600x600cm, so larger values won't
    happen, at least not for now.
    
    Change-Id: I8ee159f2571f4070aded85388792a215de86f7ff
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92383
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/qa/cppunit/pdfexport/data/6m-wide.odg b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg
new file mode 100644
index 000000000000..49fb9bfff92e
Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index a3ea246ed612..a2910b44fb81 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -143,6 +143,7 @@ public:
     void testReduceSmallImage();
     void testReduceImage();
     void testLinkWrongPage();
+    void testLargePage();
 
     CPPUNIT_TEST_SUITE(PdfExportTest);
     CPPUNIT_TEST(testTdf106059);
@@ -183,6 +184,7 @@ public:
     CPPUNIT_TEST(testReduceSmallImage);
     CPPUNIT_TEST(testReduceImage);
     CPPUNIT_TEST(testLinkWrongPage);
+    CPPUNIT_TEST(testLargePage);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -1996,6 +1998,27 @@ void PdfExportTest::testLinkWrongPage()
     CPPUNIT_ASSERT(!HasLinksOnPage(pPdfPage2));
 }
 
+void PdfExportTest::testLargePage()
+{
+    // Import the bugdoc and export as PDF.
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "6m-wide.odg";
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export");
+    DocumentHolder pPdfDocument = exportAndParse(aURL, aMediaDescriptor);
+
+    // The document has 1 page.
+    CPPUNIT_ASSERT_EQUAL(1, FPDF_GetPageCount(pPdfDocument.get()));
+
+    // Check the value (not the unit) of the page size.
+    FS_SIZEF aSize;
+    FPDF_GetPageSizeByIndexF(pPdfDocument.get(), 0, &aSize);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 8503.94
+    // - Actual  : 17007.875
+    // i.e. the value for 600 cm was larger than the 14 400 limit set in the spec.
+    CPPUNIT_ASSERT_DOUBLES_EQUAL(8503.94, static_cast<double>(aSize.width), 0.01);
+}
+
 void PdfExportTest::testPdfImageResourceInlineXObjectRef()
 {
     // Create an empty document.
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index e98e822c62e1..05fca4cf21f4 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -557,6 +557,7 @@ PDFPage::PDFPage( PDFWriterImpl* pWriter, double nPageWidth, double nPageHeight,
 {
     // object ref must be only ever updated in emit()
     m_nPageObject = m_pWriter->createObject();
+    m_nUserUnit = std::ceil(std::max(nPageWidth, nPageHeight) / 14400.0);
 }
 
 void PDFPage::beginStream()
@@ -635,10 +636,15 @@ bool PDFPage::emit(sal_Int32 nParentObject )
     if( m_nPageWidth && m_nPageHeight )
     {
         aLine.append( "/MediaBox[0 0 " );
-        aLine.append( m_nPageWidth );
+        aLine.append(m_nPageWidth / m_nUserUnit);
         aLine.append( ' ' );
-        aLine.append( m_nPageHeight );
+        aLine.append(m_nPageHeight / m_nUserUnit);
         aLine.append( "]" );
+        if (m_nUserUnit > 1)
+        {
+            aLine.append("\n/UserUnit ");
+            aLine.append(m_nUserUnit);
+        }
     }
     switch( m_eOrientation )
     {
@@ -1116,6 +1122,18 @@ void PDFPage::appendMatrix3(Matrix3 const & rMatrix, OStringBuffer& rBuffer)
     appendPoint(Point(long(rMatrix.get(4)), long(rMatrix.get(5))), rBuffer);
 }
 
+double PDFPage::getHeight() const
+{
+    double fRet = m_nPageHeight ? m_nPageHeight : vcl::pdf::g_nInheritedPageHeight;
+
+    if (m_nUserUnit > 1)
+    {
+        fRet /= m_nUserUnit;
+    }
+
+    return fRet;
+}
+
 PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext,
                                const css::uno::Reference< css::beans::XMaterialHolder >& xEnc,
                                PDFWriter& i_rOuterFace)
@@ -1612,6 +1630,14 @@ void PDFWriterImpl::newPage( double nPageWidth, double nPageHeight, PDFWriter::O
     endPage();
     m_nCurrentPage = m_aPages.size();
     m_aPages.emplace_back(this, nPageWidth, nPageHeight, eOrientation );
+
+    sal_Int32 nUserUnit = m_aPages.back().m_nUserUnit;
+    if (nUserUnit > 1)
+    {
+        m_aMapMode = MapMode(MapUnit::MapPoint, Point(), Fraction(nUserUnit, pointToPixel(1)),
+                             Fraction(nUserUnit, pointToPixel(1)));
+    }
+
     m_aPages.back().beginStream();
 
     // setup global graphics state
@@ -4409,6 +4435,7 @@ bool PDFWriterImpl::emitCatalog()
 
     sal_Int32 nMediaBoxWidth = 0;
     sal_Int32 nMediaBoxHeight = 0;
+    sal_Int32 nUserUnit = 1;
     if( m_aPages.empty() ) // sanity check, this should not happen
     {
         nMediaBoxWidth = g_nInheritedPageWidth;
@@ -4419,17 +4446,29 @@ bool PDFWriterImpl::emitCatalog()
         for (auto const& page : m_aPages)
         {
             if( page.m_nPageWidth > nMediaBoxWidth )
+            {
                 nMediaBoxWidth = page.m_nPageWidth;
+                nUserUnit = page.m_nUserUnit;
+            }
             if( page.m_nPageHeight > nMediaBoxHeight )
+            {
                 nMediaBoxHeight = page.m_nPageHeight;
+                nUserUnit = page.m_nUserUnit;
+            }
         }
     }
     aLine.append( "/MediaBox[ 0 0 " );
-    aLine.append( nMediaBoxWidth );
+    aLine.append(nMediaBoxWidth / nUserUnit);
     aLine.append( ' ' );
-    aLine.append( nMediaBoxHeight );
-    aLine.append( " ]\n"
-                  "/Kids[ " );
+    aLine.append(nMediaBoxHeight / nUserUnit);
+    aLine.append(" ]\n");
+    if (nUserUnit > 1)
+    {
+        aLine.append("/UserUnit ");
+        aLine.append(nUserUnit);
+        aLine.append("\n");
+    }
+    aLine.append("/Kids[ ");
     unsigned int i = 0;
     for (const auto & page : m_aPages)
     {
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 155ca74be58b..71de229f2c41 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -115,6 +115,11 @@ struct PDFPage
     VclPtr<PDFWriterImpl>       m_pWriter;
     double                      m_nPageWidth;           // in inch/72
     double                      m_nPageHeight;          // in inch/72
+    /**
+     * A positive number that gives the size of default user space units, in multiples of points.
+     * Typically 1, larger if page size is > 508 cm.
+     */
+    sal_Int32 m_nUserUnit;
     PDFWriter::Orientation      m_eOrientation;
     sal_Int32                   m_nPageObject;
     std::vector<sal_Int32>      m_aStreamObjects;
@@ -167,7 +172,7 @@ struct PDFPage
 
     void appendMatrix3(Matrix3 const & rMatrix, OStringBuffer& rBuffer);
 
-    double getHeight() const { return m_nPageHeight ? m_nPageHeight : vcl::pdf::g_nInheritedPageHeight; }
+    double getHeight() const;
 };
 
 /// Contains information to emit a reference XObject.


More information about the Libreoffice-commits mailing list