diff options
Diffstat (limited to 'pdf/pdf_annot.c')
-rw-r--r-- | pdf/pdf_annot.c | 215 |
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: |