summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxclpath.c')
-rw-r--r--base/gxclpath.c188
1 files changed, 123 insertions, 65 deletions
diff --git a/base/gxclpath.c b/base/gxclpath.c
index 5c757e36..c202178c 100644
--- a/base/gxclpath.c
+++ b/base/gxclpath.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -37,7 +37,7 @@
#include "gxdevsop.h"
/* Statistics */
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+#ifdef COLLECT_STATS_CLIST
ulong stats_cmd_diffs[5];
#endif
@@ -175,15 +175,17 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
left = dc_size;
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
- /* see if phase informaiton must be inserted in the command list */
- if ( pdcolor->type->get_phase(pdcolor, &color_phase) &&
- (color_phase.x != pcls->tile_phase.x ||
- color_phase.y != pcls->tile_phase.y || all_bands) &&
- (code = cmd_set_tile_phase_generic( cldev,
- pcls,
- color_phase.x,
- color_phase.y, all_bands)) < 0 )
- return code;
+ /* see if phase information must be inserted in the command list */
+ if (pdcolor->type->get_phase(pdcolor, &color_phase) &&
+ (color_phase.x != pcls->screen_phase[gs_color_select_texture].x ||
+ color_phase.y != pcls->screen_phase[gs_color_select_texture].y || all_bands)) {
+ /* Devc phase is the reverse of screen phase! */
+ code = cmd_set_screen_phase_generic(cldev, pcls,
+ -color_phase.x, -color_phase.y,
+ gs_color_select_texture, all_bands);
+ if (code < 0)
+ return code;
+ }
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
if (is_pattern) {
@@ -200,6 +202,7 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
}
do {
+ int extop;
prefix_size = 2 + 1 + (offset > 0 ? enc_u_sizew(offset) : 0);
req_size = left + prefix_size + enc_u_sizew(left);
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
@@ -212,29 +215,29 @@ cmd_put_drawing_color(gx_device_clist_writer * cldev, gx_clist_state * pcls,
if (req_size_final > buffer_space)
return_error(gs_error_unregistered); /* Must not happen. */
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cldev);
- if (all_bands)
- code = set_cmd_put_all_op(&dp, cldev, cmd_opv_extend, req_size_final);
- else
- code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_extend, req_size_final);
- if (code < 0)
- return code;
- dp0 = dp;
switch (devn_type) {
case devn_not_tile_fill:
- dp[1] = cmd_opv_ext_put_fill_dcolor;
+ extop = cmd_opv_ext_put_fill_dcolor;
break;
case devn_not_tile_stroke:
- dp[1] = cmd_opv_ext_put_stroke_dcolor;
+ extop = cmd_opv_ext_put_stroke_dcolor;
break;
case devn_tile0:
- dp[1] = cmd_opv_ext_put_tile_devn_color0;
+ extop = cmd_opv_ext_put_tile_devn_color0;
break;
case devn_tile1:
- dp[1] = cmd_opv_ext_put_tile_devn_color1;
+ extop = cmd_opv_ext_put_tile_devn_color1;
break;
default:
- dp[1] = cmd_opv_ext_put_fill_dcolor;
+ extop = cmd_opv_ext_put_fill_dcolor;
}
+ if (all_bands)
+ code = set_cmd_put_all_extended_op(&dp, cldev, extop, req_size_final);
+ else
+ code = set_cmd_put_extended_op(&dp, cldev, pcls, extop, req_size_final);
+ if (code < 0)
+ return code;
+ dp0 = dp;
dp += 2;
*dp++ = di | (offset > 0 ? 0x80 : 0);
if (offset > 0)
@@ -597,56 +600,99 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
int ymin = (pcls - cldev->states) * band_height;
int ymax = min(ymin + band_height, cldev->height);
gs_fixed_rect box;
- bool punt_to_outer_box = false;
int code;
+ int fill_adjust_size;
+ enum {
+ write_path_as_rect = 0,
+ write_path_as_rects = 1,
+ write_path_as_outer_box = 2,
+ write_path_as_path = 3
+ } method;
+
+ /* We are going to begin_clip followed by the fill_adjust to use.
+ * In order to know what fill_adjust to use, we need to know whether
+ * we are going to send the clip through based upon its actual
+ * 'path' entry, or whether we are going to send it based upon its
+ * rectangle list representation. Accordingly, we have to do the
+ * logic to figure out how we are going to send it now. */
+ if (pcpath->path_valid) {
+ if (gx_path_is_rectangle(&pcpath->path, &box) &&
+ fixed_is_int(box.p.x | box.p.y | box.q.x | box.q.y))
+ method = write_path_as_rect;
+ else if ( !(cldev->disable_mask & clist_disable_complex_clip) )
+ method = write_path_as_path;
+ else
+ method = write_path_as_outer_box;
+ } else {
+ const gx_clip_list *list = gx_cpath_list(pcpath);
+ const gx_clip_rect *prect = list->head;
+
+ if (prect != NULL &&
+ cldev->disable_mask & clist_disable_complex_clip)
+ method = write_path_as_outer_box;
+ else
+ method = write_path_as_rects;
+ }
+
+ /* And thus how large the fill_adjust values will be. */
+ if (method == write_path_as_path)
+ fill_adjust_size = cmd_size2w(pcpath->path_fill_adjust.x,
+ pcpath->path_fill_adjust.y);
+ else
+ fill_adjust_size = cmd_size2w(0, 0);
- code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_begin_clip, 1);
+ /* Send the 'begin_clip' with the fill_adjust values. */
+ code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_begin_clip, 1+fill_adjust_size);
if (code < 0)
return code;
- if (pcpath->path_valid) {
- if (gx_path_is_rectangle(&pcpath->path, &box) &&
- fixed_is_int(box.p.x | box.p.y | box.q.x | box.q.y)
- ) {
- /* Write the path as a rectangle. */
- code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect,
- fixed2int_var(box.p.x),
- fixed2int_var(box.p.y),
- fixed2int(box.q.x - box.p.x),
- fixed2int(box.q.y - box.p.y));
- } else if ( !(cldev->disable_mask & clist_disable_complex_clip) ) {
- /* Write the path. */
- code = cmd_put_path(cldev, pcls, &pcpath->path,
- int2fixed(ymin - 1),
- int2fixed(ymax + 1),
- (byte)(pcpath->rule == gx_rule_even_odd ?
- cmd_opv_eofill : cmd_opv_fill),
- true, sn_not_first);
- } else {
- /* Complex paths disabled: write outer box as clip */
- punt_to_outer_box = true;
- }
- } else { /* Write out the rectangles. */
+ dp++;
+ if (method == write_path_as_path)
+ cmd_put2w(pcpath->path_fill_adjust.x,
+ pcpath->path_fill_adjust.y, &dp);
+ else
+ cmd_put2w(0, 0, &dp);
+
+ /* Then send the actual clip path representation. */
+ switch (method)
+ {
+ case write_path_as_rect:
+ /* Write the path as a rectangle. */
+ code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect,
+ fixed2int_var(box.p.x),
+ fixed2int_var(box.p.y),
+ fixed2int(box.q.x - box.p.x),
+ fixed2int(box.q.y - box.p.y));
+ break;
+ case write_path_as_path:
+ /* Write the path. */
+ code = cmd_put_path(cldev, pcls, &pcpath->path,
+ int2fixed(ymin - 1),
+ int2fixed(ymax + 1),
+ (byte)(pcpath->rule == gx_rule_even_odd ?
+ cmd_opv_eofill : cmd_opv_fill),
+ true, sn_not_first);
+ break;
+ case write_path_as_rects:
+ {
+ /* Write out the rectangles. */
const gx_clip_list *list = gx_cpath_list(pcpath);
const gx_clip_rect *prect = list->head;
if (prect == 0)
prect = &list->single;
- else if (cldev->disable_mask & clist_disable_complex_clip)
- punt_to_outer_box = true;
- if (!punt_to_outer_box) {
- for (; prect != 0 && code >= 0; prect = prect->next)
- if (prect->xmax > prect->xmin &&
- prect->ymin < ymax && prect->ymax > ymin
- ) {
- code =
- cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect,
- prect->xmin, prect->ymin,
- prect->xmax - prect->xmin,
- prect->ymax - prect->ymin);
- }
+ for (; prect != 0 && code >= 0; prect = prect->next) {
+ if (prect->xmax > prect->xmin &&
+ prect->ymin < ymax && prect->ymax > ymin) {
+ code = cmd_write_rect_cmd(cldev, pcls, cmd_op_fill_rect,
+ prect->xmin, prect->ymin,
+ prect->xmax - prect->xmin,
+ prect->ymax - prect->ymin);
+ }
}
+ break;
}
- if (punt_to_outer_box) {
+ default:
+ {
/* Clip is complex, but disabled. Write out the outer box */
gs_fixed_rect box;
@@ -659,6 +705,9 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
fixed2int_ceiling(box.q.x - box.p.x),
fixed2int_ceiling(box.q.y - box.p.y));
}
+ }
+
+ /* And now we can send 'end_clip' so the reader can finalise everything. */
{
int end_code =
set_cmd_put_op(&dp, cldev, pcls, cmd_opv_end_clip, 1);
@@ -715,10 +764,10 @@ cmd_write_unknown(gx_device_clist_writer * cldev, gx_clist_state * pcls,
} else {
code = set_cmd_put_op(&dp, cldev, pcls, cmd_opv_set_color_space,
2 + sizeof(clist_icc_color_t));
- memcpy(dp + 2, &(cldev->color_space.icc_info),
- sizeof(clist_icc_color_t));
if (code < 0)
return code;
+ memcpy(dp + 2, &(cldev->color_space.icc_info),
+ sizeof(clist_icc_color_t));
}
dp[1] = cldev->color_space.byte1;
pcls->known |= color_space_known;
@@ -1204,8 +1253,17 @@ clist_stroke_path(gx_device * dev, const gs_gstate * pgs, gx_path * ppath,
return code;
if (code < 0) {
/* Something went wrong, use the default implementation. */
- return gx_default_stroke_path(dev, pgs, ppath, params, pdcolor,
+ cdev->cropping_saved = false;
+ code = gx_default_stroke_path(dev, pgs, ppath, params, pdcolor,
pcpath);
+ if (cdev->cropping_saved) {
+ cdev->cropping_min = cdev->save_cropping_min;
+ cdev->cropping_max = cdev->save_cropping_max;
+ if_debug2m('v', cdev->memory,
+ "[v] clist_stroke_path: restore cropping_min=%d croping_max=%d\n",
+ cdev->save_cropping_min, cdev->save_cropping_max);
+ }
+ return code;
}
re.pcls->color_usage.slow_rop |= slow_rop;
CMD_CHECK_LAST_OP_BLOCK_DEFINED(cdev);