From 60aa2d2f7109bc8e975f949d88729f1f3e4e7ac3 Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 22 Jan 2018 18:43:01 +0000 Subject: 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. --- include/mupdf/fitz/device.h | 5 ++++ source/fitz/device.c | 12 ++++++++++ source/fitz/list-device.c | 56 ++++++++++++++++++++++++++++++++++++++++++--- source/fitz/svg-device.c | 36 +++++++++++++++++++++++++++++ source/fitz/trace-device.c | 17 ++++++++++++++ source/pdf/pdf-op-run.c | 20 ++++++++++++++++ 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 }; @@ -1261,6 +1263,44 @@ fz_list_set_default_colorspaces(fz_context *ctx, fz_device *dev, fz_default_colo sizeof(default_cs2)); /* private_data_len */ } +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) { @@ -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 @@ -1162,11 +1164,41 @@ svg_dev_end_tile(fz_context *ctx, fz_device *dev) t->pattern, t->area.x0, t->area.y0, t->area.x1 - t->area.x0, t->area.y1 - t->area.y0); } +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, "\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, "\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, "\n"); + sdev->layers--; + } + fz_write_printf(ctx, out, "\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, "\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, "\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, "\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 */ -- cgit v1.2.3