From 4fd9a47465c0f2f17aa2a840d8452b2bee6bec33 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Thu, 1 Jun 2017 18:56:09 -0400 Subject: 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 Reviewed-by: Lei Zhang Reviewed-by: dsinclair --- samples/pdfium_test.cc | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) (limited to 'samples/pdfium_test.cc') diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index e33ceadabf..5520fa4c26 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -19,6 +19,7 @@ #include "core/fdrm/crypto/fx_crypt.h" #include "public/cpp/fpdf_deleters.h" +#include "public/fpdf_annot.h" #include "public/fpdf_dataavail.h" #include "public/fpdf_edit.h" #include "public/fpdf_ext.h" @@ -28,6 +29,7 @@ #include "public/fpdfview.h" #include "samples/image_diff_png.h" #include "testing/test_support.h" +#include "third_party/base/logging.h" #ifdef _WIN32 #include @@ -57,6 +59,7 @@ enum OutputFormat { OUTPUT_TEXT, OUTPUT_PPM, OUTPUT_PNG, + OUTPUT_ANNOT, #ifdef _WIN32 OUTPUT_BMP, OUTPUT_EMF, @@ -193,6 +196,154 @@ void WriteText(FPDF_PAGE page, const char* pdf_name, int num) { (void)fclose(fp); } +std::string AnnotSubtypeToString(FPDF_ANNOTATION_SUBTYPE subtype) { + if (subtype == FPDF_ANNOT_TEXT) + return "Text"; + if (subtype == FPDF_ANNOT_LINK) + return "Link"; + if (subtype == FPDF_ANNOT_FREETEXT) + return "FreeText"; + if (subtype == FPDF_ANNOT_LINE) + return "Line"; + if (subtype == FPDF_ANNOT_SQUARE) + return "Square"; + if (subtype == FPDF_ANNOT_CIRCLE) + return "Circle"; + if (subtype == FPDF_ANNOT_POLYGON) + return "Polygon"; + if (subtype == FPDF_ANNOT_POLYLINE) + return "PolyLine"; + if (subtype == FPDF_ANNOT_HIGHLIGHT) + return "Highlight"; + if (subtype == FPDF_ANNOT_UNDERLINE) + return "Underline"; + if (subtype == FPDF_ANNOT_SQUIGGLY) + return "Squiggly"; + if (subtype == FPDF_ANNOT_STRIKEOUT) + return "StrikeOut"; + if (subtype == FPDF_ANNOT_STAMP) + return "Stamp"; + if (subtype == FPDF_ANNOT_CARET) + return "Caret"; + if (subtype == FPDF_ANNOT_INK) + return "Ink"; + if (subtype == FPDF_ANNOT_POPUP) + return "Popup"; + if (subtype == FPDF_ANNOT_FILEATTACHMENT) + return "FileAttachment"; + if (subtype == FPDF_ANNOT_SOUND) + return "Sound"; + if (subtype == FPDF_ANNOT_MOVIE) + return "Movie"; + if (subtype == FPDF_ANNOT_WIDGET) + return "Widget"; + if (subtype == FPDF_ANNOT_SCREEN) + return "Screen"; + if (subtype == FPDF_ANNOT_PRINTERMARK) + return "PrinterMark"; + if (subtype == FPDF_ANNOT_TRAPNET) + return "TrapNet"; + if (subtype == FPDF_ANNOT_WATERMARK) + return "Watermark"; + if (subtype == FPDF_ANNOT_THREED) + return "3D"; + if (subtype == FPDF_ANNOT_RICHMEDIA) + return "RichMedia"; + if (subtype == FPDF_ANNOT_XFAWIDGET) + return "XFAWidget"; + NOTREACHED(); + return ""; +} + +void WriteAnnot(FPDF_PAGE page, const char* pdf_name, int num) { + // Open the output text file. + char filename[256]; + int chars_formatted = + snprintf(filename, sizeof(filename), "%s.%d.annot.txt", pdf_name, num); + if (chars_formatted < 0 || + static_cast(chars_formatted) >= sizeof(filename)) { + fprintf(stderr, "Filename %s is too long\n", filename); + return; + } + FILE* fp = fopen(filename, "w"); + if (!fp) { + fprintf(stderr, "Failed to open %s for output\n", filename); + return; + } + + int annot_count = FPDFPage_GetAnnotCount(page); + fprintf(fp, "Number of annotations: %d\n\n", annot_count); + + // Iterate through all annotations on this page. + for (int i = 0; i < annot_count; i++) { + // Retrieve the annotation object and its subtype. + fprintf(fp, "Annotation #%d:\n", i + 1); + FPDF_ANNOTATION annot; + if (!FPDFPage_GetAnnot(page, i, &annot)) { + fprintf(fp, "Failed to retrieve annotation!\n\n"); + continue; + } + FPDF_ANNOTATION_SUBTYPE subtype = FPDFAnnot_GetSubtype(annot); + fprintf(fp, "Subtype: %s\n", AnnotSubtypeToString(subtype).c_str()); + + // Retrieve the annotation's color and interior color. + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + if (!FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_Color, &R, &G, &B, &A)) { + fprintf(fp, "Failed to retrieve color.\n"); + } else { + fprintf(fp, "Color in RGBA: %d %d %d %d\n", R, G, B, A); + } + if (!FPDFAnnot_GetColor(annot, FPDFANNOT_COLORTYPE_InteriorColor, &R, &G, + &B, &A)) { + fprintf(fp, "Failed to retrieve interior color.\n"); + } else { + fprintf(fp, "Interior color in RGBA: %d %d %d %d\n", R, G, B, A); + } + + // Retrieve the annotation's contents and author. + unsigned long len = + FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents, nullptr, 0); + std::vector buf(len); + FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Contents, buf.data(), len); + fprintf(fp, "Content: %ls\n", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + len = FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Author, nullptr, 0); + buf.clear(); + buf.resize(len); + FPDFAnnot_GetText(annot, FPDFANNOT_TEXTTYPE_Author, buf.data(), len); + fprintf(fp, "Author: %ls\n", + GetPlatformWString(reinterpret_cast(buf.data())) + .c_str()); + + // Retrieve the annotation's quadpoints if it is a markup annotation. + FS_QUADPOINTSF quadpoints; + if (FPDFAnnot_HasAttachmentPoints(annot)) { + if (!FPDFAnnot_GetAttachmentPoints(annot, &quadpoints)) { + fprintf(fp, "Failed to retrieve quadpoints.\n"); + } else { + fprintf(fp, "Quadpoints: (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n", + quadpoints.x1, quadpoints.y1, quadpoints.x2, quadpoints.y2, + quadpoints.x3, quadpoints.y3, quadpoints.x4, quadpoints.y4); + } + } + + // Retrieve the annotation's rectangle coordinates. + FS_RECTF rect; + if (!FPDFAnnot_GetRect(annot, &rect)) { + fprintf(fp, "Failed to retrieve rectangle.\n\n"); + } else { + fprintf(fp, "Rectangle: l - %f, b - %f, r - %f, t - %f\n\n", rect.left, + rect.bottom, rect.right, rect.top); + } + } + + (void)fclose(fp); +} + static std::string WritePng(const char* pdf_name, int num, const void* buffer_void, @@ -494,6 +645,12 @@ bool ParseCommandLine(const std::vector& args, return false; } options->output_format = OUTPUT_TEXT; + } else if (cur_arg == "--annot") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --annot argument\n"); + return false; + } + options->output_format = OUTPUT_ANNOT; #ifdef PDF_ENABLE_SKIA } else if (cur_arg == "--skp") { if (options->output_format != OUTPUT_NONE) { @@ -807,6 +964,10 @@ bool RenderPage(const std::string& name, WriteText(page.get(), name.c_str(), page_index); break; + case OUTPUT_ANNOT: + WriteAnnot(page.get(), name.c_str(), page_index); + break; + case OUTPUT_PNG: image_file_name = WritePng(name.c_str(), page_index, buffer, stride, width, height); -- cgit v1.2.3