summaryrefslogtreecommitdiff
path: root/fpdfsdk/fpdfannot.cpp
diff options
context:
space:
mode:
authorJane Liu <janeliulwq@google.com>2017-06-01 18:56:09 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-06-01 23:17:03 +0000
commit4fd9a47465c0f2f17aa2a840d8452b2bee6bec33 (patch)
tree4dbd633596216ceddf817e693376a3626e28f112 /fpdfsdk/fpdfannot.cpp
parent8cb884102c17ef0530277126fd8da054d329d065 (diff)
downloadpdfium-4fd9a47465c0f2f17aa2a840d8452b2bee6bec33.tar.xz
Basic APIs and tests for extracting annotations
1. Added API for extracting annotation properties: * Added testing flag "--annot" that outputs the annotation properties into a .txt file. * Added two embedder tests covering all the API functions. Bug=pdfium:737 Change-Id: I95943a9b2b3d5d431bc8a74a31b27b4f4b521026 Reviewed-on: https://pdfium-review.googlesource.com/6092 Commit-Queue: Jane Liu <janeliulwq@google.com> Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'fpdfsdk/fpdfannot.cpp')
-rw-r--r--fpdfsdk/fpdfannot.cpp238
1 files changed, 238 insertions, 0 deletions
diff --git a/fpdfsdk/fpdfannot.cpp b/fpdfsdk/fpdfannot.cpp
new file mode 100644
index 0000000000..6e5b7ba063
--- /dev/null
+++ b/fpdfsdk/fpdfannot.cpp
@@ -0,0 +1,238 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "public/fpdf_annot.h"
+
+#include "core/fpdfapi/page/cpdf_page.h"
+#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
+#include "core/fpdfdoc/cpdf_annot.h"
+#include "core/fpdfdoc/cpvt_color.h"
+#include "core/fpdfdoc/cpvt_generateap.h"
+#include "fpdfsdk/fsdk_define.h"
+
+// These checks ensure the consistency of annotation subtype values across core/
+// and public.
+static_assert(static_cast<int>(CPDF_Annot::Subtype::UNKNOWN) ==
+ FPDF_ANNOT_UNKNOWN,
+ "CPDF_Annot::UNKNOWN value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::TEXT) == FPDF_ANNOT_TEXT,
+ "CPDF_Annot::TEXT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::LINK) == FPDF_ANNOT_LINK,
+ "CPDF_Annot::LINK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::FREETEXT) ==
+ FPDF_ANNOT_FREETEXT,
+ "CPDF_Annot::FREETEXT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::LINE) == FPDF_ANNOT_LINE,
+ "CPDF_Annot::LINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUARE) ==
+ FPDF_ANNOT_SQUARE,
+ "CPDF_Annot::SQUARE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::CIRCLE) ==
+ FPDF_ANNOT_CIRCLE,
+ "CPDF_Annot::CIRCLE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYGON) ==
+ FPDF_ANNOT_POLYGON,
+ "CPDF_Annot::POLYGON value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POLYLINE) ==
+ FPDF_ANNOT_POLYLINE,
+ "CPDF_Annot::POLYLINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::HIGHLIGHT) ==
+ FPDF_ANNOT_HIGHLIGHT,
+ "CPDF_Annot::HIGHLIGHT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::UNDERLINE) ==
+ FPDF_ANNOT_UNDERLINE,
+ "CPDF_Annot::UNDERLINE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SQUIGGLY) ==
+ FPDF_ANNOT_SQUIGGLY,
+ "CPDF_Annot::SQUIGGLY value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::STRIKEOUT) ==
+ FPDF_ANNOT_STRIKEOUT,
+ "CPDF_Annot::STRIKEOUT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::STAMP) == FPDF_ANNOT_STAMP,
+ "CPDF_Annot::STAMP value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::CARET) == FPDF_ANNOT_CARET,
+ "CPDF_Annot::CARET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::INK) == FPDF_ANNOT_INK,
+ "CPDF_Annot::INK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::POPUP) == FPDF_ANNOT_POPUP,
+ "CPDF_Annot::POPUP value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::FILEATTACHMENT) ==
+ FPDF_ANNOT_FILEATTACHMENT,
+ "CPDF_Annot::FILEATTACHMENT value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SOUND) == FPDF_ANNOT_SOUND,
+ "CPDF_Annot::SOUND value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::MOVIE) == FPDF_ANNOT_MOVIE,
+ "CPDF_Annot::MOVIE value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::WIDGET) ==
+ FPDF_ANNOT_WIDGET,
+ "CPDF_Annot::WIDGET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::SCREEN) ==
+ FPDF_ANNOT_SCREEN,
+ "CPDF_Annot::SCREEN value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::PRINTERMARK) ==
+ FPDF_ANNOT_PRINTERMARK,
+ "CPDF_Annot::PRINTERMARK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::TRAPNET) ==
+ FPDF_ANNOT_TRAPNET,
+ "CPDF_Annot::TRAPNET value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::WATERMARK) ==
+ FPDF_ANNOT_WATERMARK,
+ "CPDF_Annot::WATERMARK value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::THREED) ==
+ FPDF_ANNOT_THREED,
+ "CPDF_Annot::THREED value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::RICHMEDIA) ==
+ FPDF_ANNOT_RICHMEDIA,
+ "CPDF_Annot::RICHMEDIA value mismatch");
+static_assert(static_cast<int>(CPDF_Annot::Subtype::XFAWIDGET) ==
+ FPDF_ANNOT_XFAWIDGET,
+ "CPDF_Annot::XFAWIDGET value mismatch");
+
+DLLEXPORT int STDCALL FPDFPage_GetAnnotCount(FPDF_PAGE page) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pFormDict)
+ return 0;
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ return pAnnots ? pAnnots->GetCount() : 0;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetAnnot(FPDF_PAGE page,
+ int index,
+ FPDF_ANNOTATION* annot) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage || !pPage->m_pFormDict || index < 0 || !annot)
+ return false;
+ CPDF_Array* pAnnots = pPage->m_pFormDict->GetArrayFor("Annots");
+ if (!pAnnots || static_cast<size_t>(index) >= pAnnots->GetCount())
+ return false;
+
+ CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(index));
+ *annot = FPDFAnnotationFromCPDFDictionary(pDict);
+ return *annot ? true : false;
+}
+
+DLLEXPORT FPDF_ANNOTATION_SUBTYPE STDCALL
+FPDFAnnot_GetSubtype(FPDF_ANNOTATION annot) {
+ CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot);
+ if (!pAnnotDict)
+ return FPDF_ANNOT_UNKNOWN;
+ return static_cast<FPDF_ANNOTATION_SUBTYPE>(
+ CPDF_Annot::StringToAnnotSubtype(pAnnotDict->GetStringFor("Subtype")));
+}
+
+DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetColor(FPDF_ANNOTATION annot,
+ FPDFANNOT_COLORTYPE type,
+ unsigned int* R,
+ unsigned int* G,
+ unsigned int* B,
+ unsigned int* A) {
+ CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot);
+ if (!pAnnotDict || !R || !G || !B || !A)
+ return false;
+
+ CPDF_Array* pColor = pAnnotDict->GetArrayFor(
+ type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C");
+ *A =
+ (pAnnotDict->KeyExist("CA") ? pAnnotDict->GetNumberFor("CA") : 1) * 255.f;
+ if (!pColor) {
+ // Use default color. The default colors must be consistent with the ones
+ // used to generate AP. See calls to GetColorStringWithDefault() in
+ // CPVT_GenerateAP::Generate*AP().
+ if (pAnnotDict->GetStringFor("Subtype") == "Highlight") {
+ *R = 255;
+ *G = 255;
+ *B = 0;
+ } else {
+ *R = 0;
+ *G = 0;
+ *B = 0;
+ }
+ return true;
+ }
+ CPVT_Color color = CPVT_Color::ParseColor(*pColor);
+ switch (color.nColorType) {
+ case CPVT_Color::kRGB:
+ *R = color.fColor1 * 255.f;
+ *G = color.fColor2 * 255.f;
+ *B = color.fColor3 * 255.f;
+ break;
+ case CPVT_Color::kGray:
+ *R = 255.f * color.fColor1;
+ *G = 255.f * color.fColor1;
+ *B = 255.f * color.fColor1;
+ break;
+ case CPVT_Color::kCMYK:
+ *R = 255.f * (1 - color.fColor1) * (1 - color.fColor4);
+ *G = 255.f * (1 - color.fColor2) * (1 - color.fColor4);
+ *B = 255.f * (1 - color.fColor3) * (1 - color.fColor4);
+ break;
+ case CPVT_Color::kTransparent:
+ *R = 0;
+ *G = 0;
+ *B = 0;
+ break;
+ }
+ return true;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL
+FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) {
+ if (!annot)
+ return false;
+ FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot);
+ return subtype == FPDF_ANNOT_LINK || subtype == FPDF_ANNOT_HIGHLIGHT ||
+ subtype == FPDF_ANNOT_UNDERLINE || subtype == FPDF_ANNOT_SQUIGGLY ||
+ subtype == FPDF_ANNOT_STRIKEOUT;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL
+FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot,
+ FS_QUADPOINTSF* quadPoints) {
+ if (!annot || !quadPoints || !FPDFAnnot_HasAttachmentPoints(annot))
+ return false;
+ CPDF_Array* pArray =
+ CPDFDictionaryFromFPDFAnnotation(annot)->GetArrayFor("QuadPoints");
+ if (!pArray)
+ return false;
+ quadPoints->x1 = pArray->GetNumberAt(0);
+ quadPoints->y1 = pArray->GetNumberAt(1);
+ quadPoints->x2 = pArray->GetNumberAt(2);
+ quadPoints->y2 = pArray->GetNumberAt(3);
+ quadPoints->x3 = pArray->GetNumberAt(4);
+ quadPoints->y3 = pArray->GetNumberAt(5);
+ quadPoints->x4 = pArray->GetNumberAt(6);
+ quadPoints->y4 = pArray->GetNumberAt(7);
+ return true;
+}
+
+DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetRect(FPDF_ANNOTATION annot,
+ FS_RECTF* rect) {
+ CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot);
+ if (!rect || !pAnnotDict)
+ return false;
+ CFX_FloatRect rt = pAnnotDict->GetRectFor("Rect");
+ rect->left = rt.left;
+ rect->bottom = rt.bottom;
+ rect->right = rt.right;
+ rect->top = rt.top;
+ return true;
+}
+
+DLLEXPORT unsigned long STDCALL FPDFAnnot_GetText(FPDF_ANNOTATION annot,
+ FPDFANNOT_TEXTTYPE type,
+ char* buffer,
+ unsigned long buflen) {
+ CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFAnnotation(annot);
+ if (!pAnnotDict)
+ return 0;
+ CFX_ByteString key = type == FPDFANNOT_TEXTTYPE_Author ? "T" : "Contents";
+ CFX_ByteString contents = pAnnotDict->GetUnicodeTextFor(key).UTF16LE_Encode();
+ unsigned long len = contents.GetLength();
+ if (buffer && buflen >= len)
+ memcpy(buffer, contents.c_str(), len);
+ return len;
+}