Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/gxshade6.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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 *
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
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
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
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
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
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 
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
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
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 
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
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
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
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
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
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
996
covers_pixel_centers(fixed ybot, fixed ytop)
997
{
998
    return fixed_pixround(ybot) < fixed_pixround(ytop);
999
}
1000
 
1001
private inline int
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
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
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
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
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 
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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 
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
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
 
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 
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
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 
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 
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
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
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
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
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
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
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
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
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 
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 
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 
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
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
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
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
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
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
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 
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 
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 
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
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
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 
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 
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 
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
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
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
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
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 
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
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
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 
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 
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
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
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
 
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
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
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
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
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
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
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 
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
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
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
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
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 
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
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
}