summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2020-10-03 11:02:34 +0200
committerTomaž Vajngerl <quikee@gmail.com>2020-10-04 08:40:01 +0200
commitb68761f4a5cd22b48c3214c8be919cb4c84da241 (patch)
treed4939210d51101e560ec3d830f1ada3922e6d8dc
parentpdfium: extend the PDF test with more types of annotations (diff)
downloadcore-b68761f4a5cd22b48c3214c8be919cb4c84da241.tar.gz
core-b68761f4a5cd22b48c3214c8be919cb4c84da241.zip
pdfium: Support for InkStrokes and Vertices
This extends PDFium with getting InkStrokes and Vertices for annotations, which wasn't implemented before, and adds support to PDFium wrapper in LibreOffice. Change-Id: I570d53038a59ab830fcd5639583c75cf8adda86c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103885 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--external/pdfium/AnnotationInkAndVertices.patch.1155
-rw-r--r--external/pdfium/UnpackedTarball_pdfium.mk2
-rw-r--r--include/vcl/filter/PDFiumLibrary.hxx2
-rw-r--r--vcl/qa/cppunit/PDFiumLibraryTest.cxx6
-rw-r--r--vcl/source/pdf/PDFiumLibrary.cxx40
5 files changed, 205 insertions, 0 deletions
diff --git a/external/pdfium/AnnotationInkAndVertices.patch.1 b/external/pdfium/AnnotationInkAndVertices.patch.1
new file mode 100644
index 000000000000..a7fa04ddef05
--- /dev/null
+++ b/external/pdfium/AnnotationInkAndVertices.patch.1
@@ -0,0 +1,155 @@
+diff --git a/fpdfsdk/fpdf_annot.cpp b/fpdfsdk/fpdf_annot.cpp
+index 98b3e4f0a..c1471220b 100644
+--- a/fpdfsdk/fpdf_annot.cpp
++++ b/fpdfsdk/fpdf_annot.cpp
+@@ -493,6 +493,65 @@ FPDFAnnot_RemoveInkList(FPDF_ANNOTATION annot) {
+ return true;
+ }
+
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetInkStrokeCount(FPDF_ANNOTATION annot)
++{
++ if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_INK)
++ return -1;
++
++ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++
++ CPDF_Array* inklist = pAnnotDict->GetArrayFor("InkList");
++ if (!inklist)
++ return 0;
++
++ return static_cast<int>(inklist->size());
++}
++
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetInkStrokePointCount(FPDF_ANNOTATION annot, int index)
++{
++ if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_INK)
++ return -1;
++
++ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++
++ CPDF_Array* pInkList = pAnnotDict->GetArrayFor("InkList");
++ if (!pInkList)
++ return 0;
++
++ CPDF_Array* pInkPoints = pInkList->GetArrayAt(index);
++ if (!pInkPoints)
++ return 0;
++
++ return static_cast<int>(pInkPoints->size() / 2);
++}
++
++FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
++FPDFAnnot_GetInkStrokePoints(FPDF_ANNOTATION annot, int index,
++ FS_POINTF* points)
++{
++ if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_INK)
++ return false;
++
++ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++
++ CPDF_Array* pInkList = pAnnotDict->GetArrayFor("InkList");
++ if (!pInkList)
++ return false;
++ CPDF_Array* pInkPoints = pInkList->GetArrayAt(index);
++ if (!pInkPoints)
++ return false;
++
++ for (int i = 0; i < pInkPoints->size(); i += 2) {
++ int pointIndex = i / 2;
++ points[pointIndex].x = pInkPoints->GetNumberAt(i);
++ points[pointIndex].y = pInkPoints->GetNumberAt(i + 1);
++ }
++
++ return true;
++}
++
+ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+ FPDFAnnot_AppendObject(FPDF_ANNOTATION annot, FPDF_PAGEOBJECT obj) {
+ CPDF_AnnotContext* pAnnot = CPDFAnnotContextFromFPDFAnnotation(annot);
+@@ -806,6 +865,48 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot,
+ return true;
+ }
+
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetVerticesCount(FPDF_ANNOTATION annot)
++{
++ if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_POLYGON &&
++ FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_POLYLINE) {
++ return -1;
++ }
++
++ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++
++ CPDF_Array* pVertices = pAnnotDict->GetArrayFor("Vertices");
++
++ if (!pVertices)
++ return 0;
++
++ return static_cast<int>(pVertices->size() / 2);
++}
++
++FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
++FPDFAnnot_GetVertices(FPDF_ANNOTATION annot, FS_POINTF* points)
++{
++ if (FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_POLYGON &&
++ FPDFAnnot_GetSubtype(annot) != FPDF_ANNOT_POLYLINE) {
++ return false;
++ }
++
++ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
++
++ CPDF_Array* pVertices = pAnnotDict->GetArrayFor("Vertices");
++
++ if (!pVertices)
++ return false;
++
++ for (int i = 0; i < pVertices->size(); i += 2) {
++ int pointIndex = i / 2;
++ points[pointIndex].x = pVertices->GetNumberAt(i);
++ points[pointIndex].y = pVertices->GetNumberAt(i + 1);
++ }
++
++ return true;
++}
++
+ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_HasKey(FPDF_ANNOTATION annot,
+ FPDF_BYTESTRING key) {
+ CPDF_Dictionary* pAnnotDict = GetAnnotDictFromFPDFAnnotation(annot);
+diff --git a/public/fpdf_annot.h b/public/fpdf_annot.h
+index 9561d8416..2176450c8 100644
+--- a/public/fpdf_annot.h
++++ b/public/fpdf_annot.h
+@@ -222,6 +222,16 @@ FPDF_EXPORT int FPDF_CALLCONV FPDFAnnot_AddInkStroke(FPDF_ANNOTATION annot,
+ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
+ FPDFAnnot_RemoveInkList(FPDF_ANNOTATION annot);
+
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetInkStrokeCount(FPDF_ANNOTATION annot);
++
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetInkStrokePointCount(FPDF_ANNOTATION annot, int index);
++
++FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
++FPDFAnnot_GetInkStrokePoints(FPDF_ANNOTATION annot, int index,
++ FS_POINTF* points);
++
+ // Experimental API.
+ // Add |obj| to |annot|. |obj| must have been created by
+ // FPDFPageObj_CreateNew{Path|Rect}() or FPDFPageObj_New{Text|Image}Obj(), and
+@@ -394,6 +404,12 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_SetRect(FPDF_ANNOTATION annot,
+ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAnnot_GetRect(FPDF_ANNOTATION annot,
+ FS_RECTF* rect);
+
++FPDF_EXPORT int FPDF_CALLCONV
++FPDFAnnot_GetVerticesCount(FPDF_ANNOTATION annot);
++
++FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
++FPDFAnnot_GetVertices(FPDF_ANNOTATION annot, FS_POINTF* points);
++
+ // Experimental API.
+ // Check if |annot|'s dictionary has |key| as a key.
+ //
+--
+2.26.2
diff --git a/external/pdfium/UnpackedTarball_pdfium.mk b/external/pdfium/UnpackedTarball_pdfium.mk
index 43c17aa3dd97..b5cbb6dc23df 100644
--- a/external/pdfium/UnpackedTarball_pdfium.mk
+++ b/external/pdfium/UnpackedTarball_pdfium.mk
@@ -14,6 +14,8 @@ pdfium_patches += build.patch.1
# Avoids Windows 8 build dependency.
pdfium_patches += windows7.patch.1
pdfium_patches += c++20-comparison.patch
+pdfium_patches += AnnotationInkAndVertices.patch.1
+
# Work around <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94141> "c++20 rewritten operator==
# recursive call mixing friend and external operators for template class" in GCC with
# --with-latest-c++:
diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx
index 3688d091d601..205f8cc62ca6 100644
--- a/include/vcl/filter/PDFiumLibrary.hxx
+++ b/include/vcl/filter/PDFiumLibrary.hxx
@@ -77,6 +77,8 @@ public:
std::unique_ptr<PDFiumAnnotation> getLinked(OString const& rKey);
int getObjectCount();
std::unique_ptr<PDFiumPageObject> getObject(int nIndex);
+ std::vector<std::vector<basegfx::B2DPoint>> getInkStrokes();
+ std::vector<basegfx::B2DPoint> getVertices();
};
class PDFiumTextPage;
diff --git a/vcl/qa/cppunit/PDFiumLibraryTest.cxx b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
index 547c59872216..3fc4ba86a6c3 100644
--- a/vcl/qa/cppunit/PDFiumLibraryTest.cxx
+++ b/vcl/qa/cppunit/PDFiumLibraryTest.cxx
@@ -334,6 +334,10 @@ void PDFiumLibraryTest::testAnnotationsDifferentTypes()
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
CPPUNIT_ASSERT_EQUAL(OUString("Freehand Text"), aContentsString);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pAnnotation->getInkStrokes().size());
+ auto const& aInkStrokes = pAnnotation->getInkStrokes();
+ auto const& aPoints = aInkStrokes[0];
+ CPPUNIT_ASSERT_EQUAL(size_t(74), aPoints.size());
}
{
@@ -353,6 +357,8 @@ void PDFiumLibraryTest::testAnnotationsDifferentTypes()
CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey("Vertices"));
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
CPPUNIT_ASSERT_EQUAL(OUString("Polygon Text"), aContentsString);
+ auto const& aVertices = pAnnotation->getVertices();
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aVertices.size());
}
{
diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx
index 136a40786112..dc31eb4fb952 100644
--- a/vcl/source/pdf/PDFiumLibrary.cxx
+++ b/vcl/source/pdf/PDFiumLibrary.cxx
@@ -465,6 +465,46 @@ OUString PDFiumAnnotation::getString(OString const& rKey)
return rString;
}
+std::vector<std::vector<basegfx::B2DPoint>> PDFiumAnnotation::getInkStrokes()
+{
+ std::vector<std::vector<basegfx::B2DPoint>> aB2DPointList;
+ int nInkStrokes = FPDFAnnot_GetInkStrokeCount(mpAnnotation);
+ for (int i = 0; i < nInkStrokes; i++)
+ {
+ std::vector<basegfx::B2DPoint> aB2DPoints;
+ int nPoints = FPDFAnnot_GetInkStrokePointCount(mpAnnotation, i);
+ if (nPoints)
+ {
+ std::vector<FS_POINTF> aPoints(nPoints);
+ if (FPDFAnnot_GetInkStrokePoints(mpAnnotation, i, aPoints.data()))
+ {
+ for (auto const& rPoint : aPoints)
+ {
+ aB2DPoints.emplace_back(rPoint.x, rPoint.y);
+ }
+ aB2DPointList.push_back(aB2DPoints);
+ }
+ }
+ }
+ return aB2DPointList;
+}
+
+std::vector<basegfx::B2DPoint> PDFiumAnnotation::getVertices()
+{
+ std::vector<basegfx::B2DPoint> aB2DPoints;
+ int nPoints = FPDFAnnot_GetVerticesCount(mpAnnotation);
+ if (nPoints)
+ {
+ std::vector<FS_POINTF> aPoints(nPoints);
+ if (FPDFAnnot_GetVertices(mpAnnotation, aPoints.data()))
+ {
+ for (auto const& rPoint : aPoints)
+ aB2DPoints.emplace_back(rPoint.x, rPoint.y);
+ }
+ }
+ return aB2DPoints;
+}
+
std::unique_ptr<PDFiumAnnotation> PDFiumAnnotation::getLinked(OString const& rKey)
{
std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;