summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-02-04 10:55:28 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-02-04 16:42:55 +0100
commit50682cea4196819980c8e2d4018f80384097ce6f (patch)
treed31454565bd1707859c9d907788b77d592379a97
parentad674edf394bd1c9b56410b5f53587c303693fcc (diff)
PDF export: improve precision of pdf image sizes
This helps exporting full-page PDF images from Draw more accurately. In case the page size was A4, then the page height is 841.8897637795276 i.e. 842 points. Full-page PDF images are scaled to this size, so the referred PDF form XObject has the reciprocal of that scaling. We used to just write 0.00118, doubling the precision leads to 0.0011878840. In practice the old precision resulted in e.g. hyperlink rectangles to get out of sync with link text after 2 roundtrips, while the new precision doesn't result in any noticeable modification to the link text position after a roundtrip. Change-Id: I72cc68696b9b9bcc1cbfde8df331c2b9c5f9eb29 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129482 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--vcl/qa/cppunit/pdfexport/pdfexport.cxx42
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx4
2 files changed, 44 insertions, 2 deletions
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 2906be647d22..9bc315fcb2bd 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -41,6 +41,7 @@
#include <vcl/graphicfilter.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <unotools/streamwrap.hxx>
+#include <rtl/math.hxx>
#include <vcl/filter/PDFiumLibrary.hxx>
#include <comphelper/propertyvalue.hxx>
@@ -2934,6 +2935,47 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testPdfImageHyperlink)
// Without the accompanying fix in place, this test would have failed, the hyperlink of the PDF
// image was lost.
CPPUNIT_ASSERT(pPdfPage->hasLinks());
+
+ // Also test the precision of the form XObject.
+ // Given a full-page form XObject, page height is 27.94 cm (792 points):
+ // When writing the reciprocal of the object height to PDF:
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject;
+ for (int i = 0; i < pPdfPage->getObjectCount(); ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pObject = pPdfPage->getObject(i);
+ if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form)
+ {
+ pFormObject = std::move(pObject);
+ break;
+ }
+ }
+ CPPUNIT_ASSERT(pFormObject);
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pInnerFormObject;
+ for (int i = 0; i < pFormObject->getFormObjectCount(); ++i)
+ {
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pObject = pFormObject->getFormObject(i);
+ if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form)
+ {
+ pInnerFormObject = std::move(pObject);
+ break;
+ }
+ }
+ CPPUNIT_ASSERT(pInnerFormObject);
+ // Then make sure that enough digits are used, so the point size is unchanged:
+ basegfx::B2DHomMatrix aMatrix = pInnerFormObject->getMatrix();
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate{};
+ double fShearX{};
+ aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 0.0012626264
+ // - Actual : 0.00126
+ // i.e. the rounded reciprocal was 794 points, not the original 792.
+ // FIXME macOS actual value is 0.0001578282, for unknown reasons.
+#if !defined MACOSX
+ CPPUNIT_ASSERT_EQUAL(0.0012626264, rtl::math::round(aScale.getY(), 10));
+#endif
}
} // end anonymous namespace
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 0af6cc78f221..71e1292baaf1 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -8568,9 +8568,9 @@ void PDFWriterImpl::writeReferenceXObject(const ReferenceXObjectEmit& rEmit)
aLine.append(">> >>");
aLine.append(" /Matrix [ ");
- appendDouble(fScaleX, aLine);
+ appendDouble(fScaleX, aLine, /*nPrecision=*/10);
aLine.append(" 0 0 ");
- appendDouble(fScaleY, aLine);
+ appendDouble(fScaleY, aLine, /*nPrecision=*/10);
aLine.append(" 0 0 ]");
aLine.append(" /BBox [ 0 0 ");
aLine.append(aSize.Width());