diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2013-08-29 17:12:48 +0100 |
---|---|---|
committer | Paul Gardiner <paulg.artifex@glidos.net> | 2013-08-29 17:12:48 +0100 |
commit | 6453f81a6f1c218cd118427bb8e23f2b2ede2f7d (patch) | |
tree | f085f21c0ee013883cda791759bc8f113268b044 /source | |
parent | d396b126c7ab5c241e0dc7ff0edd9942ad5dfdaa (diff) | |
download | mupdf-6453f81a6f1c218cd118427bb8e23f2b2ede2f7d.tar.xz |
Make the pdf device produce more efficient appearance streams for text
Diffstat (limited to 'source')
-rw-r--r-- | source/pdf/pdf-device.c | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/source/pdf/pdf-device.c b/source/pdf/pdf-device.c index 0074f7eb..1ce80b17 100644 --- a/source/pdf/pdf-device.c +++ b/source/pdf/pdf-device.c @@ -1,5 +1,11 @@ #include "mupdf/pdf.h" +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_ADVANCES_H + +#define ALLOWED_TEXT_POS_ERROR (0.001f) + typedef struct pdf_device_s pdf_device; typedef struct gstate_s gstate; @@ -653,8 +659,9 @@ pdf_dev_pop(pdf_device *pdev) } static void -pdf_dev_text(pdf_device *pdev, fz_text *text) +pdf_dev_text(pdf_device *pdev, fz_text *text, float size) { + int mask = FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM; int i; fz_matrix trm; fz_matrix inverse; @@ -670,10 +677,14 @@ pdf_dev_text(pdf_device *pdev, fz_text *text) trunc_trm.f = 0; fz_invert_matrix(&inverse, &trunc_trm); - for (i=0; i < text->len; i++) + i = 0; + while (i < text->len) { fz_text_item *it = &text->items[i]; fz_point delta; + float x; + int j; + delta.x = it->x - trm.e; delta.y = it->y - trm.f; fz_transform_point(&delta, &inverse); @@ -683,12 +694,32 @@ pdf_dev_text(pdf_device *pdev, fz_text *text) trm.e = it->x; trm.f = it->y; } - /* FIXME: should use it->gid, rather than it->ucs, and convert - * to the correct encoding */ - fz_buffer_printf(pdev->ctx, gs->buf, "<%02x> Tj\n", it->ucs); - /* FIXME: Advance the text position - doesn't matter at the - * moment as we absolutely position each glyph, but we should - * use more efficient text outputting where possible. */ + + j = i+1; + if (text->font->ft_face) + { + /* Find prefix of text for which the advance of each character accounts + * for the position offset */ + x = it->x; + while (j < text->len) + { + FT_Fixed adv; + FT_Get_Advance(text->font->ft_face, text->items[j-1].gid, mask, &adv); + x += (float)adv * size /((FT_Face)text->font->ft_face)->units_per_EM; + if (fabs(x - text->items[j].x) > ALLOWED_TEXT_POS_ERROR || fabs(it->y - text->items[j].y) > ALLOWED_TEXT_POS_ERROR) + break; + j++; + } + } + + fz_buffer_printf(pdev->ctx, gs->buf, "<"); + for (i = i; i < j; i++) + { + /* FIXME: should use it->gid, rather than it->ucs, and convert + * to the correct encoding */ + fz_buffer_printf(pdev->ctx, gs->buf, "%02x", text->items[i].ucs); + } + fz_buffer_printf(pdev->ctx, gs->buf, "> Tj\n"); } gs->tm.e = trm.e; gs->tm.f = trm.f; @@ -913,7 +944,7 @@ pdf_dev_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, pdf_dev_ctm(pdev, ctm); pdf_dev_alpha(pdev, alpha, 0); pdf_dev_color(pdev, colorspace, color, 0); - pdf_dev_text(pdev, text); + pdf_dev_text(pdev, text, size); } static void @@ -921,46 +952,62 @@ pdf_dev_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, cons fz_colorspace *colorspace, float *color, float alpha) { pdf_device *pdev = dev->user; + fz_matrix trm = text->trm; + float size = fz_matrix_expansion(&trm); + + fz_pre_scale(&trm, 1/size, 1/size); pdf_dev_begin_text(pdev, &text->trm, 1); pdf_dev_font(pdev, text->font, 1); pdf_dev_ctm(pdev, ctm); pdf_dev_alpha(pdev, alpha, 1); pdf_dev_color(pdev, colorspace, color, 1); - pdf_dev_text(pdev, text); + pdf_dev_text(pdev, text, size); } static void pdf_dev_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate) { pdf_device *pdev = dev->user; + fz_matrix trm = text->trm; + float size = fz_matrix_expansion(&trm); + + fz_pre_scale(&trm, 1/size, 1/size); pdf_dev_begin_text(pdev, &text->trm, 0); pdf_dev_ctm(pdev, ctm); pdf_dev_font(pdev, text->font, 7); - pdf_dev_text(pdev, text); + pdf_dev_text(pdev, text, size); } static void pdf_dev_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm) { pdf_device *pdev = dev->user; + fz_matrix trm = text->trm; + float size = fz_matrix_expansion(&trm); + + fz_pre_scale(&trm, 1/size, 1/size); pdf_dev_begin_text(pdev, &text->trm, 0); pdf_dev_font(pdev, text->font, 5); pdf_dev_ctm(pdev, ctm); - pdf_dev_text(pdev, text); + pdf_dev_text(pdev, text, size); } static void pdf_dev_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm) { pdf_device *pdev = dev->user; + fz_matrix trm = text->trm; + float size = fz_matrix_expansion(&trm); + + fz_pre_scale(&trm, 1/size, 1/size); pdf_dev_begin_text(pdev, &text->trm, 0); pdf_dev_ctm(pdev, ctm); pdf_dev_font(pdev, text->font, 3); - pdf_dev_text(pdev, text); + pdf_dev_text(pdev, text, size); } static void |