summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxclpath.c')
-rw-r--r--base/gxclpath.c231
1 files changed, 212 insertions, 19 deletions
diff --git a/base/gxclpath.c b/base/gxclpath.c
index cc5a5e3e..9a57932e 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,189 @@ 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 (pdevc_stroke == NULL || pdevc_fill == NULL)
+ return_error(gs_error_unknownerror); /* shouldn't happen */
+
+ 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 (gx_dc_is_pattern2_color(pdevc_fill) || 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;
+
+ 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 +1193,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 +1295,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,