xref: /plan9/sys/src/cmd/gs/src/gdevddrw.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevddrw.c,v 1.27 2004/12/08 21:35:13 stefan Exp $ */
18 /* Default polygon and image drawing device procedures */
19 #include <assert.h>
20 #include "math_.h"
21 #include "memory_.h"
22 #include "stdint_.h"
23 #include "gx.h"
24 #include "gpcheck.h"
25 #include "gserrors.h"
26 #include "gsrect.h"
27 #include "gxfixed.h"
28 #include "gxmatrix.h"
29 #include "gxdcolor.h"
30 #include "gxdevice.h"
31 #include "gxiparam.h"
32 #include "gxistate.h"
33 #include "gdevddrw.h"
34 #include "vdtrace.h"
35 /*
36 #include "gxdtfill.h" - Do not remove this comment.
37                         "gxdtfill.h" is included below.
38 */
39 
40 #define VD_RECT_COLOR RGB(0, 0, 255)
41 
42 #define SWAP(a, b, t)\
43   (t = a, a = b, b = t)
44 
45 /* ---------------- Polygon and line drawing ---------------- */
46 
47 /* Define the 'remainder' analogue of fixed_mult_quo. */
48 private fixed
fixed_mult_rem(fixed a,fixed b,fixed c)49 fixed_mult_rem(fixed a, fixed b, fixed c)
50 {
51     /* All kinds of truncation may happen here, but it's OK. */
52     return a * b - fixed_mult_quo(a, b, c) * c;
53 }
54 
55 /*
56  * The trapezoid fill algorithm uses trap_line structures to keep track of
57  * the left and right edges during the Bresenham loop.
58  */
59 typedef struct trap_line_s {
60 	/*
61 	 * h is the y extent of the line (edge.end.y - edge.start.y).
62 	 * We know h > 0.
63 	 */
64     fixed h;
65 	/*
66 	 * The dx/dy ratio for the line is di + df/h.
67 	 * (The quotient refers to the l.s.b. of di, not fixed_1.)
68 	 * We know 0 <= df < h.
69 	 */
70     int di;
71     fixed df;
72 	/*
73 	 * The intersection of the line with a scan line is x + xf/h + 1.
74 	 * (The 1 refers to the least significant bit of x, not fixed_1;
75 	 * similarly, the quotient refers to the l.s.b. of x.)
76 	 * We know -h <= xf < 0.
77 	 *
78 	 * This rational value preciselly represents the mathematical line
79 	 * (with no machine arithmetic error).
80 	 *
81 	 * Note that the fractional part is negative to simplify
82 	 * some conditions in the Bresenham algorithm.
83 	 * Due to that some expressions are inobvious.
84 	 * We believe that it's a kind of archaic
85 	 * for the modern hyperthreading architecture,
86 	 * we still keep it because the code passed a huge testing
87 	 * on various platforms.
88 	 */
89     fixed x, xf;
90 	/*
91 	 * We increment (x,xf) by (ldi,ldf) after each scan line.
92 	 * (ldi,ldf) is just (di,df) converted to fixed point.
93 	 * We know 0 <= ldf < h.
94 	 */
95     fixed ldi, ldf;
96 } trap_line;
97 
98 
99 /*
100  * The linear color trapezoid fill algorithm uses trap_color structures to keep track of
101  * the color change during the Bresenham loop.
102  */
103 typedef struct trap_gradient_s {
104 	frac31 *c; /* integer part of the color in frac32 units. */
105 	int32_t *f; /* the fraction part numerator */
106 	int32_t *num; /* the gradient numerator */
107 	int32_t den; /* color gradient denominator */
108 } trap_gradient;
109 
110 
111 /*
112  * Compute the di and df members of a trap_line structure.  The x extent
113  * (edge.end.x - edge.start.x) is a parameter; the y extent (h member)
114  * has already been set.  Also adjust x for the initial y.
115  */
116 inline private void
compute_dx(trap_line * tl,fixed xd,fixed ys)117 compute_dx(trap_line *tl, fixed xd, fixed ys)
118 {
119     fixed h = tl->h;
120     int di;
121 
122     if (xd >= 0) {
123 	if (xd < h)
124 	    tl->di = 0, tl->df = xd;
125 	else {
126 	    tl->di = di = (int)(xd / h);
127 	    tl->df = xd - di * h;
128 	    tl->x += ys * di;
129 	}
130     } else {
131 	if ((tl->df = xd + h) >= 0 /* xd >= -h */)
132 	    tl->di = -1, tl->x -= ys;
133 	else {
134 	    tl->di = di = (int)-((h - 1 - xd) / h);
135 	    tl->df = xd - di * h;
136 	    tl->x += ys * di;
137 	}
138     }
139 }
140 
141 #define YMULT_LIMIT (max_fixed / fixed_1)
142 
143 /* Compute ldi, ldf, and xf similarly. */
144 inline private void
compute_ldx(trap_line * tl,fixed ys)145 compute_ldx(trap_line *tl, fixed ys)
146 {
147     int di = tl->di;
148     fixed df = tl->df;
149     fixed h = tl->h;
150 
151     if ( df < YMULT_LIMIT ) {
152 	 if ( df == 0 )		/* vertical edge, worth checking for */
153 	     tl->ldi = int2fixed(di), tl->ldf = 0, tl->xf = -h;
154 	 else {
155 	     tl->ldi = int2fixed(di) + int2fixed(df) / h;
156 	     tl->ldf = int2fixed(df) % h;
157 	     tl->xf =
158 		 (ys < fixed_1 ? ys * df % h : fixed_mult_rem(ys, df, h)) - h;
159 	 }
160     }
161     else {
162 	tl->ldi = int2fixed(di) + fixed_mult_quo(fixed_1, df, h);
163 	tl->ldf = fixed_mult_rem(fixed_1, df, h);
164 	tl->xf = fixed_mult_rem(ys, df, h) - h;
165     }
166 }
167 
168 private inline void
init_gradient(trap_gradient * g,const gs_fill_attributes * fa,const gs_linear_color_edge * e,const gs_linear_color_edge * e1,const trap_line * l,fixed ybot,int num_components)169 init_gradient(trap_gradient *g, const gs_fill_attributes *fa,
170 		const gs_linear_color_edge *e, const gs_linear_color_edge *e1,
171 		const trap_line *l, fixed ybot, int num_components)
172 {
173     int i;
174     int64_t c;
175     int32_t d;
176 
177     if (e->c1 == NULL || e->c0 == NULL)
178 	g->den = 0; /* A wedge - the color is axial along another edge. */
179     else {
180 	bool ends_from_fa = (e1->c1 == NULL || e1->c0 == NULL);
181 
182 	if (ends_from_fa)
183 	    g->den = fa->yend - fa->ystart;
184 	else {
185 	    g->den = e->end.y - e->start.y;
186 	    assert(g->den == l->h);
187 	}
188 	for (i = 0; i < num_components; i++) {
189 	    g->num[i] = e->c1[i] - e->c0[i];
190 	    c = (int64_t)g->num[i] * (uint32_t)(ybot -
191 		    (ends_from_fa ? fa->ystart : e->start.y));
192 	    d = (int32_t)(c / g->den);
193 	    g->c[i] = e->c0[i] + d;
194 	    c -= (int64_t)d * g->den;
195 	    if (c < 0) {
196 		g->c[i]--;
197 		c += g->den;
198 	    }
199 	    g->f[i] = (int32_t)c;
200 	}
201     }
202 }
203 
204 private inline void
step_gradient(trap_gradient * g,int num_components)205 step_gradient(trap_gradient *g, int num_components)
206 {
207     int i;
208 
209     if (g->den == 0)
210 	return;
211     for (i = 0; i < num_components; i++) {
212 	int64_t fc = g->f[i] + (int64_t)g->num[i] * fixed_1;
213 	int32_t fc32;
214 
215 	g->c[i] += (int32_t)(fc / g->den);
216 	fc32 = (int32_t)(fc -  fc / g->den * g->den);
217 	if (fc32 < 0) {
218 	    fc32 += g->den;
219 	    g->c[i]--;
220 	}
221 	g->f[i] = fc32;
222     }
223 }
224 
225 private inline bool
check_gradient_overflow(const gs_linear_color_edge * le,const gs_linear_color_edge * re,int num_components)226 check_gradient_overflow(const gs_linear_color_edge *le, const gs_linear_color_edge *re,
227 		int num_components)
228 {
229     if (le->c1 == NULL || re->c1 == NULL) {
230 	/* A wedge doesn't use a gradient by X. */
231 	return false;
232     } else {
233 	/* Check whether set_x_gradient, fill_linear_color_scanline can overflow.
234 
235 	   dev_proc(dev, fill_linear_color_scanline) can perform its computation in 32-bit fractions,
236 	   so we assume it never overflows. Devices which implement it with no this
237 	   assumption must implement the check in gx_default_fill_linear_color_trapezoid,
238 	   gx_default_fill_linear_color_triangle with a function other than this one.
239 
240 	   Since set_x_gradient perform computations in int64_t, which provides 63 bits
241 	   while multiplying a 32-bits color value to a coordinate,
242 	   we must restrict the X span with 63 - 32 = 31 bits.
243 	 */
244 	int32_t xl = min(le->start.x, le->end.x);
245 	int32_t xr = min(re->start.x, re->end.x);
246 	/* The pixel span boundaries : */
247 	return arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE;
248     }
249 }
250 
251 
252 private inline int
set_x_gradient_nowedge(trap_gradient * xg,const trap_gradient * lg,const trap_gradient * rg,const trap_line * l,const trap_line * r,int il,int ir,int num_components)253 set_x_gradient_nowedge(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg,
254 	     const trap_line *l, const trap_line *r, int il, int ir, int num_components)
255 {
256     /* Ignoring the ending coordinats fractions,
257        so the gridient is slightly shifted to the left (in <1 'fixed' unit). */
258     int32_t xl = l->x - (l->xf == -l->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
259     int32_t xr = r->x - (r->xf == -r->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
260     /* The pixel span boundaries : */
261     int32_t x0 = int2fixed(il) + fixed_half; /* Shift to the pixel center. */
262     int32_t x1 = int2fixed(ir) + fixed_half; /* Shift to the pixel center. */
263     int i;
264 
265 #   ifdef DEBUG
266 	if (arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE) /* Can overflow ? */
267 	    return_error(gs_error_unregistered); /* Must not happen. */
268 #   endif
269     xg->den = fixed2int(x1 - x0);
270     for (i = 0; i < num_components; i++) {
271 	/* Ignoring the ending colors fractions,
272 	   so the color gets a slightly smaller value
273 	   (in <1 'frac31' unit), but it's not important due to
274 	   the further conversion to [0, 1 << cinfo->comp_bits[j]],
275 	   which drops the fraction anyway. */
276 	int32_t cl = lg->c[i];
277 	int32_t cr = rg->c[i];
278 	int32_t c0 = (int32_t)(cl + ((int64_t)cr - cl) * (x0 - xl) / (xr - xl));
279 	int32_t c1 = (int32_t)(cl + ((int64_t)cr - cl) * (x1 - xl) / (xr - xl));
280 
281 	xg->c[i] = c0;
282 	xg->f[i] = 0; /* Insufficient bits to compute it better.
283 	                 The color so the color gets a slightly smaller value
284 			 (in <1 'frac31' unit), but it's not important due to
285 			 the further conversion to [0, 1 << cinfo->comp_bits[j]],
286 			 which drops the fraction anyway.
287 			 So setting 0 appears pretty good and fast. */
288 	xg->num[i] = c1 - c0;
289     }
290     return 0;
291 }
292 
293 private inline int
set_x_gradient(trap_gradient * xg,const trap_gradient * lg,const trap_gradient * rg,const trap_line * l,const trap_line * r,int il,int ir,int num_components)294 set_x_gradient(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg,
295 	     const trap_line *l, const trap_line *r, int il, int ir, int num_components)
296 {
297     if (lg->den == 0 || rg->den == 0) {
298 	/* A wedge doesn't use a gradient by X. */
299 	int i;
300 
301 	xg->den = 1;
302 	for (i = 0; i < num_components; i++) {
303 	    xg->c[i] = (lg->den == 0 ? rg->c[i] : lg->c[i]);
304 	    xg->f[i] = 0; /* Compatible to set_x_gradient_nowedge. */
305 	    xg->num[i] = 0;
306 	}
307 	return 0;
308     } else
309 	return set_x_gradient_nowedge(xg, lg, rg, l, r, il, ir, num_components);
310 }
311 
312 /*
313  * Fill a trapezoid.
314  * Since we need several statically defined variants of this algorithm,
315  * we stored it in gxdtfill.h and include it configuring with
316  * macros defined here.
317  */
318 #define LINEAR_COLOR 0 /* Common for shading variants. */
319 #define EDGE_TYPE gs_fixed_edge  /* Common for non-shading variants. */
320 #define FILL_ATTRS gs_logical_operation_t  /* Common for non-shading variants. */
321 
322 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_as_fd
323 #define CONTIGUOUS_FILL 0
324 #define SWAP_AXES 1
325 #define FILL_DIRECT 1
326 #include "gxdtfill.h"
327 #undef GX_FILL_TRAPEZOID
328 #undef CONTIGUOUS_FILL
329 #undef SWAP_AXES
330 #undef FILL_DIRECT
331 
332 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_as_nd
333 #define CONTIGUOUS_FILL 0
334 #define SWAP_AXES 1
335 #define FILL_DIRECT 0
336 #include "gxdtfill.h"
337 #undef GX_FILL_TRAPEZOID
338 #undef CONTIGUOUS_FILL
339 #undef SWAP_AXES
340 #undef FILL_DIRECT
341 
342 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_ns_fd
343 #define CONTIGUOUS_FILL 0
344 #define SWAP_AXES 0
345 #define FILL_DIRECT 1
346 #include "gxdtfill.h"
347 #undef GX_FILL_TRAPEZOID
348 #undef CONTIGUOUS_FILL
349 #undef SWAP_AXES
350 #undef FILL_DIRECT
351 
352 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_ns_nd
353 #define CONTIGUOUS_FILL 0
354 #define SWAP_AXES 0
355 #define FILL_DIRECT 0
356 #include "gxdtfill.h"
357 #undef GX_FILL_TRAPEZOID
358 #undef CONTIGUOUS_FILL
359 #undef SWAP_AXES
360 #undef FILL_DIRECT
361 
362 #define GX_FILL_TRAPEZOID int gx_fill_trapezoid_cf_fd
363 #define CONTIGUOUS_FILL 1
364 #define SWAP_AXES 0
365 #define FILL_DIRECT 1
366 #include "gxdtfill.h"
367 #undef GX_FILL_TRAPEZOID
368 #undef CONTIGUOUS_FILL
369 #undef SWAP_AXES
370 #undef FILL_DIRECT
371 
372 #define GX_FILL_TRAPEZOID int gx_fill_trapezoid_cf_nd
373 #define CONTIGUOUS_FILL 1
374 #define SWAP_AXES 0
375 #define FILL_DIRECT 0
376 #include "gxdtfill.h"
377 #undef GX_FILL_TRAPEZOID
378 #undef CONTIGUOUS_FILL
379 #undef SWAP_AXES
380 #undef FILL_DIRECT
381 
382 #undef EDGE_TYPE
383 #undef LINEAR_COLOR
384 #undef FILL_ATTRS
385 
386 #define LINEAR_COLOR 1 /* Common for shading variants. */
387 #define EDGE_TYPE gs_linear_color_edge /* Common for shading variants. */
388 #define FILL_ATTRS const gs_fill_attributes *  /* Common for non-shading variants. */
389 
390 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_ns_lc
391 #define CONTIGUOUS_FILL 0
392 #define SWAP_AXES 0
393 #define FILL_DIRECT 1
394 #include "gxdtfill.h"
395 #undef GX_FILL_TRAPEZOID
396 #undef CONTIGUOUS_FILL
397 #undef SWAP_AXES
398 #undef FILL_DIRECT
399 
400 #define GX_FILL_TRAPEZOID private int gx_fill_trapezoid_as_lc
401 #define CONTIGUOUS_FILL 0
402 #define SWAP_AXES 1
403 #define FILL_DIRECT 1
404 #include "gxdtfill.h"
405 #undef GX_FILL_TRAPEZOID
406 #undef CONTIGUOUS_FILL
407 #undef SWAP_AXES
408 #undef FILL_DIRECT
409 
410 #undef EDGE_TYPE
411 #undef LINEAR_COLOR
412 #undef FILL_ATTRS
413 
414 
415 int
gx_default_fill_trapezoid(gx_device * dev,const gs_fixed_edge * left,const gs_fixed_edge * right,fixed ybot,fixed ytop,bool swap_axes,const gx_device_color * pdevc,gs_logical_operation_t lop)416 gx_default_fill_trapezoid(gx_device * dev, const gs_fixed_edge * left,
417     const gs_fixed_edge * right, fixed ybot, fixed ytop, bool swap_axes,
418     const gx_device_color * pdevc, gs_logical_operation_t lop)
419 {
420     bool fill_direct = color_writes_pure(pdevc, lop);
421 
422     if (swap_axes) {
423 	if (fill_direct)
424 	    return gx_fill_trapezoid_as_fd(dev, left, right, ybot, ytop, 0, pdevc, lop);
425 	else
426 	    return gx_fill_trapezoid_as_nd(dev, left, right, ybot, ytop, 0, pdevc, lop);
427     } else {
428 	if (fill_direct)
429 	    return gx_fill_trapezoid_ns_fd(dev, left, right, ybot, ytop, 0, pdevc, lop);
430 	else
431 	    return gx_fill_trapezoid_ns_nd(dev, left, right, ybot, ytop, 0, pdevc, lop);
432     }
433 }
434 
435 private inline void
middle_frac31_color(frac31 * c,const frac31 * c0,const frac31 * c2,int num_components)436 middle_frac31_color(frac31 *c, const frac31 *c0, const frac31 *c2, int num_components)
437 {
438     /* Assuming non-negative values. */
439     int i;
440 
441     for (i = 0; i < num_components; i++)
442 	c[i] = (int32_t)(((uint32_t)c0[i] + (uint32_t)c2[i]) >> 1);
443 }
444 
445 private inline int
fill_linear_color_trapezoid_nocheck(gx_device * dev,const gs_fill_attributes * fa,const gs_linear_color_edge * le,const gs_linear_color_edge * re)446 fill_linear_color_trapezoid_nocheck(gx_device *dev, const gs_fill_attributes *fa,
447 	const gs_linear_color_edge *le, const gs_linear_color_edge *re)
448 {
449     fixed y02 = max(le->start.y, re->start.y), ymin = max(y02, fa->clip->p.y);
450     fixed y13 = min(le->end.y, re->end.y), ymax = min(y13, fa->clip->q.y);
451     int code;
452 
453     code = (fa->swap_axes ? gx_fill_trapezoid_as_lc : gx_fill_trapezoid_ns_lc)(dev,
454 	    le, re, ymin, ymax, 0, NULL, fa);
455     if (code < 0)
456 	return code;
457     return !code;
458 }
459 
460 
461 /*  Fill a trapezoid with a linear color.
462     [p0 : p1] - left edge, from bottom to top.
463     [p2 : p3] - right edge, from bottom to top.
464     The filled area is within Y-spans of both edges.
465 
466     This implemetation actually handles a bilinear color,
467     in which the generatrix keeps a parallelizm to the X axis.
468     In general a bilinear function doesn't keep the generatrix parallelizm,
469     so the caller must decompose/approximate such functions.
470 
471     Return values :
472     1 - success;
473     0 - Too big. The area isn't filled. The client must decompose the area.
474     <0 - error.
475  */
476 int
gx_default_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)477 gx_default_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
478 	const gs_fixed_point *p0, const gs_fixed_point *p1,
479 	const gs_fixed_point *p2, const gs_fixed_point *p3,
480 	const frac31 *c0, const frac31 *c1,
481 	const frac31 *c2, const frac31 *c3)
482 {
483     gs_linear_color_edge le, re;
484     int num_components = dev->color_info.num_components;
485 
486     le.start = *p0;
487     le.end = *p1;
488     le.c0 = c0;
489     le.c1 = c1;
490     le.clip_x = fa->clip->p.x;
491     re.start = *p2;
492     re.end = *p3;
493     re.c0 = c2;
494     re.c1 = c3;
495     re.clip_x = fa->clip->q.x;
496     if (check_gradient_overflow(&le, &re, num_components))
497         return 0;
498     return fill_linear_color_trapezoid_nocheck(dev, fa, &le, &re);
499 }
500 
501 private inline int
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)502 fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
503 	const gs_fixed_point *p0, const gs_fixed_point *p1,
504 	const gs_fixed_point *p2,
505 	const frac31 *c0, const frac31 *c1, const frac31 *c2)
506 {   /* p0 must be the lowest vertex. */
507     int code;
508     gs_linear_color_edge e0, e1, e2;
509     int num_components = dev->color_info.num_components;
510 
511     if (p0->y == p1->y)
512 	return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p2, p1, p2, c0, c2, c1, c2);
513     if (p1->y == p2->y)
514 	return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p2, p0, p1, c0, c2, c0, c1);
515     e0.start = *p0;
516     e0.end = *p2;
517     e0.c0 = c0;
518     e0.c1 = c2;
519     e0.clip_x = fa->clip->p.x;
520     e1.start = *p0;
521     e1.end = *p1;
522     e1.c0 = c0;
523     e1.c1 = c1;
524     e1.clip_x = fa->clip->q.x;
525     if (p0->y < p1->y && p1->y < p2->y) {
526 	e2.start = *p1;
527 	e2.end = *p2;
528 	e2.c0 = c1;
529 	e2.c1 = c2;
530 	e2.clip_x = fa->clip->q.x;
531 	if (check_gradient_overflow(&e0, &e1, num_components))
532 	    return 0;
533 	if (check_gradient_overflow(&e0, &e2, num_components))
534 	    return 0;
535 	code = fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e1);
536 	if (code <= 0) /* Sic! */
537 	    return code;
538 	return fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e2);
539     } else { /* p0->y < p2->y && p2->y < p1->y */
540 	e2.start = *p2;
541 	e2.end = *p1;
542 	e2.c0 = c2;
543 	e2.c1 = c1;
544 	e2.clip_x = fa->clip->q.x;
545 	if (check_gradient_overflow(&e0, &e1, num_components))
546 	    return 0;
547 	if (check_gradient_overflow(&e2, &e1, num_components))
548 	    return 0;
549 	code = fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e1);
550 	if (code <= 0) /* Sic! */
551 	    return code;
552 	return fill_linear_color_trapezoid_nocheck(dev, fa, &e2, &e1);
553     }
554 }
555 
556 /*  Fill a triangle with a linear color. */
557 int
gx_default_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)558 gx_default_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
559 	const gs_fixed_point *p0, const gs_fixed_point *p1,
560 	const gs_fixed_point *p2,
561 	const frac31 *c0, const frac31 *c1, const frac31 *c2)
562 {
563     fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
564     fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
565 
566     if ((int64_t)dx1 * dy2 < (int64_t)dx2 * dy1) {
567 	const gs_fixed_point *p = p1;
568 	const frac31 *c = c1;
569 
570 	p1 = p2;
571 	p2 = p;
572 	c1 = c2;
573 	c2 = c;
574     }
575     if (p0->y <= p1->y && p0->y <= p2->y)
576 	return fill_linear_color_triangle(dev, fa, p0, p1, p2, c0, c1, c2);
577     if (p1->y <= p0->y && p1->y <= p2->y)
578 	return fill_linear_color_triangle(dev, fa, p1, p2, p0, c1, c2, c0);
579     else
580 	return fill_linear_color_triangle(dev, fa, p2, p0, p1, c2, c0, c1);
581 }
582 
583 /* Fill a parallelogram whose points are p, p+a, p+b, and p+a+b. */
584 /* We should swap axes to get best accuracy, but we don't. */
585 /* We must be very careful to follow the center-of-pixel rule in all cases. */
586 int
gx_default_fill_parallelogram(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_device_color * pdevc,gs_logical_operation_t lop)587 gx_default_fill_parallelogram(gx_device * dev,
588 		 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
589 		  const gx_device_color * pdevc, gs_logical_operation_t lop)
590 {
591     fixed t;
592     fixed qx, qy, ym;
593     dev_proc_fill_trapezoid((*fill_trapezoid));
594     gs_fixed_edge left, right;
595     int code;
596 
597     /* Make a special fast check for rectangles. */
598     if (PARALLELOGRAM_IS_RECT(ax, ay, bx, by)) {
599 	gs_int_rect r;
600 
601 	INT_RECT_FROM_PARALLELOGRAM(&r, px, py, ax, ay, bx, by);
602 	return gx_fill_rectangle_device_rop(r.p.x, r.p.y, r.q.x - r.p.x,
603 					    r.q.y - r.p.y, pdevc, dev, lop);
604     }
605     /*
606      * Not a rectangle.  Ensure that the 'a' line is to the left of
607      * the 'b' line.  Testing ax <= bx is neither sufficient nor
608      * necessary: in general, we need to compare the slopes.
609      */
610     /* Ensure ay >= 0, by >= 0. */
611     if (ay < 0)
612 	px += ax, py += ay, ax = -ax, ay = -ay;
613     if (by < 0)
614 	px += bx, py += by, bx = -bx, by = -by;
615     qx = px + ax + bx;
616     if ((ax ^ bx) < 0) {	/* In this case, the test ax <= bx is sufficient. */
617 	if (ax > bx)
618 	    SWAP(ax, bx, t), SWAP(ay, by, t);
619     } else {			/*
620 				 * Compare the slopes.  We know that ay >= 0, by >= 0,
621 				 * and ax and bx have the same sign; the lines are in the
622 				 * correct order iff
623 				 *          ay/ax >= by/bx, or
624 				 *          ay*bx >= by*ax
625 				 * Eventually we can probably find a better way to test this,
626 				 * without using floating point.
627 				 */
628 	if ((double)ay * bx < (double)by * ax)
629 	    SWAP(ax, bx, t), SWAP(ay, by, t);
630     }
631     fill_trapezoid = dev_proc(dev, fill_trapezoid);
632     qy = py + ay + by;
633     left.start.x = right.start.x = px;
634     left.start.y = right.start.y = py;
635     left.end.x = px + ax;
636     left.end.y = py + ay;
637     right.end.x = px + bx;
638     right.end.y = py + by;
639 #define ROUNDED_SAME(p1, p2)\
640   (fixed_pixround(p1) == fixed_pixround(p2))
641     if (ay < by) {
642 	if (!ROUNDED_SAME(py, left.end.y)) {
643 	    code = (*fill_trapezoid) (dev, &left, &right, py, left.end.y,
644 				      false, pdevc, lop);
645 	    if (code < 0)
646 		return code;
647 	}
648 	left.start = left.end;
649 	left.end.x = qx, left.end.y = qy;
650 	ym = right.end.y;
651 	if (!ROUNDED_SAME(left.start.y, ym)) {
652 	    code = (*fill_trapezoid) (dev, &left, &right, left.start.y, ym,
653 				      false, pdevc, lop);
654 	    if (code < 0)
655 		return code;
656 	}
657 	right.start = right.end;
658 	right.end.x = qx, right.end.y = qy;
659     } else {
660 	if (!ROUNDED_SAME(py, right.end.y)) {
661 	    code = (*fill_trapezoid) (dev, &left, &right, py, right.end.y,
662 				      false, pdevc, lop);
663 	    if (code < 0)
664 		return code;
665 	}
666 	right.start = right.end;
667 	right.end.x = qx, right.end.y = qy;
668 	ym = left.end.y;
669 	if (!ROUNDED_SAME(right.start.y, ym)) {
670 	    code = (*fill_trapezoid) (dev, &left, &right, right.start.y, ym,
671 				      false, pdevc, lop);
672 	    if (code < 0)
673 		return code;
674 	}
675 	left.start = left.end;
676 	left.end.x = qx, left.end.y = qy;
677     }
678     if (!ROUNDED_SAME(ym, qy))
679 	return (*fill_trapezoid) (dev, &left, &right, ym, qy,
680 				  false, pdevc, lop);
681     else
682 	return 0;
683 #undef ROUNDED_SAME
684 }
685 
686 /* Fill a triangle whose points are p, p+a, and p+b. */
687 /* We should swap axes to get best accuracy, but we don't. */
688 int
gx_default_fill_triangle(gx_device * dev,fixed px,fixed py,fixed ax,fixed ay,fixed bx,fixed by,const gx_device_color * pdevc,gs_logical_operation_t lop)689 gx_default_fill_triangle(gx_device * dev,
690 		 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
691 		  const gx_device_color * pdevc, gs_logical_operation_t lop)
692 {
693     fixed t;
694     fixed ym;
695 
696     dev_proc_fill_trapezoid((*fill_trapezoid)) =
697 	dev_proc(dev, fill_trapezoid);
698     gs_fixed_edge left, right;
699     int code;
700 
701     /* Ensure ay >= 0, by >= 0. */
702     if (ay < 0)
703 	px += ax, py += ay, bx -= ax, by -= ay, ax = -ax, ay = -ay;
704     if (by < 0)
705 	px += bx, py += by, ax -= bx, ay -= by, bx = -bx, by = -by;
706     /* Ensure ay <= by. */
707     if (ay > by)
708 	SWAP(ax, bx, t), SWAP(ay, by, t);
709     /*
710      * Make a special check for a flat bottom or top,
711      * which we can handle with a single call on fill_trapezoid.
712      */
713     left.start.x = right.start.x = px;
714     left.start.y = right.start.y = py;
715     if (ay == 0) {
716 	/* Flat top */
717 	if (ax < 0)
718 	    left.start.x = px + ax;
719 	else
720 	    right.start.x = px + ax;
721 	left.end.x = right.end.x = px + bx;
722 	left.end.y = right.end.y = py + by;
723 	ym = py;
724     } else if (ay == by) {
725 	/* Flat bottom */
726 	if (ax < bx)
727 	    left.end.x = px + ax, right.end.x = px + bx;
728 	else
729 	    left.end.x = px + bx, right.end.x = px + ax;
730 	left.end.y = right.end.y = py + by;
731 	ym = py;
732     } else {
733 	ym = py + ay;
734 	if (fixed_mult_quo(bx, ay, by) < ax) {
735 	    /* The 'b' line is to the left of the 'a' line. */
736 	    left.end.x = px + bx, left.end.y = py + by;
737 	    right.end.x = px + ax, right.end.y = py + ay;
738 	    code = (*fill_trapezoid) (dev, &left, &right, py, ym,
739 				      false, pdevc, lop);
740 	    right.start = right.end;
741 	    right.end = left.end;
742 	} else {
743 	    /* The 'a' line is to the left of the 'b' line. */
744 	    left.end.x = px + ax, left.end.y = py + ay;
745 	    right.end.x = px + bx, right.end.y = py + by;
746 	    code = (*fill_trapezoid) (dev, &left, &right, py, ym,
747 				      false, pdevc, lop);
748 	    left.start = left.end;
749 	    left.end = right.end;
750 	}
751 	if (code < 0)
752 	    return code;
753     }
754     return (*fill_trapezoid) (dev, &left, &right, ym, right.end.y,
755 			      false, pdevc, lop);
756 }
757 
758 /* Draw a one-pixel-wide line. */
759 int
gx_default_draw_thin_line(gx_device * dev,fixed fx0,fixed fy0,fixed fx1,fixed fy1,const gx_device_color * pdevc,gs_logical_operation_t lop)760 gx_default_draw_thin_line(gx_device * dev,
761 			  fixed fx0, fixed fy0, fixed fx1, fixed fy1,
762 		  const gx_device_color * pdevc, gs_logical_operation_t lop)
763 {
764     int ix = fixed2int_var(fx0);
765     int iy = fixed2int_var(fy0);
766     int itox = fixed2int_var(fx1);
767     int itoy = fixed2int_var(fy1);
768 
769     return_if_interrupt(dev->memory);
770     if (itoy == iy) {		/* horizontal line */
771 	return (ix <= itox ?
772 		gx_fill_rectangle_device_rop(ix, iy, itox - ix + 1, 1,
773 					     pdevc, dev, lop) :
774 		gx_fill_rectangle_device_rop(itox, iy, ix - itox + 1, 1,
775 					     pdevc, dev, lop)
776 	    );
777     }
778     if (itox == ix) {		/* vertical line */
779 	return (iy <= itoy ?
780 		gx_fill_rectangle_device_rop(ix, iy, 1, itoy - iy + 1,
781 					     pdevc, dev, lop) :
782 		gx_fill_rectangle_device_rop(ix, itoy, 1, iy - itoy + 1,
783 					     pdevc, dev, lop)
784 	    );
785     } {
786 	fixed h = fy1 - fy0;
787 	fixed w = fx1 - fx0;
788 	fixed tf;
789 	bool swap_axes;
790 	gs_fixed_edge left, right;
791 
792 	if ((w < 0 ? -w : w) <= (h < 0 ? -h : h)) {
793 	    if (h < 0)
794 		SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
795 		    h = -h;
796 	    right.start.x = (left.start.x = fx0 - fixed_half) + fixed_1;
797 	    right.end.x = (left.end.x = fx1 - fixed_half) + fixed_1;
798 	    left.start.y = right.start.y = fy0;
799 	    left.end.y = right.end.y = fy1;
800 	    swap_axes = false;
801 	} else {
802 	    if (w < 0)
803 		SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
804 		    w = -w;
805 	    right.start.x = (left.start.x = fy0 - fixed_half) + fixed_1;
806 	    right.end.x = (left.end.x = fy1 - fixed_half) + fixed_1;
807 	    left.start.y = right.start.y = fx0;
808 	    left.end.y = right.end.y = fx1;
809 	    swap_axes = true;
810 	}
811 	return (*dev_proc(dev, fill_trapezoid)) (dev, &left, &right,
812 						 left.start.y, left.end.y,
813 						 swap_axes, pdevc, lop);
814     }
815 }
816 
817 /* Stub out the obsolete procedure. */
818 int
gx_default_draw_line(gx_device * dev,int x0,int y0,int x1,int y1,gx_color_index color)819 gx_default_draw_line(gx_device * dev,
820 		     int x0, int y0, int x1, int y1, gx_color_index color)
821 {
822     return -1;
823 }
824 
825 /* ---------------- Image drawing ---------------- */
826 
827 /* GC structures for image enumerator */
828 public_st_gx_image_enum_common();
829 
830 private
831 ENUM_PTRS_WITH(image_enum_common_enum_ptrs, gx_image_enum_common_t *eptr)
832     return 0;
833 case 0: return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
834 ENUM_PTRS_END
835 
RELOC_PTRS_WITH(image_enum_common_reloc_ptrs,gx_image_enum_common_t * eptr)836 private RELOC_PTRS_WITH(image_enum_common_reloc_ptrs, gx_image_enum_common_t *eptr)
837 {
838     eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst);
839 }
840 RELOC_PTRS_END
841 
842 /*
843  * gx_default_begin_image is only invoked for ImageType 1 images.  However,
844  * the argument types are different, and if the device provides a
845  * begin_typed_image procedure, we should use it.  See gxdevice.h.
846  */
847 private int
gx_no_begin_image(gx_device * dev,const gs_imager_state * pis,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)848 gx_no_begin_image(gx_device * dev,
849 		  const gs_imager_state * pis, const gs_image_t * pim,
850 		  gs_image_format_t format, const gs_int_rect * prect,
851 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
852 		  gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
853 {
854     return -1;
855 }
856 int
gx_default_begin_image(gx_device * dev,const gs_imager_state * pis,const gs_image_t * pim,gs_image_format_t format,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)857 gx_default_begin_image(gx_device * dev,
858 		       const gs_imager_state * pis, const gs_image_t * pim,
859 		       gs_image_format_t format, const gs_int_rect * prect,
860 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
861 		       gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
862 {
863     /*
864      * Hand off to begin_typed_image, being careful to avoid a
865      * possible recursion loop.
866      */
867     dev_proc_begin_image((*save_begin_image)) = dev_proc(dev, begin_image);
868     gs_image_t image;
869     const gs_image_t *ptim;
870     int code;
871 
872     set_dev_proc(dev, begin_image, gx_no_begin_image);
873     if (pim->format == format)
874 	ptim = pim;
875     else {
876 	image = *pim;
877 	image.format = format;
878 	ptim = &image;
879     }
880     code = (*dev_proc(dev, begin_typed_image))
881 	(dev, pis, NULL, (const gs_image_common_t *)ptim, prect, pdcolor,
882 	 pcpath, memory, pinfo);
883     set_dev_proc(dev, begin_image, save_begin_image);
884     return code;
885 }
886 
887 int
gx_default_begin_typed_image(gx_device * dev,const gs_imager_state * pis,const gs_matrix * pmat,const gs_image_common_t * pic,const gs_int_rect * prect,const gx_drawing_color * pdcolor,const gx_clip_path * pcpath,gs_memory_t * memory,gx_image_enum_common_t ** pinfo)888 gx_default_begin_typed_image(gx_device * dev,
889 			const gs_imager_state * pis, const gs_matrix * pmat,
890 		   const gs_image_common_t * pic, const gs_int_rect * prect,
891 	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
892 		      gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
893 {	/*
894 	 * If this is an ImageType 1 image using the imager's CTM,
895 	 * defer to begin_image.
896 	 */
897     if (pic->type->begin_typed_image == gx_begin_image1) {
898 	const gs_image_t *pim = (const gs_image_t *)pic;
899 
900 	if (pmat == 0 ||
901 	    (pis != 0 && !memcmp(pmat, &ctm_only(pis), sizeof(*pmat)))
902 	    ) {
903 	    int code = (*dev_proc(dev, begin_image))
904 	    (dev, pis, pim, pim->format, prect, pdcolor,
905 	     pcpath, memory, pinfo);
906 
907 	    if (code >= 0)
908 		return code;
909 	}
910     }
911     return (*pic->type->begin_typed_image)
912 	(dev, pis, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
913 }
914 
915 /* Backward compatibility for obsolete driver procedures. */
916 
917 int
gx_default_image_data(gx_device * dev,gx_image_enum_common_t * info,const byte ** plane_data,int data_x,uint raster,int height)918 gx_default_image_data(gx_device *dev, gx_image_enum_common_t * info,
919 		      const byte ** plane_data,
920 		      int data_x, uint raster, int height)
921 {
922     return gx_image_data(info, plane_data, data_x, raster, height);
923 }
924 
925 int
gx_default_end_image(gx_device * dev,gx_image_enum_common_t * info,bool draw_last)926 gx_default_end_image(gx_device *dev, gx_image_enum_common_t * info,
927 		     bool draw_last)
928 {
929     return gx_image_end(info, draw_last);
930 }
931