xref: /plan9/sys/src/cmd/gs/src/gxshade6.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 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: gxshade6.c,v 1.100 2005/05/25 15:57:58 igor Exp $ */
18 /* Rendering for Coons and tensor patch shadings */
19 /*
20    A contiguous non-overlapping decomposition
21    of a tensor shading into linear color triangles.
22  */
23 #include "memory_.h"
24 #include "gx.h"
25 #include "gserrors.h"
26 #include "gsmatrix.h"		/* for gscoord.h */
27 #include "gscoord.h"
28 #include "gxcspace.h"
29 #include "gxdcolor.h"
30 #include "gxistate.h"
31 #include "gxshade.h"
32 #include "gxshade4.h"
33 #include "gxdevcli.h"
34 #include "gxarith.h"
35 #include "gzpath.h"
36 #include "stdint_.h"
37 #include "math_.h"
38 #include "vdtrace.h"
39 #include <assert.h>
40 
41 #define VD_TRACE_TENSOR_PATCH 1
42 
43 #if NOFILL_TEST
44 static bool dbg_nofill = false;
45 #endif
46 #if SKIP_TEST
47 static int dbg_patch_cnt = 0;
48 static int dbg_quad_cnt = 0;
49 static int dbg_triangle_cnt = 0;
50 static int dbg_wedge_triangle_cnt = 0;
51 #endif
52 
53 static int min_linear_grades = 255; /* The minimal number of device color grades,
54             required to apply linear color device functions. */
55 
56 /* ================ Utilities ================ */
57 
58 /* Get colors for patch vertices. */
59 private int
shade_next_colors(shade_coord_stream_t * cs,patch_curve_t * curves,int num_vertices)60 shade_next_colors(shade_coord_stream_t * cs, patch_curve_t * curves,
61 		  int num_vertices)
62 {
63     int i, code = 0;
64 
65     for (i = 0; i < num_vertices && code >= 0; ++i) {
66         curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
67 	code = shade_next_color(cs, curves[i].vertex.cc);
68     }
69     return code;
70 }
71 
72 /* Get a Bezier or tensor patch element. */
73 private int
shade_next_curve(shade_coord_stream_t * cs,patch_curve_t * curve)74 shade_next_curve(shade_coord_stream_t * cs, patch_curve_t * curve)
75 {
76     int code = shade_next_coords(cs, &curve->vertex.p, 1);
77 
78     if (code >= 0)
79 	code = shade_next_coords(cs, curve->control,
80 				 countof(curve->control));
81     return code;
82 }
83 
84 /*
85  * Parse the next patch out of the input stream.  Return 1 if done,
86  * 0 if patch, <0 on error.
87  */
88 private int
shade_next_patch(shade_coord_stream_t * cs,int BitsPerFlag,patch_curve_t curve[4],gs_fixed_point interior[4])89 shade_next_patch(shade_coord_stream_t * cs, int BitsPerFlag,
90 	patch_curve_t curve[4], gs_fixed_point interior[4] /* 0 for Coons patch */ )
91 {
92     int flag = shade_next_flag(cs, BitsPerFlag);
93     int num_colors, code;
94 
95     if (flag < 0) {
96 	if (!cs->is_eod(cs))
97 	    return_error(gs_error_rangecheck);
98 	return 1;		/* no more data */
99     }
100     switch (flag & 3) {
101 	default:
102 	    return_error(gs_error_rangecheck);	/* not possible */
103 	case 0:
104 	    if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
105 		(code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
106 		)
107 		return code;
108 	    num_colors = 4;
109 	    goto vx;
110 	case 1:
111 	    curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
112 	    goto v3;
113 	case 2:
114 	    curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
115 	    goto v3;
116 	case 3:
117 	    curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
118 v3:	    num_colors = 2;
119 vx:	    if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
120 		(code = shade_next_curve(cs, &curve[2])) < 0 ||
121 		(code = shade_next_curve(cs, &curve[3])) < 0 ||
122 		(interior != 0 &&
123 		 (code = shade_next_coords(cs, interior, 4)) < 0) ||
124 		(code = shade_next_colors(cs, &curve[4 - num_colors],
125 					  num_colors)) < 0
126 		)
127 		return code;
128     }
129     return 0;
130 }
131 
132 int
init_patch_fill_state(patch_fill_state_t * pfs)133 init_patch_fill_state(patch_fill_state_t *pfs)
134 {
135     /* Warning : pfs->Function must be set in advance. */
136     const gs_color_space *pcs = pfs->direct_space;
137     gs_client_color fcc0, fcc1;
138     int i, code;
139 
140     for (i = 0; i < pfs->num_components; i++) {
141 	fcc0.paint.values[i] = -1000000;
142 	fcc1.paint.values[i] = 1000000;
143     }
144     pcs->type->restrict_color(&fcc0, pcs);
145     pcs->type->restrict_color(&fcc1, pcs);
146     for (i = 0; i < pfs->num_components; i++)
147 	pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
148     pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
149     pfs->maybe_self_intersecting = true;
150     pfs->monotonic_color = (pfs->Function == NULL);
151     pfs->linear_color = false;
152     pfs->inside = false;
153     pfs->n_color_args = 1;
154     pfs->fixed_flat = float2fixed(pfs->pis->flatness);
155     pfs->smoothness = pfs->pis->smoothness;
156 #   if LAZY_WEDGES
157 	code = wedge_vertex_list_elem_buffer_alloc(pfs);
158 	if (code < 0)
159 	    return code;
160 #   endif
161     pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
162 return 0;
163 }
164 
165 void
term_patch_fill_state(patch_fill_state_t * pfs)166 term_patch_fill_state(patch_fill_state_t *pfs)
167 {
168 #   if LAZY_WEDGES
169 	wedge_vertex_list_elem_buffer_free(pfs);
170 #   endif
171 }
172 
173 /* Resolve a patch color using the Function if necessary. */
174 inline private void
patch_resolve_color_inline(patch_color_t * ppcr,const patch_fill_state_t * pfs)175 patch_resolve_color_inline(patch_color_t * ppcr, const patch_fill_state_t *pfs)
176 {
177     if (pfs->Function) {
178 	const gs_color_space *pcs = pfs->direct_space;
179 
180 	gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
181 	pcs->type->restrict_color(&ppcr->cc, pcs);
182     }
183 }
184 
185 void
patch_resolve_color(patch_color_t * ppcr,const patch_fill_state_t * pfs)186 patch_resolve_color(patch_color_t * ppcr, const patch_fill_state_t *pfs)
187 {
188     patch_resolve_color_inline(ppcr, pfs);
189 }
190 
191 
192 /*
193  * Calculate the interpolated color at a given point.
194  * Note that we must do this twice for bilinear interpolation.
195  * We use the name ppcr rather than ppc because an Apple compiler defines
196  * ppc when compiling on PowerPC systems (!).
197  */
198 private void
patch_interpolate_color(patch_color_t * ppcr,const patch_color_t * ppc0,const patch_color_t * ppc1,const patch_fill_state_t * pfs,floatp t)199 patch_interpolate_color(patch_color_t * ppcr, const patch_color_t * ppc0,
200        const patch_color_t * ppc1, const patch_fill_state_t *pfs, floatp t)
201 {
202     /* The old code gives -IND on Intel. */
203     if (pfs->Function) {
204 	ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
205 	ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
206 	patch_resolve_color_inline(ppcr, pfs);
207     } else {
208 	int ci;
209 
210 	for (ci = pfs->num_components - 1; ci >= 0; --ci)
211 	    ppcr->cc.paint.values[ci] =
212 		ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
213     }
214 }
215 
216 /* ================ Specific shadings ================ */
217 
218 /*
219  * The curves are stored in a clockwise or counter-clockwise order that maps
220  * to the patch definition in a non-intuitive way.  The documentation
221  * (pp. 277-281 of the PostScript Language Reference Manual, Third Edition)
222  * says that the curves are in the order D1, C2, D2, C1.
223  */
224 /* The starting points of the curves: */
225 #define D1START 0
226 #define C2START 1
227 #define D2START 3
228 #define C1START 0
229 /* The control points of the curves (x means reversed order): */
230 #define D1CTRL 0
231 #define C2CTRL 1
232 #define D2XCTRL 2
233 #define C1XCTRL 3
234 /* The end points of the curves: */
235 #define D1END 1
236 #define C2END 2
237 #define D2END 2
238 #define C1END 3
239 
240 /* ---------------- Common code ---------------- */
241 
242 /* Evaluate a curve at a given point. */
243 private void
curve_eval(gs_fixed_point * pt,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2,const gs_fixed_point * p3,floatp t)244 curve_eval(gs_fixed_point * pt, const gs_fixed_point * p0,
245 	   const gs_fixed_point * p1, const gs_fixed_point * p2,
246 	   const gs_fixed_point * p3, floatp t)
247 {
248     fixed a, b, c, d;
249     fixed t01, t12;
250 
251     d = p0->x;
252     curve_points_to_coefficients(d, p1->x, p2->x, p3->x,
253 				 a, b, c, t01, t12);
254     pt->x = (fixed) (((a * t + b) * t + c) * t + d);
255     d = p0->y;
256     curve_points_to_coefficients(d, p1->y, p2->y, p3->y,
257 				 a, b, c, t01, t12);
258     pt->y = (fixed) (((a * t + b) * t + c) * t + d);
259     if_debug3('2', "[2]t=%g => (%g,%g)\n", t, fixed2float(pt->x),
260 	      fixed2float(pt->y));
261 }
262 
263 /* ---------------- Coons patch shading ---------------- */
264 
265 /* Calculate the device-space coordinate corresponding to (u,v). */
266 private void
Cp_transform(gs_fixed_point * pt,const patch_curve_t curve[4],const gs_fixed_point ignore_interior[4],floatp u,floatp v)267 Cp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
268 	     const gs_fixed_point ignore_interior[4], floatp u, floatp v)
269 {
270     double co_u = 1.0 - u, co_v = 1.0 - v;
271     gs_fixed_point c1u, d1v, c2u, d2v;
272 
273     curve_eval(&c1u, &curve[C1START].vertex.p,
274 	       &curve[C1XCTRL].control[1], &curve[C1XCTRL].control[0],
275 	       &curve[C1END].vertex.p, u);
276     curve_eval(&d1v, &curve[D1START].vertex.p,
277 	       &curve[D1CTRL].control[0], &curve[D1CTRL].control[1],
278 	       &curve[D1END].vertex.p, v);
279     curve_eval(&c2u, &curve[C2START].vertex.p,
280 	       &curve[C2CTRL].control[0], &curve[C2CTRL].control[1],
281 	       &curve[C2END].vertex.p, u);
282     curve_eval(&d2v, &curve[D2START].vertex.p,
283 	       &curve[D2XCTRL].control[1], &curve[D2XCTRL].control[0],
284 	       &curve[D2END].vertex.p, v);
285 #define COMPUTE_COORD(xy)\
286     pt->xy = (fixed)\
287 	((co_v * c1u.xy + v * c2u.xy) + (co_u * d1v.xy + u * d2v.xy) -\
288 	 (co_v * (co_u * curve[C1START].vertex.p.xy +\
289 		  u * curve[C1END].vertex.p.xy) +\
290 	  v * (co_u * curve[C2START].vertex.p.xy +\
291 	       u * curve[C2END].vertex.p.xy)))
292     COMPUTE_COORD(x);
293     COMPUTE_COORD(y);
294 #undef COMPUTE_COORD
295     if_debug4('2', "[2](u=%g,v=%g) => (%g,%g)\n",
296 	      u, v, fixed2float(pt->x), fixed2float(pt->y));
297 }
298 
299 int
gs_shading_Cp_fill_rectangle(const gs_shading_t * psh0,const gs_rect * rect,const gs_fixed_rect * rect_clip,gx_device * dev,gs_imager_state * pis)300 gs_shading_Cp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
301 			     const gs_fixed_rect * rect_clip,
302 			     gx_device * dev, gs_imager_state * pis)
303 {
304     const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
305     patch_fill_state_t state;
306     shade_coord_stream_t cs;
307     patch_curve_t curve[4];
308     int code;
309 
310     code = mesh_init_fill_state((mesh_fill_state_t *) &state,
311 			 (const gs_shading_mesh_t *)psh0, rect_clip, dev, pis);
312     if (code < 0)
313 	return code;
314     state.Function = psh->params.Function;
315     code = init_patch_fill_state(&state);
316     if(code < 0)
317 	return code;
318     if (VD_TRACE_TENSOR_PATCH && vd_allowed('s')) {
319 	vd_get_dc('s');
320 	vd_set_shift(0, 0);
321 	vd_set_scale(0.01);
322 	vd_set_origin(0, 0);
323 	/* vd_erase(RGB(192, 192, 192)); */
324     }
325 
326     curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
327     shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pis);
328     while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
329 				    curve, NULL)) == 0 &&
330 	   (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
331 	) {
332 	DO_NOTHING;
333     }
334     if (VD_TRACE_TENSOR_PATCH && vd_allowed('s'))
335 	vd_release_dc;
336     term_patch_fill_state(&state);
337     return min(code, 0);
338 }
339 
340 /* ---------------- Tensor product patch shading ---------------- */
341 
342 /* Calculate the device-space coordinate corresponding to (u,v). */
343 private void
Tpp_transform(gs_fixed_point * pt,const patch_curve_t curve[4],const gs_fixed_point interior[4],floatp u,floatp v)344 Tpp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
345 	      const gs_fixed_point interior[4], floatp u, floatp v)
346 {
347     double Bu[4], Bv[4];
348     gs_fixed_point pts[4][4];
349     int i, j;
350     double x = 0, y = 0;
351 
352     /* Compute the Bernstein polynomials of u and v. */
353     {
354 	double u2 = u * u, co_u = 1.0 - u, co_u2 = co_u * co_u;
355 	double v2 = v * v, co_v = 1.0 - v, co_v2 = co_v * co_v;
356 
357 	Bu[0] = co_u * co_u2, Bu[1] = 3 * u * co_u2,
358 	    Bu[2] = 3 * u2 * co_u, Bu[3] = u * u2;
359 	Bv[0] = co_v * co_v2, Bv[1] = 3 * v * co_v2,
360 	    Bv[2] = 3 * v2 * co_v, Bv[3] = v * v2;
361     }
362 
363     /* Arrange the points into an indexable order. */
364     pts[0][0] = curve[0].vertex.p;
365     pts[0][1] = curve[0].control[0];
366     pts[0][2] = curve[0].control[1];
367     pts[0][3] = curve[1].vertex.p;
368     pts[1][3] = curve[1].control[0];
369     pts[2][3] = curve[1].control[1];
370     pts[3][3] = curve[2].vertex.p;
371     pts[3][2] = curve[2].control[0];
372     pts[3][1] = curve[2].control[1];
373     pts[3][0] = curve[3].vertex.p;
374     pts[2][0] = curve[3].control[0];
375     pts[1][0] = curve[3].control[1];
376     pts[1][1] = interior[0];
377     pts[2][1] = interior[1];
378     pts[2][2] = interior[2];
379     pts[1][2] = interior[3];
380 
381     /* Now compute the actual point. */
382     for (i = 0; i < 4; ++i)
383 	for (j = 0; j < 4; ++j) {
384 	    double coeff = Bu[i] * Bv[j];
385 
386 	    x += pts[i][j].x * coeff, y += pts[i][j].y * coeff;
387 	}
388     pt->x = (fixed)x, pt->y = (fixed)y;
389 }
390 
391 int
gs_shading_Tpp_fill_rectangle(const gs_shading_t * psh0,const gs_rect * rect,const gs_fixed_rect * rect_clip,gx_device * dev,gs_imager_state * pis)392 gs_shading_Tpp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
393 			     const gs_fixed_rect * rect_clip,
394 			      gx_device * dev, gs_imager_state * pis)
395 {
396     const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
397     patch_fill_state_t state;
398     shade_coord_stream_t cs;
399     patch_curve_t curve[4];
400     gs_fixed_point interior[4];
401     int code;
402 
403     code = mesh_init_fill_state((mesh_fill_state_t *) & state,
404 			 (const gs_shading_mesh_t *)psh0, rect_clip, dev, pis);
405     if (code < 0)
406 	return code;
407     state.Function = psh->params.Function;
408     code = init_patch_fill_state(&state);
409     if(code < 0)
410 	return code;
411     if (VD_TRACE_TENSOR_PATCH && vd_allowed('s')) {
412 	vd_get_dc('s');
413 	vd_set_shift(0, 0);
414 	vd_set_scale(0.01);
415 	vd_set_origin(0, 0);
416 	/* vd_erase(RGB(192, 192, 192)); */
417     }
418     curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
419     shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pis);
420     while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
421 				    curve, interior)) == 0) {
422 	/*
423 	 * The order of points appears to be consistent with that for Coons
424 	 * patches, which is different from that documented in Red Book 3.
425 	 */
426 	gs_fixed_point swapped_interior[4];
427 
428 	swapped_interior[0] = interior[0];
429 	swapped_interior[1] = interior[3];
430 	swapped_interior[2] = interior[2];
431 	swapped_interior[3] = interior[1];
432 	code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
433 	if (code < 0)
434 	    break;
435     }
436     term_patch_fill_state(&state);
437     if (VD_TRACE_TENSOR_PATCH && vd_allowed('s'))
438 	vd_release_dc;
439     return min(code, 0);
440 }
441 
442 /*
443     This algorithm performs a decomposition of the shading area
444     into a set of constant color trapezoids, some of which
445     may use the transpozed coordinate system.
446 
447     The target device assumes semi-open intrvals by X to be painted
448     (See PLRM3, 7.5. Scan conversion details), i.e.
449     it doesn't paint pixels which falls exactly to the right side.
450     Note that with raster devices the algorithm doesn't paint pixels,
451     whigh are partially covered by the shading area,
452     but which's centers are outside the area.
453 
454     Pixels inside a monotonic part of the shading area are painted
455     at once, but some exceptions may happen :
456 
457         - While flattening boundaries of a subpatch,
458 	to keep the plane coverage contiguity we insert wedges
459 	between neighbor subpatches, which use a different
460 	flattening factor. With non-monotonic curves
461 	those wedges may overlap or be self-overlapping, and a pixel
462 	is painted so many times as many wedges cover it. Fortunately
463 	the area of most wedges is zero or extremily small.
464 
465 	- Since quazi-horizontal wedges may have a non-constant color,
466 	they can't decompose into constant color trapezoids with
467 	keeping the coverage contiguity. To represent them we
468 	apply the XY plane transposition. But with the transposition
469 	a semiopen interval can met a non-transposed one,
470 	so that some lines are not covered. Therefore we emulate
471 	closed intervals with expanding the transposed trapesoids in
472 	fixed_epsilon, and pixels at that boundary may be painted twice.
473 
474 	- A boundary of a monotonic area can't compute in XY
475 	preciselly due to high order polynomial equations.
476 	Therefore the subdivision near the monotonity boundary
477 	may paint some pixels twice within same monotonic part.
478 
479     Non-monotonic areas slow down due to a tinny subdivision required.
480 
481     The target device may be either raster or vector.
482     Vector devices should preciselly pass trapezoids to the output.
483     Note that ends of sides of a trapesoid are not necessary
484     the trapezoid's vertices. Converting this thing into
485     an exact quadrangle may cause an arithmetic error,
486     and the rounding must be done so that the coverage
487     contiguity is not lost.
488 
489     When a device passes a trapezoid to it's output,
490     a regular rounding would keep the coverage contiguity,
491     except for the transposed trapesoids.
492     If a transposed trapezoid is being transposed back,
493     it doesn't become a canonic trapezoid, and a further
494     decomposition is neccessary. But rounding errors here
495     would break the coverage contiguity at boundaries
496     of the tansposed part of the area.
497 
498     Devices, which have no transposed trapezoids and represent
499     trapezoids only with 8 coordinates of vertices of the quadrangle
500     (pclwrite is an example) may apply the backward transposition,
501     and a clipping instead the further decomposition.
502     Note that many clip regions may appear for all wedges.
503     Note that in some cases the adjustment of the right side to be
504     withdrown before the backward transposition.
505  */
506  /* We believe that a multiplication of 32-bit integers with a
507     64-bit result is performed by modern platforms performs
508     in hardware level. Therefore we widely use it here,
509     but we minimize the usage of a multiplication of longer integers.
510 
511     Unfortunately we do need a multiplication of long integers
512     in intersection_of_small_bars, because solving the linear system
513     requires tripple multiples of 'fixed'. Therefore we retain
514     of it's usage in the algorithm of the main branch.
515     Configuration macro QUADRANGLES prevents it.
516   */
517 
518 typedef struct {
519     gs_fixed_point pole[4][4]; /* [v][u] */
520     patch_color_t c[2][2];     /* [v][u] */
521 } tensor_patch;
522 
523 typedef struct {
524     const shading_vertex_t *p[2][2]; /* [v][u] */
525     wedge_vertex_list_t *l0001, *l0111, *l1110, *l1000;
526 } quadrangle_patch;
527 
528 typedef enum {
529     interpatch_padding = 1, /* A Padding between patches for poorly designed documents. */
530     inpatch_wedge = 2  /* Wedges while a patch decomposition. */
531 } wedge_type_t;
532 
533 int
wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t * pfs)534 wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t *pfs)
535 {
536     const int max_level = LAZY_WEDGES_MAX_LEVEL;
537     gs_memory_t *memory = pfs->pis->memory;
538 
539     pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level);
540     pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
541 	    sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
542 	    "alloc_wedge_vertex_list_elem_buffer");
543     if (pfs->wedge_vertex_list_elem_buffer == NULL)
544 	return_error(gs_error_VMerror);
545     pfs->free_wedge_vertex = NULL;
546     pfs->wedge_vertex_list_elem_count = 0;
547     return 0;
548 }
549 
550 void
wedge_vertex_list_elem_buffer_free(patch_fill_state_t * pfs)551 wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
552 {
553     gs_memory_t *memory = pfs->pis->memory;
554 
555     gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
556 		"wedge_vertex_list_elem_buffer_free");
557     pfs->wedge_vertex_list_elem_buffer = NULL;
558     pfs->free_wedge_vertex = NULL;
559 }
560 
561 private inline wedge_vertex_list_elem_t *
wedge_vertex_list_elem_reserve(patch_fill_state_t * pfs)562 wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
563 {
564     wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
565 
566     if (e != NULL) {
567 	pfs->free_wedge_vertex = e->next;
568 	return e;
569     }
570     if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
571 	return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
572     return NULL;
573 }
574 
575 private inline void
wedge_vertex_list_elem_release(patch_fill_state_t * pfs,wedge_vertex_list_elem_t * e)576 wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
577 {
578     e->next = pfs->free_wedge_vertex;
579     pfs->free_wedge_vertex = e;
580 }
581 
582 private inline void
release_triangle_wedge_vertex_list_elem(patch_fill_state_t * pfs,wedge_vertex_list_elem_t * beg,wedge_vertex_list_elem_t * end)583 release_triangle_wedge_vertex_list_elem(patch_fill_state_t *pfs,
584     wedge_vertex_list_elem_t *beg, wedge_vertex_list_elem_t *end)
585 {
586     wedge_vertex_list_elem_t *e = beg->next;
587 
588     assert(beg->next->next == end);
589     beg->next = end;
590     end->prev = beg;
591     wedge_vertex_list_elem_release(pfs, e);
592 }
593 
594 private inline void
release_wedge_vertex_list_interval(patch_fill_state_t * pfs,wedge_vertex_list_elem_t * beg,wedge_vertex_list_elem_t * end)595 release_wedge_vertex_list_interval(patch_fill_state_t *pfs,
596     wedge_vertex_list_elem_t *beg, wedge_vertex_list_elem_t *end)
597 {
598     wedge_vertex_list_elem_t *e = beg->next, *ee;
599 
600     beg->next = end;
601     end->prev = beg;
602     for (; e != end; e = ee) {
603 	ee = e->next;
604 	wedge_vertex_list_elem_release(pfs, e);
605     }
606 }
607 
608 private inline void
release_wedge_vertex_list(patch_fill_state_t * pfs,wedge_vertex_list_t * ll,int n)609 release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
610 {
611     int i;
612 
613     for (i = 0; i < n; i++) {
614 	wedge_vertex_list_t *l = ll + i;
615 
616 	if (l->beg != NULL) {
617 	    assert(l->end != NULL);
618 	    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
619 	    wedge_vertex_list_elem_release(pfs, l->beg);
620 	    wedge_vertex_list_elem_release(pfs, l->end);
621 	    l->beg = l->end = NULL;
622 	} else
623 	    assert(l->end == NULL);
624     }
625 }
626 
627 private inline wedge_vertex_list_elem_t *
wedge_vertex_list_find(wedge_vertex_list_elem_t * beg,const wedge_vertex_list_elem_t * end,int level)628 wedge_vertex_list_find(wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
629 	    int level)
630 {
631     wedge_vertex_list_elem_t *e = beg;
632 
633     assert(beg != NULL && end != NULL);
634     for (; e != end; e = e->next)
635 	if (e->level == level)
636 	    return e;
637     return NULL;
638 }
639 
640 private inline void
init_wedge_vertex_list(wedge_vertex_list_t * l,int n)641 init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
642 {
643     memset(l, 0, sizeof(*l) * n);
644 }
645 
646 private void
draw_patch(const tensor_patch * p,bool interior,ulong rgbcolor)647 draw_patch(const tensor_patch *p, bool interior, ulong rgbcolor)
648 {
649 #ifdef DEBUG
650 #if 0 /* Disabled for a better view with a specific purpose.
651 	 Feel free to enable fo needed. */
652     int i, step = (interior ? 1 : 3);
653 
654     for (i = 0; i < 4; i += step) {
655 	vd_curve(p->pole[i][0].x, p->pole[i][0].y,
656 		 p->pole[i][1].x, p->pole[i][1].y,
657 		 p->pole[i][2].x, p->pole[i][2].y,
658 		 p->pole[i][3].x, p->pole[i][3].y,
659 		 0, rgbcolor);
660 	vd_curve(p->pole[0][i].x, p->pole[0][i].y,
661 		 p->pole[1][i].x, p->pole[1][i].y,
662 		 p->pole[2][i].x, p->pole[2][i].y,
663 		 p->pole[3][i].x, p->pole[3][i].y,
664 		 0, rgbcolor);
665     }
666 #endif
667 #endif
668 }
669 
670 private inline void
draw_triangle(const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2,ulong rgbcolor)671 draw_triangle(const gs_fixed_point *p0, const gs_fixed_point *p1,
672 		const gs_fixed_point *p2, ulong rgbcolor)
673 {
674 #ifdef DEBUG
675     if (!vd_enabled)
676 	return;
677     vd_quad(p0->x, p0->y, p0->x, p0->y, p1->x, p1->y, p2->x, p2->y, 0, rgbcolor);
678 #endif
679 }
680 
681 private inline void
draw_quadrangle(const quadrangle_patch * p,ulong rgbcolor)682 draw_quadrangle(const quadrangle_patch *p, ulong rgbcolor)
683 {
684 #ifdef DEBUG
685 	vd_quad(p->p[0][0]->p.x, p->p[0][0]->p.y,
686 	    p->p[0][1]->p.x, p->p[0][1]->p.y,
687 	    p->p[1][1]->p.x, p->p[1][1]->p.y,
688 	    p->p[1][0]->p.x, p->p[1][0]->p.y,
689 	    0, rgbcolor);
690 #endif
691 }
692 
693 private inline int
curve_samples(patch_fill_state_t * pfs,const gs_fixed_point * pole,int pole_step,fixed fixed_flat)694 curve_samples(patch_fill_state_t *pfs,
695 		const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
696 {
697     curve_segment s;
698     int k;
699 
700     s.p1.x = pole[pole_step].x;
701     s.p1.y = pole[pole_step].y;
702     s.p2.x = pole[pole_step * 2].x;
703     s.p2.y = pole[pole_step * 2].y;
704     s.pt.x = pole[pole_step * 3].x;
705     s.pt.y = pole[pole_step * 3].y;
706     k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
707     {
708 #	if LAZY_WEDGES || QUADRANGLES
709 	    int k1;
710 	    fixed L = any_abs(pole[1].x - pole[0].x) + any_abs(pole[1].y - pole[0].y) +
711 		      any_abs(pole[2].x - pole[1].x) + any_abs(pole[2].y - pole[1].y) +
712 		      any_abs(pole[3].x - pole[2].x) + any_abs(pole[3].y - pole[2].y);
713 #	endif
714 
715 #	if LAZY_WEDGES
716 	    /* Restrict lengths for a reasonable memory consumption : */
717 	    k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
718 	    k = max(k, k1);
719 #	endif
720 #	if QUADRANGLES
721 	    /* Restrict lengths for intersection_of_small_bars : */
722 	    k = max(k, ilog2(L) - ilog2(pfs->max_small_coord));
723 #	endif
724     }
725     return 1 << k;
726 }
727 
728 private bool
intersection_of_small_bars(const gs_fixed_point q[4],int i0,int i1,int i2,int i3,fixed * ry,fixed * ey)729 intersection_of_small_bars(const gs_fixed_point q[4], int i0, int i1, int i2, int i3, fixed *ry, fixed *ey)
730 {
731     /* This function is only used with QUADRANGLES. */
732     fixed dx1 = q[i1].x - q[i0].x, dy1 = q[i1].y - q[i0].y;
733     fixed dx2 = q[i2].x - q[i0].x, dy2 = q[i2].y - q[i0].y;
734     fixed dx3 = q[i3].x - q[i0].x, dy3 = q[i3].y - q[i0].y;
735     int64_t vp2a, vp2b, vp3a, vp3b;
736     int s2, s3;
737 
738     if (dx1 == 0 && dy1 == 0)
739 	return false; /* Zero length bars are out of interest. */
740     if (dx2 == 0 && dy2 == 0)
741 	return false; /* Contacting ends are out of interest. */
742     if (dx3 == 0 && dy3 == 0)
743 	return false; /* Contacting ends are out of interest. */
744     if (dx2 == dx1 && dy2 == dy1)
745 	return false; /* Contacting ends are out of interest. */
746     if (dx3 == dx1 && dy3 == dy1)
747 	return false; /* Contacting ends are out of interest. */
748     if (dx2 == dx3 && dy2 == dy3)
749 	return false; /* Zero length bars are out of interest. */
750     vp2a = (int64_t)dx1 * dy2;
751     vp2b = (int64_t)dy1 * dx2;
752     /* vp2 = vp2a - vp2b; It can overflow int64_t, but we only need the sign. */
753     if (vp2a > vp2b)
754 	s2 = 1;
755     else if (vp2a < vp2b)
756 	s2 = -1;
757     else
758 	s2 = 0;
759     vp3a = (int64_t)dx1 * dy3;
760     vp3b = (int64_t)dy1 * dx3;
761     /* vp3 = vp3a - vp3b; It can overflow int64_t, but we only need the sign. */
762     if (vp3a > vp3b)
763 	s3 = 1;
764     else if (vp3a < vp3b)
765 	s3 = -1;
766     else
767 	s3 = 0;
768     if (s2 == 0) {
769 	if (s3 == 0)
770 	    return false; /* Collinear bars - out of interest. */
771 	if (0 <= dx2 && dx2 <= dx1 && 0 <= dy2 && dy2 <= dy1) {
772 	    /* The start of the bar 2 is in the bar 1. */
773 	    *ry = q[i2].y;
774 	    *ey = 0;
775 	    return true;
776 	}
777     } else if (s3 == 0) {
778 	if (0 <= dx3 && dx3 <= dx1 && 0 <= dy3 && dy3 <= dy1) {
779 	    /* The end of the bar 2 is in the bar 1. */
780 	    *ry = q[i3].y;
781 	    *ey = 0;
782 	    return true;
783 	}
784     } else if (s2 * s3 < 0) {
785 	/* The intersection definitely exists, so the determinant isn't zero.  */
786 	fixed d23x = dx3 - dx2, d23y = dy3 - dy2;
787 	int64_t det = (int64_t)dx1 * d23y - (int64_t)dy1 * d23x;
788 	int64_t mul = (int64_t)dx2 * d23y - (int64_t)dy2 * d23x;
789 #	define USE_DOUBLE 0
790 #	define USE_INT64_T (1 || !USE_DOUBLE)
791 #	if USE_DOUBLE
792 	{
793 	    /* Assuming big bars. Not a good thing due to 'double'.  */
794 	    /* The determinant can't compute in double due to
795 	       possible loss of all significant bits when subtracting the
796 	       trucnated prodicts. But after we subtract in int64_t,
797 	       it converts to 'double' with a reasonable truncation. */
798 	    double dy = dy1 * (double)mul / (double)det;
799 	    fixed iy;
800 
801 	    if (dy1 > 0 && dy >= dy1)
802 		return false; /* Outside the bar 1. */
803 	    if (dy1 < 0 && dy <= dy1)
804 		return false; /* Outside the bar 1. */
805 	    if (dy2 < dy3) {
806 		if (dy <= dy2 || dy >= dy3)
807 		    return false; /* Outside the bar 2. */
808 	    } else {
809 		if (dy >= dy2 || dy <= dy3)
810 		    return false; /* Outside the bar 2. */
811 	    }
812 	    iy = (int)floor(dy);
813 	    *ry = q[i0].y + iy;
814 	    *ey = (dy > iy ? 1 : 0);
815 	}
816 #	endif
817 #	if USE_INT64_T
818 	{
819 	    /* Assuming small bars : cubes of coordinates must fit into int64_t.
820 	       curve_samples must provide that.  */
821 	    int64_t num = dy1 * mul, iiy;
822 	    fixed iy;
823 	    fixed pry, pey;
824 
825 	    {	/* Likely when called form wedge_trap_decompose or constant_color_quadrangle,
826 		   we always have det > 0 && num >= 0, but we check here for a safety reason. */
827 		if (det < 0)
828 		    {num = -num; det = -det;}
829 		if(num >= 0)
830 			iiy = num / det;
831 		else
832 			iiy = (num - det + 1) / det;
833 		iy = (fixed)iiy;
834 		if (iy != iiy) {
835 		    /* If it is inside the bars, it must fit into fixed. */
836 		    return false;
837 		}
838 	    }
839 	    if (dy1 > 0 && iy >= dy1)
840 		return false; /* Outside the bar 1. */
841 	    if (dy1 < 0 && iy <= dy1)
842 		return false; /* Outside the bar 1. */
843 	    if (dy2 < dy3) {
844 		if (iy <= dy2 || iy >= dy3)
845 		    return false; /* Outside the bar 2. */
846 	    } else {
847 		if (iy >= dy2 || iy <= dy3)
848 		    return false; /* Outside the bar 2. */
849 	    }
850 	    pry = q[i0].y + (fixed)iy;
851 	    pey = (iy * det < num ? 1 : 0);
852 #	    if USE_DOUBLE && USE_INT64_T
853 		assert(*ry == pry);
854 		assert(*ey == pey);
855 #	    endif
856 	    *ry = pry;
857 	    *ey = pey;
858 	}
859 #	endif
860 	return true;
861     }
862     return false;
863 }
864 
865 private inline void
adjust_swapped_boundary(fixed * b,bool swap_axes)866 adjust_swapped_boundary(fixed *b, bool swap_axes)
867 {
868     if (swap_axes) {
869 	/*  Sinse the rasterizer algorithm assumes semi-open interval
870 	    when computing pixel coverage, we should expand
871 	    the right side of the area. Otherwise a dropout can happen :
872 	    if the left neighbour is painted with !swap_axes,
873 	    the left side of this area appears to be the left side
874 	    of the neighbour area, and the side is not included
875 	    into both areas.
876 	 */
877 	*b += fixed_epsilon;
878     }
879 }
880 
881 private inline void
make_trapezoid(const gs_fixed_point q[4],int vi0,int vi1,int vi2,int vi3,fixed ybot,fixed ytop,bool swap_axes,bool orient,gs_fixed_edge * le,gs_fixed_edge * re)882 make_trapezoid(const gs_fixed_point q[4],
883 	int vi0, int vi1, int vi2, int vi3, fixed ybot, fixed ytop,
884 	bool swap_axes, bool orient, gs_fixed_edge *le, gs_fixed_edge *re)
885 {
886     if (!orient) {
887 	le->start = q[vi0];
888 	le->end = q[vi1];
889 	re->start = q[vi2];
890 	re->end = q[vi3];
891     } else {
892 	le->start = q[vi2];
893 	le->end = q[vi3];
894 	re->start = q[vi0];
895 	re->end = q[vi1];
896     }
897     adjust_swapped_boundary(&re->start.x, swap_axes);
898     adjust_swapped_boundary(&re->end.x, swap_axes);
899 }
900 
901 private inline int
gx_shade_trapezoid(patch_fill_state_t * pfs,const gs_fixed_point q[4],int vi0,int vi1,int vi2,int vi3,fixed ybot0,fixed ytop0,bool swap_axes,const gx_device_color * pdevc,bool orient)902 gx_shade_trapezoid(patch_fill_state_t *pfs, const gs_fixed_point q[4],
903 	int vi0, int vi1, int vi2, int vi3, fixed ybot0, fixed ytop0,
904 	bool swap_axes, const gx_device_color *pdevc, bool orient)
905 {
906     gs_fixed_edge le, re;
907     int code;
908     fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
909     fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
910     vd_save;
911 
912     if (ybot > ytop)
913 	return 0;
914 #   if NOFILL_TEST
915 	if (dbg_nofill)
916 	    return 0;
917 #   endif
918     make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
919     if (!VD_TRACE_DOWN)
920 	vd_disable;
921     code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
922 	    &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pis->log_op);
923     vd_restore;
924     return code;
925 }
926 
927 private int
patch_color_to_device_color(const patch_fill_state_t * pfs,const patch_color_t * c,gx_device_color * pdevc)928 patch_color_to_device_color(const patch_fill_state_t *pfs, const patch_color_t *c, gx_device_color *pdevc)
929 {
930     /* A code fragment copied from mesh_fill_triangle. */
931     gs_client_color fcc;
932     const gs_color_space *pcs = pfs->direct_space;
933 
934     memcpy(fcc.paint.values, c->cc.paint.values,
935 		sizeof(fcc.paint.values[0]) * pfs->num_components);
936     return pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pis,
937 			      pfs->dev, gs_color_select_texture);
938 }
939 
940 private inline double
color_span(const patch_fill_state_t * pfs,const patch_color_t * c0,const patch_color_t * c1)941 color_span(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
942 {
943     int n = pfs->num_components, i;
944     double m;
945 
946     /* Dont want to copy colors, which are big things. */
947     m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
948     for (i = 1; i < n; i++)
949 	m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
950     return m;
951 }
952 
953 private inline void
color_diff(const patch_fill_state_t * pfs,const patch_color_t * c0,const patch_color_t * c1,patch_color_t * d)954 color_diff(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1, patch_color_t *d)
955 {
956     int n = pfs->num_components, i;
957 
958     for (i = 0; i < n; i++)
959 	d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
960 }
961 
962 private inline double
color_norm(const patch_fill_state_t * pfs,const patch_color_t * c)963 color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
964 {
965     int n = pfs->num_components, i;
966     double m;
967 
968     m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
969     for (i = 1; i < n; i++)
970 	m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
971     return m;
972 }
973 
974 private inline int
isnt_color_monotonic(const patch_fill_state_t * pfs,const patch_color_t * c0,const patch_color_t * c1)975 isnt_color_monotonic(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
976 {   /* checks whether the color is monotonic in the n-dimensional interval,
977        where n is the number of parameters in c0->t, c1->t.
978        returns : 0 = monotonic,
979        bit 0 = not or don't know by t0,
980        bit 1 = not or don't know by t1,
981        <0 = error. */
982     /* When pfs->Function is not set, the color is monotonic.
983        In this case do not call this function because
984        it doesn't check whether pfs->Function is set.
985        Actually pfs->monotonic_color prevents that.
986      */
987     uint mask;
988     int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
989 
990     if (code >= 0)
991 	return mask;
992     return code;
993 }
994 
995 private inline bool
covers_pixel_centers(fixed ybot,fixed ytop)996 covers_pixel_centers(fixed ybot, fixed ytop)
997 {
998     return fixed_pixround(ybot) < fixed_pixround(ytop);
999 }
1000 
1001 private inline int
constant_color_trapezoid(patch_fill_state_t * pfs,gs_fixed_edge * le,gs_fixed_edge * re,fixed ybot,fixed ytop,bool swap_axes,const patch_color_t * c)1002 constant_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1003 	fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c)
1004 {
1005     patch_color_t c1 = *c;
1006     gx_device_color dc;
1007     int code;
1008     vd_save;
1009 
1010 #   if NOFILL_TEST
1011 	/* if (dbg_nofill)
1012 		return 0; */
1013 #   endif
1014     code = patch_color_to_device_color(pfs, &c1, &dc);
1015     if (code < 0)
1016 	return code;
1017     if (!VD_TRACE_DOWN)
1018 	vd_disable;
1019     code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1020 	le, re, ybot, ytop, swap_axes, &dc, pfs->pis->log_op);
1021     vd_restore;
1022     return code;
1023 }
1024 
1025 private inline void
dc2fc(const patch_fill_state_t * pfs,gx_color_index c,frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS])1026 dc2fc(const patch_fill_state_t *pfs, gx_color_index c,
1027 	    frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS])
1028 {
1029     int j;
1030     const gx_device_color_info *cinfo = &pfs->dev->color_info;
1031 
1032     for (j = 0; j < cinfo->num_components; j++) {
1033 	    int shift = cinfo->comp_shift[j];
1034 	    int bits = cinfo->comp_bits[j];
1035 
1036 	    fc[j] = ((c >> shift) & ((1 << bits) - 1)) << (sizeof(frac31) * 8 - 1 - bits);
1037     }
1038 }
1039 
1040 private inline float
function_linearity(const patch_fill_state_t * pfs,const patch_color_t * c0,const patch_color_t * c1)1041 function_linearity(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1042 {
1043     float smoothness = max(pfs->smoothness, 1.0 / min_linear_grades), s = 0;
1044     /* Restrict the smoothness with 1/min_linear_grades, because cs_is_linear
1045        can't provide a better precision due to the color
1046        representation with integers.
1047      */
1048 
1049     if (pfs->Function != NULL) {
1050 	patch_color_t c;
1051 	const float q[2] = {(float)0.3, (float)0.7};
1052 	int i, j;
1053 
1054 	for (j = 0; j < count_of(q); j++) {
1055 	    c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1056 	    c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1057 	    patch_resolve_color_inline(&c, pfs);
1058 	    for (i = 0; i < pfs->num_components; i++) {
1059 		float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1060 		float d = v - c.cc.paint.values[i];
1061 		float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1062 
1063 		if (s1 > smoothness)
1064 		    return s1;
1065 		if (s < s1)
1066 		    s = s1;
1067 	    }
1068 	}
1069     }
1070     return s;
1071 }
1072 
1073 private inline int
is_color_linear(const patch_fill_state_t * pfs,const patch_color_t * c0,const patch_color_t * c1)1074 is_color_linear(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1075 {   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1076     if (pfs->unlinear)
1077 	return 1; /* Disable this check. */
1078     else {
1079 	gs_direct_color_space *cs =
1080 		    (gs_direct_color_space *)pfs->direct_space; /* break 'const'. */
1081 	int code;
1082 	float smoothness = max(pfs->smoothness, 1.0 / min_linear_grades);
1083 	/* Restrict the smoothness with 1/min_linear_grades, because cs_is_linear
1084 	   can't provide a better precision due to the color
1085 	   representation with integers.
1086 	 */
1087 	float s = function_linearity(pfs, c0, c1);
1088 
1089 	if (s > smoothness)
1090 	    return 0;
1091 	code = cs_is_linear(cs, pfs->pis, pfs->dev,
1092 		&c0->cc, &c1->cc, NULL, NULL, smoothness - s);
1093 	if (code <= 0)
1094 	    return code;
1095 	return 1;
1096     }
1097 }
1098 
1099 private int
decompose_linear_color(patch_fill_state_t * pfs,gs_fixed_edge * le,gs_fixed_edge * re,fixed ybot,fixed ytop,bool swap_axes,const patch_color_t * c0,const patch_color_t * c1,int level)1100 decompose_linear_color(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1101 	fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0,
1102 	const patch_color_t *c1, int level)
1103 {
1104     /* Assuming a very narrow trapezoid - ignore the transversal color variation. */
1105     /* Assuming the XY span is restricted with curve_samples.
1106        It is important for intersection_of_small_bars to compute faster. */
1107     int code;
1108     patch_color_t c;
1109 
1110     if (level > 100)
1111 	return_error(gs_error_unregistered); /* Must not happen. */
1112     /* Use the recursive decomposition due to isnt_color_monotonic
1113        based on fn_is_monotonic_proc_t is_monotonic,
1114        which applies to intervals. */
1115     patch_interpolate_color(&c, c0, c1, pfs, 0.5);
1116     if (ytop - ybot < fixed_1 / 2) /* Prevent an infinite color decomposition. */
1117 	return constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, &c);
1118     else {
1119 	bool monotonic_color_save = pfs->monotonic_color;
1120 	bool linear_color_save = pfs->linear_color;
1121 
1122 	if (!pfs->monotonic_color) {
1123 	    code = isnt_color_monotonic(pfs, c0, c1);
1124 	    if (code < 0)
1125 		return code;
1126 	    if (!code)
1127 		pfs->monotonic_color = true;
1128 	}
1129 	if (pfs->monotonic_color && !pfs->linear_color) {
1130 	    code = is_color_linear(pfs, c0, c1);
1131 	    if (code < 0)
1132 		return code;
1133 	    if (code > 0)
1134 		pfs->linear_color =  true;
1135 	}
1136 	if (!pfs->unlinear && pfs->linear_color) {
1137 	    gx_device *pdev = pfs->dev;
1138 	    frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1139 	    gs_fill_attributes fa;
1140 	    gx_device_color dc[2];
1141 	    gs_fixed_rect clip;
1142 	    int code;
1143 
1144 	    clip = pfs->rect;
1145 	    if (swap_axes) {
1146 		fixed v;
1147 
1148 		v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1149 		v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1150 		/* Don't need adjust_swapped_boundary here. */
1151 	    }
1152 	    clip.p.y = max(clip.p.y, ybot);
1153 	    clip.q.y = min(clip.q.y, ytop);
1154 	    fa.clip = &clip;
1155 	    fa.ht = NULL;
1156 	    fa.swap_axes = swap_axes;
1157 	    fa.lop = 0;
1158 	    fa.ystart = ybot;
1159 	    fa.yend = ytop;
1160 	    code = patch_color_to_device_color(pfs, c0, &dc[0]);
1161 	    if (code < 0)
1162 		return code;
1163 	    if (dc[0].type == &gx_dc_type_data_pure) {
1164 		dc2fc(pfs, dc[0].colors.pure, fc[0]);
1165 		code = patch_color_to_device_color(pfs, c1, &dc[1]);
1166 		if (code < 0)
1167 		    return code;
1168 		dc2fc(pfs, dc[1].colors.pure, fc[1]);
1169 		code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1170 				&le->start, &le->end, &re->start, &re->end,
1171 				fc[0], fc[1], NULL, NULL);
1172 		if (code == 1) {
1173 		    pfs->monotonic_color = monotonic_color_save;
1174 		    pfs->linear_color = linear_color_save;
1175 		    return 0; /* The area is filled. */
1176 		}
1177 		if (code < 0)
1178 		    return code;
1179 		else /* code == 0, the device requested to decompose the area. */
1180 		    return_error(gs_error_unregistered); /* Must not happen. */
1181 	    }
1182 	}
1183 	if (!pfs->unlinear || !pfs->linear_color ||
1184 		color_span(pfs, c0, c1) > pfs->smoothness) {
1185 	    fixed y = (ybot + ytop) / 2;
1186 
1187 	    code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, &c, level + 1);
1188 	    if (code >= 0)
1189 		code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, &c, c1, level + 1);
1190 	} else
1191 	    code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, &c);
1192 	pfs->monotonic_color = monotonic_color_save;
1193 	pfs->linear_color = linear_color_save;
1194 	return code;
1195     }
1196 }
1197 
1198 private inline int
linear_color_trapezoid(patch_fill_state_t * pfs,gs_fixed_point q[4],int i0,int i1,int i2,int i3,fixed ybot,fixed ytop,bool swap_axes,const patch_color_t * c0,const patch_color_t * c1,bool orient)1199 linear_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_point q[4], int i0, int i1, int i2, int i3,
1200 		fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0, const patch_color_t *c1,
1201 		bool orient)
1202 {
1203     /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1204     gs_fixed_edge le, re;
1205 
1206     make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1207     return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1, 0);
1208 }
1209 
1210 private int
wedge_trap_decompose(patch_fill_state_t * pfs,gs_fixed_point q[4],fixed ybot,fixed ytop,const patch_color_t * c0,const patch_color_t * c1,bool swap_axes,bool self_intersecting)1211 wedge_trap_decompose(patch_fill_state_t *pfs, gs_fixed_point q[4],
1212 	fixed ybot, fixed ytop, const patch_color_t *c0, const patch_color_t *c1,
1213 	bool swap_axes, bool self_intersecting)
1214 {
1215     /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1216     fixed dx1, dy1, dx2, dy2;
1217     bool orient;
1218 
1219     if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1220 	return 0;
1221     if (ybot == ytop)
1222 	return 0;
1223     dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1224     dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1225 #if 1
1226     if (!swap_axes)
1227 	vd_quad(q[0].x, q[0].y, q[1].x, q[1].y, q[3].x, q[3].y, q[2].x, q[2].y, 0, RGB(255, 0, 0));
1228     else
1229 	vd_quad(q[0].y, q[0].x, q[1].y, q[1].x, q[3].y, q[3].x, q[2].y, q[2].x, 0, RGB(255, 0, 0));
1230 #endif
1231     if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1232 	orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1233 	return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1234     } else {
1235 	fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1236 
1237 	orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1238 	return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1239     }
1240 }
1241 
1242 private inline int
fill_wedge_trap(patch_fill_state_t * pfs,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * q0,const gs_fixed_point * q1,const patch_color_t * c0,const patch_color_t * c1,bool swap_axes,bool self_intersecting)1243 fill_wedge_trap(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
1244 	    const gs_fixed_point *q0, const gs_fixed_point *q1, const patch_color_t *c0, const patch_color_t *c1,
1245 	    bool swap_axes, bool self_intersecting)
1246 {
1247     /* We assume that the width of the wedge is close to zero,
1248        so we can ignore the slope when computing transversal distances. */
1249     gs_fixed_point p[4];
1250     const patch_color_t *cc0, *cc1;
1251 
1252     if (p0->y < p1->y) {
1253 	p[2] = *p0;
1254 	p[3] = *p1;
1255 	cc0 = c0;
1256 	cc1 = c1;
1257     } else {
1258 	p[2] = *p1;
1259 	p[3] = *p0;
1260 	cc0 = c1;
1261 	cc1 = c0;
1262     }
1263     p[0] = *q0;
1264     p[1] = *q1;
1265     return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1266 }
1267 
1268 private void
split_curve_s(const gs_fixed_point * pole,gs_fixed_point * q0,gs_fixed_point * q1,int pole_step)1269 split_curve_s(const gs_fixed_point *pole, gs_fixed_point *q0, gs_fixed_point *q1, int pole_step)
1270 {
1271     /*	This copies a code fragment from split_curve_midpoint,
1272         substituting another data type.
1273      */
1274     /*
1275      * We have to define midpoint carefully to avoid overflow.
1276      * (If it overflows, something really pathological is going
1277      * on, but we could get infinite recursion that way....)
1278      */
1279 #define midpoint(a,b)\
1280   (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1281     fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1282     fixed y12 = midpoint(pole[1 * pole_step].y, pole[2 * pole_step].y);
1283 
1284     /* q[0] and q[1] must not be the same as pole. */
1285     q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1286     q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1287     q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1288     q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1289     q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1290     q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1291     q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1292     q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1293     q0[0 * pole_step].x = pole[0 * pole_step].x;
1294     q0[0 * pole_step].y = pole[0 * pole_step].y;
1295     q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1296     q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1297     q1[3 * pole_step].x = pole[3 * pole_step].x;
1298     q1[3 * pole_step].y = pole[3 * pole_step].y;
1299 #undef midpoint
1300 }
1301 
1302 private void
split_curve(const gs_fixed_point pole[4],gs_fixed_point q0[4],gs_fixed_point q1[4])1303 split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1304 {
1305     split_curve_s(pole, q0, q1, 1);
1306 }
1307 
1308 
1309 private void
generate_inner_vertices(gs_fixed_point * p,const gs_fixed_point pole[4],int k)1310 generate_inner_vertices(gs_fixed_point *p, const gs_fixed_point pole[4], int k)
1311 {
1312     /* Recure to get exactly same points as when devided a patch. */
1313     /* An iteration can't give them preciselly. */
1314     if (k > 1) {
1315 	gs_fixed_point q[2][4];
1316 
1317 	split_curve(pole, q[0], q[1]);
1318 	p[k / 2] = q[0][3];
1319 	generate_inner_vertices(p, q[0], k / 2);
1320 	generate_inner_vertices(p + k / 2, q[1], k / 2);
1321     }
1322 }
1323 
1324 private inline void
do_swap_axes(gs_fixed_point * p,int k)1325 do_swap_axes(gs_fixed_point *p, int k)
1326 {
1327     int i;
1328 
1329     for (i = 0; i < k; i++) {
1330 	p[i].x ^= p[i].y; p[i].y ^= p[i].x; p[i].x ^= p[i].y;
1331     }
1332 }
1333 
1334 private inline void
y_extreme_vertice(gs_fixed_point * q,const gs_fixed_point * p,int k,int minmax)1335 y_extreme_vertice(gs_fixed_point *q, const gs_fixed_point *p, int k, int minmax)
1336 {
1337     int i;
1338     gs_fixed_point r = *p;
1339 
1340     for (i = 1; i < k; i++)
1341 	if ((p[i].y - r.y) * minmax > 0)
1342 	    r = p[i];
1343     *q = r;
1344 }
1345 
1346 private inline fixed
span_x(const gs_fixed_point * p,int k)1347 span_x(const gs_fixed_point *p, int k)
1348 {
1349     int i;
1350     fixed xmin = p[0].x, xmax = p[0].x;
1351 
1352     for (i = 1; i < k; i++) {
1353 	xmin = min(xmin, p[i].x);
1354 	xmax = max(xmax, p[i].x);
1355     }
1356     return xmax - xmin;
1357 }
1358 
1359 private inline fixed
span_y(const gs_fixed_point * p,int k)1360 span_y(const gs_fixed_point *p, int k)
1361 {
1362     int i;
1363     fixed ymin = p[0].y, ymax = p[0].y;
1364 
1365     for (i = 1; i < k; i++) {
1366 	ymin = min(ymin, p[i].y);
1367 	ymax = max(ymax, p[i].y);
1368     }
1369     return ymax - ymin;
1370 }
1371 
1372 private inline void
draw_wedge(const gs_fixed_point * p,int n)1373 draw_wedge(const gs_fixed_point *p, int n)
1374 {
1375 #ifdef DEBUG
1376     int i;
1377 
1378     if (!vd_enabled)
1379 	return;
1380     vd_setlinewidth(4);
1381     vd_setcolor(RGB(255, 0, 0));
1382     vd_beg_path;
1383     vd_moveto(p[0].x, p[0].y);
1384     for (i = 1; i < n; i++)
1385 	vd_lineto(p[i].x, p[i].y);
1386     vd_closepath;
1387     vd_end_path;
1388     vd_fill;
1389     /*vd_stroke;*/
1390 #endif
1391 }
1392 
1393 private inline fixed
manhattan_dist(const gs_fixed_point * p0,const gs_fixed_point * p1)1394 manhattan_dist(const gs_fixed_point *p0, const gs_fixed_point *p1)
1395 {
1396     fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1397 
1398     return max(dx, dy);
1399 }
1400 
1401 private inline void
create_wedge_vertex_list(patch_fill_state_t * pfs,wedge_vertex_list_t * l,const gs_fixed_point * p0,const gs_fixed_point * p1)1402 create_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1403 	const gs_fixed_point *p0, const gs_fixed_point *p1)
1404 {
1405     assert(l->end == NULL);
1406     l->beg = wedge_vertex_list_elem_reserve(pfs);
1407     l->end = wedge_vertex_list_elem_reserve(pfs);
1408     assert(l->beg != NULL);
1409     assert(l->end != NULL);
1410     l->beg->prev = l->end->next = NULL;
1411     l->beg->next = l->end;
1412     l->end->prev = l->beg;
1413     l->beg->p = *p0;
1414     l->end->p = *p1;
1415     l->beg->level = l->end->level = 0;
1416 }
1417 
1418 private inline wedge_vertex_list_elem_t *
insert_wedge_vertex_list_elem(patch_fill_state_t * pfs,wedge_vertex_list_t * l,const gs_fixed_point * p)1419 insert_wedge_vertex_list_elem(patch_fill_state_t *pfs, wedge_vertex_list_t *l, const gs_fixed_point *p)
1420 {
1421     wedge_vertex_list_elem_t *e = wedge_vertex_list_elem_reserve(pfs);
1422 
1423     /* We have got enough free elements due to the preliminary decomposition
1424        of curves to LAZY_WEDGES_MAX_LEVEL, see curve_samples. */
1425     assert(e != NULL);
1426     assert(l->beg->next == l->end);
1427     assert(l->end->prev == l->beg);
1428     e->next = l->end;
1429     e->prev = l->beg;
1430     e->p = *p;
1431     e->level = max(l->beg->level, l->end->level) + 1;
1432     e->divide_count = 0;
1433     l->beg->next = l->end->prev = e;
1434     {	int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1435 	int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1436 
1437 	assert((p->x - l->beg->p.x) * sx >= 0);
1438 	assert((p->y - l->beg->p.y) * sy >= 0);
1439 	assert((l->end->p.x - p->x) * sx >= 0);
1440 	assert((l->end->p.y - p->y) * sy >= 0);
1441     }
1442     return e;
1443 }
1444 
1445 private inline wedge_vertex_list_elem_t *
open_wedge_median(patch_fill_state_t * pfs,wedge_vertex_list_t * l,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * pm)1446 open_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1447 	const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm)
1448 {
1449     wedge_vertex_list_elem_t *e;
1450 
1451     if (!l->last_side) {
1452 	if (l->beg == NULL)
1453 	    create_wedge_vertex_list(pfs, l, p0, p1);
1454 	assert(l->beg->p.x == p0->x);
1455 	assert(l->beg->p.y == p0->y);
1456 	assert(l->end->p.x == p1->x);
1457 	assert(l->end->p.y == p1->y);
1458 	e = insert_wedge_vertex_list_elem(pfs, l, pm);
1459 	e->divide_count++;
1460 	return e;
1461     } else {
1462 	if (l->beg == NULL) {
1463 	    create_wedge_vertex_list(pfs, l, p1, p0);
1464 	    e = insert_wedge_vertex_list_elem(pfs, l, pm);
1465 	    e->divide_count++;
1466 	    return e;
1467 	}
1468 	assert(l->beg->p.x == p1->x);
1469 	assert(l->beg->p.y == p1->y);
1470 	assert(l->end->p.x == p0->x);
1471 	assert(l->end->p.y == p0->y);
1472 	if (l->beg->next == l->end) {
1473 	    e = insert_wedge_vertex_list_elem(pfs, l, pm);
1474 	    e->divide_count++;
1475 	    return e;
1476 	} else {
1477 	    e = wedge_vertex_list_find(l->beg, l->end,
1478 			max(l->beg->level, l->end->level) + 1);
1479 	    assert(e != NULL);
1480 	    assert(e->p.x == pm->x && e->p.y == pm->y);
1481     	    e->divide_count++;
1482 	    return e;
1483 	}
1484     }
1485 }
1486 
1487 private inline void
make_wedge_median(patch_fill_state_t * pfs,wedge_vertex_list_t * l,wedge_vertex_list_t * l0,bool forth,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * pm)1488 make_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1489 	wedge_vertex_list_t *l0, bool forth,
1490 	const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm)
1491 {
1492     l->last_side = l0->last_side;
1493     if (!l->last_side ^ !forth) {
1494 	l->end = open_wedge_median(pfs, l0, p0, p1, pm);
1495 	l->beg = l0->beg;
1496     } else {
1497 	l->beg = open_wedge_median(pfs, l0, p0, p1, pm);
1498 	l->end = l0->end;
1499     }
1500 }
1501 
1502 private int fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
1503 	    const patch_color_t *c0, const patch_color_t *c1);
1504 
1505 private inline int
close_wedge_median(patch_fill_state_t * pfs,wedge_vertex_list_t * l,const patch_color_t * c0,const patch_color_t * c1)1506 close_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1507 	const patch_color_t *c0, const patch_color_t *c1)
1508 {
1509     int code;
1510 
1511     if (!l->last_side)
1512 	return 0;
1513     code = fill_wedge_from_list(pfs, l, c1, c0);
1514     if (code < 0)
1515 	return code;
1516     release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1517     return 0;
1518 }
1519 
1520 private inline void
move_wedge(wedge_vertex_list_t * l,const wedge_vertex_list_t * l0,bool forth)1521 move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1522 {
1523     if (!l->last_side ^ !forth) {
1524 	l->beg = l->end;
1525 	l->end = l0->end;
1526     } else {
1527 	l->end = l->beg;
1528 	l->beg = l0->beg;
1529     }
1530 }
1531 
1532 private inline int
fill_triangle_wedge_aux(patch_fill_state_t * pfs,const shading_vertex_t * q0,const shading_vertex_t * q1,const shading_vertex_t * q2)1533 fill_triangle_wedge_aux(patch_fill_state_t *pfs,
1534 	    const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
1535 {   int code;
1536     const gs_fixed_point *p0, *p1, *p2;
1537     gs_fixed_point qq0, qq1, qq2;
1538     fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
1539     bool swap_axes;
1540 
1541 #   if SKIP_TEST
1542 	dbg_wedge_triangle_cnt++;
1543 #   endif
1544     if (dx > dy) {
1545 	swap_axes = true;
1546 	qq0.x = q0->p.y;
1547 	qq0.y = q0->p.x;
1548 	qq1.x = q1->p.y;
1549 	qq1.y = q1->p.x;
1550 	qq2.x = q2->p.y;
1551 	qq2.y = q2->p.x;
1552 	p0 = &qq0;
1553 	p1 = &qq1;
1554 	p2 = &qq2;
1555     } else {
1556 	swap_axes = false;
1557 	p0 = &q0->p;
1558 	p1 = &q1->p;
1559 	p2 = &q2->p;
1560     }
1561     /* We decompose the thin triangle into 2 thin trapezoids.
1562        An optimization with decomposing into 2 triangles
1563        appears low useful, because the self_intersecting argument
1564        with inline expansion does that job perfectly. */
1565     if (p0->y < p1->y) {
1566 	code = fill_wedge_trap(pfs, p0, p2, p0, p1, &q0->c, &q2->c, swap_axes, false);
1567 	if (code < 0)
1568 	    return code;
1569 	return fill_wedge_trap(pfs, p2, p1, p0, p1, &q2->c, &q1->c, swap_axes, false);
1570     } else {
1571 	code = fill_wedge_trap(pfs, p0, p2, p1, p0, &q0->c, &q2->c, swap_axes, false);
1572 	if (code < 0)
1573 	    return code;
1574 	return fill_wedge_trap(pfs, p2, p1, p1, p0, &q2->c, &q1->c, swap_axes, false);
1575     }
1576 }
1577 
1578 private inline int
try_device_linear_color(patch_fill_state_t * pfs,bool wedge,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2)1579 try_device_linear_color(patch_fill_state_t *pfs, bool wedge,
1580 	const shading_vertex_t *p0, const shading_vertex_t *p1,
1581 	const shading_vertex_t *p2)
1582 {
1583     /*	Returns :
1584 	<0 - error;
1585 	0 - success;
1586 	1 - decompose to linear color areas;
1587 	2 - decompose to constant color areas;
1588      */
1589     int code;
1590 
1591     if (pfs->unlinear)
1592 	return 2;
1593     if (!wedge) {
1594 	gs_direct_color_space *cs =
1595 		(gs_direct_color_space *)pfs->direct_space; /* break 'const'. */
1596 	float smoothness = max(pfs->smoothness, 1.0 / min_linear_grades);
1597 	/* Restrict the smoothness with 1/min_linear_grades, because cs_is_linear
1598 	   can't provide a better precision due to the color
1599 	   representation with integers.
1600 	 */
1601 	float s0, s1, s2, s01, s012;
1602 
1603 	s0 = function_linearity(pfs, &p0->c, &p1->c);
1604 	if (s0 > smoothness)
1605 	    return 1;
1606 	s1 = function_linearity(pfs, &p1->c, &p2->c);
1607 	if (s1 > smoothness)
1608 	    return 1;
1609 	s2 = function_linearity(pfs, &p2->c, &p0->c);
1610 	if (s2 > smoothness)
1611 	    return 1;
1612 	/* fixme: check an inner color ? */
1613 	s01 = max(s0, s1);
1614 	s012 = max(s01, s2);
1615 	code = cs_is_linear(cs, pfs->pis, pfs->dev,
1616 			    &p0->c.cc, &p1->c.cc, &p2->c.cc, NULL, smoothness - s012);
1617 	if (code < 0)
1618 	    return code;
1619 	if (code == 0)
1620 	    return 1;
1621     }
1622     {   gx_device *pdev = pfs->dev;
1623 	frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
1624 	gs_fill_attributes fa;
1625 	gx_device_color dc[3];
1626 	vd_save;
1627 
1628 	fa.clip = &pfs->rect;
1629 	fa.ht = NULL;
1630 	fa.swap_axes = false;
1631 	fa.lop = 0;
1632 	code = patch_color_to_device_color(pfs, &p0->c, &dc[0]);
1633 	if (code < 0)
1634 	    return code;
1635 	if (dc[0].type != &gx_dc_type_data_pure)
1636 	    return 2;
1637 	dc2fc(pfs, dc[0].colors.pure, fc[0]);
1638 	if (!wedge) {
1639 	    code = patch_color_to_device_color(pfs, &p1->c, &dc[1]);
1640 	    if (code < 0)
1641 		return code;
1642 	    dc2fc(pfs, dc[1].colors.pure, fc[1]);
1643 	}
1644 	code = patch_color_to_device_color(pfs, &p2->c, &dc[2]);
1645 	if (code < 0)
1646 	    return code;
1647 	dc2fc(pfs, dc[2].colors.pure, fc[2]);
1648 	draw_triangle(&p0->p, &p1->p, &p2->p, RGB(255, 0, 0));
1649 	if (!VD_TRACE_DOWN)
1650 	    vd_disable;
1651 	code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
1652 			&p0->p, &p1->p, &p2->p,
1653 			fc[0], (wedge ? NULL : fc[1]), fc[2]);
1654 	vd_restore;
1655 	if (code == 1)
1656 	    return 0; /* The area is filled. */
1657 	if (code < 0)
1658 	    return code;
1659 	else /* code == 0, the device requested to decompose the area. */
1660 	    return 1;
1661     }
1662 }
1663 
1664 private inline int
fill_triangle_wedge(patch_fill_state_t * pfs,const shading_vertex_t * q0,const shading_vertex_t * q1,const shading_vertex_t * q2)1665 fill_triangle_wedge(patch_fill_state_t *pfs,
1666 	    const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
1667 {
1668     if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
1669 	(int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
1670 	return 0; /* Zero area. */
1671     draw_triangle(&q0->p, &q1->p, &q2->p, RGB(255, 255, 0));
1672     /*
1673 	Can't apply try_device_linear_color here
1674 	because didn't check is_color_linear.
1675 	Maybe need a decomposition.
1676 	Do same as for 'unlinear', and branch later.
1677      */
1678     return fill_triangle_wedge_aux(pfs, q0, q1, q2);
1679 }
1680 
1681 private inline int
fill_triangle_wedge_from_list(patch_fill_state_t * pfs,const wedge_vertex_list_elem_t * beg,const wedge_vertex_list_elem_t * end,const wedge_vertex_list_elem_t * mid,const patch_color_t * c0,const patch_color_t * c1)1682 fill_triangle_wedge_from_list(patch_fill_state_t *pfs,
1683     const wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
1684     const wedge_vertex_list_elem_t *mid,
1685     const patch_color_t *c0, const patch_color_t *c1)
1686 {
1687     shading_vertex_t p[3];
1688 
1689     p[0].p = beg->p;
1690     p[0].c = *c0; /* fixme : unhappy copying colors. */
1691     p[1].p = end->p;
1692     p[1].c = *c1;
1693     p[2].p = mid->p;
1694     patch_interpolate_color(&p[2].c, c0, c1, pfs, 0.5);
1695     return fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
1696 }
1697 
1698 private int
fill_wedge_from_list_rec(patch_fill_state_t * pfs,wedge_vertex_list_elem_t * beg,const wedge_vertex_list_elem_t * end,int level,const patch_color_t * c0,const patch_color_t * c1)1699 fill_wedge_from_list_rec(patch_fill_state_t *pfs,
1700 	    wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
1701 	    int level, const patch_color_t *c0, const patch_color_t *c1)
1702 {
1703     if (beg->next == end)
1704 	return 0;
1705     else if (beg->next->next == end) {
1706 	assert(beg->next->divide_count == 1 || beg->next->divide_count == 2);
1707 	if (beg->next->divide_count != 1)
1708 	    return 0;
1709 	return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
1710     } else {
1711 	gs_fixed_point p;
1712 	wedge_vertex_list_elem_t *e;
1713 	patch_color_t c;
1714 	int code;
1715 
1716 	p.x = (beg->p.x + end->p.x) / 2;
1717 	p.y = (beg->p.y + end->p.y) / 2;
1718 	e = wedge_vertex_list_find(beg, end, level + 1);
1719 	assert(e != NULL);
1720 	assert(e->p.x == p.x && e->p.y == p.y);
1721 	patch_interpolate_color(&c, c0, c1, pfs, 0.5);
1722 	code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, &c);
1723 	if (code < 0)
1724 	    return code;
1725 	code = fill_wedge_from_list_rec(pfs, e, end, level + 1, &c, c1);
1726 	if (code < 0)
1727 	    return code;
1728 	assert(e->divide_count == 1 || e->divide_count == 2);
1729 	if (e->divide_count != 1)
1730 	    return 0;
1731 	return fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
1732     }
1733 }
1734 
1735 private int
fill_wedge_from_list(patch_fill_state_t * pfs,const wedge_vertex_list_t * l,const patch_color_t * c0,const patch_color_t * c1)1736 fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
1737 	    const patch_color_t *c0, const patch_color_t *c1)
1738 {
1739     return fill_wedge_from_list_rec(pfs, l->beg, l->end,
1740 		    max(l->beg->level, l->end->level), c0, c1);
1741 }
1742 
1743 private inline int
terminate_wedge_vertex_list(patch_fill_state_t * pfs,wedge_vertex_list_t * l,const patch_color_t * c0,const patch_color_t * c1)1744 terminate_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1745 	const patch_color_t *c0, const patch_color_t *c1)
1746 {
1747     if (l->beg != NULL) {
1748 	int code = fill_wedge_from_list(pfs, l, c0, c1);
1749 
1750 	if (code < 0)
1751 	    return code;
1752 	release_wedge_vertex_list(pfs, l, 1);
1753     }
1754     return 0;
1755 }
1756 
1757 private int
wedge_by_triangles(patch_fill_state_t * pfs,int ka,const gs_fixed_point pole[4],const patch_color_t * c0,const patch_color_t * c1)1758 wedge_by_triangles(patch_fill_state_t *pfs, int ka,
1759 	const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1)
1760 {   /* Assuming ka >= 2, see fill_wedges. */
1761     gs_fixed_point q[2][4];
1762     shading_vertex_t p[3];
1763     int code;
1764 
1765     split_curve(pole, q[0], q[1]);
1766     p[0].p = pole[0];
1767     p[0].c = *c0; /* fixme : unhappy copying colors. */
1768     p[1].p = pole[3];
1769     p[1].c = *c1;
1770     p[2].p = q[0][3];
1771     patch_interpolate_color(&p[2].c, c0, c1, pfs, 0.5);
1772     code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
1773     if (code < 0)
1774 	return code;
1775     if (ka == 2)
1776 	return 0;
1777     code = wedge_by_triangles(pfs, ka / 2, q[0], c0, &p[2].c);
1778     if (code < 0)
1779 	return code;
1780     return wedge_by_triangles(pfs, ka / 2, q[1], &p[2].c, c1);
1781 }
1782 
1783 private inline bool
is_linear_color_applicable(const patch_fill_state_t * pfs)1784 is_linear_color_applicable(const patch_fill_state_t *pfs)
1785 {
1786     if (!USE_LINEAR_COLOR_PROCS)
1787 	return false;
1788     if (pfs->dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
1789 	return false;
1790     if (gx_get_cmap_procs(pfs->pis, pfs->dev)->is_halftoned(pfs->pis, pfs->dev))
1791 	return false;
1792     return true;
1793 }
1794 
1795 int
mesh_padding(patch_fill_state_t * pfs,const gs_fixed_point * p0,const gs_fixed_point * p1,const patch_color_t * c0,const patch_color_t * c1)1796 mesh_padding(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
1797 	    const patch_color_t *c0, const patch_color_t *c1)
1798 {
1799     gs_fixed_point q0, q1;
1800     const patch_color_t *cc0, *cc1;
1801     fixed dx = p1->x - p0->x;
1802     fixed dy = p1->y - p0->y;
1803     bool swap_axes = (any_abs(dx) > any_abs(dy));
1804     gs_fixed_edge le, re;
1805     const fixed adjust = INTERPATCH_PADDING;
1806 
1807     pfs->unlinear = !is_linear_color_applicable(pfs);
1808     if (swap_axes) {
1809 	if (p0->x < p1->x) {
1810 	    q0.x = p0->y;
1811 	    q0.y = p0->x;
1812 	    q1.x = p1->y;
1813 	    q1.y = p1->x;
1814 	    cc0 = c0;
1815 	    cc1 = c1;
1816 	} else {
1817 	    q0.x = p1->y;
1818 	    q0.y = p1->x;
1819 	    q1.x = p0->y;
1820 	    q1.y = p0->x;
1821 	    cc0 = c1;
1822 	    cc1 = c0;
1823 	}
1824     } else if (p0->y < p1->y) {
1825 	q0 = *p0;
1826 	q1 = *p1;
1827 	cc0 = c0;
1828 	cc1 = c1;
1829     } else {
1830 	q0 = *p1;
1831 	q1 = *p0;
1832 	cc0 = c1;
1833 	cc1 = c0;
1834     }
1835     le.start.x = q0.x - adjust;
1836     re.start.x = q0.x + adjust;
1837     le.start.y = re.start.y = q0.y - adjust;
1838     le.end.x = q1.x - adjust;
1839     re.end.x = q1.x + adjust;
1840     le.end.y = re.end.y = q1.y + adjust;
1841     adjust_swapped_boundary(&re.start.x, swap_axes);
1842     adjust_swapped_boundary(&re.end.x, swap_axes);
1843     return decompose_linear_color(pfs, &le, &re, le.start.y, le.end.y, swap_axes, cc0, cc1, 0);
1844     /* fixme : for a better performance and quality, we would like to
1845        consider the bar as an oriented one and to know at what side of it the spot resides.
1846        If we know that, we could expand only to outside the spot.
1847        Note that if the boundary has a self-intersection,
1848        we still need to expand to both directions.
1849      */
1850 }
1851 
1852 private int
fill_wedges_aux(patch_fill_state_t * pfs,int k,int ka,const gs_fixed_point pole[4],const patch_color_t * c0,const patch_color_t * c1,int wedge_type)1853 fill_wedges_aux(patch_fill_state_t *pfs, int k, int ka,
1854 	const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1,
1855 	int wedge_type)
1856 {
1857     int code;
1858 
1859     if (k > 1) {
1860 	gs_fixed_point q[2][4];
1861 	patch_color_t c;
1862 
1863 	patch_interpolate_color(&c, c0, c1, pfs, 0.5);
1864 	split_curve(pole, q[0], q[1]);
1865 	code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, &c, wedge_type);
1866 	if (code < 0)
1867 	    return code;
1868 	return fill_wedges_aux(pfs, k / 2, ka, q[1], &c, c1, wedge_type);
1869     } else {
1870 	if (INTERPATCH_PADDING && (wedge_type & interpatch_padding)) {
1871 	    vd_bar(pole[0].x, pole[0].y, pole[3].x, pole[3].y, 0, RGB(255, 0, 0));
1872 	    code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
1873 	    if (code < 0)
1874 		return code;
1875 	}
1876 	if (ka >= 2 && (wedge_type & inpatch_wedge))
1877 	    return wedge_by_triangles(pfs, ka, pole, c0, c1);
1878 	return 0;
1879     }
1880 }
1881 
1882 private int
fill_wedges(patch_fill_state_t * pfs,int k0,int k1,const gs_fixed_point * pole,int pole_step,const patch_color_t * c0,const patch_color_t * c1,int wedge_type)1883 fill_wedges(patch_fill_state_t *pfs, int k0, int k1,
1884 	const gs_fixed_point *pole, int pole_step,
1885 	const patch_color_t *c0, const patch_color_t *c1, int wedge_type)
1886 {
1887     /* Generate wedges between 2 variants of a curve flattening. */
1888     /* k0, k1 is a power of 2. */
1889     gs_fixed_point p[4];
1890 
1891     if (!(wedge_type & interpatch_padding) && k0 == k1)
1892 	return 0; /* Wedges are zero area. */
1893     if (k0 > k1) {
1894 	k0 ^= k1; k1 ^= k0; k0 ^= k1;
1895     }
1896     p[0] = pole[0];
1897     p[1] = pole[pole_step];
1898     p[2] = pole[pole_step * 2];
1899     p[3] = pole[pole_step * 3];
1900     return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
1901 }
1902 
1903 private inline void
make_vertices(gs_fixed_point q[4],const quadrangle_patch * p)1904 make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
1905 {
1906     q[0] = p->p[0][0]->p;
1907     q[1] = p->p[0][1]->p;
1908     q[2] = p->p[1][1]->p;
1909     q[3] = p->p[1][0]->p;
1910 }
1911 
1912 private inline void
wrap_vertices_by_y(gs_fixed_point q[4],const gs_fixed_point s[4])1913 wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
1914 {
1915     fixed y = s[0].y;
1916     int i = 0;
1917 
1918     if (y > s[1].y)
1919 	i = 1, y = s[1].y;
1920     if (y > s[2].y)
1921 	i = 2, y = s[2].y;
1922     if (y > s[3].y)
1923 	i = 3, y = s[3].y;
1924     q[0] = s[(i + 0) % 4];
1925     q[1] = s[(i + 1) % 4];
1926     q[2] = s[(i + 2) % 4];
1927     q[3] = s[(i + 3) % 4];
1928 }
1929 
1930 private int
ordered_triangle(patch_fill_state_t * pfs,gs_fixed_edge * le,gs_fixed_edge * re,patch_color_t * c)1931 ordered_triangle(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re, patch_color_t *c)
1932 {
1933     gs_fixed_edge ue;
1934     int code;
1935     gx_device_color dc;
1936     vd_save;
1937 
1938 #   if NOFILL_TEST
1939 	if (dbg_nofill)
1940 	    return 0;
1941 #   endif
1942     if (!VD_TRACE_DOWN)
1943         vd_disable;
1944     code = patch_color_to_device_color(pfs, c, &dc);
1945     if (code < 0)
1946 	return code;
1947     if (le->end.y < re->end.y) {
1948 	code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1949 	    le, re, le->start.y, le->end.y, false, &dc, pfs->pis->log_op);
1950 	if (code >= 0) {
1951 	    ue.start = le->end;
1952 	    ue.end = re->end;
1953 	    code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1954 		&ue, re, le->end.y, re->end.y, false, &dc, pfs->pis->log_op);
1955 	}
1956     } else if (le->end.y > re->end.y) {
1957 	code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1958 	    le, re, le->start.y, re->end.y, false, &dc, pfs->pis->log_op);
1959 	if (code >= 0) {
1960 	    ue.start = re->end;
1961 	    ue.end = le->end;
1962 	    code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1963 		le, &ue, re->end.y, le->end.y, false, &dc, pfs->pis->log_op);
1964 	}
1965     } else
1966 	code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1967 	    le, re, le->start.y, le->end.y, false, &dc, pfs->pis->log_op);
1968     vd_restore;
1969     return code;
1970 }
1971 
1972 private int
constant_color_triangle(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2)1973 constant_color_triangle(patch_fill_state_t *pfs,
1974 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
1975 {
1976     patch_color_t c, cc;
1977     gs_fixed_edge le, re;
1978     fixed dx0, dy0, dx1, dy1;
1979     const shading_vertex_t *pp;
1980     int i;
1981 
1982     draw_triangle(&p0->p, &p1->p, &p2->p, RGB(255, 0, 0));
1983     patch_interpolate_color(&c, &p0->c, &p1->c, pfs, 0.5);
1984     patch_interpolate_color(&cc, &p2->c, &c, pfs, 0.5);
1985     for (i = 0; i < 3; i++) {
1986 	/* fixme : does optimizer compiler expand this cycle ? */
1987 	if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
1988 	    le.start = re.start = p0->p;
1989 	    le.end = p1->p;
1990 	    re.end = p2->p;
1991 
1992 	    dx0 = le.end.x - le.start.x;
1993 	    dy0 = le.end.y - le.start.y;
1994 	    dx1 = re.end.x - re.start.x;
1995 	    dy1 = re.end.y - re.start.y;
1996 	    if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
1997     		return ordered_triangle(pfs, &le, &re, &c);
1998 	    else
1999     		return ordered_triangle(pfs, &re, &le, &c);
2000 	}
2001 	pp = p0; p0 = p1; p1 = p2; p2 = pp;
2002     }
2003     return 0;
2004 }
2005 
2006 
2007 private int
constant_color_quadrangle(patch_fill_state_t * pfs,const quadrangle_patch * p,bool self_intersecting)2008 constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2009 {
2010     /* Assuming the XY span is restricted with curve_samples.
2011        It is important for intersection_of_small_bars to compute faster. */
2012     gs_fixed_point q[4];
2013     fixed ry, ey;
2014     int code;
2015     bool swap_axes = false;
2016     gx_device_color dc;
2017     patch_color_t c1, c2, c;
2018     bool orient;
2019 
2020     draw_quadrangle(p, RGB(0, 255, 0));
2021     patch_interpolate_color(&c1, &p->p[0][0]->c, &p->p[0][1]->c, pfs, 0.5);
2022     patch_interpolate_color(&c2, &p->p[1][0]->c, &p->p[1][1]->c, pfs, 0.5);
2023     patch_interpolate_color(&c, &c1, &c2, pfs, 0.5);
2024     code = patch_color_to_device_color(pfs, &c, &dc);
2025     if (code < 0)
2026 	return code;
2027     {	gs_fixed_point qq[4];
2028 
2029 	make_vertices(qq, p);
2030 #	if 0 /* Swapping axes may improve the precision,
2031 		but slows down due to the area expantion needed
2032 		in gx_shade_trapezoid. */
2033 	    dx = span_x(qq, 4);
2034 	    dy = span_y(qq, 4);
2035 	    if (dy < dx) {
2036 		do_swap_axes(qq, 4);
2037 		swap_axes = true;
2038 	    }
2039 #	endif
2040 	wrap_vertices_by_y(q, qq);
2041     }
2042     {	fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2043 	fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2044 	int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2045 
2046 	if (g13 == h13) {
2047 	    fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2048 	    int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2049 
2050 	    if (dx1 == 0 && dy1 == 0 && g23 == h23)
2051 		return 0;
2052 	    if (g23 != h23) {
2053 		orient = (g23 > h23);
2054 		if (q[2].y <= q[3].y) {
2055 		    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2056 			return code;
2057 		    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2058 		} else {
2059 		    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2060 			return code;
2061 		    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2062 		}
2063 	    } else {
2064 		int64_t g12 = (int64_t)dx1 * dy2, h12 = (int64_t)dy1 * dx2;
2065 
2066 		if (dx3 == 0 && dy3 == 0 && g12 == h12)
2067 		    return 0;
2068 		orient = (g12 > h12);
2069 		if (q[1].y <= q[2].y) {
2070 		    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2071 			return code;
2072 		    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2073 		} else {
2074 		    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2075 			return code;
2076 		    return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2077 		}
2078 	    }
2079 	}
2080 	orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2081     }
2082     if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2083 	if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2084 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2085 		return code;
2086 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2087 		return code;
2088 	    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2089 		return code;
2090 	    return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2091 	} else {
2092 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2093 		return code;
2094 	    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2095 		return code;
2096 	    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2097 	}
2098     } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2099 	if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2100 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2101 		return code;
2102 	    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2103 		return code;
2104 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, ry, q[3].y, swap_axes, &dc, orient)) < 0)
2105 		return code;
2106 	    return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2107 	} else {
2108 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2109 		return code;
2110 	    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2111 		return code;
2112 	    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2113 	}
2114     } else if (q[2].y <= q[1].y && q[1].y <= q[3].y) {
2115 	if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2116 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2117 		return code;
2118 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2119 		return code;
2120 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2121 		return code;
2122 	    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2123 	} else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2124 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2125 		return code;
2126 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2127 		return code;
2128 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2129 		return code;
2130 	    return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2131 	} else {
2132 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2133 		return code;
2134 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient)) < 0)
2135 		return code;
2136 	    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient);
2137 	}
2138     } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2139 	if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2140 	    /* Same code as someone above. */
2141 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2142 		return code;
2143 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2144 		return code;
2145 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2146 		return code;
2147 	    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2148 	} else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 2, 1, &ry, &ey)) {
2149 	    /* Same code as someone above. */
2150 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2151 		return code;
2152 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2153 		return code;
2154 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2155 		return code;
2156 	    return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2157 	} else {
2158 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2159 		return code;
2160 	    if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient)) < 0)
2161 		return code;
2162 	    return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2163 	}
2164     } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2165 	if (self_intersecting && intersection_of_small_bars(q, 0, 1, 3, 2, &ry, &ey)) {
2166 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2167 		return code;
2168 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2169 		return code;
2170 	    if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2171 		return code;
2172 	    return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2173 	} else {
2174 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2175 		return code;
2176 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[1].y, swap_axes, &dc, orient)) < 0)
2177 		return code;
2178 	    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2179 	}
2180     } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2181 	if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2182 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2183 		return code;
2184 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2185 		return code;
2186 	    if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2187 		return code;
2188 	    return gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2189 	} else {
2190 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2191 		return code;
2192 	    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient)) < 0)
2193 		return code;
2194 	    return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2195 	}
2196     } else {
2197 	/* Impossible. */
2198 	return_error(gs_error_unregistered);
2199     }
2200 }
2201 
2202 private inline void
divide_quadrangle_by_v(patch_fill_state_t * pfs,quadrangle_patch * s0,quadrangle_patch * s1,shading_vertex_t q[2],const quadrangle_patch * p)2203 divide_quadrangle_by_v(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2204 	    shading_vertex_t q[2], const quadrangle_patch *p)
2205 {
2206     q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2207     q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2208     q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2209     q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2210     patch_interpolate_color(&q[0].c, &p->p[0][0]->c, &p->p[1][0]->c, pfs, 0.5);
2211     patch_interpolate_color(&q[1].c, &p->p[0][1]->c, &p->p[1][1]->c, pfs, 0.5);
2212     s0->p[0][0] = p->p[0][0];
2213     s0->p[0][1] = p->p[0][1];
2214     s0->p[1][0] = s1->p[0][0] = &q[0];
2215     s0->p[1][1] = s1->p[0][1] = &q[1];
2216     s1->p[1][0] = p->p[1][0];
2217     s1->p[1][1] = p->p[1][1];
2218 }
2219 
2220 private inline void
divide_quadrangle_by_u(patch_fill_state_t * pfs,quadrangle_patch * s0,quadrangle_patch * s1,shading_vertex_t q[2],const quadrangle_patch * p)2221 divide_quadrangle_by_u(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2222 	    shading_vertex_t q[2], const quadrangle_patch *p)
2223 {
2224     q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2225     q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2226     q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2227     q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2228     patch_interpolate_color(&q[0].c, &p->p[0][0]->c, &p->p[0][1]->c, pfs, 0.5);
2229     patch_interpolate_color(&q[1].c, &p->p[1][0]->c, &p->p[1][1]->c, pfs, 0.5);
2230     s0->p[0][0] = p->p[0][0];
2231     s0->p[1][0] = p->p[1][0];
2232     s0->p[0][1] = s1->p[0][0] = &q[0];
2233     s0->p[1][1] = s1->p[1][0] = &q[1];
2234     s1->p[0][1] = p->p[0][1];
2235     s1->p[1][1] = p->p[1][1];
2236 }
2237 
2238 private inline int
is_quadrangle_color_monotonic(const patch_fill_state_t * pfs,const quadrangle_patch * p,bool * not_monotonic_by_u,bool * not_monotonic_by_v)2239 is_quadrangle_color_monotonic(const patch_fill_state_t *pfs, const quadrangle_patch *p,
2240 			      bool *not_monotonic_by_u, bool *not_monotonic_by_v)
2241 {   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2242     int code;
2243 
2244     code = isnt_color_monotonic(pfs, &p->p[0][0]->c, &p->p[1][1]->c);
2245     if (code <= 0)
2246 	return code;
2247     if (code & 1)
2248 	*not_monotonic_by_v = true;
2249     if (code & 2)
2250 	*not_monotonic_by_u = true;
2251     return !code;
2252 }
2253 
2254 private inline bool
quadrangle_bbox_covers_pixel_centers(const quadrangle_patch * p)2255 quadrangle_bbox_covers_pixel_centers(const quadrangle_patch *p)
2256 {
2257     fixed xbot, xtop, ybot, ytop;
2258 
2259     xbot = min(min(p->p[0][0]->p.x, p->p[0][1]->p.x),
2260 	       min(p->p[1][0]->p.x, p->p[1][1]->p.x));
2261     xtop = max(max(p->p[0][0]->p.x, p->p[0][1]->p.x),
2262 	       max(p->p[1][0]->p.x, p->p[1][1]->p.x));
2263     if (covers_pixel_centers(xbot, xtop))
2264 	return true;
2265     ybot = min(min(p->p[0][0]->p.y, p->p[0][1]->p.y),
2266 	       min(p->p[1][0]->p.y, p->p[1][1]->p.y));
2267     ytop = max(max(p->p[0][0]->p.y, p->p[0][1]->p.y),
2268 	       max(p->p[1][0]->p.y, p->p[1][1]->p.y));
2269     if (covers_pixel_centers(ybot, ytop))
2270 	return true;
2271     return false;
2272 }
2273 
2274 private inline void
divide_bar(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,int radix,shading_vertex_t * p)2275 divide_bar(patch_fill_state_t *pfs,
2276 	const shading_vertex_t *p0, const shading_vertex_t *p1, int radix, shading_vertex_t *p)
2277 {
2278     p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2279     p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2280     patch_interpolate_color(&p->c, &p0->c, &p1->c, pfs, (double)(radix - 1) / radix);
2281 }
2282 
2283 private inline void
bbox_of_points(gs_fixed_rect * r,const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2,const gs_fixed_point * p3)2284 bbox_of_points(gs_fixed_rect *r,
2285 	const gs_fixed_point *p0, const gs_fixed_point *p1,
2286 	const gs_fixed_point *p2, const gs_fixed_point *p3)
2287 {
2288     r->p.x = r->q.x = p0->x;
2289     r->p.y = r->q.y = p0->y;
2290 
2291     if (r->p.x > p1->x)
2292 	r->p.x = p1->x;
2293     if (r->q.x < p1->x)
2294 	r->q.x = p1->x;
2295     if (r->p.y > p1->y)
2296 	r->p.y = p1->y;
2297     if (r->q.y < p1->y)
2298 	r->q.y = p1->y;
2299 
2300     if (r->p.x > p2->x)
2301 	r->p.x = p2->x;
2302     if (r->q.x < p2->x)
2303 	r->q.x = p2->x;
2304     if (r->p.y > p2->y)
2305 	r->p.y = p2->y;
2306     if (r->q.y < p2->y)
2307 	r->q.y = p2->y;
2308 
2309     if (p3 == NULL)
2310 	return;
2311 
2312     if (r->p.x > p3->x)
2313 	r->p.x = p3->x;
2314     if (r->q.x < p3->x)
2315 	r->q.x = p3->x;
2316     if (r->p.y > p3->y)
2317 	r->p.y = p3->y;
2318     if (r->q.y < p3->y)
2319 	r->q.y = p3->y;
2320 }
2321 
2322 private int
triangle_by_4(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2,wedge_vertex_list_t * l01,wedge_vertex_list_t * l12,wedge_vertex_list_t * l20,double cd,fixed sd)2323 triangle_by_4(patch_fill_state_t *pfs,
2324 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2325 	wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20,
2326 	double cd, fixed sd)
2327 {
2328     shading_vertex_t p01, p12, p20;
2329     wedge_vertex_list_t L01, L12, L20, L[3];
2330     bool inside_save = pfs->inside;
2331     gs_fixed_rect r, r1;
2332     int code;
2333 
2334     if (!pfs->inside) {
2335 	bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2336 	r1 = r;
2337 	rect_intersect(r, pfs->rect);
2338 	if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2339 	    return 0; /* Outside. */
2340     }
2341     code = try_device_linear_color(pfs, false, p0, p1, p2);
2342     switch(code) {
2343 	case 0: /* The area is filled. */
2344 	    return 0;
2345 	case 2: /* decompose to constant color areas */
2346 	    if (sd < fixed_1 * 4)
2347 		return constant_color_triangle(pfs, p2, p0, p1);
2348 	    if (pfs->Function != NULL) {
2349 		double d01 = color_span(pfs, &p1->c, &p0->c);
2350 		double d12 = color_span(pfs, &p2->c, &p1->c);
2351 		double d20 = color_span(pfs, &p0->c, &p2->c);
2352 
2353 		if (d01 <= pfs->smoothness / COLOR_CONTIGUITY &&
2354 		    d12 <= pfs->smoothness / COLOR_CONTIGUITY &&
2355 		    d20 <= pfs->smoothness / COLOR_CONTIGUITY)
2356 		    return constant_color_triangle(pfs, p2, p0, p1);
2357 	    } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY)
2358 		return constant_color_triangle(pfs, p2, p0, p1);
2359 	    break;
2360 	case 1: /* decompose to linear color areas */
2361 	    if (sd < fixed_1)
2362 		return constant_color_triangle(pfs, p2, p0, p1);
2363 	    break;
2364 	default: /* Error. */
2365 	    return code;
2366     }
2367     if (!pfs->inside) {
2368 	if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2369 	    r.q.x == r1.q.x && r.q.y == r1.q.y)
2370 	    pfs->inside = true;
2371     }
2372     divide_bar(pfs, p0, p1, 2, &p01);
2373     divide_bar(pfs, p1, p2, 2, &p12);
2374     divide_bar(pfs, p2, p0, 2, &p20);
2375     if (LAZY_WEDGES) {
2376 	init_wedge_vertex_list(L, count_of(L));
2377 	make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2378 	make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2379 	make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2380     } else {
2381 	code = fill_triangle_wedge(pfs, p0, p1, &p01);
2382 	if (code < 0)
2383 	    return code;
2384 	code = fill_triangle_wedge(pfs, p1, p2, &p12);
2385 	if (code < 0)
2386 	    return code;
2387 	code = fill_triangle_wedge(pfs, p2, p0, &p20);
2388 	if (code < 0)
2389 	    return code;
2390     }
2391     code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2392     if (code < 0)
2393 	return code;
2394     if (LAZY_WEDGES) {
2395 	move_wedge(&L01, l01, true);
2396 	move_wedge(&L20, l20, false);
2397     }
2398     code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2399     if (code < 0)
2400 	return code;
2401     if (LAZY_WEDGES)
2402 	move_wedge(&L12, l12, true);
2403     code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2404     if (code < 0)
2405 	return code;
2406     L[0].last_side = L[1].last_side = L[2].last_side = true;
2407     code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2408     if (code < 0)
2409 	return code;
2410     if (LAZY_WEDGES) {
2411 	code = close_wedge_median(pfs, l01, &p0->c, &p1->c);
2412 	if (code < 0)
2413 	    return code;
2414 	code = close_wedge_median(pfs, l12, &p1->c, &p2->c);
2415 	if (code < 0)
2416 	    return code;
2417 	code = close_wedge_median(pfs, l20, &p2->c, &p0->c);
2418 	if (code < 0)
2419 	    return code;
2420 	code = terminate_wedge_vertex_list(pfs, &L[0], &p01.c, &p20.c);
2421 	if (code < 0)
2422 	    return code;
2423 	code = terminate_wedge_vertex_list(pfs, &L[1], &p12.c, &p01.c);
2424 	if (code < 0)
2425 	    return code;
2426 	code = terminate_wedge_vertex_list(pfs, &L[2], &p20.c, &p12.c);
2427 	if (code < 0)
2428 	    return code;
2429     }
2430     pfs->inside = inside_save;
2431     return 0;
2432 }
2433 
2434 private inline int
fill_triangle(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2,wedge_vertex_list_t * l01,wedge_vertex_list_t * l12,wedge_vertex_list_t * l20)2435 fill_triangle(patch_fill_state_t *pfs,
2436 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2437 	wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20)
2438 {
2439     fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2440     fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2441     fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2442     fixed sd1 = max(sd01, sd12);
2443     fixed sd = max(sd1, sd20);
2444     double cd = 0;
2445 
2446 #   if SKIP_TEST
2447 	dbg_triangle_cnt++;
2448 #   endif
2449     if (pfs->Function == NULL) {
2450     	double d01 = color_span(pfs, &p1->c, &p0->c);
2451 	double d12 = color_span(pfs, &p2->c, &p1->c);
2452 	double d20 = color_span(pfs, &p0->c, &p2->c);
2453 	double cd1 = max(d01, d12);
2454 
2455 	cd = max(cd1, d20);
2456     }
2457     return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2458 }
2459 
2460 private int
small_mesh_triangle(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2)2461 small_mesh_triangle(patch_fill_state_t *pfs,
2462 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2463 {
2464     int code;
2465     wedge_vertex_list_t l[3];
2466 
2467     init_wedge_vertex_list(l, count_of(l));
2468     code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2469     if (code < 0)
2470 	return code;
2471     code = terminate_wedge_vertex_list(pfs, &l[0], &p0->c, &p1->c);
2472     if (code < 0)
2473 	return code;
2474     code = terminate_wedge_vertex_list(pfs, &l[1], &p1->c, &p2->c);
2475     if (code < 0)
2476 	return code;
2477     return terminate_wedge_vertex_list(pfs, &l[2], &p2->c, &p0->c);
2478 }
2479 
2480 private int
mesh_triangle_rec(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2)2481 mesh_triangle_rec(patch_fill_state_t *pfs,
2482 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2483 {
2484     pfs->unlinear = !is_linear_color_applicable(pfs);
2485     if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
2486 	manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
2487 	manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
2488 	return small_mesh_triangle(pfs, p0, p1, p2);
2489     else {
2490 	/* Subdivide into 4 triangles with 3 triangle non-lazy wedges.
2491 	   Doing so against the wedge_vertex_list_elem_buffer overflow.
2492 	   We could apply a smarter method, dividing long sides
2493 	   with no wedges and short sides with lazy wedges.
2494 	   This needs to start wedges dynamically when
2495 	   a side becomes short. We don't do so because the
2496 	   number of checks per call significantly increases
2497 	   and the logics is complicated, but the performance
2498 	   advantage appears small due to big meshes are rare.
2499 	 */
2500 	shading_vertex_t p01, p12, p20;
2501 	int code;
2502 
2503 	divide_bar(pfs, p0, p1, 2, &p01);
2504 	divide_bar(pfs, p1, p2, 2, &p12);
2505 	divide_bar(pfs, p2, p0, 2, &p20);
2506 	code = fill_triangle_wedge(pfs, p0, p1, &p01);
2507 	if (code < 0)
2508 	    return code;
2509 	code = fill_triangle_wedge(pfs, p1, p2, &p12);
2510 	if (code < 0)
2511 	    return code;
2512 	code = fill_triangle_wedge(pfs, p2, p0, &p20);
2513 	if (code < 0)
2514 	    return code;
2515 	code = mesh_triangle_rec(pfs, p0, &p01, &p20);
2516 	if (code < 0)
2517 	    return code;
2518 	code = mesh_triangle_rec(pfs, p1, &p12, &p01);
2519 	if (code < 0)
2520 	    return code;
2521 	code = mesh_triangle_rec(pfs, p2, &p20, &p12);
2522 	if (code < 0)
2523 	    return code;
2524 	return mesh_triangle_rec(pfs, &p01, &p12, &p20);
2525     }
2526 }
2527 
2528 int
mesh_triangle(patch_fill_state_t * pfs,const shading_vertex_t * p0,const shading_vertex_t * p1,const shading_vertex_t * p2)2529 mesh_triangle(patch_fill_state_t *pfs,
2530 	const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2531 {
2532     if ((*dev_proc(pfs->dev, pattern_manage))(pfs->dev,
2533 	    gs_no_id, NULL, pattern_manage__shading_area) > 0) {
2534 	/* Inform the device with the shading coverage area.
2535 	   First compute the sign of the area, because
2536 	   all areas to be clipped in same direction. */
2537 	gx_device *pdev = pfs->dev;
2538 	gx_path path;
2539 	int code;
2540 	fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
2541 	fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
2542 	int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
2543 
2544 	gx_path_init_local(&path, pdev->memory);
2545 	code = gx_path_add_point(&path, p0->p.x, p0->p.y);
2546 	if (code >= 0 && s1 >= 0)
2547 	    code = gx_path_add_line(&path, p1->p.x, p1->p.y);
2548 	if (code >= 0)
2549 	    code = gx_path_add_line(&path, p2->p.x, p2->p.y);
2550 	if (code >= 0 && s1 < 0)
2551 	    code = gx_path_add_line(&path, p1->p.x, p1->p.y);
2552 	if (code >= 0)
2553 	    code = gx_path_close_subpath(&path);
2554 	if (code >= 0)
2555 	    code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
2556 	gx_path_free(&path, "mesh_triangle");
2557 	if (code < 0)
2558 	    return code;
2559     }
2560     return mesh_triangle_rec(pfs, p0, p1, p2);
2561 }
2562 
2563 private inline int
triangles4(patch_fill_state_t * pfs,const quadrangle_patch * p,bool dummy_argument)2564 triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
2565 {
2566     shading_vertex_t p0001, p1011, q;
2567     wedge_vertex_list_t l[4];
2568     int code;
2569 
2570     init_wedge_vertex_list(l, count_of(l));
2571     divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001);
2572     divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011);
2573     divide_bar(pfs, &p0001, &p1011, 2, &q);
2574     code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
2575     if (code < 0)
2576 	return code;
2577     l[0].last_side = true;
2578     l[3].last_side = true;
2579     code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
2580     if (code < 0)
2581 	return code;
2582     l[1].last_side = true;
2583     code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
2584     if (code < 0)
2585 	return code;
2586     l[2].last_side = true;
2587     code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
2588     if (code < 0)
2589 	return code;
2590     code = terminate_wedge_vertex_list(pfs, &l[0], &p->p[0][1]->c, &q.c);
2591     if (code < 0)
2592 	return code;
2593     code = terminate_wedge_vertex_list(pfs, &l[1], &p->p[1][1]->c, &q.c);
2594     if (code < 0)
2595 	return code;
2596     code = terminate_wedge_vertex_list(pfs, &l[2], &p->p[1][0]->c, &q.c);
2597     if (code < 0)
2598 	return code;
2599     code = terminate_wedge_vertex_list(pfs, &l[3], &q.c, &p->p[0][0]->c);
2600     if (code < 0)
2601 	return code;
2602     return 0;
2603 }
2604 
2605 private inline int
triangles2(patch_fill_state_t * pfs,const quadrangle_patch * p,bool dummy_argument)2606 triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
2607 {
2608     wedge_vertex_list_t l;
2609     int code;
2610 
2611     init_wedge_vertex_list(&l, 1);
2612     code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
2613     if (code < 0)
2614 	return code;
2615     l.last_side = true;
2616     code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
2617     if (code < 0)
2618 	return code;
2619     code = terminate_wedge_vertex_list(pfs, &l, &p->p[1][1]->c, &p->p[0][0]->c);
2620     if (code < 0)
2621 	return code;
2622     return 0;
2623 }
2624 
2625 private inline void
make_quadrangle(const tensor_patch * p,shading_vertex_t qq[2][2],wedge_vertex_list_t l[4],quadrangle_patch * q)2626 make_quadrangle(const tensor_patch *p, shading_vertex_t qq[2][2],
2627 	wedge_vertex_list_t l[4], quadrangle_patch *q)
2628 {
2629     qq[0][0].p = p->pole[0][0];
2630     qq[0][1].p = p->pole[0][3];
2631     qq[1][0].p = p->pole[3][0];
2632     qq[1][1].p = p->pole[3][3];
2633     qq[0][0].c = p->c[0][0];
2634     qq[0][1].c = p->c[0][1];
2635     qq[1][0].c = p->c[1][0];
2636     qq[1][1].c = p->c[1][1];
2637     q->p[0][0] = &qq[0][0];
2638     q->p[0][1] = &qq[0][1];
2639     q->p[1][0] = &qq[1][0];
2640     q->p[1][1] = &qq[1][1];
2641     q->l0001 = &l[0];
2642     q->l0111 = &l[1];
2643     q->l1110 = &l[2];
2644     q->l1000 = &l[3];
2645 }
2646 
2647 private inline int
is_quadrangle_color_linear_by_u(const patch_fill_state_t * pfs,const quadrangle_patch * p)2648 is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
2649 {   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
2650     int code;
2651 
2652     code = is_color_linear(pfs, &p->p[0][0]->c, &p->p[0][1]->c);
2653     if (code <= 0)
2654 	return code;
2655     return is_color_linear(pfs, &p->p[1][0]->c, &p->p[1][1]->c);
2656 }
2657 
2658 private inline int
is_quadrangle_color_linear_by_v(const patch_fill_state_t * pfs,const quadrangle_patch * p)2659 is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
2660 {   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
2661     int code;
2662 
2663     code = is_color_linear(pfs, &p->p[0][0]->c, &p->p[1][0]->c);
2664     if (code <= 0)
2665 	return code;
2666     return is_color_linear(pfs, &p->p[0][1]->c, &p->p[1][1]->c);
2667 }
2668 
2669 private inline int
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t * pfs,const quadrangle_patch * p)2670 is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
2671 {   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
2672     int code;
2673 
2674     code = is_color_linear(pfs, &p->p[0][0]->c, &p->p[1][1]->c);
2675     if (code <= 0)
2676 	return code;
2677     return is_color_linear(pfs, &p->p[0][1]->c, &p->p[1][0]->c);
2678 }
2679 
2680 typedef enum {
2681     color_change_small,
2682     color_change_gradient,
2683     color_change_linear,
2684     color_change_bilinear,
2685     color_change_general
2686 } color_change_type_t;
2687 
2688 private inline color_change_type_t
quadrangle_color_change(const patch_fill_state_t * pfs,const quadrangle_patch * p,bool is_big_u,bool is_big_v,bool * divide_u,bool * divide_v)2689 quadrangle_color_change(const patch_fill_state_t *pfs, const quadrangle_patch *p,
2690 			bool is_big_u, bool is_big_v, bool *divide_u, bool *divide_v)
2691 {
2692     patch_color_t d0001, d1011, d;
2693     double D, D0001, D1011, D0010, D0111, D0011, D0110;
2694     double Du, Dv;
2695 
2696     color_diff(pfs, &p->p[0][0]->c, &p->p[0][1]->c, &d0001);
2697     color_diff(pfs, &p->p[1][0]->c, &p->p[1][1]->c, &d1011);
2698     D0001 = color_norm(pfs, &d0001);
2699     D1011 = color_norm(pfs, &d1011);
2700     D0010 = color_span(pfs, &p->p[0][0]->c, &p->p[1][0]->c);
2701     D0111 = color_span(pfs, &p->p[0][1]->c, &p->p[1][1]->c);
2702     D0011 = color_span(pfs, &p->p[0][0]->c, &p->p[1][1]->c);
2703     D0110 = color_span(pfs, &p->p[0][1]->c, &p->p[1][0]->c);
2704     if (pfs->unlinear) {
2705 	if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
2706 	    D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
2707 	    D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
2708 	    return color_change_small;
2709 	if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
2710 	    if (!is_big_v) {
2711 		/* The color function looks uncontiguous. */
2712 		return color_change_small;
2713 	    }
2714 	    *divide_v = true;
2715 	    return color_change_gradient;
2716 	}
2717 	if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
2718 	    if (!is_big_u) {
2719 		/* The color function looks uncontiguous. */
2720 		return color_change_small;
2721 	    }
2722 	    *divide_u = true;
2723 	    return color_change_gradient;
2724 	}
2725     }
2726     color_diff(pfs, &d0001, &d1011, &d);
2727     Du = max(D0001, D1011);
2728     Dv = max(D0010, D0111);
2729     if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
2730 	return color_change_small;
2731     if (Du <= pfs->smoothness / 8)
2732 	return color_change_linear;
2733     if (Dv <= pfs->smoothness / 8)
2734 	return color_change_linear;
2735     D = color_norm(pfs, &d);
2736     if (D <= pfs->smoothness)
2737 	return color_change_bilinear;
2738 #if 0 /* Disabled due to a 0.5% slowdown with the test file of the Bug 687948. */
2739     if (Du > Dv && is_big_u)
2740 	*divide_u = true;
2741     else if (Du < Dv && is_big_v)
2742 	*divide_v = true;
2743     else if (is_big_u)
2744 	*divide_u = true;
2745     else if (is_big_v)
2746 	*divide_v = true;
2747     else {
2748 	/* The color function looks uncontiguous. */
2749 	return color_change_small;
2750     }
2751 #else
2752     if (Du > Dv)
2753 	*divide_u = true;
2754     else
2755 	*divide_v = true;
2756 #endif
2757     return color_change_general;
2758 }
2759 
2760 private int
fill_quadrangle(patch_fill_state_t * pfs,const quadrangle_patch * p,bool big,int level)2761 fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big, int level)
2762 {
2763     /* The quadrangle is flattened enough by V and U, so ignore inner poles. */
2764     /* Assuming the XY span is restricted with curve_samples.
2765        It is important for intersection_of_small_bars to compute faster. */
2766     quadrangle_patch s0, s1;
2767     wedge_vertex_list_t l0, l1, l2;
2768     int code;
2769     bool divide_u = false, divide_v = false, big1 = big;
2770     shading_vertex_t q[2];
2771     bool monotonic_color_save = pfs->monotonic_color;
2772     bool linear_color_save = pfs->linear_color;
2773     bool inside_save = pfs->inside;
2774     gs_fixed_rect r, r1;
2775     /* Warning : pfs->monotonic_color is not restored on error. */
2776 
2777     if (level > 100)
2778 	return_error(gs_error_unregistered); /* Safety. */
2779     if (!pfs->inside) {
2780 	bbox_of_points(&r, &p->p[0][0]->p, &p->p[0][1]->p, &p->p[1][0]->p, &p->p[1][1]->p);
2781 	r1 = r;
2782 	rect_intersect(r, pfs->rect);
2783 	if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2784 	    return 0; /* Outside. */
2785     }
2786     if (big) {
2787 	/* Likely 'big' is an unuseful rudiment due to curve_samples
2788 	   restricts lengthes. We keep it for a while because its implementation
2789 	   isn't obvious and its time consumption is invisibly small.
2790 	 */
2791 	fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
2792 			       any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
2793 			   max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
2794 			       any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
2795 	fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
2796 			       any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
2797 			   max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
2798 			       any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
2799 
2800 	if (QUADRANGLES && pfs->maybe_self_intersecting) {
2801 	    if (size_v > pfs->max_small_coord) {
2802 		/* constant_color_quadrangle can't handle big self-intersecting areas
2803 		   because we don't want int64_t in it. */
2804 		divide_v = true;
2805 	    } else if (size_u > pfs->max_small_coord) {
2806 		/* constant_color_quadrangle can't handle big self-intersecting areas,
2807 		   because we don't want int64_t in it. */
2808 		divide_u = true;
2809 	    } else
2810 		big1 = false;
2811 	} else
2812 	    big1 = false;
2813     }
2814     if (!big1) {
2815 	bool is_big_u = false, is_big_v = false;
2816 	double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
2817 	double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
2818 	double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
2819 	double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
2820 	double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
2821 	double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
2822 	double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
2823 	double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
2824 
2825 	if (d0001x > fixed_1 || d1011x > fixed_1 || d0001y > fixed_1 || d1011y > fixed_1)
2826 	    is_big_u = true;
2827 	if (d0010x > fixed_1 || d0111x > fixed_1 || d0010y > fixed_1 || d0111y > fixed_1)
2828 	    is_big_v = true;
2829 	else if (!is_big_u)
2830 	    return (QUADRANGLES || !pfs->maybe_self_intersecting ?
2831 			constant_color_quadrangle : triangles4)(pfs, p,
2832 			    pfs->maybe_self_intersecting);
2833 	if (!pfs->monotonic_color) {
2834 	    bool not_monotonic_by_u = false, not_monotonic_by_v = false;
2835 
2836 	    code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
2837 	    if (code < 0)
2838 		return code;
2839 	    if (is_big_u)
2840 		divide_u = not_monotonic_by_u;
2841 	    if (is_big_v)
2842 		divide_v = not_monotonic_by_v;
2843 	    if (!divide_u && !divide_v)
2844 		pfs->monotonic_color = true;
2845 	}
2846 	if (pfs->monotonic_color && !pfs->linear_color) {
2847 	    if (divide_v && divide_u) {
2848 		if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y)
2849 		    divide_v = false;
2850 		else
2851 		    divide_u = false;
2852 	    } else if (!divide_u && !divide_v && !pfs->unlinear) {
2853 		if (is_big_u) {
2854 		    code = is_quadrangle_color_linear_by_u(pfs, p);
2855 		    if (code < 0)
2856 			return code;
2857 		    divide_u = !code;
2858 		}
2859 		if (is_big_v) {
2860 		    code = is_quadrangle_color_linear_by_v(pfs, p);
2861 		    if (code < 0)
2862 			return code;
2863 		    divide_v = !code;
2864 		}
2865 		if (is_big_u && is_big_v) {
2866 		    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
2867 		    if (code < 0)
2868 			return code;
2869 		    if (!code) {
2870 			if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) {
2871 			    divide_u = true;
2872 			    divide_v = false;
2873 			} else {
2874 			    divide_v = true;
2875 			    divide_u = false;
2876 			}
2877 		    }
2878 		}
2879 	    }
2880 	    if (!divide_u && !divide_v)
2881 		pfs->linear_color = true;
2882 	}
2883 	if (!pfs->linear_color) {
2884 	    /* go to divide. */
2885 	} else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, &divide_u, &divide_v)) {
2886 	    case color_change_small:
2887 		code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
2888 			    constant_color_quadrangle : triangles4)(pfs, p,
2889 				pfs->maybe_self_intersecting);
2890 		pfs->monotonic_color = monotonic_color_save;
2891 		pfs->linear_color = linear_color_save;
2892 		return code;
2893 	    case color_change_bilinear:
2894 		if (!QUADRANGLES) {
2895 		    code = triangles4(pfs, p, true);
2896 		    pfs->monotonic_color = monotonic_color_save;
2897 		    pfs->linear_color = linear_color_save;
2898 		    return code;
2899 		}
2900 	    case color_change_linear:
2901 		if (!QUADRANGLES) {
2902 		    code = triangles2(pfs, p, true);
2903 		    pfs->monotonic_color = monotonic_color_save;
2904 		    pfs->linear_color = linear_color_save;
2905 		    return code;
2906 		}
2907 	    case color_change_gradient:
2908 	    case color_change_general:
2909 		; /* goto divide. */
2910 	}
2911     }
2912     if (!pfs->inside) {
2913 	if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2914 	    r.q.x == r1.q.x && r.q.y == r1.q.y)
2915 	    pfs->inside = true;
2916     }
2917     if (LAZY_WEDGES)
2918 	init_wedge_vertex_list(&l0, 1);
2919     if (divide_v) {
2920 	divide_quadrangle_by_v(pfs, &s0, &s1, q, p);
2921 	if (LAZY_WEDGES) {
2922 	    make_wedge_median(pfs, &l1, p->l0111, true,  &p->p[0][1]->p, &p->p[1][1]->p, &s0.p[1][1]->p);
2923 	    make_wedge_median(pfs, &l2, p->l1000, false, &p->p[1][0]->p, &p->p[0][0]->p, &s0.p[1][0]->p);
2924 	    s0.l1110 = s1.l0001 = &l0;
2925 	    s0.l0111 = s1.l0111 = &l1;
2926 	    s0.l1000 = s1.l1000 = &l2;
2927 	    s0.l0001 = p->l0001;
2928 	    s1.l1110 = p->l1110;
2929 	} else {
2930 	    code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[1][0], s0.p[1][0]);
2931 	    if (code < 0)
2932 		return code;
2933 	    code = fill_triangle_wedge(pfs, s0.p[0][1], s1.p[1][1], s0.p[1][1]);
2934 	    if (code < 0)
2935 		return code;
2936 	}
2937 	code = fill_quadrangle(pfs, &s0, big, level + 1);
2938 	if (code < 0)
2939 	    return code;
2940 	if (LAZY_WEDGES) {
2941 	    l0.last_side = true;
2942 	    move_wedge(&l1, p->l0111, true);
2943 	    move_wedge(&l2, p->l1000, false);
2944 	}
2945 	code = fill_quadrangle(pfs, &s1, big1, level + 1);
2946 	if (LAZY_WEDGES) {
2947 	    if (code < 0)
2948 		return code;
2949 	    code = close_wedge_median(pfs, p->l0111, &p->p[0][1]->c, &p->p[1][1]->c);
2950 	    if (code < 0)
2951 		return code;
2952 	    code = close_wedge_median(pfs, p->l1000, &p->p[1][0]->c, &p->p[0][0]->c);
2953 	    if (code < 0)
2954 		return code;
2955 	    code = terminate_wedge_vertex_list(pfs, &l0, &s0.p[1][0]->c, &s0.p[1][1]->c);
2956 	}
2957     } else if (divide_u) {
2958 	divide_quadrangle_by_u(pfs, &s0, &s1, q, p);
2959 	if (LAZY_WEDGES) {
2960 	    make_wedge_median(pfs, &l1, p->l0001, true,  &p->p[0][0]->p, &p->p[0][1]->p, &s0.p[0][1]->p);
2961 	    make_wedge_median(pfs, &l2, p->l1110, false, &p->p[1][1]->p, &p->p[1][0]->p, &s0.p[1][1]->p);
2962 	    s0.l0111 = s1.l1000 = &l0;
2963 	    s0.l0001 = s1.l0001 = &l1;
2964 	    s0.l1110 = s1.l1110 = &l2;
2965 	    s0.l1000 = p->l1000;
2966 	    s1.l0111 = p->l0111;
2967 	} else {
2968 	    code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[0][1], s0.p[0][1]);
2969 	    if (code < 0)
2970 		return code;
2971 	    code = fill_triangle_wedge(pfs, s0.p[1][0], s1.p[1][1], s0.p[1][1]);
2972 	    if (code < 0)
2973 		return code;
2974 	}
2975 	code = fill_quadrangle(pfs, &s0, big1, level + 1);
2976 	if (code < 0)
2977 	    return code;
2978 	if (LAZY_WEDGES) {
2979 	    l0.last_side = true;
2980 	    move_wedge(&l1, p->l0001, true);
2981 	    move_wedge(&l2, p->l1110, false);
2982 	}
2983 	code = fill_quadrangle(pfs, &s1, big1, level + 1);
2984 	if (LAZY_WEDGES) {
2985 	    if (code < 0)
2986 		return code;
2987 	    code = close_wedge_median(pfs, p->l0001, &p->p[0][0]->c, &p->p[0][1]->c);
2988 	    if (code < 0)
2989 		return code;
2990 	    code = close_wedge_median(pfs, p->l1110, &p->p[1][1]->c, &p->p[1][0]->c);
2991 	    if (code < 0)
2992 		return code;
2993 	    code = terminate_wedge_vertex_list(pfs, &l0, &s0.p[0][1]->c, &s0.p[1][1]->c);
2994 	}
2995     } else
2996 	code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
2997 		    constant_color_quadrangle : triangles4)(pfs, p,
2998 			pfs->maybe_self_intersecting);
2999     pfs->monotonic_color = monotonic_color_save;
3000     pfs->linear_color = linear_color_save;
3001     pfs->inside = inside_save;
3002     return code;
3003 }
3004 
3005 
3006 
3007 private inline void
split_stripe(patch_fill_state_t * pfs,tensor_patch * s0,tensor_patch * s1,const tensor_patch * p)3008 split_stripe(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p)
3009 {
3010     split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3011     split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3012     split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3013     split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3014     s0->c[0][0] = p->c[0][0];
3015     s0->c[1][0] = p->c[1][0];
3016     patch_interpolate_color(&s0->c[0][1], &p->c[0][0], &p->c[0][1], pfs, 0.5);
3017     patch_interpolate_color(&s0->c[1][1], &p->c[1][0], &p->c[1][1], pfs, 0.5);
3018     s1->c[0][0] = s0->c[0][1];
3019     s1->c[1][0] = s0->c[1][1];
3020     s1->c[0][1] = p->c[0][1];
3021     s1->c[1][1] = p->c[1][1];
3022 }
3023 
3024 private inline void
split_patch(patch_fill_state_t * pfs,tensor_patch * s0,tensor_patch * s1,const tensor_patch * p)3025 split_patch(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p)
3026 {
3027     split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3028     split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3029     split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3030     split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3031     s0->c[0][0] = p->c[0][0];
3032     s0->c[0][1] = p->c[0][1];
3033     patch_interpolate_color(&s0->c[1][0], &p->c[0][0], &p->c[1][0], pfs, 0.5);
3034     patch_interpolate_color(&s0->c[1][1], &p->c[0][1], &p->c[1][1], pfs, 0.5);
3035     s1->c[0][0] = s0->c[1][0];
3036     s1->c[0][1] = s0->c[1][1];
3037     s1->c[1][0] = p->c[1][0];
3038     s1->c[1][1] = p->c[1][1];
3039 }
3040 
3041 private int
decompose_stripe(patch_fill_state_t * pfs,const tensor_patch * p,int ku)3042 decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3043 {
3044     if (ku > 1) {
3045 	tensor_patch s0, s1;
3046 	int code;
3047 
3048 	split_stripe(pfs, &s0, &s1, p);
3049 	if (0) { /* Debug purpose only. */
3050 	    draw_patch(&s0, true, RGB(0, 128, 128));
3051 	    draw_patch(&s1, true, RGB(0, 128, 128));
3052 	}
3053 	code = decompose_stripe(pfs, &s0, ku / 2);
3054 	if (code < 0)
3055 	    return code;
3056 	return decompose_stripe(pfs, &s1, ku / 2);
3057     } else {
3058 	quadrangle_patch q;
3059 	shading_vertex_t qq[2][2];
3060 	wedge_vertex_list_t l[4];
3061 	int code;
3062 
3063 	init_wedge_vertex_list(l, count_of(l));
3064 	make_quadrangle(p, qq, l, &q);
3065 #	if SKIP_TEST
3066 	    dbg_quad_cnt++;
3067 #	endif
3068 	code = fill_quadrangle(pfs, &q, true, 0);
3069 	if (LAZY_WEDGES) {
3070 	    code = terminate_wedge_vertex_list(pfs, &l[0], &q.p[0][0]->c, &q.p[0][1]->c);
3071 	    if (code < 0)
3072 		return code;
3073 	    code = terminate_wedge_vertex_list(pfs, &l[1], &q.p[0][1]->c, &q.p[1][1]->c);
3074 	    if (code < 0)
3075 		return code;
3076 	    code = terminate_wedge_vertex_list(pfs, &l[2], &q.p[1][1]->c, &q.p[1][0]->c);
3077 	    if (code < 0)
3078 		return code;
3079 	    code = terminate_wedge_vertex_list(pfs, &l[3], &q.p[1][0]->c, &q.p[0][1]->c);
3080 	    if (code < 0)
3081 		return code;
3082 	}
3083 	return code;
3084     }
3085 }
3086 
3087 private int
fill_stripe(patch_fill_state_t * pfs,const tensor_patch * p)3088 fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3089 {
3090     /* The stripe is flattened enough by V, so ignore inner poles. */
3091     int ku[4], kum, code;
3092 
3093     /* We would like to apply iterations for enumerating the kum curve parts,
3094        but the roundinmg errors would be too complicated due to
3095        the dependence on the direction. Note that neigbour
3096        patches may use the opposite direction for same bounding curve.
3097        We apply the recursive dichotomy, in which
3098        the rounding errors do not depend on the direction. */
3099     ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3100     ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3101     kum = max(ku[0], ku[3]);
3102     code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, &p->c[0][0], &p->c[0][1], inpatch_wedge);
3103     if (code < 0)
3104 	return code;
3105     if (INTERPATCH_PADDING) {
3106 	vd_bar(p->pole[0][0].x, p->pole[0][0].y, p->pole[3][0].x, p->pole[3][0].y, 0, RGB(255, 0, 0));
3107 	code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], &p->c[0][0], &p->c[1][0]);
3108 	if (code < 0)
3109 	    return code;
3110 	vd_bar(p->pole[0][3].x, p->pole[0][3].y, p->pole[3][3].x, p->pole[3][3].y, 0, RGB(255, 0, 0));
3111 	code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], &p->c[0][1], &p->c[1][1]);
3112 	if (code < 0)
3113 	    return code;
3114     }
3115     code = decompose_stripe(pfs, p, kum);
3116     if (code < 0)
3117 	return code;
3118     return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, &p->c[1][0], &p->c[1][1], inpatch_wedge);
3119 }
3120 
3121 private inline bool
is_curve_x_monotonic(const gs_fixed_point * pole,int pole_step)3122 is_curve_x_monotonic(const gs_fixed_point *pole, int pole_step)
3123 {   /* true = monotonic, false = don't know. */
3124     return (pole[0 * pole_step].x <= pole[1 * pole_step].x &&
3125 	    pole[1 * pole_step].x <= pole[2 * pole_step].x &&
3126 	    pole[2 * pole_step].x <= pole[3 * pole_step].x) ||
3127 	   (pole[0 * pole_step].x >= pole[1 * pole_step].x &&
3128 	    pole[1 * pole_step].x >= pole[2 * pole_step].x &&
3129 	    pole[2 * pole_step].x >= pole[3 * pole_step].x);
3130 }
3131 
3132 private inline bool
is_curve_y_monotonic(const gs_fixed_point * pole,int pole_step)3133 is_curve_y_monotonic(const gs_fixed_point *pole, int pole_step)
3134 {   /* true = monotonic, false = don't know. */
3135     return (pole[0 * pole_step].y <= pole[1 * pole_step].y &&
3136 	    pole[1 * pole_step].y <= pole[2 * pole_step].y &&
3137 	    pole[2 * pole_step].y <= pole[3 * pole_step].y) ||
3138 	   (pole[0 * pole_step].y >= pole[1 * pole_step].y &&
3139 	    pole[1 * pole_step].y >= pole[2 * pole_step].y &&
3140 	    pole[2 * pole_step].y >= pole[3 * pole_step].y);
3141 }
3142 
neqs(int * a,int b)3143 private inline bool neqs(int *a, int b)
3144 {   /* Unequal signs. Assuming -1, 0, 1 only. */
3145     if (*a * b < 0)
3146 	return true;
3147     if (!*a)
3148 	*a = b;
3149     return false;
3150 }
3151 
3152 private inline int
vector_pair_orientation(const gs_fixed_point * p0,const gs_fixed_point * p1,const gs_fixed_point * p2)3153 vector_pair_orientation(const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *p2)
3154 {   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3155     fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3156     int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3157 
3158     return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3159 }
3160 
3161 private inline bool
is_x_bended(const tensor_patch * p)3162 is_x_bended(const tensor_patch *p)
3163 {
3164     int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3165 
3166     if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3167 	return true;
3168     if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3169 	return true;
3170     if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3171 	return true;
3172 
3173     if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3174 	return true;
3175     if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3176 	return true;
3177     if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3178 	return true;
3179     if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3180 	return true;
3181 
3182     if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3183 	return true;
3184     if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3185 	return true;
3186     if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3187 	return true;
3188     if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3189 	return true;
3190 
3191     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3192 	return true;
3193     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3194 	return true;
3195     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3196 	return true;
3197     if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3198 	return true;
3199     return false;
3200 }
3201 
3202 private inline bool
is_y_bended(const tensor_patch * p)3203 is_y_bended(const tensor_patch *p)
3204 {
3205     int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3206 
3207     if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3208 	return true;
3209     if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3210 	return true;
3211     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3212 	return true;
3213 
3214     if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3215 	return true;
3216     if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3217 	return true;
3218     if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3219 	return true;
3220     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3221 	return true;
3222 
3223     if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3224 	return true;
3225     if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3226 	return true;
3227     if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3228 	return true;
3229     if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3230 	return true;
3231 
3232     if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3233 	return true;
3234     if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3235 	return true;
3236     if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3237 	return true;
3238     if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3239 	return true;
3240     return false;
3241 }
3242 
3243 private inline bool
is_curve_x_small(const gs_fixed_point * pole,int pole_step,fixed fixed_flat)3244 is_curve_x_small(const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3245 {   /* Is curve within a single pixel, or smaller than half pixel ? */
3246     fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3247     fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3248     fixed xmin =  min(xmin0, xmin1);
3249     fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3250     fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3251     fixed xmax =  max(xmax0, xmax1);
3252 
3253     if(xmax - xmin <= fixed_1)
3254 	return true;
3255     return false;
3256 }
3257 
3258 private inline bool
is_curve_y_small(const gs_fixed_point * pole,int pole_step,fixed fixed_flat)3259 is_curve_y_small(const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3260 {   /* Is curve within a single pixel, or smaller than half pixel ? */
3261     fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3262     fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3263     fixed ymin =  min(ymin0, ymin1);
3264     fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3265     fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3266     fixed ymax =  max(ymax0, ymax1);
3267 
3268     if (ymax - ymin <= fixed_1)
3269 	return true;
3270     return false;
3271 }
3272 
3273 private inline bool
is_patch_narrow(const patch_fill_state_t * pfs,const tensor_patch * p)3274 is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3275 {
3276     if (!is_curve_x_small(&p->pole[0][0], 4, pfs->fixed_flat))
3277 	return false;
3278     if (!is_curve_x_small(&p->pole[0][1], 4, pfs->fixed_flat))
3279 	return false;
3280     if (!is_curve_x_small(&p->pole[0][2], 4, pfs->fixed_flat))
3281 	return false;
3282     if (!is_curve_x_small(&p->pole[0][3], 4, pfs->fixed_flat))
3283 	return false;
3284     if (!is_curve_y_small(&p->pole[0][0], 4, pfs->fixed_flat))
3285 	return false;
3286     if (!is_curve_y_small(&p->pole[0][1], 4, pfs->fixed_flat))
3287 	return false;
3288     if (!is_curve_y_small(&p->pole[0][2], 4, pfs->fixed_flat))
3289 	return false;
3290     if (!is_curve_y_small(&p->pole[0][3], 4, pfs->fixed_flat))
3291 	return false;
3292     return true;
3293 }
3294 
3295 private int
fill_patch(patch_fill_state_t * pfs,const tensor_patch * p,int kv,int kv0,int kv1)3296 fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3297 {
3298     if (kv <= 1) {
3299 	if (is_patch_narrow(pfs, p))
3300 	    return fill_stripe(pfs, p);
3301 	if (!is_x_bended(p))
3302 	    return fill_stripe(pfs, p);
3303     }
3304     {	tensor_patch s0, s1;
3305         shading_vertex_t q0, q1, q2;
3306 	int code;
3307 
3308 	split_patch(pfs, &s0, &s1, p);
3309 	if (kv0 <= 1) {
3310 	    q0.p = s0.pole[0][0];
3311 	    q0.c = s0.c[0][0];
3312 	    q1.p = s1.pole[3][0];
3313 	    q1.c = s1.c[1][0];
3314 	    q2.p = s0.pole[3][0];
3315 	    q2.c = s0.c[1][0];
3316 	    code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3317 	    if (code < 0)
3318 		return code;
3319 	}
3320 	if (kv1 <= 1) {
3321 	    q0.p = s0.pole[0][3];
3322 	    q0.c = s0.c[0][1];
3323 	    q1.p = s1.pole[3][3];
3324 	    q1.c = s1.c[1][1];
3325 	    q2.p = s0.pole[3][3];
3326 	    q2.c = s0.c[1][1];
3327 	    code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3328 	    if (code < 0)
3329 		return code;
3330 	}
3331 	code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
3332 	if (code < 0)
3333 	    return code;
3334 	return fill_patch(pfs, &s1, kv / 2, kv0 / 2, kv1 / 2);
3335 	/* fixme : To privide the precise filling order, we must
3336 	   decompose left and right wedges into pieces by intersections
3337 	   with stripes, and fill each piece with its stripe.
3338 	   A lazy wedge list would be fine for storing
3339 	   the necessary information.
3340 
3341 	   If the patch is created from a radial shading,
3342 	   the wedge color appears a constant, so the filling order
3343 	   isn't important. The order is important for other
3344 	   self-overlapping patches, but the visible effect is
3345 	   just a slight norrowing the patch (as its lower layer appears
3346 	   visible through the upper layer near the side).
3347 	   This kind of dropout isn't harmful, because
3348 	   contacring self-overlapping patches are painted
3349 	   one after one by definition, so that a side coverage break
3350 	   appears unavoidable by definition.
3351 
3352 	   Delaying this improvement because it is low important.
3353 	 */
3354     }
3355 }
3356 
3357 private inline fixed
lcp1(fixed p0,fixed p3)3358 lcp1(fixed p0, fixed p3)
3359 {   /* Computing the 1st pole of a 3d order besier, which applears a line. */
3360     return (p0 + p0 + p3) / 3;
3361 }
3362 private inline fixed
lcp2(fixed p0,fixed p3)3363 lcp2(fixed p0, fixed p3)
3364 {   /* Computing the 2nd pole of a 3d order besier, which applears a line. */
3365     return (p0 + p3 + p3) / 3;
3366 }
3367 
3368 private void
patch_set_color(const patch_fill_state_t * pfs,patch_color_t * c,const float * cc)3369 patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
3370 {
3371     if (pfs->Function) {
3372 	c->t[0] = cc[0];
3373 	c->t[1] = cc[1];
3374     } else
3375 	memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
3376 }
3377 
3378 private void
make_tensor_patch(const patch_fill_state_t * pfs,tensor_patch * p,const patch_curve_t curve[4],const gs_fixed_point interior[4])3379 make_tensor_patch(const patch_fill_state_t *pfs, tensor_patch *p, const patch_curve_t curve[4],
3380 	   const gs_fixed_point interior[4])
3381 {
3382     const gs_color_space *pcs = pfs->direct_space;
3383 
3384     p->pole[0][0] = curve[0].vertex.p;
3385     p->pole[1][0] = curve[0].control[0];
3386     p->pole[2][0] = curve[0].control[1];
3387     p->pole[3][0] = curve[1].vertex.p;
3388     p->pole[3][1] = curve[1].control[0];
3389     p->pole[3][2] = curve[1].control[1];
3390     p->pole[3][3] = curve[2].vertex.p;
3391     p->pole[2][3] = curve[2].control[0];
3392     p->pole[1][3] = curve[2].control[1];
3393     p->pole[0][3] = curve[3].vertex.p;
3394     p->pole[0][2] = curve[3].control[0];
3395     p->pole[0][1] = curve[3].control[1];
3396     if (interior != NULL) {
3397 	p->pole[1][1] = interior[0];
3398 	p->pole[1][2] = interior[1];
3399 	p->pole[2][2] = interior[2];
3400 	p->pole[2][1] = interior[3];
3401     } else {
3402 	p->pole[1][1].x = lcp1(p->pole[0][1].x, p->pole[3][1].x) +
3403 			  lcp1(p->pole[1][0].x, p->pole[1][3].x) -
3404 			  lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
3405 			       lcp1(p->pole[3][0].x, p->pole[3][3].x));
3406 	p->pole[1][2].x = lcp1(p->pole[0][2].x, p->pole[3][2].x) +
3407 			  lcp2(p->pole[1][0].x, p->pole[1][3].x) -
3408 			  lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
3409 			       lcp2(p->pole[3][0].x, p->pole[3][3].x));
3410 	p->pole[2][1].x = lcp2(p->pole[0][1].x, p->pole[3][1].x) +
3411 			  lcp1(p->pole[2][0].x, p->pole[2][3].x) -
3412 			  lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
3413 			       lcp1(p->pole[3][0].x, p->pole[3][3].x));
3414 	p->pole[2][2].x = lcp2(p->pole[0][2].x, p->pole[3][2].x) +
3415 			  lcp2(p->pole[2][0].x, p->pole[2][3].x) -
3416 			  lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
3417 			       lcp2(p->pole[3][0].x, p->pole[3][3].x));
3418 
3419 	p->pole[1][1].y = lcp1(p->pole[0][1].y, p->pole[3][1].y) +
3420 			  lcp1(p->pole[1][0].y, p->pole[1][3].y) -
3421 			  lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
3422 			       lcp1(p->pole[3][0].y, p->pole[3][3].y));
3423 	p->pole[1][2].y = lcp1(p->pole[0][2].y, p->pole[3][2].y) +
3424 			  lcp2(p->pole[1][0].y, p->pole[1][3].y) -
3425 			  lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
3426 			       lcp2(p->pole[3][0].y, p->pole[3][3].y));
3427 	p->pole[2][1].y = lcp2(p->pole[0][1].y, p->pole[3][1].y) +
3428 			  lcp1(p->pole[2][0].y, p->pole[2][3].y) -
3429 			  lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
3430 			       lcp1(p->pole[3][0].y, p->pole[3][3].y));
3431 	p->pole[2][2].y = lcp2(p->pole[0][2].y, p->pole[3][2].y) +
3432 			  lcp2(p->pole[2][0].y, p->pole[2][3].y) -
3433 			  lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
3434 			       lcp2(p->pole[3][0].y, p->pole[3][3].y));
3435     }
3436     patch_set_color(pfs, &p->c[0][0], curve[0].vertex.cc);
3437     patch_set_color(pfs, &p->c[1][0], curve[1].vertex.cc);
3438     patch_set_color(pfs, &p->c[1][1], curve[2].vertex.cc);
3439     patch_set_color(pfs, &p->c[0][1], curve[3].vertex.cc);
3440     patch_resolve_color_inline(&p->c[0][0], pfs);
3441     patch_resolve_color_inline(&p->c[0][1], pfs);
3442     patch_resolve_color_inline(&p->c[1][0], pfs);
3443     patch_resolve_color_inline(&p->c[1][1], pfs);
3444     if (!pfs->Function) {
3445 	pcs->type->restrict_color(&p->c[0][0].cc, pcs);
3446 	pcs->type->restrict_color(&p->c[0][1].cc, pcs);
3447 	pcs->type->restrict_color(&p->c[1][0].cc, pcs);
3448 	pcs->type->restrict_color(&p->c[1][1].cc, pcs);
3449     }
3450 }
3451 
3452 int
gx_shade_background(gx_device * pdev,const gs_fixed_rect * rect,const gx_device_color * pdevc,gs_logical_operation_t log_op)3453 gx_shade_background(gx_device *pdev, const gs_fixed_rect *rect,
3454 	const gx_device_color *pdevc, gs_logical_operation_t log_op)
3455 {
3456     gs_fixed_edge le, re;
3457 
3458     le.start.x = rect->p.x - INTERPATCH_PADDING;
3459     le.start.y = rect->p.y - INTERPATCH_PADDING;
3460     le.end.x = rect->p.x - INTERPATCH_PADDING;
3461     le.end.y = rect->q.y + INTERPATCH_PADDING;
3462     re.start.x = rect->q.x + INTERPATCH_PADDING;
3463     re.start.y = rect->p.y - INTERPATCH_PADDING;
3464     re.end.x = rect->q.x + INTERPATCH_PADDING;
3465     re.end.y = rect->q.y + INTERPATCH_PADDING;
3466     return dev_proc(pdev, fill_trapezoid)(pdev,
3467 	    &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
3468 }
3469 
3470 
3471 int
patch_fill(patch_fill_state_t * pfs,const patch_curve_t curve[4],const gs_fixed_point interior[4],void (* transform)(gs_fixed_point *,const patch_curve_t[4],const gs_fixed_point[4],floatp,floatp))3472 patch_fill(patch_fill_state_t *pfs, const patch_curve_t curve[4],
3473 	   const gs_fixed_point interior[4],
3474 	   void (*transform) (gs_fixed_point *, const patch_curve_t[4],
3475 			      const gs_fixed_point[4], floatp, floatp))
3476 {
3477     tensor_patch p;
3478     int kv[4], kvm, ku[4], kum, km;
3479     int code = 0;
3480 
3481 #if SKIP_TEST
3482     dbg_patch_cnt++;
3483     /*if (dbg_patch_cnt != 67 && dbg_patch_cnt != 78)
3484 	return 0;*/
3485 #endif
3486     /* We decompose the patch into tiny quadrangles,
3487        possibly inserting wedges between them against a dropout. */
3488     make_tensor_patch(pfs, &p, curve, interior);
3489     pfs->unlinear = !is_linear_color_applicable(pfs);
3490     pfs->linear_color = false;
3491     if ((*dev_proc(pfs->dev, pattern_manage))(pfs->dev,
3492 	    gs_no_id, NULL, pattern_manage__shading_area) > 0) {
3493 	/* Inform the device with the shading coverage area.
3494 	   First compute the sign of the area, because
3495 	   all areas to be clipped in same direction. */
3496 	gx_device *pdev = pfs->dev;
3497 	gx_path path;
3498 	fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
3499 	fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
3500 	fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
3501 	fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
3502 	fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
3503 	fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
3504 	fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
3505 	fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
3506 	int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3507 	int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
3508 	int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
3509 
3510 	gx_path_init_local(&path, pdev->memory);
3511 	if (is_x_bended(&p) || is_y_bended(&p)) {
3512 	    /* The patch possibly is self-overlapping,
3513 	       so the patch coverage may fall outside the patch outline.
3514 	       In this case we pass an empty path,
3515 	       and the device must use a bitmap mask instead clipping. */
3516 	} else {
3517     	    code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
3518 	    for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
3519 		j = (i + s) % 4, jj = (s == 1 ? i : j);
3520 		if (curve[jj].straight)
3521 		    code = gx_path_add_line(&path, curve[j].vertex.p.x,
3522 						curve[j].vertex.p.y);
3523 		else
3524 		    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
3525 						    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
3526 						    curve[j].vertex.p.x,
3527 						    curve[j].vertex.p.y);
3528 	    }
3529 	    if (code >= 0)
3530 		code = gx_path_close_subpath(&path);
3531 	}
3532 	if (code >= 0)
3533 	    code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3534 	gx_path_free(&path, "patch_fill");
3535 	if (code < 0)
3536 	    return code;
3537     }
3538     /* draw_patch(&p, true, RGB(0, 0, 0)); */
3539     kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
3540     kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
3541     kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
3542     kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
3543     kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
3544     ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
3545     ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
3546     kum = max(ku[0], ku[3]);
3547     km = max(kvm, kum);
3548 #   if NOFILL_TEST
3549 	dbg_nofill = false;
3550 #   endif
3551     code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, &p.c[0][0], &p.c[0][1],
3552 		interpatch_padding | inpatch_wedge);
3553     if (code >= 0) {
3554 	/* We would like to apply iterations for enumerating the kvm curve parts,
3555 	   but the roundinmg errors would be too complicated due to
3556 	   the dependence on the direction. Note that neigbour
3557 	   patches may use the opposite direction for same bounding curve.
3558 	   We apply the recursive dichotomy, in which
3559 	   the rounding errors do not depend on the direction. */
3560 #	if NOFILL_TEST
3561 	    dbg_nofill = false;
3562 	    code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
3563 	    dbg_nofill = true;
3564 #	endif
3565 	code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
3566     }
3567     if (code >= 0)
3568 	code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, &p.c[1][0], &p.c[1][1],
3569 		interpatch_padding | inpatch_wedge);
3570     return code;
3571 }
3572