summaryrefslogtreecommitdiff
path: root/source/fitz
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2017-02-17 15:09:20 +0100
committerTor Andersson <tor.andersson@artifex.com>2017-02-20 16:54:50 +0100
commitf4defeee497d21a211f83e7a8d2d6c2dcadca607 (patch)
treed3c9c3c02f4d64f172842423e43fca7c0373bdcf /source/fitz
parent029d5db2c4928a0bb4c357fc4db53aa614eac7f9 (diff)
downloadmupdf-f4defeee497d21a211f83e7a8d2d6c2dcadca607.tar.xz
Add no-reuse-images option to SVG device.
Also add explicit viewBox and width/height to image symbol and use elements, to work around a strange clipping/image scaling issue with firefox.
Diffstat (limited to 'source/fitz')
-rw-r--r--source/fitz/output-svg.c8
-rw-r--r--source/fitz/svg-device.c96
2 files changed, 58 insertions, 46 deletions
diff --git a/source/fitz/output-svg.c b/source/fitz/output-svg.c
index 40260fae..f8711031 100644
--- a/source/fitz/output-svg.c
+++ b/source/fitz/output-svg.c
@@ -9,12 +9,14 @@ struct fz_svg_writer_s
int count;
fz_output *out;
int text_format;
+ int reuse_images;
};
const char *fz_svg_write_options_usage =
"SVG output options:\n"
"\ttext=text: Emit text as <text> elements (inaccurate fonts).\n"
"\ttext=path: Emit text as <path> elements (accurate fonts).\n"
+ "\tno-reuse-images: Do not reuse images using <symbol> definitions.\n"
"\n"
;
@@ -31,7 +33,7 @@ svg_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabo
fz_format_output_path(ctx, path, sizeof path, wri->path, wri->count);
wri->out = fz_new_output_with_path(ctx, path, 0);
- return fz_new_svg_device(ctx, wri->out, w, h, wri->text_format);
+ return fz_new_svg_device(ctx, wri->out, w, h, wri->text_format, wri->reuse_images);
}
static void
@@ -65,6 +67,7 @@ fz_new_svg_writer(fz_context *ctx, const char *path, const char *args)
wri->super.drop_writer = svg_drop_writer;
wri->text_format = FZ_SVG_TEXT_AS_PATH;
+ wri->reuse_images = 1;
fz_try(ctx)
{
@@ -75,6 +78,9 @@ fz_new_svg_writer(fz_context *ctx, const char *path, const char *args)
else if (fz_option_eq(val, "path"))
wri->text_format = FZ_SVG_TEXT_AS_PATH;
}
+ if (fz_has_option(ctx, args, "no-reuse-images", &val))
+ if (fz_option_eq(val, "yes"))
+ wri->reuse_images = 0;
wri->path = fz_strdup(ctx, path ? path : "out-%04d.svg");
}
fz_catch(ctx)
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 09b3d82d..89c3b4b6 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -42,6 +42,7 @@ struct svg_device_s
fz_device super;
int text_as_text;
+ int reuse_images;
fz_output *out;
fz_output *out_store;
@@ -806,26 +807,28 @@ send_data_base64(fz_context *ctx, fz_output *out, fz_buffer *buffer)
/* We spot repeated images, and send them just once using
* symbols. Unfortunately, for pathological files, such
* as the example in Bug695988, this can cause viewers to
- * have conniptions. We therefore have a define that can
- * be made to avoid this (SVG_SEND_REPEATED_IMAGES). */
+ * have conniptions. We therefore have an option that is
+ * made to avoid this (reuse-images=no). */
static void
svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img)
{
fz_output *out = sdev->out;
fz_compressed_buffer *buffer;
-#ifndef SVG_SEND_REPEATED_IMAGES
int i;
int id;
- for (i = sdev->num_images-1; i >= 0; i--)
- {
- if (img == sdev->images[i].image)
- break;
- }
- if (i >= 0)
- id = sdev->images[i].id;
- else
+ if (sdev->reuse_images)
{
+ for (i = sdev->num_images-1; i >= 0; i--)
+ if (img == sdev->images[i].image)
+ break;
+ if (i >= 0)
+ {
+ fz_printf(ctx, out, "<use xlink:href=\"#im%d\" x=\"0\" y=\"0\" width=\"%d\" height=\"%d\"/>\n",
+ sdev->images[i].id, img->w, img->h);
+ return;
+ }
+
/* We need to send this image for the first time */
if (sdev->num_images == sdev->max_images)
{
@@ -838,48 +841,50 @@ svg_send_image(fz_context *ctx, svg_device *sdev, fz_image *img)
id = sdev->id++;
out = start_def(ctx, sdev);
- fz_printf(ctx, out, "<symbol id=\"im%d\">\n", id);
-#endif
- fz_printf(ctx, out, "<image");
- buffer = fz_compressed_image_buffer(ctx, img);
- fz_printf(ctx, out, " width=\"%dpx\" height=\"%dpx\" xlink:href=\"data:", img->w, img->h);
- switch (buffer == NULL ? FZ_IMAGE_JPX : buffer->params.type)
+ fz_printf(ctx, out, "<symbol id=\"im%d\" viewBox=\"0 0 %d %d\">\n", id, img->w, img->h);
+ }
+
+ fz_printf(ctx, out, "<image");
+ buffer = fz_compressed_image_buffer(ctx, img);
+ fz_printf(ctx, out, " width=\"%d\" height=\"%d\" xlink:href=\"data:", img->w, img->h);
+ switch (buffer == NULL ? FZ_IMAGE_JPX : buffer->params.type)
+ {
+ case FZ_IMAGE_PNG:
+ fz_printf(ctx, out, "image/png;base64,");
+ send_data_base64(ctx, out, buffer->buffer);
+ break;
+ case FZ_IMAGE_JPEG:
+ /* SVG cannot cope with CMYK images */
+ if (img->colorspace != fz_device_cmyk(ctx))
{
- case FZ_IMAGE_PNG:
- fz_printf(ctx, out, "image/png;base64,");
+ fz_printf(ctx, out, "image/jpeg;base64,");
send_data_base64(ctx, out, buffer->buffer);
break;
- case FZ_IMAGE_JPEG:
- /* SVG cannot cope with CMYK images */
- if (img->colorspace != fz_device_cmyk(ctx))
- {
- fz_printf(ctx, out, "image/jpeg;base64,");
- send_data_base64(ctx, out, buffer->buffer);
- break;
- }
- /*@fallthough@*/
- default:
- {
- fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, img);
- fz_printf(ctx, out, "image/png;base64,");
- send_data_base64(ctx, out, buf);
- fz_drop_buffer(ctx, buf);
- break;
- }
}
- fz_printf(ctx, out, "\"/>\n");
-#ifndef SVG_SEND_REPEATED_IMAGES
+ /*@fallthough@*/
+ default:
+ {
+ fz_buffer *buf = fz_new_buffer_from_image_as_png(ctx, img);
+ fz_printf(ctx, out, "image/png;base64,");
+ send_data_base64(ctx, out, buf);
+ fz_drop_buffer(ctx, buf);
+ break;
+ }
+ }
+ fz_printf(ctx, out, "\"/>\n");
+ if (sdev->reuse_images)
+ {
fz_printf(ctx, out, "</symbol>\n");
out = end_def(ctx, sdev);
sdev->images[sdev->num_images].id = id;
sdev->images[sdev->num_images].image = fz_keep_image(ctx, img);
sdev->num_images++;
- }
- fz_printf(ctx, out, "<use x=\"0\" y=\"0\" xlink:href=\"#im%d\"/>\n", id);
-#endif
+ fz_printf(ctx, out, "<use xlink:href=\"#im%d\" x=\"0\" y=\"0\" width=\"%d\" height=\"%d\"/>\n",
+ id, img->w, img->h);
+ }
}
static void
@@ -931,7 +936,7 @@ svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
buf = fz_new_buffer_from_pixmap_as_png(ctx, pix);
if (alpha != 1.0f)
fz_printf(ctx, out, "<g opacity=\"%g\">\n", alpha);
- fz_printf(ctx, out, "<image x=\"%dpx\" y=\"%dpx\" width=\"%dpx\" height=\"%dpx\" xlink:href=\"data:image/png;base64,", pix->x, pix->y, pix->w, pix->h);
+ fz_printf(ctx, out, "<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" xlink:href=\"data:image/png;base64,", pix->x, pix->y, pix->w, pix->h);
send_data_base64(ctx, out, buf);
fz_printf(ctx, out, "\"/>\n");
if (alpha != 1.0f)
@@ -1198,7 +1203,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, int text_format)
+fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height, int text_format, int reuse_images)
{
svg_device *dev = fz_new_device(ctx, sizeof *dev);
@@ -1237,13 +1242,14 @@ fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width,
dev->out_store = out;
dev->id = 0;
dev->text_as_text = (text_format == FZ_SVG_TEXT_AS_TEXT);
+ dev->reuse_images = reuse_images;
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");
fz_printf(ctx, out, "<svg xmlns=\"http://www.w3.org/2000/svg\" "
"xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" "
- "width=\"%gcm\" height=\"%gcm\" viewBox=\"0 0 %g %g\">\n",
- page_width*2.54/72, page_height*2.54/72, page_width, page_height);
+ "width=\"%gpt\" height=\"%gpt\" viewBox=\"0 0 %g %g\">\n",
+ page_width, page_height, page_width, page_height);
return (fz_device*)dev;
}