vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf |binary
 vcl/qa/cppunit/pdfexport/pdfexport.cxx        |   61 ++++++++++++++++++++++++++
 vcl/source/gdi/pdfwriter_impl.cxx             |   29 ++++++++++--
 3 files changed, 85 insertions(+), 5 deletions(-)

New commits:
commit d9cab7dc6dbbbe3d80aa765cfd0b3c9f85d73c06
Author:     Dennis Francis <dennis.fran...@collabora.com>
AuthorDate: Thu Dec 1 11:47:12 2022 +0530
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Mon Jan 9 17:08:24 2023 +0000

    vcl: use /MediaBox origin in the ctm...
    
    of the inner XObject, else the clip polypolygon may clip out partly or
    whole contents. Adjusting the clip polypolygon is not straightforward.
    
    Change-Id: If3b208ba850c3579c9e16c15e4fb2f947dad4406
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143561
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit a67dcc248a103098de883a4dd2fa9ff2e1cc1f90)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144436
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145202

diff --git a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf 
b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf
index 598358a636aa..0390ccad8410 100644
Binary files a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf and 
b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 428f9d5a132a..ce070a711911 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -4186,6 +4186,67 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, 
testRexportFilterSingletonArray)
     CPPUNIT_ASSERT(it != pEnd);
 }
 
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testRexportMediaBoxOrigin)
+{
+    // We need to enable PDFium import (and make sure to disable after the 
test)
+    bool bResetEnvVar = false;
+    if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+    {
+        bResetEnvVar = true;
+        osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, 
OUString("1").pData);
+    }
+    comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+        if (bResetEnvVar)
+            osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData);
+    });
+
+    // Load the PDF and save as PDF
+    vcl::filter::PDFDocument aDocument;
+    load(u"ref-to-kids.pdf", aDocument);
+
+    std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size());
+
+    // Directly go to the inner XObject Im10 that contains the rectangle 
drawings in page 2.
+    auto pInnerIm = aDocument.LookupObject(10);
+    CPPUNIT_ASSERT(pInnerIm);
+
+    constexpr sal_Int32 aOrigin[2] = { -800, -600 };
+    sal_Int32 aSize[2] = { 0, 0 };
+
+    auto pBBox = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pInnerIm->Lookup("BBox"));
+    CPPUNIT_ASSERT(pBBox);
+    const auto& rElements2 = pBBox->GetElements();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements2.size());
+    for (sal_Int32 nIdx = 0; nIdx < 4; ++nIdx)
+    {
+        const auto* pNumElement = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements2[nIdx]);
+        CPPUNIT_ASSERT(pNumElement);
+        if (nIdx < 2)
+            CPPUNIT_ASSERT_EQUAL(aOrigin[nIdx], 
static_cast<sal_Int32>(pNumElement->GetValue()));
+        else
+            aSize[nIdx - 2] = static_cast<sal_Int32>(pNumElement->GetValue()) 
- aOrigin[nIdx - 2];
+    }
+
+    auto pMatrix = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pInnerIm->Lookup("Matrix"));
+    CPPUNIT_ASSERT(pMatrix);
+    const auto& rElements = pMatrix->GetElements();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(6), rElements.size());
+    sal_Int32 aMatTranslate[6]
+        = { // Rotation by $\theta$ $cos(\theta), sin(\theta), -sin(\theta), 
cos(\theta)$
+            0, -1, 1, 0,
+            // Translate x,y
+            -aOrigin[1] - aSize[1] / 2 + aSize[0] / 2, aOrigin[0] + aSize[0] / 
2 + aSize[1] / 2
+          };
+
+    for (sal_Int32 nIdx = 0; nIdx < 6; ++nIdx)
+    {
+        const auto* pNumElement = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[nIdx]);
+        CPPUNIT_ASSERT(pNumElement);
+        CPPUNIT_ASSERT_EQUAL(aMatTranslate[nIdx], 
static_cast<sal_Int32>(pNumElement->GetValue()));
+    }
+}
+
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index f4a3145c5085..d95a74aeb6af 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -8873,6 +8873,21 @@ void PDFWriterImpl::writeReferenceXObject(const 
ReferenceXObjectEmit& rEmit)
             return;
         }
 
+        double aOrigin[2] = { 0.0, 0.0 };
+        if (auto* pArray = 
dynamic_cast<filter::PDFArrayElement*>(pPage->Lookup("MediaBox")))
+        {
+            const auto& rElements = pArray->GetElements();
+            if (rElements.size() >= 4)
+            {
+                // get x1, y1 of the rectangle.
+                for (sal_Int32 nIdx = 0; nIdx < 2; ++nIdx)
+                {
+                    if (const auto* pNumElement = 
dynamic_cast<filter::PDFNumberElement*>(rElements[nIdx]))
+                        aOrigin[nIdx] = pNumElement->GetValue();
+                }
+            }
+        }
+
         std::vector<filter::PDFObjectElement*> aContentStreams;
         if (filter::PDFObjectElement* pContentStream = 
pPage->LookupObject("Contents"))
             aContentStreams.push_back(pContentStream);
@@ -8974,7 +8989,7 @@ void PDFWriterImpl::writeReferenceXObject(const 
ReferenceXObjectEmit& rEmit)
             // Now transform the object: rotate around the center and make 
sure that the rotation
             // doesn't affect the aspect ratio.
             basegfx::B2DHomMatrix aMat;
-            aMat.translate(-0.5 * aBBox.getWidth(), -0.5 * aBBox.getHeight());
+            aMat.translate(-0.5 * aBBox.getWidth() - aOrigin[0], -0.5 * 
aBBox.getHeight() - aOrigin[1]);
             aMat.rotate(basegfx::deg2rad(nAngle));
             aMat.translate(0.5 * nWidth, 0.5 * nHeight);
 
@@ -8997,10 +9012,14 @@ void PDFWriterImpl::writeReferenceXObject(const 
ReferenceXObjectEmit& rEmit)
         auto & rResources = rExternalPDFStream.getCopiedResources();
         aCopier.copyPageResources(pPage, aLine, rResources);
 
-        aLine.append(" /BBox [ 0 0 ");
-        aLine.append(aBBox.getWidth());
-        aLine.append(" ");
-        aLine.append(aBBox.getHeight());
+        aLine.append(" /BBox [ ");
+        aLine.append(aOrigin[0]);
+        aLine.append(' ');
+        aLine.append(aOrigin[1]);
+        aLine.append(' ');
+        aLine.append(aBBox.getWidth() + aOrigin[0]);
+        aLine.append(' ');
+        aLine.append(aBBox.getHeight() + aOrigin[1]);
         aLine.append(" ]");
 
         if (!g_bDebugDisableCompression)

Reply via email to