diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2022-12-01 11:47:12 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2023-01-03 07:25:42 +0000 |
commit | e72f77b8164820569834f5459514c18d2bfd911b (patch) | |
tree | 61f4838e5ab5efc1ba2806ad22bdc0bd8924176f /vcl | |
parent | 9fdf6b4d8317df2a6ccc866fad93292b41c97274 (diff) |
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 <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit a67dcc248a103098de883a4dd2fa9ff2e1cc1f90)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144436
Tested-by: Jenkins
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf | bin | 1451 -> 1493 bytes | |||
-rw-r--r-- | vcl/qa/cppunit/pdfexport/pdfexport.cxx | 61 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 29 |
3 files changed, 85 insertions, 5 deletions
diff --git a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf Binary files differindex 598358a636aa..0390ccad8410 100644 --- a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf +++ b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf 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) |