summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNancy Durgin <nancy.durgin@artifex.com>2021-05-04 13:31:00 -0700
committerNancy Durgin <nancy.durgin@artifex.com>2021-05-04 14:42:47 -0700
commit4446af64ac67fc75e3c2e5dc0564ad75a131d29f (patch)
tree7d19e7447b8c1d056892c024a7b13d03e4fb8f71
parent017c34239a7328799e16def7c60a2111efa886fd (diff)
downloadghostpdl-4446af64ac67fc75e3c2e5dc0564ad75a131d29f.tar.gz
Implement MultiLine for UTF16 in Tx Widgets
Added a bunch of comments. Fix unrelated compiler warning.
-rw-r--r--pdf/pdf_annot.c69
-rw-r--r--pdf/pdf_doc.c2
2 files changed, 52 insertions, 19 deletions
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 4d4eac015..ad8b3cbaf 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -960,10 +960,19 @@ pdfi_annot_display_centered_text(pdf_context *ctx, pdf_dict *annot, gs_rect *rec
return code;
}
-/* Display a string formatted to fit in rect (outside BT/ET) */
+/* Display a string formatted to fit in rect (outside BT/ET)
+ *
+ * TODO: I am sharing code between the FreeText and field/Tx implementation.
+ * The gs code has completely different implementations for these.
+ * I am not sure if there are some different assumptions about font encodings?
+ * The Tx field can apparently be UTF8 or UTF16, whereas the FreeText implementation just assumed
+ * it was ASCII.
+ * If you see some weird behavior with character mappings or line breaks, then
+ * this might be something to revisit.
+ */
static int
pdfi_annot_display_formatted_text(pdf_context *ctx, pdf_dict *annot,
- gs_rect *rect, pdf_string *text)
+ gs_rect *rect, pdf_string *text, bool is_UTF16)
{
double x;
double lineheight = 0;
@@ -978,13 +987,19 @@ pdfi_annot_display_formatted_text(pdf_context *ctx, pdf_dict *annot,
byte ch;
bool firstchar = true;
bool linestart = true;
+ int charlen;
+
+ if (is_UTF16)
+ charlen = 2;
+ else
+ charlen = 1;
code = pdfi_BT(ctx);
if (code < 0)
return code;
/* Allocate a temp string to use, length 1 char */
- code = pdfi_object_alloc(ctx, PDF_STRING, 1, (pdf_obj **)&temp_string);
+ code = pdfi_object_alloc(ctx, PDF_STRING, charlen, (pdf_obj **)&temp_string);
if (code < 0) goto exit;
pdfi_countup(temp_string);
@@ -996,18 +1011,24 @@ pdfi_annot_display_formatted_text(pdf_context *ctx, pdf_dict *annot,
x_max = rect->q.x;
x = x_start;
- for (i=0; i<text->length; i++) {
+ for (i=0; i<text->length; i+=charlen) {
+ int j;
+
if (linestart) {
x = x_start;
}
- ch = text->data[i];
- temp_string->data[0] = ch;
+ for (j = 0; j < charlen; j++) {
+ ch = text->data[i+j];
+ temp_string->data[j] = ch;
+ }
/* If EOL character encountered, move down to next line */
- if (ch == '\r' || ch == '\n') {
- linestart = true;
- continue;
+ if (charlen == 1) { /* Can only check this for ASCII font */
+ if (ch == '\r' || ch == '\n') {
+ linestart = true;
+ continue;
+ }
}
/* get size of the character */
@@ -2265,7 +2286,7 @@ static int pdfi_annot_draw_FreeText(pdf_context *ctx, pdf_dict *annot, pdf_obj *
code = pdfi_dict_knownget_type(ctx, annot, "Contents", PDF_STRING, (pdf_obj **)&Contents);
if (code < 0) goto exit;
if (code > 0) {
- code = pdfi_annot_display_formatted_text(ctx, annot, &modrect, Contents);
+ code = pdfi_annot_display_formatted_text(ctx, annot, &modrect, Contents, false);
if (code < 0) goto exit;
}
@@ -3345,12 +3366,7 @@ static int pdfi_form_Tx_multiline(pdf_context *ctx, pdf_dict *annot, gs_rect *re
modrect.q.x -= 2;
modrect.q.y -= 2;
- if (is_UTF16) {
- /* TODO: Not supported yet */
- code = pdfi_form_Tx_simple(ctx, annot, rect, V, Ff, Q, is_UTF16);
- } else {
- code = pdfi_annot_display_formatted_text(ctx, annot, &modrect, V);
- }
+ code = pdfi_annot_display_formatted_text(ctx, annot, &modrect, V, is_UTF16);
if (code < 0) goto exit;
exit:
@@ -3364,7 +3380,7 @@ static int pdfi_form_Tx_comb(pdf_context *ctx, pdf_dict *annot, gs_rect *rect, p
{
int code = 0;
- /* TODO: Implement... */
+ /* TODO: Implement... Need a sample that uses COMB! */
code = pdfi_form_Tx_simple(ctx, annot, rect, V, Ff, Q, is_UTF16);
if (code < 0) goto exit;
exit:
@@ -3380,6 +3396,10 @@ static int pdfi_form_display_Tx(pdf_context *ctx, pdf_dict *annot, gs_rect *rect
pdf_string *modV = NULL;
bool is_UTF16;
+ /* TODO: If we wanted to preserve this for pdfwrite, we would have to generate
+ * a stream for the AP. See PDF1.7 spec, Variable Text (page 677).
+ */
+
/* Get modified V that skips the BOM, if any */
code = pdfi_form_modV(ctx, V, &modV, &is_UTF16);
if (code < 0) goto exit;
@@ -3467,6 +3487,17 @@ static int pdfi_form_draw_Sig(pdf_context *ctx, pdf_dict *field, pdf_obj *AP)
return code;
}
+/* TODO: The spec handles "regenerate appearance", which it does by generating
+ * a new AP stream for the field, and then rendering it as a form.
+ * The gs code does try to handle this case.
+ * For now I am just going to generate the data inline, without building it as a Form/Stream.
+ * If we have want to preserve the AP (i.e. for pdfwrite device, generate the AP and include
+ * it in the output, rather than just rendering it into the output) then this needs to change.
+ * Currently gs doesn't try to preserve AcroForms, so we aren't losing any functionality by
+ * not doing this. But it is a place for a future enhancement.
+ *
+ * See also, the comment on pdfi_annot_preserve_Widget().
+ */
static int pdfi_annot_render_field(pdf_context *ctx, pdf_dict *field, pdf_name *FT, pdf_obj *AP)
{
int code;
@@ -4112,7 +4143,9 @@ static int pdfi_annot_preserve_Widget(pdf_context *ctx, pdf_dict *annot, pdf_nam
%% we don't want to preserve widget annotations either, because the consumer of the new
%% PDF won't know what values they should take. So we draw widget annotations instead. If we
%% ever preserve AcroForms then we should alter this to preserve Widgets as well.
- */
+ *
+ * TODO: See also, comment on pdfi_annot_render_field().
+ */
return pdfi_annot_draw(ctx, annot, subtype);
}
diff --git a/pdf/pdf_doc.c b/pdf/pdf_doc.c
index db5a6017f..4b4d87d07 100644
--- a/pdf/pdf_doc.c
+++ b/pdf/pdf_doc.c
@@ -222,7 +222,7 @@ void pdfi_read_OptionalRoot(pdf_context *ctx)
if (known) {
if (ctx->args.pdfdebug)
dmprintf(ctx->memory, "%% Collection\n");
- code = pdfi_dict_get(ctx, ctx->Root, "Collection", &ctx->Collection);
+ code = pdfi_dict_get(ctx, ctx->Root, "Collection", (pdf_obj **)&ctx->Collection);
if (code < 0)
dmprintf(ctx->memory, "\n **** Warning: Failed to read Collection information.\n");
}