[Libreoffice-commits] core.git: Branch 'private/tvajngerl/staging' - drawinglayer/source filter/CppunitTest_filter_pdfimporter_test.mk filter/Library_pdfimporter.mk filter/Module_filter.mk filter/qa filter/source include/filter Repository.mk

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Mon May 10 06:47:09 UTC 2021


 Repository.mk                                    |    1 
 drawinglayer/source/tools/primitive2dxmldump.cxx |    7 
 filter/CppunitTest_filter_pdfimporter_test.mk    |   48 ++
 filter/Library_pdfimporter.mk                    |   35 ++
 filter/Module_filter.mk                          |    2 
 filter/qa/cppunit/PdfImporterTest.cxx            |  173 ++++++++++
 filter/qa/cppunit/data/PdfTest-Image.pdf         |binary
 filter/qa/cppunit/data/PdfTest-Rect.pdf          |  134 ++++++++
 filter/qa/cppunit/data/PdfTest-Text.pdf          |binary
 filter/source/pdfimporter/PDFImporter.cxx        |  384 +++++++++++++++++++++++
 include/filter/pdfimporter/PDFImporter.hxx       |   45 ++
 11 files changed, 829 insertions(+)

New commits:
commit 61c2b262461a271cf0db984f06061a370eede07c
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Mon May 3 16:42:22 2021 +0900
Commit:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
CommitDate: Mon May 10 15:44:02 2021 +0900

    Add PDF importer to read a PDF into drawinglayer primitives
    
    Change-Id: I8d2e28a39515dfef8a1b4c6b06df095dd3a4eaec

diff --git a/Repository.mk b/Repository.mk
index 0a985e59ca5f..2c9b77d026dd 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -398,6 +398,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \
 	passwordcontainer \
 	pcr \
 	pdffilter \
+	pdfimporter \
 	$(call gb_Helper_optional,SCRIPTING,protocolhandler) \
 	sax \
 	sb \
diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx
index ade8cfaed89b..992619fe89f6 100644
--- a/drawinglayer/source/tools/primitive2dxmldump.cxx
+++ b/drawinglayer/source/tools/primitive2dxmldump.cxx
@@ -113,6 +113,13 @@ void Primitive2dXmlDump::dump(
     aWriter.endDocument();
 
     pStream->Seek(STREAM_SEEK_TO_BEGIN);
+
+    std::size_t nSize = pStream->remainingSize();
+    std::unique_ptr<sal_uInt8[]> pBuffer(new sal_uInt8[nSize + 1]);
+    pStream->ReadBytes(pBuffer.get(), nSize);
+    pBuffer[nSize] = 0;
+
+    printf ("%s\n", pBuffer.get());
 }
 
 xmlDocUniquePtr Primitive2dXmlDump::dumpAndParse(
diff --git a/filter/CppunitTest_filter_pdfimporter_test.mk b/filter/CppunitTest_filter_pdfimporter_test.mk
new file mode 100644
index 000000000000..3b17dcdcb43f
--- /dev/null
+++ b/filter/CppunitTest_filter_pdfimporter_test.mk
@@ -0,0 +1,48 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_pdfimporter_test))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_pdfimporter_test,\
+	boost_headers \
+	libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_pdfimporter_test, \
+    filter/qa/cppunit/PdfImporterTest \
+))
+
+$(eval $(call gb_CppunitTest_use_library_objects,filter_pdfimporter_test,\
+    pdfimporter \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_pdfimporter_test, \
+    basegfx \
+    drawinglayer \
+    comphelper \
+    cppu \
+    cppuhelper \
+    sal \
+    test \
+    unotest \
+    utl \
+    tl \
+    vcl \
+    tk \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_pdfimporter_test))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_pdfimporter_test))
+$(eval $(call gb_CppunitTest_use_ure,filter_pdfimporter_test))
+$(eval $(call gb_CppunitTest_use_vcl,filter_pdfimporter_test))
+$(eval $(call gb_CppunitTest_use_rdb,filter_pdfimporter_test,services))
+
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_pdfimporter.mk b/filter/Library_pdfimporter.mk
new file mode 100644
index 000000000000..93a567cbc247
--- /dev/null
+++ b/filter/Library_pdfimporter.mk
@@ -0,0 +1,35 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Library_Library,pdfimporter))
+
+$(eval $(call gb_Library_set_include,pdfimporter,\
+	-I$(SRCDIR)/filter/inc \
+	$$(INCLUDE) \
+))
+
+$(eval $(call gb_Library_use_external,pdfimporter,boost_headers))
+
+$(eval $(call gb_Library_add_exception_objects,pdfimporter,\
+	filter/source/pdfimporter/PDFImporter \
+))
+
+$(eval $(call gb_Library_use_libraries,pdfimporter,\
+	drawinglayer \
+	basegfx \
+	vcl \
+	tl \
+	sal \
+	cppu \
+	tk \
+))
+
+$(eval $(call gb_Library_use_sdk_api,pdfimporter))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk
index 42a82bacf5c0..e079e523aa99 100644
--- a/filter/Module_filter.mk
+++ b/filter/Module_filter.mk
@@ -26,6 +26,7 @@ $(eval $(call gb_Module_add_targets,filter,\
 	Library_msfilter \
 	Library_odfflatxml \
 	Library_pdffilter \
+	Library_pdfimporter \
 	Library_storagefd \
 	Library_svgfilter \
 	Library_graphicfilter \
@@ -49,6 +50,7 @@ $(eval $(call gb_Module_add_check_targets,filter,\
     CppunitTest_filter_xslt \
     CppunitTest_filter_priority \
     CppunitTest_filter_msfilter \
+    CppunitTest_filter_pdfimporter_test \
     CppunitTest_filter_textfilterdetect \
 ))
 
diff --git a/filter/qa/cppunit/PdfImporterTest.cxx b/filter/qa/cppunit/PdfImporterTest.cxx
new file mode 100644
index 000000000000..ee57b9bdbc67
--- /dev/null
+++ b/filter/qa/cppunit/PdfImporterTest.cxx
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+#include <sal/types.h>
+#include <test/bootstrapfixture.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <filter/pdfimporter/PDFImporter.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+#include <tools/stream.hxx>
+#include <drawinglayer/converters.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/tools/primitive2dxmldump.hxx>
+
+#include <tools/stream.hxx>
+#include <vcl/pngwrite.hxx>
+
+class PDFImporterTest : public test::BootstrapFixture, public XmlTestTools
+{
+    OUString getFullUrl(std::u16string_view sFileName)
+    {
+        return m_directories.getURLFromSrc(u"/filter/qa/cppunit/data/") + sFileName;
+    }
+
+    void testPath();
+    void testImage();
+    void testText();
+
+    CPPUNIT_TEST_SUITE(PDFImporterTest);
+    //CPPUNIT_TEST(testPath);
+    //CPPUNIT_TEST(testImage);
+    CPPUNIT_TEST(testText);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void PDFImporterTest::testPath()
+{
+    SvFileStream aFileStream(getFullUrl(u"/PdfTest-Rect.pdf"), StreamMode::READ);
+    const sal_uInt64 nStreamLength = aFileStream.TellEnd();
+    auto rData = std::make_unique<std::vector<sal_uInt8>>(nStreamLength);
+    aFileStream.ReadBytes(rData->data(), rData->size());
+    BinaryDataContainer aDataContainer(std::move(rData));
+    PDFImporter aImporter(aDataContainer);
+
+    drawinglayer::primitive2d::Primitive2DContainer aContainer;
+    aImporter.importPage(0, aContainer);
+
+    drawinglayer::geometry::ViewInformation2D rViewInformation2D;
+
+    auto aRange = aContainer.getB2DRange(rViewInformation2D);
+
+    BitmapEx aBitmapEx
+        = drawinglayer::convertToBitmapEx(aContainer, rViewInformation2D, 2000, 2000, 10000 * 1000);
+
+    SvFileStream aNew("~/xxxxxxx.png", StreamMode::WRITE | StreamMode::TRUNC);
+    vcl::PNGWriter aPNGWriter(aBitmapEx);
+    aPNGWriter.Write(aNew);
+
+    drawinglayer::Primitive2dXmlDump aDumper;
+    aDumper.dump(aContainer, OUString());
+    xmlDocUniquePtr pDocument = aDumper.dumpAndParse(aContainer);
+    CPPUNIT_ASSERT(pDocument);
+
+    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence",
+                "transparence", "0.498039215686275");
+
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinX());
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinY());
+    CPPUNIT_ASSERT_EQUAL(612.5, aRange.getMaxX());
+    CPPUNIT_ASSERT_EQUAL(792.5, aRange.getMaxY());
+
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Height());
+
+    CPPUNIT_ASSERT(false);
+}
+
+void PDFImporterTest::testImage()
+{
+    SvFileStream aFileStream(getFullUrl(u"/PdfTest-Image.pdf"), StreamMode::READ);
+    const sal_uInt64 nStreamLength = aFileStream.TellEnd();
+    auto rData = std::make_unique<std::vector<sal_uInt8>>(nStreamLength);
+    aFileStream.ReadBytes(rData->data(), rData->size());
+    BinaryDataContainer aDataContainer(std::move(rData));
+    PDFImporter aImporter(aDataContainer);
+
+    drawinglayer::primitive2d::Primitive2DContainer aContainer;
+    aImporter.importPage(0, aContainer);
+
+    drawinglayer::geometry::ViewInformation2D rViewInformation2D;
+
+    auto aRange = aContainer.getB2DRange(rViewInformation2D);
+
+    BitmapEx aBitmapEx
+        = drawinglayer::convertToBitmapEx(aContainer, rViewInformation2D, 2000, 2000, 10000 * 1000);
+
+    SvFileStream aNew("~/xxxxxxx.png", StreamMode::WRITE | StreamMode::TRUNC);
+    vcl::PNGWriter aPNGWriter(aBitmapEx);
+    aPNGWriter.Write(aNew);
+
+    drawinglayer::Primitive2dXmlDump aDumper;
+    aDumper.dump(aContainer, OUString());
+    xmlDocUniquePtr pDocument = aDumper.dumpAndParse(aContainer);
+    CPPUNIT_ASSERT(pDocument);
+
+    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence",
+                "transparence", "0.498039215686275");
+
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinX());
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinY());
+    CPPUNIT_ASSERT_EQUAL(612.5, aRange.getMaxX());
+    CPPUNIT_ASSERT_EQUAL(792.5, aRange.getMaxY());
+
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Height());
+
+    CPPUNIT_ASSERT(false);
+}
+
+void PDFImporterTest::testText()
+{
+    SvFileStream aFileStream(getFullUrl(u"/PdfTest-Text.pdf"), StreamMode::READ);
+    const sal_uInt64 nStreamLength = aFileStream.TellEnd();
+    auto rData = std::make_unique<std::vector<sal_uInt8>>(nStreamLength);
+    aFileStream.ReadBytes(rData->data(), rData->size());
+    BinaryDataContainer aDataContainer(std::move(rData));
+    PDFImporter aImporter(aDataContainer);
+
+    drawinglayer::primitive2d::Primitive2DContainer aContainer;
+    aImporter.importPage(0, aContainer);
+
+    drawinglayer::geometry::ViewInformation2D rViewInformation2D;
+
+    auto aRange = aContainer.getB2DRange(rViewInformation2D);
+
+    BitmapEx aBitmapEx
+        = drawinglayer::convertToBitmapEx(aContainer, rViewInformation2D, 2000, 2000, 10000 * 1000);
+
+    SvFileStream aNew("~/xxxxxxx.png", StreamMode::WRITE | StreamMode::TRUNC);
+    vcl::PNGWriter aPNGWriter(aBitmapEx);
+    aPNGWriter.Write(aNew);
+
+    drawinglayer::Primitive2dXmlDump aDumper;
+    aDumper.dump(aContainer, OUString());
+    xmlDocUniquePtr pDocument = aDumper.dumpAndParse(aContainer);
+    CPPUNIT_ASSERT(pDocument);
+
+    assertXPath(pDocument, "/primitive2D/metafile/transform/mask/transform/unifiedtransparence",
+                "transparence", "0.498039215686275");
+
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinX());
+    CPPUNIT_ASSERT_EQUAL(-0.5, aRange.getMinY());
+    CPPUNIT_ASSERT_EQUAL(612.5, aRange.getMaxX());
+    CPPUNIT_ASSERT_EQUAL(792.5, aRange.getMaxY());
+
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(tools::Long(1000), aBitmapEx.GetSizePixel().Height());
+
+    CPPUNIT_ASSERT(false);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PDFImporterTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/cppunit/data/PdfTest-Image.pdf b/filter/qa/cppunit/data/PdfTest-Image.pdf
new file mode 100644
index 000000000000..394ee272f3d4
Binary files /dev/null and b/filter/qa/cppunit/data/PdfTest-Image.pdf differ
diff --git a/filter/qa/cppunit/data/PdfTest-Rect.pdf b/filter/qa/cppunit/data/PdfTest-Rect.pdf
new file mode 100644
index 000000000000..7115df65176f
--- /dev/null
+++ b/filter/qa/cppunit/data/PdfTest-Rect.pdf
@@ -0,0 +1,134 @@
+%PDF-1.6
+%äüöß
+2 0 obj
+<</Length 3 0 R/Filter/FlateDecode>>
+stream
+xœ¥ÁJA†ïyŠœ{˜&Ù™ÙY(=¸UQè¡zð	Úªl.H_ßÄìÈ"¢™Ãü!Éÿ%¡Àx7$¤@R03‡®el;ÿÇ=<-ðŒöÆ#¦Oà…ò
X#7¾ìLyÅ3°¼y9¾ûÕj¹íï6HëõÕ¦
+1¶”´%K“̤0·ÙhL:R,ÊSsSHÇ8Sž¬õBJ¹duL’bg„¢|¸Õ•s ê4¸èŒ÷ºÜë¿h°ƒëmÿ}Eö¢	ç‰Æ…ª£*§H’™òlíø…'ž´‘8a¥ÔñM9¬É4Sž­ÓQºÃX8wY
+endstream
+endobj
+
+3 0 obj
+241
+endobj
+
+8 0 obj
+<<
+>>
+endobj
+
+9 0 obj
+<</Font 8 0 R
+/ProcSet[/PDF/Text]
+>>
+endobj
+
+1 0 obj
+<</Type/Page/Parent 7 0 R/Resources 9 0 R/MediaBox[0 0 612 792]/StructParents 0
+/Group<</S/Transparency/CS/DeviceRGB/I true>>/Contents 2 0 R>>
+endobj
+
+10 0 obj
+<</Count 1/First 11 0 R/Last 11 0 R
+>>
+endobj
+
+11 0 obj
+<</Count 0/Title<FEFF005000610067006500200031>
+/Dest[1 0 R/XYZ 0 792 0]/Parent 10 0 R>>
+endobj
+
+4 0 obj
+<</Type/StructElem
+/S/Figure
+/P 12 0 R
+/Pg 1 0 R
+/K[0 ]
+>>
+endobj
+
+5 0 obj
+<</Type/StructElem
+/S/Figure
+/P 12 0 R
+/Pg 1 0 R
+/K[1 ]
+>>
+endobj
+
+6 0 obj
+<</Type/StructElem
+/S/Figure
+/P 12 0 R
+/Pg 1 0 R
+/K[2 ]
+>>
+endobj
+
+12 0 obj
+<</Type/StructTreeRoot
+/ParentTree 13 0 R
+/K[4 0 R 5 0 R 6 0 R ]
+>>
+endobj
+
+13 0 obj
+<</Nums[
+0 [ 4 0 R 5 0 R 6 0 R ]
+]>>
+endobj
+
+7 0 obj
+<</Type/Pages
+/Resources 9 0 R
+/MediaBox[ 0 0 612 792 ]
+/Kids[ 1 0 R ]
+/Count 1>>
+endobj
+
+14 0 obj
+<</Type/Catalog/Pages 7 0 R
+/OpenAction[1 0 R /XYZ null null 0]
+/ViewerPreferences<</DisplayDocTitle true
+>>
+/Outlines 10 0 R
+/StructTreeRoot 12 0 R
+/MarkInfo<</Marked true>>
+>>
+endobj
+
+15 0 obj
+<</Title<FEFF004D007900540065006D0070006C006100740065>
+/Creator<FEFF0044007200610077>
+/Producer<FEFF004C0069006200720065004F0066006600690063006500200037002E0030>
+/CreationDate(D:20210505091047+09'00')>>
+endobj
+
+xref
+0 16
+0000000000 65535 f 
+0000000426 00000 n 
+0000000019 00000 n 
+0000000331 00000 n 
+0000000746 00000 n 
+0000000821 00000 n 
+0000000896 00000 n 
+0000001110 00000 n 
+0000000351 00000 n 
+0000000373 00000 n 
+0000000585 00000 n 
+0000000641 00000 n 
+0000000971 00000 n 
+0000001056 00000 n 
+0000001208 00000 n 
+0000001403 00000 n 
+trailer
+<</Size 16/Root 14 0 R
+/Info 15 0 R
+/ID [ <3F7788F2D0928B3B95B0CDBBD9EAC1B8>
+<3F7788F2D0928B3B95B0CDBBD9EAC1B8> ]
+/DocChecksum /F2715E25D79DC609834CA579FA23A5BA
+>>
+startxref
+1623
+%%EOF
diff --git a/filter/qa/cppunit/data/PdfTest-Text.pdf b/filter/qa/cppunit/data/PdfTest-Text.pdf
new file mode 100644
index 000000000000..c449bf559228
Binary files /dev/null and b/filter/qa/cppunit/data/PdfTest-Text.pdf differ
diff --git a/filter/source/pdfimporter/PDFImporter.cxx b/filter/source/pdfimporter/PDFImporter.cxx
new file mode 100644
index 000000000000..b4b37aea7128
--- /dev/null
+++ b/filter/source/pdfimporter/PDFImporter.cxx
@@ -0,0 +1,384 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <filter/pdfimporter/PDFImporter.hxx>
+
+#include <sal/log.hxx>
+#include <tools/UnitConversion.hxx>
+#include <tools/color.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/BitmapTools.hxx>
+
+#include <cmath>
+
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+
+#include <drawinglayer/attribute/lineattribute.hxx>
+#include <drawinglayer/attribute/strokeattribute.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+
+PDFImporter::PDFImporter(BinaryDataContainer& rDataContainer)
+    : mpPDFium(vcl::pdf::PDFiumLibrary::get())
+{
+    auto* pData = rDataContainer.getData();
+    sal_Int32 nSize = rDataContainer.getSize();
+
+    mpPdfDocument = mpPDFium->openDocument(pData, nSize);
+}
+
+namespace
+{
+void setupPage(drawinglayer::primitive2d::Primitive2DContainer& rContainer,
+               basegfx::B2DSize const& rPageSize)
+{
+    basegfx::B2DRange aPageRange(0.0, 0.0, rPageSize.getX(), rPageSize.getY());
+
+    printf("Page Size %.2fpt %.2fpt\n", rPageSize.getX(), rPageSize.getY());
+
+    const auto aPolygon = basegfx::utils::createPolygonFromRect(aPageRange);
+
+    const drawinglayer::primitive2d::Primitive2DReference xPage(
+        new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aPolygon,
+                                                                  basegfx::BColor(0.0, 0.0, 0.0)));
+    const drawinglayer::primitive2d::Primitive2DReference xHidden(
+        new drawinglayer::primitive2d::HiddenGeometryPrimitive2D(
+            drawinglayer::primitive2d::Primitive2DContainer{ xPage }));
+
+    rContainer.push_back(xHidden);
+}
+
+double sqrt2(double a, double b) { return sqrt(a * a + b * b); }
+
+} // end anonymous namespace
+
+bool PDFImporter::importPage(int nPageIndex,
+                             drawinglayer::primitive2d::Primitive2DContainer& rContainer)
+{
+    if (!mpPdfDocument)
+        return false;
+
+    drawinglayer::primitive2d::Primitive2DContainer aContent;
+
+    const int nPageCount = mpPdfDocument->getPageCount();
+    if (!(nPageCount > 0 && nPageIndex >= 0 && nPageIndex < nPageCount))
+        return false;
+
+    mpPdfPage = mpPdfDocument->openPage(nPageIndex);
+    if (!mpPdfPage)
+        return false;
+
+    basegfx::B2DSize aPageSize = mpPdfDocument->getPageSize(nPageIndex);
+
+    setupPage(aContent, aPageSize);
+
+    // Load the page text to extract it when we get text elements.
+    auto pTextPage = mpPdfPage->getTextPage();
+
+    const int nPageObjectCount = mpPdfPage->getObjectCount();
+
+    for (int nPageObjectIndex = 0; nPageObjectIndex < nPageObjectCount; ++nPageObjectIndex)
+    {
+        auto pPageObject = mpPdfPage->getObject(nPageObjectIndex);
+        importPdfObject(pPageObject, pTextPage, nPageObjectIndex, aContent);
+    }
+
+    // point to pixel conversion
+    double dConversionFactor = double(conversionFract(o3tl::Length::pt, o3tl::Length::px));
+    const auto aTransform = basegfx::utils::createScaleTranslateB2DHomMatrix(
+        dConversionFactor, -dConversionFactor, 0.0, aPageSize.getY() * dConversionFactor);
+
+    const drawinglayer::primitive2d::Primitive2DReference xTransform(
+        new drawinglayer::primitive2d::TransformPrimitive2D(aTransform, aContent));
+
+    rContainer.push_back(xTransform);
+
+    return true;
+}
+
+void PDFImporter::importPdfObject(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                                  std::unique_ptr<vcl::pdf::PDFiumTextPage> const& pTextPage,
+                                  int nPageObjectIndex,
+                                  drawinglayer::primitive2d::Primitive2DContainer& rContent)
+{
+    if (!pPageObject)
+        return;
+
+    const vcl::pdf::PDFPageObjectType ePageObjectType = pPageObject->getType();
+    switch (ePageObjectType)
+    {
+        case vcl::pdf::PDFPageObjectType::Text:
+            printf("pdf::PDFPageObjectType::Text\n");
+            importText(pPageObject, pTextPage, rContent);
+            break;
+        case vcl::pdf::PDFPageObjectType::Path:
+            printf("pdf::PDFPageObjectType::Path\n");
+            importPath(pPageObject, rContent);
+            break;
+        case vcl::pdf::PDFPageObjectType::Image:
+            printf("pdf::PDFPageObjectType::Image\n");
+            importImage(pPageObject, rContent);
+            break;
+        case vcl::pdf::PDFPageObjectType::Shading:
+            printf("pdf::PDFPageObjectType::Shading\n");
+            break;
+        case vcl::pdf::PDFPageObjectType::Form:
+            printf("pdf::PDFPageObjectType::Form\n");
+            break;
+        case vcl::pdf::PDFPageObjectType::Unknown:
+            SAL_WARN("filter", "Unknown PDF page object #" << nPageObjectIndex
+                                                           << " of type: " << int(ePageObjectType));
+            break;
+    }
+}
+
+void PDFImporter::importText(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                             std::unique_ptr<vcl::pdf::PDFiumTextPage> const& pTextPage,
+                             drawinglayer::primitive2d::Primitive2DContainer& rRootContainer)
+{
+    basegfx::B2DRectangle aTextRect = pPageObject->getBounds();
+    basegfx::B2DHomMatrix aMatrix = pPageObject->getMatrix();
+
+    OUString sText = pPageObject->getText(pTextPage);
+
+    const double dFontSize = pPageObject->getFontSize();
+    double dFontSizeH = std::fabs(sqrt2(aMatrix.a(), aMatrix.c()) * dFontSize);
+    double dFontSizeV = std::fabs(sqrt2(aMatrix.b(), aMatrix.d()) * dFontSize);
+
+    OUString sFontName = pPageObject->getFontName();
+
+    printf("TEXT: %s\n", sText.toUtf8().getStr());
+
+    Color aTextColor(COL_TRANSPARENT);
+    bool bFill = false;
+    bool bUse = true;
+
+    switch (pPageObject->getTextRenderMode())
+    {
+        case vcl::pdf::PDFTextRenderMode::Fill:
+        case vcl::pdf::PDFTextRenderMode::FillClip:
+        case vcl::pdf::PDFTextRenderMode::FillStroke:
+        case vcl::pdf::PDFTextRenderMode::FillStrokeClip:
+            bFill = true;
+            break;
+        case vcl::pdf::PDFTextRenderMode::Stroke:
+        case vcl::pdf::PDFTextRenderMode::StrokeClip:
+        case vcl::pdf::PDFTextRenderMode::Unknown:
+            break;
+        case vcl::pdf::PDFTextRenderMode::Invisible:
+        case vcl::pdf::PDFTextRenderMode::Clip:
+            bUse = false;
+            break;
+    }
+
+    if (bUse)
+    {
+        Color aColor = bFill ? pPageObject->getFillColor() : pPageObject->getStrokeColor();
+        if (aColor != COL_TRANSPARENT)
+        {
+            aTextColor = aColor.GetRGBColor();
+        }
+    }
+}
+
+void PDFImporter::importImage(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                              drawinglayer::primitive2d::Primitive2DContainer& rRootContainer)
+{
+    std::unique_ptr<vcl::pdf::PDFiumBitmap> pPdfBitmap = pPageObject->getImageBitmap();
+    if (!pPdfBitmap)
+    {
+        SAL_WARN("filter", "Failed to get IMAGE");
+        return;
+    }
+
+    const vcl::pdf::PDFBitmapType eFormat = pPdfBitmap->getFormat();
+    if (eFormat == vcl::pdf::PDFBitmapType::Unknown)
+    {
+        SAL_WARN("filter", "Failed to get IMAGE format");
+        return;
+    }
+
+    vcl::pdf::PDFImageMetadata aMetadata = pPageObject->getImageMetadata(*mpPdfPage);
+    printf("METADATA %lu %lu %lu\n", aMetadata.mnWidth, aMetadata.mnHeight,
+           aMetadata.mnBitsPerPixel);
+
+    const sal_uInt8* pBuffer = pPdfBitmap->getBuffer();
+    const int nWidth = pPdfBitmap->getWidth();
+    const int nHeight = pPdfBitmap->getHeight();
+    const int nStride = pPdfBitmap->getStride();
+
+    BitmapEx aBitmap;
+
+    printf("hasTransparency %d\n", pPageObject->hasTransparency());
+
+    switch (eFormat)
+    {
+        case vcl::pdf::PDFBitmapType::BGR:
+            printf("vcl::pdf::PDFBitmapType::BGR\n");
+            aBitmap = vcl::bitmap::CreateFromData(pBuffer, nWidth, nHeight, nStride,
+                                                  vcl::PixelFormat::N24_BPP);
+            break;
+        case vcl::pdf::PDFBitmapType::BGRx:
+            printf("vcl::pdf::PDFBitmapType::BGRx\n");
+            aBitmap = vcl::bitmap::CreateFromData(pBuffer, nWidth, nHeight, nStride,
+                                                  vcl::PixelFormat::N32_BPP);
+            break;
+        case vcl::pdf::PDFBitmapType::BGRA:
+            printf("vcl::pdf::PDFBitmapType::BGRA\n");
+            aBitmap = vcl::bitmap::CreateFromData(pBuffer, nWidth, nHeight, nStride,
+                                                  vcl::PixelFormat::N32_BPP);
+            break;
+        case vcl::pdf::PDFBitmapType::Gray:
+            // TODO
+        default:
+            SAL_WARN("filter", "Got IMAGE width: " << nWidth << ", height: " << nHeight
+                                                   << ", stride: " << nStride
+                                                   << ", format: " << int(eFormat));
+            break;
+    }
+
+    basegfx::B2DRectangle aBounds = pPageObject->getBounds();
+
+    rRootContainer.push_back(new drawinglayer::primitive2d::BitmapPrimitive2D(
+        VCLUnoHelper::CreateVCLXBitmap(aBitmap), basegfx::utils::createScaleTranslateB2DHomMatrix(
+                                                     aBounds.getRange(), aBounds.getMinimum())));
+}
+
+void PDFImporter::importPath(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                             drawinglayer::primitive2d::Primitive2DContainer& rRootContainer)
+{
+    drawinglayer::primitive2d::Primitive2DContainer aContent;
+
+    basegfx::B2DHomMatrix aPathMatrix = pPageObject->getMatrix();
+
+    basegfx::B2DPolyPolygon aPolyPolygon;
+    basegfx::B2DPolygon aPolygon;
+    std::vector<basegfx::B2DPoint> aBezier;
+
+    const int nSegments = pPageObject->getPathSegmentCount();
+    for (int nSegmentIndex = 0; nSegmentIndex < nSegments; ++nSegmentIndex)
+    {
+        auto pPathSegment = pPageObject->getPathSegment(nSegmentIndex);
+        if (!pPathSegment)
+            continue;
+
+        basegfx::B2DPoint aB2DPoint = pPathSegment->getPoint();
+
+        aPolygon.setClosed(pPathSegment->isClosed());
+
+        const vcl::pdf::PDFSegmentType eSegmentType = pPathSegment->getType();
+        switch (eSegmentType)
+        {
+            case vcl::pdf::PDFSegmentType::Lineto:
+            {
+                aPolygon.append(aB2DPoint);
+            }
+            break;
+
+            case vcl::pdf::PDFSegmentType::Bezierto:
+            {
+                aBezier.emplace_back(aB2DPoint.getX(), aB2DPoint.getY());
+                if (aBezier.size() == 3)
+                {
+                    aPolygon.appendBezierSegment(aBezier[0], aBezier[1], aBezier[2]);
+                    aBezier.clear();
+                }
+            }
+            break;
+
+            case vcl::pdf::PDFSegmentType::Moveto:
+            {
+                if (aPolygon.count() > 0)
+                {
+                    aPolyPolygon.append(aPolygon);
+                    aPolygon.clear();
+                }
+
+                aPolygon.append(aB2DPoint);
+            }
+            break;
+
+            case vcl::pdf::PDFSegmentType::Unknown:
+            default:
+            {
+                SAL_WARN("filter", "Unknown path segment type in PDF: " << int(eSegmentType));
+            }
+            break;
+        }
+    }
+
+    if (aBezier.size() == 3)
+    {
+        aPolygon.appendBezierSegment(aBezier[0], aBezier[1], aBezier[2]);
+        aBezier.clear();
+    }
+
+    if (aPolygon.count() > 0)
+    {
+        aPolyPolygon.append(aPolygon, 1);
+        aPolygon.clear();
+    }
+
+    printf("PolyPoly size %d\n", aPolyPolygon.count());
+    for (auto const& rPoly : aPolyPolygon)
+        printf("Poly size %d\n", rPoly.count());
+
+    double fStrokeWidth = pPageObject->getStrokeWidth();
+    printf("Stroke: %f\n", fStrokeWidth);
+
+    vcl::pdf::PDFFillMode nFillMode = vcl::pdf::PDFFillMode::Alternate;
+    bool bStroke = true;
+
+    if (!pPageObject->getDrawMode(nFillMode, bStroke))
+    {
+        SAL_WARN("filter", "Huh...");
+    }
+
+    Color aFillColor = pPageObject->getFillColor();
+    Color aStokeColor = COL_TRANSPARENT;
+
+    if (bStroke)
+    {
+        aStokeColor = pPageObject->getStrokeColor();
+    }
+
+    if (aStokeColor == COL_TRANSPARENT)
+        aStokeColor = aFillColor;
+
+    if (!bStroke)
+    {
+        const drawinglayer::primitive2d::Primitive2DReference xPolyPolygonColorPrimitive(
+            new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(aPolyPolygon,
+                                                                       aFillColor.getBColor()));
+        aContent.push_back(xPolyPolygonColorPrimitive);
+    }
+
+    drawinglayer::attribute::LineAttribute aLineAttribute(aStokeColor.getBColor(), fStrokeWidth);
+    const drawinglayer::primitive2d::Primitive2DReference xPolyPolygonStrokePrimitive(
+        new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(aPolyPolygon, aLineAttribute));
+    aContent.push_back(xPolyPolygonStrokePrimitive);
+
+    const drawinglayer::primitive2d::Primitive2DReference xTransform(
+        new drawinglayer::primitive2d::TransformPrimitive2D(aPathMatrix, aContent));
+    rRootContainer.push_back(xTransform);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/filter/pdfimporter/PDFImporter.hxx b/include/filter/pdfimporter/PDFImporter.hxx
new file mode 100644
index 000000000000..01cd94d264c9
--- /dev/null
+++ b/include/filter/pdfimporter/PDFImporter.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+
+class PDFImporter
+{
+private:
+    std::shared_ptr<vcl::pdf::PDFium> mpPDFium;
+    std::unique_ptr<vcl::pdf::PDFiumDocument> mpPdfDocument;
+    std::unique_ptr<vcl::pdf::PDFiumPage> mpPdfPage;
+
+    void importPdfObject(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                         std::unique_ptr<vcl::pdf::PDFiumTextPage> const& pTextPage,
+                         int nPageObjectIndex,
+                         drawinglayer::primitive2d::Primitive2DContainer& rRootContainer);
+
+    void importText(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                    std::unique_ptr<vcl::pdf::PDFiumTextPage> const& pTextPage,
+                    drawinglayer::primitive2d::Primitive2DContainer& rRootContainer);
+
+    void importPath(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                    drawinglayer::primitive2d::Primitive2DContainer& rRootContainer);
+
+    void importImage(std::unique_ptr<vcl::pdf::PDFiumPageObject> const& pPageObject,
+                     drawinglayer::primitive2d::Primitive2DContainer& rRootContainer);
+
+public:
+    PDFImporter(BinaryDataContainer& rDataContainer);
+
+    bool importPage(int nPageIndex, drawinglayer::primitive2d::Primitive2DContainer& rContainer);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list