diff options
author | Paul Gardiner <paul@glidos.net> | 2012-05-08 15:06:57 +0100 |
---|---|---|
committer | Paul Gardiner <paul@glidos.net> | 2012-05-08 15:06:57 +0100 |
commit | 4a908c019f65ec3b5e50a916e3d209c6ad8ed23c (patch) | |
tree | 27e6b0961fd0b5f5e376de8f405d372d0ac3c4ea /pdf/pdf_form.c | |
parent | ce1398aeb5f2acec5d313f74958e703d2b14644d (diff) | |
download | mupdf-4a908c019f65ec3b5e50a916e3d209c6ad8ed23c.tar.xz |
Forms: handle scaling text to fit
Diffstat (limited to 'pdf/pdf_form.c')
-rw-r--r-- | pdf/pdf_form.c | 143 |
1 files changed, 105 insertions, 38 deletions
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c index c500b872..d5d7be72 100644 --- a/pdf/pdf_form.c +++ b/pdf/pdf_form.c @@ -111,9 +111,9 @@ static fz_widget *new_widget(pdf_document *doc, pdf_obj *obj) return widget; } -static int copy_da_with_size_check(fz_context *ctx, fz_buffer *fzbuf, char *da, int h) +static int read_font_size_from_da(fz_context *ctx, char *da) { - int tok, fontsize = h; /* Default to use if Tf defines size 0 */ + int tok, fontsize = 0; pdf_lexbuf lbuf; fz_stream *str = fz_open_memory(ctx, da, strlen(da)); @@ -129,18 +129,51 @@ static int copy_da_with_size_check(fz_context *ctx, fz_buffer *fzbuf, char *da, if (last_tok_was_int) { if (tok = PDF_TOK_NAME && !strcmp(lbuf.scratch, "Tf")) - { - /* Tf defines nonzero font size. Use defined value - * rather than the default */ - if(last_int_tok_val != 0) - fontsize = last_int_tok_val; + fontsize = last_int_tok_val; - fz_buffer_printf(ctx, fzbuf, " %d", fontsize); - } + last_tok_was_int = 0; + } + + if (tok == PDF_TOK_INT) + { + last_tok_was_int = 1; + last_int_tok_val = lbuf.i; + } + } + } + fz_always(ctx) + { + fz_close(str); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return fontsize; +} + +static void copy_da_with_altered_size(fz_context *ctx, fz_buffer *fzbuf, char *da, float size) +{ + int tok; + pdf_lexbuf lbuf; + fz_stream *str = fz_open_memory(ctx, da, strlen(da)); + + memset(lbuf.scratch, 0, sizeof(lbuf.scratch)); + lbuf.size = sizeof(lbuf.scratch); + fz_try(ctx) + { + int last_tok_was_int = 0; + int last_int_tok_val = 0; + + for (tok = pdf_lex(str, &lbuf); tok != PDF_TOK_EOF; tok = pdf_lex(str, &lbuf)) + { + if (last_tok_was_int) + { + if (tok = PDF_TOK_NAME && !strcmp(lbuf.scratch, "Tf")) + fz_buffer_printf(ctx, fzbuf, " %1.2f", size); else - { fz_buffer_printf(ctx, fzbuf, " %d", last_int_tok_val); - } last_tok_was_int = 0; } @@ -165,15 +198,38 @@ static int copy_da_with_size_check(fz_context *ctx, fz_buffer *fzbuf, char *da, { fz_rethrow(ctx); } +} - return fontsize; +static fz_bbox measure_text(pdf_document *doc, pdf_obj *dr, fz_buffer *fzbuf) +{ + fz_context *ctx = doc->ctx; + fz_device *dev = NULL; + fz_bbox bbox = fz_empty_bbox; + + fz_try(ctx) + { + dev = fz_new_bbox_device(doc->ctx, &bbox); + pdf_run_glyph(doc, dr, fzbuf, dev, fz_identity, NULL); + } + fz_always(ctx) + { + fz_free_device(dev); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return bbox; } -fz_buffer *create_text_appearance(fz_context *ctx, fz_rect *bbox, char *da, char *text) +fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, pdf_obj *dr, char *da, char *text) { - int height, fontsize; - fz_buffer *fzbuf; + fz_context *ctx = doc->ctx; + float height, width, fontsize; + fz_buffer *fzbuf = NULL; fz_rect rect; + fz_bbox tbox; const char *fmt1 = "/Tx BMC" " q" @@ -198,37 +254,48 @@ fz_buffer *create_text_appearance(fz_context *ctx, fz_rect *bbox, char *da, char rect.y1 -= 1.0; } - height = MAX(floor(bbox->y1 - bbox->y0 - 4.0), 1); - - fzbuf = fz_new_buffer(ctx, 0); - fz_buffer_printf(ctx, fzbuf, fmt1, rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0); - fontsize = copy_da_with_size_check(ctx, fzbuf, da, height); - fz_buffer_printf(ctx, fzbuf, fmt2, (bbox->y1 - bbox->y0 - fontsize)/2, text); - - return fzbuf; -} - -static fz_bbox measure_text(pdf_document *doc, pdf_obj *dr, fz_buffer *fzbuf) -{ - fz_context *ctx = doc->ctx; - fz_device *dev = NULL; - fz_bbox bbox = fz_empty_bbox; + height = MAX(bbox->y1 - bbox->y0 - 4.0, 1); + width = MAX(bbox->x1 - bbox->x0 - 4.0, 1); + fz_var(fzbuf); fz_try(ctx) { - dev = fz_new_bbox_device(doc->ctx, &bbox); - pdf_run_glyph(doc, dr, fzbuf, dev, fz_identity, NULL); - } - fz_always(ctx) - { - fz_free_device(dev); + 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); + } + 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); + tbox = measure_text(doc, dr, fzbuf); + + if (tbox.x1 - tbox.x0 > width) + { + /* 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); + } + } } fz_catch(ctx) { + fz_drop_buffer(ctx, fzbuf); fz_rethrow(ctx); } - return bbox; + return fzbuf; } static void update_text_appearance(pdf_document *doc, pdf_obj *obj, char *text) @@ -265,7 +332,7 @@ static void update_text_appearance(pdf_document *doc, pdf_obj *obj, char *text) fz_dict_put(form->resources, key, pdf_dict_get_val(dr, i)); } - fzbuf = create_text_appearance(ctx, &form->bbox, pdf_to_str_buf(da), text); + fzbuf = create_text_appearance(doc, &form->bbox, dr, pdf_to_str_buf(da), text); pdf_xobject_set_contents(ctx, form, fzbuf); } } |