summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/fitz/output-svg.h19
-rw-r--r--source/fitz/svg-device.c120
-rw-r--r--source/tools/mudraw.c2
3 files changed, 83 insertions, 58 deletions
diff --git a/include/mupdf/fitz/output-svg.h b/include/mupdf/fitz/output-svg.h
index 348d6c7c..ebabc42a 100644
--- a/include/mupdf/fitz/output-svg.h
+++ b/include/mupdf/fitz/output-svg.h
@@ -6,16 +6,23 @@
#include "mupdf/fitz/device.h"
#include "mupdf/fitz/output.h"
+enum {
+ FZ_SVG_TEXT_AS_PATH = 0,
+ FZ_SVG_TEXT_AS_TEXT = 1,
+};
+
/*
fz_new_svg_device: Create a device that outputs (single page)
- SVG files to the given output stream.
+ SVG files to the given output stream.
+
+ output: The output stream to send the constructed SVG page to.
- output: The output stream to send the constructed SVG page
- to.
+ page_width, page_height: The page dimensions to use (in points).
- page_width, page_height: The page dimensions to use (in
- points).
+ text_format: How to emit text. One of the following values:
+ FZ_SVG_TEXT_AS_TEXT: As <text> elements with possible layout errors and mismatching fonts.
+ FZ_SVG_TEXT_AS_PATH: As <path> elements with exact visual appearance.
*/
-fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height);
+fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height, int text_format);
#endif
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 3db68ada..c460df18 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -1,12 +1,6 @@
#include "fitz-imp.h"
#include "glyph-cache-imp.h"
-#ifdef SVG_TEXT_AS_TEXT
-#define SVG_TEXT_ALPHA(A) A
-#else
-#define SVG_TEXT_ALPHA(A) 0
-#endif
-
typedef struct svg_device_s svg_device;
typedef struct tile_s tile;
@@ -47,6 +41,8 @@ struct svg_device_s
{
fz_device super;
+ int text_as_text;
+
fz_output *out;
fz_output *out_store;
fz_output *defs;
@@ -598,19 +594,23 @@ svg_dev_fill_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
font *fnt;
fz_text_span *span;
- for (span = text->head; span; span = span->next)
+ if (sdev->text_as_text)
{
- fz_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, colorspace, color, SVG_TEXT_ALPHA(alpha));
- svg_dev_text_span(ctx, sdev, ctm, span);
+ for (span = text->head; span; span = span->next)
+ {
+ fz_printf(ctx, out, "<text");
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_text_span(ctx, sdev, ctm, span);
+ }
}
-#ifndef SVG_TEXT_AS_TEXT
- for (span = text->head; span; span = span->next)
+ else
{
- 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);
+ 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);
+ }
}
-#endif
}
static void
@@ -622,19 +622,23 @@ svg_dev_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
font *fnt;
fz_text_span *span;
- for (span = text->head; span; span = span->next)
+ if (sdev->text_as_text)
{
- fz_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, colorspace, color, SVG_TEXT_ALPHA(alpha));
- svg_dev_text_span(ctx, sdev, ctm, span);
+ for (span = text->head; span; span = span->next)
+ {
+ fz_printf(ctx, out, "<text");
+ svg_dev_fill_color(ctx, sdev, colorspace, color, alpha);
+ svg_dev_text_span(ctx, sdev, ctm, span);
+ }
}
-#ifndef SVG_TEXT_AS_TEXT
- for (span = text->head; span; span = span->next)
+ else
{
- 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);
+ 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);
+ }
}
-#endif
}
static void
@@ -652,21 +656,26 @@ svg_dev_clip_text(fz_context *ctx, fz_device *dev, const fz_text *text, const fz
fz_bound_text(ctx, text, NULL, ctm, &bounds);
out = start_def(ctx, sdev);
- fz_printf(ctx, out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n",
- num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
- for (span = text->head; span; span = span->next)
+ fz_printf(ctx, out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
+ num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
+ fz_printf(ctx, out, " maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n");
+ if (sdev->text_as_text)
{
- fz_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), white, SVG_TEXT_ALPHA(1));
- svg_dev_text_span(ctx, sdev, ctm, span);
+ for (span = text->head; span; span = span->next)
+ {
+ fz_printf(ctx, out, "<text");
+ svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
+ svg_dev_text_span(ctx, sdev, ctm, span);
+ }
}
-#ifndef SVG_TEXT_AS_TEXT
- for (span = text->head; span; span = span->next)
+ else
{
- 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);
+ 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);
+ }
}
-#endif
fz_printf(ctx, out, "</mask>\n");
out = end_def(ctx, sdev);
fz_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", num);
@@ -687,22 +696,27 @@ svg_dev_clip_stroke_text(fz_context *ctx, fz_device *dev, const fz_text *text, c
fz_bound_text(ctx, text, NULL, ctm, &bounds);
out = start_def(ctx, sdev);
- fz_printf(ctx, out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n",
+ fz_printf(ctx, out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"",
num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
- for (span = text->head; span; span = span->next)
+ fz_printf(ctx, out, " maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n");
+ if (sdev->text_as_text)
{
- fz_printf(ctx, out, "<text");
- svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
- svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, SVG_TEXT_ALPHA(1));
- svg_dev_text_span(ctx, sdev, ctm, span);
+ for (span = text->head; span; span = span->next)
+ {
+ fz_printf(ctx, out, "<text");
+ svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
+ svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
+ svg_dev_text_span(ctx, sdev, ctm, span);
+ }
}
-#ifndef SVG_TEXT_AS_TEXT
- for (span = text->head; span; span = span->next)
+ else
{
- 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);
+ 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);
+ }
}
-#endif
fz_printf(ctx, out, "</mask>\n");
out = end_def(ctx, sdev);
fz_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", num);
@@ -717,11 +731,14 @@ svg_dev_ignore_text(fz_context *ctx, fz_device *dev, const fz_text *text, const
float black[3] = { 0, 0, 0};
- for (span = text->head; span; span = span->next)
+ if (sdev->text_as_text)
{
- fz_printf(ctx, out, "<text");
- svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), black, 0.0f);
- svg_dev_text_span(ctx, sdev, ctm, span);
+ for (span = text->head; span; span = span->next)
+ {
+ fz_printf(ctx, out, "<text");
+ svg_dev_fill_color(ctx, sdev, fz_device_rgb(ctx), black, 0.0f);
+ svg_dev_text_span(ctx, sdev, ctm, span);
+ }
}
}
@@ -1158,7 +1175,7 @@ svg_dev_drop_device(fz_context *ctx, fz_device *dev)
fz_free(ctx, sdev->images);
}
-fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height)
+fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height, int text_format)
{
svg_device *dev = fz_new_device(ctx, sizeof *dev);
@@ -1196,6 +1213,7 @@ fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width,
dev->out = out;
dev->out_store = out;
dev->id = 0;
+ dev->text_as_text = (text_format == FZ_SVG_TEXT_AS_TEXT);
fz_printf(ctx, out, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
fz_printf(ctx, out, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 2bcf989e..ff915f6c 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -594,7 +594,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
fz_try(ctx)
{
- dev = fz_new_svg_device(ctx, out, tbounds.x1-tbounds.x0, tbounds.y1-tbounds.y0);
+ dev = fz_new_svg_device(ctx, out, tbounds.x1-tbounds.x0, tbounds.y1-tbounds.y0, FZ_SVG_TEXT_AS_PATH);
if (lowmemory)
fz_enable_device_hints(ctx, dev, FZ_NO_CACHE);
if (list)