summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2018-01-22 18:43:01 +0000
committerTor Andersson <tor.andersson@artifex.com>2018-02-13 14:45:02 +0100
commit60aa2d2f7109bc8e975f949d88729f1f3e4e7ac3 (patch)
tree67ab8847fcf4d2a7ba8928227b3a561c46a5a7d8
parent4e928c68b1852b860122bac28cc0f3af96c3156e (diff)
downloadmupdf-60aa2d2f7109bc8e975f949d88729f1f3e4e7ac3.tar.xz
Add fz_begin_layer/fz_end_layer.
Call these from the PDF interpreter. Make the DisplayList and Trace devices cope. Use these in the SVG output device.
-rw-r--r--include/mupdf/fitz/device.h5
-rw-r--r--source/fitz/device.c12
-rw-r--r--source/fitz/list-device.c56
-rw-r--r--source/fitz/svg-device.c36
-rw-r--r--source/fitz/trace-device.c17
-rw-r--r--source/pdf/pdf-op-run.c20
6 files changed, 143 insertions, 3 deletions
diff --git a/include/mupdf/fitz/device.h b/include/mupdf/fitz/device.h
index 549ae9be..132668c1 100644
--- a/include/mupdf/fitz/device.h
+++ b/include/mupdf/fitz/device.h
@@ -115,6 +115,9 @@ struct fz_device_s
void (*render_flags)(fz_context *, fz_device *, int set, int clear);
void (*set_default_colorspaces)(fz_context *, fz_device *, fz_default_colorspaces *);
+ void (*begin_layer)(fz_context *, fz_device *, const char *layer_name);
+ void (*end_layer)(fz_context *, fz_device *);
+
fz_rect d1_rect;
int error_depth;
@@ -148,6 +151,8 @@ int fz_begin_tile_id(fz_context *ctx, fz_device *dev, const fz_rect *area, const
void fz_end_tile(fz_context *ctx, fz_device *dev);
void fz_render_flags(fz_context *ctx, fz_device *dev, int set, int clear);
void fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspaces *default_cs);
+void fz_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name);
+void fz_end_layer(fz_context *ctx, fz_device *dev);
fz_device *fz_new_device_of_size(fz_context *ctx, int size);
#define fz_new_derived_device(CTX, TYPE) \
diff --git a/source/fitz/device.c b/source/fitz/device.c
index 8a4e3394..42377030 100644
--- a/source/fitz/device.c
+++ b/source/fitz/device.c
@@ -528,6 +528,18 @@ fz_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colorspac
dev->set_default_colorspaces(ctx, dev, default_cs);
}
+void fz_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
+{
+ if (dev->begin_layer)
+ dev->begin_layer(ctx, dev, layer_name);
+}
+
+void fz_end_layer(fz_context *ctx, fz_device *dev)
+{
+ if (dev->end_layer)
+ dev->end_layer(ctx, dev);
+}
+
const fz_rect *
fz_device_current_scissor(fz_context *ctx, fz_device *dev)
{
diff --git a/source/fitz/list-device.c b/source/fitz/list-device.c
index 7a1f67ee..39314b54 100644
--- a/source/fitz/list-device.c
+++ b/source/fitz/list-device.c
@@ -31,7 +31,9 @@ typedef enum fz_display_command_e
FZ_CMD_BEGIN_TILE,
FZ_CMD_END_TILE,
FZ_CMD_RENDER_FLAGS,
- FZ_CMD_DEFAULT_COLORSPACES
+ FZ_CMD_DEFAULT_COLORSPACES,
+ FZ_CMD_BEGIN_LAYER,
+ FZ_CMD_END_LAYER
} fz_display_command;
/* The display list is a list of nodes.
@@ -165,7 +167,7 @@ fz_append_display_node(
const float *alpha,
const fz_matrix *ctm,
const fz_stroke_state *stroke,
- void *private_data,
+ const void *private_data,
int private_data_len)
{
fz_display_node node = { 0 };
@@ -1262,6 +1264,44 @@ fz_list_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colo
}
static void
+fz_list_begin_layer(fz_context *ctx, fz_device *dev, const char *layer_name)
+{
+ fz_append_display_node(
+ ctx,
+ dev,
+ FZ_CMD_BEGIN_LAYER,
+ 0, /* flags */
+ NULL,
+ NULL, /* path */
+ NULL, /* color */
+ NULL, /* colorspace */
+ NULL, /* alpha */
+ NULL,
+ NULL, /* stroke */
+ layer_name, /* private_data */
+ 1+strlen(layer_name)); /* private_data_len */
+}
+
+static void
+fz_list_end_layer(fz_context *ctx, fz_device *dev)
+{
+ fz_append_display_node(
+ ctx,
+ dev,
+ FZ_CMD_END_LAYER,
+ 0, /* flags */
+ NULL,
+ NULL, /* path */
+ NULL, /* color */
+ NULL, /* colorspace */
+ NULL, /* alpha */
+ NULL, /* ctm */
+ NULL, /* stroke */
+ NULL, /* private_data */
+ 0); /* private_data_len */
+}
+
+static void
fz_list_drop_device(fz_context *ctx, fz_device *dev)
{
fz_list_device *writer = (fz_list_device *)dev;
@@ -1307,6 +1347,9 @@ fz_new_list_device(fz_context *ctx, fz_display_list *list)
dev->super.render_flags = fz_list_render_flags;
dev->super.set_default_colorspaces = fz_list_set_default_colorspaces;
+ dev->super.begin_layer = fz_list_begin_layer;
+ dev->super.end_layer = fz_list_end_layer;
+
dev->super.drop_device = fz_list_drop_device;
dev->list = list;
@@ -1645,7 +1688,8 @@ fz_run_display_list(fz_context *ctx, fz_display_list *list, fz_device *dev, cons
if (tiled ||
n.cmd == FZ_CMD_BEGIN_TILE || n.cmd == FZ_CMD_END_TILE ||
- n.cmd == FZ_CMD_RENDER_FLAGS || n.cmd == FZ_CMD_DEFAULT_COLORSPACES)
+ n.cmd == FZ_CMD_RENDER_FLAGS || n.cmd == FZ_CMD_DEFAULT_COLORSPACES ||
+ n.cmd == FZ_CMD_BEGIN_LAYER || n.cmd == FZ_CMD_END_LAYER)
{
empty = 0;
}
@@ -1778,6 +1822,12 @@ visible:
case FZ_CMD_DEFAULT_COLORSPACES:
fz_set_default_colorspaces(ctx, dev, *(fz_default_colorspaces **)node);
break;
+ case FZ_CMD_BEGIN_LAYER:
+ fz_begin_layer(ctx, dev, (const char *)node);
+ break;
+ case FZ_CMD_END_LAYER:
+ fz_end_layer(ctx, dev);
+ break;
}
}
fz_catch(ctx)
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 7c8dfd50..c5905938 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -66,6 +66,8 @@ struct svg_device_s
int num_images;
int max_images;
image *images;
+
+ int layers;
};
/* SVG is awkward about letting us define things within symbol definitions
@@ -1163,10 +1165,40 @@ svg_dev_end_tile(fz_context *ctx, fz_device *dev)
}
static void
+svg_dev_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
+{
+ svg_device *sdev = (svg_device*)dev;
+ fz_output *out = sdev->out;
+
+ sdev->layers++;
+ fz_write_printf(ctx, out, "<g id=\"Layer-%d\" data-name=\"%s\">\n", sdev->layers, name);
+}
+
+static void
+svg_dev_end_layer(fz_context *ctx, fz_device *dev)
+{
+ svg_device *sdev = (svg_device*)dev;
+ fz_output *out = sdev->out;
+
+ if (sdev->layers == 0)
+ return;
+
+ sdev->layers--;
+ fz_write_printf(ctx, out, "</g>\n");
+}
+
+static void
svg_dev_close_device(fz_context *ctx, fz_device *dev)
{
svg_device *sdev = (svg_device*)dev;
fz_output *out = sdev->out;
+
+ while (sdev->layers > 0)
+ {
+ fz_write_printf(ctx, out, "</g>\n");
+ sdev->layers--;
+ }
+
fz_write_printf(ctx, out, "</svg>\n");
}
@@ -1225,11 +1257,15 @@ fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width,
dev->super.begin_tile = svg_dev_begin_tile;
dev->super.end_tile = svg_dev_end_tile;
+ dev->super.begin_layer = svg_dev_begin_layer;
+ dev->super.end_layer = svg_dev_end_layer;
+
dev->super.hints |= FZ_MAINTAIN_CONTAINER_STACK;
dev->out = out;
dev->out_store = out;
dev->id = 0;
+ dev->layers = 0;
dev->text_as_text = (text_format == FZ_SVG_TEXT_AS_TEXT);
dev->reuse_images = reuse_images;
diff --git a/source/fitz/trace-device.c b/source/fitz/trace-device.c
index 65c91924..59d625c7 100644
--- a/source/fitz/trace-device.c
+++ b/source/fitz/trace-device.c
@@ -348,6 +348,20 @@ fz_trace_end_tile(fz_context *ctx, fz_device *dev)
fz_write_printf(ctx, out, "</tile>\n");
}
+static void
+fz_trace_begin_layer(fz_context *ctx, fz_device *dev, const char *name)
+{
+ fz_output *out = ((fz_trace_device*)dev)->out;
+ fz_write_printf(ctx, out, "<layer name=\"%s\">\n", name);
+}
+
+static void
+fz_trace_end_layer(fz_context *ctx, fz_device *dev)
+{
+ fz_output *out = ((fz_trace_device*)dev)->out;
+ fz_write_printf(ctx, out, "</layer>\n");
+}
+
fz_device *fz_new_trace_device(fz_context *ctx, fz_output *out)
{
fz_trace_device *dev = fz_new_derived_device(ctx, fz_trace_device);
@@ -378,6 +392,9 @@ fz_device *fz_new_trace_device(fz_context *ctx, fz_output *out)
dev->super.begin_tile = fz_trace_begin_tile;
dev->super.end_tile = fz_trace_end_tile;
+ dev->super.begin_layer = fz_trace_begin_layer;
+ dev->super.end_layer = fz_trace_end_layer;
+
dev->out = out;
return (fz_device*)dev;
diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c
index c51bb535..355e94d2 100644
--- a/source/pdf/pdf-op-run.c
+++ b/source/pdf/pdf-op-run.c
@@ -1987,14 +1987,34 @@ static void pdf_run_DP(fz_context *ctx, pdf_processor *proc, const char *tag, pd
static void pdf_run_BMC(fz_context *ctx, pdf_processor *proc, const char *tag)
{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+
+ if (!tag)
+ tag = "UnnamedLayer";
+
+ fz_begin_layer(ctx, pr->dev, tag);
}
static void pdf_run_BDC(fz_context *ctx, pdf_processor *proc, const char *tag, pdf_obj *raw, pdf_obj *cooked)
{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+ const char *str;
+
+ if (!tag || strcmp(tag, "OC"))
+ return;
+
+ str = pdf_to_str_buf(ctx, pdf_dict_get(ctx, cooked, PDF_NAME_Name));
+ if (str == NULL)
+ str = "UnnamedLayer";
+
+ fz_begin_layer(ctx, pr->dev, str);
}
static void pdf_run_EMC(fz_context *ctx, pdf_processor *proc)
{
+ pdf_run_processor *pr = (pdf_run_processor *)proc;
+
+ fz_end_layer(ctx, pr->dev);
}
/* compatibility */