summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul@glidos.net>2012-04-09 13:08:36 +0100
committerPaul Gardiner <paul@glidos.net>2012-05-08 15:07:21 +0100
commit2aff7f90f0c2f60406b2854d1bea2217b44b78e1 (patch)
tree74dfc23da2671263693cef07cb0db0668152815b /pdf
parentc51bde81f837da868bde3d5395c9f44ee8c179b3 (diff)
downloadmupdf-2aff7f90f0c2f60406b2854d1bea2217b44b78e1.tar.xz
Forms: fix the base line for fit to width text
Diffstat (limited to 'pdf')
-rw-r--r--pdf/pdf_form.c107
1 files changed, 81 insertions, 26 deletions
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index a116e53e..aec11a09 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -128,7 +128,7 @@ static int read_font_size_from_da(fz_context *ctx, char *da)
{
if (last_tok_was_int)
{
- if (tok = PDF_TOK_NAME && !strcmp(lbuf.scratch, "Tf"))
+ if (tok == PDF_TOK_KEYWORD && !strcmp(lbuf.scratch, "Tf"))
fontsize = last_int_tok_val;
last_tok_was_int = 0;
@@ -170,7 +170,7 @@ static void copy_da_with_altered_size(fz_context *ctx, fz_buffer *fzbuf, char *d
{
if (last_tok_was_int)
{
- if (tok = PDF_TOK_NAME && !strcmp(lbuf.scratch, "Tf"))
+ if (tok == PDF_TOK_KEYWORD && !strcmp(lbuf.scratch, "Tf"))
fz_buffer_printf(ctx, fzbuf, " %1.2f", size);
else
fz_buffer_printf(ctx, fzbuf, " %d", last_int_tok_val);
@@ -223,27 +223,86 @@ static fz_bbox measure_text(pdf_document *doc, pdf_obj *dr, fz_buffer *fzbuf)
return bbox;
}
-fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, pdf_obj *dr, char *da, char *text)
+static fz_buffer *create_text_buffer(fz_context *ctx, fz_rect *clip, char *da, float fontsize, float x, float y, char *text)
{
- fz_context *ctx = doc->ctx;
- float height, width, fontsize;
- fz_buffer *fzbuf = NULL;
- fz_rect rect;
- fz_bbox tbox;
- const char *fmt1 =
+ fz_buffer *fzbuf = fz_new_buffer(ctx, 0);
+ const char *fmtstart =
"/Tx BMC"
- " q"
+ " q";
+ const char *fmtclip =
" %1.2f %1.2f %1.2f %1.2f re"
" W"
- " n"
+ " n";
+ const char *fmtbtxt =
" BT";
- const char *fmt2 =
- " 2 %1.2f Td"
+ const char *fmttxt =
+ " %1.2f %1.2f Td"
" (%s) Tj"
" ET"
" Q"
" EMC";
+ fz_try(ctx)
+ {
+ fz_buffer_printf(ctx, fzbuf, fmtstart);
+ if (clip)
+ fz_buffer_printf(ctx, fzbuf, fmtclip, clip->x0, clip->y0, clip->x1 - clip->x0, clip->y1 - clip->y0);
+ fz_buffer_printf(ctx, fzbuf, fmtbtxt);
+ if (fontsize < 0.0)
+ fz_buffer_printf(ctx, fzbuf, " %s", da); /* Copy da unchanged */
+ else
+ copy_da_with_altered_size(ctx, fzbuf, da, fontsize);
+ fz_buffer_printf(ctx, fzbuf, fmttxt, x, y, text);
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_buffer(ctx, fzbuf);
+ fz_rethrow(ctx);
+ }
+
+ return fzbuf;
+}
+
+static void measure_ascent_descent(pdf_document *doc, pdf_obj *dr, char *da, char *text, float *ascent, float *descent)
+{
+ fz_context *ctx = doc->ctx;
+ char *testtext = NULL;
+ fz_buffer *fzbuf = NULL;
+ fz_bbox bbox;
+
+ fz_var(testtext);
+ fz_var(fzbuf);
+ fz_try(ctx)
+ {
+ /* Heuristic: adding "My" to text will in most cases
+ * produce a measurement that will accompass all chars */
+ testtext = fz_malloc(ctx, strlen(text) + 3);
+ strcpy(testtext, "My");
+ strcat(testtext, text);
+ /* Use large font size for increased accuracy */
+ fzbuf = create_text_buffer(ctx, NULL, da, 100, 0, 0, testtext);
+ bbox = measure_text(doc, dr, fzbuf);
+ *descent = -bbox.y0 / 100.0;
+ *ascent = bbox.y1 / 100.0;
+ }
+ fz_always(ctx)
+ {
+ fz_drop_buffer(ctx, fzbuf);
+ fz_free(ctx, testtext);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, pdf_obj *dr, char *da, char *text)
+{
+ fz_context *ctx = doc->ctx;
+ float height, width, fontsize;
+ fz_buffer *fzbuf = NULL;
+ fz_rect rect;
+ fz_bbox tbox;
rect = *bbox;
if (rect.x1 - rect.x0 >= 2.0 && rect.y1 - rect.y0 >= 2.0)
@@ -260,20 +319,18 @@ fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, pdf_obj *dr,
fz_var(fzbuf);
fz_try(ctx)
{
+ float ascent, descent;
+
+ measure_ascent_descent(doc, dr, da, text, &ascent, &descent);
fontsize = read_font_size_from_da(ctx, da);
if (fontsize)
{
- fzbuf = fz_new_buffer(ctx, 0);
- fz_buffer_printf(ctx, fzbuf, fmt1, rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0);
- fz_buffer_printf(ctx, fzbuf, " %s", da); /* Copy da unchanged */
- fz_buffer_printf(ctx, fzbuf, fmt2, (bbox->y1 - bbox->y0 - fontsize)/2, text);
+ fzbuf = create_text_buffer(ctx, &rect, da, -1.0, 2.0, 2.0 + fontsize * descent, text);
}
else
{
- fzbuf = fz_new_buffer(ctx, 0);
- fz_buffer_printf(ctx, fzbuf, fmt1, rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0);
- copy_da_with_altered_size(ctx, fzbuf, da, height);
- fz_buffer_printf(ctx, fzbuf, fmt2, (bbox->y1 - bbox->y0 - height)/2, text);
+ fontsize = height;
+ fzbuf = create_text_buffer(ctx, &rect, da, fontsize, 2.0, 2.0 + height * descent, text);
tbox = measure_text(doc, dr, fzbuf);
if (tbox.x1 - tbox.x0 > width)
@@ -281,11 +338,9 @@ fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, pdf_obj *dr,
/* Text doesn't fit. Regenerate with a calculated font size */
fz_drop_buffer(ctx, fzbuf);
fzbuf = NULL;
- height = height * width / (tbox.x1 - tbox.x0);
- fzbuf = fz_new_buffer(ctx, 0);
- fz_buffer_printf(ctx, fzbuf, fmt1, rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0);
- copy_da_with_altered_size(ctx, fzbuf, da, height);
- fz_buffer_printf(ctx, fzbuf, fmt2, (bbox->y1 - bbox->y0 - height)/2, text);
+ fontsize = height * width / (tbox.x1 - tbox.x0);
+ /* Use the same offset to keep the baseline constant */
+ fzbuf = create_text_buffer(ctx, &rect, da, fontsize, 2.0, 2.0 + height * descent, text);
}
}
}