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)