summaryrefslogtreecommitdiff
path: root/source/fitz/svg-device.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-10-07 16:58:12 +0100
committerRobin Watts <robin.watts@artifex.com>2013-10-07 18:38:46 +0100
commit17c797eaaec9b33aedf4970fe2184f86f65b25d8 (patch)
tree9962266c90753103ca4adb39e4994d25a8a84514 /source/fitz/svg-device.c
parent97307cc25161194a4bceeaccdbb49d644fc395c3 (diff)
downloadmupdf-17c797eaaec9b33aedf4970fe2184f86f65b25d8.tar.xz
SVG device: Send text as reusable paths
Diffstat (limited to 'source/fitz/svg-device.c')
-rw-r--r--source/fitz/svg-device.c105
1 files changed, 95 insertions, 10 deletions
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index d49a7ab9..f26e8e13 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -3,6 +3,8 @@
typedef struct svg_device_s svg_device;
typedef struct tile_s tile;
+typedef struct font_s font;
+typedef struct glyph_s glyph;
struct tile_s
{
@@ -13,6 +15,20 @@ struct tile_s
fz_point step;
};
+struct glyph_s
+{
+ float x_off;
+ float y_off;
+};
+
+struct font_s
+{
+ int id;
+ fz_font *font;
+ int max_sentlist;
+ glyph *sentlist;
+};
+
struct svg_device_s
{
fz_context *ctx;
@@ -23,6 +39,10 @@ struct svg_device_s
int num_tiles;
int max_tiles;
tile *tiles;
+
+ int num_fonts;
+ int max_fonts;
+ font *fonts;
};
/* Helper functions */
@@ -244,32 +264,97 @@ static void
svg_dev_text_as_paths(svg_device *sdev, const fz_matrix *ctm, fz_text *text,
fz_colorspace *colorspace, float *color, float alpha)
{
+ fz_context *ctx = sdev->ctx;
fz_output *out = sdev->out;
- int i;
+ int i, font_idx;
fz_matrix local_trm, local_trm2;
- float size;
+ font *fnt;
+ fz_matrix shift = { 1, 0, 0, 1, 0, 0};
+
+ for (font_idx = 0; font_idx < sdev->num_fonts; font_idx++)
+ {
+ if (sdev->fonts[font_idx].font == text->font)
+ break;
+ }
+ if (font_idx == sdev->num_fonts)
+ {
+ /* New font */
+ if (font_idx == sdev->max_fonts)
+ {
+ int newmax = sdev->max_fonts * 2;
+ if (newmax == 0)
+ newmax = 4;
+ sdev->fonts = fz_resize_array(ctx, sdev->fonts, newmax, sizeof(*sdev->fonts));
+ memset(&sdev->fonts[font_idx], 0, (newmax - font_idx) * sizeof(sdev->fonts[0]));
+ sdev->max_fonts = newmax;
+ }
+ sdev->fonts[font_idx].id = sdev->id++;
+ sdev->fonts[font_idx].font = fz_keep_font(ctx, text->font);
+ sdev->num_fonts++;
+ }
+ fnt = &sdev->fonts[font_idx];
+
+ for (i=0; i < text->len; i++)
+ {
+ fz_text_item *it = &text->items[i];
+ int gid = it->gid;
+
+ if (gid < 0)
+ continue;
+ if (gid >= fnt->max_sentlist)
+ {
+ int j;
+ fnt->sentlist = fz_resize_array(ctx, fnt->sentlist, gid+1, sizeof(fnt->sentlist[0]));
+ for (j = fnt->max_sentlist; j <= gid; j++)
+ {
+ fnt->sentlist[j].x_off = FLT_MIN;
+ fnt->sentlist[j].y_off = FLT_MIN;
+ }
+ fnt->max_sentlist = gid+1;
+ }
+ if (fnt->sentlist[gid].x_off == FLT_MIN)
+ {
+ /* Need to send this one */
+ fz_path *path = fz_outline_glyph(sdev->ctx, text->font, gid, &fz_identity);
+ fz_rect rect;
+ fz_bound_path(ctx, path, NULL, &fz_identity, &rect);
+ shift.e = -rect.x0;
+ shift.f = -rect.y0;
+ fz_transform_path(ctx, path, &shift);
+ fz_printf(out, "<symbol id=\"font_%x_%x\">", fnt->id, gid);
+ fz_printf(out, "<path");
+ svg_dev_path(sdev, path);
+ fz_printf(out, "/>\n");
+ fz_printf(out, "</symbol>");
+ fnt->sentlist[gid].x_off = rect.x0;
+ fnt->sentlist[gid].y_off = rect.y0;
+ }
+ }
/* Rely on the fact that trm.{e,f} == 0 */
local_trm.a = text->trm.a;
local_trm.b = text->trm.b;
- local_trm.c = -text->trm.c;
- local_trm.d = -text->trm.d;
+ local_trm.c = text->trm.c;
+ local_trm.d = text->trm.d;
local_trm.e = 0;
local_trm.f = 0;
- fz_concat(&local_trm, &local_trm, ctm);
for (i=0; i < text->len; i++)
{
fz_text_item *it = &text->items[i];
- int c = it->ucs;
- fz_path *path;
+ int gid = it->gid;
+
+ if (gid < 0)
+ continue;
+ shift.e = fnt->sentlist[gid].x_off;
+ shift.f = fnt->sentlist[gid].y_off;
local_trm.e = it->x;
local_trm.f = it->y;
fz_concat(&local_trm2, &local_trm, ctm);
- path = fz_outline_glyph(sdev->ctx, text->font, it->gid, &local_trm2);
- fz_printf(out, "<path");
- svg_dev_path(sdev, path);
+ fz_concat(&local_trm2, &shift, &local_trm2);
+ fz_printf(out, "<use xlink:href=\"#font_%x_%x\"", fnt->id, gid);
+ svg_dev_ctm(sdev, &local_trm2);
svg_dev_fill_color(sdev, colorspace, color, alpha);
fz_printf(out, "/>\n");
}