summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Resource/Init/pdf_ops.ps83
-rw-r--r--base/gdbflags.h2
-rw-r--r--base/gdevdflt.c4
-rw-r--r--base/gdevepo.c17
-rw-r--r--base/gdevflp.c20
-rw-r--r--base/gdevmem.h3
-rw-r--r--base/gdevmplt.c3
-rw-r--r--base/gdevnfwd.c20
-rw-r--r--base/gdevoflt.c3
-rw-r--r--base/gdevp14.c767
-rw-r--r--base/gdevp14.h15
-rw-r--r--base/gdevsclass.c11
-rw-r--r--base/gdevsclass.h1
-rw-r--r--base/gscdevn.c14
-rw-r--r--base/gscolor.c16
-rw-r--r--base/gscolor2.c16
-rw-r--r--base/gscolor3.c14
-rw-r--r--base/gscpixel.c3
-rw-r--r--base/gscsepr.c15
-rw-r--r--base/gscspace.c79
-rw-r--r--base/gscspace.h3
-rw-r--r--base/gsdcolor.h2
-rw-r--r--base/gsdevice.c2
-rw-r--r--base/gsdparam.c6
-rw-r--r--base/gsdps1.c2
-rw-r--r--base/gsicc.c11
-rw-r--r--base/gsicc_manage.c2
-rw-r--r--base/gsimage.c18
-rw-r--r--base/gsovrc.c471
-rw-r--r--base/gsovrc.h37
-rw-r--r--base/gspaint.c285
-rw-r--r--base/gspaint.h4
-rw-r--r--base/gspath.c49
-rw-r--r--base/gspcolor.c2
-rw-r--r--base/gsptype1.c13
-rw-r--r--base/gsptype2.c3
-rw-r--r--base/gsstate.c91
-rw-r--r--base/gstext.c41
-rw-r--r--base/gstrans.h10
-rw-r--r--base/gxblend.c378
-rw-r--r--base/gxblend1.c24
-rw-r--r--base/gxccache.c2
-rw-r--r--base/gxclimag.c4
-rw-r--r--base/gxclip.c81
-rw-r--r--base/gxclip.h10
-rw-r--r--base/gxclipm.c3
-rw-r--r--base/gxclist.c5
-rw-r--r--base/gxclist.h6
-rw-r--r--base/gxclpath.c230
-rw-r--r--base/gxclpath.h47
-rw-r--r--base/gxclrast.c130
-rw-r--r--base/gxclrect.c12
-rw-r--r--base/gxcmap.c3
-rw-r--r--base/gxdevcli.h14
-rw-r--r--base/gxdevice.h2
-rw-r--r--base/gxdevsop.h7
-rw-r--r--base/gxfill.c24
-rw-r--r--base/gxgstate.h10
-rw-r--r--base/gxpaint.c24
-rw-r--r--base/gxpaint.h2
-rw-r--r--base/gxpath.h1
-rw-r--r--base/gxpath2.c3
-rw-r--r--base/gxpcmap.c42
-rw-r--r--base/gxpcolor.h15
-rw-r--r--base/gxstroke.c7
-rw-r--r--base/lib.mak9
-rw-r--r--devices/gdevpsd.c5
-rw-r--r--devices/vector/gdevpdfb.h11
-rw-r--r--devices/vector/gdevpdfd.c199
-rw-r--r--devices/vector/gdevpdfg.c169
-rw-r--r--devices/vector/gdevpdfg.h1
-rw-r--r--devices/vector/gdevpdfx.h6
-rw-r--r--lcms2mt/ChangeLog2
-rw-r--r--lcms2mt/Projects/VC2010/lcms2mt.rc15
-rwxr-xr-xlcms2mt/config.guess1
-rw-r--r--psi/int.mak2
-rw-r--r--psi/zcolor.c7
-rw-r--r--psi/zpaint.c60
78 files changed, 2836 insertions, 895 deletions
diff --git a/Resource/Init/pdf_ops.ps b/Resource/Init/pdf_ops.ps
index 4379ce23c..14065a817 100644
--- a/Resource/Init/pdf_ops.ps
+++ b/Resource/Init/pdf_ops.ps
@@ -785,7 +785,7 @@ currentdict dup /Dpush .undef /Dpop .undef
/fsexec % <fillop|strokeop> fsexec -
{
PDFusingtransparency {
- dup /stroke eq {
+ dup /stroke eq 1 index /.fillstroke eq or 1 index /.eofillstroke eq or {
% BBox needs to include line width / line join expansion.
% strokepath will return empty path (no currentpoint) if nothing is stroked
{ gsave strokepath pathbbox } stopped grestore {
@@ -932,23 +932,7 @@ currentdict dup /Dpush .undef /Dpop .undef
/B {
OFFlevels length 0 eq {
- PDFusingtransparency {
- % knockout trans group around the filled and stroked object
- mark
- /Isolated //true /Knockout //true
- .dicttomark
- % strokepath will return empty path (no currentpoint) if nothing is stroked
- gsave { strokepath pathbbox } stopped grestore not {
- 1 .setopacityalpha
- .begintransparencygroup
- gsave setfillstate fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- .endtransparencygroup
- } { newpath pop } ifelse
- } {
- gsave setfillstate fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- } ifelse
+ setstrokestate setfillstate /.fillstroke fsexec
} {
newpath
} ifelse
@@ -958,23 +942,7 @@ currentdict dup /Dpush .undef /Dpop .undef
/B* {
OFFlevels length 0 eq {
- PDFusingtransparency {
- % knockout trans group around the filled and stroked object
- mark
- /Isolated //true /Knockout //true
- .dicttomark
- % strokepath will return empty path (no currentpoint) if nothing is stroked
- gsave { strokepath pathbbox } stopped grestore not {
- 1 .setopacityalpha
- .begintransparencygroup
- gsave setfillstate eofill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- .endtransparencygroup
- } { newpath pop } ifelse
- } {
- gsave setfillstate eofill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- } ifelse
+ setstrokestate setfillstate /.eofillstroke fsexec
} {
newpath
} ifelse
@@ -990,49 +958,14 @@ currentdict dup /Dpush .undef /Dpop .undef
/f* { OFFlevels length 0 eq { gsave setfillstate eofill grestore } if n } bind executeonly def
/B {
OFFlevels length 0 eq {
- PDFusingtransparency {
- % knockout trans group around the filled and stroked object
- mark
- /Isolated //true /Knockout //true
- .dicttomark
- % strokepath will return empty path (no currentpoint) if nothing is stroked
- gsave {strokepath pathbbox } stopped grestore not
- {
- 1 .setopacityalpha
- .begintransparencygroup
- gsave setfillstate fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- .endtransparencygroup
- } {
- newpath pop
- } ifelse
- } {
- gsave setfillstate fill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- } ifelse
+ .fillstroke
} if
n
} bind executeonly def
/b { closepath B } bind executeonly def
/B* {
OFFlevels length 0 eq {
- PDFusingtransparency {
- % knockout trans group around the filled and stroked object
- mark
- /Isolated //true /Knockout //true
- .dicttomark
- % strokepath will return empty path (no currentpoint) if nothing is stroked
- gsave {strokepath pathbbox} stopped grestore not {
- 1 .setopacityalpha
- .begintransparencygroup
- gsave setfillstate eofill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- .endtransparencygroup
- } { newpath pop } ifelse
- } {
- gsave setfillstate eofill grestore
- setstrokestate .swapcolors /stroke fsexec .swapcolors
- } ifelse
+ .eofillstroke
} if
n
} bind executeonly def
@@ -1650,15 +1583,17 @@ end readonly def
% If current path is not known to be valid, use the clip path
/TextTransSetup { % showarg path_valid TextTransSetup showarg
% showarg path_valid false TextTransSetup showarg
+ gsave
% NB: if 'show' is used, then we use the clippath, but a smaller bbox is preferred
{
% path was (probably) valid (CTM may not be invertable)
% Since TR mode may include stroking, expand for stroke
% If we get an error, just emit an empty box
- { gsave strokepath pathbbox } stopped grestore { 0 0 0 0 } if
+ { strokepath pathbbox } stopped { 0 0 0 0 } if
} {
- gsave clippath pathbbox grestore % path not valid -- use clippath
+ clippath pathbbox stopped { 0 0 0 0 } if
} ifelse
+ grestore
4 array astore //null
setup_trans
} bind executeonly def
diff --git a/base/gdbflags.h b/base/gdbflags.h
index 9d6376f63..1ac6c5867 100644
--- a/base/gdbflags.h
+++ b/base/gdbflags.h
@@ -31,7 +31,7 @@ FLAG(epo_disable, 4, 0, "Disable Erasepage Optimization (completely)"),
FLAG(epo_details, 5, 0, "Erasepage Optimization tracing"),
FLAG(epo_install_only, 6, 0, "Erasepage Optimization install only (for debugging subclass)"),
FLAG(init_details, 7, 0, "Language initialisation (detail)"),
-UNUSED(8)
+FLAG(overprint, 8, 0, "Overprint"),
UNUSED(9)
UNUSED(10)
UNUSED(11)
diff --git a/base/gdevdflt.c b/base/gdevdflt.c
index 92edd4c59..8d342995e 100644
--- a/base/gdevdflt.c
+++ b/base/gdevdflt.c
@@ -767,6 +767,7 @@ gx_device_fill_in_procs(register gx_device * dev)
fill_dev_proc(dev, copy_planes, gx_default_copy_planes);
fill_dev_proc(dev, process_page, gx_default_process_page);
fill_dev_proc(dev, transform_pixel_region, gx_default_transform_pixel_region);
+ fill_dev_proc(dev, fill_stroke_path, gx_default_fill_stroke_path);
}
@@ -1062,6 +1063,8 @@ gx_default_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
/* Just ignore information about events */
case gxdso_event_info:
return 0;
+ case gxdso_overprint_active:
+ return 0;
}
return_error(gs_error_undefined);
}
@@ -1315,6 +1318,7 @@ int gx_copy_device_procs(gx_device *dest, gx_device *src, gx_device *prototype)
set_dev_proc(dest, strip_tile_rect_devn, dev_proc(prototype, strip_tile_rect_devn));
set_dev_proc(dest, process_page, dev_proc(prototype, process_page));
set_dev_proc(dest, transform_pixel_region, dev_proc(prototype, transform_pixel_region));
+ set_dev_proc(dest, fill_stroke_path, dev_proc(prototype, fill_stroke_path));
/*
* We absolutely must set the 'set_graphics_type_tag' to the default subclass one
diff --git a/base/gdevepo.c b/base/gdevepo.c
index e57c1db9b..45363781a 100644
--- a/base/gdevepo.c
+++ b/base/gdevepo.c
@@ -81,6 +81,7 @@ static dev_proc_copy_planes(epo_copy_planes);
static dev_proc_copy_alpha_hl_color(epo_copy_alpha_hl_color);
static dev_proc_process_page(epo_process_page);
static dev_proc_transform_pixel_region(epo_transform_pixel_region);
+static dev_proc_fill_stroke_path(epo_fill_stroke_path);
/* The device prototype */
#define MAX_COORD (max_int_in_fixed - 1000)
@@ -184,7 +185,8 @@ gx_device_epo gs_epo_device =
default_subclass_strip_tile_rect_devn,
epo_copy_alpha_hl_color,
epo_process_page,
- epo_transform_pixel_region
+ epo_transform_pixel_region,
+ epo_fill_stroke_path,
}
};
@@ -679,6 +681,19 @@ int epo_process_page(gx_device *dev, gx_process_page_options_t *options)
return dev_proc(dev, process_page)(dev, options);
}
+int epo_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
+ const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
+ const gx_clip_path *pcpath)
+{
+ int code = epo_handle_erase_page(dev);
+
+ if (code != 0)
+ return code;
+ return dev_proc(dev, fill_stroke_path)(dev, pgs, ppath, fill_params, pdcolor_fill,
+ stroke_params, pdcolor_stroke, pcpath);
+}
+
int epo_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
{
int code = epo_handle_erase_page(dev);
diff --git a/base/gdevflp.c b/base/gdevflp.c
index f4b9a847c..0ad196561 100644
--- a/base/gdevflp.c
+++ b/base/gdevflp.c
@@ -106,6 +106,7 @@ static dev_proc_strip_tile_rect_devn(flp_strip_tile_rect_devn);
static dev_proc_copy_alpha_hl_color(flp_copy_alpha_hl_color);
static dev_proc_process_page(flp_process_page);
static dev_proc_transform_pixel_region(flp_transform_pixel_region);
+static dev_proc_fill_stroke_path(flp_fill_stroke_path);
/* The device prototype */
#define MAX_COORD (max_int_in_fixed - 1000)
@@ -208,7 +209,9 @@ gx_device_flp gs_flp_device =
flp_strip_copy_rop2,
flp_strip_tile_rect_devn,
flp_copy_alpha_hl_color,
- flp_process_page
+ flp_process_page,
+ flp_transform_pixel_region,
+ flp_fill_stroke_path,
}
};
@@ -1213,6 +1216,21 @@ int flp_process_page(gx_device *dev, gx_process_page_options_t *options)
return 0;
}
+int flp_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
+ const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
+ const gx_clip_path *pcpath)
+{
+ int code = SkipPage(dev);
+
+ if (code < 0)
+ return code;
+ if (!code)
+ return default_subclass_fill_stroke_path(dev, pgs, ppath, fill_params, pdcolor_fill,
+ stroke_params, pdcolor_stroke, pcpath);
+ return 0;
+}
+
int flp_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
{
int code = SkipPage(dev);
diff --git a/base/gdevmem.h b/base/gdevmem.h
index c973ab40b..69cb6d0f3 100644
--- a/base/gdevmem.h
+++ b/base/gdevmem.h
@@ -203,7 +203,8 @@ dev_proc_transform_pixel_region(mem_transform_pixel_region);
NULL, /* strip_tile_rect_devn */\
NULL, /* copy_alpha_hl_color */\
NULL, /* process_page */\
- mem_transform_pixel_region\
+ mem_transform_pixel_region,\
+ NULL, /* fill_stroke_path */\
},\
0, /* target */\
mem_device_init_private /* see gxdevmem.h */\
diff --git a/base/gdevmplt.c b/base/gdevmplt.c
index d10f194a2..c102639fa 100644
--- a/base/gdevmplt.c
+++ b/base/gdevmplt.c
@@ -152,7 +152,8 @@ gx_device_mplt gs_pcl_mono_palette_device =
default_subclass_strip_tile_rect_devn,
default_subclass_copy_alpha_hl_color,
default_subclass_process_page,
- default_subclass_transform_pixel_region
+ default_subclass_transform_pixel_region,
+ default_subclass_fill_stroke_path,
}
};
diff --git a/base/gdevnfwd.c b/base/gdevnfwd.c
index a78d3038d..4174c957a 100644
--- a/base/gdevnfwd.c
+++ b/base/gdevnfwd.c
@@ -117,7 +117,9 @@ gx_device_forward_fill_in_procs(register gx_device_forward * dev)
fill_dev_proc(dev, set_graphics_type_tag, gx_forward_set_graphics_type_tag);
fill_dev_proc(dev, strip_copy_rop2, gx_forward_strip_copy_rop2);
fill_dev_proc(dev, strip_tile_rect_devn, gx_forward_strip_tile_rect_devn);
+ fill_dev_proc(dev, strip_tile_rect_devn, gx_forward_strip_tile_rect_devn);
fill_dev_proc(dev, transform_pixel_region, gx_forward_transform_pixel_region);
+ fill_dev_proc(dev, fill_stroke_path, gx_forward_fill_stroke_path);
gx_device_fill_in_procs((gx_device *) dev);
}
@@ -450,6 +452,24 @@ gx_forward_stroke_path(gx_device * dev, const gs_gstate * pgs,
}
int
+gx_forward_fill_stroke_path(gx_device * dev, const gs_gstate * pgs,
+ gx_path * ppath,
+ const gx_fill_params * params_fill,
+ const gx_drawing_color * pdcolor_fill,
+ const gx_stroke_params * params_stroke,
+ const gx_drawing_color * pdcolor_stroke,
+ const gx_clip_path * pcpath)
+{
+ gx_device_forward * const fdev = (gx_device_forward *)dev;
+ gx_device *tdev = fdev->target;
+ dev_proc_fill_stroke_path((*proc)) =
+ (tdev == 0 ? (tdev = dev, gx_default_fill_stroke_path) :
+ dev_proc(tdev, fill_stroke_path));
+
+ return proc(tdev, pgs, ppath, params_fill, pdcolor_fill, params_stroke, pdcolor_stroke, pcpath);
+}
+
+int
gx_forward_fill_mask(gx_device * dev,
const byte * data, int dx, int raster, gx_bitmap_id id,
int x, int y, int w, int h,
diff --git a/base/gdevoflt.c b/base/gdevoflt.c
index f08180642..6e441180c 100644
--- a/base/gdevoflt.c
+++ b/base/gdevoflt.c
@@ -174,7 +174,8 @@ gx_device_obj_filter gs_obj_filter_device =
obj_filter_strip_tile_rect_devn,
default_subclass_copy_alpha_hl_color,
default_subclass_process_page,
- default_subclass_transform_pixel_region
+ default_subclass_transform_pixel_region,
+ default_subclass_fill_stroke_path,
}
};
diff --git a/base/gdevp14.c b/base/gdevp14.c
index 1c534c358..c8adaeb9f 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -15,6 +15,7 @@
/* Compositing devices for implementing PDF 1.4 imaging model */
+#include "assert_.h"
#include "math_.h"
#include "memory_.h"
#include "gx.h"
@@ -182,6 +183,7 @@ dev_proc_decode_color(pdf14_decode_color16);
static dev_proc_fill_rectangle(pdf14_fill_rectangle);
static dev_proc_fill_rectangle_hl_color(pdf14_fill_rectangle_hl_color);
static dev_proc_fill_path(pdf14_fill_path);
+static dev_proc_fill_stroke_path(pdf14_fill_stroke_path);
static dev_proc_copy_mono(pdf14_copy_mono);
static dev_proc_fill_mask(pdf14_fill_mask);
static dev_proc_stroke_path(pdf14_stroke_path);
@@ -283,7 +285,10 @@ static const gx_color_map_procs *
gx_forward_set_graphics_type_tag, /* set_graphics_type_tag */\
NULL, /* strip_copy_rop2 */\
NULL, /* strip_tile_rect_devn */\
- pdf14_copy_alpha_hl_color /* copy_alpha_hl_color */\
+ pdf14_copy_alpha_hl_color, /* copy_alpha_hl_color */\
+ NULL, /* process_page */\
+ NULL, /* transform_pixel_region */\
+ pdf14_fill_stroke_path, /* fill_stroke */\
}
static const gx_device_procs pdf14_Gray_procs =
@@ -1295,26 +1300,42 @@ pdf14_ctx_free(pdf14_ctx *ctx)
* if backdrop is fully transparent.
**/
static pdf14_buf *
-pdf14_find_backdrop_buf(pdf14_ctx *ctx)
+pdf14_find_backdrop_buf(pdf14_ctx *ctx, bool *is_backdrop)
{
+ /* Our new buffer is buf */
pdf14_buf *buf = ctx->stack;
- while (buf != NULL) {
+ *is_backdrop = false;
+
+ if (buf != NULL) {
+ /* If the new buffer is isolated there is no backdrop */
if (buf->isolated) return NULL;
- if (buf->knockout && !buf->isolated) return buf->saved;
- /* If target (NOS) is knockout and isolated then the compositing will happen
- at the end */
- if (buf->saved != NULL && buf->saved->knockout && buf->saved->isolated) return NULL;
- /* Target (NOS) is not isolated. Next group on stack is a knockout.
- We need to compose with the backdrop when we do the pop */
- if (buf->saved != NULL && buf->saved->knockout && !buf->saved->isolated)
- return NULL;
- /* Not a knockout and not isolated. Initialize backdrop */
- if (!buf->knockout) return buf->saved;
- buf = buf->saved;
+
+ /* If the previous buffer is a knockout group
+ then we need to use its backdrop as the backdrop. If
+ it was isolated then that back drop was NULL */
+ if (buf->saved != NULL && buf->saved->knockout) {
+ /* This bit of logic is need to get both
+ fts_25_2524.pdf and the overlapping Altona
+ file working. The difference is between a
+ knockout group in a knockout group vs. a
+ non-knockout group in a knockout group.
+ fts_25_2524.pdf has a knockout in a knockout
+ due to the stroke fill that occurs within
+ the knockout group. */
+ if (!buf->knockout)
+ return NULL;
+ else {
+ *is_backdrop = true;
+ return buf->saved;
+ }
+ }
+ /* This should be the non-isolated case where its parent is
+ not a knockout */
+ if (buf->saved != NULL) {
+ return buf->saved;
+ }
}
- /* this really shouldn't happen, as bottom-most buf should be
- non-knockout */
return NULL;
}
@@ -1328,8 +1349,8 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated,
gx_device *dev)
{
pdf14_buf *tos = ctx->stack;
- pdf14_buf *buf, *backdrop;
- bool has_shape, has_tags;
+ pdf14_buf *buf, * pdf14_backdrop;
+ bool has_shape, has_tags, is_backdrop;
if_debug1m('v', ctx->memory,
"[v]pdf14_push_transparency_group, idle = %d\n", idle);
@@ -1372,97 +1393,56 @@ pdf14_push_transparency_group(pdf14_ctx *ctx, gs_int_rect *rect, bool isolated,
return 0;
if (idle)
return 0;
- backdrop = pdf14_find_backdrop_buf(ctx);
- if (backdrop == NULL) {
+ pdf14_backdrop = pdf14_find_backdrop_buf(ctx, &is_backdrop);
+
+ /* Initializes buf->data with the backdrop or as opaque */
+ if (pdf14_backdrop == NULL || (is_backdrop && pdf14_backdrop->backdrop == NULL)) {
/* Note, don't clear out tags set by pdf14_buf_new == GS_UNKNOWN_TAG */
/* Memsetting by 0, so this copes with the deep case too */
memset(buf->data, 0, buf->planestride * (buf->n_chan +
(buf->has_shape ? 1 : 0) +
(buf->has_alpha_g ? 1 : 0)));
} else {
- if (!buf->knockout) {
- if (!cm_back_drop) {
- pdf14_preserve_backdrop(buf, tos, false
+ if (!cm_back_drop) {
+ pdf14_preserve_backdrop(buf, pdf14_backdrop, is_backdrop
#if RAW_DUMP
- , ctx->memory
+ , ctx->memory
#endif
- );
- } else {
- /* We must have an non-isolated group with a mismatch in color spaces.
- In this case, we can't just copy the buffer but must CM it */
- pdf14_preserve_backdrop_cm(buf, group_profile, tos, tos_profile,
- ctx->memory, pgs, dev, false);
- }
+ );
+ } else {
+ /* We must have an non-isolated group with a mismatch in color spaces.
+ In this case, we can't just copy the buffer but must CM it */
+ pdf14_preserve_backdrop_cm(buf, group_profile, pdf14_backdrop, tos_profile,
+ ctx->memory, pgs, dev, is_backdrop);
}
}
- /* If knockout, we have to maintain a copy of the backdrop in case we are
- drawing nonisolated groups on top of the knockout group. */
- if (buf->knockout) {
+ /* If our new group is a non-isolated knockout group, we have to maintain
+ a copy of the backdrop in case we are drawing nonisolated groups on top of the
+ knockout group. They have to always blend with the groups backdrop
+ not what is currently drawn in the group. Selection of the backdrop
+ depends upon the properties of the parent group. For example, if
+ the parent itself is a knockout group we actually
+ need to blend with its backdrop. This could be NULL if the parent was
+ an isolated knockout group. */
+ if (buf->knockout && pdf14_backdrop != NULL) {
buf->backdrop = gs_alloc_bytes(ctx->memory, buf->planestride * buf->n_chan,
- "pdf14_push_transparency_group");
+ "pdf14_push_transparency_group");
if (buf->backdrop == NULL) {
return gs_throw(gs_error_VMerror, "Knockout backdrop allocation failed");
}
- if (buf->isolated) {
- /* We will have opaque backdrop for non-isolated compositing */
- /* Memsetting by 0, so this copes with the deep case too */
- memset(buf->backdrop, 0, buf->planestride * buf->n_chan);
- } else {
- /* Save knockout backdrop for non-isolated compositing */
- /* Note that we need to drill down through the non-isolated groups in our
- stack and make sure that we are not embedded in another knockout group */
- pdf14_buf *check = tos;
- pdf14_buf *child = NULL; /* Needed so we can get profile */
- cmm_profile_t *prev_knockout_profile;
-
- while (check != NULL) {
- if (check->isolated)
- break;
- if (check->knockout) {
- break;
- }
- child = check;
- check = check->saved;
- }
- /* Here we need to grab a back drop from a knockout parent group and
- potentially worry about color differences. */
- if (check == NULL || check->page_group) {
- prev_knockout_profile = tos_profile;
- check = tos;
- } else {
- if (child == NULL) {
- prev_knockout_profile = tos_profile;
- } else {
- prev_knockout_profile = child->parent_color_info->icc_profile;
- }
- }
- if (!cm_back_drop) {
- pdf14_preserve_backdrop(buf, check, false
-#if RAW_DUMP
- , ctx->memory
-#endif
- );
- } else {
- /* We must have an non-isolated group with a mismatch in color spaces.
- In this case, we can't just copy the buffer but must CM it */
- pdf14_preserve_backdrop_cm(buf, group_profile, check,
- prev_knockout_profile, ctx->memory, pgs,
- dev, false);
- }
- memcpy(buf->backdrop, buf->data, buf->planestride * buf->n_chan);
- }
+
+ memcpy(buf->backdrop, buf->data, buf->planestride * buf->n_chan);
+
#if RAW_DUMP
/* Dump the current buffer to see what we have. */
dump_raw_buffer(ctx->memory,
- ctx->stack->rect.q.y-ctx->stack->rect.p.y,
- ctx->stack->rowstride>>buf->deep, buf->n_chan,
- ctx->stack->planestride, ctx->stack->rowstride,
- "KnockoutBackDrop", buf->backdrop, buf->deep);
+ ctx->stack->rect.q.y - ctx->stack->rect.p.y,
+ ctx->stack->rowstride >> buf->deep, buf->n_chan,
+ ctx->stack->planestride, ctx->stack->rowstride,
+ "KnockoutBackDrop", buf->backdrop, buf->deep);
global_index++;
#endif
- } else {
- buf->backdrop = NULL;
}
#if RAW_DUMP
/* Dump the current buffer to see what we have. */
@@ -1490,7 +1470,7 @@ pdf14_pop_transparency_group(gs_gstate *pgs, pdf14_ctx *ctx,
bool icc_match;
pdf14_device *pdev = (pdf14_device *)dev;
bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ gx_color_index drawn_comps = pdev->drawn_comps_stroke | pdev->drawn_comps_fill;
bool has_matte = false;
if (nos == NULL)
@@ -2943,11 +2923,14 @@ pdf14_set_marking_params(gx_device *dev, const gs_gstate *pgs)
pdev->alpha = pgs->opacity.alpha * pgs->shape.alpha;
pdev->blend_mode = pgs->blend_mode;
pdev->overprint = pgs->overprint;
- pdev->effective_overprint_mode = pgs->effective_overprint_mode;
+ pdev->stroke_overprint = pgs->stroke_overprint;
+ pdev->fillconstantalpha = pgs->fillconstantalpha;
+ pdev->strokeconstantalpha = pgs->strokeconstantalpha;
- if_debug5m('v', dev->memory,
- "[v]set_marking_params, opacity = %g, shape = %g, bm = %d, op = %d, eop = %d\n",
- pdev->opacity, pdev->shape, pgs->blend_mode, pgs->overprint, pgs->effective_overprint_mode);
+ if_debug6m('v', dev->memory,
+ "[v]set_marking_params, opacity = %g, shape = %g, bm = %d, op = %d, eop = %d seop = %d\n",
+ pdev->opacity, pdev->shape, pgs->blend_mode, pgs->overprint, pdev->effective_overprint_mode,
+ pdev->stroke_effective_op_mode);
}
static void
@@ -3243,6 +3226,183 @@ pdf14_stroke_path(gx_device *dev, const gs_gstate *pgs,
}
static int
+pdf14_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
+ const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
+ const gx_clip_path *pcpath)
+{
+ int code, code2;
+ gs_transparency_group_params_t params = { 0 };
+ gs_fixed_rect clip_bbox;
+ gs_rect bbox, group_stroke_box;
+ float opacity = pgs->opacity.alpha;
+ gs_blend_mode_t blend_mode = pgs->blend_mode;
+ gs_fixed_rect path_bbox;
+ int expansion_code;
+ gs_fixed_point expansion;
+
+ if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) ||
+ (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0))
+ return 0;
+
+ code = gx_curr_fixed_bbox((gs_gstate *)pgs, &clip_bbox, NO_PATH);
+ if (code < 0 && code != gs_error_unknownerror)
+ return code;
+ if (code == gs_error_unknownerror) {
+ /* didn't get clip box from gx_curr_fixed_bbox */
+ clip_bbox.p.x = clip_bbox.p.y = 0.0;
+ clip_bbox.q.x = int2fixed(dev->width);
+ clip_bbox.q.y = int2fixed(dev->height);
+ }
+ if (pcpath)
+ rect_intersect(clip_bbox, pcpath->outer_box);
+
+ /* expand the ppath using stroke expansion rule, then intersect it */
+ code = gx_path_bbox(ppath, &path_bbox);
+ if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0)
+ return 0; /* ignore empty path */
+ if (code < 0)
+ return code;
+ expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion);
+ if (expansion_code >= 0) {
+ path_bbox.p.x -= expansion.x;
+ path_bbox.p.y -= expansion.y;
+ path_bbox.q.x += expansion.x;
+ path_bbox.q.y += expansion.y;
+ }
+ rect_intersect(path_bbox, clip_bbox);
+ bbox.p.x = fixed2float(path_bbox.p.x);
+ bbox.p.y = fixed2float(path_bbox.p.y);
+ bbox.q.x = fixed2float(path_bbox.q.x);
+ bbox.q.y = fixed2float(path_bbox.q.y);
+
+ code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box);
+ if (code < 0)
+ return code;
+
+ /* See if overprint is enabled for both stroke and fill AND if ca == CA */
+ if (pgs->fillconstantalpha == pgs->strokeconstantalpha &&
+ (((pdf14_device*)dev)->overprint && ((pdf14_device*)dev)->stroke_overprint)) {
+ /* Push a non-isolated non-knockout group with alpha = 1.0 and
+ compatible overprint mode. Group will be composited with
+ original alpha and blend mode */
+ params.Isolated = false;
+ params.group_color = UNKNOWN;
+ params.Knockout = false;
+
+ /* non-isolated non-knockout group pushed with original alpha and blend mode */
+ code = pdf14_begin_transparency_group(dev, (const gs_transparency_group_params_t*) &params,
+ (const gs_rect*) &group_stroke_box, (gs_gstate*) pgs, dev->memory);
+ if (code < 0)
+ return code;
+
+ /* Change alpha to 1.0 and blend mode to compatible overprint for actual drawing */
+ code = gs_setopacityalpha((gs_gstate *) pgs, 1.0);
+ if (code < 0)
+ goto cleanup;
+ code = gs_setblendmode((gs_gstate *) pgs, BLEND_MODE_CompatibleOverprint);
+ if (code < 0)
+ goto cleanup;
+
+ if (pgs->fillconstantalpha > 0) {
+ ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_FILL;
+ code = pdf14_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
+ if (code < 0)
+ goto cleanup;
+ }
+
+ if (pgs->strokeconstantalpha > 0) {
+ gs_swapcolors_quick((gs_gstate*)pgs); /* flips stroke_color_index (to stroke) */
+ ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_STROKE;
+ code = pdf14_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
+ gs_swapcolors_quick((gs_gstate*)pgs); /* this flips pgs->stroke_color_index back as well */
+ if (code < 0)
+ goto cleanup; /* bail out (with colors swapped back to fill) */
+ }
+
+ } else {
+ /* Push a non-isolated knockout group. Do not change the alpha or
+ blend modes. Note: we need to draw those that have alpha = 0 */
+ params.Isolated = false;
+ params.group_color = UNKNOWN;
+ params.Knockout = true;
+
+ /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */
+ code = gs_setopacityalpha((gs_gstate*) pgs, 1.0);
+ if (code < 0)
+ return code;
+ code = gs_setblendmode((gs_gstate*) pgs, BLEND_MODE_Normal);
+ if (code < 0)
+ return code;
+
+ code = pdf14_begin_transparency_group(dev, (const gs_transparency_group_params_t*) &params,
+ (const gs_rect*) &group_stroke_box, (gs_gstate*) pgs, dev->memory);
+ if (code < 0)
+ return code;
+
+ /* restore blend mode for actual drawing in the group */
+ code = gs_setblendmode((gs_gstate*) pgs, blend_mode);
+ if (code < 0)
+ goto cleanup;
+
+ code = gs_setopacityalpha((gs_gstate*) pgs, pgs->fillconstantalpha);
+ if (code < 0)
+ goto cleanup;
+ ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_FILL;
+
+ /* If we are in an overprint situation, set the blend mode to compatible
+ overprint */
+ if (pgs->overprint)
+ code = gs_setblendmode((gs_gstate*) pgs, BLEND_MODE_CompatibleOverprint);
+ code = pdf14_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
+ if (pgs->overprint)
+ code = gs_setblendmode((gs_gstate*) pgs, blend_mode);
+ if (code < 0)
+ goto cleanup;
+
+ code = gs_setopacityalpha((gs_gstate*) pgs, pgs->strokeconstantalpha);
+ if (code < 0)
+ goto cleanup;
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ ((pdf14_device*)dev)->op_state = PDF14_OP_STATE_STROKE;
+ if (pgs->stroke_overprint)
+ code = gs_setblendmode((gs_gstate*) pgs, BLEND_MODE_CompatibleOverprint);
+ code = pdf14_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
+ if (pgs->stroke_overprint)
+ code = gs_setblendmode((gs_gstate*) pgs, blend_mode);
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ if (code < 0)
+ goto cleanup; /* bail out (with colors swapped back to fill) */
+ }
+
+ /* Now during the pop do the compositing with alpha of 1.0 and normal blend */
+ code = gs_setopacityalpha((gs_gstate*) pgs, 1.0);
+ if (code < 0)
+ goto cleanup;
+ code = gs_setblendmode((gs_gstate*) pgs, BLEND_MODE_Normal);
+
+ /* Restore where we were. If an error occured while in the group push
+ return that error code but try to do the cleanup */
+cleanup:
+ code2 = pdf14_end_transparency_group(dev, (gs_gstate*) pgs);
+ if (code2 < 0) {
+ /* At this point things have gone very wrong. We should just shut down */
+ code = gs_abort_pdf14trans_device((gs_gstate*) pgs);
+ return code2;
+ }
+
+ /* Restore if there were any changes */
+ code2 = gs_setopacityalpha((gs_gstate*) pgs, opacity);
+ if (code2 < 0)
+ return code2;
+ code2 = gs_setblendmode((gs_gstate*) pgs, blend_mode);
+ if (code2 < 0)
+ return code2;
+
+ return code;
+}
+
+static int
pdf14_copy_alpha(gx_device * dev, const byte * data, int data_x,
int aa_raster, gx_bitmap_id id, int x, int y, int w, int h,
gx_color_index color, int depth)
@@ -3290,8 +3450,9 @@ do_pdf14_copy_alpha_color(gx_device * dev, const byte * data, int data_x,
int shape_off = num_chan * planestride;
int alpha_g_off = shape_off + (has_shape ? planestride : 0);
int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
gx_color_index comps;
byte shape = 0; /* Quiet compiler. */
byte src_alpha;
@@ -3478,8 +3639,9 @@ do_pdf14_copy_alpha_color_16(gx_device * dev, const byte * data, int data_x,
int shape_off = num_chan * planestride;
int alpha_g_off = shape_off + (has_shape ? planestride : 0);
int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
gx_color_index comps;
uint16_t shape = 0; /* Quiet compiler. */
uint16_t src_alpha;
@@ -4180,8 +4342,15 @@ pdf14_set_params(gs_gstate * pgs,
pgs->opacity.alpha = pparams->opacity.alpha;
if (pparams->changed & PDF14_SET_OVERPRINT)
pgs->overprint = pparams->overprint;
- if (pparams->changed & PDF14_SET_OVERPRINT_MODE)
- pgs->effective_overprint_mode = pparams->effective_overprint_mode;
+ if (pparams->changed & PDF14_SET_STROKEOVERPRINT)
+ pgs->stroke_overprint = pparams->stroke_overprint;
+ if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA)
+ pgs->fillconstantalpha = pparams->fillconstantalpha;
+ if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA)
+ pgs->strokeconstantalpha = pparams->strokeconstantalpha;
+ if (pparams->changed & PDF_SET_FILLSTROKE_STATE) {
+ gs_swapcolors_quick((gs_gstate*)pgs);
+ }
pdf14_set_marking_params(dev, pgs);
}
@@ -4756,12 +4925,27 @@ pdf14_create_compositor(gx_device * dev, gx_device * * pcdev,
values around a fair amount. Hence the forced assignement here.
See gx_spot_colors_set_overprint in gscspace for issues... */
const gs_overprint_t * op_pct = (const gs_overprint_t *) pct;
- if (op_pct->params.retain_any_comps && !op_pct->params.retain_spot_comps) {
- p14dev->drawn_comps = op_pct->params.drawn_comps;
- } else {
- /* Draw everything. If this parameter was not set, clist does
- not fill it in. */
- p14dev->drawn_comps = ( (gx_color_index) 1 << (p14dev->color_info.num_components)) - (gx_color_index) 1;
+ gx_color_index drawn_comps;
+
+ p14dev->op_state = op_pct->params.op_state;
+
+ if (!p14dev->op_state) {
+ if (op_pct->params.retain_any_comps) {
+ drawn_comps = op_pct->params.drawn_comps;
+ } else {
+ /* Draw everything. If this parameter was not set, clist does
+ not fill it in. */
+ drawn_comps = ((gx_color_index)1 << (p14dev->color_info.num_components)) - (gx_color_index)1;
+ }
+
+ if (op_pct->params.is_fill_color) {
+ p14dev->effective_overprint_mode = op_pct->params.effective_opm;
+ p14dev->drawn_comps_fill = drawn_comps;
+ } else {
+ p14dev->stroke_effective_op_mode = op_pct->params.effective_opm;
+ p14dev->drawn_comps_stroke = drawn_comps;
+ }
+
}
*pcdev = dev;
return 0;
@@ -5990,6 +6174,7 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
byte *bline, *bg_ptr, *line, *dst_ptr;
byte src[PDF14_MAX_PLANES];
byte dst[PDF14_MAX_PLANES] = { 0 };
+ byte dst2[PDF14_MAX_PLANES] = { 0 };
int rowstride = buf->rowstride;
int planestride = buf->planestride;
int num_chan = buf->n_chan;
@@ -6007,9 +6192,11 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
int shift = 8;
byte shape = 0; /* Quiet compiler. */
byte src_alpha;
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
gx_color_index comps;
+ bool has_backdrop = buf->backdrop != NULL;
if (buf->data == NULL)
return 0;
@@ -6075,8 +6262,12 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
- /* composite with backdrop only */
- bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
+ /* composite with backdrop only. */
+ if (has_backdrop)
+ bline = buf->backdrop + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
+ else
+ bline = NULL;
+
line = buf->data + (x - buf->rect.p.x) + (y - buf->rect.p.y) * rowstride;
for (j = 0; j < h; ++j) {
@@ -6084,19 +6275,21 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
dst_ptr = line;
for (i = 0; i < w; ++i) {
/* Complement the components for subtractive color spaces */
- if (additive) {
- for (k = 0; k < num_chan; ++k)
- dst[k] = bg_ptr[k * planestride];
- } else {
- for (k = 0; k < num_comp; ++k)
- dst[k] = 255 - bg_ptr[k * planestride];
+ if (has_backdrop) {
+ if (additive) {
+ for (k = 0; k < num_chan; ++k)
+ dst[k] = bg_ptr[k * planestride];
+ } else {
+ for (k = 0; k < num_comp; ++k)
+ dst2[k] = dst[k] = 255 - bg_ptr[k * planestride];
+ }
+ dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */
}
- dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */
- if (buf->isolated) {
+ if (buf->isolated || !has_backdrop) {
art_pdf_knockoutisolated_group_8(dst, src, num_comp);
} else {
art_pdf_composite_knockout_8(dst, src, num_comp,
- blend_mode, pdev->blend_procs, pdev);
+ blend_mode, pdev->blend_procs, pdev);
}
/* Complement the results for subtractive color spaces */
if (additive) {
@@ -6104,9 +6297,17 @@ do_mark_fill_rectangle_ko_simple(gx_device *dev, int x, int y, int w, int h,
dst_ptr[k * planestride] = dst[k];
} else {
if (overprint) {
- for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
+ /* We may have to do the compatible overprint blending */
+ if (!buf->isolated && drawn_comps != ((1 << dev->color_info.num_components)-1)) {
+ art_pdf_composite_knockout_8(dst2, src, num_comp,
+ blend_mode, pdev->blend_procs, pdev);
+ }
+ for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
if ((comps & 0x1) != 0) {
dst_ptr[k * planestride] = 255 - dst[k];
+ } else {
+ /* Compatible overprint blend result. */
+ dst_ptr[k * planestride] = 255 - dst2[k];
}
}
} else {
@@ -6167,6 +6368,7 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
uint16_t *bline, *bg_ptr, *line, *dst_ptr;
uint16_t src[PDF14_MAX_PLANES];
uint16_t dst[PDF14_MAX_PLANES] = { 0 };
+ uint16_t dst2[PDF14_MAX_PLANES] = { 0 };
int rowstride = buf->rowstride;
int planestride = buf->planestride;
int num_chan = buf->n_chan;
@@ -6182,9 +6384,11 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
gs_graphics_type_tag_t curr_tag = GS_UNKNOWN_TAG; /* Quiet compiler */
uint16_t shape = 0; /* Quiet compiler. */
uint16_t src_alpha;
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
gx_color_index comps;
+ bool has_backdrop = buf->backdrop != NULL;
if (buf->data == NULL)
return 0;
@@ -6250,8 +6454,13 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
if (x + w > buf->dirty.q.x) buf->dirty.q.x = x + w;
if (y + h > buf->dirty.q.y) buf->dirty.q.y = y + h;
- /* composite with backdrop only */
- bline = (uint16_t *)(void *)(buf->backdrop + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride);
+
+ /* composite with backdrop only. */
+ if (has_backdrop)
+ bline = (uint16_t*)(void*)(buf->backdrop + (x - buf->rect.p.x) * 2 + (y - buf->rect.p.y) * rowstride);
+ else
+ bline = NULL;
+
line = (uint16_t *)(void *)(buf->data + (x - buf->rect.p.x)*2 + (y - buf->rect.p.y) * rowstride);
planestride >>= 1;
rowstride >>= 1;
@@ -6264,15 +6473,17 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
dst_ptr = line;
for (i = 0; i < w; ++i) {
/* Complement the components for subtractive color spaces */
- if (additive) {
- for (k = 0; k < num_chan; ++k)
- dst[k] = bg_ptr[k * planestride];
- } else {
- for (k = 0; k < num_comp; ++k)
- dst[k] = 65535 - bg_ptr[k * planestride];
+ if (has_backdrop) {
+ if (additive) {
+ for (k = 0; k < num_chan; ++k)
+ dst[k] = bg_ptr[k * planestride];
+ } else {
+ for (k = 0; k < num_comp; ++k)
+ dst2[k] = dst[k] = 65535 - bg_ptr[k * planestride];
+ }
+ dst2[num_comp] = dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */
}
- dst[num_comp] = bg_ptr[num_comp * planestride]; /* alpha doesn't invert */
- if (buf->isolated) {
+ if (buf->isolated || !has_backdrop) {
art_pdf_knockoutisolated_group_16(dst, src, num_comp);
} else {
art_pdf_composite_knockout_16(dst, src, num_comp,
@@ -6284,9 +6495,17 @@ do_mark_fill_rectangle_ko_simple16(gx_device *dev, int x, int y, int w, int h,
dst_ptr[k * planestride] = dst[k];
} else {
if (overprint) {
- for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
+ /* We may have to do the compatible overprint blending */
+ if (!buf->isolated && drawn_comps != ((1 << dev->color_info.num_components) - 1)) {
+ art_pdf_composite_knockout_16(dst2, src, num_comp,
+ blend_mode, pdev->blend_procs, pdev);
+ }
+ for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
if ((comps & 0x1) != 0) {
dst_ptr[k * planestride] = 65535 - dst[k];
+ } else {
+ /* Compatible overprint blend result. */
+ dst_ptr[k * planestride] = 65535 - dst2[k];
}
}
} else {
@@ -6771,6 +6990,8 @@ pdf14_dev_spec_op(gx_device *pdev, int dev_spec_op,
return 0;
if(dev_spec_op == gxdso_JPEG_passthrough_query)
return 0;
+ if (dev_spec_op == gxdso_overprint_active)
+ return p14dev->overprint || p14dev->stroke_overprint;
return dev_proc(p14dev->target, dev_spec_op)(p14dev->target, dev_spec_op, data, size);
}
@@ -6907,6 +7128,8 @@ gs_pdf14_device_push(gs_memory_t *mem, gs_gstate * pgs,
p14dev->width = 1;
p14dev->height = 1;
}
+
+ p14dev->op_state = pgs->is_fill_color;
code = dev_proc((gx_device *) p14dev, open_device) ((gx_device *) p14dev);
*pdev = (gx_device *) p14dev;
pdf14_set_marking_params((gx_device *)p14dev, pgs);
@@ -7237,7 +7460,8 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
pdf14_needed = false; /* At page level, set back to false */
if (smask_level == 0 && trans_group_level == 0)
cdev->page_pdf14_needed = pdf14_needed; /* save for after popping to page level */
- *pbuf++ = pparams->changed;
+ /* Changed is now two bytes due to overprint stroke fill. Write as int */
+ put_value(pbuf, pparams->changed);
if (pparams->changed & PDF14_SET_BLEND_MODE)
*pbuf++ = pparams->blend_mode;
if (pparams->changed & PDF14_SET_TEXT_KNOCKOUT)
@@ -7248,8 +7472,14 @@ c_pdf14trans_write(const gs_composite_t * pct, byte * data, uint * psize,
put_value(pbuf, pparams->shape.alpha);
if (pparams->changed & PDF14_SET_OVERPRINT)
put_value(pbuf, pparams->overprint);
- if (pparams->changed & PDF14_SET_OVERPRINT_MODE)
- put_value(pbuf, pparams->effective_overprint_mode);
+ if (pparams->changed & PDF14_SET_STROKEOVERPRINT)
+ put_value(pbuf, pparams->stroke_overprint);
+ if (pparams->changed & PDF14_SET_FILLCONSTANTALPHA)
+ put_value(pbuf, pparams->fillconstantalpha);
+ if (pparams->changed & PDF14_SET_STROKECONSTANTALPHA)
+ put_value(pbuf, pparams->strokeconstantalpha);
+ if (pparams->changed & PDF_SET_FILLSTROKE_STATE)
+ put_value(pbuf, pparams->op_fs_state);
break;
case PDF14_PUSH_TRANS_STATE:
break;
@@ -7434,7 +7664,7 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
return 0;
break;
case PDF14_SET_BLEND_PARAMS:
- params.changed = *data++;
+ read_value(data, params.changed);
if (params.changed & PDF14_SET_BLEND_MODE)
params.blend_mode = *data++;
if (params.changed & PDF14_SET_TEXT_KNOCKOUT)
@@ -7445,8 +7675,14 @@ c_pdf14trans_read(gs_composite_t * * ppct, const byte * data,
read_value(data, params.shape.alpha);
if (params.changed & PDF14_SET_OVERPRINT)
read_value(data, params.overprint);
- if (params.changed & PDF14_SET_OVERPRINT_MODE)
- read_value(data, params.effective_overprint_mode);
+ if (params.changed & PDF14_SET_STROKEOVERPRINT)
+ read_value(data, params.stroke_overprint);
+ if (params.changed & PDF14_SET_FILLCONSTANTALPHA)
+ read_value(data, params.fillconstantalpha);
+ if (params.changed & PDF14_SET_STROKECONSTANTALPHA)
+ read_value(data, params.strokeconstantalpha);
+ if (params.changed & PDF_SET_FILLSTROKE_STATE)
+ read_value(data, params.op_fs_state);
break;
}
code = gs_create_pdf14trans(ppct, &params, mem);
@@ -7870,13 +8106,17 @@ send_pdf14trans(gs_gstate * pgs, gx_device * dev,
gx_forward_set_graphics_type_tag, /* set_graphics_type_tag */\
NULL, /* strip_copy_rop2 */\
NULL, /* strip_tile_rect_devn */\
- gx_forward_copy_alpha_hl_color\
+ gx_forward_copy_alpha_hl_color,\
+ NULL, /* process_page */\
+ NULL, /* transform_pixel_region */\
+ pdf14_clist_fill_stroke_path,\
}
static dev_proc_create_compositor(pdf14_clist_create_compositor);
static dev_proc_create_compositor(pdf14_clist_forward_create_compositor);
static dev_proc_fill_path(pdf14_clist_fill_path);
static dev_proc_stroke_path(pdf14_clist_stroke_path);
+static dev_proc_fill_stroke_path(pdf14_clist_fill_stroke_path);
static dev_proc_text_begin(pdf14_clist_text_begin);
static dev_proc_begin_image(pdf14_clist_begin_image);
static dev_proc_begin_typed_image(pdf14_clist_begin_typed_image);
@@ -8160,6 +8400,7 @@ pdf14_create_clist_device(gs_memory_t *mem, gs_gstate * pgs,
pdev->pad = target->pad;
pdev->log2_align_mod = target->log2_align_mod;
pdev->is_planar = target->is_planar;
+ pdev->op_state = pgs->is_fill_color;
if (deep) {
set_dev_proc(pdev, encode_color, pdf14_encode_color16);
@@ -8855,9 +9096,21 @@ pdf14_clist_update_params(pdf14_clist_device * pdev, const gs_gstate * pgs,
changed |= PDF14_SET_OVERPRINT;
params.overprint = pdev->overprint = pgs->overprint;
}
- if (pgs->effective_overprint_mode != pdev->effective_overprint_mode) {
- changed |= PDF14_SET_OVERPRINT_MODE;
- params.effective_overprint_mode = pdev->effective_overprint_mode = pgs->effective_overprint_mode;
+ if (pgs->stroke_overprint != pdev->stroke_overprint) {
+ changed |= PDF14_SET_STROKEOVERPRINT;
+ params.stroke_overprint = pdev->stroke_overprint = pgs->stroke_overprint;
+ }
+ if (pgs->fillconstantalpha != pdev->fillconstantalpha) {
+ changed |= PDF14_SET_FILLCONSTANTALPHA;
+ params.fillconstantalpha = pdev->fillconstantalpha = pgs->fillconstantalpha;
+ }
+ if (pgs->strokeconstantalpha != pdev->strokeconstantalpha) {
+ changed |= PDF14_SET_STROKECONSTANTALPHA;
+ params.strokeconstantalpha = pdev->strokeconstantalpha = pgs->strokeconstantalpha;
+ }
+ if (pgs->is_fill_color != pdev->op_state) {
+ changed |= PDF_SET_FILLSTROKE_STATE;
+ params.op_fs_state = pdev->op_state = pgs->is_fill_color;
}
if (crop_blend_params) {
params.ctm = group_params->ctm;
@@ -9087,6 +9340,234 @@ pdf14_clist_stroke_path(gx_device *dev, const gs_gstate *pgs,
return code;
}
+/* Set up work for doing shading patterns in fill stroke through
+ the clist. We have to do all the dirty work now since we are
+ going through the default fill and stroke operations individually */
+static int
+pdf14_clist_fill_stroke_path_pattern_setup(gx_device* dev, const gs_gstate* pgs, gx_path* ppath,
+ const gx_fill_params* params_fill, const gx_drawing_color* pdevc_fill,
+ const gx_stroke_params* params_stroke, const gx_drawing_color* pdevc_stroke,
+ const gx_clip_path* pcpath)
+{
+ int code, code2;
+ gs_transparency_group_params_t params = { 0 };
+ gs_fixed_rect clip_bbox;
+ gs_rect bbox, group_stroke_box;
+ float opacity = pgs->opacity.alpha;
+ gs_blend_mode_t blend_mode = pgs->blend_mode;
+ gs_fixed_rect path_bbox;
+ int expansion_code;
+ gs_fixed_point expansion;
+
+ code = gx_curr_fixed_bbox((gs_gstate*)pgs, &clip_bbox, NO_PATH);
+ if (code < 0 && code != gs_error_unknownerror)
+ return code;
+ if (code == gs_error_unknownerror) {
+ /* didn't get clip box from gx_curr_fixed_bbox */
+ clip_bbox.p.x = clip_bbox.p.y = 0.0;
+ clip_bbox.q.x = int2fixed(dev->width);
+ clip_bbox.q.y = int2fixed(dev->height);
+ }
+ if (pcpath)
+ rect_intersect(clip_bbox, pcpath->outer_box);
+
+ /* expand the ppath using stroke expansion rule, then intersect it */
+ code = gx_path_bbox(ppath, &path_bbox);
+ if (code == gs_error_nocurrentpoint && ppath->segments->contents.subpath_first == 0)
+ return 0; /* ignore empty path */
+ if (code < 0)
+ return code;
+ expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion);
+ if (expansion_code >= 0) {
+ path_bbox.p.x -= expansion.x;
+ path_bbox.p.y -= expansion.y;
+ path_bbox.q.x += expansion.x;
+ path_bbox.q.y += expansion.y;
+ }
+ rect_intersect(path_bbox, clip_bbox);
+ bbox.p.x = fixed2float(path_bbox.p.x);
+ bbox.p.y = fixed2float(path_bbox.p.y);
+ bbox.q.x = fixed2float(path_bbox.q.x);
+ bbox.q.y = fixed2float(path_bbox.q.y);
+
+ code = gs_bbox_transform_inverse(&bbox, &ctm_only(pgs), &group_stroke_box);
+ if (code < 0)
+ return code;
+
+ /* See if overprint is enabled for both stroke and fill AND if ca == CA */
+ if (pgs->fillconstantalpha == pgs->strokeconstantalpha &&
+ (pgs->overprint && pgs->stroke_overprint)) {
+ /* Push a non-isolated non-knockout group with alpha = 1.0 and
+ compatible overprint mode. Group will be composited with
+ original alpha and blend mode */
+ params.Isolated = false;
+ params.group_color = UNKNOWN;
+ params.Knockout = false;
+
+ /* non-isolated non-knockout group pushed with original alpha and blend mode */
+ code = gs_begin_transparency_group((gs_gstate*)pgs, &params, (const gs_rect*)&group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
+ if (code < 0)
+ return code;
+
+ /* Change alpha to 1.0 and blend mode to compatible overprint for actual drawing */
+ code = gs_setopacityalpha((gs_gstate*)pgs, 1.0);
+ if (code < 0)
+ goto cleanup;
+ code = gs_setblendmode((gs_gstate*)pgs, BLEND_MODE_CompatibleOverprint);
+ if (code < 0)
+ goto cleanup;
+
+ /* Do fill */
+ if (pgs->fillconstantalpha > 0.0) {
+ code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath);
+ if (code < 0)
+ goto cleanup;
+ }
+
+ /* Do stroke */
+ if (pgs->strokeconstantalpha > 0.0) {
+ code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
+ if (code < 0)
+ goto cleanup;
+ }
+
+ } else {
+ /* Push a non-isolated knockout group. Do not change the alpha or
+ blend modes */
+ params.Isolated = false;
+ params.group_color = UNKNOWN;
+ params.Knockout = true;
+
+ /* non-isolated knockout group is pushed with alpha = 1.0 and Normal blend mode */
+ code = gs_setopacityalpha((gs_gstate*)pgs, 1.0);
+ if (code < 0)
+ return code;
+ code = gs_setblendmode((gs_gstate*)pgs, BLEND_MODE_Normal);
+ if (code < 0)
+ return code;
+
+ code = gs_begin_transparency_group((gs_gstate*)pgs, &params, (const gs_rect*)&group_stroke_box, PDF14_BEGIN_TRANS_GROUP);
+ if (code < 0)
+ return code;
+
+ /* restore blend mode for actual drawing in the group */
+ code = gs_setblendmode((gs_gstate*)pgs, blend_mode);
+ if (code < 0)
+ goto cleanup;
+
+ if (pgs->fillconstantalpha > 0.0) {
+ code = gs_setopacityalpha((gs_gstate*)pgs, pgs->fillconstantalpha);
+ if (code < 0)
+ goto cleanup;
+
+ /* If we are in an overprint situation, set the blend mode to compatible
+ overprint */
+ if (pgs->overprint)
+ code = gs_setblendmode((gs_gstate*)pgs, BLEND_MODE_CompatibleOverprint);
+ if (code < 0)
+ goto cleanup;
+
+ code = pdf14_clist_fill_path(dev, pgs, ppath, params_fill, pdevc_fill, pcpath);
+ if (code < 0)
+ goto cleanup;
+
+ if (pgs->overprint)
+ code = gs_setblendmode((gs_gstate*)pgs, blend_mode);
+ if (code < 0)
+ goto cleanup;
+ }
+
+ if (pgs->strokeconstantalpha > 0.0) {
+ code = gs_setopacityalpha((gs_gstate*)pgs, pgs->strokeconstantalpha);
+ if (code < 0)
+ goto cleanup;
+ if (pgs->stroke_overprint)
+ code = gs_setblendmode((gs_gstate*)pgs, BLEND_MODE_CompatibleOverprint);
+ code = pdf14_clist_stroke_path(dev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
+ if (code < 0)
+ goto cleanup;
+
+ if (pgs->stroke_overprint)
+ code = gs_setblendmode((gs_gstate*)pgs, blend_mode);
+ if (code < 0)
+ goto cleanup;
+ }
+ }
+ /* Now during the pop do the compositing with alpha of 1.0 and normal blend */
+ code = gs_setopacityalpha((gs_gstate*)pgs, 1.0);
+ if (code < 0)
+ goto cleanup;
+ code = gs_setblendmode((gs_gstate*)pgs, BLEND_MODE_Normal);
+ if (code < 0)
+ goto cleanup;
+
+ /* Restore where we were. If an error occured while in the group push
+ return that error code but try to do the cleanup */
+cleanup:
+ code2 = gs_end_transparency_group((gs_gstate*)pgs);
+ if (code2 < 0) {
+ /* At this point things have gone very wrong. We should just shut down */
+ code = gs_abort_pdf14trans_device((gs_gstate*)pgs);
+ return code2;
+ }
+
+ /* Restore if there were any changes */
+ code2 = gs_setopacityalpha((gs_gstate*)pgs, opacity);
+ if (code2 < 0)
+ return code2;
+ code2 = gs_setblendmode((gs_gstate*)pgs, blend_mode);
+ if (code2 < 0)
+ return code2;
+ return code;
+}
+
+/*
+ * fill_path routine for the PDF 1.4 transaprency compositor device for
+ * writing the clist.
+ */
+static int
+pdf14_clist_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *params_fill, const gx_drawing_color *pdevc_fill,
+ const gx_stroke_params *params_stroke, const gx_drawing_color *pdevc_stroke,
+ const gx_clip_path *pcpath)
+{
+ pdf14_clist_device * pdev = (pdf14_clist_device *)dev;
+ gs_gstate new_pgs = *pgs;
+ int code;
+
+ if ((pgs->fillconstantalpha == 0.0 && pgs->strokeconstantalpha == 0.0) ||
+ (pgs->ctm.xx == 0.0 && pgs->ctm.xy == 0.0 && pgs->ctm.yx == 0.0 && pgs->ctm.yy == 0.0))
+ return 0;
+
+ /*
+ * Ensure that that the PDF 1.4 reading compositor will have the current
+ * blending parameters. This is needed since the fill_rectangle routines
+ * do not have access to the gs_gstate. Thus we have to pass any
+ * changes explictly.
+ */
+ code = pdf14_clist_update_params(pdev, pgs, false, NULL);
+ if (code < 0)
+ return code;
+ /* If we are doing a shading fill or stroke, the clist can't
+ deal with this and end up in the pdf_fill_stroke operation.
+ We will need to break up the fill stroke now and do
+ the appropriate group pushes and set up. */
+
+ if ((pdevc_fill != NULL && gx_dc_is_pattern2_color(pdevc_fill)) ||
+ (pdevc_stroke != NULL && gx_dc_is_pattern2_color(pdevc_stroke))) {
+ return pdf14_clist_fill_stroke_path_pattern_setup(dev, pgs, ppath,
+ params_fill, pdevc_fill, params_stroke, pdevc_stroke, pcpath);
+ }
+ update_lop_for_pdf14(&new_pgs, pdevc_fill);
+ new_pgs.trans_device = dev;
+ new_pgs.has_transparency = true;
+ code = gx_forward_fill_stroke_path(dev, &new_pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ new_pgs.trans_device = NULL;
+ new_pgs.has_transparency = false;
+ return code;
+}
+
/*
* text_begin routine for the PDF 1.4 transaprency compositor device for
* writing the clist.
diff --git a/base/gdevp14.h b/base/gdevp14.h
index 349919395..5c20ba57a 100644
--- a/base/gdevp14.h
+++ b/base/gdevp14.h
@@ -34,6 +34,12 @@ typedef enum {
PDF14_DeviceCustom = 4
} pdf14_default_colorspace_t;
+typedef enum {
+ PDF14_OP_STATE_NONE = 0,
+ PDF14_OP_STATE_FILL = 1,
+ PDF14_OP_STATE_STROKE = 2,
+} PDF14_OP_FS_STATE;
+
/*
* This structure contains procedures for processing routine which differ
* between the different blending color spaces.
@@ -205,12 +211,19 @@ typedef struct pdf14_device_s {
float opacity;
float shape;
float alpha; /* alpha = opacity * shape */
+ float fillconstantalpha;
+ float strokeconstantalpha;
gs_blend_mode_t blend_mode;
bool text_knockout;
bool overprint;
- bool effective_overprint_mode;
+ bool effective_overprint_mode;
+ bool stroke_effective_op_mode;
+ bool stroke_overprint;
int text_group;
gx_color_index drawn_comps; /* Used for overprinting. Passed from overprint compositor */
+ gx_color_index drawn_comps_fill; /* selected by color_is_fill */
+ gx_color_index drawn_comps_stroke;
+ PDF14_OP_FS_STATE op_state;
gx_device * pclist_device;
bool free_devicen; /* Used to avoid freeing a deviceN parameter from target clist device */
bool sep_device;
diff --git a/base/gdevsclass.c b/base/gdevsclass.c
index 0e2bf3a87..4623e5fd0 100644
--- a/base/gdevsclass.c
+++ b/base/gdevsclass.c
@@ -894,6 +894,17 @@ int default_subclass_process_page(gx_device *dev, gx_process_page_options_t *opt
return 0;
}
+int default_subclass_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
+ const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
+ const gx_clip_path *pcpath)
+{
+ if (dev->child)
+ return dev_proc(dev->child, fill_stroke_path)(dev, pgs, ppath, fill_params, pdcolor_fill,
+ stroke_params, pdcolor_stroke, pcpath);
+ return 0;
+}
+
int default_subclass_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason, transform_pixel_region_data *data)
{
if (dev->child)
diff --git a/base/gdevsclass.h b/base/gdevsclass.h
index ada3a4e36..cc7a43597 100644
--- a/base/gdevsclass.h
+++ b/base/gdevsclass.h
@@ -102,6 +102,7 @@ dev_proc_strip_tile_rect_devn(default_subclass_strip_tile_rect_devn);
dev_proc_copy_alpha_hl_color(default_subclass_copy_alpha_hl_color);
dev_proc_process_page(default_subclass_process_page);
dev_proc_transform_pixel_region(default_subclass_transform_pixel_region);
+dev_proc_fill_stroke_path(default_subclass_fill_stroke_path);
void default_subclass_finalize(const gs_memory_t *cmem, void *vptr);
diff --git a/base/gscdevn.c b/base/gscdevn.c
index 32b68f38f..98718796a 100644
--- a/base/gscdevn.c
+++ b/base/gscdevn.c
@@ -734,14 +734,18 @@ gx_set_overprint_DeviceN(const gs_color_space * pcs, gs_gstate * pgs)
if ( base_type->index == gs_color_space_index_DeviceCMYK )
return base_type->set_overprint( pcs->base_space, pgs );
else
- return gx_spot_colors_set_overprint( pcs->base_space, pgs);
+ return gx_set_no_overprint(pgs);
} else {
gs_overprint_params_t params;
- if ((params.retain_any_comps = pgs->overprint)) {
+
+ params.retain_any_comps = (pgs->overprint && pgs->is_fill_color) ||
+ (pgs->stroke_overprint && !pgs->is_fill_color);
+
+ if (params.retain_any_comps) {
int i, ncomps = pcs->params.device_n.num_components;
- params.retain_spot_comps = false;
+ params.is_fill_color = pgs->is_fill_color; /* for fill_stroke */
params.drawn_comps = 0;
for (i = 0; i < ncomps; i++) {
int mcomp = pcmap->color_map[i];
@@ -751,7 +755,9 @@ gx_set_overprint_DeviceN(const gs_color_space * pcs, gs_gstate * pgs)
}
/* Only DeviceCMYK can use overprint mode */
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
+ params.op_state = OP_STATE_NONE;
+ params.is_fill_color =pgs->is_fill_color;
return gs_gstate_update_overprint(pgs, &params);
}
}
diff --git a/base/gscolor.c b/base/gscolor.c
index edf31994a..81effa945 100644
--- a/base/gscolor.c
+++ b/base/gscolor.c
@@ -217,12 +217,14 @@ gx_set_device_color_1(gs_gstate * pgs)
{
gs_color_space *pcs;
- /* Get the current overprint setting so that it can be properly restored.
- No need to fool with the mode */
- int overprint = pgs->overprint;
+ /* We need to set the stroke *and* the fill overprint off
+ to ensure the op compositor is disabled. They will be
+ restored when the graphic state is restored */
+ if (pgs->stroke_overprint)
+ gs_setstrokeoverprint(pgs, false);
+ if (pgs->overprint)
+ gs_setfilloverprint(pgs, false);
- if (overprint)
- gs_setoverprint(pgs, false);
pcs = gs_cspace_new_DeviceGray(pgs->memory);
if (pcs) {
gs_setcolorspace(pgs, pcs);
@@ -234,10 +236,6 @@ gx_set_device_color_1(gs_gstate * pgs)
set_nonclient_dev_color(gs_currentdevicecolor_inline(pgs), 1);
pgs->log_op = lop_default;
- /* If we changed the overprint condition, restore */
- if (overprint)
- gs_setoverprint(pgs, true);
-
return 0;
}
diff --git a/base/gscolor2.c b/base/gscolor2.c
index a076d0cb2..5e1bd11b4 100644
--- a/base/gscolor2.c
+++ b/base/gscolor2.c
@@ -43,8 +43,7 @@ gs_setcolorspace_only(gs_gstate * pgs, gs_color_space * pcs)
if (pcs->id != cs_old->id) {
rc_increment_cs(pcs);
pgs->color[0].color_space = pcs;
- if ( (code = pcs->type->install_cspace(pcs, pgs)) < 0 ||
- (pgs->overprint && (code = gs_do_set_overprint(pgs)) < 0) ) {
+ if ( (code = pcs->type->install_cspace(pcs, pgs)) < 0) {
pgs->color[0].color_space = cs_old;
rc_decrement_only_cs(pcs, "gs_setcolorspace");
} else {
@@ -86,6 +85,7 @@ gs_setcolor(gs_gstate * pgs, const gs_client_color * pcc)
gs_client_color cc_old = *pgs->color[0].ccolor;
gx_device_color *dev_color = pgs->color[0].dev_color;
bool do_unset = true;
+ bool op;
if (pgs->in_cachedevice)
return_error(gs_error_undefined); /* PLRM3 page 215. */
@@ -105,6 +105,18 @@ gs_setcolor(gs_gstate * pgs, const gs_client_color * pcc)
(*pcs->type->restrict_color)(pgs->color[0].ccolor, pcs);
(*pcs->type->adjust_color_count)(&cc_old, pcs, -1);
+ /* If we are in a situation where we are doing overprint
+ with OPM, then we need to update the overprint
+ compositor as these values can affect what is drawn */
+ op = pgs->is_fill_color ? pgs->overprint : pgs->stroke_overprint;
+ if (pgs->color[0].effective_opm && op) {
+ if (pgs->is_fill_color) {
+ gs_setfilloverprint(pgs, op);
+ } else {
+ gs_setstrokeoverprint(pgs, op);
+ }
+ }
+
return 0;
}
diff --git a/base/gscolor3.c b/base/gscolor3.c
index 832cd35a7..47b22f0b1 100644
--- a/base/gscolor3.c
+++ b/base/gscolor3.c
@@ -73,6 +73,20 @@ gs_shfill(gs_gstate * pgs, const gs_shading_t * psh)
because .shfill is always called within gsave-grestore -
see gs/lib . */
code = gs_setcolorspace(pgs, psh->params.ColorSpace);
+ if (pgs->overprint || (!pgs->overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ gs_overprint_params_t op_params = { 0 };
+
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Shading Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+
+ op_params.op_state = OP_STATE_FILL;
+ gs_gstate_update_overprint(pgs, &op_params);
+ }
+
if (code < 0)
return 0;
if (psh->params.cie_joint_caches != NULL) {
diff --git a/base/gscpixel.c b/base/gscpixel.c
index 6663f1c4c..37904406a 100644
--- a/base/gscpixel.c
+++ b/base/gscpixel.c
@@ -113,7 +113,8 @@ gx_set_overprint_DevicePixel(const gs_color_space * pcs, gs_gstate * pgs)
gs_overprint_params_t params;
params.retain_any_comps = false;
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
+ params.is_fill_color = pgs->is_fill_color;
return gs_gstate_update_overprint(pgs, &params);
}
diff --git a/base/gscsepr.c b/base/gscsepr.c
index d0c81f0ff..3f10ba249 100644
--- a/base/gscsepr.c
+++ b/base/gscsepr.c
@@ -186,16 +186,17 @@ gx_set_overprint_Separation(const gs_color_space * pcs, gs_gstate * pgs)
gs_devicen_color_map * pcmap = &pgs->color_component_map;
if (pcmap->use_alt_cspace)
- return gx_spot_colors_set_overprint(pcs->base_space, pgs);
+ return gx_set_no_overprint(pgs);
else {
gs_overprint_params_t params;
- /* We should not have to blend if we don't need the alternate tint transform */
- params.retain_any_comps = pgs->overprint &&
- pcs->params.separation.sep_type != SEP_ALL;
+ params.retain_any_comps = (((pgs->overprint && pgs->is_fill_color) ||
+ (pgs->stroke_overprint && !pgs->is_fill_color)) &&
+ (pcs->params.separation.sep_type != SEP_ALL));
+ params.is_fill_color = pgs->is_fill_color;
+ params.drawn_comps = 0;
+ params.op_state = OP_STATE_NONE;
if (params.retain_any_comps) {
- params.retain_spot_comps = false;
- params.drawn_comps = 0;
if (pcs->params.separation.sep_type != SEP_NONE) {
int mcomp = pcmap->color_map[0];
@@ -204,7 +205,7 @@ gx_set_overprint_Separation(const gs_color_space * pcs, gs_gstate * pgs)
}
}
/* Only DeviceCMYK can use overprint mode */
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
return gs_gstate_update_overprint(pgs, &params);
}
}
diff --git a/base/gscspace.c b/base/gscspace.c
index d4ebef6d8..b061d40a1 100644
--- a/base/gscspace.c
+++ b/base/gscspace.c
@@ -465,26 +465,47 @@ gx_install_DeviceCMYK(gs_color_space * pcs, gs_gstate * pgs)
}
/*
+ * Communicate to the overprint compositor that this particular
+ * state overprint is not enabled. This could be due to a
+ * mismatched color space, or that overprint is false or the
+ * device does not support it.
+ */
+int
+gx_set_no_overprint(gs_gstate* pgs)
+{
+ gs_overprint_params_t params = { 0 };
+
+ params.retain_any_comps = false;
+ params.op_state = OP_STATE_NONE;
+ params.is_fill_color = pgs->is_fill_color;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
+
+ return gs_gstate_update_overprint(pgs, &params);
+}
+
+/*
* Push an overprint compositor onto the current device indicating that,
* at most, the spot color parameters are to be preserved.
*
* This routine should be used for all Device, CIEBased, and ICCBased
- * color spaces, except for DeviceCMKY. Also, it would not be used for
- * DeviceRGB if we have simulated overprint turned on.
- * These latter cases requires a
- * special verson that supports overprint mode.
+ * color spaces, except for DeviceCMKY.
*/
int
gx_spot_colors_set_overprint(const gs_color_space * pcs, gs_gstate * pgs)
{
- gs_overprint_params_t params;
+ gs_overprint_params_t params = {0};
+ bool op = pgs->is_fill_color ? pgs->overprint : pgs->stroke_overprint;
- if ((params.retain_any_comps = pgs->overprint)) {
- params.retain_spot_comps = true;
+ if (!op)
params.retain_any_comps = false;
- }
+ else
+ params.retain_any_comps = true;
+
+ params.is_fill_color = pgs->is_fill_color;
+ params.op_state = OP_STATE_NONE;
+
/* Only DeviceCMYK case can have overprint mode set to true */
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
return gs_gstate_update_overprint(pgs, &params);
}
@@ -615,7 +636,7 @@ gx_set_overprint_DeviceCMYK(const gs_color_space * pcs, gs_gstate * pgs)
overprint simulation. This is seen with AR when doing output preview,
overprint simulation enabled of the file overprint_icc.pdf (see our
test files) which has SWOP ICC based CMYK fills. In AR, if we use a
- simluation ICC profile that is different than the source profile,
+ simulation ICC profile that is different than the source profile,
overprinting is no longer previewed. We follow the same logic here.
If the source and destination ICC profiles do not match, then there is
effectively no overprinting enabled. This is bug 692433 */
@@ -624,13 +645,17 @@ int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs)
gx_device * dev = pgs->device;
gx_device_color_info * pcinfo = (dev == 0 ? 0 : &dev->color_info);
gx_color_index drawn_comps = 0;
- gs_overprint_params_t params;
+ gs_overprint_params_t params = { 0 };
gx_device_color *pdc;
cmm_dev_profile_t *dev_profile;
cmm_profile_t *output_profile = 0;
int code;
bool profile_ok = false;
gsicc_rendering_param_t render_cond;
+ bool eop;
+
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_cmyk\n");
if (dev) {
code = dev_proc(dev, get_profile)(dev, &dev_profile);
@@ -646,6 +671,10 @@ int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs)
else
drawn_comps = pcinfo->process_comps;
}
+
+ if_debug1m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_cmyk. drawn_comps = 0x%x\n", drawn_comps);
+
if (drawn_comps == 0)
return gx_spot_colors_set_overprint(pcs, pgs);
@@ -658,15 +687,24 @@ int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs)
}
}
- pdc = gs_currentdevicecolor_inline(pgs);
- if (color_is_set(pdc) && profile_ok && pgs->effective_overprint_mode) {
+ eop = gs_currentcolor_eopm(pgs);
+
+ if_debug3m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_cmyk. is_fill_color = %d, pgs->color[0].effective_opm = %d pgs->color[1].effective_opm = %d\n",
+ pgs->is_fill_color, pgs->color[0].effective_opm, pgs->color[1].effective_opm);
+
+ if (profile_ok && eop) {
gx_color_index nz_comps, one, temp;
int code;
int num_colorant[4], k;
bool colorant_ok;
-
dev_color_proc_get_nonzero_comps((*procp));
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_cmyk. color_is_set, profile_ok and eop\n");
+
+ gx_set_dev_color(pgs);
+ pdc = gs_currentdevicecolor_inline(pgs);
procp = pdc->type->get_nonzero_comps;
if (pdc->ccolor_valid) {
/* If we have the source colors, then use those in making the
@@ -707,15 +745,20 @@ int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs)
}
drawn_comps &= nz_comps;
}
+ params.is_fill_color = pgs->is_fill_color;
params.retain_any_comps = true;
- params.retain_spot_comps = false;
params.drawn_comps = drawn_comps;
+ params.op_state = OP_STATE_NONE;
+
+ if_debug2m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_cmyk. retain_any_comps = %d, drawn_comps = 0x%x\n",
+ params.retain_any_comps, params.drawn_comps);
+
/* We are in CMYK, the profiles match and overprint is true. Set effective
overprint mode to overprint mode but only if effective has not already
been set to 0 */
- pgs->effective_overprint_mode =
- (pgs->overprint_mode && pgs->effective_overprint_mode);
-
+ params.effective_opm = pgs->color[0].effective_opm =
+ pgs->overprint_mode && gs_currentcolor_eopm(pgs);
return gs_gstate_update_overprint(pgs, &params);
}
diff --git a/base/gscspace.h b/base/gscspace.h
index c46ffdbc0..b4ef3e078 100644
--- a/base/gscspace.h
+++ b/base/gscspace.h
@@ -367,6 +367,9 @@ bool gs_color_space_equal(const gs_color_space *pcs1,
/* Restrict a color to its legal range. */
void gs_color_space_restrict_color(gs_client_color *, const gs_color_space *);
+/* Communicate to overprint compositor that overprint is not to be used */
+int gx_set_no_overprint(gs_gstate* pgs);
+
/*
* Get the base space of an Indexed or uncolored Pattern color space, or the
* alternate space of a Separation or DeviceN space. Return NULL if the
diff --git a/base/gsdcolor.h b/base/gsdcolor.h
index 9c553026b..857ba7353 100644
--- a/base/gsdcolor.h
+++ b/base/gsdcolor.h
@@ -360,7 +360,7 @@ struct gx_device_color_s {
struct gx_device_color_saved_s {
gx_device_color_type type;
- gs_graphics_type_tag_t tag; /* value used to set dev_color */
+ int devn_type; /* for fill / stroke */
union _svc {
gx_color_index pure;
struct _svbin {
diff --git a/base/gsdevice.c b/base/gsdevice.c
index 69fb17407..6e3ce83fe 100644
--- a/base/gsdevice.c
+++ b/base/gsdevice.c
@@ -605,7 +605,7 @@ gs_setdevice_no_init(gs_gstate * pgs, gx_device * dev)
}
rc_assign(pgs->device, dev, "gs_setdevice_no_init");
gs_gstate_update_device(pgs, dev);
- return pgs->overprint ? gs_do_set_overprint(pgs) : 0;
+ return 0;
}
/* Initialize a just-allocated device. */
diff --git a/base/gsdparam.c b/base/gsdparam.c
index 631321295..70a2305b0 100644
--- a/base/gsdparam.c
+++ b/base/gsdparam.c
@@ -87,7 +87,7 @@ int gx_default_get_param(gx_device *dev, char *Param, void *list)
bool devicegraytok = true; /* Default if device profile stuct not set */
bool graydetection = false;
bool usefastcolor = false; /* set for unmanaged color */
- bool sim_overprint = false; /* By default do not simulate overprinting */
+ bool sim_overprint = true; /* By default simulate overprinting (only valid with cmyk devices) */
bool prebandthreshold = true, temp_bool = false;
if(strcmp(Param, "OutputDevice") == 0){
@@ -506,7 +506,7 @@ gx_default_get_params(gx_device * dev, gs_param_list * plist)
bool devicegraytok = true; /* Default if device profile stuct not set */
bool graydetection = false;
bool usefastcolor = false; /* set for unmanaged color */
- bool sim_overprint = false; /* By default do not simulate overprinting */
+ bool sim_overprint = true; /* By default simulate overprinting */
bool prebandthreshold = true, temp_bool;
int k;
int color_accuracy = MAX_COLOR_ACCURACY;
@@ -1421,7 +1421,7 @@ gx_default_put_params(gx_device * dev, gs_param_list * plist)
bool devicegraytok = true;
bool graydetection = false;
bool usefastcolor = false;
- bool sim_overprint = false;
+ bool sim_overprint = true;
bool prebandthreshold = false;
bool use_antidropout = dev->color_info.use_antidropout_downscaler;
bool temp_bool;
diff --git a/base/gsdps1.c b/base/gsdps1.c
index c59534cd6..020eac671 100644
--- a/base/gsdps1.c
+++ b/base/gsdps1.c
@@ -217,7 +217,7 @@ gs_rectfill(gs_gstate * pgs, const gs_rect * pr, uint count)
gs_gstate_color_load(pgs) >= 0 &&
(*dev_proc(pdev, get_alpha_bits)) (pdev, go_graphics)
<= 1 &&
- (!pgs->overprint || !pgs->effective_overprint_mode)
+ (!pgs->overprint || !gs_currentcolor_eopm(pgs))
) {
uint i;
gs_fixed_rect clip_rect;
diff --git a/base/gsicc.c b/base/gsicc.c
index 4f26eda1a..22b704815 100644
--- a/base/gsicc.c
+++ b/base/gsicc.c
@@ -656,9 +656,10 @@ gx_set_overprint_ICC(const gs_color_space * pcs, gs_gstate * pgs)
bool cs_ok;
cmm_dev_profile_t *dev_profile;
bool gray_to_k;
+ bool op = pgs->is_fill_color ? pgs->overprint : pgs->stroke_overprint;
if (dev == 0 || pcinfo == NULL)
- return gx_spot_colors_set_overprint(pcs, pgs);
+ return gx_set_no_overprint(pgs);
dev_proc(dev, get_profile)(dev, &dev_profile);
gray_to_k = dev_profile->devicegraytok;
@@ -669,8 +670,12 @@ gx_set_overprint_ICC(const gs_color_space * pcs, gs_gstate * pgs)
cs_ok = ((pcs->cmm_icc_profile_data->data_cs == gsCMYK) ||
(pcs->cmm_icc_profile_data->data_cs == gsGRAY && gray_to_k));
- if (!pgs->overprint || pcinfo->opmode == GX_CINFO_OPMODE_NOT || !cs_ok)
- return gx_spot_colors_set_overprint(pcs, pgs);
+ if_debug4m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gx_set_overprint_ICC. cs_ok = %d is_fill_color = %d overprint = %d stroke_overprint = %d \n",
+ cs_ok, pgs->is_fill_color, pgs->overprint, pgs->stroke_overprint);
+
+ if (!op || pcinfo->opmode == GX_CINFO_OPMODE_NOT || !cs_ok)
+ return gx_set_no_overprint(pgs);
else
return gx_set_overprint_cmyk(pcs, pgs);
}
diff --git a/base/gsicc_manage.c b/base/gsicc_manage.c
index 5c400b966..206baead9 100644
--- a/base/gsicc_manage.c
+++ b/base/gsicc_manage.c
@@ -1440,7 +1440,7 @@ gsicc_new_device_profile_array(gs_memory_t *memory)
result->usefastcolor = false; /* Default is to not use fast color */
result->prebandthreshold = true;
result->supports_devn = false;
- result->sim_overprint = false; /* Default is now not to simulate overprint */
+ result->sim_overprint = true; /* Default is to simulate overprint */
rc_init_free(result, memory->non_gc_memory, 1, rc_free_profile_array);
return result;
}
diff --git a/base/gsimage.c b/base/gsimage.c
index be7d2f2c5..7b4602fcc 100644
--- a/base/gsimage.c
+++ b/base/gsimage.c
@@ -223,6 +223,24 @@ gs_image_begin_typed(const gs_image_common_t * pic, gs_gstate * pgs,
if (code < 0)
return code;
}
+
+ if (pgs->overprint || (!pgs->overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ gs_overprint_params_t op_params = { 0 };
+
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Image Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+
+ op_params.op_state = OP_STATE_FILL;
+ gs_gstate_update_overprint(pgs, &op_params);
+
+ dev = gs_currentdevice(pgs);
+ dev2 = dev;
+ }
+
/* Imagemask with shading color needs a special optimization
with converting the image into a clipping.
Check for such case after gs_gstate_color_load is done,
diff --git a/base/gsovrc.c b/base/gsovrc.c
index 3407e93df..81e3fcd96 100644
--- a/base/gsovrc.c
+++ b/base/gsovrc.c
@@ -16,6 +16,7 @@
/* overprint/overprint mode compositor implementation */
+#include "assert_.h"
#include "memory_.h"
#include "gx.h"
#include "gserrors.h"
@@ -29,6 +30,8 @@
#include "gxoprect.h"
#include "gsbitops.h"
#include "gxgstate.h"
+#include "gxdevsop.h"
+#include "gxcldev.h"
/* GC descriptor for gs_overprint_t */
private_st_gs_overprint_t();
@@ -109,10 +112,11 @@ c_overprint_equal(const gs_composite_t * pct0, const gs_composite_t * pct1)
pparams0 = &((const gs_overprint_t *)(pct0))->params;
pparams1 = &((const gs_overprint_t *)(pct1))->params;
+
+ if (pparams0->is_fill_color != pparams1->is_fill_color)
+ return true; /* this changed */
if (!pparams0->retain_any_comps)
return !pparams1->retain_any_comps;
- else if (pparams0->retain_spot_comps)
- return pparams1->retain_spot_comps;
else
return pparams0->drawn_comps == pparams1->drawn_comps;
} else
@@ -123,8 +127,10 @@ c_overprint_equal(const gs_composite_t * pct0, const gs_composite_t * pct1)
* Bits corresponding to boolean values in the first byte of the string
* representation of an overprint compositor.
*/
-#define OVERPRINT_ANY_COMPS 1
-#define OVERPRINT_SPOT_COMPS 2
+#define OVERPRINT_ANY_COMPS 1
+#define OVERPRINT_IS_FILL_COLOR 2
+#define OVERPRINT_SET_FILL_COLOR 0xc
+#define OVERPRINT_EOPM 0x10
/*
* Convert an overprint compositor to string form for use by the command
@@ -137,20 +143,40 @@ c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize, gx_devi
byte flags = 0;
int used = 1, avail = *psize;
+ /* Clist writer needs to store active state of op device so that
+ we know when to send compositor actions to disable it */
+ if (pparams->op_state == OP_STATE_NONE) {
+ if (pparams->is_fill_color) {
+ if (pparams->retain_any_comps)
+ cdev->op_fill_active = true;
+ else
+ cdev->op_fill_active = false;
+ } else {
+ if (pparams->retain_any_comps)
+ cdev->op_stroke_active = true;
+ else
+ cdev->op_stroke_active = false;
+ }
+ }
+
/* encoded the booleans in a single byte */
- if (pparams->retain_any_comps) {
- flags |= OVERPRINT_ANY_COMPS;
- if (pparams->retain_spot_comps)
- flags |= OVERPRINT_SPOT_COMPS;
- /* write out the component bits only if necessary (and possible) */
- if (!pparams->retain_spot_comps) {
+ if (pparams->retain_any_comps || pparams->is_fill_color || pparams->op_state) {
+ flags |= (pparams->retain_any_comps) ? OVERPRINT_ANY_COMPS : 0;
+ flags |= (pparams->is_fill_color) ? OVERPRINT_IS_FILL_COLOR : 0;
+ flags |= (pparams->op_state) << 2;
+ flags |= (pparams->effective_opm) << 4;
+
+ /* write out the component bits */
+ if (pparams->retain_any_comps) {
uint tmp_size = (avail > 0 ? avail - 1 : 0);
int code = write_color_index(pparams->drawn_comps, data + 1,
- &tmp_size);
+ &tmp_size);
if (code < 0 && code != gs_error_rangecheck)
return code;
used += tmp_size;
- }
+ if_debug0m('v', ((const gx_device*)cdev)->memory, "[v] drawn_comps stored\n");
+
+ }
}
/* check for overflow */
@@ -158,7 +184,8 @@ c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize, gx_devi
if (used > avail)
return_error(gs_error_rangecheck);
data[0] = flags;
- if_debug1m('v', ((const gx_device *)cdev)->memory, "[v]c_overprint_write(%d)\n", flags);
+ if_debug2m('v', ((const gx_device *)cdev)->memory, "[v]c_overprint_write(%d), drawn_comps=0x%x\n",
+ flags, pparams->drawn_comps);
return 0;
}
@@ -180,19 +207,27 @@ c_overprint_read(
if (size < 1)
return_error(gs_error_rangecheck);
flags = *data;
- if_debug1m('v', mem, "[v]c_overprint_read(%d)\n", flags);
+ if_debug1m('v', mem, "[v]c_overprint_read(%d)", flags);
params.retain_any_comps = (flags & OVERPRINT_ANY_COMPS) != 0;
- params.retain_spot_comps = (flags & OVERPRINT_SPOT_COMPS) != 0;
+ params.is_fill_color = (flags & OVERPRINT_IS_FILL_COLOR) != 0;
+ params.op_state = (flags & OVERPRINT_SET_FILL_COLOR) >> 2;
+ params.effective_opm = (flags & OVERPRINT_EOPM) >> 4;
params.idle = 0;
params.drawn_comps = 0;
/* check if the drawn_comps array is present */
- if (params.retain_any_comps && (!params.retain_spot_comps)) {
+ if (params.retain_any_comps) {
code = read_color_index(&params.drawn_comps, data + 1, size - 1);
if (code < 0)
return code;
nbytes += code;
+ if_debug0m('v', mem, ", drawn_comps read");
}
+ if_debug1m('v', mem, ", retain_any_comps=%d", params.retain_any_comps);
+ if_debug1m('v', mem, ", is_fill_color=%d", params.is_fill_color);
+ if_debug1m('v', mem, ", drawn_comps=0x%x", params.drawn_comps);
+ if_debug1m('v', mem, ", op_state=%d", params.op_state);
+ if_debug0m('v', mem, "\n");
code = gs_create_overprint(ppct, &params, mem);
return code < 0 ? code : nbytes;
}
@@ -203,9 +238,7 @@ c_overprint_read(
static gs_compositor_closing_state
c_overprint_is_closing(const gs_composite_t *this, gs_composite_t **ppcte, gx_device *dev)
{
- if (*ppcte != NULL && (*ppcte)->type->comp_id != GX_COMPOSITOR_OVERPRINT)
- return COMP_ENQUEUE;
- return COMP_REPLACE_PREV;
+ return COMP_ENQUEUE; /* maybe extra work, but these actions are fast */
}
static composite_create_default_compositor_proc(c_overprint_create_default_compositor);
@@ -280,8 +313,7 @@ gs_is_overprint_compositor(const gs_composite_t * pct)
* The data fields reflect entries in the gs_overprint_params_t
* structure. There is no explicit retain_any_comps field, as the current
* setting of this field can be determined by checking the fill_rectangle
- * method. There is also no retain_spot_comps field, as the code will
- * will determine explicitly which components are to be drawn.
+ * method.
*/
typedef struct overprint_device_s {
gx_device_forward_common;
@@ -291,7 +323,11 @@ typedef struct overprint_device_s {
* target color space is not separable and linear. It is also used
* for the devn color values since we may need more than 8 components
*/
- gx_color_index drawn_comps;
+ OP_FS_STATE op_state; /* used to select drawn_comps, fill or stroke */
+ gx_color_index drawn_comps_fill;
+ gx_color_index drawn_comps_stroke; /* pparams->is_fill_color determines which to set */
+ bool retain_none_stroke; /* These are used to know when we can set the procs to forward */
+ bool retain_none_fill;
/*
* The mask of gx_color_index bits to be retained during a drawing
@@ -313,7 +349,8 @@ typedef struct overprint_device_s {
* required. It will be required if depth > 8 and the host processor
* is little-endian.
*/
- gx_color_index retain_mask;
+ gx_color_index retain_mask_fill;
+ gx_color_index retain_mask_stroke;
bool copy_alpha_hl;
@@ -325,6 +362,13 @@ typedef struct overprint_device_s {
gx_device_procs generic_overprint_procs;
gx_device_procs no_overprint_procs;
gx_device_procs sep_overprint_procs;
+
+ /* Due to the setting of stroke and fill overprint we can get in
+ a situation where one makes the device idle. We need to know
+ if that is the case when doing a compositor push even when
+ no parameters have changed */
+ bool is_idle;
+
} overprint_device_t;
gs_private_st_suffix_add0_final( st_overprint_device_t,
@@ -354,6 +398,11 @@ static dev_proc_put_params(overprint_put_params);
static dev_proc_get_page_device(overprint_get_page_device);
static dev_proc_create_compositor(overprint_create_compositor);
static dev_proc_get_color_comp_index(overprint_get_color_comp_index);
+static dev_proc_fill_stroke_path(overprint_fill_stroke_path);
+static dev_proc_fill_path(overprint_fill_path);
+static dev_proc_stroke_path(overprint_stroke_path);
+static dev_proc_text_begin(overprint_text_begin);
+static dev_proc_dev_spec_op(overprint_dev_spec_op);
static const gx_device_procs no_overprint_procs = {
overprint_open_device, /* open_device */
@@ -421,13 +470,16 @@ static const gx_device_procs no_overprint_procs = {
0, /* push_transparency_state */
0, /* pop_transparency_state */
0, /* put_image */
- 0, /* dev_spec_op */
+ overprint_dev_spec_op, /* dev_spec_op */
gx_forward_copy_planes,
0, /* get profile */
0, /* set graphics type tag */
0, /* strip_copy_rop2 */
0, /* strip_tile_rect_devn */
- gx_forward_copy_alpha_hl_color /* copy_alpha_hl_color */
+ gx_forward_copy_alpha_hl_color, /* copy_alpha_hl_color */
+ NULL, /* process_page */\
+ NULL, /* transform_pixel_region */\
+ gx_forward_fill_stroke_path, /* fill_stroke */\
};
/*
@@ -489,8 +541,8 @@ static const gx_device_procs generic_overprint_procs = {
gx_default_copy_alpha, /* copy alpha */
0, /* get_band */
gx_default_copy_rop, /* copy_rop */
- gx_default_fill_path, /* fill_path */
- gx_default_stroke_path, /* stroke_path */
+ overprint_fill_path, /* fill_path */
+ overprint_stroke_path, /* stroke_path */
gx_default_fill_mask, /* fill_mask */
gx_default_fill_trapezoid, /* fill_trapezoid */
gx_default_fill_parallelogram, /* fill_parallelogram */
@@ -507,7 +559,7 @@ static const gx_device_procs generic_overprint_procs = {
0, /* map_color_rgb_alpha */
overprint_create_compositor, /* create_compositor */
0, /* get_hardware_params */
- gx_default_text_begin, /* text_begin */
+ overprint_text_begin, /* text_begin */
0, /* gx_finish_copydevice */
0, /* begin_transparency_group */
0, /* end_transparency_group */
@@ -530,13 +582,16 @@ static const gx_device_procs generic_overprint_procs = {
0, /* push_transparency_state */
0, /* pop_transparency_state */
0, /* put_image */
- 0, /* dev_spec_op */
+ overprint_dev_spec_op, /* dev_spec_op */
gx_forward_copy_planes,
0, /* get profile */
0, /* set graphics type tag */
0, /* strip_copy_rop2 */
0, /* strip_tile_rect_devn */
- gx_forward_copy_alpha_hl_color /* copy_alpha_hl_color */
+ gx_forward_copy_alpha_hl_color, /* copy_alpha_hl_color */
+ NULL, /* process_page */\
+ NULL, /* transform_pixel_region */\
+ overprint_fill_stroke_path, /* fill_stroke */
};
static const gx_device_procs sep_overprint_procs = {
@@ -564,14 +619,14 @@ static const gx_device_procs sep_overprint_procs = {
gx_default_copy_alpha, /* copy alpha */
0, /* get_band */
gx_default_copy_rop, /* copy_rop */
- gx_default_fill_path, /* fill_path */
- gx_default_stroke_path, /* stroke_path */
+ overprint_fill_path, /* fill_path */
+ overprint_stroke_path, /* stroke_path */
gx_default_fill_mask, /* fill_mask */
gx_default_fill_trapezoid, /* fill_trapezoid */
gx_default_fill_parallelogram, /* fill_parallelogram */
gx_default_fill_triangle, /* fill_triangle */
gx_default_draw_thin_line, /* draw_thin_line */
- gx_default_begin_image, /* begin_image */
+ gx_default_begin_image, /* begin_image */
0, /* image_data (obsolete) */
0, /* end_image (obsolete) */
gx_default_strip_tile_rectangle, /* strip_tile_rectangle */
@@ -582,7 +637,7 @@ static const gx_device_procs sep_overprint_procs = {
0, /* map_color_rgb_alpha */
overprint_create_compositor, /* create_compositor */
0, /* get_hardware_params */
- gx_default_text_begin, /* text_begin */
+ overprint_text_begin, /* text_begin */
0, /* gx_finish_copydevice */
0, /* begin_transparency_group */
0, /* end_transparency_group */
@@ -605,13 +660,16 @@ static const gx_device_procs sep_overprint_procs = {
0, /* push_transparency_state */
0, /* pop_transparency_state */
0, /* put_image */
- 0, /* dev_spec_op */
+ overprint_dev_spec_op, /* dev_spec_op */
overprint_copy_planes, /* copy planes */
0, /* get profile */
0, /* set graphics type tag */
0, /* strip_copy_rop2 */
0, /* strip_tile_rect_devn */
- overprint_copy_alpha_hl_color /* copy_alpha_hl_color */
+ overprint_copy_alpha_hl_color, /* copy_alpha_hl_color */
+ NULL, /* process_page */\
+ NULL, /* transform_pixel_region */\
+ overprint_fill_stroke_path, /* fill_stroke */
};
/*
@@ -686,10 +744,12 @@ swap_color_index(int depth, gx_color_index color)
* is separable.
*/
static void
-set_retain_mask(overprint_device_t * opdev)
+set_retain_mask(overprint_device_t * opdev, bool is_fill_color)
{
uchar i, ncomps = opdev->color_info.num_components;
- gx_color_index drawn_comps = opdev->drawn_comps, retain_mask = 0;
+ gx_color_index drawn_comps = is_fill_color ?
+ opdev->drawn_comps_fill : opdev->drawn_comps_stroke;
+ gx_color_index retain_mask = 0;
#if !ARCH_IS_BIG_ENDIAN
int depth = opdev->color_info.depth;
#endif
@@ -702,21 +762,10 @@ set_retain_mask(overprint_device_t * opdev)
if (depth > 8)
retain_mask = swap_color_index(depth, retain_mask);
#endif
- opdev->retain_mask = retain_mask;
-}
-
-/* enlarge mask of non-zero components */
-static gx_color_index
-check_drawn_comps(uchar ncomps, frac cvals[GX_DEVICE_COLOR_MAX_COMPONENTS])
-{
- uchar i;
- gx_color_index mask = 0x1, drawn_comps = 0;
-
- for (i = 0; i < ncomps; i++, mask <<= 1) {
- if (cvals[i] != frac_0)
- drawn_comps |= mask;
- }
- return drawn_comps;
+ if (is_fill_color)
+ opdev->retain_mask_fill = retain_mask;
+ else
+ opdev->retain_mask_stroke = retain_mask;
}
/*
@@ -728,68 +777,83 @@ check_drawn_comps(uchar ncomps, frac cvals[GX_DEVICE_COLOR_MAX_COMPONENTS])
*/
static int
update_overprint_params(
- overprint_device_t * opdev,
- const gs_overprint_params_t * pparams )
+ overprint_device_t* opdev,
+ const gs_overprint_params_t* pparams)
{
- uchar ncomps = opdev->color_info.num_components;
+ /* We can only turn off the overprint compositor if
+ BOTH the stroke and fill op are false. Otherwise
+ we will turn it off when setting one and turn on
+ when setting the other (or vice versa) */
+
+ /* Note if pparams is to set the opdev fill stroke state. Do that now and exit */
+ if (pparams->op_state != OP_STATE_NONE) {
+ opdev->op_state = pparams->op_state;
+ return 0;
+ }
+
+ if_debug4m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] update_overprint_params enter. retain_any_comps = %d, idle = %d, drawn_comps = 0x%x, is_fill_color = %d\n",
+ pparams->retain_any_comps, pparams->idle, pparams->drawn_comps, pparams->is_fill_color);
/* check if overprint is to be turned off */
if (!pparams->retain_any_comps || pparams->idle) {
- /* if fill_rectangle forwards, overprint is already off */
- if (dev_proc(opdev, fill_rectangle) != gx_forward_fill_rectangle)
- memcpy( &opdev->procs,
- &opdev->no_overprint_procs,
- sizeof(opdev->no_overprint_procs) );
+ if (pparams->is_fill_color) {
+ opdev->retain_none_fill = true;
+ opdev->drawn_comps_fill =
+ ((gx_color_index)1 << (opdev->color_info.num_components)) - (gx_color_index)1;
+ } else {
+ opdev->retain_none_stroke = true;
+ opdev->drawn_comps_stroke =
+ ((gx_color_index)1 << (opdev->color_info.num_components)) - (gx_color_index)1;
+ }
+
+ /* Set to forward only if both stroke and fill are not retaining any
+ and if we have not already set it to forward */
+ if (dev_proc(opdev, fill_rectangle) != gx_forward_fill_rectangle &&
+ opdev->retain_none_fill && opdev->retain_none_stroke) {
+ memcpy(&opdev->procs,
+ &opdev->no_overprint_procs,
+ sizeof(opdev->no_overprint_procs));
+ opdev->is_idle = true;
+ if_debug0m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] overprint fill_rectangle set to forward\n");
+ }
+
+ if_debug4m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] update_overprint_params exit. drawn_comps_fill = 0x%x, drawn_comps_stroke = 0x%x, retain_none_fill = %d, retain_none_stroke = %d \n",
+ opdev->drawn_comps_fill, opdev->drawn_comps_stroke, opdev->retain_none_fill, opdev->retain_none_stroke);
return 0;
}
+ opdev->is_idle = false;
/* set the procedures according to the color model */
- if (colors_are_separable_and_linear(&opdev->color_info))
- memcpy( &opdev->procs,
- &opdev->sep_overprint_procs,
- sizeof(opdev->sep_overprint_procs) );
- else
- memcpy( &opdev->procs,
- &opdev->generic_overprint_procs,
- sizeof(opdev->generic_overprint_procs) );
+ if (colors_are_separable_and_linear(&opdev->color_info)) {
+ memcpy(&opdev->procs, &opdev->sep_overprint_procs,
+ sizeof(opdev->sep_overprint_procs));
+ if_debug0m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] overprint procs set to sep\n");
+ } else {
+ memcpy(&opdev->procs, &opdev->generic_overprint_procs,
+ sizeof(opdev->generic_overprint_procs));
+ if_debug0m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] overprint procs set to generic\n");
+ }
- /* see if we need to determine the spot color components */
- if (!pparams->retain_spot_comps) {
- opdev->drawn_comps = pparams->drawn_comps;
+ if (pparams->is_fill_color) {
+ opdev->retain_none_fill = false;
+ opdev->drawn_comps_fill = pparams->drawn_comps;
} else {
- gx_device * dev = (gx_device *)opdev;
- subclass_color_mappings scm;
- frac cvals[GX_DEVICE_COLOR_MAX_COMPONENTS];
- gx_color_index drawn_comps = 0;
- static const frac frac_13 = float2frac(1.0 / 3.0);
-
- scm = get_color_mapping_procs_subclass(dev);
-
- map_gray_subclass(scm, frac_13, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
-
- map_rgb_subclass(scm, 0, frac_13, frac_0, frac_0, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
- map_rgb_subclass(scm, 0, frac_0, frac_13, frac_0, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
- map_rgb_subclass(scm, 0, frac_0, frac_0, frac_13, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
-
- map_cmyk_subclass(scm, frac_13, frac_0, frac_0, frac_0, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
- map_cmyk_subclass(scm, frac_0, frac_13, frac_0, frac_0, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
- map_cmyk_subclass(scm, frac_0, frac_0, frac_13, frac_0, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
- map_cmyk_subclass(scm, frac_0, frac_0, frac_0, frac_13, cvals);
- drawn_comps |= check_drawn_comps(ncomps, cvals);
-
- opdev->drawn_comps = drawn_comps;
+ opdev->retain_none_stroke = false;
+ opdev->drawn_comps_stroke = pparams->drawn_comps;
}
+ if_debug4m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] update_overprint_params exit. drawn_comps_fill = 0x%x, drawn_comps_stroke = 0x%x, retain_none_fill = %d, retain_none_stroke = %d \n",
+ opdev->drawn_comps_fill, opdev->drawn_comps_stroke, opdev->retain_none_fill, opdev->retain_none_stroke);
+
/* if appropriate, update the retain_mask field */
if (colors_are_separable_and_linear(&opdev->color_info))
- set_retain_mask(opdev);
+ set_retain_mask(opdev, pparams->is_fill_color);
return 0;
}
@@ -816,6 +880,7 @@ overprint_open_device(gx_device * dev)
if ((code = gs_opendevice(tdev)) >= 0) {
gx_device_copy_params(dev, tdev);
opdev->copy_alpha_hl = false;
+ opdev->is_idle = false;
}
return code;
}
@@ -893,11 +958,25 @@ overprint_create_compositor(
return gx_default_create_compositor(dev, pcdev, pct, pgs, memory, cdev);
else {
gs_overprint_params_t params = ((const gs_overprint_t *)pct)->params;
- int code;
+ overprint_device_t *opdev = (overprint_device_t *)dev;
+ int code = 0;
+ bool update;
+
+ if (params.is_fill_color)
+ update = (params.drawn_comps != opdev->drawn_comps_fill) ||
+ ((!params.retain_any_comps) != opdev->retain_none_fill);
+ else
+ update = (params.drawn_comps != opdev->drawn_comps_stroke) ||
+ ((!params.retain_any_comps) != opdev->retain_none_stroke);
params.idle = pct->idle;
- /* device must already exist, so just update the parameters */
- code = update_overprint_params((overprint_device_t *)dev, &params);
+ /* device must already exist, so just update the parameters if settings change */
+ if_debug6m(gs_debug_flag_overprint, opdev->memory,
+ "[overprint] overprint_create_compositor test for change. params.idle = %d vs. opdev->is_idle = %d \n params.is_fill_color = %d: params.drawn_comps = 0x%x vs. opdev->drawn_comps_fill = 0x%x OR opdev->drawn_comps_stroke = 0x%x\n",
+ params.idle, opdev->is_idle, params.is_fill_color, params.drawn_comps, opdev->drawn_comps_fill, opdev->drawn_comps_stroke);
+
+ if (update || params.idle != opdev->is_idle || params.op_state != OP_STATE_NONE)
+ code = update_overprint_params(opdev, &params);
if (code >= 0)
*pcdev = dev;
return code;
@@ -925,10 +1004,22 @@ overprint_generic_fill_rectangle(
if (tdev == 0)
return 0;
- else
- return gx_overprint_generic_fill_rectangle(tdev, opdev->drawn_comps, x,
- y, width, height, color,
- dev->memory);
+ else {
+
+ assert(opdev->op_state != 0);
+
+ /* See if we even need to do any overprinting. We have to maintain
+ the compositor active for fill/stroke cases even if we are only
+ doing a fill or a stroke */
+ if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) ||
+ (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke))
+ return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, width, height, color);
+
+ return gx_overprint_generic_fill_rectangle(tdev,
+ opdev->op_state == OP_STATE_FILL ?
+ opdev->drawn_comps_fill : opdev->drawn_comps_stroke,
+ x, y, width, height, color, dev->memory);
+ }
}
static int
@@ -973,7 +1064,7 @@ overprint_copy_planes(gx_device * dev, const byte * data, int data_x, int raster
uchar num_comps;
uchar k,j;
gs_memory_t * mem = dev->memory;
- gx_color_index comps = opdev->drawn_comps;
+ gx_color_index comps = opdev->op_state == OP_STATE_FILL ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke;
byte *curr_data = (byte *) data + data_x;
int row, offset;
@@ -1015,7 +1106,6 @@ overprint_copy_planes(gx_device * dev, const byte * data, int data_x, int raster
/* step through the height */
row = 0;
while (h-- > 0 && code >= 0) {
- comps = opdev->drawn_comps;
gb_rect.p.y = y++;
gb_rect.q.y = y;
offset = row * raster_in + data_x;
@@ -1087,7 +1177,7 @@ overprint_fill_rectangle_hl_color(gx_device *dev,
int x, y, w, h;
uchar k, j;
gs_memory_t * mem = dev->memory;
- gx_color_index comps = opdev->drawn_comps;
+ gx_color_index comps;
gx_color_index mask;
int shift;
int deep;
@@ -1095,6 +1185,15 @@ overprint_fill_rectangle_hl_color(gx_device *dev,
if (tdev == 0)
return 0;
+ assert(opdev->op_state != 0);
+
+ /* See if we even need to do any overprinting. We have to maintain
+ the compositor active for fill/stroke cases even if we are only
+ doing a fill or a stroke */
+ if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) ||
+ (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke))
+ return (*dev_proc(tdev, fill_rectangle_hl_color)) (tdev, rect, pgs, pdcolor, pcpath);
+
depth = tdev->color_info.depth;
num_comps = tdev->color_info.num_components;
@@ -1133,9 +1232,9 @@ overprint_fill_rectangle_hl_color(gx_device *dev,
/* step through the height */
while (h-- > 0 && code >= 0) {
- comps = opdev->drawn_comps;
gb_rect.p.y = y++;
gb_rect.q.y = y;
+ comps = opdev->op_state == OP_STATE_FILL ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke;
/* And now through each plane */
for (k = 0; k < tdev->color_info.num_components; k++) {
/* First set the params to zero for all planes except the one we want */
@@ -1189,6 +1288,15 @@ overprint_sep_fill_rectangle(
else {
int depth = tdev->color_info.depth;
+ assert(opdev->op_state != 0);
+
+ /* See if we even need to do any overprinting. We have to maintain
+ the compositor active for fill/stroke cases even if we are only
+ doing a fill or a stroke */
+ if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) ||
+ (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke))
+ return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, width, height, color);
+
/*
* Swap the color index into the order required by a byte-oriented
* bitmap. This is required only for littl-endian processors, and
@@ -1214,16 +1322,113 @@ overprint_sep_fill_rectangle(
* depth < 8 * sizeof(mono_fill_chunk).
*/
if ( depth <= 8 * sizeof(mono_fill_chunk) && (depth & (depth - 1)) == 0)
- return gx_overprint_sep_fill_rectangle_1(tdev, opdev->retain_mask,
- x, y, width, height,
- color, dev->memory);
+ return gx_overprint_sep_fill_rectangle_1(tdev, opdev->op_state == OP_STATE_FILL ?
+ opdev->retain_mask_fill : opdev->retain_mask_stroke,
+ x, y, width, height,
+ color, dev->memory);
else
- return gx_overprint_sep_fill_rectangle_2(tdev,opdev->retain_mask,
- x, y, width, height,
- color, dev->memory);
+ return gx_overprint_sep_fill_rectangle_2(tdev, opdev->op_state == OP_STATE_FILL ?
+ opdev->retain_mask_fill : opdev->retain_mask_stroke,
+ x, y, width, height,
+ color, dev->memory);
}
}
+/* We need this to ensure the device knows we are doing a fill */
+static int
+overprint_fill_path(gx_device* pdev, const gs_gstate* pgs,
+ gx_path* ppath, const gx_fill_params* params_fill,
+ const gx_device_color* pdcolor, const gx_clip_path* pcpath)
+{
+ overprint_device_t* opdev = (overprint_device_t*)pdev;
+
+ opdev->op_state = OP_STATE_FILL;
+ return gx_default_fill_path(pdev, pgs, ppath, params_fill,
+ pdcolor, pcpath);
+}
+
+/* We need this to ensure the device knows we are doing a stroke */
+static int
+overprint_stroke_path(gx_device* pdev, const gs_gstate* pgs,
+ gx_path* ppath, const gx_stroke_params* params_stroke,
+ const gx_device_color* pdcolor, const gx_clip_path* pcpath)
+{
+ overprint_device_t* opdev = (overprint_device_t*)pdev;
+ int code;
+
+ opdev->op_state = OP_STATE_STROKE;
+
+ /* Stroke methods use fill path so set that to default to
+ avoid mix up of is_fill_color */
+ opdev->procs.fill_path = gx_default_fill_path;
+ code = gx_default_stroke_path(pdev, pgs, ppath, params_stroke,
+ pdcolor, pcpath);
+ opdev->procs.fill_path = overprint_fill_path;
+
+ return code;
+}
+
+/*
+ * Cannot use default_fill_stroke_path because we need to set the is_fill_color
+ */
+static int
+overprint_fill_stroke_path(gx_device * pdev, const gs_gstate * pgs,
+ gx_path * ppath,
+ const gx_fill_params * params_fill,
+ const gx_device_color * pdevc_fill,
+ const gx_stroke_params * params_stroke,
+ const gx_device_color * pdevc_stroke,
+ const gx_clip_path * pcpath)
+{
+ int code;
+ overprint_device_t *opdev = (overprint_device_t *)pdev;
+
+ opdev->op_state = OP_STATE_FILL;
+ code = dev_proc(pdev, fill_path)(pdev, pgs, ppath, params_fill, pdevc_fill, pcpath);
+ if (code < 0)
+ return code;
+
+ /* Set up for stroke */
+ opdev->op_state = OP_STATE_STROKE;
+ code = dev_proc(pdev, stroke_path)(pdev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
+ return code;
+}
+
+/* We need to make sure we are set up properly based upon the text mode */
+static int
+overprint_text_begin(gx_device* dev, gs_gstate* pgs,
+ const gs_text_params_t* text, gs_font* font,
+ gx_path* path, const gx_device_color* pdcolor,
+ const gx_clip_path* pcpath,
+ gs_memory_t* mem, gs_text_enum_t** ppte)
+{
+ overprint_device_t* opdev = (overprint_device_t*)dev;
+
+ if (pgs->text_rendering_mode == 0)
+ opdev->op_state = OP_STATE_FILL;
+ else if (pgs->text_rendering_mode == 1)
+ opdev->op_state = OP_STATE_STROKE;
+
+ return gx_default_text_begin(dev, pgs, text, font,
+ path, pdcolor, pcpath, mem, ppte);
+}
+
+static int
+overprint_dev_spec_op(gx_device* pdev, int dev_spec_op,
+ void* data, int size)
+{
+ overprint_device_t* opdev = (overprint_device_t*)pdev;
+ gx_device* tdev = opdev->target;
+
+ if (tdev == 0)
+ return 0;
+
+ if (dev_spec_op == gxdso_overprint_active)
+ return !opdev->is_idle;
+
+ return dev_proc(tdev, dev_spec_op)(tdev, dev_spec_op, data, size);
+}
+
/* complete a procedure set */
static void
fill_in_procs(gx_device_procs * pprocs)
@@ -1256,14 +1461,6 @@ fill_in_procs(gx_device_procs * pprocs)
* Note that this routine will be called only if the device is not already
* an overprint compositor. Hence, if pct->params.retain_any_comps is
* false, we can just return.
- *
- * We also suppress use of overprint if the current device color model has only
- * a single component. In this case overprint mode is inapplicable (it applies
- * only to CMYK devices), and nothing can possibly be gained by using overprint.
- * More significantly, this cause avoids erroneous use of overprint when a
- * mask caching device is the current device, which would otherwise require
- * elaborate special handling in the caching device create_compositor
- * procedure.
*/
static int
c_overprint_create_default_compositor(
@@ -1288,17 +1485,17 @@ c_overprint_create_default_compositor(
}
/* build the overprint device */
- opdev = gs_alloc_struct_immovable( mem,
- overprint_device_t,
- &st_overprint_device_t,
- "create overprint compositor" );
+ opdev = gs_alloc_struct_immovable(mem,
+ overprint_device_t,
+ &st_overprint_device_t,
+ "create overprint compositor" );
*popdev = (gx_device *)opdev;
if (opdev == NULL)
return_error(gs_error_VMerror);
- gx_device_init( (gx_device *)opdev,
- (const gx_device *)&gs_overprint_device,
- mem,
- false );
+ gx_device_init((gx_device *)opdev,
+ (const gx_device *)&gs_overprint_device,
+ mem,
+ false );
memcpy(&opdev->no_overprint_procs,
&no_overprint_procs,
sizeof(no_overprint_procs));
@@ -1323,6 +1520,10 @@ c_overprint_create_default_compositor(
params = ovrpct->params;
params.idle = ovrpct->idle;
+ /* Initialize the stroke and fill states */
+ opdev->retain_none_fill = true;
+ opdev->retain_none_stroke = true;
+
/* set up the overprint parameters */
- return update_overprint_params( opdev, &params);
+ return update_overprint_params(opdev, &params);
}
diff --git a/base/gsovrc.h b/base/gsovrc.h
index 4df2df224..ccef5f5c2 100644
--- a/base/gsovrc.h
+++ b/base/gsovrc.h
@@ -216,6 +216,12 @@
* closing of a device is not itself used as an error indication.
*/
+typedef enum {
+ OP_STATE_NONE = 0,
+ OP_STATE_FILL,
+ OP_STATE_STROKE,
+} OP_FS_STATE;
+
typedef struct gs_overprint_params_s gs_overprint_params_t;
struct gs_overprint_params_s {
@@ -227,38 +233,12 @@ struct gs_overprint_params_s {
* are ignored, and the compositor does nothing with respect to rendering
* (it doesn't even impose a performance penalty).
*
- * If this field is true, the retain_spot_comps and potentially the
- * retained_comps fields should be initialized.
*
* Note that this field may be false even if overprint is true. This
* would be the case if the current color space was a Separation color
* space with the component "All".
*/
- bool retain_any_comps;
-
- /*
- * Are spot (non-process) color component values retained?
- *
- * If overprint is true, this field will be true for all color spaces
- * other than Separation/DeviceN color spaces.
- *
- * The overprint compositor will itself determine what constitutes a
- * process color. This is done by using the color space mapping
- * routines for the target device for all three standard device
- * color spaces (DeviceGray, DeviceRGB, and DeviceCMYK) and the
- * set of all possible colors with individual components either 0
- * or 1. Any color model component which is mapped to 0 for all of
- * these cases is considered a spot color.
- *
- * If this field is true, the drawn_comps field (see below) is ignored.
- *
- * NB: This field should not be used if the DeviceCMYK color space
- * is being used with a DeviceCMYK color model (which may have
- * additional spot colors). Such a color model must explicitly
- * list the set of drawn components, so as to support overprint
- * mode.
- */
- bool retain_spot_comps;
+ bool retain_any_comps;
/*
* Don't we print anything with overprint ?
@@ -274,6 +254,9 @@ struct gs_overprint_params_s {
* it is to be left unaffected.
*/
gx_color_index drawn_comps;
+ bool is_fill_color; /* This tells us what the current color is for our set up */
+ OP_FS_STATE op_state; /* This sets the state of the device for an upcoming command */
+ bool effective_opm; /* PDF14 needs this information for its compatible blend mode */
};
/*
diff --git a/base/gspaint.c b/base/gspaint.c
index c8a982341..13836061b 100644
--- a/base/gspaint.c
+++ b/base/gspaint.c
@@ -26,6 +26,7 @@
#include "gspath.h"
#include "gzpath.h"
#include "gxpaint.h"
+#include "gxpcolor.h" /* for do_fill_stroke */
#include "gzstate.h"
#include "gxdevice.h"
#include "gxdevmem.h"
@@ -36,6 +37,7 @@
#include "gxdevsop.h"
#include "gsicc_cms.h"
#include "gdevepo.h"
+#include "assert_.h"
/* Define the nominal size for alpha buffers. */
#define abuf_nominal_SMALL 500
@@ -198,7 +200,7 @@ scale_dash_pattern(gs_gstate * pgs, double scale)
Returns -ve for error
*/
static int
-alpha_buffer_init(gs_gstate * pgs, fixed extra_x, fixed extra_y, int alpha_bits,
+alpha_buffer_init(gs_gstate * pgs, fixed extra_x, fixed extra_y, int alpha_bits,
bool devn)
{
gx_device *dev = gs_currentdevice_inline(pgs);
@@ -303,6 +305,21 @@ static int do_fill(gs_gstate *pgs, int rule)
code = gs_gstate_color_load(pgs);
if (code < 0)
return code;
+
+ if (pgs->overprint || (!pgs->overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ gs_overprint_params_t op_params = { 0 };
+
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Fill Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+
+ op_params.op_state = OP_STATE_FILL;
+ gs_gstate_update_overprint(pgs, &op_params);
+ }
+
abits = 0;
{
gx_device_color *col = gs_currentdevicecolor_inline(pgs);
@@ -379,6 +396,7 @@ do_stroke(gs_gstate * pgs)
{
int code, abits, acode, rcode = 0;
bool devn;
+ bool is_fill_correct = true;
/* We need to distinguish text from vectors to set the object tag.
@@ -407,6 +425,34 @@ do_stroke(gs_gstate * pgs)
code = gs_gstate_color_load(pgs);
if (code < 0)
return code;
+
+
+ if (pgs->stroke_overprint || (!pgs->stroke_overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ gs_overprint_params_t op_params = { 0 };
+
+ /* PS2 does not have the concept of fill and stroke colors. Here we need to possibly correct
+ for that in the graphic state during this operation */
+ if (pgs->is_fill_color) {
+ is_fill_correct = false;
+ pgs->is_fill_color = false;
+ }
+
+
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Stroke Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0) {
+ if (!is_fill_correct) {
+ pgs->is_fill_color = true;
+ }
+ return code;
+ }
+
+ op_params.op_state = OP_STATE_STROKE;
+ gs_gstate_update_overprint(pgs, &op_params);
+ }
+
abits = 0;
{
gx_device_color *col = gs_currentdevicecolor_inline(pgs);
@@ -437,10 +483,18 @@ do_stroke(gs_gstate * pgs)
pgs->fill_adjust.x + extra_adjust,
pgs->fill_adjust.y + extra_adjust,
abits, devn);
- if (acode == 2) /* Special code meaning no fill required */
+ if (acode == 2) { /* Special code meaning no fill required */
+ if (!is_fill_correct) {
+ pgs->is_fill_color = true;
+ }
return 0;
- if (acode < 0)
+ }
+ if (acode < 0) {
+ if (!is_fill_correct) {
+ pgs->is_fill_color = true;
+ }
return acode;
+ }
gs_setlinewidth(pgs, new_width);
scale_dash_pattern(pgs, scale);
gs_setflat(pgs, orig_flatness * scale);
@@ -465,6 +519,10 @@ do_stroke(gs_gstate * pgs)
code = gx_stroke_fill(pgs->path, pgs);
if (code >= 0 && rcode < 0)
code = rcode;
+
+ if (!is_fill_correct) {
+ pgs->is_fill_color = true;
+ }
return code;
}
@@ -539,3 +597,224 @@ gs_strokepath2(gs_gstate * pgs)
{
return gs_strokepath_aux(pgs, false);
}
+
+static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
+{
+ int code, abits, acode = 0, rcode = 0;
+ bool devn;
+ float orig_width, scale, orig_flatness;
+
+ /* It is either our first time, or the stroke was a pattern and
+ we are coming back from the error if restart < 1 (0 is first
+ time, 1 stroke is set, and we only need to finish out fill */
+ if (pgs->is_fill_color)
+ gs_swapcolors_quick(pgs);
+
+ if (*restart < 1) {
+
+ /* We need to distinguish text from vectors to set the object tag.
+
+ To make that determination, we check for the show graphics state being stored
+ in the current graphics state. This works even in the case of a glyph from a
+ Type 3 Postscript/PDF font which has multiple, nested gsave/grestore pairs in
+ the BuildGlyph/BuildChar procedure. Also, it works in the case of operating
+ without a glyph cache or bypassing the cache because the glyph is too large or
+ the cache being already full.
+
+ Note that it doesn't work for a construction like:
+ "(xyz) true charpath fill/stroke"
+ where the show machinations have completed before we get to the fill operation.
+ This has implications for how we handle PDF text rendering modes 1 and 2. To
+ handle that, we'll have to add a flag to the path structure, or to the path
+ segment structure (depending on how fine grained we require it to be).
+ */
+ if (pgs->show_gstate == NULL)
+ ensure_tag_is_set(pgs, pgs->device, GS_PATH_TAG); /* NB: may unset_dev_color */
+ else
+ ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
+
+ /* if we are at restart == 0, we set the stroke color. */
+ code = gx_set_dev_color(pgs);
+ if (code != 0)
+ return code; /* may be gs_error_Remap_color or real error */
+ code = gs_gstate_color_load(pgs);
+ if (code < 0)
+ return code;
+ /* If this was a pattern color, make sure and lock it in the pattern_cache */
+ if (gx_dc_is_pattern1_color(gs_currentdevicecolor_inline(pgs))) {
+ gs_id id = gs_currentdevicecolor_inline(pgs)->colors.pattern.p_tile->id;
+
+ code = gx_pattern_cache_entry_set_lock(pgs, id, true);
+ if (code < 0)
+ return code; /* lock failed -- tile not in cache? */
+ }
+ }
+
+ if (pgs->stroke_overprint || (!pgs->stroke_overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] StrokeFill Stroke Set Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+ }
+ *restart = 1; /* finished, successfully with stroke_color */
+
+ gs_swapcolors_quick(pgs); /* switch to fill color */
+
+ /* Have to set the fill color too */
+ if (pgs->show_gstate == NULL)
+ ensure_tag_is_set(pgs, pgs->device, GS_PATH_TAG); /* NB: may unset_dev_color */
+ else
+ ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
+
+ code = gx_set_dev_color(pgs);
+ if (code != 0) {
+ return code;
+ }
+ code = gs_gstate_color_load(pgs);
+ if (code < 0) {
+ /* color is set for fill, but a failure here is a problem */
+ /* i.e., something other than error_Remap_Color */
+ *restart = 2; /* we shouldn't re-enter with '2' */
+ goto out;
+ }
+
+ if (pgs->overprint || (!pgs->overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
+ gxdso_overprint_active, NULL, 0))) {
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] StrokeFill Fill Set Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ goto out; /* fatal */
+ }
+
+ abits = 0;
+ {
+ gx_device_color *col_fill = gs_currentdevicecolor_inline(pgs);
+ gx_device_color *col_stroke = gs_altdevicecolor_inline(pgs);
+ devn = color_is_devn(col_fill) && color_is_devn(col_stroke);
+ /* could be devn and masked_devn */
+ if (color_is_pure(col_fill) || color_is_pure(col_stroke) || devn)
+ abits = alpha_buffer_bits(pgs);
+ }
+ if (abits > 1) {
+ /*
+ * Expand the bounding box by the line width.
+ * This is expensive to compute, so we only do it
+ * if we know we're going to buffer.
+ */
+ float new_width;
+ fixed extra_adjust;
+ float xxyy = fabs(pgs->ctm.xx) + fabs(pgs->ctm.yy);
+ float xyyx = fabs(pgs->ctm.xy) + fabs(pgs->ctm.yx);
+ gs_logical_operation_t orig_lop = pgs->log_op;
+ pgs->log_op |= lop_pdf14; /* Force stroking to happen all in 1 go */
+ scale = (float)(1 << (abits / 2));
+ orig_width = gs_currentlinewidth(pgs);
+ new_width = orig_width * scale;
+ extra_adjust =
+ float2fixed(max(xxyy, xyyx) * new_width / 2);
+ orig_flatness = gs_currentflat(pgs);
+
+ /* Scale up the line width, dash pattern, and flatness. */
+ if (extra_adjust < fixed_1)
+ extra_adjust = fixed_1;
+ acode = alpha_buffer_init(pgs,
+ pgs->fill_adjust.x + extra_adjust,
+ pgs->fill_adjust.y + extra_adjust,
+ abits, devn);
+ if (acode == 2) /* Special case for no fill required */
+ goto out;
+ if (acode < 0)
+ goto out;
+ gs_setlinewidth(pgs, new_width);
+ scale_dash_pattern(pgs, scale);
+ gs_setflat(pgs, orig_flatness * scale);
+ pgs->log_op = orig_lop;
+ } else
+ acode = 0;
+ code = gx_fill_stroke_path(pgs, rule);
+ if (abits > 1)
+ {
+ gs_setlinewidth(pgs, orig_width);
+ scale_dash_pattern(pgs, 1.0 / scale);
+ gs_setflat(pgs, orig_flatness);
+ acode = alpha_buffer_release(pgs, code >= 0);
+ }
+out:
+ if (gx_dc_is_pattern1_color(gs_altdevicecolor_inline(pgs))) {
+ gs_id id = gs_altdevicecolor_inline(pgs)->colors.pattern.p_tile->id;
+
+ rcode = gx_pattern_cache_entry_set_lock(pgs, id, false);
+ if (rcode < 0)
+ return rcode; /* unlock failed -- shouldn't be possible */
+ }
+ if (code >= 0 && acode < 0)
+ code = acode;
+ return code;
+}
+
+/* Fill the current path using a specified rule. */
+static int
+fill_stroke_with_rule(gs_gstate * pgs, int rule, int *restart)
+{
+ int code;
+
+ /* If we're inside a charpath, just merge the current path */
+ /* into the parent's path. */
+ if (pgs->in_charpath) {
+ /* If we're rendering a glyph cached, the show machinery decides
+ * whether to actually image it on the output or not, but uncached
+ * will render directly to the output, so for text rendering
+ * mode 3, we have to short circuit it here, but keep the
+ * current point
+ */
+ *restart = 0;
+ code = gx_path_add_char_path(pgs->show_gstate->path, pgs->path,
+ pgs->in_charpath);
+ if (code < 0)
+ return code;
+ if (pgs->in_charpath == cpm_true_charpath) {
+ /*
+ * A stroke inside a true charpath should do the
+ * equivalent of strokepath.
+ */
+ code = gs_strokepath(pgs);
+ if (code < 0)
+ return code;
+ code = gx_path_add_char_path(pgs->show_gstate->path, pgs->path,
+ pgs->in_charpath);
+ if (code < 0)
+ return code;
+ }
+ }
+ else if (gs_is_null_device(pgs->device) ||
+ (pgs->show_gstate && pgs->text_rendering_mode == 3 &&
+ pgs->in_cachedevice == CACHE_DEVICE_NOT_CACHING)) {
+ /* Text Rendering Mode = 3 => Neither stroke, nor fill */
+ /* Handle separately to prevent gs_gstate_color_load - bug 688308. */
+ *restart = 0;
+ gs_newpath(pgs);
+ code = 0;
+ } else {
+ code = do_fill_stroke(pgs, rule, restart);
+ if (code >= 0)
+ gs_newpath(pgs);
+ }
+ return code;
+}
+/* Fill using the winding number rule */
+int
+gs_fillstroke(gs_gstate * pgs, int *restart)
+{
+ pgs->device->sgr.stroke_stored = false;
+ return fill_stroke_with_rule(pgs, gx_rule_winding_number, restart);
+}
+/* Fill using the even/odd rule */
+int
+gs_eofillstroke(gs_gstate * pgs, int *restart)
+{
+ pgs->device->sgr.stroke_stored = false;
+ return fill_stroke_with_rule(pgs, gx_rule_even_odd, restart);
+}
diff --git a/base/gspaint.h b/base/gspaint.h
index 19a1040dd..c95b6b48b 100644
--- a/base/gspaint.h
+++ b/base/gspaint.h
@@ -28,7 +28,9 @@ int gs_erasepage(gs_gstate *),
gs_fillpage(gs_gstate *),
gs_fill(gs_gstate *),
gs_eofill(gs_gstate *),
- gs_stroke(gs_gstate *);
+ gs_stroke(gs_gstate *),
+ gs_fillstroke(gs_gstate * pgs, int *restart),
+ gs_eofillstroke(gs_gstate * pgs, int *restart);
/* Image tracing */
int gs_imagepath(gs_gstate *, int, int, const byte *);
diff --git a/base/gspath.c b/base/gspath.c
index d55d5ffec..2080d2c4f 100644
--- a/base/gspath.c
+++ b/base/gspath.c
@@ -329,26 +329,28 @@ static int common_clip(gs_gstate *, int);
The transparency group will be the intersection of the path and clipping
path */
int
-gx_curr_bbox(gs_gstate * pgs, gs_rect *bbox, gs_bbox_comp_t comp_type)
+gx_curr_fixed_bbox(gs_gstate * pgs, gs_fixed_rect *bbox, gs_bbox_comp_t comp_type)
{
- gx_clip_path *clip_path;
int code;
+ gx_clip_path *clip_path;
gs_fixed_rect path_bbox;
int expansion_code;
bool include_path = true;
gs_fixed_point expansion;
code = gx_effective_clip_path(pgs, &clip_path);
- if (code < 0) return code;
+ if (code < 0 || clip_path == NULL) {
+ bbox->p.x = bbox->p.y = bbox->q.x = bbox->q.y = 0;
+ return (code < 0) ? code : gs_error_unknownerror;
+ } else {
+ *bbox = clip_path->outer_box;
+ }
if (comp_type == NO_PATH) {
- bbox->p.x = fixed2float(clip_path->outer_box.p.x);
- bbox->p.y = fixed2float(clip_path->outer_box.p.y);
- bbox->q.x = fixed2float(clip_path->outer_box.q.x);
- bbox->q.y = fixed2float(clip_path->outer_box.q.y);
- return 0;
+ return 0;
}
code = gx_path_bbox(pgs->path, &path_bbox);
- if (code < 0) return code;
+ if (code < 0)
+ return code;
if (comp_type == PATH_STROKE) {
/* Handle any stroke expansion of our bounding box */
expansion_code = gx_stroke_path_expansion(pgs, pgs->path, &expansion);
@@ -364,22 +366,25 @@ gx_curr_bbox(gs_gstate * pgs, gs_rect *bbox, gs_bbox_comp_t comp_type)
}
}
if (include_path) {
- rect_intersect(path_bbox, clip_path->outer_box);
- /* clip path and drawing path */
- bbox->p.x = fixed2float(path_bbox.p.x);
- bbox->p.y = fixed2float(path_bbox.p.y);
- bbox->q.x = fixed2float(path_bbox.q.x);
- bbox->q.y = fixed2float(path_bbox.q.y);
- } else {
- /* clip path only */
- bbox->p.x = fixed2float(clip_path->outer_box.p.x);
- bbox->p.y = fixed2float(clip_path->outer_box.p.y);
- bbox->q.x = fixed2float(clip_path->outer_box.q.x);
- bbox->q.y = fixed2float(clip_path->outer_box.q.y);
+ rect_intersect(*bbox, path_bbox);
}
return 0;
}
+/* A variation of the above that returns a gs_rect (double) bbox */
+int
+gx_curr_bbox(gs_gstate * pgs, gs_rect *bbox, gs_bbox_comp_t comp_type)
+{
+ gs_fixed_rect curr_fixed_bbox;
+
+ gx_curr_fixed_bbox(pgs, &curr_fixed_bbox, comp_type);
+ bbox->p.x = fixed2float(curr_fixed_bbox.p.x);
+ bbox->p.y = fixed2float(curr_fixed_bbox.p.y);
+ bbox->q.x = fixed2float(curr_fixed_bbox.q.x);
+ bbox->q.y = fixed2float(curr_fixed_bbox.q.y);
+ return 0;
+}
+
/*
* Return the effective clipping path of a graphics state. Sometimes this
* is the intersection of the clip path and the view clip path; sometimes it
@@ -395,7 +400,7 @@ gx_effective_clip_path(gs_gstate * pgs, gx_clip_path ** ppcpath)
(pgs->view_clip == 0 || pgs->view_clip->rule == 0 ? gs_no_id :
pgs->view_clip->id);
- if (gs_device_is_memory(pgs->device)) {
+ if (pgs->device == NULL || gs_device_is_memory(pgs->device) || pgs->clip_path == NULL) {
*ppcpath = pgs->clip_path;
return 0;
}
diff --git a/base/gspcolor.c b/base/gspcolor.c
index 350682c6e..e96331b1f 100644
--- a/base/gspcolor.c
+++ b/base/gspcolor.c
@@ -281,7 +281,7 @@ gx_set_overprint_Pattern(const gs_color_space * pcs, gs_gstate * pgs)
if (!pgs->overprint) {
params.retain_any_comps = false;
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
return gs_gstate_update_overprint(pgs, &params);
}
return 0;
diff --git a/base/gsptype1.c b/base/gsptype1.c
index 8fe977f49..ccd723e66 100644
--- a/base/gsptype1.c
+++ b/base/gsptype1.c
@@ -704,7 +704,7 @@ gs_pattern1_set_color(const gs_client_color * pcc, gs_gstate * pgs)
gs_overprint_params_t params;
params.retain_any_comps = false;
- pgs->effective_overprint_mode = 0;
+ params.effective_opm = pgs->color[0].effective_opm = 0;
return gs_gstate_update_overprint(pgs, &params);
}
}
@@ -1628,6 +1628,7 @@ typedef struct gx_dc_serialized_tile_s {
} gx_dc_serialized_tile_t;
enum {
+ TILE_IS_LOCKED = 0x80000000,
TILE_HAS_OVERLAP = 0x40000000,
TILE_IS_SIMPLE = 0x20000000,
TILE_USES_TRANSP = 0x10000000,
@@ -1672,7 +1673,8 @@ gx_dc_pattern_write_raster(gx_color_tile *ptile, int64_t offset, byte *data,
buf.flags = ptile->depth
| (ptile->tiling_type<<TILE_TYPE_SHIFT)
| (ptile->is_simple ? TILE_IS_SIMPLE : 0)
- | (ptile->has_overlap ? TILE_HAS_OVERLAP : 0);
+ | (ptile->has_overlap ? TILE_HAS_OVERLAP : 0)
+ | (ptile->is_locked ? TILE_IS_LOCKED : 0);
if (sizeof(buf) > left) {
/* For a while we require the client to provide enough buffer size. */
return_error(gs_error_unregistered); /* Must not happen. */
@@ -1764,7 +1766,8 @@ gx_dc_pattern_trans_write_raster(gx_color_tile *ptile, int64_t offset, byte *dat
| TILE_USES_TRANSP
| (ptile->tiling_type<<TILE_TYPE_SHIFT)
| (ptile->is_simple ? TILE_IS_SIMPLE : 0)
- | (ptile->has_overlap ? TILE_HAS_OVERLAP : 0);
+ | (ptile->has_overlap ? TILE_HAS_OVERLAP : 0)
+ | (ptile->is_locked ? TILE_IS_LOCKED : 0);
buf.step_matrix = ptile->step_matrix;
buf.bbox = ptile->bbox;
buf.blending_mode = ptile->blending_mode;
@@ -1889,6 +1892,7 @@ gx_dc_pattern_write(
| (ptile->tiling_type<<TILE_TYPE_SHIFT)
| (ptile->is_simple ? TILE_IS_SIMPLE : 0)
| (ptile->has_overlap ? TILE_HAS_OVERLAP : 0)
+ | (ptile->is_locked ? TILE_IS_LOCKED : 0)
| (ptile->cdev->common.page_uses_transparency ? TILE_USES_TRANSP : 0);
buf.blending_mode = ptile->blending_mode; /* in case tile has transparency */
if (sizeof(buf) > left) {
@@ -2114,8 +2118,9 @@ gx_dc_pattern_read(
ptile->tiling_type = (buf.flags & TILE_TYPE_MASK)>>TILE_TYPE_SHIFT;
ptile->is_simple = !!(buf.flags & TILE_IS_SIMPLE);
ptile->has_overlap = !!(buf.flags & TILE_HAS_OVERLAP);
+ ptile->is_locked = !!(buf.flags & TILE_IS_LOCKED);
ptile->blending_mode = buf.blending_mode;
- ptile->is_dummy = 0;
+ ptile->is_dummy = false;
if (!(buf.flags & TILE_IS_CLIST)) {
diff --git a/base/gsptype2.c b/base/gsptype2.c
index 9bcf8af63..6573dee90 100644
--- a/base/gsptype2.c
+++ b/base/gsptype2.c
@@ -204,6 +204,9 @@ gs_pattern2_set_color(const gs_client_color * pcc, gs_gstate * pgs)
int code;
uchar k, num_comps;
+ /* Shading patterns can't use opm */
+ pgs->color[!pgs->is_fill_color].effective_opm = 0;
+
pinst->saved->overprint_mode = pgs->overprint_mode;
pinst->saved->overprint = pgs->overprint;
diff --git a/base/gsstate.c b/base/gsstate.c
index a7a61618f..16815fee7 100644
--- a/base/gsstate.c
+++ b/base/gsstate.c
@@ -233,6 +233,9 @@ gs_gstate_alloc(gs_memory_t * mem)
if (code < 0)
goto fail;
gs_setalpha(pgs, 1.0);
+ gs_setfillconstantalpha(pgs, 1.0);
+ gs_setstrokeconstantalpha(pgs, 1.0);
+ gs_setalphaisshape(pgs, false);
gs_settransfer(pgs, gs_identity_transfer);
gs_setflat(pgs, 1.0);
gs_setfilladjust(pgs, 0.3, 0.3);
@@ -366,7 +369,6 @@ gs_grestore_only(gs_gstate * pgs)
gs_gstate tmp_gstate;
void *pdata = pgs->client_data;
void *sdata;
- bool prior_overprint = pgs->overprint;
if_debug2m('g', pgs->memory, "[g]grestore 0x%lx, level was %d\n",
(ulong) saved, pgs->level);
@@ -388,11 +390,6 @@ gs_grestore_only(gs_gstate * pgs)
*saved = tmp_gstate; /* restore "freed" state (pointers zeroed after contents freed) */
gs_free_object(pgs->memory, saved, "gs_grestore");
- /* update the overprint compositor, if necessary */
- if (prior_overprint || pgs->overprint)
- {
- return gs_do_set_overprint(pgs);
- }
return 0;
}
@@ -521,12 +518,7 @@ gs_setgstate(gs_gstate * pgs, const gs_gstate * pfrom)
pgs->view_clip = view_clip;
pgs->show_gstate =
(pgs->show_gstate == pfrom ? pgs : saved_show);
-
- /* update the overprint compositor, unconditionally. Unlike grestore, this */
- /* may skip over states where overprint was set, so the prior state can */
- /* not be relied on to avoid this call. setgstate is not as commonly used */
- /* as grestore, so the overhead of the compositor call is acceptable. */
- return(gs_do_set_overprint(pgs));
+ return 0;
}
/* Get the allocator pointer of a graphics state. */
@@ -632,28 +624,39 @@ gs_do_set_overprint(gs_gstate * pgs)
if (cs_num_components(pcs) < 0 && pcc->pattern != 0)
code = pcc->pattern->type->procs.set_color(pcc, pgs);
- else
- {
+ else {
+ gx_device* dev = pgs->device;
+ cmm_dev_profile_t* dev_profile;
+
+ dev_proc(dev, get_profile)(dev, &dev_profile);
+ if (!dev_profile->sim_overprint || dev_profile->device_profile[0]->data_cs != gsCMYK)
+ return code;
+
/* The spaces that do not allow opm (e.g. ones that are not ICC or DeviceCMYK)
will blow away any true setting later. But we have to be prepared
- in case this is an CMYK ICC space for example. Hence we set effective mode
+ in case this is a CMYK ICC space for example. Hence we set effective mode
to mode here (Bug 698721)*/
- pgs->effective_overprint_mode = pgs->overprint_mode;
+ pgs->color[0].effective_opm = pgs->overprint_mode;
+
+ if_debug2m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] gs_do_set_overprint. Preset effective mode. pgs->color[0].effective_opm = %d pgs->color[1].effective_opm = %d\n",
+ pgs->color[0].effective_opm, pgs->color[1].effective_opm);
+
pcs->type->set_overprint(pcs, pgs);
}
return code;
}
-/* setoverprint */
+/* setoverprint (non-stroke case) interpreter code
+ ensures that this is called when appropriate. This
+ should only be coming when we are doing PS files.
+ As they don't have separate stroke and fill overprint
+ controls */
void
gs_setoverprint(gs_gstate * pgs, bool ovp)
{
- bool prior_ovp = pgs->overprint;
-
pgs->overprint = ovp;
pgs->stroke_overprint = ovp;
- if (prior_ovp != ovp)
- (void)gs_do_set_overprint(pgs);
}
/* currentoverprint */
@@ -681,11 +684,7 @@ gs_currentstrokeoverprint(const gs_gstate * pgs)
void
gs_setfilloverprint(gs_gstate * pgs, bool ovp)
{
- bool prior_ovp = pgs->overprint;
-
pgs->overprint = ovp;
- if (prior_ovp != ovp)
- (void)gs_do_set_overprint(pgs);
}
/* currentstrokeoverprint */
@@ -699,15 +698,11 @@ gs_currentfilloverprint(const gs_gstate * pgs)
int
gs_setoverprintmode(gs_gstate * pgs, int mode)
{
- int prior_mode = pgs->effective_overprint_mode;
- int code = 0;
-
if (mode < 0 || mode > 1)
return_error(gs_error_rangecheck);
pgs->overprint_mode = mode;
- if (pgs->overprint && prior_mode != mode)
- code = gs_do_set_overprint(pgs);
- return code;
+
+ return 0;
}
/* currentoverprintmode */
@@ -1446,6 +1441,11 @@ void gs_swapcolors_quick(gs_gstate *pgs)
pgs->color[0].color_space = pgs->color[1].color_space;
pgs->color[1].color_space = tmp_cs;
+ /* Overprint and effective_op vary with stroke/fill and cs */
+ tmp = pgs->color[0].effective_opm;
+ pgs->color[0].effective_opm = pgs->color[1].effective_opm;
+ pgs->color[1].effective_opm = tmp;
+
/* Swap the bits of the gs_gstate that depend on the current color */
tmp_cie = pgs->cie_joint_caches;
pgs->cie_joint_caches = pgs->cie_joint_caches_alt;
@@ -1455,32 +1455,5 @@ void gs_swapcolors_quick(gs_gstate *pgs)
pgs->color_component_map = pgs->color_component_map_alt;
pgs->color_component_map_alt = tmp_ccm;
- tmp = pgs->overprint;
- pgs->overprint = pgs->stroke_overprint;
- pgs->stroke_overprint = tmp;
-}
-
-int gs_swapcolors(gs_gstate *pgs)
-{
- int prior_overprint = pgs->overprint;
-
- gs_swapcolors_quick(pgs);
-
- /* The following code will only call gs_do_set_overprint when we
- * have a change:
- * if ((prior_overprint != pgs->overprint) ||
- * ((prior_mode != pgs->effective_overprint_mode) &&
- * (pgs->overprint)))
- * return gs_do_set_overprint(pgs);
- * Sadly, that's no good, as we need to call when we have swapped
- * image space types too (separation <-> non separation for example).
- *
- * So instead, we call whenever at least one of them had overprint
- * turned on.
- */
- if (prior_overprint || pgs->overprint)
- {
- return gs_do_set_overprint(pgs);
- }
- return 0;
+ pgs->is_fill_color = !(pgs->is_fill_color); /* used by overprint for fill_stroke */
}
diff --git a/base/gstext.c b/base/gstext.c
index 1296e64f4..c1fea18f6 100644
--- a/base/gstext.c
+++ b/base/gstext.c
@@ -31,6 +31,7 @@
#include "gxtext.h"
#include "gzstate.h"
#include "gsutil.h"
+#include "gxdevsop.h"
/* GC descriptors */
public_st_gs_text_params();
@@ -271,6 +272,12 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text,
{
gx_clip_path *pcpath = 0;
int code;
+ gs_overprint_params_t op_params = { 0 };
+ bool op_active = dev_proc(pgs->device, dev_spec_op)(pgs->device, gxdso_overprint_active, NULL, 0);
+ bool text_op_fill = ((pgs->overprint || (!pgs->overprint && op_active)) &&
+ (pgs->text_rendering_mode == 0));
+ bool text_op_stroke = ((pgs->stroke_overprint || (!pgs->stroke_overprint && op_active)) &&
+ (pgs->text_rendering_mode == 1));
/*
* Detect nocurrentpoint now, even if the string is empty, for Adobe
@@ -310,6 +317,40 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text,
code = gs_gstate_color_load(pgs);
if (code < 0)
return code;
+
+ if (text_op_stroke) {
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Stroke Text Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+ } else if (text_op_fill) {
+ if_debug0m(gs_debug_flag_overprint, pgs->memory,
+ "[overprint] Fill Text Overprint\n");
+ code = gs_do_set_overprint(pgs);
+ if (code < 0)
+ return code;
+ }
+
+ /* If overprint is true, push the compositor action to set the op device state */
+ if ((pgs->overprint && pgs->text_rendering_mode == 0) ||
+ (pgs->stroke_overprint && pgs->text_rendering_mode == 1) ||
+ op_active) {
+ gx_device* dev = pgs->device;
+ cmm_dev_profile_t* dev_profile;
+
+ dev_proc(dev, get_profile)(dev, &dev_profile);
+ if (dev_profile->sim_overprint && dev_profile->device_profile[0]->data_cs == gsCMYK) {
+ if (pgs->text_rendering_mode == 0) {
+ op_params.op_state = OP_STATE_FILL;
+ gs_gstate_update_overprint(pgs, &op_params);
+ } else if (pgs->text_rendering_mode == 1) {
+ op_params.op_state = OP_STATE_STROKE;
+ gs_gstate_update_overprint(pgs, &op_params);
+ }
+ }
+ }
+
pgs->device->sgr.stroke_stored = false;
return gx_device_text_begin(pgs->device, pgs,
text, pgs->font, pgs->path,
diff --git a/base/gstrans.h b/base/gstrans.h
index 1868517df..3dc729833 100644
--- a/base/gstrans.h
+++ b/base/gstrans.h
@@ -72,7 +72,10 @@ typedef enum {
#define PDF14_SET_SHAPE_ALPHA (1 << 2)
#define PDF14_SET_OPACITY_ALPHA (1 << 3)
#define PDF14_SET_OVERPRINT (1 << 4)
-#define PDF14_SET_OVERPRINT_MODE (1 << 5)
+#define PDF14_SET_FILLCONSTANTALPHA (1 << 6)
+#define PDF14_SET_STROKECONSTANTALPHA (1 << 7)
+#define PDF14_SET_STROKEOVERPRINT (1 << 8)
+#define PDF_SET_FILLSTROKE_STATE (1 << 9)
/* Used for keeping track of the text group madness, since we have the pdf14
device needs to know if we are int an BT/ET group vs. a FreeText Annotation
@@ -123,11 +126,15 @@ struct gs_pdf14trans_params_s {
int text_group;
gs_transparency_source_t opacity;
gs_transparency_source_t shape;
+ float fillconstantalpha;
+ float strokeconstantalpha;
bool mask_is_image;
gs_matrix ctm;
bool replacing;
bool overprint;
+ bool stroke_overprint;
bool effective_overprint_mode;
+ bool stroke_effective_op_mode;
bool idle; /* For clist reader.*/
uint mask_id; /* For clist reader.*/
int group_color_numcomps;
@@ -137,6 +144,7 @@ struct gs_pdf14trans_params_s {
bool crop_blend_params; /* This is used when the blend params are updated
during a transparency group push */
bool is_pattern; /* Needed to detect device push and pop for clist pattern */
+ PDF14_OP_FS_STATE op_fs_state;
};
/*
diff --git a/base/gxblend.c b/base/gxblend.c
index c07b2fbd7..580696ead 100644
--- a/base/gxblend.c
+++ b/base/gxblend.c
@@ -1207,7 +1207,10 @@ art_blend_pixel_8_inline(byte *gs_restrict dst, const byte *gs_restrict backdrop
* PDF specification */
case BLEND_MODE_CompatibleOverprint:
{
- gx_color_index drawn_comps = p14dev->drawn_comps;
+ gx_color_index drawn_comps = p14dev->op_state == PDF14_OP_STATE_FILL ?
+ p14dev->drawn_comps_fill : p14dev->drawn_comps_stroke;
+ bool opm = p14dev->op_state == PDF14_OP_STATE_FILL ?
+ p14dev->effective_overprint_mode : p14dev->stroke_effective_op_mode;
gx_color_index comps;
/* If overprint mode is true and the current color space and
* the group color space are CMYK (or CMYK and spots), then
@@ -1266,7 +1269,7 @@ art_blend_pixel_8_inline(byte *gs_restrict dst, const byte *gs_restrict backdrop
the mixing of the source with the blend result. Essentially
replacing that mixing with the color we have here.
*/
- if (p14dev->effective_overprint_mode && p14dev->color_info.num_components > 3
+ if (opm && p14dev->color_info.num_components > 3
&& !(p14dev->ctx->additive)) {
for (i = 0; i < 4; i++) {
b = backdrop[i];
@@ -1462,7 +1465,8 @@ art_blend_pixel_16_inline(uint16_t *gs_restrict dst, const uint16_t *gs_restrict
* PDF specification */
case BLEND_MODE_CompatibleOverprint:
{
- gx_color_index drawn_comps = p14dev->drawn_comps;
+ gx_color_index drawn_comps = p14dev->op_state == PDF14_OP_STATE_FILL ?
+ p14dev->drawn_comps_fill : p14dev->drawn_comps_stroke;
gx_color_index comps;
/* If overprint mode is true and the current color space and
* the group color space are CMYK (or CMYK and spots), then
@@ -2247,7 +2251,8 @@ art_pdf_recomposite_group_16(uint16_t *gs_restrict *dstp, uint16_t *gs_restrict
* @NOTE: This function may corrupt src.
**/
static forceinline void
-art_pdf_composite_knockout_group_8(byte *gs_restrict backdrop, byte tos_shape, byte *gs_restrict dst,
+art_pdf_composite_knockout_group_8(byte *gs_restrict backdrop, byte tos_shape,
+ byte* gs_restrict src_alpha_g, byte *gs_restrict dst,
byte *gs_restrict dst_alpha_g, byte *gs_restrict src, int n_chan, byte alpha,
gs_blend_mode_t blend_mode,
const pdf14_nonseparable_blending_procs_t * pblend_procs,
@@ -2256,7 +2261,7 @@ art_pdf_composite_knockout_group_8(byte *gs_restrict backdrop, byte tos_shape, b
byte src_alpha; /* $\alpha g_n$ */
int tmp;
- if (tos_shape == 0) {
+ if (tos_shape == 0 || (src_alpha_g != NULL && *src_alpha_g == 0)) {
/* If a softmask was present pass it along Bug 693548 */
if (has_mask)
dst[n_chan] = alpha;
@@ -2282,7 +2287,8 @@ art_pdf_composite_knockout_group_8(byte *gs_restrict backdrop, byte tos_shape, b
}
static forceinline void
-art_pdf_composite_knockout_group_16(uint16_t *gs_restrict backdrop, uint16_t tos_shape, uint16_t *gs_restrict dst,
+art_pdf_composite_knockout_group_16(uint16_t *gs_restrict backdrop, uint16_t tos_shape,
+ uint16_t* gs_restrict src_alpha_g, uint16_t *gs_restrict dst,
uint16_t *gs_restrict dst_alpha_g, uint16_t *gs_restrict src, int n_chan, uint16_t alpha,
gs_blend_mode_t blend_mode,
const pdf14_nonseparable_blending_procs_t * pblend_procs,
@@ -2291,7 +2297,7 @@ art_pdf_composite_knockout_group_16(uint16_t *gs_restrict backdrop, uint16_t tos
int src_alpha; /* $\alpha g_n$ */
int tmp;
- if (tos_shape == 0) {
+ if (tos_shape == 0 || (src_alpha_g != NULL && *src_alpha_g == 0)) {
/* If a softmask was present pass it along Bug 693548 */
if (has_mask)
dst[n_chan] = alpha;
@@ -2486,7 +2492,9 @@ art_pdf_composite_knockout_8(byte *gs_restrict dst,
inner loop is a single interpolation */
tmp = dst[i] * dst_alpha * (255 - src_shape) +
((int)src[i]) * 255 * src_shape + (result_alpha << 7);
- dst[i] = tmp / (result_alpha * 255);
+ tmp = tmp / (result_alpha * 255);
+ if (tmp > 255) tmp = 255;
+ dst[i] = tmp;
}
dst[n_chan] = result_alpha;
}
@@ -2504,23 +2512,24 @@ art_pdf_composite_knockout_8(byte *gs_restrict dst,
/* Result alpha is Union of backdrop and source alpha */
tmp = (0xff - a_b) * (0xff - a_s) + 0x80;
a_r = 0xff - (((tmp >> 8) + tmp) >> 8);
- /* todo: verify that a_r is nonzero in all cases */
- /* Compute a_s / a_r in 16.16 format */
- src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
+ if (a_r != 0) {
+ /* Compute a_s / a_r in 16.16 format */
+ src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
- art_blend_pixel_8(blend, dst, src, n_chan, blend_mode, pblend_procs, p14dev);
- for (i = 0; i < n_chan; i++) {
- int c_bl; /* Result of blend function */
- int c_mix; /* Blend result mixed with source color */
+ art_blend_pixel_8(blend, dst, src, n_chan, blend_mode, pblend_procs, p14dev);
+ for (i = 0; i < n_chan; i++) {
+ int c_bl; /* Result of blend function */
+ int c_mix; /* Blend result mixed with source color */
- c_s = src[i];
- c_b = dst[i];
- c_bl = blend[i];
- tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
- c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
- tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
- dst[i] = tmp >> 16;
+ c_s = src[i];
+ c_b = dst[i];
+ c_bl = blend[i];
+ tmp = a_b * (c_bl - ((int)c_s)) + 0x80;
+ c_mix = c_s + (((tmp >> 8) + tmp) >> 8);
+ tmp = (c_b << 16) + src_scale * (c_mix - c_b) + 0x8000;
+ dst[i] = tmp >> 16;
+ }
}
dst[n_chan] = a_r;
}
@@ -2562,7 +2571,10 @@ art_pdf_composite_knockout_16(uint16_t *gs_restrict dst,
tmp = dst[i] * dst_alpha;
tmp = (tmp>>16) * (65535 - src_shape) +
src[i] * src_shape + (result_alpha>>1);
- dst[i] = tmp / result_alpha;
+ tmp = tmp / result_alpha;
+ if (tmp > 65535) tmp = 65535;
+ dst[i] = tmp;
+
}
}
dst[n_chan] = result_alpha;
@@ -2581,26 +2593,27 @@ art_pdf_composite_knockout_16(uint16_t *gs_restrict dst,
/* Result alpha is Union of backdrop and source alpha */
tmp = (0xffff - a_b) * (0xffff - a_s) + 0x8000;
a_r = 0xffff - (((tmp >> 16) + tmp) >> 16);
- /* todo: verify that a_r is nonzero in all cases */
- /* Compute a_s / a_r in 16.16 format */
- src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
+ if (a_r != 0) {
+ /* Compute a_s / a_r in 16.16 format */
+ src_scale = ((a_s << 16) + (a_r >> 1)) / a_r;
- src_scale >>= 1; /* Lose a bit to avoid overflow */
- a_b >>= 1; /* Lose a bit to avoid overflow */
- art_blend_pixel_16(blend, dst, src, n_chan, blend_mode, pblend_procs, p14dev);
- for (i = 0; i < n_chan; i++) {
- int c_bl; /* Result of blend function */
- int c_mix; /* Blend result mixed with source color */
- int stmp;
+ src_scale >>= 1; /* Lose a bit to avoid overflow */
+ a_b >>= 1; /* Lose a bit to avoid overflow */
+ art_blend_pixel_16(blend, dst, src, n_chan, blend_mode, pblend_procs, p14dev);
+ for (i = 0; i < n_chan; i++) {
+ int c_bl; /* Result of blend function */
+ int c_mix; /* Blend result mixed with source color */
+ int stmp;
- c_s = src[i];
- c_b = dst[i];
- c_bl = blend[i];
- stmp = a_b * (c_bl - ((int)c_s)) + 0x4000;
- c_mix = c_s + (((stmp >> 16) + stmp) >> 15);
- tmp = src_scale * (c_mix - c_b) + 0x4000;
- dst[i] = c_b + (tmp >> 15);
+ c_s = src[i];
+ c_b = dst[i];
+ c_bl = blend[i];
+ stmp = a_b * (c_bl - ((int)c_s)) + 0x4000;
+ c_mix = c_s + (((stmp >> 16) + stmp) >> 15);
+ tmp = src_scale * (c_mix - c_b) + 0x4000;
+ dst[i] = c_b + (tmp >> 15);
+ }
}
dst[n_chan] = a_r;
}
@@ -2785,7 +2798,7 @@ dump_raw_buffer_be(const gs_memory_t *mem, int num_rows, int width, int n_chan,
typedef void (*art_pdf_compose_group_fn)(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
- byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride,
+ byte *tos_alpha_g_ptr, byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride,
byte *nos_alpha_g_ptr, bool nos_knockout, int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
byte *backdrop_ptr, bool has_matte, int n_chan, bool additive, int num_spots, bool overprint,
@@ -2798,7 +2811,8 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
byte alpha, byte shape, gs_blend_mode_t blend_mode,
bool tos_has_shape, int tos_shape_offset,
int tos_alpha_g_offset, int tos_tag_offset,
- bool tos_has_tag, byte *gs_restrict nos_ptr,
+ bool tos_has_tag, byte *gs_restrict tos_alpha_g_ptr,
+ byte *gs_restrict nos_ptr,
bool nos_isolated, int nos_planestride,
int nos_rowstride, byte *gs_restrict nos_alpha_g_ptr,
bool nos_knockout, int nos_shape_offset,
@@ -2819,7 +2833,6 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
byte tos_pixel[PDF14_MAX_PLANES];
byte nos_pixel[PDF14_MAX_PLANES];
byte back_drop[PDF14_MAX_PLANES];
- gx_color_index comps;
bool in_mask_rect_y;
bool in_mask_rect;
byte pix_alpha;
@@ -2955,7 +2968,7 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
/* alpha */
back_drop[n_chan] = backdrop_ptr[n_chan * nos_planestride];
}
- art_pdf_composite_knockout_group_8(back_drop, tos_shape,
+ art_pdf_composite_knockout_group_8(back_drop, tos_shape, tos_alpha_g_ptr,
nos_pixel, nos_alpha_g_ptr,
tos_pixel, n_chan, pix_alpha,
blend_mode, pblend_procs,
@@ -2992,24 +3005,8 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
}
} else {
/* Pure subtractive */
- /* If we were running in the compatible overprint blend mode
- * and popping the group, we don't need to fool with the
- * drawn components as that should have already have been
- * handled during the blending within our special non-isolated
- * group. So in other words, if the blend mode is normal
- * (or compatible) and we are doing overprint, the overprint
- * has NOT been handled by compatible overprint mode and we
- * need to take care of it now */
- if (overprint) {
- for (i = 0, comps = drawn_comps; comps != 0; ++i, comps >>= 1) {
- if ((comps & 0x1) != 0) {
- nos_ptr[i * nos_planestride] = 255 - dst[i];
- }
- }
- } else {
- for (i = 0; i < n_chan; ++i)
- nos_ptr[i * nos_planestride] = 255 - dst[i];
- }
+ for (i = 0; i < n_chan; ++i)
+ nos_ptr[i * nos_planestride] = 255 - dst[i];
}
/* alpha */
nos_ptr[n_chan * nos_planestride] = dst[n_chan];
@@ -3021,6 +3018,8 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
if (nos_alpha_g_ptr != NULL)
++nos_alpha_g_ptr;
+ if (tos_alpha_g_ptr != NULL)
+ ++tos_alpha_g_ptr;
if (backdrop_ptr != NULL)
++backdrop_ptr;
++tos_ptr;
@@ -3028,6 +3027,8 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
}
tos_ptr += tos_rowstride - width;
nos_ptr += nos_rowstride - width;
+ if (tos_alpha_g_ptr != NULL)
+ tos_alpha_g_ptr += tos_rowstride - width;
if (nos_alpha_g_ptr != NULL)
nos_alpha_g_ptr += nos_rowstride - width;
if (mask_row_ptr != NULL)
@@ -3039,7 +3040,7 @@ template_compose_group(byte *gs_restrict tos_ptr, bool tos_isolated,
static void
compose_group_knockout(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte *tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3048,7 +3049,7 @@ compose_group_knockout(byte *tos_ptr, bool tos_isolated, int tos_planestride, in
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */1,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, has_matte, n_chan, additive, num_spots, overprint, drawn_comps, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3056,7 +3057,7 @@ compose_group_knockout(byte *tos_ptr, bool tos_isolated, int tos_planestride, in
static void
compose_group_nonknockout_blend(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3065,7 +3066,7 @@ compose_group_nonknockout_blend(byte *tos_ptr, bool tos_isolated, int tos_planes
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, has_matte, n_chan, additive, num_spots, overprint, drawn_comps, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3073,7 +3074,7 @@ compose_group_nonknockout_blend(byte *tos_ptr, bool tos_isolated, int tos_planes
static void
compose_group_nonknockout_nonblend_isolated_allmask_common(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3138,7 +3139,7 @@ compose_group_nonknockout_nonblend_isolated_allmask_common(byte *tos_ptr, bool t
static void
compose_group_nonknockout_nonblend_isolated_mask_common(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3228,7 +3229,7 @@ compose_group_nonknockout_nonblend_isolated_mask_common(byte *tos_ptr, bool tos_
static void
compose_group_nonknockout_nonblend_isolated_nomask_common(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3237,7 +3238,7 @@ compose_group_nonknockout_nonblend_isolated_nomask_common(byte *tos_ptr, bool to
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, /*tos_isolated*/1, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0, /*tos_alpha_g_ptr*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, /*has_mask*/0, /*maskbuf*/NULL, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, /*has_matte*/0, n_chan, /*additive*/1, /*num_spots*/0, /*overprint*/0, /*drawn_comps*/0, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3245,7 +3246,7 @@ compose_group_nonknockout_nonblend_isolated_nomask_common(byte *tos_ptr, bool to
static void
compose_group_nonknockout_nonblend_nonisolated_mask_common(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3254,7 +3255,7 @@ compose_group_nonknockout_nonblend_nonisolated_mask_common(byte *tos_ptr, bool t
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0, /*tos_alpha_g_ptr*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, /*has_matte*/0, n_chan, /*additive*/1, /*num_spots*/0, /*overprint*/0, /*drawn_comps*/0, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3262,7 +3263,7 @@ compose_group_nonknockout_nonblend_nonisolated_mask_common(byte *tos_ptr, bool t
static void
compose_group_nonknockout_nonblend_nonisolated_nomask_common(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3271,7 +3272,7 @@ compose_group_nonknockout_nonblend_nonisolated_nomask_common(byte *tos_ptr, bool
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0, /*tos_alpha_g_ptr*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, /*has_mask*/0, /*maskbuf*/NULL, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, /*has_matte*/0, n_chan, /*additive*/1, /*num_spots*/0, /*overprint*/0, /*drawn_comps*/0, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3279,7 +3280,7 @@ compose_group_nonknockout_nonblend_nonisolated_nomask_common(byte *tos_ptr, bool
static void
compose_group_nonknockout_noblend_general(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3288,7 +3289,7 @@ compose_group_nonknockout_noblend_general(byte *tos_ptr, bool tos_isolated, int
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, tos_has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
backdrop_ptr, has_matte, n_chan, additive, num_spots, overprint, drawn_comps, x0, y0, x1, y1, pblend_procs, pdev, 1);
@@ -3296,7 +3297,7 @@ compose_group_nonknockout_noblend_general(byte *tos_ptr, bool tos_isolated, int
static void
compose_group_alphaless_knockout(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3305,7 +3306,7 @@ compose_group_alphaless_knockout(byte *tos_ptr, bool tos_isolated, int tos_plane
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */1,
nos_shape_offset, nos_tag_offset, /* mask_row_ptr */ NULL, /* has_mask */ 0, /* maskbuf */ NULL, mask_bg_alpha, /* mask_tr_fn */ NULL,
backdrop_ptr, /* has_matte */ false , n_chan, additive, num_spots, overprint, drawn_comps, x0, y0, x1, y1, pblend_procs, pdev, 0);
@@ -3313,7 +3314,7 @@ compose_group_alphaless_knockout(byte *tos_ptr, bool tos_isolated, int tos_plane
static void
compose_group_alphaless_nonknockout(byte *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, byte alpha, byte shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
- int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
+ int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag, byte* tos_alpha_g_ptr,
byte *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, byte *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
byte *mask_row_ptr, int has_mask, pdf14_buf *maskbuf, byte mask_bg_alpha, const byte *mask_tr_fn,
@@ -3322,7 +3323,7 @@ compose_group_alphaless_nonknockout(byte *tos_ptr, bool tos_isolated, int tos_pl
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
template_compose_group(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, /* mask_row_ptr */ NULL, /* has_mask */ 0, /* maskbuf */ NULL, mask_bg_alpha, /* mask_tr_fn */ NULL,
backdrop_ptr, /* has_matte */ false , n_chan, additive, num_spots, overprint, drawn_comps, x0, y0, x1, y1, pblend_procs, pdev, 0);
@@ -3351,6 +3352,7 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
bool nos_isolated = nos->isolated;
bool nos_knockout = nos->knockout;
byte *nos_alpha_g_ptr;
+ byte* tos_alpha_g_ptr;
int tos_shape_offset = n_chan * tos_planestride;
int tos_alpha_g_offset = tos_shape_offset + (tos->has_shape ? tos_planestride : 0);
bool tos_has_tag = tos->has_tags;
@@ -3390,6 +3392,10 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
nos_alpha_g_ptr = nos_ptr + nos_alpha_g_offset;
} else
nos_alpha_g_ptr = NULL;
+ if (tos->has_alpha_g) {
+ tos_alpha_g_ptr = tos_ptr + tos_alpha_g_offset;
+ } else
+ tos_alpha_g_ptr = NULL;
if (nos->backdrop != NULL) {
backdrop_ptr = nos->backdrop + x0 - nos->rect.p.x +
(y0 - nos->rect.p.y) * nos->rowstride;
@@ -3473,7 +3479,7 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
fn = &compose_group_nonknockout_blend; /* Small %ages, nothing more than 2% */
else if (tos->has_shape == 0 && tos_has_tag == 0 && nos_isolated == 0 && nos_alpha_g_ptr == NULL &&
nos_shape_offset == 0 && nos_tag_offset == 0 && backdrop_ptr == NULL && has_matte == 0 && num_spots == 0 &&
- overprint == 0) {
+ overprint == 0 && tos_alpha_g_ptr == NULL) {
/* Additive vs Subtractive makes no difference in normal blend mode with no spots */
if (tos_isolated) {
if (has_mask && maskbuf) {/* 7% */
@@ -3495,8 +3501,12 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
}
} else
fn = &compose_group_nonknockout_nonblend_isolated_mask_common;
- } else /* 14% */
- fn = &compose_group_nonknockout_nonblend_isolated_nomask_common;
+ } else
+ if (maskbuf) {
+ /* Outside mask */
+ fn = &compose_group_nonknockout_nonblend_isolated_mask_common;
+ } else
+ fn = &compose_group_nonknockout_nonblend_isolated_nomask_common;
} else {
if (has_mask || maskbuf) /* 4% */
fn = &compose_group_nonknockout_nonblend_nonisolated_mask_common;
@@ -3508,7 +3518,7 @@ do_compose_group(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
fn(tos_ptr, tos_isolated, tos_planestride, tos->rowstride, alpha, shape,
blend_mode, tos->has_shape, tos_shape_offset, tos_alpha_g_offset,
- tos_tag_offset, tos_has_tag, nos_ptr, nos_isolated, nos_planestride,
+ tos_tag_offset, tos_has_tag, tos_alpha_g_ptr, nos_ptr, nos_isolated, nos_planestride,
nos->rowstride, nos_alpha_g_ptr, nos_knockout, nos_shape_offset,
nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha,
mask_tr_fn, backdrop_ptr, has_matte, n_chan, additive, num_spots,
@@ -3531,7 +3541,7 @@ interp16(const uint16_t *table, uint16_t idx)
return a + ((0x80 + b*(idx & 0xff))>>8);
}
-typedef void (*art_pdf_compose_group16_fn)(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+typedef void (*art_pdf_compose_group16_fn)(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t* tos_alpha_g_ptr,
uint16_t alpha, uint16_t shape, gs_blend_mode_t blend_mode, bool tos_has_shape,
int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride,
@@ -3543,7 +3553,7 @@ typedef void (*art_pdf_compose_group16_fn)(uint16_t *tos_ptr, bool tos_isolated,
static forceinline void
template_compose_group16(uint16_t *gs_restrict tos_ptr, bool tos_isolated,
- int tos_planestride, int tos_rowstride,
+ int tos_planestride, int tos_rowstride, uint16_t* gs_restrict tos_alpha_g_ptr,
uint16_t alpha, uint16_t shape, gs_blend_mode_t blend_mode,
bool tos_has_shape, int tos_shape_offset,
int tos_alpha_g_offset, int tos_tag_offset,
@@ -3713,7 +3723,7 @@ template_compose_group16(uint16_t *gs_restrict tos_ptr, bool tos_isolated,
/* alpha */
back_drop[n_chan] = backdrop_ptr[n_chan * nos_planestride];
}
- art_pdf_composite_knockout_group_16(back_drop, tos_shape,
+ art_pdf_composite_knockout_group_16(back_drop, tos_shape, tos_alpha_g_ptr,
nos_pixel, nos_alpha_g_ptr,
tos_pixel, n_chan, pix_alpha,
blend_mode, pblend_procs,
@@ -3784,11 +3794,15 @@ template_compose_group16(uint16_t *gs_restrict tos_ptr, bool tos_isolated,
++nos_alpha_g_ptr;
if (backdrop_ptr != NULL)
++backdrop_ptr;
+ if (tos_alpha_g_ptr != NULL)
+ ++tos_alpha_g_ptr;
++tos_ptr;
++nos_ptr;
}
tos_ptr += tos_rowstride - width;
nos_ptr += nos_rowstride - width;
+ if (tos_alpha_g_ptr != NULL)
+ tos_alpha_g_ptr += tos_rowstride - width;
if (nos_alpha_g_ptr != NULL)
nos_alpha_g_ptr += nos_rowstride - width;
if (mask_row_ptr != NULL)
@@ -3799,7 +3813,8 @@ template_compose_group16(uint16_t *gs_restrict tos_ptr, bool tos_isolated,
}
static void
-compose_group16_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape, gs_blend_mode_t blend_mode,
+compose_group16_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape, gs_blend_mode_t blend_mode,
bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -3808,7 +3823,7 @@ compose_group16_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestri
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
+ template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, tos_alpha_g_ptr, alpha, shape, blend_mode, tos_has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */1,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
@@ -3816,7 +3831,8 @@ compose_group16_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestri
}
static void
-compose_group16_nonknockout_blend(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape,
+compose_group16_nonknockout_blend(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape,
gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -3825,7 +3841,8 @@ compose_group16_nonknockout_blend(uint16_t *tos_ptr, bool tos_isolated, int tos_
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
+ template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride,
+ tos_alpha_g_ptr, alpha, shape, blend_mode, tos_has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
@@ -3833,7 +3850,8 @@ compose_group16_nonknockout_blend(uint16_t *tos_ptr, bool tos_isolated, int tos_
}
static void
-compose_group16_nonknockout_nonblend_isolated_allmask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha,
+compose_group16_nonknockout_nonblend_isolated_allmask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride,
+ int tos_rowstride, uint16_t* tos_alpha_g_ptr, uint16_t alpha,
uint16_t shape, gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -3904,7 +3922,8 @@ compose_group16_nonknockout_nonblend_isolated_allmask_common(uint16_t *tos_ptr,
}
static void
-compose_group16_nonknockout_nonblend_isolated_mask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape,
+compose_group16_nonknockout_nonblend_isolated_mask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape,
gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -3999,7 +4018,8 @@ compose_group16_nonknockout_nonblend_isolated_mask_common(uint16_t *tos_ptr, boo
}
static void
-compose_group16_nonknockout_nonblend_isolated_nomask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha,
+compose_group16_nonknockout_nonblend_isolated_nomask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha,
uint16_t shape, gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4008,7 +4028,7 @@ compose_group16_nonknockout_nonblend_isolated_nomask_common(uint16_t *tos_ptr, b
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, /*tos_isolated*/1, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
+ template_compose_group16(tos_ptr, /*tos_isolated*/1, tos_planestride, tos_rowstride, /*tos_alpha_g_ptr*/ 0, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, /*has_mask*/0, /*maskbuf*/NULL, mask_bg_alpha, mask_tr_fn,
@@ -4016,7 +4036,8 @@ compose_group16_nonknockout_nonblend_isolated_nomask_common(uint16_t *tos_ptr, b
}
static void
-compose_group16_nonknockout_nonblend_nonisolated_mask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha,
+compose_group16_nonknockout_nonblend_nonisolated_mask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha,
uint16_t shape, gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4025,7 +4046,7 @@ compose_group16_nonknockout_nonblend_nonisolated_mask_common(uint16_t *tos_ptr,
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
+ template_compose_group16(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, /*tos_alpha_g_ptr*/0, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
@@ -4033,7 +4054,8 @@ compose_group16_nonknockout_nonblend_nonisolated_mask_common(uint16_t *tos_ptr,
}
static void
-compose_group16_nonknockout_nonblend_nonisolated_nomask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha,
+compose_group16_nonknockout_nonblend_nonisolated_nomask_common(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha,
uint16_t shape, gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4042,7 +4064,7 @@ compose_group16_nonknockout_nonblend_nonisolated_nomask_common(uint16_t *tos_ptr
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
+ template_compose_group16(tos_ptr, /*tos_isolated*/0, tos_planestride, tos_rowstride, /*tos_alpha_g_ptr*/0, alpha, shape, BLEND_MODE_Normal, /*tos_has_shape*/0,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, /*tos_has_tag*/0,
nos_ptr, /*nos_isolated*/0, nos_planestride, nos_rowstride, /*nos_alpha_g_ptr*/0, /* nos_knockout = */0,
/*nos_shape_offset*/0, /*nos_tag_offset*/0, mask_row_ptr, /*has_mask*/0, /*maskbuf*/NULL, mask_bg_alpha, mask_tr_fn,
@@ -4050,7 +4072,8 @@ compose_group16_nonknockout_nonblend_nonisolated_nomask_common(uint16_t *tos_ptr
}
static void
-compose_group16_nonknockout_noblend_general(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape,
+compose_group16_nonknockout_noblend_general(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape,
gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4059,7 +4082,7 @@ compose_group16_nonknockout_noblend_general(uint16_t *tos_ptr, bool tos_isolated
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, BLEND_MODE_Normal, tos_has_shape,
+ template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, tos_alpha_g_ptr, alpha, shape, BLEND_MODE_Normal, tos_has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, mask_row_ptr, has_mask, maskbuf, mask_bg_alpha, mask_tr_fn,
@@ -4067,7 +4090,8 @@ compose_group16_nonknockout_noblend_general(uint16_t *tos_ptr, bool tos_isolated
}
static void
-compose_group16_alphaless_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape,
+compose_group16_alphaless_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape,
gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4076,7 +4100,8 @@ compose_group16_alphaless_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
+ template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride,
+ tos_alpha_g_ptr, alpha, shape, blend_mode, tos_has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */1,
nos_shape_offset, nos_tag_offset, /* mask_row_ptr */ NULL, /* has_mask */ 0, /* maskbuf */ NULL, mask_bg_alpha, /* mask_tr_fn */ NULL,
@@ -4084,7 +4109,8 @@ compose_group16_alphaless_knockout(uint16_t *tos_ptr, bool tos_isolated, int tos
}
static void
-compose_group16_alphaless_nonknockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride, uint16_t alpha, uint16_t shape,
+compose_group16_alphaless_nonknockout(uint16_t *tos_ptr, bool tos_isolated, int tos_planestride, int tos_rowstride,
+ uint16_t* tos_alpha_g_ptr, uint16_t alpha, uint16_t shape,
gs_blend_mode_t blend_mode, bool tos_has_shape, int tos_shape_offset, int tos_alpha_g_offset, int tos_tag_offset, bool tos_has_tag,
uint16_t *nos_ptr, bool nos_isolated, int nos_planestride, int nos_rowstride, uint16_t *nos_alpha_g_ptr, bool nos_knockout,
int nos_shape_offset, int nos_tag_offset,
@@ -4093,7 +4119,8 @@ compose_group16_alphaless_nonknockout(uint16_t *tos_ptr, bool tos_isolated, int
bool has_matte, int n_chan, bool additive, int num_spots, bool overprint, gx_color_index drawn_comps, int x0, int y0, int x1, int y1,
const pdf14_nonseparable_blending_procs_t *pblend_procs, pdf14_device *pdev)
{
- template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride, alpha, shape, blend_mode, tos_has_shape,
+ template_compose_group16(tos_ptr, tos_isolated, tos_planestride, tos_rowstride,
+ tos_alpha_g_ptr, alpha, shape, blend_mode, tos_has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos_rowstride, nos_alpha_g_ptr, /* nos_knockout = */0,
nos_shape_offset, nos_tag_offset, /* mask_row_ptr */ NULL, /* has_mask */ 0, /* maskbuf */ NULL, mask_bg_alpha, /* mask_tr_fn */ NULL,
@@ -4124,7 +4151,8 @@ do_compose_group16(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
bool tos_isolated = tos->isolated;
bool nos_isolated = nos->isolated;
bool nos_knockout = nos->knockout;
- uint16_t *nos_alpha_g_ptr;
+ uint16_t* nos_alpha_g_ptr;
+ uint16_t* tos_alpha_g_ptr;
int tos_shape_offset = n_chan * tos_planestride;
int tos_alpha_g_offset = tos_shape_offset + (tos->has_shape ? tos_planestride : 0);
bool tos_has_tag = tos->has_tags;
@@ -4161,6 +4189,11 @@ do_compose_group16(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
nos_alpha_g_ptr = nos_ptr + (nos_alpha_g_offset>>1);
} else
nos_alpha_g_ptr = NULL;
+ if (tos->has_alpha_g) {
+ tos_alpha_g_ptr = tos_ptr + (tos_alpha_g_offset>>1);
+ } else
+ tos_alpha_g_ptr = NULL;
+
if (nos->backdrop != NULL) {
backdrop_ptr =
(uint16_t *)(void *)(nos->backdrop + (x0 - nos->rect.p.x)*2 +
@@ -4243,7 +4276,7 @@ do_compose_group16(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
fn = &compose_group16_nonknockout_blend; /* Small %ages, nothing more than 2% */
else if (tos->has_shape == 0 && tos_has_tag == 0 && nos_isolated == 0 && nos_alpha_g_ptr == NULL &&
nos_shape_offset == 0 && nos_tag_offset == 0 && backdrop_ptr == NULL && has_matte == 0 && num_spots == 0 &&
- overprint == 0) {
+ overprint == 0 && tos_alpha_g_ptr == NULL) {
/* Additive vs Subtractive makes no difference in normal blend mode with no spots */
if (tos_isolated) {
if (has_mask && maskbuf) {/* 7% */
@@ -4253,8 +4286,13 @@ do_compose_group16(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
fn = &compose_group16_nonknockout_nonblend_isolated_allmask_common;
else
fn = &compose_group16_nonknockout_nonblend_isolated_mask_common;
- } else /* 14% */
- fn = &compose_group16_nonknockout_nonblend_isolated_nomask_common;
+ } else
+ if (maskbuf) {
+ /* Outside mask data but still has mask */
+ fn = &compose_group16_nonknockout_nonblend_isolated_mask_common;
+ } else {
+ fn = &compose_group16_nonknockout_nonblend_isolated_nomask_common;
+ }
} else {
if (has_mask || maskbuf) /* 4% */
fn = &compose_group16_nonknockout_nonblend_nonisolated_mask_common;
@@ -4271,7 +4309,7 @@ do_compose_group16(pdf14_buf *tos, pdf14_buf *nos, pdf14_buf *maskbuf,
nos_planestride >>= 1;
nos_shape_offset >>= 1;
nos_tag_offset >>= 1;
- fn(tos_ptr, tos_isolated, tos_planestride, tos->rowstride>>1, alpha, shape, blend_mode, tos->has_shape,
+ fn(tos_ptr, tos_isolated, tos_planestride, tos->rowstride>>1, tos_alpha_g_ptr, alpha, shape, blend_mode, tos->has_shape,
tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride, nos->rowstride>>1, nos_alpha_g_ptr, nos_knockout,
nos_shape_offset, nos_tag_offset,
@@ -4310,9 +4348,10 @@ do_compose_alphaless_group(pdf14_buf *tos, pdf14_buf *nos,
gs_memory_t *memory, gx_device *dev)
{
pdf14_device *pdev = (pdf14_device *)dev;
- bool overprint = pdev->overprint;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
bool additive = pdev->ctx->additive;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
int n_chan = nos->n_chan;
int num_spots = tos->num_spots;
byte alpha = tos->alpha>>8;
@@ -4329,7 +4368,7 @@ do_compose_alphaless_group(pdf14_buf *tos, pdf14_buf *nos,
bool tos_isolated = false;
bool nos_isolated = nos->isolated;
bool nos_knockout = nos->knockout;
- byte *nos_alpha_g_ptr;
+ byte *nos_alpha_g_ptr, *tos_alpha_g_ptr;
int tos_shape_offset = n_chan * tos_planestride;
int tos_alpha_g_offset = tos_shape_offset + (tos->has_shape ? tos_planestride : 0);
bool tos_has_tag = tos->has_tags;
@@ -4365,6 +4404,10 @@ do_compose_alphaless_group(pdf14_buf *tos, pdf14_buf *nos,
nos_alpha_g_ptr = nos_ptr + nos_alpha_g_offset;
} else
nos_alpha_g_ptr = NULL;
+ if (tos->has_alpha_g) {
+ tos_alpha_g_ptr = tos_ptr + tos_alpha_g_offset;
+ } else
+ tos_alpha_g_ptr = NULL;
if (nos->backdrop != NULL) {
backdrop_ptr = nos->backdrop + x0 - nos->rect.p.x +
(y0 - nos->rect.p.y) * nos->rowstride;
@@ -4419,7 +4462,7 @@ do_compose_alphaless_group(pdf14_buf *tos, pdf14_buf *nos,
fn = &compose_group_alphaless_nonknockout;
fn(tos_ptr, tos_isolated, tos_planestride, tos->rowstride, alpha, shape, blend_mode, tos->has_shape,
- tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag,
+ tos_shape_offset, tos_alpha_g_offset, tos_tag_offset, tos_has_tag, tos_alpha_g_ptr,
nos_ptr, nos_isolated, nos_planestride, nos->rowstride, nos_alpha_g_ptr, nos_knockout,
nos_shape_offset, nos_tag_offset,
mask_row_ptr, has_mask, /* maskbuf */ NULL, mask_bg_alpha, mask_tr_fn,
@@ -4440,9 +4483,10 @@ do_compose_alphaless_group16(pdf14_buf *tos, pdf14_buf *nos,
gs_memory_t *memory, gx_device *dev)
{
pdf14_device *pdev = (pdf14_device *)dev;
- bool overprint = pdev->overprint;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
bool additive = pdev->ctx->additive;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
int n_chan = nos->n_chan;
int num_spots = tos->num_spots;
uint16_t alpha = tos->alpha;
@@ -4461,7 +4505,8 @@ do_compose_alphaless_group16(pdf14_buf *tos, pdf14_buf *nos,
bool tos_isolated = false;
bool nos_isolated = nos->isolated;
bool nos_knockout = nos->knockout;
- uint16_t *nos_alpha_g_ptr;
+ uint16_t* nos_alpha_g_ptr;
+ uint16_t* tos_alpha_g_ptr;
int tos_shape_offset = n_chan * tos_planestride;
int tos_alpha_g_offset = tos_shape_offset + (tos->has_shape ? tos_planestride : 0);
bool tos_has_tag = tos->has_tags;
@@ -4496,6 +4541,11 @@ do_compose_alphaless_group16(pdf14_buf *tos, pdf14_buf *nos,
nos_alpha_g_ptr = nos_ptr + (nos_alpha_g_offset>>1);
} else
nos_alpha_g_ptr = NULL;
+ if (tos->has_alpha_g) {
+ tos_alpha_g_ptr = tos_ptr + (tos_alpha_g_offset>>1);
+ } else
+ tos_alpha_g_ptr = NULL;
+
if (nos->backdrop != NULL) {
backdrop_ptr =
(uint16_t *)(void *)(nos->backdrop + (x0 - nos->rect.p.x)*2 +
@@ -4550,7 +4600,7 @@ do_compose_alphaless_group16(pdf14_buf *tos, pdf14_buf *nos,
else
fn = &compose_group16_alphaless_nonknockout;
- fn(tos_ptr, tos_isolated, tos_planestride>>1, tos->rowstride>>1, alpha, shape, blend_mode, tos->has_shape,
+ fn(tos_ptr, tos_isolated, tos_planestride>>1, tos->rowstride>>1, tos_alpha_g_ptr, alpha, shape, blend_mode, tos->has_shape,
tos_shape_offset>>1, tos_alpha_g_offset>>1, tos_tag_offset>>1, tos_has_tag,
nos_ptr, nos_isolated, nos_planestride>>1, nos->rowstride>>1, nos_alpha_g_ptr, nos_knockout,
nos_shape_offset>>1, nos_tag_offset>>1,
@@ -4589,7 +4639,6 @@ template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restri
int alpha_g_off, int shape_off, byte shape, bool isolated)
{
int i, j, k;
- gx_color_index comps;
byte dst[PDF14_MAX_PLANES] = { 0 };
byte dest_alpha;
bool tag_blend = blend_mode == BLEND_MODE_Normal ||
@@ -4638,14 +4687,19 @@ template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restri
dest_alpha = dst[num_comp];
pdst = art_pdf_composite_pixel_alpha_8_inline(dst, src, num_comp, blend_mode, first_blend_spot,
pdev->blend_procs, pdev);
- /* Until I see otherwise in AR or the spec, do not fool
- with spot overprinting while we are in an RGB or Gray
- blend color space. */
- if (!additive && overprint) {
+ /* Post blend complement for subtractive and handling of drawncomps
+ if overprint. We will have already done the compatible overprint
+ mode in the above composition */
+ if (!additive && !overprint) {
+ /* Pure subtractive */
+ for (k = 0; k < num_comp; ++k)
+ dst_ptr[k * planestride] = 255 - pdst[k];
+ } else if (!additive && overprint) {
+ int comps;
/* If this is an overprint case, and alpha_r is different
than alpha_d then we will need to adjust
the colors of the non-drawn components here too */
- for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
+ for (k = 0, comps = drawn_comps; k < num_comp; ++k, comps >>= 1) {
if ((comps & 0x1) != 0) {
dst_ptr[k * planestride] = 255 - pdst[k];
} else if (dest_alpha != pdst[num_comp]) {
@@ -4661,21 +4715,13 @@ template_mark_fill_rect(int w, int h, byte *gs_restrict dst_ptr, byte *gs_restri
}
}
} else {
- /* Post blend complement for subtractive */
- if (!additive) {
- /* Pure subtractive */
- for (k = 0; k < num_comp; ++k)
- dst_ptr[k * planestride] = 255 - pdst[k];
-
- } else {
- /* Hybrid case, additive with subtractive spots */
- for (k = 0; k < (num_comp - num_spots); k++) {
- dst_ptr[k * planestride] = pdst[k];
- }
- for (k = 0; k < num_spots; k++) {
- dst_ptr[(k + num_comp - num_spots) * planestride] =
- 255 - pdst[k + num_comp - num_spots];
- }
+ /* Hybrid case, additive with subtractive spots */
+ for (k = 0; k < (num_comp - num_spots); k++) {
+ dst_ptr[k * planestride] = pdst[k];
+ }
+ for (k = 0; k < num_spots; k++) {
+ dst_ptr[(k + num_comp - num_spots) * planestride] =
+ 255 - pdst[k + num_comp - num_spots];
}
}
/* The alpha channel */
@@ -5024,8 +5070,9 @@ do_mark_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
int shape_off = num_chan * planestride;
int alpha_g_off = shape_off + (has_shape ? planestride : 0);
int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
byte shape = 0; /* Quiet compiler. */
byte src_alpha;
const gx_color_index mask = ((gx_color_index)1 << 8) - 1;
@@ -5170,7 +5217,6 @@ template_mark_fill_rect16(int w, int h, uint16_t *gs_restrict dst_ptr, uint16_t
int alpha_g_off, int shape_off, uint16_t shape_)
{
int i, j, k;
- gx_color_index comps;
uint16_t dst[PDF14_MAX_PLANES] = { 0 };
/* Expand src_alpha and shape to be 0...0x10000 rather than 0...0xffff */
int src_alpha = src_alpha_ + (src_alpha_>>15);
@@ -5220,31 +5266,30 @@ template_mark_fill_rect16(int w, int h, uint16_t *gs_restrict dst_ptr, uint16_t
dst[num_comp] = dst_ptr[num_comp * planestride];
pdst = art_pdf_composite_pixel_alpha_16_inline(dst, src, num_comp, blend_mode, first_blend_spot,
pdev->blend_procs, pdev);
- /* Until I see otherwise in AR or the spec, do not fool
- with spot overprinting while we are in an RGB or Gray
- blend color space. */
- if (!additive && overprint) {
+
+ /* Post blend complement for subtractive */
+ if (!additive && !overprint) {
+ /* Pure subtractive */
+ for (k = 0; k < num_comp; ++k)
+ dst_ptr[k * planestride] = 65535 - pdst[k];
+
+ } else if (!additive && overprint) {
+ int comps;
+
for (k = 0, comps = drawn_comps; comps != 0; ++k, comps >>= 1) {
if ((comps & 0x1) != 0) {
dst_ptr[k * planestride] = 65535 - pdst[k];
}
}
- } else {
- /* Post blend complement for subtractive */
- if (!additive) {
- /* Pure subtractive */
- for (k = 0; k < num_comp; ++k)
- dst_ptr[k * planestride] = 65535 - pdst[k];
-
- } else {
- /* Hybrid case, additive with subtractive spots */
- for (k = 0; k < (num_comp - num_spots); k++) {
- dst_ptr[k * planestride] = pdst[k];
- }
- for (k = 0; k < num_spots; k++) {
- dst_ptr[(k + num_comp - num_spots) * planestride] =
- 65535 - pdst[k + num_comp - num_spots];
- }
+ }
+ else {
+ /* Hybrid case, additive with subtractive spots */
+ for (k = 0; k < (num_comp - num_spots); k++) {
+ dst_ptr[k * planestride] = pdst[k];
+ }
+ for (k = 0; k < num_spots; k++) {
+ dst_ptr[(k + num_comp - num_spots) * planestride] =
+ 65535 - pdst[k + num_comp - num_spots];
}
}
/* The alpha channel */
@@ -5627,10 +5672,11 @@ do_mark_fill_rectangle16(gx_device * dev, int x, int y, int w, int h,
int shape_off = num_chan * planestride;
int alpha_g_off = shape_off + (has_shape ? planestride : 0);
int tag_off = alpha_g_off + (has_alpha_g ? planestride : 0);
- bool overprint = pdev->overprint;
- gx_color_index drawn_comps = pdev->drawn_comps;
- uint16_t shape = 0; /* Quiet compiler. */
- uint16_t src_alpha;
+ bool overprint = pdev->op_state == PDF14_OP_STATE_FILL ? pdev->overprint : pdev->stroke_overprint;
+ gx_color_index drawn_comps = pdev->op_state == PDF14_OP_STATE_FILL ?
+ pdev->drawn_comps_fill : pdev->drawn_comps_stroke;
+ byte shape = 0; /* Quiet compiler. */
+ byte src_alpha;
int num_spots = buf->num_spots;
int first_blend_spot = num_comp;
pdf14_mark_fill_rect16_fn fn;
diff --git a/base/gxblend1.c b/base/gxblend1.c
index 2f15c7c44..ea05abf44 100644
--- a/base/gxblend1.c
+++ b/base/gxblend1.c
@@ -311,7 +311,7 @@ pdf14_preserve_backdrop_cm(pdf14_buf *buf, cmm_profile_t *group_profile,
}
void
-pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool knockout_buff
+pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool from_backdrop
#if RAW_DUMP
, const gs_memory_t *mem
#endif
@@ -330,8 +330,8 @@ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool knockout_buff
int i, n_planes;
bool deep = buf->deep;
- if (knockout_buff) {
- buf_plane = buf->backdrop;
+ if (from_backdrop) {
+ buf_plane = buf->data;
tos_plane = tos->backdrop;
n_planes = buf->n_chan;
} else {
@@ -353,7 +353,7 @@ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool knockout_buff
* alpha_g and shape, but don't need to clear the tag plane
* if it would be copied below (and if it exists). */
int tag_plane_num = tos->n_chan + !!buf->has_shape + !!buf->has_alpha_g;
- if (!knockout_buff && n_planes > tag_plane_num)
+ if (!from_backdrop && n_planes > tag_plane_num)
n_planes = tag_plane_num;
if (n_planes > tos->n_chan)
memset(buf->data + tos->n_chan * buf->planestride, 0, (n_planes - tos->n_chan) * buf->planestride);
@@ -369,17 +369,19 @@ pdf14_preserve_backdrop(pdf14_buf *buf, pdf14_buf *tos, bool knockout_buff
buf_plane += buf->planestride;
tos_plane += tos->planestride;
}
- if (!knockout_buff)
+ if (!from_backdrop)
copy_extra_planes(buf_plane, buf, tos_plane, tos, width, height);
}
#if RAW_DUMP
if (x0 < x1 && y0 < y1) {
- byte *buf_plane = (knockout_buff ? buf->backdrop : buf->data);
- buf_plane += ((x0 - buf->rect.p.x)<<buf->deep) +
- (y0 - buf->rect.p.y) * buf->rowstride;
- dump_raw_buffer(mem, y1 - y0, x1 - x0, buf->n_planes, buf->planestride,
- buf->rowstride, "BackDropInit", buf_plane, buf->deep);
- global_index++;
+ byte *buf_plane = (from_backdrop ? buf->backdrop : buf->data);
+ if (buf_plane != NULL) {
+ buf_plane += ((x0 - buf->rect.p.x) << buf->deep) +
+ (y0 - buf->rect.p.y) * buf->rowstride;
+ dump_raw_buffer(mem, y1 - y0, x1 - x0, buf->n_planes, buf->planestride,
+ buf->rowstride, "BackDropInit", buf_plane, buf->deep);
+ global_index++;
+ }
}
#endif
}
diff --git a/base/gxccache.c b/base/gxccache.c
index 3190cebe3..7133a0026 100644
--- a/base/gxccache.c
+++ b/base/gxccache.c
@@ -212,7 +212,7 @@ gx_image_cached_char(register gs_show_enum * penum, register cached_char * cc)
else
dmputs(penum->memory, "[K]no bits\n");
dmlprintf3(penum->memory, "[K]copying 0x%lx, offset=(%g,%g)\n", (ulong) cc,
- fixed2float(-cc->offset.x),
+ fixed2float(-cc->offset.x),
fixed2float(-cc->offset.y));
dmlprintf6(penum->memory, " at (%g,%g)+(%d,%d)->(%d,%d)\n",
fixed2float(pt.x), fixed2float(pt.y),
diff --git a/base/gxclimag.c b/base/gxclimag.c
index 7f5ea57b6..19e0a9669 100644
--- a/base/gxclimag.c
+++ b/base/gxclimag.c
@@ -220,7 +220,7 @@ clist_fill_mask(gx_device * dev,
if (code < 0)
return code;
code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
- devn_not_tile);
+ devn_not_tile_fill);
if (code == gs_error_unregistered)
return code;
if (depth > 1 && code >= 0)
@@ -1119,7 +1119,7 @@ clist_image_plane_data(gx_image_enum_common_t * info,
re.rect_nbands = ((pie->ymax + re.band_height - 1) / re.band_height) -
((pie->ymin) / re.band_height);
code = cmd_put_drawing_color(cdev, re.pcls, &pie->dcolor,
- &re, devn_not_tile);
+ &re, devn_not_tile_fill);
if (code < 0)
return code;
}
diff --git a/base/gxclip.c b/base/gxclip.c
index 47a199653..b8927af38 100644
--- a/base/gxclip.c
+++ b/base/gxclip.c
@@ -47,6 +47,7 @@ static dev_proc_get_clipping_box(clip_get_clipping_box);
static dev_proc_get_bits_rectangle(clip_get_bits_rectangle);
static dev_proc_fill_path(clip_fill_path);
static dev_proc_transform_pixel_region(clip_transform_pixel_region);
+static dev_proc_fill_stroke_path(clip_fill_stroke_path);
/* The device descriptor. */
static const gx_device_clip gs_clip_device =
@@ -124,8 +125,9 @@ static const gx_device_clip gs_clip_device =
clip_strip_copy_rop2,
clip_strip_tile_rect_devn,
clip_copy_alpha_hl_color,
- NULL,
- clip_transform_pixel_region
+ NULL, /* process_page */
+ clip_transform_pixel_region,
+ clip_fill_stroke_path,
}
};
@@ -1634,3 +1636,78 @@ clip_transform_pixel_region(gx_device *dev, transform_pixel_region_reason reason
return ret;
}
+
+static int
+clip_call_fill_stroke_path(clip_callback_data_t * pccd, int xc, int yc, int xec, int yec)
+{
+ gx_device *tdev = pccd->tdev;
+ dev_proc_fill_stroke_path((*proc));
+ int code;
+ gx_clip_path cpath_intersection;
+ gx_clip_path *pcpath = (gx_clip_path *)pccd->pcpath;
+
+ /* Previously the code here tested for pcpath != NULL, but
+ * we can commonly (such as from clist_playback_band) be
+ * called with a non-NULL, but still invalid clip path.
+ * Detect this by the list having at least one entry in it. */
+ if (pcpath != NULL && pcpath->rect_list->list.count != 0) {
+ gx_path rect_path;
+ code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, pccd->ppath->memory, 1);
+ if (code < 0)
+ return code;
+ gx_path_init_local(&rect_path, pccd->ppath->memory);
+ code = gx_path_add_rectangle(&rect_path, int2fixed(xc), int2fixed(yc), int2fixed(xec), int2fixed(yec));
+ if (code < 0)
+ return code;
+ code = gx_cpath_intersect(&cpath_intersection, &rect_path,
+ gx_rule_winding_number, (gs_gstate *)(pccd->pgs));
+ gx_path_free(&rect_path, "clip_call_fill_stroke_path");
+ } else {
+ gs_fixed_rect clip_box;
+ clip_box.p.x = int2fixed(xc);
+ clip_box.p.y = int2fixed(yc);
+ clip_box.q.x = int2fixed(xec);
+ clip_box.q.y = int2fixed(yec);
+ gx_cpath_init_local(&cpath_intersection, pccd->ppath->memory);
+ code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box);
+ }
+ if (code < 0)
+ return code;
+ proc = dev_proc(tdev, fill_stroke_path);
+ if (proc == NULL)
+ proc = gx_default_fill_stroke_path;
+ code = (*proc)(pccd->tdev, pccd->pgs, pccd->ppath, pccd->params,
+ pccd->pdcolor, pccd->stroke_params, pccd->pstroke_dcolor,
+ &cpath_intersection);
+ gx_cpath_free(&cpath_intersection, "clip_call_fill_stroke_path");
+ return code;
+}
+
+static int
+clip_fill_stroke_path(gx_device *dev, const gs_gstate *pgs,
+ gx_path *ppath,
+ const gx_fill_params *params,
+ const gx_drawing_color *pdcolor,
+ const gx_stroke_params *stroke_params,
+ const gx_drawing_color *pstroke_dcolor,
+ const gx_clip_path *pcpath)
+{
+ gx_device_clip *rdev = (gx_device_clip *) dev;
+ clip_callback_data_t ccdata;
+ gs_fixed_rect box;
+
+ ccdata.pgs = pgs;
+ ccdata.ppath = ppath;
+ ccdata.params = params;
+ ccdata.pdcolor = pdcolor;
+ ccdata.stroke_params = stroke_params;
+ ccdata.pstroke_dcolor = pstroke_dcolor;
+ ccdata.pcpath = pcpath;
+ clip_get_clipping_box(dev, &box);
+ return clip_enumerate(rdev,
+ fixed2int(box.p.x),
+ fixed2int(box.p.y),
+ fixed2int(box.q.x - box.p.x),
+ fixed2int(box.q.y - box.p.y),
+ clip_call_fill_stroke_path, &ccdata);
+}
diff --git a/base/gxclip.h b/base/gxclip.h
index 61521ad1d..c052200ce 100644
--- a/base/gxclip.h
+++ b/base/gxclip.h
@@ -42,7 +42,8 @@ typedef struct clip_callback_data_s {
int sourcex; /* ibid. */
uint raster; /* ibid. */
int depth; /* copy_alpha, fill_mask */
- const gx_drawing_color *pdcolor; /* fill_mask, fill_rectangle_hl_color */
+ const gx_drawing_color *pdcolor; /* fill_mask, fill_rectangle_hl_color, fill_path, fill_stroke_path */
+ const gx_drawing_color *pstroke_dcolor; /* fill_stroke_path */
gs_logical_operation_t lop; /* fill_mask, strip_copy_rop */
const gx_clip_path *pcpath; /* fill_mask, fill_rectangle_hl_color*/
const gx_strip_bitmap *tiles; /* strip_tile_rectangle */
@@ -51,9 +52,10 @@ typedef struct clip_callback_data_s {
const gx_strip_bitmap *textures; /* ibid. */
const gx_color_index *tcolors; /* ibid. */
int plane_height; /* copy_planes, strip_copy_rop2 */
- const gs_gstate * pgs; /* fill_path, fill_rectangle_hl_color */
- gx_path * ppath; /* fill_path */
- const gx_fill_params * params; /* fill_path */
+ const gs_gstate *pgs; /* fill_path, fill_stroke_path, fill_rectangle_hl_color */
+ gx_path *ppath; /* fill_path, fill_stroke_path */
+ const gx_fill_params *params; /* fill_path, fill_stroke_path */
+ const gx_stroke_params *stroke_params; /* fill_stroke_path */
} clip_callback_data_t;
/* Declare the callback procedures. */
diff --git a/base/gxclipm.c b/base/gxclipm.c
index 40e503ad5..0a98eb065 100644
--- a/base/gxclipm.c
+++ b/base/gxclipm.c
@@ -113,7 +113,8 @@ const gx_device_mask_clip gs_mask_clip_device =
mask_clip_strip_tile_rect_devn,
mask_clip_copy_alpha_hl_color,
NULL,
- gx_default_transform_pixel_region
+ gx_default_transform_pixel_region,
+ gx_forward_fill_stroke_path,
}
};
diff --git a/base/gxclist.c b/base/gxclist.c
index 833990b78..c5e8feadd 100644
--- a/base/gxclist.c
+++ b/base/gxclist.c
@@ -201,7 +201,8 @@ const gx_device_procs gs_clist_device_procs = {
clist_strip_tile_rect_devn,
clist_copy_alpha_hl_color,
clist_process_page,
- gx_default_transform_pixel_region
+ gx_default_transform_pixel_region,
+ clist_fill_stroke_path,
};
/*------------------- Choose the implementation -----------------------
@@ -577,6 +578,8 @@ clist_reset(gx_device * dev)
cdev->cropping_level = 0;
cdev->mask_id_count = cdev->mask_id = cdev->temp_mask_id = 0;
cdev->icc_table = NULL;
+ cdev->op_fill_active = false;
+ cdev->op_stroke_active = false;
return 0;
}
/*
diff --git a/base/gxclist.h b/base/gxclist.h
index 43cc3d5b1..e1e7ff1b5 100644
--- a/base/gxclist.h
+++ b/base/gxclist.h
@@ -336,8 +336,7 @@ struct gx_device_clist_writer_s {
const gx_clip_path *clip_path; /* current clip path, */
/* only non-transient for images */
gs_id clip_path_id; /* id of current clip path */
- clist_color_space_t color_space; /* current color space, */
- /* only used for non-mask images */
+ clist_color_space_t color_space; /* only used for non-mask images */
gs_id transfer_ids[4]; /* ids of transfer maps */
gs_id black_generation_id; /* id of black generation map */
gs_id undercolor_removal_id; /* id of u.c.r. map */
@@ -366,6 +365,9 @@ struct gx_device_clist_writer_s {
access to the graphic state information in those
routines, this is the logical place to put this
information */
+ bool op_fill_active; /* Needed so we know state during clist writing */
+ bool op_stroke_active; /* Needed so we know state during clist writing */
+
};
/* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */
diff --git a/base/gxclpath.c b/base/gxclpath.c
index cc5a5e3e4..32012dd10 100644
--- a/base/gxclpath.c
+++ b/base/gxclpath.c
@@ -127,14 +127,18 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
pdht->id != cldev->device_halftone_id ) {
if ((code = cmd_put_halftone(cldev, pdht)) < 0)
return code;
- color_unset(psdc);
+ psdc->type = gx_dc_type_none; /* force writing */
}
+ if (psdc->devn_type != devn_type) {
+ psdc->type = gx_dc_type_none; /* force writing if fill/stroke mismatch. */
+ psdc->devn_type = devn_type;
+ }
/*
* Get the device color type index and the required size.
*
* The complete cmd_opv_ext_put_drawing_color consists of:
- * comand code (2 bytes)
+ * command code (2 bytes)
* tile index value or non tile color (1)
* device color type index (1)
* length of serialized device color (enc_u_sizew(dc_size))
@@ -149,7 +153,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
&dc_size );
/* if the returned value is > 0, no change in the color is necessary */
- if (code > 0 && devn_type == devn_not_tile)
+ if (code > 0 && ((devn_type == devn_not_tile_fill) || (devn_type == devn_not_tile_stroke)))
return 0;
else if (code < 0 && code != gs_error_rangecheck)
return code;
@@ -216,8 +220,11 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
return code;
dp0 = dp;
switch (devn_type) {
- case devn_not_tile:
- dp[1] = cmd_opv_ext_put_drawing_color;
+ case devn_not_tile_fill:
+ dp[1] = cmd_opv_ext_put_fill_dcolor;
+ break;
+ case devn_not_tile_stroke:
+ dp[1] = cmd_opv_ext_put_stroke_dcolor;
break;
case devn_tile0:
dp[1] = cmd_opv_ext_put_tile_devn_color0;
@@ -226,7 +233,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
dp[1] = cmd_opv_ext_put_tile_devn_color1;
break;
default:
- dp[1] = cmd_opv_ext_put_drawing_color;
+ dp[1] = cmd_opv_ext_put_fill_dcolor;
}
dp += 2;
*dp++ = di | (offset > 0 ? 0x80 : 0);
@@ -365,9 +372,9 @@ cmd_check_clip_path(gx_device_clist_writer * cldev, const gx_clip_path * pcpath)
(cj_ac_sa_known | flatness_known | op_bm_tk_known | opacity_alpha_known |\
shape_alpha_known | fill_adjust_known | alpha_known | clip_path_known)
static void
-cmd_check_fill_known(gx_device_clist_writer *cdev, const gs_gstate *pgs,
- double flatness, const gs_fixed_point *padjust,
- const gx_clip_path *pcpath, uint *punknown)
+cmd_check_fill_known(gx_device_clist_writer* cdev, const gs_gstate* pgs,
+ double flatness, const gs_fixed_point* padjust,
+ const gx_clip_path* pcpath, uint* punknown)
{
/*
* stroke_adjust is not needed for fills, and none of these are needed
@@ -391,14 +398,15 @@ cmd_check_fill_known(gx_device_clist_writer *cdev, const gs_gstate *pgs,
* though both parameters are passed in the state as well, this usually
* has no effect.
*/
- if (state_neq(overprint) || state_neq(effective_overprint_mode) ||
+ if (state_neq(overprint) || state_neq(overprint_mode) ||
state_neq(blend_mode) || state_neq(text_knockout) ||
- state_neq(renderingintent)) {
+ state_neq(stroke_overprint) || state_neq(renderingintent)) {
*punknown |= op_bm_tk_known;
state_update(overprint);
- state_update(effective_overprint_mode);
+ state_update(overprint_mode);
state_update(blend_mode);
state_update(text_knockout);
+ state_update(stroke_overprint);
state_update(renderingintent);
}
if (state_neq(opacity.alpha)) {
@@ -477,7 +485,7 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
sizeof(float) + /* flatness */
sizeof(float) + /* line width */
sizeof(float) + /* miter limit */
- 2 + /* op_bm_tk and rend intent */
+ 3 + /* bm_tk, op, and rend intent */
sizeof(float) * 2 + /* opacity/shape alpha */
sizeof(cldev->gs_gstate.alpha)
];
@@ -513,8 +521,10 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
if (unknown & op_bm_tk_known) {
*bp++ =
((int)cldev->gs_gstate.blend_mode << 3) +
- (cldev->gs_gstate.text_knockout << 2) +
- (cldev->gs_gstate.overprint_mode << 1) +
+ cldev->gs_gstate.text_knockout;
+ *bp++ =
+ (cldev->gs_gstate.overprint_mode << 2) +
+ (cldev->gs_gstate.stroke_overprint << 1) +
cldev->gs_gstate.overprint;
*bp++ = cldev->gs_gstate.renderingintent;
}
@@ -846,7 +856,7 @@ clist_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
)
return code;
code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
- devn_not_tile);
+ devn_not_tile_fill);
if (code == gs_error_unregistered)
return code;
if (code < 0) {
@@ -869,6 +879,188 @@ clist_fill_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
}
int
+clist_fill_stroke_path(gx_device * pdev, const gs_gstate * pgs,
+ gx_path * ppath,
+ const gx_fill_params * params_fill,
+ const gx_device_color * pdevc_fill,
+ const gx_stroke_params * params_stroke,
+ const gx_device_color * pdevc_stroke,
+ const gx_clip_path * pcpath)
+{
+ gx_device_clist_writer * const cdev =
+ &((gx_device_clist *)pdev)->writer;
+ int pattern_size = pgs->line_params.dash.pattern_size;
+ byte op = (byte) (params_fill->rule == gx_rule_even_odd ?
+ cmd_opv_eofill_stroke : cmd_opv_fill_stroke);
+ uint unknown = 0;
+ gs_fixed_rect bbox;
+ gs_fixed_point expansion;
+ int adjust_y, expansion_code;
+ int ry, rheight;
+ gs_logical_operation_t lop = pgs->log_op;
+ bool slow_rop = cmd_slow_rop(pdev, lop_know_S_0(lop), pdevc_fill);
+ cmd_rects_enum_t re;
+
+ if ((cdev->disable_mask & (clist_disable_fill_path || clist_disable_stroke_path)) ||
+ gs_debug_c(',')
+ ) {
+ /* Disable path-based banding. */
+ return gx_default_fill_stroke_path(pdev, pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ }
+ /* TODO: For now punt to default if we have shaded color (pattern2) */
+ if ((pdevc_fill != NULL && gx_dc_is_pattern2_color(pdevc_fill)) ||
+ (pdevc_stroke != NULL && gx_dc_is_pattern2_color(pdevc_stroke)) ) {
+ return gx_default_fill_stroke_path(pdev, pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ }
+ gx_path_bbox(ppath, &bbox);
+ /* We must use the supplied gs_gstate, not our saved one, */
+ /* for computing the stroke expansion. */
+ expansion_code = gx_stroke_path_expansion(pgs, ppath, &expansion);
+ if (expansion_code < 0) {
+ /* Expansion is too large: use the entire page. */
+ adjust_y = 0;
+ ry = 0;
+ rheight = pdev->height;
+ } else {
+ adjust_y = fixed2int_ceiling(expansion.y) + 1;
+ ry = fixed2int(bbox.p.y) - adjust_y;
+ rheight = fixed2int_ceiling(bbox.q.y) - ry + adjust_y;
+ fit_fill_y(pdev, ry, rheight);
+ fit_fill_h(pdev, ry, rheight);
+ if (rheight <= 0)
+ return 0;
+ }
+ /* Check the dash pattern, since we bail out if */
+ /* the pattern is too large. */
+ if (cdev->gs_gstate.line_params.dash.pattern_size != pattern_size ||
+ (pattern_size != 0 &&
+ memcmp(cdev->dash_pattern, pgs->line_params.dash.pattern,
+ pattern_size * sizeof(float))) ||
+ cdev->gs_gstate.line_params.dash.offset !=
+ pgs->line_params.dash.offset ||
+ cdev->gs_gstate.line_params.dash.adapt !=
+ pgs->line_params.dash.adapt ||
+ cdev->gs_gstate.line_params.dot_length !=
+ pgs->line_params.dot_length ||
+ cdev->gs_gstate.line_params.dot_length_absolute !=
+ pgs->line_params.dot_length_absolute
+ ) {
+ /* Bail out if the dash pattern is too long. */
+ if (pattern_size > cmd_max_dash)
+ return gx_default_fill_stroke_path(pdev, pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ unknown |= dash_known;
+ /*
+ * Temporarily reset the dash pattern pointer for gx_set_dash,
+ * but don't leave it set, since that would confuse the GC.
+ */
+ cdev->gs_gstate.line_params.dash.pattern = cdev->dash_pattern;
+ gx_set_dash(&cdev->gs_gstate.line_params.dash,
+ pgs->line_params.dash.pattern,
+ pgs->line_params.dash.pattern_size,
+ pgs->line_params.dash.offset, NULL);
+ cdev->gs_gstate.line_params.dash.pattern = 0;
+ gx_set_dash_adapt(&cdev->gs_gstate.line_params.dash,
+ pgs->line_params.dash.adapt);
+ gx_set_dot_length(&cdev->gs_gstate.line_params,
+ pgs->line_params.dot_length,
+ pgs->line_params.dot_length_absolute);
+ }
+
+ if (state_neq(line_params.start_cap) || state_neq(line_params.join) ||
+ state_neq(line_params.end_cap) || state_neq(line_params.dash_cap)) {
+ unknown |= cap_join_known;
+ state_update(line_params.start_cap);
+ state_update(line_params.end_cap);
+ state_update(line_params.dash_cap);
+ state_update(line_params.join);
+ }
+ cmd_check_fill_known(cdev, pgs, params_fill->flatness, &pgs->fill_adjust,
+ pcpath, &unknown);
+ if (state_neq(line_params.half_width)) {
+ unknown |= line_width_known;
+ state_update(line_params.half_width);
+ }
+ if (state_neq(line_params.miter_limit)) {
+ unknown |= miter_limit_known;
+ gx_set_miter_limit(&cdev->gs_gstate.line_params,
+ pgs->line_params.miter_limit);
+ }
+ if (state_neq(ctm.xx) || state_neq(ctm.xy) ||
+ state_neq(ctm.yx) || state_neq(ctm.yy) ||
+ /* We don't actually need tx or ty, but we don't want to bother */
+ /* tracking them separately from the other coefficients. */
+ state_neq(ctm.tx) || state_neq(ctm.ty)
+ ) {
+ unknown |= ctm_known;
+ state_update(ctm);
+ }
+ if (unknown)
+ cmd_clear_known(cdev, unknown);
+ if (cdev->permanent_error < 0)
+ return (cdev->permanent_error);
+ /* If needed, update the trans_bbox */
+ if (cdev->pdf14_needed) {
+ gs_int_rect trans_bbox;
+ int rx = fixed2int(bbox.p.x) - 1;
+ int rwidth = fixed2int_ceiling(bbox.q.x) - rx + 1;
+ unknown |= STROKE_ALL_KNOWN;
+
+ fit_fill_w(cdev, rx, rwidth);
+ trans_bbox.p.x = rx;
+ trans_bbox.q.x = rx + rwidth - 1;
+ trans_bbox.p.y = ry;
+ trans_bbox.q.y = ry + rheight - 1;
+
+ clist_update_trans_bbox(cdev, &trans_bbox);
+ }
+ /* If either fill or stroke uses overprint, or overprint_mode != 0, then we */
+ /* need to write out the overprint drawn_comps and retain_* */
+ if (((pgs->overprint_mode || pgs->overprint || pgs->stroke_overprint))) {
+ unknown |= op_bm_tk_known;
+ }
+ RECT_ENUM_INIT(re, ry, rheight);
+ do {
+ int code;
+ fixed ymin, ymax;
+
+ RECT_STEP_INIT(re);
+ if ((code = cmd_do_write_unknown(cdev, re.pcls, STROKE_ALL_KNOWN | FILL_KNOWN)) < 0)
+ return code;
+ if ((code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0)
+ return code;
+ if ((code = cmd_update_lop(cdev, re.pcls, lop)) < 0)
+ return code;
+ /* Write the stroke first since do_fill_stroke will have locked the pattern */
+ /* tile if needed, and we want it locked after reading the stroke color. */
+ code = cmd_put_drawing_color(cdev, re.pcls, pdevc_stroke, &re, devn_not_tile_stroke);
+ if (code < 0) {
+ /* Something went wrong, use the default implementation. */
+ return gx_default_fill_stroke_path(pdev, pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ }
+ code = cmd_put_drawing_color(cdev, re.pcls, pdevc_fill, &re, devn_not_tile_fill);
+ if (code < 0) {
+ /* Something went wrong, use the default implementation. */
+ return gx_default_fill_stroke_path(pdev, pgs, ppath, params_fill, pdevc_fill,
+ params_stroke, pdevc_stroke, pcpath);
+ }
+ re.pcls->color_usage.slow_rop |= slow_rop;
+
+ /* Don't skip segments when expansion is unknown. */
+
+ code = cmd_put_path(cdev, re.pcls, ppath, min_fixed, max_fixed,
+ op, false, (segment_notes)~0);
+ if (code < 0)
+ return code;
+ re.y += re.height;
+ } while (re.y < re.yend);
+ return 0;
+}
+
+int
clist_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
const gx_stroke_params * params,
const gx_drawing_color * pdcolor, const gx_clip_path * pcpath)
@@ -1000,13 +1192,13 @@ clist_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
RECT_STEP_INIT(re);
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev);
- if ((code = cmd_do_write_unknown(cdev, re.pcls, stroke_all_known)) < 0 ||
+ if ((code = cmd_do_write_unknown(cdev, re.pcls, STROKE_ALL_KNOWN)) < 0 ||
(code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0 ||
(code = cmd_update_lop(cdev, re.pcls, lop)) < 0
)
return code;
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev);
- code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile);
+ code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile_stroke);
if (code == gs_error_unregistered)
return code;
if (code < 0) {
@@ -1102,7 +1294,7 @@ clist_put_polyfill(gx_device *dev, fixed px, fixed py,
do {
RECT_STEP_INIT(re);
if ((code = cmd_update_lop(cdev, re.pcls, lop)) < 0 ||
- (code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile)) < 0)
+ (code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile_fill)) < 0)
goto out;
re.pcls->color_usage.slow_rop |= slow_rop;
code = cmd_put_path(cdev, re.pcls, &path,
diff --git a/base/gxclpath.h b/base/gxclpath.h
index cda124e26..19e008c2d 100644
--- a/base/gxclpath.h
+++ b/base/gxclpath.h
@@ -42,11 +42,12 @@
#define alpha_known (1<<9)
#define misc2_all_known ((1<<10)-1)
/* End of misc2 flags. */
+/* The following bits don't get passed in misc2, so are only limited by sizeof uint */
#define fill_adjust_known (1<<10)
#define ctm_known (1<<11)
#define dash_known (1<<12)
#define clip_path_known (1<<13)
-#define stroke_all_known ((1<<14)-1)
+#define STROKE_ALL_KNOWN ((1<<14)-1)
#define color_space_known (1<<14)
/*#define all_known ((1<<15)-1) */
@@ -145,44 +146,49 @@ typedef enum {
cmd_opv_fill = 0xf0,
cmd_opv_rgapto = 0xf1, /* dx%, dy% */
cmd_opv_eofill = 0xf3,
+ cmd_opv_fill_stroke = 0xf4,
+ cmd_opv_eofill_stroke = 0xf5,
cmd_opv_stroke = 0xf6,
cmd_opv_polyfill = 0xf9,
cmd_opv_fill_trapezoid = 0xfc
#define cmd_path_op_name_strings\
"fill", "rgapto", "?f2?", "eofill",\
- "?f4?", "?f5", "stroke", "?f7?",\
+ "fill_stroke", "eofill_stroke", "stroke", "?f7?",\
"?f8?", "polyfill", "?fa?", "?fb?",\
"fill_trapezoid", "?fd?", "?fe?", "?ff?"
-/* unused cmd_op values: 0xd0, 0xf2, 0xf4, 0xf5, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfd, 0xfe, 0xff */
+/* unused cmd_op values: 0xd0, 0xf2, 0xf7, 0xf8, 0xfa, 0xfb, 0xfd, 0xfe, 0xff */
} gx_cmd_xop;
/* This is usd for cmd_opv_ext_put_drawing_color so that we know if it
- is assocated with a tile or not */
+ is assocated with a tile or not and for fill or stroke color */
typedef enum {
- devn_not_tile = 0x00,
- devn_tile0 = 0x01,
- devn_tile1 = 0x02
+ devn_not_tile_fill = 0x00,
+ devn_not_tile_stroke = 0x01,
+ devn_tile0 = 0x02,
+ devn_tile1 = 0x03
} dc_devn_cl_type;
/*
* Further extended command set. This code always occupies a byte, which
* is the second byte of a command whose first byte is cmd_opv_extend.
*/
typedef enum {
- cmd_opv_ext_put_params = 0x00, /* serialized parameter list */
- cmd_opv_ext_create_compositor = 0x01, /* compositor id,
- * serialized compositor */
- cmd_opv_ext_put_halftone = 0x02, /* length of entire halftone */
- cmd_opv_ext_put_ht_seg = 0x03, /* segment length,
- * halftone segment data */
- cmd_opv_ext_put_drawing_color = 0x04, /* length, color type id,
- * serialized color */
- cmd_opv_ext_tile_rect_hl = 0x05, /* Uses devn colors in tiling fill */
- cmd_opv_ext_put_tile_devn_color0 = 0x6, /* Devn color0 for tile filling */
- cmd_opv_ext_put_tile_devn_color1 = 0x7, /* Devn color1 for tile filling */
- cmd_opv_ext_set_color_is_devn = 0x8, /* Used for overload of copy_color_alpha */
- cmd_opv_ext_unset_color_is_devn = 0x9 /* Used for overload of copy_color_alpha */
+ cmd_opv_ext_put_params = 0x00, /* serialized parameter list */
+ cmd_opv_ext_create_compositor = 0x01, /* compositor id,
+ * serialized compositor */
+ cmd_opv_ext_put_halftone = 0x02, /* length of entire halftone */
+ cmd_opv_ext_put_ht_seg = 0x03, /* segment length,
+ * halftone segment data */
+ cmd_opv_ext_put_fill_dcolor = 0x04, /* length, color type id,
+ * serialized color */
+ cmd_opv_ext_put_stroke_dcolor = 0x05, /* length, color type id,
+ * serialized color */
+ cmd_opv_ext_tile_rect_hl = 0x06, /* Uses devn colors in tiling fill */
+ cmd_opv_ext_put_tile_devn_color0 = 0x07, /* Devn color0 for tile filling */
+ cmd_opv_ext_put_tile_devn_color1 = 0x08, /* Devn color1 for tile filling */
+ cmd_opv_ext_set_color_is_devn = 0x09, /* Used for overload of copy_color_alpha */
+ cmd_opv_ext_unset_color_is_devn = 0x0a /* Used for overload of copy_color_alpha */
} gx_cmd_ext_op;
#define cmd_segment_op_num_operands_values\
@@ -210,6 +216,7 @@ typedef enum {
/* In gxclpath.c */
dev_proc_fill_path(clist_fill_path);
dev_proc_stroke_path(clist_stroke_path);
+dev_proc_fill_stroke_path(clist_fill_stroke_path);
dev_proc_fill_parallelogram(clist_fill_parallelogram);
dev_proc_fill_triangle(clist_fill_triangle);
diff --git a/base/gxclrast.c b/base/gxclrast.c
index b75054f50..c58e0af00 100644
--- a/base/gxclrast.c
+++ b/base/gxclrast.c
@@ -249,9 +249,8 @@ static int read_set_bits(command_buf_t *pcb, tile_slot *bits,
gx_device_clist_reader *cdev, gs_memory_t *mem);
static int read_set_misc2(command_buf_t *pcb, gs_gstate *pgs,
segment_notes *pnotes);
-static int read_set_color_space(command_buf_t *pcb, gs_gstate *pgs,
- gs_color_space **ppcs, gx_device_clist_reader *cdev,
- gs_memory_t *mem);
+static int read_set_color_space(command_buf_t *pcb, gs_gstate *pgs, gs_color_space **ppcs,
+ gx_device_clist_reader *cdev, gs_memory_t *mem);
static int read_begin_image(command_buf_t *pcb, gs_image_common_t *pic,
gs_color_space *pcs);
static int read_put_params(command_buf_t *pcb, gs_gstate *pgs,
@@ -510,7 +509,8 @@ clist_playback_band(clist_playback_action playback_action,
} clip_save;
bool in_clip = false;
gs_gstate gs_gstate;
- gx_device_color dev_color;
+ gx_device_color fill_color;
+ gx_device_color stroke_color;
float dash_pattern[cmd_max_dash];
gx_fill_params fill_params;
gx_stroke_params stroke_params;
@@ -611,6 +611,19 @@ in: /* Initialize for a new page. */
memset(&gs_gstate, 0, sizeof(gs_gstate));
GS_STATE_INIT_VALUES_CLIST((&gs_gstate));
code = gs_gstate_initialize(&gs_gstate, mem);
+ gs_gstate.device = tdev;
+ gs_gstate.view_clip = NULL; /* Avoid issues in pdf14 fill stroke */
+ gs_gstate.clip_path = &clip_path;
+ pcs = gs_cspace_new_DeviceGray(mem);
+ if (pcs == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto out;
+ }
+ pcs->type->install_cspace(pcs, &gs_gstate);
+ gs_gstate.color[0].color_space = pcs;
+ rc_increment_cs(pcs);
+ gs_gstate.color[1].color_space = pcs;
+ rc_increment_cs(pcs);
/* Remove the ICC link cache and replace with the device link cache
so that we share the cache across bands */
rc_decrement(gs_gstate.icc_link_cache,"clist_playback_band");
@@ -630,13 +643,8 @@ in: /* Initialize for a new page. */
#ifdef DEBUG
halftone_type = ht_type_none;
#endif
- pcs = gs_cspace_new_DeviceGray(mem);
- if (pcs == NULL) {
- code = gs_note_error(gs_error_VMerror);
- goto out;
- }
- dev_color.ccolor_valid = false;
- color_unset(&dev_color);
+ fill_color.ccolor_valid = false;
+ color_unset(&fill_color);
data_bits = gs_alloc_bytes(mem, data_bits_size,
"clist_playback_band(data_bits)");
if (data_bits == 0) {
@@ -1290,9 +1298,9 @@ set_phase: /*
&target_box);
tdev = (gx_device *)&clip_accum;
clip_save.lop_enabled = state.lop_enabled;
- clip_save.dcolor = dev_color;
+ clip_save.dcolor = fill_color;
/* temporarily set a solid color */
- color_set_pure(&dev_color, (gx_color_index)1);
+ color_set_pure(&fill_color, (gx_color_index)1);
state.lop_enabled = false;
gs_gstate.log_op = lop_default;
break;
@@ -1325,13 +1333,13 @@ set_phase: /*
gs_gstate.log_op =
(state.lop_enabled ? state.lop :
lop_default);
- dev_color = clip_save.dcolor;
+ fill_color = clip_save.dcolor;
in_clip = false;
break;
case cmd_opv_set_color_space:
cbuf.ptr = cbp;
- code = read_set_color_space(&cbuf, &gs_gstate,
- &pcs, cdev, mem);
+ code = read_set_color_space(&cbuf, &gs_gstate, &pcs, cdev, mem);
+ pcs = gs_gstate.color[0].color_space;
cbp = cbuf.ptr;
if (code < 0) {
if (code == gs_error_rangecheck)
@@ -1344,7 +1352,7 @@ set_phase: /*
gs_fixed_rect rect_hl;
cbp = cmd_read_rect(op & 0xf0, &state.rect, cbp);
- if (dev_color.type != gx_dc_type_devn) {
+ if (fill_color.type != gx_dc_type_devn) {
if_debug0m('L', mem, "hl rect fill without devn color\n");
code = gs_note_error(gs_error_typecheck);
goto out;
@@ -1358,7 +1366,7 @@ set_phase: /*
rect_hl.q.y = int2fixed(state.rect.height) + rect_hl.p.y;
code = dev_proc(tdev, fill_rectangle_hl_color) (tdev,
&rect_hl, NULL,
- &dev_color, NULL);
+ &fill_color, NULL);
}
continue;
case cmd_opv_begin_image_rect:
@@ -1400,7 +1408,7 @@ ibegin: if_debug0m('L', mem, "\n");
code = (*dev_proc(tdev, begin_typed_image))
(tdev, &gs_gstate, NULL,
(const gs_image_common_t *)&image,
- &image_rect, &dev_color, pcpath, mem,
+ &image_rect, &fill_color, pcpath, mem,
&image_info);
}
if (code < 0)
@@ -1785,14 +1793,17 @@ idata: data_size = 0;
&(state.tile_color_devn[1]),
tile_phase.x, tile_phase.y);
break;
+ case cmd_opv_ext_put_fill_dcolor:
+ pdcolor = &fill_color;
+ goto load_dcolor;
+ case cmd_opv_ext_put_stroke_dcolor:
+ pdcolor = &stroke_color;
+ goto load_dcolor;
case cmd_opv_ext_put_tile_devn_color0:
pdcolor = &set_dev_colors[0];
goto load_dcolor;
case cmd_opv_ext_put_tile_devn_color1:
pdcolor = &set_dev_colors[1];
- goto load_dcolor;
- case cmd_opv_ext_put_drawing_color:
- pdcolor = &dev_color;
load_dcolor:{
uint color_size;
int left, offset, l;
@@ -1952,10 +1963,38 @@ idata: data_size = 0;
fill:
fill_params.adjust = gs_gstate.fill_adjust;
fill_params.flatness = gs_gstate.flatness;
- code = gx_fill_path_only(ppath, tdev,
- &gs_gstate,
- &fill_params,
- &dev_color, pcpath);
+ code = (*dev_proc(tdev, fill_path))(tdev, &gs_gstate, ppath,
+ &fill_params, &fill_color, pcpath);
+ break;
+ case cmd_opv_fill_stroke:
+ fill_params.rule = gx_rule_winding_number;
+ goto fill_stroke;
+ case cmd_opv_eofill_stroke:
+ fill_params.rule = gx_rule_even_odd;
+ fill_stroke:
+ fill_params.adjust = gs_gstate.fill_adjust;
+ fill_params.flatness = gs_gstate.flatness;
+ stroke_params.flatness = gs_gstate.flatness;
+ stroke_params.traditional = false;
+ code = (*dev_proc(tdev, fill_stroke_path))(tdev, &gs_gstate, ppath,
+ &fill_params, &fill_color,
+ &stroke_params, &stroke_color, pcpath);
+ /* if the color is a pattern, it may have had the "is_locked" flag set */
+ /* clear those now (see do_fill_stroke). */
+ if (gx_dc_is_pattern1_color(&stroke_color)) {
+ gs_id id = stroke_color.colors.pattern.p_tile->id;
+
+ code = gx_pattern_cache_entry_set_lock(&gs_gstate, id, false);
+ if (code < 0)
+ return code; /* unlock failed -- should not happen */
+ }
+ if (gx_dc_is_pattern1_color(&fill_color)) {
+ gs_id id = fill_color.colors.pattern.p_tile->id;
+
+ code = gx_pattern_cache_entry_set_lock(&gs_gstate, id, false);
+ if (code < 0)
+ return code; /* unlock failed -- should not happen */
+ }
break;
case cmd_opv_stroke:
stroke_params.flatness = gs_gstate.flatness;
@@ -1963,10 +2002,10 @@ idata: data_size = 0;
code = (*dev_proc(tdev, stroke_path))
(tdev, &gs_gstate,
ppath, &stroke_params,
- &dev_color, pcpath);
+ &stroke_color, pcpath);
break;
case cmd_opv_polyfill:
- code = clist_do_polyfill(tdev, ppath, &dev_color,
+ code = clist_do_polyfill(tdev, ppath, &fill_color,
gs_gstate.log_op);
break;
case cmd_opv_fill_trapezoid:
@@ -2109,7 +2148,7 @@ idata: data_size = 0;
code = gx_default_fill_trapezoid(ttdev, &left, &right,
max(ybot - y0f, fixed_half),
min(ytop - y0f, int2fixed(wh)), swap_axes,
- &dev_color, gs_gstate.log_op);
+ &fill_color, gs_gstate.log_op);
}
break;
default:
@@ -2155,7 +2194,7 @@ idata: data_size = 0;
* is open pending a proper fix. */
code = (dev_proc(tdev, fillpage) == NULL ? 0 :
(*dev_proc(tdev, fillpage))(tdev, &gs_gstate,
- &dev_color));
+ &fill_color));
break;
}
case cmd_op_fill_rect_short >> 4:
@@ -2201,7 +2240,7 @@ idata: data_size = 0;
case cmd_op_tile_rect >> 4:
if (state.rect.width == 0 && state.rect.height == 0 &&
state.rect.x == 0 && state.rect.y == 0) {
- code = (*dev_proc(tdev, fillpage))(tdev, &gs_gstate, &dev_color);
+ code = (*dev_proc(tdev, fillpage))(tdev, &gs_gstate, &fill_color);
break;
}
case cmd_op_tile_rect_short >> 4:
@@ -2228,7 +2267,7 @@ idata: data_size = 0;
(tdev, source, data_x, raster, gx_no_bitmap_id,
state.rect.x - x0, state.rect.y - y0,
state.rect.width - data_x, state.rect.height,
- &dev_color, 1, gs_gstate.log_op, pcpath);
+ &fill_color, 1, gs_gstate.log_op, pcpath);
} else {
if (plane_height == 0) {
code = (*dev_proc(tdev, copy_mono))
@@ -2256,7 +2295,7 @@ idata: data_size = 0;
(tdev, source, data_x, raster, gx_no_bitmap_id,
state.rect.x - x0, state.rect.y - y0,
state.rect.width - data_x, state.rect.height,
- &dev_color, depth);
+ &fill_color, depth);
} else {
code = (*dev_proc(tdev, copy_alpha))
(tdev, source, data_x, raster, gx_no_bitmap_id,
@@ -2297,7 +2336,6 @@ idata: data_size = 0;
if (code == 0)
code = code1;
}
- rc_decrement_cs(pcs, "clist_playback_band");
gx_cpath_free(&clip_path, "clist_render_band exit");
gx_path_free(&path, "clist_render_band exit");
if (gs_gstate.pattern_cache != NULL) {
@@ -2342,6 +2380,7 @@ idata: data_size = 0;
goto in;
if (pfs.dev != NULL)
term_patch_fill_state(&pfs);
+ gs_free_object(mem, pcs, "clist_playback_band(pcs)");
gs_free_object(mem, cbuf_storage, "clist_playback_band(cbuf_storage)");
gx_cpath_free(&clip_path, "clist_playback_band");
if (pcpath != &clip_path)
@@ -2682,16 +2721,17 @@ read_set_misc2(command_buf_t *pcb, gs_gstate *pgs, segment_notes *pnotes)
if (mask & op_bm_tk_known) {
cb = *cbp++;
pgs->blend_mode = cb >> 3;
- pgs->text_knockout = (cb & 4) != 0;
+ pgs->text_knockout = cb & 1;
/* the following usually have no effect; see gxclpath.c */
- pgs->overprint_mode = (cb >> 1) & 1;
- pgs->effective_overprint_mode = pgs->overprint_mode;
+ cb = *cbp++;
+ pgs->overprint_mode = (cb >> 2) & 1;
+ pgs->stroke_overprint = (cb >> 1) & 1;
pgs->overprint = cb & 1;
cb = *cbp++;
pgs->renderingintent = cb;
- if_debug5m('L', pgs->memory, " BM=%d TK=%d OPM=%d OP=%d RI=%d\n",
+ if_debug6m('L', pgs->memory, " BM=%d TK=%d OPM=%d OP=%d op=%d RI=%d\n",
pgs->blend_mode, pgs->text_knockout, pgs->overprint_mode,
- pgs->overprint, pgs->renderingintent);
+ pgs->stroke_overprint, pgs->overprint, pgs->renderingintent);
}
if (mask & segment_notes_known) {
cb = *cbp++;
@@ -2715,9 +2755,8 @@ read_set_misc2(command_buf_t *pcb, gs_gstate *pgs, segment_notes *pnotes)
}
static int
-read_set_color_space(command_buf_t *pcb, gs_gstate *pgs,
- gs_color_space **ppcs, gx_device_clist_reader *cdev,
- gs_memory_t *mem)
+read_set_color_space(command_buf_t *pcb, gs_gstate *pgs, gs_color_space** ppcs,
+ gx_device_clist_reader *cdev, gs_memory_t *mem)
{
const byte *cbp = pcb->ptr;
byte b = *cbp++;
@@ -2727,6 +2766,8 @@ read_set_color_space(command_buf_t *pcb, gs_gstate *pgs,
cmm_profile_t *picc_profile;
clist_icc_color_t icc_information;
+ ppcs = &pcs;
+
if_debug3m('L', mem, " %d%s%s\n", index,
(b & 8 ? " (indexed)" : ""),
(b & 4 ? "(proc)" : ""));
@@ -2832,8 +2873,9 @@ read_set_color_space(command_buf_t *pcb, gs_gstate *pgs,
}
/* Release reference to old color space before installing new one. */
- rc_decrement_only_cs(*ppcs, "read_set_color_space");
- *ppcs = pcs;
+ if (pgs->color[0].color_space != NULL)
+ rc_decrement_only_cs(pgs->color[0].color_space, "read_set_color_space");
+ pgs->color[0].color_space = pcs;
out:
pcb->ptr = cbp;
return code;
diff --git a/base/gxclrect.c b/base/gxclrect.c
index 6f53ddd5e..00f01ba26 100644
--- a/base/gxclrect.c
+++ b/base/gxclrect.c
@@ -321,7 +321,7 @@ clist_fillpage(gx_device * dev, gs_gstate *pgs, gx_drawing_color *pdcolor)
pcls = cdev->states; /* Use any. */
- code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL, devn_not_tile);
+ code = cmd_put_drawing_color(cdev, pcls, pdcolor, NULL, devn_not_tile_fill);
if (code >= 0)
code = cmd_write_page_rect_cmd(cdev, cmd_op_fill_rect);
return code;
@@ -414,7 +414,7 @@ clist_fill_rectangle_hl_color(gx_device *dev, const gs_fixed_rect *rect,
re.pcls->color_usage.or |= color_usage;
code = cmd_disable_lop(cdev, re.pcls);
code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
- devn_not_tile);
+ devn_not_tile_fill);
if (code >= 0) {
code = cmd_write_rect_hl_cmd(cdev, re.pcls, cmd_op_fill_rect_hl,
rx, re.y, rwidth, re.height, false);
@@ -492,7 +492,7 @@ clist_write_fill_trapezoid(gx_device * dev,
RECT_STEP_INIT(re);
if (pdcolor != NULL) {
code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re,
- devn_not_tile);
+ devn_not_tile_fill);
if (code == gs_error_unregistered)
return code;
if (code < 0) {
@@ -618,6 +618,10 @@ clist_dev_spec_op(gx_device *pdev, int dev_spec_op, void *data, int size)
ibox->q.y = cwdev->cropping_max;
return 0;
}
+ if (dev_spec_op == gxdso_overprint_active) {
+ gx_device_clist_writer* cwdev = &((gx_device_clist*)pdev)->writer;
+ return cwdev->op_fill_active || cwdev->op_stroke_active;
+ }
/* forward to the appropriate super class */
if (cdev->is_printer)
return gdev_prn_forwarding_dev_spec_op(pdev, dev_spec_op, data, size);
@@ -1216,7 +1220,7 @@ clist_copy_alpha_hl_color(gx_device * dev, const byte * data, int data_x,
re.pcls->color_is_alpha = 1;
}
/* Set the color */
- code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile);
+ code = cmd_put_drawing_color(cdev, re.pcls, pdcolor, &re, devn_not_tile_fill);
copy:{
gx_cmd_rect rect;
int rsize;
diff --git a/base/gxcmap.c b/base/gxcmap.c
index 417a2ea03..68d3a0bfc 100644
--- a/base/gxcmap.c
+++ b/base/gxcmap.c
@@ -570,9 +570,6 @@ gx_remap_color(gs_gstate * pgs)
pcs, gs_currentdevicecolor_inline(pgs),
(gs_gstate *) pgs, pgs->device,
gs_color_select_texture);
- /* if overprint mode is in effect, update the overprint information */
- if (code >= 0 && pgs->overprint)
- code = gs_do_set_overprint(pgs);
return code;
}
diff --git a/base/gxdevcli.h b/base/gxdevcli.h
index 5524ff81f..30d0eda01 100644
--- a/base/gxdevcli.h
+++ b/base/gxdevcli.h
@@ -1035,6 +1035,19 @@ typedef enum FILTER_FLAGS {
#define dev_proc_stroke_path(proc)\
dev_t_proc_stroke_path(proc, gx_device)
+ /* Added in release 9.22 */
+
+#define dev_t_proc_fill_stroke_path(proc, dev_t)\
+ int proc(dev_t *dev,\
+ const gs_gstate *pgs, gx_path *ppath,\
+ const gx_fill_params *fill_params,\
+ const gx_drawing_color *pdcolor_fill,\
+ const gx_stroke_params *stroke_params,\
+ const gx_drawing_color *pdcolor_stroke,\
+ const gx_clip_path *pcpath)
+#define dev_proc_fill_stroke_path(proc)\
+ dev_t_proc_fill_stroke_path(proc, gx_device)
+
/* Added in release 3.60 */
#define dev_t_proc_fill_mask(proc, dev_t)\
@@ -1642,6 +1655,7 @@ typedef struct {
dev_t_proc_copy_alpha_hl_color((*copy_alpha_hl_color), dev_t);\
dev_t_proc_process_page((*process_page), dev_t);\
dev_t_proc_transform_pixel_region((*transform_pixel_region), dev_t);\
+ dev_t_proc_fill_stroke_path((*fill_stroke_path), dev_t);\
}
/*
diff --git a/base/gxdevice.h b/base/gxdevice.h
index 03525a9be..c7fd7454f 100644
--- a/base/gxdevice.h
+++ b/base/gxdevice.h
@@ -314,6 +314,7 @@ dev_proc_strip_tile_rect_devn(gx_default_strip_tile_rect_devn);
dev_proc_copy_alpha_hl_color(gx_default_copy_alpha_hl_color);
dev_proc_process_page(gx_default_process_page);
dev_proc_transform_pixel_region(gx_default_transform_pixel_region);
+dev_proc_fill_stroke_path(gx_default_fill_stroke_path);
dev_proc_begin_transparency_group(gx_default_begin_transparency_group);
dev_proc_end_transparency_group(gx_default_end_transparency_group);
dev_proc_begin_transparency_mask(gx_default_begin_transparency_mask);
@@ -418,6 +419,7 @@ dev_proc_strip_copy_rop2(gx_forward_strip_copy_rop2);
dev_proc_strip_tile_rect_devn(gx_forward_strip_tile_rect_devn);
dev_proc_copy_alpha_hl_color(gx_forward_copy_alpha_hl_color);
dev_proc_transform_pixel_region(gx_forward_transform_pixel_region);
+dev_proc_fill_stroke_path(gx_forward_fill_stroke_path);
/* ---------------- Implementation utilities ---------------- */
int gx_default_get_param(gx_device *dev, char *Param, void *list);
diff --git a/base/gxdevsop.h b/base/gxdevsop.h
index 2d4d1a970..dce154410 100644
--- a/base/gxdevsop.h
+++ b/base/gxdevsop.h
@@ -352,6 +352,13 @@ enum {
* the PDF font may not match the widths of the glyphs in the font.
*/
gxdso_event_info,
+ /* gxdso_overprint_active:
+ * data = NULL
+ * size = 0
+ * Returns 1 if the overprint device is active,
+ * 0 otherwise.
+ */
+ gxdso_overprint_active,
/* Debug only dsos follow here */
#ifdef DEBUG
diff --git a/base/gxfill.c b/base/gxfill.c
index 2605dccdc..1abea4911 100644
--- a/base/gxfill.c
+++ b/base/gxfill.c
@@ -663,6 +663,30 @@ gx_default_fill_path(gx_device * pdev, const gs_gstate * pgs,
return code;
}
+/*
+ * Fill/Stroke a path. This is the default implementation of the driver
+ * fill_path procedure.
+ */
+int
+gx_default_fill_stroke_path(gx_device * pdev, const gs_gstate * pgs,
+ gx_path * ppath,
+ const gx_fill_params * params_fill,
+ const gx_device_color * pdevc_fill,
+ const gx_stroke_params * params_stroke,
+ const gx_device_color * pdevc_stroke,
+ const gx_clip_path * pcpath)
+{
+ int code = dev_proc(pdev, fill_path)(pdev, pgs, ppath, params_fill, pdevc_fill, pcpath);
+
+ if (code < 0)
+ return code;
+ /* Swap colors to make sure the pgs colorspace is correct for stroke */
+ gs_swapcolors_quick((gs_gstate *) pgs);
+ code = dev_proc(pdev, stroke_path)(pdev, pgs, ppath, params_stroke, pdevc_stroke, pcpath);
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ return code;
+}
+
/* Free the line list. */
static void
free_line_list(line_list *ll)
diff --git a/base/gxgstate.h b/base/gxgstate.h
index 4f2431656..33f642027 100644
--- a/base/gxgstate.h
+++ b/base/gxgstate.h
@@ -127,6 +127,7 @@ typedef struct gs_gstate_color_s {
gs_color_space *color_space; /* after substitution */
gs_client_color *ccolor;
gx_device_color *dev_color;
+ bool effective_opm;
} gs_gstate_color;
/*
@@ -201,6 +202,7 @@ typedef struct gs_xstate_trans_flags {
#define gs_currentcolor_inline(pgs) ((pgs)->color[0].ccolor)
#define gs_currentcolorspace_inline(pgs) ((pgs)->color[0].color_space)
#define gs_altdevicecolor_inline(pgs) ((pgs)->color[1].dev_color)
+#define gs_currentcolor_eopm(pgs) ((pgs)->color[0].effective_opm)
#define char_tm_only(pgs) *(gs_matrix *)&(pgs)->char_tm
@@ -249,7 +251,6 @@ struct gs_gstate_s {
gx_device *trans_device; /* trans device has all mappings to group color space */
bool overprint;
int overprint_mode;
- int effective_overprint_mode;
bool stroke_overprint;
float flatness;
gs_fixed_point fill_adjust; /* A path expansion for fill; -1 = dropout prevention*/
@@ -303,7 +304,7 @@ struct gs_gstate_s {
gs_matrix textmatrix;
/* Current colors (non-stroking, and stroking) */
gs_gstate_color color[2];
-
+ int is_fill_color;
/* Font: */
gs_font *font;
gs_font *root_font;
@@ -325,7 +326,7 @@ struct gs_gstate_s {
{ (float)(scale), 0.0, 0.0, (float)(-(scale)), 0.0, 0.0 },\
false, {0, 0}, {0, 0}, false, \
lop_default, gx_max_color_value, BLEND_MODE_Compatible,\
-{ 1.0 }, { 1.0 }, {0, 0}, 0, 0/*false*/, 0, 0/*false*/, 0, 0/*false*/, 0, 0, 0/*false*/, 1.0, \
+{ 1.0 }, { 1.0 }, {0, 0}, 0, 0/*false*/, 0, 0/*false*/, 0, 0/*false*/, 0, 0/*false*/, 1.0, \
{ fixed_half, fixed_half }, 0/*false*/, 1/*true*/, 0/*false*/, 1.0,\
1, 1/* bpt true */, 0, 0, 0, INIT_CUSTOM_COLOR_PTR /* 'Custom color' callback pointer */ \
gx_default_get_cmap_procs
@@ -355,7 +356,6 @@ struct gs_gstate_s {
s->trans_device = __state_init.trans_device; \
s->overprint = __state_init.overprint; \
s->overprint_mode = __state_init.overprint_mode; \
- s->effective_overprint_mode = __state_init.effective_overprint_mode; \
s->stroke_overprint = __state_init.stroke_overprint; \
s->flatness = __state_init.flatness; \
s->fill_adjust = __state_init.fill_adjust; \
@@ -370,6 +370,7 @@ struct gs_gstate_s {
s->icc_profile_cache = __state_init.icc_profile_cache; \
s->get_cmap_procs = __state_init.get_cmap_procs; \
s->show_gstate = NULL; \
+ s->is_fill_color = 1; \
} while (0)
struct_proc_finalize(gs_gstate_finalize);
@@ -437,7 +438,6 @@ int gs_currentscreenphase_pgs(const gs_gstate *, gs_int_point *, gs_color_select
(pgs)->current_point.x = xx;\
(pgs)->current_point.y = yy;
-int gs_swapcolors(gs_gstate *);
void gs_swapcolors_quick(gs_gstate *);
/* Set the graphics_type_tag iff the requested tag bit is not set in the dev_color and */
diff --git a/base/gxpaint.c b/base/gxpaint.c
index 9ea236eb0..19e56b436 100644
--- a/base/gxpaint.c
+++ b/base/gxpaint.c
@@ -73,6 +73,30 @@ gx_stroke_fill(gx_path * ppath, gs_gstate * pgs)
}
int
+gx_fill_stroke_path(gs_gstate * pgs, int rule)
+{
+ gx_device *dev = gs_currentdevice_inline(pgs);
+ gx_clip_path *pcpath;
+ int code = gx_effective_clip_path(pgs, &pcpath);
+ gx_stroke_params stroke_params;
+ gx_fill_params fill_params;
+
+ if (code < 0)
+ return code;
+ fill_params.rule = rule;
+ fill_params.adjust.x = pgs->fill_adjust.x;
+ fill_params.adjust.y = pgs->fill_adjust.y;
+ fill_params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
+ stroke_params.flatness = (caching_an_outline_font(pgs) ? 0.0 : pgs->flatness);
+ stroke_params.traditional = false;
+ return (*dev_proc(dev, fill_stroke_path))
+ (dev, (const gs_gstate *)pgs, pgs->path,
+ &fill_params, gs_currentdevicecolor_inline(pgs),
+ &stroke_params, gs_altdevicecolor_inline(pgs),
+ pcpath);
+}
+
+int
gx_stroke_add(gx_path * ppath, gx_path * to_path,
const gs_gstate * pgs, bool traditional)
{
diff --git a/base/gxpaint.h b/base/gxpaint.h
index e3e56e666..558e39789 100644
--- a/base/gxpaint.h
+++ b/base/gxpaint.h
@@ -36,6 +36,8 @@ int gx_fill_path(gx_path * ppath, gx_device_color * pdevc, gs_gstate * pgs,
int rule, fixed adjust_x, fixed adjust_y);
int gx_stroke_fill(gx_path * ppath, gs_gstate * pgs);
int gx_stroke_add(gx_path *ppath, gx_path *to_path, const gs_gstate * pgs, bool traditional);
+int gx_fill_stroke_path(gs_gstate *pgs, int rule);
+
/*
* gx_gstate_stroke_add needs a device for the sake of absolute-length
* dots (and for no other reason).
diff --git a/base/gxpath.h b/base/gxpath.h
index 505353a86..3c8d41242 100644
--- a/base/gxpath.h
+++ b/base/gxpath.h
@@ -309,6 +309,7 @@ int gx_clip_to_rectangle(gs_gstate *, gs_fixed_rect *);
int gx_clip_to_path(gs_gstate *);
int gx_default_clip_box(const gs_gstate *, gs_fixed_rect *);
int gx_effective_clip_path(gs_gstate *, gx_clip_path **);
+int gx_curr_fixed_bbox(gs_gstate * pgs, gs_fixed_rect *bbox, gs_bbox_comp_t comp_type);
int gx_curr_bbox(gs_gstate * pgs, gs_rect *bbox, gs_bbox_comp_t comp_type);
diff --git a/base/gxpath2.c b/base/gxpath2.c
index 49cad4d7c..ed795ca5c 100644
--- a/base/gxpath2.c
+++ b/base/gxpath2.c
@@ -58,6 +58,9 @@ gx_path_subpath_start_point(const gx_path * ppath, gs_fixed_point * ppt)
int
gx_path_bbox(gx_path * ppath, gs_fixed_rect * pbox)
{
+ if (ppath == NULL) {
+ return_error(gs_error_unknownerror) ;
+ }
if (ppath->bbox_accurate) {
/* The bounding box was set by setbbox. */
*pbox = ppath->bbox;
diff --git a/base/gxpcmap.c b/base/gxpcmap.c
index 3be145aef..6f2f5ac29 100644
--- a/base/gxpcmap.c
+++ b/base/gxpcmap.c
@@ -180,7 +180,8 @@ static const gx_device_pattern_accum gs_pattern_accum_device =
gx_default_strip_tile_rect_devn,
NULL, /* alpha_hl_color */
NULL, /* process_page */
- gx_default_transform_pixel_region /* NOT the default forwarding one */
+ gx_default_transform_pixel_region, /* NOT the default forwarding one */
+ gx_default_fill_stroke_path,
},
0, /* target */
0, 0, 0, 0 /* bitmap_memory, bits, mask, instance */
@@ -907,12 +908,14 @@ gstate_set_pattern_cache(gs_gstate * pgs, gx_pattern_cache * pcache)
}
/* Free a Pattern cache entry. */
+/* This will not free a pattern if it is 'locked' which should only be for */
+/* a stroke pattern during fill_stroke_path. */
static void
gx_pattern_cache_free_entry(gx_pattern_cache * pcache, gx_color_tile * ctile)
{
gx_device *temp_device;
- if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy) {
+ if ((ctile->id != gx_no_bitmap_id) && !ctile->is_dummy && !ctile->is_locked) {
gs_memory_t *mem = pcache->memory;
/*
@@ -991,18 +994,25 @@ gx_pattern_cache_ensure_space(gs_gstate * pgs, int needed)
{
int code = ensure_pattern_cache(pgs);
gx_pattern_cache *pcache;
+ int start_free_id;
if (code < 0)
return; /* no cache -- just exit */
pcache = pgs->pattern_cache;
-
+ start_free_id = pcache->next; /* for scan wrap check */
/* If too large then start freeing entries */
- /* By starting at 'next', we attempt to first free the oldest entries */
+ /* By starting just after 'next', we attempt to first free the oldest entries */
while (pcache->bits_used + needed > pcache->max_bits &&
pcache->bits_used != 0) {
pcache->next = (pcache->next + 1) % pcache->num_tiles;
gx_pattern_cache_free_entry(pcache, &pcache->tiles[pcache->next]);
+ /* since a pattern may be temporarily locked (stroke pattern for fill_stroke_path) */
+ /* we may not have freed all entries even though we've scanned the entire cache. */
+ /* The following check for wrapping prevents infinite loop if stroke pattern was */
+ /* larger than pcache->max_bits, */
+ if (pcache->next == start_free_id)
+ break; /* we wrapped -- cache may not be empty */
}
}
@@ -1133,12 +1143,14 @@ gx_pattern_cache_add_entry(gs_gstate * pgs,
ctile->is_simple = pinst->is_simple;
ctile->has_overlap = pinst->has_overlap;
ctile->is_dummy = false;
+ ctile->is_locked = false;
if (pinst->templat.uses_transparency) {
/* to work with pdfi get the blend mode out of the saved pgs device */
ctile->blending_mode = ((pdf14_device*)(saved->device))->blend_mode;
}
else
ctile->blending_mode = 0;
+ ctile->trans_group_popped = false;
if (dev_proc(fdev, open_device) != pattern_clist_open_device) {
if (mbits != 0) {
make_bitmap(&ctile->tbits, mbits, gs_next_ids(pgs->memory, 1), pgs->memory);
@@ -1183,6 +1195,26 @@ gx_pattern_cache_add_entry(gs_gstate * pgs,
return 0;
}
+/* set or clear the 'is_locked' flag for a tile in the cache. Used by */
+/* fill_stroke_path to make sure a large stroke pattern stays in the */
+/* cache even if the fill is also a pattern. */
+int
+gx_pattern_cache_entry_set_lock(gs_gstate *pgs, gs_id id, bool new_lock_value)
+{
+ gx_pattern_cache *pcache;
+ gx_color_tile *ctile;
+ int code = ensure_pattern_cache(pgs);
+
+ if (code < 0)
+ return code;
+ pcache = pgs->pattern_cache;
+ ctile = &pcache->tiles[id % pcache->num_tiles];
+ if (ctile->id != id)
+ return_error(gs_error_undefined);
+ ctile->is_locked = new_lock_value;
+ return 0;
+}
+
/* Get entry for reading a pattern from clist. */
int
gx_pattern_cache_get_entry(gs_gstate * pgs, gs_id id, gx_color_tile ** pctile)
@@ -1232,6 +1264,7 @@ gx_pattern_cache_add_dummy_entry(gs_gstate *pgs,
ctile->is_simple = pinst->is_simple;
ctile->has_overlap = pinst->has_overlap;
ctile->is_dummy = true;
+ ctile->is_locked = false;
memset(&ctile->tbits, 0 , sizeof(ctile->tbits));
ctile->tbits.size = pinst->size;
ctile->tbits.id = gs_no_bitmap_id;
@@ -1368,6 +1401,7 @@ gx_pattern_cache_winnow(gx_pattern_cache * pcache,
for (i = 0; i < pcache->num_tiles; ++i) {
gx_color_tile *ctile = &pcache->tiles[i];
+ ctile->is_locked = false; /* force freeing */
if (ctile->id != gx_no_bitmap_id && (*proc) (ctile, proc_data))
gx_pattern_cache_free_entry(pcache, ctile);
}
diff --git a/base/gxpcolor.h b/base/gxpcolor.h
index afa62b38f..38cd625bf 100644
--- a/base/gxpcolor.h
+++ b/base/gxpcolor.h
@@ -214,17 +214,17 @@ struct gx_color_tile_s {
byte has_overlap; /* true if step size is smaller than bounding box */
byte is_dummy; /* if true, the device manages the pattern,
and the content of the tile is empty. */
- byte pad[2]; /* structure members alignment. */
- /* The following is neither key nor value. */
- uint index; /* the index of the tile within */
- bool trans_group_popped; /* Used to avoid multiple group pops in image mask fills */
- bool is_planar; /* Has to be stored here due to the device
+ byte trans_group_popped; /* Used to avoid multiple group pops in image mask fills */
+ byte is_planar; /* Has to be stored here due to the device
change that can occur when the tile is
created and when it is written in the clist
when we are writing to a transparency
device which, is not planar but the target
is */
- /* the cache (for GC) */
+ byte is_locked; /* stroke patterns cannot be freed during fill_stroke_path */
+ byte pad[2]; /* structure members alignment. */
+ /* The following is neither key nor value. */
+ uint index; /* the index of the tile within the cache (for GC) */
};
#define private_st_color_tile() /* in gxpcmap.c */\
@@ -312,6 +312,9 @@ int gx_pattern_cache_add_entry(gs_gstate *, gx_device_forward *,
int gx_pattern_cache_add_dummy_entry(gs_gstate *pgs, gs_pattern1_instance_t *pinst,
int depth);
+/* set or clear the lock for a tile in the cache. Returns error if tile not in cache */
+int gx_pattern_cache_entry_set_lock(gs_gstate * pgs, gs_id id, bool new_lock_value);
+
/* Get entry for reading a pattern from clist. */
int gx_pattern_cache_get_entry(gs_gstate * pgs, gs_id id, gx_color_tile ** pctile);
diff --git a/base/gxstroke.c b/base/gxstroke.c
index e3cc508a8..52c15437f 100644
--- a/base/gxstroke.c
+++ b/base/gxstroke.c
@@ -105,13 +105,18 @@ int
gx_stroke_path_expansion(const gs_gstate * pgs, const gx_path * ppath,
gs_fixed_point * ppt)
{
- const subpath *psub = ppath->first_subpath;
+ const subpath *psub;
const segment *pseg;
double cx = fabs(pgs->ctm.xx) + fabs(pgs->ctm.yx);
double cy = fabs(pgs->ctm.xy) + fabs(pgs->ctm.yy);
double expand = pgs->line_params.half_width;
int result = 1;
+ if (ppath == NULL) {
+ ppt->x = ppt->y = 0;
+ return 0; /* no expansion */
+ }
+ psub = ppath->first_subpath;
/* Adjust the expansion (E) for square caps, if needed */
if (pgs->line_params.start_cap == gs_cap_square ||
pgs->line_params.end_cap == gs_cap_square)
diff --git a/base/lib.mak b/base/lib.mak
index e8050b43f..8890d911e 100644
--- a/base/lib.mak
+++ b/base/lib.mak
@@ -952,8 +952,9 @@ $(GLOBJ)gscicach.$(OBJ) : $(GLSRC)gscicach.c $(AK) $(gx_h)\
$(GLCC) $(GLO_)gscicach.$(OBJ) $(C_) $(GLSRC)gscicach.c
$(GLOBJ)gsovrc.$(OBJ) : $(GLSRC)gsovrc.c $(AK) $(gx_h) $(gserrors_h)\
- $(memory__h) $(gsutil_h) $(gxcomp_h) $(gxdevice_h) $(gsdevice_h) $(gxgetbit_h)\
- $(gsovrc_h) $(gxdcolor_h) $(gxoprect_h) $(gsbitops_h) $(gxgstate_h) $(LIB_MAK) $(MAKEDIRS)
+ $(assert__h) $(memory__h) $(gsutil_h) $(gxcomp_h) $(gxdevice_h) $(gsdevice_h)\
+ $(gxgetbit_h) $(gsovrc_h) $(gxdcolor_h) $(gxoprect_h) $(gsbitops_h) $(gxgstate_h)\
+ $(gxdevsop_h) $(gxcldev_h) $(LIB_MAK) $(MAKEDIRS)
$(GLCC) $(GLO_)gsovrc.$(OBJ) $(C_) $(GLSRC)gsovrc.c
$(GLOBJ)gxoprect.$(OBJ) : $(GLSRC)gxoprect.c $(AK) $(gx_h)\
@@ -1051,7 +1052,7 @@ $(GLOBJ)gspaint.$(OBJ) : $(GLSRC)gspaint.c $(AK) $(gx_h) $(gserrors_h)\
$(math__h) $(gpcheck_h) $(gsropt_h) $(gxfixed_h) $(gxmatrix_h) $(gspaint_h)\
$(gspath_h) $(gzpath_h) $(gxpaint_h) $(gzstate_h) $(gxdevice_h) $(gxdevmem_h)\
$(gzcpath_h) $(gxhldevc_h) $(gsutil_h) $(gxdevsop_h) $(gsicc_cms_h)\
- $(gdevepo_h) $(gxscanc_h) $(LIB_MAK) $(MAKEDIRS)
+ $(gdevepo_h) $(gxscanc_h) $(gxpcolor_h) $(LIB_MAK) $(MAKEDIRS)
$(GLCC) $(GLO_)gspaint.$(OBJ) $(C_) $(GLSRC)gspaint.c
$(GLOBJ)gsparam.$(OBJ) : $(GLSRC)gsparam.c $(AK) $(gx_h) $(gserrors_h)\
@@ -1090,7 +1091,7 @@ $(GLOBJ)gsstate.$(OBJ) : $(GLSRC)gsstate.c $(AK) $(gx_h) $(gserrors_h)\
$(GLOBJ)gstext.$(OBJ) : $(GLSRC)gstext.c $(AK) $(memory__h) $(gdebug_h)\
$(gserrors_h) $(gsmemory_h) $(gsstruct_h) $(gstypes_h)\
$(gxfcache_h) $(gxdevcli_h) $(gxdcolor_h) $(gxfont_h) $(gxpath_h)\
- $(gxtext_h) $(gzstate_h) $(gsutil_h) $(LIB_MAK) $(MAKEDIRS)
+ $(gxtext_h) $(gzstate_h) $(gsutil_h) $(gxdevsop_h) $(LIB_MAK) $(MAKEDIRS)
$(GLCC) $(GLO_)gstext.$(OBJ) $(C_) $(GLSRC)gstext.c
# We make gsiodevs a separate module so the PS interpreter can replace it.
diff --git a/devices/gdevpsd.c b/devices/gdevpsd.c
index 26580aee8..ee13a7088 100644
--- a/devices/gdevpsd.c
+++ b/devices/gdevpsd.c
@@ -453,7 +453,10 @@ psd_prn_open(gx_device * pdev)
pdev->color_info.depth = pdev->color_info.num_components *
pdev_psd->devn_params.bitspercomponent;
pdev->color_info.separable_and_linear = GX_CINFO_SEP_LIN;
- pdev->icc_struct->supports_devn = true;
+ if (pdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
+ pdev->icc_struct->supports_devn = false;
+ else
+ pdev->icc_struct->supports_devn = true;
code = gdev_prn_open_planar(pdev, true);
return code;
}
diff --git a/devices/vector/gdevpdfb.h b/devices/vector/gdevpdfb.h
index e1ca2361d..d84754048 100644
--- a/devices/vector/gdevpdfb.h
+++ b/devices/vector/gdevpdfb.h
@@ -98,7 +98,16 @@ const gx_device_pdf PDF_DEVICE_IDENT =
NULL, /* push_transparency_state */
NULL, /* pop_transparency_state */
NULL, /* put_image */
- gdev_pdf_dev_spec_op /* dev_spec_op */
+ gdev_pdf_dev_spec_op, /* dev_spec_op */
+ NULL, /* copy_planes */
+ NULL, /* get_profile */
+ NULL, /* set_graphics_type_tag */
+ NULL, /* strip_copy_rop2 */
+ NULL, /* strip_tile_rect_devn */
+ NULL, /* copy_alpha_hl_color */
+ NULL, /* process_page */
+ NULL, /* transform_pixel_region */
+ gdev_pdf_fill_stroke_path /* fill_stroke_path */
},
psdf_initial_values(PSDF_VERSION_INITIAL, 0 /*false */ ), /* (!ASCII85EncodePages) */
0, /* pdf_font_dir */
diff --git a/devices/vector/gdevpdfd.c b/devices/vector/gdevpdfd.c
index 5c8907cff..e7ad75668 100644
--- a/devices/vector/gdevpdfd.c
+++ b/devices/vector/gdevpdfd.c
@@ -1866,6 +1866,205 @@ gdev_pdf_stroke_path(gx_device * dev, const gs_gstate * pgs,
return 0;
}
+int
+gdev_pdf_fill_stroke_path(gx_device *dev, const gs_gstate *pgs, gx_path *ppath,
+ const gx_fill_params *fill_params, const gx_drawing_color *pdcolor_fill,
+ const gx_stroke_params *stroke_params, const gx_drawing_color *pdcolor_stroke,
+ const gx_clip_path *pcpath)
+{
+ gx_device_pdf *pdev = (gx_device_pdf *) dev;
+ int code;
+ bool new_clip;
+ bool have_path;
+
+ have_path = !gx_path_is_void(ppath);
+ if (!have_path) {
+ if (!pdev->vg_initial_set) {
+ /* See lib/gs_pdfwr.ps about "initial graphic state". */
+ pdf_prepare_initial_viewer_state(pdev, pgs);
+ pdf_reset_graphics(pdev);
+ return 0;
+ }
+ }
+
+ /* PostScript doesn't have a fill+stroke primitive, so break it into two operations
+ * PDF 1.2 only has a single overprint setting, we can't be certainto match that
+ * Because our inpu tcould be from a higher level. So be sure and break it into
+ * 2 operations.
+ */
+ if (pdev->ForOPDFRead || pdev->CompatibilityLevel < 1.3) {
+ code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
+ if (code < 0)
+ return code;
+ gs_swapcolors_quick(pgs);
+ code = gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
+ gs_swapcolors_quick(pgs);
+ return code;
+ } else {
+ bool set_ctm;
+ gs_matrix mat;
+ double scale, path_scale;
+ double prescale = 1;
+ gs_fixed_rect bbox;
+ gs_path_enum cenum;
+ gdev_vector_dopath_state_t state;
+ stream *s = pdev->strm;
+ /*
+ * Check for an empty clipping path.
+ */
+ if (pcpath) {
+ gs_fixed_rect cbox;
+
+ gx_cpath_outer_box(pcpath, &cbox);
+ if (cbox.p.x >= cbox.q.x || cbox.p.y >= cbox.q.y)
+ return 1; /* empty clipping path */
+// *box = cbox;
+ }
+ code = pdf_check_soft_mask(pdev, (gs_gstate *)pgs);
+ if (code < 0)
+ return code;
+
+ new_clip = pdf_must_put_clip_path(pdev, pcpath);
+ if (have_path || pdev->context == PDF_IN_NONE || new_clip) {
+ if (new_clip)
+ code = pdf_unclip(pdev);
+ else
+ code = pdf_open_page(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return code;
+ }
+ code = pdf_prepare_fill_stroke(pdev, pgs, false);
+ if (code < 0)
+ return code;
+
+ code = pdf_put_clip_path(pdev, pcpath);
+ if (code < 0)
+ return code;
+ /*
+ * If the CTM is not uniform, stroke width depends on angle.
+ * We'd like to avoid resetting the CTM, so we check for uniform
+ * CTMs explicitly. Note that in PDF, unlike PostScript, it is
+ * the CTM at the time of the stroke operation, not the CTM at
+ * the time the path was constructed, that is used for transforming
+ * the points of the path; so if we have to reset the CTM, we must
+ * do it before constructing the path, and inverse-transform all
+ * the coordinates.
+ */
+ set_ctm = (bool)gdev_vector_stroke_scaling((gx_device_vector *)pdev,
+ pgs, &scale, &mat);
+ if (set_ctm && ((pgs->ctm.xx == 0 && pgs->ctm.xy == 0) ||
+ (pgs->ctm.yx == 0 && pgs->ctm.yy == 0))) {
+ /* Acrobat Reader 5 and Adobe Reader 6 issues
+ the "Wrong operand type" error with matrices, which have 3 zero coefs.
+ Besides that, we found that Acrobat Reader 4, Acrobat Reader 5
+ and Adobe Reader 6 all store the current path in user space
+ and apply CTM in the time of stroking - See the bug 687901.
+ Therefore a precise conversion of Postscript to PDF isn't possible in this case.
+ Adobe viewers render a line with a constant width instead.
+ At last, with set_ctm == true we need the inverse matrix in
+ gdev_vector_dopath. Therefore we exclude projection matrices
+ (see bug 688363). */
+ set_ctm = false;
+ scale = fabs(pgs->ctm.xx + pgs->ctm.xy + pgs->ctm.yx + pgs->ctm.yy) /* Using the non-zero coeff. */
+ / sqrt(2); /* Empirically from Adobe. */
+ }
+ if (set_ctm) {
+ /*
+ * We want a scaling factor that will bring the largest reasonable
+ * user coordinate within bounds. We choose a factor based on the
+ * minor axis of the transformation. Thanks to Raph Levien for
+ * the following formula.
+ */
+ double a = mat.xx, b = mat.xy, c = mat.yx, d = mat.yy;
+ double u = fabs(a * d - b * c);
+ double v = a * a + b * b + c * c + d * d;
+ double minor = (sqrt(v + 2 * u) - sqrt(v - 2 * u)) * 0.5;
+
+ prescale = (minor == 0 || minor > 1 ? 1 : 1 / minor);
+ }
+ gx_path_bbox(ppath, &bbox);
+ {
+ /* Check whether a painting appears inside the clipping box.
+ Doing so after writing the clipping path due to /SP pdfmark
+ uses a special hack with painting outside the clipping box
+ for synchronizing the clipping path (see lib/gs_pdfwr.ps).
+ That hack appeared because there is no way to pass
+ the gs_gstate through gdev_pdf_put_params,
+ which pdfmark is implemented with.
+ */
+ gs_fixed_rect clip_box, stroke_bbox = bbox;
+ gs_point d0, d1;
+ gs_fixed_point p0, p1;
+ fixed bbox_expansion_x, bbox_expansion_y;
+
+ gs_distance_transform(pgs->line_params.half_width, 0, &ctm_only(pgs), &d0);
+ gs_distance_transform(0, pgs->line_params.half_width, &ctm_only(pgs), &d1);
+ p0.x = float2fixed(any_abs(d0.x));
+ p0.y = float2fixed(any_abs(d0.y));
+ p1.x = float2fixed(any_abs(d1.x));
+ p1.y = float2fixed(any_abs(d1.y));
+ bbox_expansion_x = max(p0.x, p1.x) + fixed_1 * 2;
+ bbox_expansion_y = max(p0.y, p1.y) + fixed_1 * 2;
+ stroke_bbox.p.x -= bbox_expansion_x;
+ stroke_bbox.p.y -= bbox_expansion_y;
+ stroke_bbox.q.x += bbox_expansion_x;
+ stroke_bbox.q.y += bbox_expansion_y;
+ gx_cpath_outer_box(pcpath, &clip_box);
+ rect_intersect(stroke_bbox, clip_box);
+ if (stroke_bbox.q.x < stroke_bbox.p.x || stroke_bbox.q.y < stroke_bbox.p.y)
+ return 0;
+ }
+ if (make_rect_scaling(pdev, &bbox, prescale, &path_scale)) {
+ scale /= path_scale;
+ if (set_ctm)
+ gs_matrix_scale(&mat, path_scale, path_scale, &mat);
+ else {
+ gs_make_scaling(path_scale, path_scale, &mat);
+ set_ctm = true;
+ }
+ }
+
+ code = pdf_setfillcolor((gx_device_vector *)pdev, pgs, pdcolor_fill);
+ if (code == gs_error_rangecheck) {
+ /* rangecheck means we revert to the equivalent to the default implementation */
+ code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
+ if (code < 0)
+ return code;
+ /* Swap colors to make sure the pgs colorspace is correct for stroke */
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ code = gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ return code;
+ }
+
+ /* Swap colors to make sure the pgs colorspace is correct for stroke */
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, pgs, stroke_params,
+ pdcolor_stroke, scale);
+ gs_swapcolors_quick((gs_gstate*) pgs);
+ if (code < 0) {
+ code = gdev_pdf_fill_path(dev, pgs, ppath, fill_params, pdcolor_fill, pcpath);
+ if (code < 0)
+ return code;
+ return gdev_pdf_stroke_path(dev, pgs, ppath, stroke_params, pdcolor_stroke, pcpath);
+ }
+ if (!pdev->HaveStrokeColor)
+ pdev->saved_fill_color = pdev->saved_stroke_color;
+ if (set_ctm)
+ pdf_put_matrix(pdev, "q ", &mat, "cm\n");
+ if (pgs->line_params.dash.offset != 0 || pgs->line_params.dash.pattern_size != 0)
+ code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_stroke | gx_path_type_optimize | gx_path_type_dashed_stroke, (set_ctm ? &mat : (const gs_matrix *)0));
+ else
+ code = pdf_write_path(pdev, (gs_path_enum *)&cenum, &state, (gx_path *)ppath, 0, gx_path_type_stroke | gx_path_type_optimize, (set_ctm ? &mat : (const gs_matrix *)0));
+ if (code < 0)
+ return code;
+ s = pdev->strm;
+ stream_puts(s, (fill_params->rule < 0 ? "B\n" : "B*\n"));
+ stream_puts(s, (set_ctm ? " Q\n" : "\n"));
+ }
+ return 0;
+}
+
/*
The fill_rectangle_hl_color device method.
See gxdevcli.h about return codes.
diff --git a/devices/vector/gdevpdfg.c b/devices/vector/gdevpdfg.c
index d82aca504..aaa362267 100644
--- a/devices/vector/gdevpdfg.c
+++ b/devices/vector/gdevpdfg.c
@@ -75,8 +75,9 @@ pdf_save_viewer_state(gx_device_pdf *pdev, stream *s)
pdev->vgstack[i].transfer_ids[2] = pdev->transfer_ids[2];
pdev->vgstack[i].transfer_ids[3] = pdev->transfer_ids[3];
pdev->vgstack[i].transfer_not_identity = pdev->transfer_not_identity;
- pdev->vgstack[i].opacity_alpha = pdev->state.opacity.alpha;
- pdev->vgstack[i].shape_alpha = pdev->state.shape.alpha;
+ pdev->vgstack[i].strokeconstantalpha = pdev->state.strokeconstantalpha;
+ pdev->vgstack[i].fillconstantalpha = pdev->state.fillconstantalpha;
+ pdev->vgstack[i].alphaisshape = pdev->state.alphaisshape;
pdev->vgstack[i].blend_mode = pdev->state.blend_mode;
pdev->vgstack[i].halftone_id = pdev->halftone_id;
pdev->vgstack[i].black_generation_id = pdev->black_generation_id;
@@ -125,8 +126,9 @@ pdf_load_viewer_state(gx_device_pdf *pdev, pdf_viewer_state *s)
pdev->transfer_ids[2] = s->transfer_ids[2];
pdev->transfer_ids[3] = s->transfer_ids[3];
pdev->transfer_not_identity = s->transfer_not_identity;
- pdev->state.opacity.alpha = s->opacity_alpha;
- pdev->state.shape.alpha = s->shape_alpha;
+ pdev->state.strokeconstantalpha = s->strokeconstantalpha;
+ pdev->state.fillconstantalpha = s->fillconstantalpha;
+ pdev->state.alphaisshape = s->alphaisshape;
pdev->state.blend_mode = s->blend_mode;
pdev->halftone_id = s->halftone_id;
pdev->black_generation_id = s->black_generation_id;
@@ -209,8 +211,9 @@ pdf_viewer_state_from_gs_gstate_aux(pdf_viewer_state *pvs, const gs_gstate *pgs)
pvs->transfer_ids[1] = (pgs->set_transfer.green != NULL ? pgs->set_transfer.green->id : 0);
pvs->transfer_ids[2] = (pgs->set_transfer.blue != NULL ? pgs->set_transfer.blue->id : 0);
pvs->transfer_ids[3] = (pgs->set_transfer.gray != NULL ? pgs->set_transfer.gray->id : 0);
- pvs->opacity_alpha = pgs->opacity.alpha;
- pvs->shape_alpha = pgs->shape.alpha;
+ pvs->fillconstantalpha = pgs->fillconstantalpha;
+ pvs->strokeconstantalpha = pgs->strokeconstantalpha;
+ pvs->alphaisshape = pgs->alphaisshape;
pvs->blend_mode = pgs->blend_mode;
pvs->halftone_id = (pgs->dev_ht != 0 ? pgs->dev_ht->id : 0);
pvs->black_generation_id = (pgs->black_generation != 0 ? pgs->black_generation->id : 0);
@@ -2871,8 +2874,6 @@ static int
pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs,
pdf_resource_t **ppres, bool for_text)
{
- bool ais;
- double alpha;
int code;
if (pdev->state.soft_mask_id != pgs->soft_mask_id) {
@@ -2903,51 +2904,27 @@ pdf_update_alpha(gx_device_pdf *pdev, const gs_gstate *pgs,
}
pdev->state.soft_mask_id = pgs->soft_mask_id;
}
- if (pdev->state.opacity.alpha != pgs->opacity.alpha) {
- if (pdev->state.shape.alpha != pgs->shape.alpha) {
- /* We had previously set one of opacity or shape, but we didn't
- * ever need to write the graphcis state out, leaving us with a
- * dangling alpha. We should honour the current state. One of
- * opacity or alpha will be the default (1.0), so use the other.
- */
- pdev->state.opacity.alpha = pgs->opacity.alpha;
- pdev->state.shape.alpha = pgs->shape.alpha;
- if (pgs->opacity.alpha != 1.0) {
- ais = false;
- alpha = pdev->state.opacity.alpha;
- }
- else {
- ais = true;
- alpha = pdev->state.shape.alpha;
- }
- } else {
- ais = false;
- alpha = pdev->state.opacity.alpha = pgs->opacity.alpha;
- }
- } else if (pdev->state.shape.alpha != pgs->shape.alpha) {
- ais = true;
- alpha = pdev->state.shape.alpha = pgs->shape.alpha;
- } else
- return 0;
- code = pdf_open_gstate(pdev, ppres);
- if (code < 0)
- return code;
- code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", ais);
- if (code < 0)
- return code;
- if (!for_text) {
- /* we never do the 'both' operations (b, B, b*, B*) so we set both */
- /* CA and ca the same so that we stay in sync with state.*.alpha */
- code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", alpha);
- if (code < 0)
- return code;
- return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", alpha);
- } else {
+
+ if (pdev->state.alphaisshape != pgs->alphaisshape ||
+ pdev->state.strokeconstantalpha != pgs->strokeconstantalpha ||
+ pdev->state.fillconstantalpha != pgs->fillconstantalpha) {
+
+ pdev->state.strokeconstantalpha = pgs->strokeconstantalpha;
+ pdev->state.fillconstantalpha = pgs->fillconstantalpha;
+ pdev->state.alphaisshape = pgs->alphaisshape;
+
+ code = pdf_open_gstate(pdev, ppres);
+ if (code < 0)
+ return code;
+ code = cos_dict_put_c_key_bool(resource_dict(*ppres), "/AIS", pgs->alphaisshape);
+ if (code < 0)
+ return code;
code = cos_dict_put_c_key_real(resource_dict(*ppres), "/CA", pgs->strokeconstantalpha);
if (code < 0)
return code;
return cos_dict_put_c_key_real(resource_dict(*ppres), "/ca", pgs->fillconstantalpha);
- }
+ } else
+ return 0;
}
/*
@@ -2983,8 +2960,8 @@ pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs,
* If the graphics state calls for any transparency functions,
* we can't represent them, so return a rangecheck.
*/
- if (pgs->opacity.alpha != 1 ||
- pgs->shape.alpha != 1)
+ if (pgs->strokeconstantalpha != 1 ||
+ pgs->fillconstantalpha != 1)
return_error(gs_error_rangecheck);
}
/*
@@ -3234,20 +3211,95 @@ pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
}
/* Update overprint, stroke adjustment. */
if (pdev->params.PreserveOverprintSettings &&
- pdev->stroke_overprint != pgs->overprint &&
+ pdev->stroke_overprint != pgs->stroke_overprint &&
!pdev->skip_colors
) {
if (pres == 0)
code = pdf_open_gstate(pdev, &pres);
if (code < 0)
return code;
- code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
+ code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
+ if (code < 0)
+ return code;
+ pdev->stroke_overprint = pgs->stroke_overprint;
+
+ /* According to PDF>=1.3 spec, OP also sets op,
+ if there is no /op in same graphic state object.
+ We don't write /op, so monitor the viewer's state here : */
+ pdev->fill_overprint = pgs->stroke_overprint;
+ }
+ if (pdev->state.stroke_adjust != pgs->stroke_adjust) {
+ code = pdf_open_gstate(pdev, &pres);
+ if (code < 0)
+ return code;
+ code = cos_dict_put_c_key_bool(resource_dict(pres), "/SA", pgs->stroke_adjust);
+ if (code < 0)
+ return code;
+ pdev->state.stroke_adjust = pgs->stroke_adjust;
+ }
+ return pdf_end_gstate(pdev, pres);
+}
+int
+pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
+{
+ int code;
+
+ if (pdev->context != PDF_IN_STREAM) {
+ code = pdf_try_prepare_stroke(pdev, pgs, for_text);
+ if (code != gs_error_interrupt) /* See pdf_open_gstate */
+ return code;
+ code = pdf_open_contents(pdev, PDF_IN_STREAM);
+ if (code < 0)
+ return code;
+ }
+ return pdf_try_prepare_stroke(pdev, pgs, for_text);
+}
+
+static int
+pdf_try_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
+{
+ pdf_resource_t *pres = 0;
+ int code = pdf_prepare_drawing(pdev, pgs, &pres, for_text);
+
+ if (code < 0)
+ return code;
+ /* Update overprint. */
+ if (pdev->params.PreserveOverprintSettings &&
+ (pdev->fill_overprint != pgs->overprint ||
+ pdev->stroke_overprint != pgs->stroke_overprint ||
+ pdev->font3) && !pdev->skip_colors
+ ) {
+ code = pdf_open_gstate(pdev, &pres);
if (code < 0)
return code;
- pdev->stroke_overprint = pgs->overprint;
+ /* PDF 1.2 only has a single overprint setting. */
+ if (pdev->CompatibilityLevel < 1.3) {
+ code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->overprint);
+ if (code < 0)
+ return code;
+ pdev->stroke_overprint = pgs->overprint;
+ } else {
+ code = cos_dict_put_c_key_bool(resource_dict(pres), "/op", pgs->overprint);
+ if (code < 0)
+ return code;
+ }
+ pdev->fill_overprint = pgs->overprint;
+ }
+ /* Update overprint, stroke adjustment. */
+ if (pdev->params.PreserveOverprintSettings &&
+ pdev->stroke_overprint != pgs->stroke_overprint &&
+ !pdev->skip_colors
+ ) {
+ code = pdf_open_gstate(pdev, &pres);
+ if (code < 0)
+ return code;
+ code = cos_dict_put_c_key_bool(resource_dict(pres), "/OP", pgs->stroke_overprint);
+ if (code < 0)
+ return code;
+ pdev->stroke_overprint = pgs->stroke_overprint;
if (pdev->CompatibilityLevel < 1.3) {
/* PDF 1.2 only has a single overprint setting. */
- pdev->fill_overprint = pgs->overprint;
+ pdev->fill_overprint = pgs->stroke_overprint;
} else {
/* According to PDF>=1.3 spec, OP also sets op,
if there is no /op in same garphic state object.
@@ -3266,20 +3318,21 @@ pdf_try_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
}
return pdf_end_gstate(pdev, pres);
}
+
int
-pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
+pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text)
{
int code;
if (pdev->context != PDF_IN_STREAM) {
- code = pdf_try_prepare_stroke(pdev, pgs, for_text);
+ code = pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
if (code != gs_error_interrupt) /* See pdf_open_gstate */
return code;
code = pdf_open_contents(pdev, PDF_IN_STREAM);
if (code < 0)
return code;
}
- return pdf_try_prepare_stroke(pdev, pgs, for_text);
+ return pdf_try_prepare_fill_stroke(pdev, pgs, for_text);
}
/* Update the graphics state for an image other than an ImageType 1 mask. */
diff --git a/devices/vector/gdevpdfg.h b/devices/vector/gdevpdfg.h
index bd126769a..e846b1a8f 100644
--- a/devices/vector/gdevpdfg.h
+++ b/devices/vector/gdevpdfg.h
@@ -154,6 +154,7 @@ int pdf_try_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_tex
int pdf_prepare_drawing(gx_device_pdf *pdev, const gs_gstate *pgs, pdf_resource_t **ppres, bool for_text);
int pdf_prepare_fill(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text);
int pdf_prepare_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text);
+int pdf_prepare_fill_stroke(gx_device_pdf *pdev, const gs_gstate *pgs, bool for_text);
int pdf_prepare_image(gx_device_pdf *pdev, const gs_gstate *pgs);
int pdf_prepare_imagemask(gx_device_pdf *pdev, const gs_gstate *pgs,
const gx_drawing_color *pdcolor);
diff --git a/devices/vector/gdevpdfx.h b/devices/vector/gdevpdfx.h
index ad484edfb..6a02717ca 100644
--- a/devices/vector/gdevpdfx.h
+++ b/devices/vector/gdevpdfx.h
@@ -480,8 +480,9 @@ struct pdf_font_cache_elem_s {
typedef struct pdf_viewer_state_s {
int transfer_not_identity; /* bitmask */
gs_id transfer_ids[4];
- float opacity_alpha; /* state.opacity.alpha */
- float shape_alpha; /* state.shape.alpha */
+ float strokeconstantalpha;
+ float fillconstantalpha;
+ bool alphaisshape;
gs_blend_mode_t blend_mode; /* state.blend_mode */
gs_id halftone_id;
gs_id black_generation_id;
@@ -963,6 +964,7 @@ extern const gx_device_vector_procs pdf_vector_procs;
dev_proc_fill_rectangle(gdev_pdf_fill_rectangle);
dev_proc_fill_path(gdev_pdf_fill_path);
dev_proc_stroke_path(gdev_pdf_stroke_path);
+dev_proc_fill_stroke_path(gdev_pdf_fill_stroke_path);
dev_proc_fillpage(gdev_pdf_fillpage);
/* In gdevpdfi.c */
dev_proc_begin_typed_image(gdev_pdf_begin_typed_image);
diff --git a/lcms2mt/ChangeLog b/lcms2mt/ChangeLog
index 49342f049..9a30cd419 100644
--- a/lcms2mt/ChangeLog
+++ b/lcms2mt/ChangeLog
@@ -28,7 +28,7 @@ Several fixes related with security, and therefore not detailed here.
C++ compiles now without warnings
Added OSX and clang in travis
Added a travis-ci test matrix for many compilers and OS. Thanks to Thomas Weber (debian) for this great improvement.
-testbed can now work with dynamic versions of library
+testbed can now work with dynamic versions of library
Fixed wrong planar formatters regarding linestride interpretation
-----------------------
diff --git a/lcms2mt/Projects/VC2010/lcms2mt.rc b/lcms2mt/Projects/VC2010/lcms2mt.rc
index 2d0d0a8ff..65f192bc6 100644
--- a/lcms2mt/Projects/VC2010/lcms2mt.rc
+++ b/lcms2mt/Projects/VC2010/lcms2mt.rc
@@ -66,12 +66,20 @@ END
// TEXTINCLUDE
//
+<<<<<<< e2c48062c190a618a765f443fdfcac76a80d684d
1 TEXTINCLUDE
+=======
+1 TEXTINCLUDE
+>>>>>>> Pull in newly merged and updated LCMS2MT from MuPDF thirdparty repo.
BEGIN
"resource.h\0"
END
+<<<<<<< e2c48062c190a618a765f443fdfcac76a80d684d
2 TEXTINCLUDE
+=======
+2 TEXTINCLUDE
+>>>>>>> Pull in newly merged and updated LCMS2MT from MuPDF thirdparty repo.
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
@@ -79,7 +87,11 @@ BEGIN
"\0"
END
+<<<<<<< e2c48062c190a618a765f443fdfcac76a80d684d
3 TEXTINCLUDE
+=======
+3 TEXTINCLUDE
+>>>>>>> Pull in newly merged and updated LCMS2MT from MuPDF thirdparty repo.
BEGIN
"\r\n"
"\0"
@@ -101,4 +113,7 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+<<<<<<< e2c48062c190a618a765f443fdfcac76a80d684d
+=======
+>>>>>>> Pull in newly merged and updated LCMS2MT from MuPDF thirdparty repo.
diff --git a/lcms2mt/config.guess b/lcms2mt/config.guess
index e7464614e..82e59e2a7 100755
--- a/lcms2mt/config.guess
+++ b/lcms2mt/config.guess
@@ -1101,6 +1101,7 @@ EOF
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configuration will decide that
+ # prints for the "djgpp" host, or else GDB configuration will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
diff --git a/psi/int.mak b/psi/int.mak
index 4be5a5690..f149452a6 100644
--- a/psi/int.mak
+++ b/psi/int.mak
@@ -525,7 +525,7 @@ $(PSOBJ)zmatrix.$(OBJ) : $(PSSRC)zmatrix.c $(OP)\
$(PSCC) $(PSO_)zmatrix.$(OBJ) $(C_) $(PSSRC)zmatrix.c
$(PSOBJ)zpaint.$(OBJ) : $(PSSRC)zpaint.c $(OP)\
- $(gspaint_h) $(igstate_h) $(INT_MAK) $(MAKEDIRS)
+ $(gspaint_h) $(igstate_h) $(store_h) $(estack_h) $(INT_MAK) $(MAKEDIRS)
$(PSCC) $(PSO_)zpaint.$(OBJ) $(C_) $(PSSRC)zpaint.c
$(PSOBJ)zpath.$(OBJ) : $(PSSRC)zpath.c $(OP) $(math__h)\
diff --git a/psi/zcolor.c b/psi/zcolor.c
index d20434e70..373bc06ba 100644
--- a/psi/zcolor.c
+++ b/psi/zcolor.c
@@ -792,9 +792,9 @@ int
zcolor_remap_color(i_ctx_t *i_ctx_p)
{
/* Remap both colors. This should never hurt. */
- gs_swapcolors(igs);
+ gs_swapcolors_quick(igs);
gx_unset_dev_color(igs);
- gs_swapcolors(igs);
+ gs_swapcolors_quick(igs);
gx_unset_dev_color(igs);
return 0;
}
@@ -6929,7 +6929,8 @@ zswapcolors(i_ctx_t * i_ctx_p)
istate->pattern[0] = istate->pattern[1];
istate->pattern[1] = tmp_pat;
- return gs_swapcolors(igs);
+ gs_swapcolors_quick(igs);
+ return 0;
}
static int
diff --git a/psi/zpaint.c b/psi/zpaint.c
index efffaab8b..3251c1be8 100644
--- a/psi/zpaint.c
+++ b/psi/zpaint.c
@@ -19,6 +19,8 @@
#include "oper.h"
#include "gspaint.h"
#include "igstate.h"
+#include "store.h"
+#include "estack.h"
/* - fill - */
static int
@@ -41,6 +43,60 @@ zstroke(i_ctx_t *i_ctx_p)
return gs_stroke(igs);
}
+static int
+fillstroke_cont(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ int restart, code;
+
+ check_type(*op, t_integer);
+ restart = (int)op->value.intval;
+ code = gs_fillstroke(igs, &restart);
+ if (code == gs_error_Remap_Color) {
+ op->value.intval = restart;
+ return code;
+ }
+ pop(1);
+ return code;
+}
+
+static int
+zfillstroke(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ push(1);
+ make_int(op, 0); /* 0 implies we are at fill color, need to swap first */
+ push_op_estack(fillstroke_cont);
+ return o_push_estack;
+}
+
+static int
+eofillstroke_cont(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ int restart, code;
+
+ check_type(*op, t_integer);
+ restart = (int)op->value.intval;
+ code = gs_eofillstroke(igs, &restart);
+ if (code == gs_error_Remap_Color) {
+ op->value.intval = restart;
+ return code;
+ }
+ pop(1);
+ return code;
+}
+
+static int
+zeofillstroke(i_ctx_t *i_ctx_p)
+{
+ os_ptr op = osp;
+ push(1);
+ make_int(op, 0);
+ push_op_estack(eofillstroke_cont);
+ return o_push_estack;
+}
+
/* ------ Non-standard operators ------ */
/* - .fillpage - */
@@ -80,5 +136,9 @@ const op_def zpaint_op_defs[] =
/* Non-standard operators */
{"0.fillpage", zfillpage},
{"3.imagepath", zimagepath},
+ {"0.eofillstroke", zeofillstroke},
+ {"0.fillstroke", zfillstroke},
+ {"0%eofillstroke_cont", eofillstroke_cont },
+ {"0%fillstroke_cont", fillstroke_cont },
op_def_end(0)
};