summaryrefslogtreecommitdiff
path: root/source/fitz/svg-device.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2015-10-09 11:07:42 +0200
committerTor Andersson <tor.andersson@artifex.com>2015-12-11 13:02:33 +0100
commitfa0bffa57e7e2164f0201b0f2fdc984d475674ae (patch)
treead6a7d7bc8641e390552ba8c49fdba351de00f82 /source/fitz/svg-device.c
parente3275837d5738c5092b2e452829919e31ad553e5 (diff)
downloadmupdf-fa0bffa57e7e2164f0201b0f2fdc984d475674ae.tar.xz
Keep spans of multiple fonts and sizes in one fz_text object.
Diffstat (limited to 'source/fitz/svg-device.c')
-rw-r--r--source/fitz/svg-device.c214
1 files changed, 117 insertions, 97 deletions
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 4461f79e..a2cc5ed1 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -238,82 +238,86 @@ svg_dev_text(fz_context *ctx, svg_device *sdev, const fz_matrix *ctm, fz_text *t
fz_matrix local_trm;
float size;
int start, is_wspace, was_wspace;
+ fz_text_span *span;
- /* Rely on the fact that trm.{e,f} == 0 */
- size = fz_matrix_expansion(&text->trm);
- local_trm.a = text->trm.a / size;
- local_trm.b = text->trm.b / size;
- local_trm.c = -text->trm.c / size;
- local_trm.d = -text->trm.d / size;
- local_trm.e = 0;
- local_trm.f = 0;
- fz_invert_matrix(&inverse, &local_trm);
- fz_concat(&local_trm, &local_trm, ctm);
+ for (span = text->head; text; span = span->next)
+ {
+ /* Rely on the fact that trm.{e,f} == 0 */
+ size = fz_matrix_expansion(&span->trm);
+ local_trm.a = span->trm.a / size;
+ local_trm.b = span->trm.b / size;
+ local_trm.c = -span->trm.c / size;
+ local_trm.d = -span->trm.d / size;
+ local_trm.e = 0;
+ local_trm.f = 0;
+ fz_invert_matrix(&inverse, &local_trm);
+ fz_concat(&local_trm, &local_trm, ctm);
- fz_printf(ctx, out, " transform=\"matrix(%g,%g,%g,%g,%g,%g)\"",
- local_trm.a, local_trm.b, local_trm.c, local_trm.d, local_trm.e, local_trm.f);
- fz_printf(ctx, out, " font-size=\"%g\"", size);
- fz_printf(ctx, out, " font-family=\"%s\"", text->font->name);
+ fz_printf(ctx, out, " transform=\"matrix(%g,%g,%g,%g,%g,%g)\"",
+ local_trm.a, local_trm.b, local_trm.c, local_trm.d, local_trm.e, local_trm.f);
+ fz_printf(ctx, out, " font-size=\"%g\"", size);
+ fz_printf(ctx, out, " font-family=\"%s\"", span->font->name);
- /* Leading (and repeated) whitespace presents a problem for SVG
- * text, so elide it here. */
- for (start=0; start < text->len; start++)
- {
- fz_text_item *it = &text->items[start];
- if (!is_xml_wspace(it->ucs))
- break;
- }
+ /* Leading (and repeated) whitespace presents a problem for SVG
+ * text, so elide it here. */
+ for (start=0; start < span->len; start++)
+ {
+ fz_text_item *it = &span->items[start];
+ if (!is_xml_wspace(it->ucs))
+ break;
+ }
- fz_printf(ctx, out, " x=");
- was_wspace = 0;
- for (i=start; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- fz_point p;
- is_wspace = is_xml_wspace(it->ucs);
- if (is_wspace && was_wspace)
- continue;
- was_wspace = is_wspace;
- p.x = it->x;
- p.y = it->y;
- fz_transform_point(&p, &inverse);
- fz_printf(ctx, out, "%c%g", i == start ? '\"' : ' ', p.x);
- }
- fz_printf(ctx, out, "\" y=");
- was_wspace = 0;
- for (i=start; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- fz_point p;
- is_wspace = is_xml_wspace(it->ucs);
- if (is_wspace && was_wspace)
- continue;
- was_wspace = is_wspace;
- p.x = it->x;
- p.y = it->y;
- fz_transform_point(&p, &inverse);
- fz_printf(ctx, out, "%c%g", i == start ? '\"' : ' ', p.y);
- }
- fz_printf(ctx, out, "\">\n");
- was_wspace = 0;
- for (i=start; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- int c = it->ucs;
- is_wspace = is_xml_wspace(c);
- if (is_wspace && was_wspace)
- continue;
- was_wspace = is_wspace;
- if (c >= 32 && c <= 127 && c != '<' && c != '&')
- fz_printf(ctx, out, "%c", c);
- else
- fz_printf(ctx, out, "&#x%04x;", c);
+ fz_printf(ctx, out, " x=");
+ was_wspace = 0;
+ for (i=start; i < span->len; i++)
+ {
+ fz_text_item *it = &span->items[i];
+ fz_point p;
+ is_wspace = is_xml_wspace(it->ucs);
+ if (is_wspace && was_wspace)
+ continue;
+ was_wspace = is_wspace;
+ p.x = it->x;
+ p.y = it->y;
+ fz_transform_point(&p, &inverse);
+ fz_printf(ctx, out, "%c%g", i == start ? '\"' : ' ', p.x);
+ }
+ fz_printf(ctx, out, "\" y=");
+ was_wspace = 0;
+ for (i=start; i < span->len; i++)
+ {
+ fz_text_item *it = &span->items[i];
+ fz_point p;
+ is_wspace = is_xml_wspace(it->ucs);
+ if (is_wspace && was_wspace)
+ continue;
+ was_wspace = is_wspace;
+ p.x = it->x;
+ p.y = it->y;
+ fz_transform_point(&p, &inverse);
+ fz_printf(ctx, out, "%c%g", i == start ? '\"' : ' ', p.y);
+ }
+ fz_printf(ctx, out, "\">\n");
+ was_wspace = 0;
+ for (i=start; i < span->len; i++)
+ {
+ fz_text_item *it = &span->items[i];
+ int c = it->ucs;
+ is_wspace = is_xml_wspace(c);
+ if (is_wspace && was_wspace)
+ continue;
+ was_wspace = is_wspace;
+ if (c >= 32 && c <= 127 && c != '<' && c != '&')
+ fz_printf(ctx, out, "%c", c);
+ else
+ fz_printf(ctx, out, "&#x%04x;", c);
+ }
+ fz_printf(ctx, out, "\n</text>\n");
}
- fz_printf(ctx, out, "\n</text>\n");
}
static font *
-svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matrix *ctm)
+svg_dev_text_span_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text_span *span, const fz_matrix *ctm)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
@@ -323,7 +327,7 @@ svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const
for (font_idx = 0; font_idx < sdev->num_fonts; font_idx++)
{
- if (sdev->fonts[font_idx].font == text->font)
+ if (sdev->fonts[font_idx].font == span->font)
break;
}
if (font_idx == sdev->num_fonts)
@@ -339,14 +343,14 @@ svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const
sdev->max_fonts = newmax;
}
sdev->fonts[font_idx].id = sdev->id++;
- sdev->fonts[font_idx].font = fz_keep_font(ctx, text->font);
+ sdev->fonts[font_idx].font = fz_keep_font(ctx, span->font);
sdev->num_fonts++;
}
fnt = &sdev->fonts[font_idx];
- for (i=0; i < text->len; i++)
+ for (i=0; i < span->len; i++)
{
- fz_text_item *it = &text->items[i];
+ fz_text_item *it = &span->items[i];
int gid = it->gid;
if (gid < 0)
@@ -367,7 +371,7 @@ svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const
/* Need to send this one */
fz_rect rect;
fz_path *path;
- path = fz_outline_glyph(ctx, text->font, gid, &fz_identity);
+ path = fz_outline_glyph(ctx, span->font, gid, &fz_identity);
if (path)
{
fz_bound_path(ctx, path, NULL, &fz_identity, &rect);
@@ -382,12 +386,12 @@ svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const
}
else
{
- fz_bound_glyph(ctx, text->font, gid, &fz_identity, &rect);
+ fz_bound_glyph(ctx, span->font, gid, &fz_identity, &rect);
shift.e = -rect.x0;
shift.f = -rect.y0;
out = start_def(ctx, sdev);
fz_printf(ctx, out, "<symbol id=\"font_%x_%x\">", fnt->id, gid);
- fz_run_t3_glyph(ctx, text->font, gid, &shift, dev);
+ fz_run_t3_glyph(ctx, span->font, gid, &shift, dev);
}
fz_printf(ctx, out, "</symbol>");
out = end_def(ctx, sdev);
@@ -399,7 +403,7 @@ svg_dev_text_as_paths_defs(fz_context *ctx, fz_device *dev, fz_text *text, const
}
static void
-svg_dev_text_as_paths_fill(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matrix *ctm,
+svg_dev_text_span_as_paths_fill(fz_context *ctx, fz_device *dev, fz_text_span *span, const fz_matrix *ctm,
fz_colorspace *colorspace, float *color, float alpha, font *fnt)
{
svg_device *sdev = (svg_device*)dev;
@@ -410,16 +414,16 @@ svg_dev_text_as_paths_fill(fz_context *ctx, fz_device *dev, fz_text *text, const
fz_matrix shift = { 1, 0, 0, 1, 0, 0};
/* 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.a = span->trm.a;
+ local_trm.b = span->trm.b;
+ local_trm.c = span->trm.c;
+ local_trm.d = span->trm.d;
local_trm.e = 0;
local_trm.f = 0;
- for (i=0; i < text->len; i++)
+ for (i=0; i < span->len; i++)
{
- fz_text_item *it = &text->items[i];
+ fz_text_item *it = &span->items[i];
int gid = it->gid;
if (gid < 0)
@@ -439,7 +443,7 @@ svg_dev_text_as_paths_fill(fz_context *ctx, fz_device *dev, fz_text *text, const
}
static void
-svg_dev_text_as_paths_stroke(fz_context *ctx, fz_device *dev, fz_text *text,
+svg_dev_text_span_as_paths_stroke(fz_context *ctx, fz_device *dev, fz_text_span *span,
fz_stroke_state *stroke, const fz_matrix *ctm,
fz_colorspace *colorspace, float *color, float alpha, font *fnt)
{
@@ -451,16 +455,16 @@ svg_dev_text_as_paths_stroke(fz_context *ctx, fz_device *dev, fz_text *text,
fz_matrix shift = { 1, 0, 0, 1, 0, 0};
/* 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.a = span->trm.a;
+ local_trm.b = span->trm.b;
+ local_trm.c = span->trm.c;
+ local_trm.d = span->trm.d;
local_trm.e = 0;
local_trm.f = 0;
- for (i=0; i < text->len; i++)
+ for (i=0; i < span->len; i++)
{
- fz_text_item *it = &text->items[i];
+ fz_text_item *it = &span->items[i];
int gid = it->gid;
if (gid < 0)
@@ -566,12 +570,16 @@ svg_dev_fill_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matri
fz_output *out = sdev->out;
font *fnt;
+ fz_text_span *span;
fz_printf(ctx, out, "<text");
svg_dev_fill_color(ctx, sdev, colorspace, color, 0.0f);
svg_dev_text(ctx, sdev, ctm, text);
- fnt = svg_dev_text_as_paths_defs(ctx, dev, text, ctm);
- svg_dev_text_as_paths_fill(ctx, dev, text, ctm, colorspace, color, alpha, fnt);
+ for (span = text->head; span; span = span->next)
+ {
+ fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
+ svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, colorspace, color, alpha, fnt);
+ }
}
static void
@@ -582,12 +590,16 @@ svg_dev_stroke_text(fz_context *ctx, fz_device *dev, fz_text *text, fz_stroke_st
fz_output *out = sdev->out;
font *fnt;
+ fz_text_span *span;
fz_printf(ctx, out, "<text");
svg_dev_fill_color(ctx, sdev, colorspace, color, 0.0f);
svg_dev_text(ctx, sdev, ctm, text);
- fnt = svg_dev_text_as_paths_defs(ctx, dev, text, ctm);
- svg_dev_text_as_paths_stroke(ctx, dev, text, stroke, ctm, colorspace, color, alpha, fnt);
+ for (span = text->head; span; span = span->next)
+ {
+ fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
+ svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, colorspace, color, alpha, fnt);
+ }
}
static void
@@ -600,6 +612,7 @@ svg_dev_clip_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matri
int num = sdev->id++;
float white[3] = { 1, 1, 1 };
font *fnt;
+ fz_text_span *span;
fz_bound_text(ctx, text, NULL, ctm, &bounds);
@@ -609,8 +622,11 @@ svg_dev_clip_text(fz_context *ctx, fz_device *dev, fz_text *text, const fz_matri
fz_printf(ctx, out, "<text");
svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), white, 0.0f);
svg_dev_text(ctx, sdev, ctm, text);
- fnt = svg_dev_text_as_paths_defs(ctx, dev, text, ctm);
- svg_dev_text_as_paths_fill(ctx, dev, text, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ for (span = text->head; span; span = span->next)
+ {
+ fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
+ svg_dev_text_span_as_paths_fill(ctx, dev, span, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ }
fz_printf(ctx, out, "</mask>\n");
out = end_def(ctx, sdev);
fz_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", num);
@@ -626,6 +642,7 @@ svg_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, fz_text *text, fz_stro
int num = sdev->id++;
float white[3] = { 255, 255, 255 };
font *fnt;
+ fz_text_span *span;
fz_bound_text(ctx, text, NULL, ctm, &bounds);
@@ -636,8 +653,11 @@ svg_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, fz_text *text, fz_stro
svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 0.0f);
svg_dev_text(ctx, sdev, ctm, text);
- fnt = svg_dev_text_as_paths_defs(ctx, dev, text, ctm);
- svg_dev_text_as_paths_stroke(ctx, dev, text, stroke, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ for (span = text->head; span; span = span->next)
+ {
+ fnt = svg_dev_text_span_as_paths_defs(ctx, dev, span, ctm);
+ svg_dev_text_span_as_paths_stroke(ctx, dev, span, stroke, ctm, fz_device_rgb(ctx), white, 1.0f, fnt);
+ }
fz_printf(ctx, out, "</mask>\n");
out = end_def(ctx, sdev);
fz_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", num);