summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-08-29 17:12:48 +0100
committerPaul Gardiner <paulg.artifex@glidos.net>2013-08-29 17:12:48 +0100
commit6453f81a6f1c218cd118427bb8e23f2b2ede2f7d (patch)
treef085f21c0ee013883cda791759bc8f113268b044
parentd396b126c7ab5c241e0dc7ff0edd9942ad5dfdaa (diff)
downloadmupdf-6453f81a6f1c218cd118427bb8e23f2b2ede2f7d.tar.xz
Make the pdf device produce more efficient appearance streams for text
-rw-r--r--source/pdf/pdf-device.c73
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