summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-appearance.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2018-06-13 19:31:23 +0200
committerRobin Watts <robin.watts@artifex.com>2018-06-22 16:48:45 +0100
commit23cc78236960753e6157d5038db9e960670f0c64 (patch)
treebabe8ff6ff3055ca25ee43c3bfe9c1f5ba1b8e25 /source/pdf/pdf-appearance.c
parentcb3bfc400fc9ff2393d819f56120a1bde3b26e90 (diff)
downloadmupdf-23cc78236960753e6157d5038db9e960670f0c64.tar.xz
Use line spacing and padding when creating variable text appearance.
Format single-line Widget/Tx fields vertically centered.
Diffstat (limited to 'source/pdf/pdf-appearance.c')
-rw-r--r--source/pdf/pdf-appearance.c103
1 files changed, 72 insertions, 31 deletions
diff --git a/source/pdf/pdf-appearance.c b/source/pdf/pdf-appearance.c
index e690bffe..5693fe3d 100644
--- a/source/pdf/pdf-appearance.c
+++ b/source/pdf/pdf-appearance.c
@@ -637,7 +637,7 @@ pdf_write_icon_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf, fz_
}
static float
-measure_stamp_string(fz_context *ctx, fz_font *font, const char *text)
+measure_simple_string(fz_context *ctx, fz_font *font, const char *text)
{
float w = 0;
while (*text)
@@ -678,7 +678,7 @@ write_stamp_string(fz_context *ctx, fz_buffer *buf, fz_font *font, const char *t
static void
write_stamp(fz_context *ctx, fz_buffer *buf, fz_font *font, const char *text, float y, float h)
{
- float tw = measure_stamp_string(ctx, font, text) * h;
+ float tw = measure_simple_string(ctx, font, text) * h;
fz_append_string(ctx, buf, "BT\n");
fz_append_printf(ctx, buf, "/Times %g Tf\n", h);
fz_append_printf(ctx, buf, "%g %g Td\n", (190-tw)/2, y);
@@ -804,10 +804,10 @@ break_simple_string(fz_context *ctx, fz_font *font, float size, const char *a, c
static void
write_simple_string_with_quadding(fz_context *ctx, fz_buffer *buf, fz_font *font, float size,
- const char *a, float maxw, int q)
+ const char *a, float maxw, int q)
{
const char *b;
- float px = 0, x, w;
+ float px = 0, x = 0, w;
while (*a)
{
w = break_simple_string(ctx, font, size, a, &b, maxw);
@@ -844,11 +844,21 @@ static const char *full_font_name(const char **name)
static void
write_variable_text(fz_context *ctx, pdf_annot *annot, fz_buffer *buf, pdf_obj **res,
- char *text, const char *fontname, float size, float color[3], int q,
- float x, float y, float w, float h, float lw)
+ const char *text, const char *fontname, float size, float color[3], int q,
+ float w, float h, float padding, int multiline)
{
pdf_obj *res_font;
fz_font *font;
+ float lineheight;
+ float baseline;
+
+ w -= padding * 2;
+ h -= padding * 2;
+ if (size == 0)
+ size = multiline ? 12 : h;
+
+ lineheight = size * 1.15f; /* empirically derived from Adobe reader */
+ baseline = size * 0.8f;
font = fz_new_base14_font(ctx, full_font_name(&fontname));
fz_try(ctx)
@@ -861,9 +871,27 @@ write_variable_text(fz_context *ctx, pdf_annot *annot, fz_buffer *buf, pdf_obj *
fz_append_string(ctx, buf, "BT\n");
fz_append_printf(ctx, buf, "%g %g %g rg\n", color[0], color[1], color[2]);
fz_append_printf(ctx, buf, "/%s %g Tf\n", fontname, size);
- fz_append_printf(ctx, buf, "%g TL\n", size);
- fz_append_printf(ctx, buf, "%g %g Td\n", x+lw, y+h-lw);
- write_simple_string_with_quadding(ctx, buf, font, size, text, w-lw*2, q);
+ if (multiline)
+ {
+ fz_append_printf(ctx, buf, "%g TL\n", lineheight);
+ fz_append_printf(ctx, buf, "%g %g Td\n", padding, padding+h+(size-baseline));
+ write_simple_string_with_quadding(ctx, buf, font, size, text, w, q);
+ }
+ else
+ {
+ float tx = 0, ty = (h - size) / 2;
+ if (q > 0)
+ {
+ float tw = measure_simple_string(ctx, font, text) * size;
+ if (q == 1)
+ tx = (w - tw) / 2;
+ else
+ tx = (w - tw);
+ }
+ fz_append_printf(ctx, buf, "%g %g Td\n", padding+tx, padding+h-baseline-ty);
+ write_simple_string(ctx, buf, text, text + strlen(text));
+ fz_append_printf(ctx, buf, " Tj\n");
+ }
fz_append_string(ctx, buf, "ET\n");
}
fz_always(ctx)
@@ -879,7 +907,7 @@ pdf_write_free_text_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf
const char *font;
float size, color[3];
char *text;
- float x, y, w, h, t, lw;
+ float w, h, t, b;
int q, r;
/* /Rotate is an undocumented annotation property supported by Adobe */
@@ -887,7 +915,6 @@ pdf_write_free_text_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf
q = pdf_annot_quadding(ctx, annot);
pdf_annot_default_appearance(ctx, annot, &font, &size, color);
- x = y = 0;
w = rect->x1 - rect->x0;
h = rect->y1 - rect->y0;
if (r == 90 || r == 270)
@@ -899,18 +926,16 @@ pdf_write_free_text_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf
if (pdf_write_fill_color_appearance(ctx, annot, buf))
fz_append_printf(ctx, buf, "0 0 %g %g re\nf\n", w, h);
- lw = pdf_write_border_appearance(ctx, annot, buf);
- if (lw > 0)
+ b = pdf_write_border_appearance(ctx, annot, buf);
+ if (b > 0)
{
fz_append_printf(ctx, buf, "%g %g %g RG\n", color[0], color[1], color[2]);
- fz_append_printf(ctx, buf, "%g %g %g %g re\nS\n", x+lw/2, y+lw/2, w-lw, h-lw);
- x += size * 0.2f;
- w -= size * 0.4f;
+ fz_append_printf(ctx, buf, "%g %g %g %g re\nS\n", b/2, b/2, w-b, h-b);
}
text = pdf_copy_annot_contents(ctx, annot);
fz_try(ctx)
- write_variable_text(ctx, annot, buf, res, text, font, size, color, q, x, y, w, h, lw);
+ write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, b*2, 1);
fz_always(ctx)
fz_free(ctx, text);
fz_catch(ctx)
@@ -919,15 +944,16 @@ pdf_write_free_text_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf
static void
pdf_write_tx_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
- fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res)
+ fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res,
+ const char *text, int ff)
{
const char *font;
float size, color[3];
- char *text;
- float w, h, t;
+ float w, h, t, b;
int q, r;
r = pdf_dict_get_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME(MK)), PDF_NAME(R));
+ b = pdf_annot_border(ctx, annot);
q = pdf_annot_quadding(ctx, annot);
pdf_annot_default_appearance(ctx, annot, &font, &size, color);
@@ -940,22 +966,20 @@ pdf_write_tx_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf
fz_append_string(ctx, buf, "/Tx BMC\nq\n");
- text = pdf_field_value(ctx, annot->page->doc, annot->obj);
- fz_try(ctx)
- write_variable_text(ctx, annot, buf, res, text, font, size, color, q, 0, 0, w, h, 0);
- fz_always(ctx)
- fz_free(ctx, text);
- fz_catch(ctx)
- fz_rethrow(ctx);
+ if (ff & Ff_Multiline)
+ write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, 2, 1);
+ else
+ write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, 2, 0);
fz_append_string(ctx, buf, "Q\nEMC\n");
}
static void
pdf_write_ch_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
- fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res)
+ fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res,
+ const char *text, int ff)
{
- pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res);
+ pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res, text, ff);
}
static void
@@ -963,10 +987,27 @@ pdf_write_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res)
{
pdf_obj *ft = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(FT));
+ int ff = pdf_get_field_flags(ctx, annot->page->doc, annot->obj);
if (pdf_name_eq(ctx, ft, PDF_NAME(Tx)))
- pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res);
+ {
+ char *text = pdf_field_value(ctx, annot->page->doc, annot->obj);
+ fz_try(ctx)
+ pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res, text, ff);
+ fz_always(ctx)
+ fz_free(ctx, text);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+ }
else if (pdf_name_eq(ctx, ft, PDF_NAME(Ch)))
- pdf_write_ch_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res);
+ {
+ char *text = pdf_field_value(ctx, annot->page->doc, annot->obj);
+ fz_try(ctx)
+ pdf_write_ch_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res, text, ff);
+ fz_always(ctx)
+ fz_free(ctx, text);
+ fz_catch(ctx)
+ fz_rethrow(ctx);
+ }
else
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot create appearance stream for %s widgets", pdf_to_name(ctx, ft));
}