[gs-cvs] rev 8017 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Thu May 31 10:25:53 PDT 2007
Author: leonardo
Date: 2007-05-31 10:25:52 -0700 (Thu, 31 May 2007)
New Revision: 8017
Modified:
trunk/gs/src/gdevdflt.c
trunk/gs/src/gdevnfwd.c
trunk/gs/src/gdevpdfb.c
trunk/gs/src/gscolor3.c
trunk/gs/src/gsptype2.c
trunk/gs/src/gsptype2.h
trunk/gs/src/gsshade.c
trunk/gs/src/gsshade.h
trunk/gs/src/gxcpath.c
trunk/gs/src/gxdevcli.h
trunk/gs/src/gxfill.c
trunk/gs/src/gximask.c
trunk/gs/src/gxpath.h
trunk/gs/src/lib.mak
Log:
Fix (shadings) : Optimize path manipulations for shading fill.
DETAILS :
This partially improves performance for the test case of
the bug 689189 "PDF fails with /unregistered in --shfill--".
While filling a shading, the old code
converts the clipping path into a path, then
converts it to a clipping path for intersecting it
with the filling path and with the shading BBox.
These manipulations are neccessary due to the
interface restrictions for gs_shading_fill_path,
which doesn't pass a clipping path.
It causes (1) a bad performance and (2)
a wrong fill adjustment, because the conversion
of a path to a clipping path and back to path
is not identity due to fill adjustment.
The new code is a 1st step for the elimination of gs_shading_fill_path.
This patch excludes this function for raster devices.
Excluding it for higth level devices will be a next step.
The new code moves path manipulation outside the
shading color painting. Now all 3 pathes
(the filling path, the clipping patrh, and the shading BBox)
are processed in gxfill.c . The painting
is done with gs_shading_do_fill_rectangle,
which does not manipulate with pathes.
The patch modifies gx_image_fill_masked_end
to comply with the new inplementation of
gs_shading_do_fill_rectangle when a mask
is converted into a clipping path.
Another optimization avoids the generation
of a filling path for 'shfill'.
Accorgong to PLRM, shfill deals with clipping path,
but it was converted into a path due to
internal Ghostscript constraint for the device interface.
When the device implements fill_path with
the default method gx_default_fill_path,
the conversion to a path is not necessary.
To make use of this fact for optimization, the graphics library
needs to know, whether the output device uses the default
function gx_default_fill_path. This patch introduces a new response
for pattern_manage, which is named 'pattern_manage__shfill_doesnt_need_path'.
The device must respond with 1 if it does not need a path.
The patch provides implementations for raster devices and
for forwarding devices. If some device provides an instandard
fill_path method, the optimization won't work for it
(i.e. it will work as before - will recieve a path for shfill)
unless it provides a proper response to pattern_manage__shfill_doesnt_need_path .
A minor change to gdevpdfb.c fixes a paranoid compiler warning
about a possible use of unubnitialized data.
EXPECTED DIFFERENCES :
The old code erroneusely applied fill adjustment two times
when filling a path with a shading color.
Also fill adjustment was erroneusely applied when
painting a characxter with a shading color.
With new code shadings paint fewer pixels at a shading boundary,
causing a minor difference in rasters :
72dpi :
"442-01.ps"
"446-01-fixed.ps"
"470-01.ps"
"Bug687546.ps"
"Bug689189.pdf"
"chilis_black.pdf"
"chilis_red.pdf"
"Clarke Tate Manns Chinese.ai"
"gradmesh.ai"
"muur.eps"
"S2_Digitalproof-Forum_x3k.pdf"
"shading_prob_800.ps"
"SmoothShading.pdf"
"Testform.v1.0.2.pdf"
300dpi :
"470-01.ps"
"Bug687546.ps"
"Bug689189.pdf"
"chilis_black.pdf"
"chilis_red.pdf"
"Clarke Tate Manns Chinese.ai"
"muur.eps"
"S2_Digitalproof-Forum_x3k.pdf"
"SmoothShading.pdf"
Modified: trunk/gs/src/gdevdflt.c
===================================================================
--- trunk/gs/src/gdevdflt.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevdflt.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -870,6 +870,10 @@
gx_default_pattern_manage(gx_device *pdev, gx_bitmap_id id,
gs_pattern1_instance_t *pinst, pattern_manage_t function)
{
+ if (function == pattern_manage__shfill_doesnt_need_path) {
+ if (pdev->procs.fill_path == gx_default_fill_path)
+ return 1;
+ }
return 0;
}
Modified: trunk/gs/src/gdevnfwd.c
===================================================================
--- trunk/gs/src/gdevnfwd.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevnfwd.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -751,9 +751,13 @@
/* Note that clist sets fdev->target == fdev,
so this function is unapplicable to clist. */
- if (tdev == 0)
+ if (tdev == 0) {
+ if (function == pattern_manage__shfill_doesnt_need_path) {
+ if (dev->procs.fill_path == gx_default_fill_path)
+ return 1;
+ }
return 0;
- else
+ } else
return dev_proc(tdev, pattern_manage)(tdev, id, pinst, function);
}
Modified: trunk/gs/src/gdevpdfb.c
===================================================================
--- trunk/gs/src/gdevpdfb.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gdevpdfb.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -123,7 +123,7 @@
gx_color_index one, const gx_clip_path *pcpath)
{
int code;
- gs_color_space *pcs;
+ gs_color_space *pcs = NULL;
cos_value_t cs_value;
cos_value_t *pcsvalue;
byte palette[arch_sizeof_color_index * 2];
Modified: trunk/gs/src/gscolor3.c
===================================================================
--- trunk/gs/src/gscolor3.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gscolor3.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -58,7 +58,6 @@
* shading with Background removed.
*/
gs_pattern2_template_t pat;
- gx_path cpath;
gs_matrix imat;
gs_client_color cc;
gs_color_space *pcs;
@@ -98,12 +97,22 @@
code = pcs->type->remap_color(&cc, pcs, &devc, (gs_imager_state *)pgs,
pgs->device, gs_color_select_texture);
if (code >= 0) {
- gx_path_init_local(&cpath, pgs->memory);
- code = gx_cpath_to_path(pgs->clip_path, &cpath);
- if (code >= 0)
- code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
+ gx_device *dev = pgs->device;
+ bool need_path = !dev_proc(dev, pattern_manage)(dev, gs_no_id, NULL,
+ pattern_manage__shfill_doesnt_need_path);
+
+ if (need_path) {
+ gx_path cpath;
+
+ gx_path_init_local(&cpath, pgs->memory);
+ code = gx_cpath_to_path(pgs->clip_path, &cpath);
+ if (code >= 0)
+ code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number,
+ pgs->fill_adjust.x, pgs->fill_adjust.y);
+ gx_path_free(&cpath, "gs_shfill");
+ } else
+ code = gx_fill_path(NULL, &devc, pgs, gx_rule_winding_number,
pgs->fill_adjust.x, pgs->fill_adjust.y);
- gx_path_free(&cpath, "gs_shfill");
}
rc_decrement(pcs, "gs_shfill");
gs_pattern_reference(&cc, -1);
Modified: trunk/gs/src/gsptype2.c
===================================================================
--- trunk/gs/src/gsptype2.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsptype2.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -218,6 +218,10 @@
}
/* Fill a rectangle with a PatternType 2 color. */
+/* WARNING: This function doesn't account the shading BBox
+ to allow the clipent to optimize the clipping
+ with changing the order of clip patrhs and rects.
+ The client must clip with the shading BBOx before calling this function. */
private int
gx_dc_pattern2_fill_rectangle(const gx_device_color * pdevc, int x, int y,
int w, int h, gx_device * dev,
@@ -230,12 +234,15 @@
return dev_proc(dev, fill_rectangle)(dev, x, y, w, h, (gx_color_index)0/*any*/);
} else {
gs_fixed_rect rect;
+ gs_pattern2_instance_t *pinst =
+ (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
rect.p.x = int2fixed(x);
rect.p.y = int2fixed(y);
rect.q.x = int2fixed(x + w);
rect.q.y = int2fixed(y + h);
- return gx_dc_pattern2_fill_path(pdevc, NULL, &rect, dev);
+ return gs_shading_do_fill_rectangle(pinst->template.Shading, &rect, dev,
+ (gs_imager_state *)pinst->saved, !pinst->shfill);
}
}
@@ -303,6 +310,59 @@
return 1;
}
+int
+gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc)
+{
+ gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+ const gs_shading_t *psh = pinst->template.Shading;
+
+ return psh->params.have_BBox;
+}
+
+/* Create a path from a PatternType 2 shading BBox to a path. */
+int
+gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc)
+{
+ gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+ const gs_shading_t *psh = pinst->template.Shading;
+
+ if (!psh->params.have_BBox)
+ return_error(gs_error_unregistered); /* Do not call in this case. */
+ else {
+ gs_state *pis = pinst->saved;
+
+ return shading_path_add_box(ppath, &psh->params.BBox, &pis->ctm);
+ }
+}
+
+/* Intersect a clipping path a shading BBox. */
+int
+gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc, gx_device * pdev,
+ gx_clip_path *cpath_local, const gx_clip_path **ppcpath1)
+{
+ if (gx_dc_is_pattern2_color(pdevc) && gx_dc_pattern2_color_has_bbox(pdevc) &&
+ (*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__shading_area) == 0) {
+ gs_pattern2_instance_t *pinst = (gs_pattern2_instance_t *)pdevc->ccolor.pattern;
+ gx_path box_path;
+ int code;
+
+ gx_path_init_local(&box_path, pdev->memory);
+ code = gx_dc_shading_path_add_box(&box_path, pdevc);
+ if (code == gs_error_limitcheck) {
+ /* Ignore huge BBox - bug 689027. */
+ code = 0;
+ } else {
+ if (code >= 0) {
+ gx_cpath_init_local_shared(cpath_local, *ppcpath1, pdev->memory);
+ code = gx_cpath_intersect(cpath_local, &box_path, gx_rule_winding_number, (gs_imager_state *)pinst->saved);
+ *ppcpath1 = cpath_local;
+ }
+ }
+ gx_path_free(&box_path, "gx_default_fill_path(path_bbox)");
+ }
+ return 0;
+}
+
/* Get a shading color space. */
const gs_color_space *
gx_dc_pattern2_get_color_space(const gx_device_color * pdevc)
Modified: trunk/gs/src/gsptype2.h
===================================================================
--- trunk/gs/src/gsptype2.h 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsptype2.h 2007-05-31 17:25:52 UTC (rev 8017)
@@ -75,6 +75,11 @@
typedef struct gs_color_space_s gs_color_space;
#endif
+#ifndef gx_clip_path_DEFINED
+# define gx_clip_path_DEFINED
+typedef struct gx_clip_path_s gx_clip_path;
+#endif
+
extern const gx_device_color_type_t gx_dc_pattern2;
#define gx_dc_type_pattern2 (&gx_dc_pattern2)
@@ -107,6 +112,18 @@
/* Get a shading bbox. Returns 1 on success. */
int gx_dc_pattern2_get_bbox(const gx_device_color * pdevc, gs_fixed_rect *bbox);
+/* Checks whether a PatternType 2 has a shading BBox. */
+int gx_dc_pattern2_color_has_bbox(const gx_device_color * pdevc);
+
+/* Intersect a clipping path a shading BBox. */
+int gx_dc_pattern2_clip_with_bbox(const gx_device_color * pdevc, gx_device * pdev,
+ gx_clip_path *cpath_local, const gx_clip_path **cpath1);
+
+
+/* Create a path from a PatternType 2 shading BBox to a path. */
+int gx_dc_shading_path_add_box(gx_path *ppath, const gx_device_color * pdevc);
+
+
/* Get a shading color space. */
const gs_color_space *gx_dc_pattern2_get_color_space(const gx_device_color * pdevc);
Modified: trunk/gs/src/gsshade.c
===================================================================
--- trunk/gs/src/gsshade.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsshade.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -417,7 +417,7 @@
/* ================ Shading rendering ================ */
/* Add a user-space rectangle to a path. */
-private int
+int
shading_path_add_box(gx_path *ppath, const gs_rect *pbox,
const gs_matrix_fixed *pmat)
{
@@ -441,12 +441,51 @@
}
/* Fill a path with a shading. */
+int
+gs_shading_do_fill_rectangle(const gs_shading_t *psh,
+ const gs_fixed_rect *prect, gx_device *dev,
+ gs_imager_state *pis, bool fill_background)
+{ /* If you need to fill a path, clip the output device before calling this function. */
+ const gs_matrix_fixed *pmat = &pis->ctm;
+ gs_fixed_rect path_box;
+ gs_rect path_rect;
+ gs_rect rect;
+ int code = 0;
+
+ dev_proc(dev, get_clipping_box)(dev, &path_box);
+ if (prect)
+ rect_intersect(path_box, *prect);
+ if (psh->params.Background && fill_background) {
+ const gs_color_space *pcs = psh->params.ColorSpace;
+ gs_client_color cc;
+ gx_device_color dev_color;
+
+ cc = *psh->params.Background;
+ (*pcs->type->restrict_color)(&cc, pcs);
+ (*pcs->type->remap_color)(&cc, pcs, &dev_color, pis,
+ dev, gs_color_select_texture);
+
+ /****** WRONG IF NON-IDEMPOTENT RasterOp ******/
+ code = gx_shade_background(dev, &path_box, &dev_color, pis->log_op);
+ }
+ if (code >= 0) {
+ path_rect.p.x = fixed2float(path_box.p.x);
+ path_rect.p.y = fixed2float(path_box.p.y);
+ path_rect.q.x = fixed2float(path_box.q.x);
+ path_rect.q.y = fixed2float(path_box.q.y);
+ gs_bbox_transform_inverse(&path_rect, (const gs_matrix *)pmat, &rect);
+ code = gs_shading_fill_rectangle(psh, &rect, &path_box, dev, pis);
+ }
+ return code;
+}
+
+/* Fill a path with a shading. */
+/* Depricated. To be removed soon. */
private int
gs_shading_fill_path(const gs_shading_t *psh, /*const*/ gx_path *ppath,
const gs_fixed_rect *prect, gx_device *orig_dev,
gs_imager_state *pis, bool fill_background)
-{
- gs_memory_t *mem = pis->memory;
+{ gs_memory_t *mem = pis->memory;
const gs_matrix_fixed *pmat = &pis->ctm;
gx_device *dev = orig_dev;
gs_fixed_rect path_box;
Modified: trunk/gs/src/gsshade.h
===================================================================
--- trunk/gs/src/gsshade.h 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gsshade.h 2007-05-31 17:25:52 UTC (rev 8017)
@@ -253,8 +253,14 @@
# define gx_path_DEFINED
typedef struct gx_path_s gx_path;
#endif
+/* Fill a path with a shading. */
+/* Depricated. To be removed soon. */
int gs_shading_fill_path_adjusted(const gs_shading_t *psh, /*const*/ gx_path *ppath,
const gs_fixed_rect *prect, gx_device *dev,
gs_imager_state *pis, bool fill_background);
+/* Fill a path with a shading. */
+int gs_shading_do_fill_rectangle(const gs_shading_t *psh,
+ const gs_fixed_rect *prect, gx_device *dev,
+ gs_imager_state *pis, bool fill_background);
#endif /* gsshade_INCLUDED */
Modified: trunk/gs/src/gxcpath.c
===================================================================
--- trunk/gs/src/gxcpath.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxcpath.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -375,56 +375,67 @@
/* ------ Clipping path accessing ------ */
+/* Synthesize a path from a clipping path. */
+int
+gx_cpath_to_path_synthesize(const gx_clip_path * pcpath, gx_path * ppath)
+{
+ /* Synthesize a path. */
+ gs_cpath_enum cenum;
+ gs_fixed_point pts[3];
+ int code;
+
+ gx_cpath_enum_init(&cenum, pcpath);
+ while ((code = gx_cpath_enum_next(&cenum, pts)) != 0) {
+ switch (code) {
+ case gs_pe_moveto:
+ code = gx_path_add_point(ppath, pts[0].x, pts[0].y);
+ break;
+ case gs_pe_lineto:
+ code = gx_path_add_line_notes(ppath, pts[0].x, pts[0].y,
+ gx_cpath_enum_notes(&cenum));
+ break;
+ case gs_pe_curveto:
+ code = gx_path_add_curve_notes(ppath, pts[0].x, pts[0].y,
+ pts[1].x, pts[1].y,
+ pts[2].x, pts[2].y,
+ gx_cpath_enum_notes(&cenum));
+ break;
+ case gs_pe_closepath:
+ code = gx_path_close_subpath_notes(ppath,
+ gx_cpath_enum_notes(&cenum));
+ break;
+ default:
+ if (code >= 0)
+ code = gs_note_error(gs_error_unregistered);
+ }
+ if (code < 0)
+ break;
+ }
+ return 0;
+}
+
/* Return the path of a clipping path. */
int
gx_cpath_to_path(gx_clip_path * pcpath, gx_path * ppath)
{
if (!pcpath->path_valid) {
- /* Synthesize a path. */
- gs_cpath_enum cenum;
- gs_fixed_point pts[3];
gx_path rpath;
int code;
gx_path_init_local(&rpath, pcpath->path.memory);
- gx_cpath_enum_init(&cenum, pcpath);
- while ((code = gx_cpath_enum_next(&cenum, pts)) != 0) {
- switch (code) {
- case gs_pe_moveto:
- code = gx_path_add_point(&rpath, pts[0].x, pts[0].y);
- break;
- case gs_pe_lineto:
- code = gx_path_add_line_notes(&rpath, pts[0].x, pts[0].y,
- gx_cpath_enum_notes(&cenum));
- break;
- case gs_pe_curveto:
- code = gx_path_add_curve_notes(&rpath, pts[0].x, pts[0].y,
- pts[1].x, pts[1].y,
- pts[2].x, pts[2].y,
- gx_cpath_enum_notes(&cenum));
- break;
- case gs_pe_closepath:
- code = gx_path_close_subpath_notes(&rpath,
- gx_cpath_enum_notes(&cenum));
- break;
- default:
- if (code >= 0)
- code = gs_note_error(gs_error_unregistered);
- }
- if (code < 0)
- break;
- }
- if (code >= 0)
- code = gx_path_assign_free(&pcpath->path, &rpath);
+ code = gx_cpath_to_path_synthesize(pcpath, ppath);
if (code < 0) {
gx_path_free(&rpath, "gx_cpath_to_path error");
return code;
}
+ code = gx_path_assign_free(&pcpath->path, &rpath);
+ if (code < 0)
+ return code;
pcpath->path_valid = true;
+ return 0;
}
return gx_path_assign_preserve(ppath, &pcpath->path);
}
-
/* Return the inner and outer check rectangles for a clipping path. */
/* Return true iff the path is a rectangle. */
bool
@@ -474,7 +485,7 @@
}
/* Internal non-const version of the same accessor. */
inline private gx_clip_list *
-gx_cpath_list_private(gx_clip_path *pcpath)
+gx_cpath_list_private(const gx_clip_path *pcpath)
{
return &pcpath->rect_list->list;
}
@@ -760,7 +771,7 @@
/* Start enumerating a clipping path. */
int
-gx_cpath_enum_init(gs_cpath_enum * penum, gx_clip_path * pcpath)
+gx_cpath_enum_init(gs_cpath_enum * penum, const gx_clip_path * pcpath)
{
if ((penum->using_path = pcpath->path_valid)) {
gx_path_enum_init(&penum->path_enum, &pcpath->path);
Modified: trunk/gs/src/gxdevcli.h
===================================================================
--- trunk/gs/src/gxdevcli.h 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxdevcli.h 2007-05-31 17:25:52 UTC (rev 8017)
@@ -1224,7 +1224,8 @@
pattern_manage__finish_accum,
pattern_manage__load,
pattern_manage__shading_area,
- pattern_manage__is_cpath_accum
+ pattern_manage__is_cpath_accum,
+ pattern_manage__shfill_doesnt_need_path
} pattern_manage_t;
#define dev_t_proc_pattern_manage(proc, dev_t)\
Modified: trunk/gs/src/gxfill.c
===================================================================
--- trunk/gs/src/gxfill.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxfill.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -41,6 +41,7 @@
#include "gxpaint.h" /* for prototypes */
#include "gxfdrop.h"
#include "gxfill.h"
+#include "gxpath.h"
#include "gsptype1.h"
#include "gsptype2.h"
#include "gxpcolor.h"
@@ -565,7 +566,7 @@
gx_path * ppath, const gx_fill_params * params,
const gx_device_color * pdevc, const gx_clip_path * pcpath)
{
- int code;
+ int code = 0;
if (gx_dc_is_pattern2_color(pdevc)
|| pdevc->type == &gx_dc_type_data_ht_colored
@@ -585,60 +586,49 @@
/* 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;
- gx_path path_intersection;
+ gx_clip_path cpath_intersection, cpath_with_shading_bbox;
+ const gx_clip_path *pcpath1, *pcpath2;
+ gs_imager_state *pis_noconst = (gs_imager_state *)pis; /* Break const. */
- gx_path_init_local(&path_intersection, pdev->memory);
- gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
- code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule,
- (gs_imager_state *)pis, params);
+ if (ppath != NULL) {
+ gx_cpath_init_local_shared(&cpath_intersection, pcpath, pdev->memory);
+ code = gx_cpath_intersect_with_params(&cpath_intersection, ppath, params->rule,
+ pis_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) {
- if (pdevc->type == &gx_dc_type_data_ht_colored || gx_dc_is_pattern1_color(pdevc)) {
- const gx_rop_source_t *rs = NULL;
- gx_device *dev;
- gx_device_clip cdev;
- gs_fixed_rect clip_box;
- gs_int_rect cb;
+ const gx_rop_source_t *rs = NULL;
+ gx_device *dev;
+ gx_device_clip cdev;
+ gs_fixed_rect clip_box;
+ gs_int_rect cb;
- gx_cpath_outer_box(&cpath_intersection, &clip_box);
- gx_make_clip_path_device(&cdev, &cpath_intersection);
- cdev.target = pdev;
- dev = (gx_device *)&cdev;
- (*dev_proc(dev, open_device))(dev);
- 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);
- 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, pis->log_op, rs);
- } else {
- /* The shading fill algorithm fills an area restricted with a path,
- so we need to convert cpath into path.
-
- We can't set a clipping device here like we did for
- gx_dc_type_data_ht_colored, because the shading itself
- may add another clipping with its BBox,
- which may be transformed into a parallelogram.
- We don't want two clipping devices chained consequently.
- */
- if (params->rule != gx_rule_winding_number) {
- /* HACK : Rather cpath_intersection contains a valid path,
- it is not planarized to a simple winding path,
- so we can't use the contained path.
- Reset path_valid against using it.
- */
- cpath_intersection.path_valid = false;
- }
- code = gx_cpath_to_path(&cpath_intersection, &path_intersection);
- if (code >= 0)
- code = gx_dc_pattern2_fill_path(pdevc, &path_intersection, NULL, pdev);
- }
+ gx_cpath_outer_box(pcpath1, &clip_box);
+ gx_make_clip_path_device(&cdev, pcpath1);
+ cdev.HWResolution[0] = pdev->HWResolution[0];
+ cdev.HWResolution[1] = pdev->HWResolution[1];
+ cdev.target = pdev;
+ dev = (gx_device *)&cdev;
+ (*dev_proc(dev, open_device))(dev);
+ 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);
+ 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, pis->log_op, rs);
}
- /* Destruct local data and return :*/
- gx_path_free(&path_intersection, "shading_fill_path_intersection");
- gx_cpath_free(&cpath_intersection, "shading_fill_cpath_intersection");
+ 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 {
bool got_dc = false;
vd_save;
Modified: trunk/gs/src/gximask.c
===================================================================
--- trunk/gs/src/gximask.c 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gximask.c 2007-05-31 17:25:52 UTC (rev 8017)
@@ -60,23 +60,30 @@
gx_image_fill_masked_end(gx_device *dev, gx_device *tdev, const gx_device_color *pdevc)
{
gx_device_cpath_accum *pcdev = (gx_device_cpath_accum *)dev;
- gx_clip_path cpath;
+ gx_clip_path cpath, cpath_with_shading_bbox;
+ const gx_clip_path *pcpath1 = &cpath;
gx_device_clip cdev;
int code, code1;
gx_cpath_init_local(&cpath, pcdev->memory);
code = gx_cpath_accum_end(pcdev, &cpath);
- gx_make_clip_path_device(&cdev, &cpath);
- cdev.target = tdev;
- (*dev_proc(&cdev, open_device)) ((gx_device *) & cdev);
- code1 = gx_device_color_fill_rectangle(pdevc,
- pcdev->bbox.p.x, pcdev->bbox.p.y,
- pcdev->bbox.q.x - pcdev->bbox.p.x,
- pcdev->bbox.q.y - pcdev->bbox.p.y,
- (gx_device *)&cdev, lop_default, 0);
- if (code == 0)
- code = code1;
- gx_device_retain((gx_device *)pcdev, false);
+ if (code >= 0)
+ code = gx_dc_pattern2_clip_with_bbox(pdevc, tdev, &cpath_with_shading_bbox, &pcpath1);
+ if (code >= 0) {
+ gx_make_clip_path_device(&cdev, pcpath1);
+ cdev.target = tdev;
+ (*dev_proc(&cdev, open_device)) ((gx_device *) & cdev);
+ code1 = gx_device_color_fill_rectangle(pdevc,
+ pcdev->bbox.p.x, pcdev->bbox.p.y,
+ pcdev->bbox.q.x - pcdev->bbox.p.x,
+ pcdev->bbox.q.y - pcdev->bbox.p.y,
+ (gx_device *)&cdev, lop_default, 0);
+ if (code == 0)
+ code = code1;
+ gx_device_retain((gx_device *)pcdev, false);
+ }
+ if (pcpath1 == &cpath_with_shading_bbox)
+ gx_cpath_free(&cpath_with_shading_bbox, "s_image_cleanup");
gx_cpath_free(&cpath, "s_image_cleanup");
return code;
}
Modified: trunk/gs/src/gxpath.h
===================================================================
--- trunk/gs/src/gxpath.h 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/gxpath.h 2007-05-31 17:25:52 UTC (rev 8017)
@@ -334,7 +334,8 @@
gx_cpath_scale_exp2_shared(gx_clip_path *pcpath, int log2_scale_x,
int log2_scale_y, bool list_shared,
bool segments_shared),
- gx_cpath_to_path(gx_clip_path *, gx_path *);
+ gx_cpath_to_path(gx_clip_path *, gx_path *),
+ gx_cpath_to_path_synthesize(const gx_clip_path * pcpath, gx_path * ppath);
bool
gx_cpath_inner_box(const gx_clip_path *, gs_fixed_rect *),
gx_cpath_outer_box(const gx_clip_path *, gs_fixed_rect *),
@@ -345,7 +346,7 @@
/* Enumerate a clipping path. This interface does not copy the path. */
/* However, it does write into the path's "visited" flags. */
-int gx_cpath_enum_init(gs_cpath_enum *, gx_clip_path *);
+int gx_cpath_enum_init(gs_cpath_enum *, const gx_clip_path *);
int gx_cpath_enum_next(gs_cpath_enum *, gs_fixed_point[3]); /* 0 when done */
segment_notes
Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak 2007-05-30 06:05:43 UTC (rev 8016)
+++ trunk/gs/src/lib.mak 2007-05-31 17:25:52 UTC (rev 8017)
@@ -607,9 +607,10 @@
$(GLCC) $(GLO_)gxhldevc.$(OBJ) $(C_) $(GLSRC)gxhldevc.c
$(GLOBJ)gxfill.$(OBJ) : $(GLSRC)gxfill.c $(GXERR)\
- $(gsstruct_h)\
+ $(gsstruct_h) $(gsfixed_h)\
$(gxdcolor_h) $(gxdevice_h) $(gxfixed_h) $(gxhttile_h)\
- $(gxistate_h) $(gxpaint_h) $(gxfill_h) $(gxfdrop_h) $(gsptype1_h) $(gsptype2_h) $(gxpcolor_h)\
+ $(gxistate_h) $(gxpaint_h) $(gxfdrop_h) $(gxfill_h) $(gxpath_h)\
+ $(gsptype1_h) $(gsptype2_h) $(gxpcolor_h)\
$(gzcpath_h) $(gzpath_h) $(gzspotan_h) $(gdevddrw_h) $(memory__h) $(stdint_) $(vdtrace_h)\
$(gxfilltr_h) $(gxfillsl_h) $(gxfillts_h)
$(GLCC) $(GLO_)gxfill.$(OBJ) $(C_) $(GLSRC)gxfill.c
More information about the gs-cvs
mailing list