summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_annot.c')
-rw-r--r--pdf/pdf_annot.c215
1 files changed, 162 insertions, 53 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 116081c2..7b96be1c 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019-2021 Artifex Software, Inc.
+/* Copyright (C) 2019-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -24,6 +24,7 @@
#include "pdf_loop_detect.h"
#include "pdf_colour.h"
#include "pdf_trans.h"
+#include "pdf_font_types.h"
#include "pdf_gstate.h"
#include "pdf_misc.h"
#include "pdf_optcontent.h"
@@ -1076,8 +1077,7 @@ pdfi_annot_display_formatted_text(pdf_context *ctx, pdf_dict *annot,
code = pdfi_string_bbox(ctx, temp_string, &bbox, &awidth, false);
if (code < 0) goto exit;
- if (linestart || ((x + awidth.x) <= x_max)) {
- } else {
+ if (!linestart && ((x + awidth.x) > x_max)) {
x = x_start;
linestart = true;
}
@@ -1447,8 +1447,8 @@ static int pdfi_annot_draw_LE_one(pdf_context *ctx, pdf_dict *annot, pdf_name *L
}
if (!dispatch_ptr->name) {
char str[100];
- memcpy(str, (const char *)LE->data, LE->length);
- str[LE->length] = '\0';
+ memcpy(str, (const char *)LE->data, LE->length < 100 ? LE->length : 99);
+ str[LE->length < 100 ? LE->length : 99] = '\0';
dbgmprintf1(ctx->memory, "ANNOT: WARNING No handler for LE %s\n", str);
}
@@ -3091,6 +3091,11 @@ static int pdfi_annot_draw_PolyLine(pdf_context *ctx, pdf_dict *annot, pdf_obj *
code = pdfi_dict_knownget_type(ctx, annot, "Vertices", PDF_ARRAY, (pdf_obj **)&Vertices);
if (code < 0) goto exit;
+ if (code == 0) {
+ code = gs_note_error(gs_error_undefined);
+ goto exit;
+ }
+
size = pdfi_array_size(Vertices);
if (size == 0) {
code = 0;
@@ -3155,7 +3160,7 @@ static int pdfi_annot_draw_Polygon(pdf_context *ctx, pdf_dict *annot, pdf_obj *N
if (code < 0) goto exit1;
code = pdfi_dict_knownget_type(ctx, annot, "Vertices", PDF_ARRAY, (pdf_obj **)&Vertices);
- if (code < 0) goto exit;
+ if (code <= 0) goto exit;
code = pdfi_annot_path_array(ctx, annot, Vertices);
if (code < 0) goto exit1;
@@ -3708,8 +3713,8 @@ static int pdfi_annot_draw_NotImplemented(pdf_context *ctx, pdf_dict *annot, pdf
code = pdfi_dict_get_type(ctx, annot, "Subtype", PDF_NAME, (pdf_obj **)&Subtype);
if (code < 0) goto exit;
- memcpy(str, (const char *)Subtype->data, Subtype->length);
- str[Subtype->length] = '\0';
+ memcpy(str, (const char *)Subtype->data, Subtype->length < 100 ? Subtype->length : 99);
+ str[Subtype->length < 100 ? Subtype->length : 99] = '\0';
dbgmprintf1(ctx->memory, "ANNOT: No AP, default appearance for Subtype %s Not Implemented\n", str);
exit:
@@ -3880,8 +3885,8 @@ static int pdfi_annot_draw(pdf_context *ctx, pdf_dict *annot, pdf_name *subtype)
}
if (!dispatch_ptr->subtype) {
char str[100];
- memcpy(str, (const char *)subtype->data, subtype->length);
- str[subtype->length] = '\0';
+ memcpy(str, (const char *)subtype->data, subtype->length < 100 ? subtype->length : 99);
+ str[subtype->length < 100 ? subtype->length : 99] = '\0';
dbgmprintf1(ctx->memory, "ANNOT: No handler for subtype %s\n", str);
/* Not necessarily an error? We can just render the AP if there is one */
@@ -4107,6 +4112,117 @@ static int pdfi_annot_preserve_modAP(pdf_context *ctx, pdf_dict *annot, pdf_name
/* Make a temporary copy of the annotation dict with some fields left out or
* modified, then do a pdfmark on it
*/
+
+const char *PermittedKeys[] = {
+ /* These keys are valid for all annotation types, we specifically do not allow /P or /Parent */
+ "Type",
+ "Subtype",
+ "Rect",
+ "Contents",
+ "NM",
+ "M",
+ "F",
+ "AP",
+ "AS",
+ "Border",
+ "C",
+ "StructParent",
+ "OC",
+ "AF",
+ "ca",
+ "CA",
+ "BM",
+ "Lang",
+ /* Keys by annotation type (some are common to more than one type, only one entry per key) */
+ /* Markup Annotations we specifically do not permit RT, IRT or Popup */
+ "T",
+ "RC",
+ "CreationDate",
+ "Subj",
+ "IT",
+ "ExData",
+ /* Text annotations */
+ "Open",
+ "Name",
+ "State",
+ "StateModel",
+ /* This isn't specified as being allowed, but Acrobat does something with it, so we need to preserve it */
+ "Rotate",
+ /* Link annotations */
+ "A",
+ "Dest",
+ "H",
+ "PA",
+ "QuadPoints",
+ /* FreeText annotations */
+ "DA",
+ "Q",
+ "DS",
+ "CL",
+ "IT",
+ "BE",
+ "RD",
+ "BS",
+ "LE",
+ /* Line Annotations */
+ "L",
+ "LE",
+ "IC",
+ "LL",
+ "LLE",
+ "Cap",
+ "LLO",
+ "CP",
+ "Measure",
+ "CO",
+ /* Square and Circle annotations */
+ "Path",
+ /* Polygon and PolyLine annotations */
+ "Vertices",
+ /* Text Markup annotations */
+ /* Caret annotations */
+ "Sy",
+ /* Rubber Stamp annotations */
+ /* Ink annotations */
+ "InkList",
+ /* Popup annotations */
+ "Open",
+ /* File attachment annotation */
+ "FS",
+ /* Sound annotations */
+ "Sound",
+ /* Movie annotations */
+ "Movie",
+ /* Screen annotations */
+ "MK",
+ "AA",
+ /* We don't handle Widget annotations as annotations, we draw them */
+ /* Printer's Mark annotations */
+ /* Trap Network annotations */
+ /* Watermark annotations */
+ "FixedPrint",
+ "Matrix",
+ "H",
+ "V",
+ /* Redaction annotations */
+ "RO",
+ "OverlayText",
+ "Repeat",
+ /* Projection annotations */
+ /* 3D and RichMedia annotations */
+};
+
+static int isKnownKey(pdf_context *ctx, pdf_name *Key)
+{
+ int i = 0;
+
+ for (i = 0; i < sizeof(PermittedKeys) / sizeof (const char *); i++) {
+ if (pdfi_name_is(Key, PermittedKeys[i]))
+ return 1;
+ }
+ return 0;
+}
+
static int pdfi_annot_preserve_mark(pdf_context *ctx, pdf_dict *annot, pdf_name *subtype)
{
int code = 0;
@@ -4136,51 +4252,44 @@ static int pdfi_annot_preserve_mark(pdf_context *ctx, pdf_dict *annot, pdf_name
while (code >= 0) {
resolve = false;
- if (pdfi_name_is(Key, "Popup") || pdfi_name_is(Key, "IRT") || pdfi_name_is(Key, "RT") ||
- pdfi_name_is(Key, "P") || pdfi_name_is(Key, "Parent")) {
- /* Delete some keys
- * These would not be handled correctly and are optional.
- * (see pdf_draw.ps/loadannot())
- * TODO: Could probably handle some of these since they are typically
- * just references, and we do have a way to handle references?
- * Look into it later...
- */
+ if (!isKnownKey(ctx, Key)) {
code = pdfi_dict_delete_pair(ctx, tempdict, Key);
if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "AP")) {
- /* Special handling for AP -- have fun! */
- code = pdfi_annot_preserve_modAP(ctx, tempdict, Key);
- if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "QuadPoints")) {
- code = pdfi_annot_preserve_modQP(ctx, tempdict, Key);
- if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "A")) {
- code = pdfi_mark_modA(ctx, tempdict);
- if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "Dest")) {
- if (ctx->args.no_pdfmark_dests) {
- /* If omitting dests, such as for multi-page output, then omit this whole annotation */
- code = 0;
- goto exit;
- }
- code = pdfi_mark_modDest(ctx, tempdict);
- if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "StructTreeRoot")) {
- /* TODO: Bug691785 has Link annots with /StructTreeRoot
- * It is super-circular, and causes issues.
- * GS code only adds in certain values for Link so it doesn't
- * run into a problem. I am just going to delete it.
- * There should be a better solution to handle circular stuff
- * generically.
- */
- code = pdfi_dict_delete_pair(ctx, tempdict, Key);
- if (code < 0) goto exit;
- } else if (pdfi_name_is(Key, "Sound") || pdfi_name_is(Key, "Movie")) {
- resolve = false;
} else {
- resolve = true;
+ if (pdfi_name_is(Key, "AP")) {
+ /* Special handling for AP -- have fun! */
+ code = pdfi_annot_preserve_modAP(ctx, tempdict, Key);
+ if (code < 0) goto exit;
+ } else if (pdfi_name_is(Key, "QuadPoints")) {
+ code = pdfi_annot_preserve_modQP(ctx, tempdict, Key);
+ if (code < 0) goto exit;
+ } else if (pdfi_name_is(Key, "A")) {
+ code = pdfi_pdfmark_modA(ctx, tempdict);
+ if (code < 0) goto exit;
+ } else if (pdfi_name_is(Key, "Dest")) {
+ if (ctx->args.no_pdfmark_dests) {
+ /* If omitting dests, such as for multi-page output, then omit this whole annotation */
+ code = 0;
+ goto exit;
+ }
+ code = pdfi_pdfmark_modDest(ctx, tempdict);
+ if (code < 0) goto exit;
+ } else if (pdfi_name_is(Key, "StructTreeRoot")) {
+ /* TODO: Bug691785 has Link annots with /StructTreeRoot
+ * It is super-circular, and causes issues.
+ * GS code only adds in certain values for Link so it doesn't
+ * run into a problem. I am just going to delete it.
+ * There should be a better solution to handle circular stuff
+ * generically.
+ */
+ code = pdfi_dict_delete_pair(ctx, tempdict, Key);
+ if (code < 0) goto exit;
+ } else if (pdfi_name_is(Key, "Sound") || pdfi_name_is(Key, "Movie")) {
+ resolve = false;
+ } else {
+ resolve = true;
+ }
}
-
if (resolve) {
code = pdfi_dict_get_by_key(ctx, annot, (const pdf_name *)Key, &Value);
if (code < 0) goto exit;
@@ -4212,9 +4321,9 @@ static int pdfi_annot_preserve_mark(pdf_context *ctx, pdf_dict *annot, pdf_name
gs_currentmatrix(ctx->pgs, &ctm);
if (pdfi_name_is(subtype, "Link"))
- code = pdfi_mark_from_dict(ctx, tempdict, &ctm, "LNK");
+ code = pdfi_pdfmark_from_dict(ctx, tempdict, &ctm, "LNK");
else
- code = pdfi_mark_from_dict(ctx, tempdict, &ctm, "ANN");
+ code = pdfi_pdfmark_from_dict(ctx, tempdict, &ctm, "ANN");
if (code < 0) goto exit;
exit: