summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxfill.c')
-rw-r--r--base/gxfill.c177
1 files changed, 92 insertions, 85 deletions
diff --git a/base/gxfill.c b/base/gxfill.c
index 88e44c99..e33cb778 100644
--- a/base/gxfill.c
+++ b/base/gxfill.c
@@ -80,7 +80,7 @@
#define TRY_TO_EXTEND_TRAP 0
#endif
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+#ifdef COLLECT_STATS_FILL
/* Define the statistics structure instance. */
stats_fill_t stats_fill;
#endif
@@ -525,7 +525,7 @@ gx_general_fill_path(gx_device * pdev, const gs_gstate * pgs,
free_line_list(&lst);
if (pfpath != ppath) /* had to flatten */
gx_path_free(pfpath, "gx_general_fill_path");
-#if defined(DEBUG) && !defined(GS_THREADSAFE)
+#ifdef COLLECT_STATS_FILL
if (gs_debug_c('f')) {
dmlputs(ppath->memory,
"[f] # alloc up down horiz step slowx iter find band bstep bfill\n");
@@ -567,103 +567,110 @@ pass_shading_area_through_clip_path_device(gx_device * pdev, const gs_gstate * p
return gx_default_fill_path(pdev, pgs, ppath, params, pdevc, pcpath);
}
-/*
- * Fill a path. This is the default implementation of the driver
- * fill_path procedure.
- */
+/* Optimization for shading and halftone fill :
+ The general filling algorithm subdivides the fill region into
+ trapezoid or rectangle subregions and then paints each subregion
+ with given color. If the color is complex, it also needs to be subdivided
+ into constant color rectangles. In the worst case it gives
+ a multiple of numbers of rectangles, which may be too slow.
+ A faster processing may be obtained with installing a clipper
+ device with the filling path, and then render the complex color
+ through it. The speeding up happens due to the clipper device
+ is optimised for fast scans through neighbour clipping rectangles.
+*/
int
-gx_default_fill_path(gx_device * pdev, const gs_gstate * pgs,
- gx_path * ppath, const gx_fill_params * params,
- const gx_device_color * pdevc, const gx_clip_path * pcpath)
+gx_default_fill_path_shading_or_pattern(gx_device * pdev, const gs_gstate * pgs,
+ gx_path * ppath, const gx_fill_params * params,
+ const gx_device_color * pdevc, const gx_clip_path * pcpath)
{
int code = 0;
+ /* We need a single clipping path here, because shadings and
+ halftones don't take 2 paths. Compute the clipping path intersection.
+ */
+ gx_clip_path cpath_intersection, cpath_with_shading_bbox;
+ const gx_clip_path *pcpath1, *pcpath2;
+ gs_gstate *pgs_noconst = (gs_gstate *)pgs; /* Break const. */
+
+ if (ppath != NULL) {
+ code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, pdev->memory, 1);
+ if (code < 0)
+ return code;
+ if (pcpath == NULL) {
+ gs_fixed_rect clip_box1;
- if (gx_dc_is_pattern2_color(pdevc)
- || pdevc->type == &gx_dc_type_data_ht_colored
- || (gx_dc_is_pattern1_color(pdevc) && gx_pattern_tile_is_clist(pdevc->colors.pattern.p_tile))
- ) {
- /* Optimization for shading and halftone fill :
- The general filling algorithm subdivides the fill region into
- trapezoid or rectangle subregions and then paints each subregion
- with given color. If the color is complex, it also needs to be subdivided
- into constant color rectangles. In the worst case it gives
- a multiple of numbers of rectangles, which may be too slow.
- A faster processing may be obtained with installing a clipper
- device with the filling path, and then render the complex color
- through it. The speeding up happens due to the clipper device
- is optimised for fast scans through neighbour clipping rectangles.
- */
- /* We need a single clipping path here, because shadings and
- halftones don't take 2 paths. Compute the clipping path intersection.
- */
- gx_clip_path cpath_intersection, cpath_with_shading_bbox;
- const gx_clip_path *pcpath1, *pcpath2;
- gs_gstate *pgs_noconst = (gs_gstate *)pgs; /* Break const. */
-
- if (ppath != NULL) {
- code = gx_cpath_init_local_shared_nested(&cpath_intersection, pcpath, pdev->memory, 1);
- if (code < 0)
- return code;
- if (pcpath == NULL) {
- gs_fixed_rect clip_box1;
-
- (*dev_proc(pdev, get_clipping_box)) (pdev, &clip_box1);
- code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box1);
- }
- if (code >= 0)
- code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule,
- pgs_noconst, params);
- pcpath1 = &cpath_intersection;
- } else
- pcpath1 = pcpath;
- pcpath2 = pcpath1;
+ (*dev_proc(pdev, get_clipping_box)) (pdev, &clip_box1);
+ code = gx_cpath_from_rectangle(&cpath_intersection, &clip_box1);
+ }
if (code >= 0)
- code = gx_dc_pattern2_clip_with_bbox(pdevc, pdev, &cpath_with_shading_bbox, &pcpath1);
- /* Do fill : */
- if (code >= 0) {
- gs_fixed_rect clip_box;
- gs_int_rect cb;
- const gx_rop_source_t *rs = NULL;
- gx_device *dev;
- gx_device_clip cdev;
-
- gx_cpath_outer_box(pcpath1, &clip_box);
- cb.p.x = fixed2int_pixround(clip_box.p.x);
- cb.p.y = fixed2int_pixround(clip_box.p.y);
- cb.q.x = fixed2int_pixround(clip_box.q.x);
- cb.q.y = fixed2int_pixround(clip_box.q.y);
- if (gx_dc_is_pattern2_color(pdevc) &&
- (*dev_proc(pdev, dev_spec_op))(pdev,
+ code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule,
+ pgs_noconst, params);
+ pcpath1 = &cpath_intersection;
+ } else
+ pcpath1 = pcpath;
+ pcpath2 = pcpath1;
+ if (code >= 0)
+ code = gx_dc_pattern2_clip_with_bbox(pdevc, pdev, &cpath_with_shading_bbox, &pcpath1);
+ /* Do fill : */
+ if (code >= 0) {
+ gs_fixed_rect clip_box;
+ gs_int_rect cb;
+ const gx_rop_source_t *rs = NULL;
+ gx_device *dev;
+ gx_device_clip cdev;
+
+ gx_cpath_outer_box(pcpath1, &clip_box);
+ cb.p.x = fixed2int_pixround(clip_box.p.x);
+ cb.p.y = fixed2int_pixround(clip_box.p.y);
+ cb.q.x = fixed2int_pixround(clip_box.q.x);
+ cb.q.y = fixed2int_pixround(clip_box.q.y);
+ if (gx_dc_is_pattern2_color(pdevc) &&
+ (*dev_proc(pdev, dev_spec_op))(pdev,
gxdso_pattern_handles_clip_path, NULL, 0) > 0) {
- /* A special interaction with clist writer device :
- pass the intersected clipping path. It uses an unusual call to
- fill_path with NULL device color. */
- code = (*dev_proc(pdev, fill_path))(pdev, pgs, ppath, params, NULL, pcpath1);
- dev = pdev;
- } else {
- gx_make_clip_device_on_stack(&cdev, pcpath1, pdev);
- dev = (gx_device *)&cdev;
- if ((*dev_proc(pdev, dev_spec_op))(pdev,
+ /* A special interaction with clist writer device :
+ pass the intersected clipping path. It uses an unusual call to
+ fill_path with NULL device color. */
+ code = (*dev_proc(pdev, fill_path))(pdev, pgs, ppath, params, NULL, pcpath1);
+ dev = pdev;
+ } else {
+ gx_make_clip_device_on_stack(&cdev, pcpath1, pdev);
+ dev = (gx_device *)&cdev;
+ if ((*dev_proc(pdev, dev_spec_op))(pdev,
gxdso_pattern_shading_area, NULL, 0) > 0)
- set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
- code = 0;
- }
- if (code >= 0)
- code = pdevc->type->fill_rectangle(pdevc,
+ set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
+ code = 0;
+ }
+ if (code >= 0)
+ code = pdevc->type->fill_rectangle(pdevc,
cb.p.x, cb.p.y, cb.q.x - cb.p.x, cb.q.y - cb.p.y,
dev, pgs->log_op, rs);
- }
- if (ppath != NULL)
- gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
- if (pcpath1 != pcpath2)
- gx_cpath_free(&cpath_with_shading_bbox, "shading_fill_cpath_intersection");
- } else {
- code = gx_general_fill_path(pdev, pgs, ppath, params, pdevc, pcpath);
}
+ if (ppath != NULL)
+ gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
+ if (pcpath1 != pcpath2)
+ gx_cpath_free(&cpath_with_shading_bbox, "shading_fill_cpath_intersection");
+
return code;
}
/*
+ * Fill a path. This is the default implementation of the driver
+ * fill_path procedure.
+ */
+int
+gx_default_fill_path(gx_device * pdev, const gs_gstate * pgs,
+ gx_path * ppath, const gx_fill_params * params,
+ const gx_device_color * pdevc, const gx_clip_path * pcpath)
+{
+ if (gx_dc_is_pattern2_color(pdevc) ||
+ pdevc->type == &gx_dc_type_data_ht_colored ||
+ (gx_dc_is_pattern1_color(pdevc) &&
+ gx_pattern_tile_is_clist(pdevc->colors.pattern.p_tile)))
+ return gx_default_fill_path_shading_or_pattern(pdev, pgs, ppath, params, pdevc, pcpath);
+ else
+ return gx_general_fill_path(pdev, pgs, ppath, params, pdevc, pcpath);
+}
+
+/*
* Fill/Stroke a path. This is the default implementation of the driver
* fill_path procedure.
*/