[gs-cvs] rev 8118 - trunk/gs/src
leonardo at ghostscript.com
leonardo at ghostscript.com
Wed Jul 11 14:17:42 PDT 2007
Author: leonardo
Date: 2007-07-11 14:17:39 -0700 (Wed, 11 Jul 2007)
New Revision: 8118
Modified:
trunk/gs/src/gdevnfwd.c
trunk/gs/src/gxcldev.h
trunk/gs/src/gxclist.c
trunk/gs/src/gxclist.h
trunk/gs/src/gxclpath.c
trunk/gs/src/gxclrast.c
trunk/gs/src/gxclread.c
trunk/gs/src/gxclrect.c
trunk/gs/src/gxdevcli.h
trunk/gs/src/gxfill.c
trunk/gs/src/gxshade1.c
trunk/gs/src/gxshade4.h
trunk/gs/src/gxshade6.c
trunk/gs/src/lib.mak
Log:
Banding : Exten\d clist language with trapezoids, linear color trapezoids and linear color triangles.
DETAILS :
This fixes the clist expansion problem for shadings.
1. New functions clist_fill_linear_color_trapezoid, clist_fill_linear_color_triangle
provide the writing of shading parts into clist
without a further decomposition into rectangles.
2. gxclrast.c is enhanced with reading the data from 1.
3. gxfill.c needs a special interaction with the clipper device
for passing the clipping path as a high level object.
The new request pattern_manage__handles_clip_path
checks whether the target device can handle a clipping path.
The clist writer can, so the graphics library first sends the
clipping path, and then decomposes the shading into
trapezoids without installing a clipper device.
Doing so because clipper device can't handle trapezoids.
See comments in gxclpath.c, gxfill.c .
4. The clist reader installs a clipper device when processes
trapezoids and linear color triangles.
The new flag clipper_dev_open controls that.
5. A new flag gx_device_clist_writer_s::cropping_by_path
controls an additional cropping of shading components,
which fall outside the shading path's bands.
See comment in gxclpath.c .
6. R_fill_rect_with_const_color is rewritten with linear color functions,
because the old implementation creates a rectangle, which is not clipped with
4,5. It gives an invisible slowdown for unbanded rasters.
There are few things, which need further improvements :
1. A better compression for frac31 values in clist.
Such values usually have many zeros in ending bits.
2. Crop bands with ybot, ytop, fa->ystart, fa->yend in
clist_write_fill_trapezoid.
3. The clist reader must handle cases when linear color functions return 0.
It must perform a decomposition of areas with calling
appropriate parts of gxshade6.c . The current code returns error,
which does not happen in practice.
EXPECTED DIFFERENCES :
There is a problem with pkmraw -r300 Bug689189.pdf
which has to be fixed separately.
This patch causes a minor raster difference with shadings :
with a banded rendering the shading area becomes some smaller
than the old banded rendering. It needs a further analyzis.
Here is a list of files with this problem :
"442-01.ps"
"446-01-fixed.ps"
"464-01-fixed.ps"
"470-01.ps"
"478-01.ps"
"483-01.ps"
"483-05-fixed.ps"
"Altona-Testsuite_p2_S_x3.pdf"
"Altona_Visual_bb_1v1_x3.pdf"
"Altona_Visual_sb_1v1_x3.pdf"
"BEST8-99-Path.fh7.pdf"
"Bug689189.pdf"
"chilis_black.pdf"
"chilis_red.pdf"
"Clarke Tate Manns Chinese.ai"
"gradmesh.ai"
"Openhuis_pdf_zw.pdf"
"S2_Digitalproof-Forum_x3k.pdf"
"self-intersect2.ps"
"shading_prob_800.ps"
"SmoothShading.pdf"
"STEUER-RollingMesh 1(linear).ai"
"STEUER-RollingMesh 2(radial).ai"
"STEUER-RollingMesh 3(Final).ai"
"Testform.v1.0.2.pdf"
This list may be related to bug 689338.
Modified: trunk/gs/src/gdevnfwd.c
===================================================================
--- trunk/gs/src/gdevnfwd.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gdevnfwd.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -757,8 +757,13 @@
return 1;
}
return 0;
- } else
+ } else {
+ if (function == pattern_manage__handles_clip_path) {
+ if (dev->procs.fill_path == gx_default_fill_path)
+ return 0;
+ }
return dev_proc(tdev, pattern_manage)(tdev, id, pinst, function);
+ }
}
int
Modified: trunk/gs/src/gxcldev.h
===================================================================
--- trunk/gs/src/gxcldev.h 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxcldev.h 2007-07-11 21:17:39 UTC (rev 8118)
@@ -283,6 +283,9 @@
dev_proc_strip_tile_rectangle(clist_strip_tile_rectangle);
dev_proc_strip_copy_rop(clist_strip_copy_rop);
dev_proc_fill_trapezoid(clist_fill_trapezoid);
+dev_proc_fill_linear_color_trapezoid(clist_fill_linear_color_trapezoid);
+dev_proc_fill_linear_color_triangle(clist_fill_linear_color_triangle);
+dev_proc_pattern_manage(clist_pattern_manage);
/* In gxclimag.c */
dev_proc_fill_mask(clist_fill_mask);
Modified: trunk/gs/src/gxclist.c
===================================================================
--- trunk/gs/src/gxclist.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclist.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -150,12 +150,12 @@
gx_forward_get_color_comp_index,
gx_forward_encode_color,
gx_forward_decode_color,
- gx_default_pattern_manage,
+ clist_pattern_manage,
gx_default_fill_rectangle_hl_color,
gx_default_include_color_space,
gx_default_fill_linear_color_scanline,
- gx_default_fill_linear_color_trapezoid, /* fixme : write to clist. */
- gx_default_fill_linear_color_triangle,
+ clist_fill_linear_color_trapezoid,
+ clist_fill_linear_color_triangle,
gx_forward_update_spot_equivalent_colors,
gx_forward_ret_devn_params
};
@@ -457,6 +457,7 @@
cdev->undercolor_removal_id = gs_no_id;
cdev->device_halftone_id = gs_no_id;
cdev->image_enum_id = gs_no_id;
+ cdev->cropping_by_path = false;
return 0;
}
/*
Modified: trunk/gs/src/gxclist.h
===================================================================
--- trunk/gs/src/gxclist.h 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclist.h 2007-07-11 21:17:39 UTC (rev 8118)
@@ -248,6 +248,8 @@
proc_free_up_bandlist_memory((*free_up_bandlist_memory)); /* if nz, proc to free some bandlist memory */
int disable_mask; /* mask of routines to disable clist_disable_xxx */
gs_pattern1_instance_t *pinst; /* Used when it is a pattern clist. */
+ bool cropping_by_path;
+ int cropping_min, cropping_max;
} gx_device_clist_writer;
/* Bits for gx_device_clist_writer.disable_mask. Bit set disables behavior */
Modified: trunk/gs/src/gxclpath.c
===================================================================
--- trunk/gs/src/gxclpath.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclpath.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -577,7 +577,21 @@
gs_fixed_point adjust;
bool slow_rop = cmd_slow_rop(dev, lop_know_S_0(lop), pdcolor);
cmd_rects_enum_t re;
+ int code;
+ if (pdcolor != NULL && gx_dc_is_pattern2_color(pdcolor)) {
+ /* Here we need to intersect *ppath, *pcpath and shading bbox.
+ Call the default implementation, which has a special
+ branch for processing a shading fill with the clip writer device.
+ It will call us back with pdcolor=NULL for passing
+ the intersected clipping path,
+ and then will decompose the shading into trapezoids.
+ See comment below about pdcolor == NULL.
+ */
+ code = gx_default_fill_path(dev, pis, ppath, params, pdcolor, pcpath);
+ cdev->cropping_by_path = false;
+ return code;
+ }
if ( (cdev->disable_mask & clist_disable_fill_path) ||
gs_debug_c(',')
) {
@@ -604,35 +618,57 @@
if (unknown)
cmd_clear_known(cdev, unknown);
if (cdev->permanent_error < 0)
- return (cdev->permanent_error);
- RECT_ENUM_INIT(re, ry, rheight);
- do {
- int code;
-
- RECT_STEP_INIT(re);
- code = cmd_do_write_unknown(cdev, re.pcls, FILL_KNOWN);
- if (code < 0)
- return code;
- if ((code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0 ||
- (code = cmd_update_lop(cdev, re.pcls, lop)) < 0
- )
- return code;
- code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
- if (code < 0) {
- /* Something went wrong, use the default implementation. */
- return gx_default_fill_path(dev, pis, ppath, params, pdcolor,
- pcpath);
- }
- re.pcls->colors_used.slow_rop |= slow_rop;
- code = cmd_put_path(cdev, re.pcls, ppath,
- int2fixed(max(re.y - 1, y0)),
- int2fixed(min(re.y + re.height + 1, y1)),
- op,
- true, sn_none /* fill doesn't need the notes */ );
- if (code < 0)
- return code;
- re.y += re.height;
- } while (re.y < re.yend);
+ return (cdev->permanent_error);
+ if (pdcolor == NULL) {
+ /* See comment above about pattern2_color.
+ Put the clipping path only.
+ The graphics library will call us again with subdividing
+ the shading into trapezoids and rectangles.
+ Note cropping_by_path is true during such calls. */
+ cdev->cropping_by_path = true;
+ cdev->cropping_min = ry;
+ cdev->cropping_max = ry + rheight;
+ RECT_ENUM_INIT(re, ry, rheight);
+ do {
+ RECT_STEP_INIT(re);
+ if (pcpath != NULL) {
+ code = cmd_do_write_unknown(cdev, re.pcls, clip_path_known);
+ if (code < 0)
+ return code;
+ }
+ code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL);
+ if (code < 0)
+ return code;
+ re.y += re.height;
+ } while (re.y < re.yend);
+ } else {
+ RECT_ENUM_INIT(re, ry, rheight);
+ do {
+ RECT_STEP_INIT(re);
+ code = cmd_do_write_unknown(cdev, re.pcls, FILL_KNOWN);
+ if (code < 0)
+ return code;
+ if ((code = cmd_do_enable_clip(cdev, re.pcls, pcpath != NULL)) < 0 ||
+ (code = cmd_update_lop(cdev, re.pcls, lop)) < 0
+ )
+ return code;
+ code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
+ if (code < 0) {
+ /* Something went wrong, use the default implementation. */
+ return gx_default_fill_path(dev, pis, ppath, params, pdcolor,
+ pcpath);
+ }
+ re.pcls->colors_used.slow_rop |= slow_rop;
+ code = cmd_put_path(cdev, re.pcls, ppath,
+ int2fixed(max(re.y - 1, y0)),
+ int2fixed(min(re.y + re.height + 1, y1)),
+ op,
+ true, sn_none /* fill doesn't need the notes */ );
+ if (code < 0)
+ return code;
+ re.y += re.height;
+ } while (re.y < re.yend);
+ }
return 0;
}
Modified: trunk/gs/src/gxclrast.c
===================================================================
--- trunk/gs/src/gxclrast.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclrast.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -90,7 +90,7 @@
long val = *p++ & 0x7f;
int shift = 7;
- for (; val += (long)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7);
+ for (; val |= (long)(*p & 0x7f) << shift, *p++ > 0x7f; shift += 7);
*rp = p;
return val;
}
@@ -291,6 +291,8 @@
int code = 0;
ht_buff_t ht_buff;
gx_device *const orig_target = target;
+ gx_device_clip clipper_dev;
+ bool clipper_dev_open;
cbuf.data = (byte *)cbuf_storage;
cbuf.size = cbuf_size;
@@ -306,6 +308,7 @@
set_colors = state.colors;
use_clip = false;
pcpath = NULL;
+ clipper_dev_open = false;
notes = sn_none;
data_x = 0;
{
@@ -944,14 +947,17 @@
break;
case cmd_opv_enable_clip:
pcpath = (use_clip ? &clip_path : NULL);
+ clipper_dev_open = false;
if_debug0('L', "\n");
break;
case cmd_opv_disable_clip:
pcpath = NULL;
+ clipper_dev_open = false;
if_debug0('L', "\n");
break;
case cmd_opv_begin_clip:
pcpath = NULL;
+ clipper_dev_open = false;
in_clip = true;
if_debug0('L', "\n");
code = gx_cpath_reset(&clip_path);
@@ -991,6 +997,7 @@
cbox.q.y >= target_box.q.y);
}
pcpath = (use_clip ? &clip_path : NULL);
+ clipper_dev_open = false;
state.lop_enabled = clip_save.lop_enabled;
imager_state.log_op =
(state.lop_enabled ? state.lop :
@@ -1389,10 +1396,19 @@
gx_cmd_rect rl, rr;
gs_fixed_edge left, right;
fixed ybot, ytop;
- int swap_axes, wh;
+ int options, swap_axes, wh;
fixed x0f;
fixed y0f;
+ gx_device *ttdev = tdev;
+ if (pcpath != NULL && !clipper_dev_open) {
+ gx_make_clip_device(&clipper_dev, gx_cpath_list(pcpath)); /* fixme : create a global instance */
+ clipper_dev.target = tdev;
+ (*dev_proc(&clipper_dev, open_device))((gx_device *)&clipper_dev);
+ clipper_dev_open = true;
+ }
+ if (clipper_dev_open)
+ ttdev = (gx_device *)&clipper_dev;
cmd_getw(left.start.x, cbp);
cmd_getw(left.start.y, cbp);
cmd_getw(left.end.x, cbp);
@@ -1403,7 +1419,8 @@
cmd_getw(right.end.y, cbp);
cmd_getw(ybot, cbp);
cmd_getw(ytop, cbp);
- cmd_getw(swap_axes, cbp);
+ cmd_getw(options, cbp);
+ swap_axes = options & 1;
wh = swap_axes ? tdev->width : tdev->height;
x0f = int2fixed(swap_axes ? y0 : x0);
y0f = int2fixed(swap_axes ? x0 : y0);
@@ -1415,10 +1432,58 @@
right.start.y -= y0f;
right.end.x -= x0f;
right.end.y -= y0f;
- code = gx_default_fill_trapezoid(tdev, &left, &right,
- max(ybot - y0f, fixed_half),
- min(ytop - y0f, int2fixed(wh)), swap_axes,
- &dev_color, imager_state.log_op);
+ if (options & 2) {
+ int num_components = tdev->color_info.num_components;
+ frac31 c[4][GX_DEVICE_COLOR_MAX_COMPONENTS], *cc[4];
+ byte colors_mask, i, j, m = 1;
+ gs_fill_attributes fa;
+ gs_fixed_rect clip;
+
+ if (cbuf.end - cbp < 5 * cmd_max_intsize(sizeof(frac31)))
+ cbp = top_up_cbuf(&cbuf, cbp);
+ cmd_getw(clip.p.x, cbp);
+ cmd_getw(clip.p.y, cbp);
+ cmd_getw(clip.q.x, cbp);
+ cmd_getw(clip.q.y, cbp);
+ clip.p.x -= x0f;
+ clip.p.y -= y0f;
+ clip.q.x -= x0f;
+ clip.q.y -= y0f;
+ fa.clip = &clip;
+ fa.swap_axes = swap_axes;
+ fa.ht = NULL;
+ fa.lop = lop_default; /* fgixme: imager_state.log_op; */
+ fa.ystart = ybot - y0f;
+ fa.yend = ytop - y0f;
+ cmd_getw(colors_mask, cbp);
+ for (i = 0; i < 4; i++, m <<= 1) {
+ if (colors_mask & m) {
+ if (cbuf.end - cbp < num_components * cmd_max_intsize(sizeof(frac31)))
+ cbp = top_up_cbuf(&cbuf, cbp);
+ cc[i] = c[i];
+ for (j = 0; j < num_components; j++)
+ cmd_getw(c[i][j], cbp);
+ } else
+ cc[i] = NULL;
+ }
+ if (options & 4)
+ code = 1 | dev_proc(ttdev, fill_linear_color_triangle)(ttdev, &fa,
+ &left.start, &left.end, &right.start,
+ cc[0], cc[1], cc[2]);
+ else
+ code = 1 || dev_proc(ttdev, fill_linear_color_trapezoid)(ttdev, &fa,
+ &left.start, &left.end, &right.start, &right.end,
+ cc[0], cc[1], cc[2], cc[3]);
+ if (code == 0) {
+ /* Fixme : The target device didn't fill the trapezoid and
+ requests a decomposition. Call a code from gxshade6.c . */
+ code = gs_note_error(gs_error_unregistered);
+ }
+ } else
+ code = gx_default_fill_trapezoid(ttdev, &left, &right,
+ max(ybot - y0f, fixed_half),
+ min(ytop - y0f, int2fixed(wh)), swap_axes,
+ &dev_color, imager_state.log_op);
}
break;
default:
@@ -2508,8 +2573,6 @@
/*
* Execute a polyfill -- either a fill_parallelogram or a fill_triangle.
- * If we ever implement fill_trapezoid in the band list, that will be
- * detected here too.
*
* Note that degenerate parallelograms or triangles may collapse into
* a single line or point. We must check for this so we don't try to
Modified: trunk/gs/src/gxclread.c
===================================================================
--- trunk/gs/src/gxclread.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclread.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -27,6 +27,7 @@
#include "gxhttile.h"
#include "gdevplnx.h"
#include "gsmemory.h"
+#include "vdtrace.h"
/*
* We really don't like the fact that gdevprn.h is included here, since
* command lists are supposed to be usable for purposes other than printer
@@ -546,7 +547,15 @@
s_std_init(&s, sbuf, cbuf_size, &no_procs, s_mode_read);
s.foreign = 1;
s.state = (stream_state *)&rs;
+
+
+ vd_get_dc('s');
+ vd_set_shift(0, 0);
+ vd_set_scale(0.01);
+ vd_set_origin(0, 0);
+ vd_erase(RGB(192, 192, 192));
code = clist_playback_band(action, crdev, &s, target, x0, y0, mem);
+ vd_release_dc;
}
/* Close the files if we just opened them. */
Modified: trunk/gs/src/gxclrect.c
===================================================================
--- trunk/gs/src/gxclrect.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxclrect.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -134,20 +134,68 @@
return 0;
}
+private inline byte *
+cmd_put_frac31_color(gx_device_clist_writer * cldev, const frac31 *c, byte *dp)
+{
+ int num_components = cldev->color_info.num_components;
+ int j;
+
+ for (j = 0; j < num_components; j++)
+ cmd_putw(c[j], dp);
+ return dp;
+}
+
+private inline int
+cmd_size_frac31_color(gx_device_clist_writer * cldev, const frac31 *c)
+{
+ int j, s = 0;
+ int num_components = cldev->color_info.num_components;
+
+ for (j = 0; j < num_components; j++)
+ s += cmd_sizew(c[j]);
+ return s;
+}
+
private int
cmd_write_trapezoid_cmd(gx_device_clist_writer * cldev, gx_clist_state * pcls,
int op, const gs_fixed_edge *left, const gs_fixed_edge *right,
- fixed ybot, fixed ytop, bool swap_axes)
+ fixed ybot, fixed ytop, int options,
+ const gs_fill_attributes *fa,
+ const frac31 *c0, const frac31 *c1,
+ const frac31 *c2, const frac31 *c3)
{
byte *dp;
int rcsize;
int code;
+ int colors_mask = 0;
rcsize = 1 + cmd_sizew(left->start.x) + cmd_sizew(left->start.y)
+ cmd_sizew(left->end.x) + cmd_sizew(left->end.y)
+ cmd_sizew(right->start.x) + cmd_sizew(right->start.y)
+ cmd_sizew(right->end.x) + cmd_sizew(right->end.y)
- + cmd_sizew(ybot) + cmd_sizew(ytop) + cmd_sizew(swap_axes);
+ + cmd_sizew(ybot) + cmd_sizew(ytop) + cmd_sizew(options);
+
+ if (options & 2) {
+ rcsize += cmd_sizew(fa->clip->p.x) + cmd_sizew(fa->clip->p.y)
+ + cmd_sizew(fa->clip->q.x) + cmd_sizew(fa->clip->q.y);
+ if (c0 != NULL) {
+ colors_mask += 1;
+ rcsize += cmd_size_frac31_color(cldev, c0);
+ }
+ if (c1 != NULL) {
+ colors_mask += 2;
+ rcsize += cmd_size_frac31_color(cldev, c1);
+ }
+ if (c2 != NULL) {
+ colors_mask += 4;
+ rcsize += cmd_size_frac31_color(cldev, c2);
+ }
+ if (c3 != NULL) {
+ colors_mask += 8;
+ rcsize += cmd_size_frac31_color(cldev, c3);
+ }
+ rcsize += cmd_sizew(colors_mask);
+ }
code = set_cmd_put_op(dp, cldev, pcls, op, rcsize);
if (code < 0)
return code;
@@ -162,11 +210,26 @@
cmd_putw(right->end.y, dp);
cmd_putw(ybot, dp);
cmd_putw(ytop, dp);
- cmd_putw(swap_axes, dp);
+ cmd_putw(options, dp);
if_debug6('L', " t%d:%d,%d,%d,%d %d\n",
rcsize - 1, left->start.x, left->start.y, left->end.x, left->end.y, ybot);
- if_debug5('L', " t%d,%d,%d,%d %d\n",
- right->start.x, right->start.y, right->end.x, right->end.y, ytop);
+ if_debug6('L', " t%d,%d,%d,%d %d o=%d\n",
+ right->start.x, right->start.y, right->end.x, right->end.y, ytop, options);
+ if (options & 2) {
+ cmd_putw(fa->clip->p.x, dp);
+ cmd_putw(fa->clip->p.y, dp);
+ cmd_putw(fa->clip->q.x, dp);
+ cmd_putw(fa->clip->q.y, dp);
+ cmd_putw(colors_mask, dp);
+ if (c0 != NULL)
+ dp = cmd_put_frac31_color(cldev, c0, dp);
+ if (c1 != NULL)
+ dp = cmd_put_frac31_color(cldev, c1, dp);
+ if (c2 != NULL)
+ dp = cmd_put_frac31_color(cldev, c2, dp);
+ if (c3 != NULL)
+ cmd_put_frac31_color(cldev, c3, dp);
+ }
return 0;
}
@@ -210,43 +273,78 @@
return 0;
}
-int
-clist_fill_trapezoid(gx_device * dev,
+private inline int
+clist_write_fill_trapezoid(gx_device * dev,
const gs_fixed_edge *left, const gs_fixed_edge *right,
- fixed ybot, fixed ytop, bool swap_axes,
- const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
+ fixed ybot, fixed ytop, int options,
+ const gx_drawing_color *pdcolor, gs_logical_operation_t lop,
+ const gs_fill_attributes *fa,
+ const frac31 *c0, const frac31 *c1,
+ const frac31 *c2, const frac31 *c3)
{
gx_device_clist_writer * const cdev =
&((gx_device_clist *)dev)->writer;
int code;
cmd_rects_enum_t re;
int ry, rheight;
+ bool swap_axes = (options & 1);
- if (swap_axes) {
- ry = fixed2int(min(left->start.x, left->end.x));
- rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
+ if (options & 4) {
+ if (swap_axes) {
+ ry = fixed2int(min(min(left->start.x, left->end.x), right->start.x));
+ rheight = fixed2int_ceiling(max(max(left->start.x, left->end.x), right->start.x)) - ry;
+ } else {
+ ry = fixed2int(min(min(left->start.y, left->end.y), right->start.y));
+ rheight = fixed2int_ceiling(max(max(left->start.y, left->end.y), right->start.y)) - ry;
+ }
} else {
- ry = fixed2int(ybot);
- rheight = fixed2int_ceiling(ytop) - ry;
+ if (swap_axes) {
+ ry = fixed2int(min(left->start.x, left->end.x));
+ rheight = fixed2int_ceiling(max(right->start.x, right->end.x)) - ry;
+ } else {
+ ry = fixed2int(ybot);
+ rheight = fixed2int_ceiling(ytop) - ry;
+ }
}
+ if (cdev->cropping_by_path) {
+ /* Cropping by Y is necessary when the shading path is smaller than shading.
+ In this case the clipping path is written into the path's bands only.
+ Thus bands outside the shading path are not clipped,
+ but the shading may paint into them, so crop them here.
+ */
+ if (ry < cdev->cropping_min) {
+ rheight = ry + rheight - cdev->cropping_min;
+ ry = cdev->cropping_min;
+ }
+ if (ry + rheight > cdev->cropping_max)
+ rheight = cdev->cropping_max - ry;
+ }
+ fit_fill_y(dev, ry, rheight);
fit_fill_h(dev, ry, rheight);
+ if (rheight < 0)
+ return 0;
if (cdev->permanent_error < 0)
return (cdev->permanent_error);
RECT_ENUM_INIT(re, ry, rheight);
do {
RECT_STEP_INIT(re);
do {
- code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
- if (code < 0) {
- /* Something went wrong, use the default implementation. */
- return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
- }
- code = cmd_update_lop(cdev, re.pcls, lop);
+ if (pdcolor != NULL) {
+ code = cmd_put_drawing_color(cdev, re.pcls, pdcolor);
+ if (code < 0) {
+ /* Something went wrong, use the default implementation. */
+ return gx_default_fill_trapezoid(dev, left, right, ybot, ytop, swap_axes, pdcolor, lop);
+ }
+ code = cmd_update_lop(cdev, re.pcls, lop);
+ } else
+ code = 0;
if (code >= 0) {
+ byte *dp;
+
/* Dont't want to shorten the trapezoid by the band boundary,
keeping in mind a further optimization with writing same data to all bands. */
code = cmd_write_trapezoid_cmd(cdev, re.pcls, cmd_opv_fill_trapezoid, left, right,
- ybot, ytop, swap_axes);
+ ybot, ytop, options, fa, c0, c1, c2, c3);
}
} while (RECT_RECOVER(code));
if (code < 0 && SET_BAND_CODE(code))
@@ -262,6 +360,88 @@
}
int
+clist_fill_trapezoid(gx_device * dev,
+ const gs_fixed_edge *left, const gs_fixed_edge *right,
+ fixed ybot, fixed ytop, bool swap_axes,
+ const gx_drawing_color *pdcolor, gs_logical_operation_t lop)
+{
+ return clist_write_fill_trapezoid(dev, left, right,
+ ybot, ytop, swap_axes, pdcolor, lop, NULL, NULL, NULL, NULL, NULL);
+}
+
+int
+clist_fill_linear_color_trapezoid(gx_device * dev, const gs_fill_attributes *fa,
+ const gs_fixed_point *p0, const gs_fixed_point *p1,
+ const gs_fixed_point *p2, const gs_fixed_point *p3,
+ const frac31 *c0, const frac31 *c1,
+ const frac31 *c2, const frac31 *c3)
+{
+ gs_fixed_edge left, right;
+ int code;
+
+ left.start = *p0;
+ left.end = *p1;
+ right.start = *p2;
+ right.end = *p3;
+ code = clist_write_fill_trapezoid(dev, &left, &right,
+ fa->ystart, fa->yend, fa->swap_axes | 2, NULL, lop_default, fa, c0, c1, c2, c3);
+ if (code < 0)
+ return code;
+ /* NOTE : The return value 0 for the fill_linear_color_trapezoid method means
+ that the device requests a further decomposition of the trapezoid.
+ Currently we have no interface for checking whether the target device
+ can handle a trapezoid without an attempt to fill it.
+ Therefore the clist writer device must always return 1,
+ and the clist reader must perform a further decomposition
+ if the target device requests it.
+ */
+ return 1;
+}
+
+int
+clist_fill_linear_color_triangle(gx_device * dev, const gs_fill_attributes *fa,
+ const gs_fixed_point *p0, const gs_fixed_point *p1,
+ const gs_fixed_point *p2,
+ const frac31 *c0, const frac31 *c1, const frac31 *c2)
+{
+ gs_fixed_edge left, right;
+ int code;
+
+ left.start = *p0;
+ left.end = *p1;
+ right.start = *p2;
+ right.end.x = right.end.y = 0; /* unused. */
+
+ code = clist_write_fill_trapezoid(dev, &left, &right,
+ fa->ystart, fa->yend, fa->swap_axes | 2 | 4, NULL, lop_default, fa, c0, c1, c2, NULL);
+ if (code < 0)
+ return code;
+ /* NOTE : The return value 0 for the fill_linear_color_triangle method means
+ that the device requests a further decomposition of the trapezoid.
+ Currently we have no interface for checking whether the target device
+ can handle a trapezoid without an attempt to fill it.
+ Therefore the clist writer device must always return 1,
+ and the clist reader must perform a further decomposition
+ if the target device requests it.
+ */
+ return 1;
+}
+
+
+int
+clist_pattern_manage(gx_device *pdev, gx_bitmap_id id,
+ gs_pattern1_instance_t *pinst, pattern_manage_t function)
+{
+ if (function == pattern_manage__handles_clip_path)
+ return 1;
+ return gx_default_pattern_manage(pdev, id, pinst, function);
+}
+
+#define dev_proc_pattern_manage(proc)\
+ dev_t_proc_pattern_manage(proc, gx_device)
+
+
+int
clist_strip_tile_rectangle(gx_device * dev, const gx_strip_bitmap * tile,
int rx, int ry, int rwidth, int rheight,
gx_color_index color0, gx_color_index color1, int px, int py)
Modified: trunk/gs/src/gxdevcli.h
===================================================================
--- trunk/gs/src/gxdevcli.h 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxdevcli.h 2007-07-11 21:17:39 UTC (rev 8118)
@@ -1225,7 +1225,8 @@
pattern_manage__load,
pattern_manage__shading_area,
pattern_manage__is_cpath_accum,
- pattern_manage__shfill_doesnt_need_path
+ pattern_manage__shfill_doesnt_need_path,
+ pattern_manage__handles_clip_path
} pattern_manage_t;
#define dev_t_proc_pattern_manage(proc, dev_t)\
@@ -1294,12 +1295,12 @@
/* [p0 : p1] - left edge, from bottom to top.
[p2 : p3] - right edge, from bottom to top.
The filled area is within Y-spans of both edges. */
-/* If either (c0 and c1) or (c2 and c3) may be NULL.
+/* Either (c0 and c1) or (c2 and c3) may be NULL.
In this case the color doesn't depend on X (on Y if fa->swap_axes).
In this case the base coordinates for the color gradient
may be unequal to p0, p1, p2, p3, and must be provided/taken
in/from fa->ystart, fa->yend.
- The rerurn value 0 is not allowed in this case. */
+ The return value 0 is not allowed in this case. */
/* Return values :
1 - success;
0 - Too big. The area isn't filled. The client must decompose the area.
Modified: trunk/gs/src/gxfill.c
===================================================================
--- trunk/gs/src/gxfill.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxfill.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -618,27 +618,38 @@
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;
- gs_fixed_rect clip_box;
- gs_int_rect cb;
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;
- if ((*dev_proc(pdev, pattern_manage))(pdev,
- gs_no_id, NULL, pattern_manage__shading_area) > 0)
- set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
- (*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,
+ if (gx_dc_is_pattern2_color(pdevc) &&
+ (*dev_proc(pdev, pattern_manage))(pdev, gs_no_id, NULL, pattern_manage__handles_clip_path) > 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, pis, ppath, params, NULL, pcpath1);
+ dev = pdev;
+ } else {
+ 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;
+ if ((*dev_proc(pdev, pattern_manage))(pdev,
+ gs_no_id, NULL, pattern_manage__shading_area) > 0)
+ set_dev_proc(&cdev, fill_path, pass_shading_area_through_clip_path_device);
+ (*dev_proc(dev, open_device))(dev);
+ 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, pis->log_op, rs);
}
Modified: trunk/gs/src/gxshade1.c
===================================================================
--- trunk/gs/src/gxshade1.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade1.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -640,8 +640,10 @@
}
private int
-R_fill_rect_with_const_color(const patch_fill_state_t *pfs, const gs_fixed_rect *clip_rect, float t)
+R_fill_rect_with_const_color(patch_fill_state_t *pfs, const gs_fixed_rect *clip_rect, float t)
{
+#if 0 /* Disabled because the clist writer device doesn't pass
+ the clipping path with fill_recatangle. */
patch_color_t pc;
const gs_color_space *pcs = pfs->direct_space;
gx_device_color dc;
@@ -658,6 +660,34 @@
fixed2int_pixround(clip_rect->q.x) - fixed2int_pixround(clip_rect->p.x),
fixed2int_pixround(clip_rect->q.y) - fixed2int_pixround(clip_rect->p.y),
&dc, pfs->dev, pfs->pis->log_op);
+#else
+ /* Can't apply fill_rectangle, because the clist writer device doesn't pass
+ the clipping path with fill_recatangle. Convert into trapezoids instead.
+ */
+ quadrangle_patch p;
+ shading_vertex_t pp[2][2];
+ const gs_color_space *pcs = pfs->direct_space;
+ patch_color_t pc;
+ int code;
+
+ code = gs_function_evaluate(pfs->Function, &t, pc.cc.paint.values);
+ if (code < 0)
+ return code;
+ pcs->type->restrict_color(&pc.cc, pcs);
+ pc.t[0] = pc.t[1] = t;
+ pp[0][0].p = clip_rect->p;
+ pp[0][1].p.x = clip_rect->q.x;
+ pp[0][1].p.y = clip_rect->p.y;
+ pp[1][0].p.x = clip_rect->p.x;
+ pp[1][0].p.y = clip_rect->q.y;
+ pp[1][1].p = clip_rect->q;
+ pp[0][0].c = pp[0][1].c = pp[1][0].c = pp[1][1].c = &pc;
+ p.p[0][0] = &pp[0][0];
+ p.p[0][1] = &pp[0][1];
+ p.p[1][0] = &pp[1][0];
+ p.p[1][1] = &pp[1][1];
+ return constant_color_quadrangle(pfs, &p, false);
+#endif
}
typedef struct radial_shading_attrs_s {
Modified: trunk/gs/src/gxshade4.h
===================================================================
--- trunk/gs/src/gxshade4.h 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade4.h 2007-07-11 21:17:39 UTC (rev 8118)
@@ -160,6 +160,11 @@
bool straight;
} patch_curve_t;
+typedef struct {
+ const shading_vertex_t *p[2][2]; /* [v][u] */
+ wedge_vertex_list_t *l0001, *l0111, *l1110, *l1000;
+} quadrangle_patch;
+
/* Initialize the fill state for triangle shading. */
int mesh_init_fill_state(mesh_fill_state_t * pfs,
const gs_shading_mesh_t * psh,
@@ -180,6 +185,8 @@
void (*transform) (gs_fixed_point *, const patch_curve_t[4],
const gs_fixed_point[4], floatp, floatp));
+int constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting);
+
int wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t *pfs);
void wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs);
Modified: trunk/gs/src/gxshade6.c
===================================================================
--- trunk/gs/src/gxshade6.c 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/gxshade6.c 2007-07-11 21:17:39 UTC (rev 8118)
@@ -618,11 +618,6 @@
patch_color_t *c[2][2]; /* [v][u] */
} tensor_patch;
-typedef struct {
- const shading_vertex_t *p[2][2]; /* [v][u] */
- wedge_vertex_list_t *l0001, *l0111, *l1110, *l1000;
-} quadrangle_patch;
-
typedef enum {
interpatch_padding = 1, /* A Padding between patches for poorly designed documents. */
inpatch_wedge = 2 /* Wedges while a patch decomposition. */
@@ -1195,6 +1190,11 @@
code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
if (code < 0)
goto out;
+ if (fa.swap_axes) {
+ vd_quad(le->start.y, le->start.x, le->end.y, le->end.x, re->end.y, re->end.x, re->start.y, re->start.x, 0, RGB(0,255,0));
+ } else {
+ vd_quad(le->start.x, le->start.y, le->end.x, le->end.y, re->end.x, re->end.y, re->start.x, re->start.y, 0, RGB(0,255,0));
+ }
code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
&le->start, &le->end, &re->start, &re->end,
fc[0], fc[1], NULL, NULL);
@@ -2337,7 +2337,7 @@
}
}
-private int
+int
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
{
patch_color_t *c[3];
Modified: trunk/gs/src/lib.mak
===================================================================
--- trunk/gs/src/lib.mak 2007-07-11 00:26:24 UTC (rev 8117)
+++ trunk/gs/src/lib.mak 2007-07-11 21:17:39 UTC (rev 8118)
@@ -1687,7 +1687,7 @@
$(gscoord_h) $(gsdevice_h)\
$(gxcldev_h) $(gxdevice_h) $(gxdevmem_h) $(gxgetbit_h) $(gxhttile_h)\
$(gsmemory_h) \
- $(stream_h) $(strimpl_h)
+ $(stream_h) $(strimpl_h) $(vdtrace_h)
$(GLCC) $(GLO_)gxclread.$(OBJ) $(C_) $(GLSRC)gxclread.c
$(GLOBJ)gxclrect.$(OBJ) : $(GLSRC)gxclrect.c $(GXERR)\
More information about the gs-cvs
mailing list