Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxshade6.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2022 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Rendering for Coons and tensor patch shadings */
18
/*
19
   A contiguous non-overlapping decomposition
20
   of a tensor shading into linear color triangles.
21
 */
22
#include "memory_.h"
23
#include "gx.h"
24
#include "gserrors.h"
25
#include "gsmatrix.h"           /* for gscoord.h */
26
#include "gscoord.h"
27
#include "gscicach.h"
28
#include "gxcspace.h"
29
#include "gxdcolor.h"
30
#include "gxgstate.h"
31
#include "gxshade.h"
32
#include "gxdevcli.h"
33
#include "gxshade4.h"
34
#include "gxarith.h"
35
#include "gzpath.h"
36
#include "stdint_.h"
37
#include "math_.h"
38
#include "gsicc_cache.h"
39
#include "gxdevsop.h"
40
41
/* The original version of the shading code 'decompose's shadings into
42
 * smaller and smaller regions until they are smaller than 1 pixel, and then
43
 * fills them. (Either with a constant colour, or with a linear filled trap).
44
 *
45
 * Previous versions of the code (from svn revision 7936 until June 2011
46
 * (shortly after the switch to git)) changed this limit to be 1 point or 1
47
 * pixel (whichever is larger) (on the grounds that as resolution increases,
48
 * we are unlikely to be able to notice increasingly small inaccuracies in
49
 * the shading). Given how people abuse the resolution at which things are
50
 * rendered (especially when rendering to images that can subsequently be
51
 * zoomed), this seems a poor trade off. See bug 691152.
52
 *
53
 * The code has now been changed back to operate with the proper 1 pixel
54
 * decomposition, which will cost us performance in some cases. Should
55
 * people want to restore the previous operation, they should build with
56
 * MAX_SHADING_RESOLUTION predefined to 72. In general, this symbol can be
57
 * set to the maximum dpi that shading should ever be performed at. Leaving
58
 * it undefined will leave the default (1 pixel limit) in place.
59
 *
60
 * A possible future optimisation here may be to use different max shading
61
 * resolutions for linear and non-linear shadings; linear shadings appear to
62
 * result in calls to "fill linear traps", and non linear ones appear to
63
 * result in calls to "fill constant color". As such linear shadings are much
64
 * more forgiving of a higher decomposition threshold.
65
 */
66
67
#if NOFILL_TEST
68
static bool dbg_nofill = false;
69
#endif
70
#if SKIP_TEST
71
static int dbg_patch_cnt = 0;
72
static int dbg_quad_cnt = 0;
73
static int dbg_triangle_cnt = 0;
74
static int dbg_wedge_triangle_cnt = 0;
75
#endif
76
77
enum {
78
    min_linear_grades = 255 /* The minimal number of device color grades,
79
            required to apply linear color device functions. */
80
};
81
82
/* ================ Utilities ================ */
83
84
static int
85
allocate_color_stack(patch_fill_state_t *pfs, gs_memory_t *memory)
86
12.1k
{
87
12.1k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
12.1k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
12.1k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
12.1k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
12.1k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
12.1k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
12.1k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
12.1k
    pfs->color_stack_ptr = pfs->color_stack;
98
12.1k
    pfs->memory = memory;
99
12.1k
    return 0;
100
12.1k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
69.9M
{
105
69.9M
    int i;
106
69.9M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
221M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
151M
        c[i] = (patch_color_t *)ptr;
110
69.9M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
69.9M
    pfs->color_stack_ptr = ptr;
115
69.9M
    return ptr0;
116
69.9M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
135
{
121
135
    return reserve_colors_inline(pfs, c, n);
122
135
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
69.9M
{
127
#if 0 /* Saving the invariant for records. */
128
    pfs->color_stack_ptr = pfs->color_stack_step * n;
129
    assert((byte *)pfs->color_stack_ptr == ptr);
130
#else
131
69.9M
    pfs->color_stack_ptr = ptr;
132
69.9M
#endif
133
69.9M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
135
{
137
135
    release_colors_inline(pfs, ptr, n);
138
135
}
139
140
/* Get colors for patch vertices. */
141
static int
142
shade_next_colors(shade_coord_stream_t * cs, patch_curve_t * curves,
143
                  int num_vertices)
144
100k
{
145
100k
    int i, code = 0;
146
147
434k
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
334k
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
334k
        code = shade_next_color(cs, curves[i].vertex.cc);
150
334k
    }
151
100k
    return code;
152
100k
}
153
154
/* Get a Bezier or tensor patch element. */
155
static int
156
shade_next_curve(shade_coord_stream_t * cs, patch_curve_t * curve)
157
267k
{
158
267k
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
267k
    if (code >= 0)
161
267k
        code = shade_next_coords(cs, curve->control,
162
267k
                                 countof(curve->control));
163
267k
    return code;
164
267k
}
165
166
/*
167
 * Parse the next patch out of the input stream.  Return 1 if done,
168
 * 0 if patch, <0 on error.
169
 */
170
static int
171
shade_next_patch(shade_coord_stream_t * cs, int BitsPerFlag,
172
        patch_curve_t curve[4], gs_fixed_point interior[4] /* 0 for Coons patch */)
173
100k
{
174
100k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
100k
    int num_colors, code;
176
177
100k
    if (flag < 0) {
178
203
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
203
        return 1;               /* no more data */
181
203
    }
182
100k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
100k
    cs->first_patch = 0;
186
100k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
66.9k
        case 0:
190
66.9k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
66.9k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
66.9k
                )
193
14
                return code;
194
66.9k
            num_colors = 4;
195
66.9k
            goto vx;
196
8.98k
        case 1:
197
8.98k
            curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
198
8.98k
            goto v3;
199
9.51k
        case 2:
200
9.51k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
9.51k
            goto v3;
202
14.9k
        case 3:
203
14.9k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
33.4k
v3:         num_colors = 2;
205
100k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
100k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
100k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
100k
                (interior != 0 &&
209
100k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
100k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
100k
                                          num_colors)) < 0
212
100k
                )
213
96
                return code;
214
100k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
100k
    }
216
100k
    return 0;
217
100k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
3.19M
{
222
3.19M
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
3.19M
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
2.84M
        return false;
226
352k
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
6.47k
        return false;
228
345k
    return true;
229
352k
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
12.1k
{
234
12.1k
    int code;
235
236
12.1k
    pfs->memory = memory;
237
12.1k
#   if LAZY_WEDGES
238
12.1k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
12.1k
        if (code < 0)
240
0
            return code;
241
12.1k
#   endif
242
12.1k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
12.1k
    code = allocate_color_stack(pfs, memory);
244
12.1k
    if (code < 0)
245
0
        return code;
246
12.1k
    if (pfs->unlinear || pcs == NULL)
247
6.65k
        pfs->pcic = NULL;
248
5.50k
    else {
249
5.50k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
5.50k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
5.50k
    }
253
12.1k
    return 0;
254
12.1k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
12.1k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
12.1k
    const gs_color_space *pcs = pfs->direct_space;
261
12.1k
    gs_client_color fcc0, fcc1;
262
12.1k
    int i;
263
264
44.3k
    for (i = 0; i < pfs->num_components; i++) {
265
32.1k
        fcc0.paint.values[i] = -1000000;
266
32.1k
        fcc1.paint.values[i] = 1000000;
267
32.1k
    }
268
12.1k
    pcs->type->restrict_color(&fcc0, pcs);
269
12.1k
    pcs->type->restrict_color(&fcc1, pcs);
270
44.3k
    for (i = 0; i < pfs->num_components; i++)
271
32.1k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
12.1k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
12.1k
    pfs->maybe_self_intersecting = true;
274
12.1k
    pfs->monotonic_color = (pfs->Function == NULL);
275
12.1k
    pfs->function_arg_shift = 0;
276
12.1k
    pfs->linear_color = false;
277
12.1k
    pfs->inside = false;
278
12.1k
    pfs->n_color_args = 1;
279
#ifdef MAX_SHADING_RESOLUTION
280
    pfs->decomposition_limit = float2fixed(min(pfs->dev->HWResolution[0],
281
                                               pfs->dev->HWResolution[1]) / MAX_SHADING_RESOLUTION);
282
    pfs->decomposition_limit = max(pfs->decomposition_limit, fixed_1);
283
#else
284
12.1k
    pfs->decomposition_limit = fixed_1;
285
12.1k
#endif
286
12.1k
    pfs->fixed_flat = float2fixed(pfs->pgs->flatness);
287
    /* Restrict the pfs->smoothness with 1/min_linear_grades, because cs_is_linear
288
       can't provide a better precision due to the color
289
       representation with integers.
290
     */
291
12.1k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
12.1k
    pfs->color_stack_size = 0;
293
12.1k
    pfs->color_stack_step = 0;
294
12.1k
    pfs->color_stack_ptr = NULL;
295
12.1k
    pfs->color_stack = NULL;
296
12.1k
    pfs->color_stack_limit = NULL;
297
12.1k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
12.1k
    pfs->pcic = NULL;
299
12.1k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
12.1k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
12.1k
{
305
12.1k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
12.1k
#   if LAZY_WEDGES
307
12.1k
        wedge_vertex_list_elem_buffer_free(pfs);
308
12.1k
#   endif
309
12.1k
    if (pfs->color_stack)
310
12.1k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
12.1k
    if (pfs->pcic != NULL)
312
5.50k
        gs_color_index_cache_destroy(pfs->pcic);
313
12.1k
    return b;
314
12.1k
}
315
316
/* Resolve a patch color using the Function if necessary. */
317
static inline void
318
patch_resolve_color_inline(patch_color_t * ppcr, const patch_fill_state_t *pfs)
319
24.6M
{
320
24.6M
    if (pfs->Function) {
321
24.2M
        const gs_color_space *pcs = pfs->direct_space;
322
323
24.2M
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
24.2M
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
24.2M
    }
326
24.6M
}
327
328
void
329
patch_resolve_color(patch_color_t * ppcr, const patch_fill_state_t *pfs)
330
0
{
331
0
    patch_resolve_color_inline(ppcr, pfs);
332
0
}
333
334
/*
335
 * Calculate the interpolated color at a given point.
336
 * Note that we must do this twice for bilinear interpolation.
337
 * We use the name ppcr rather than ppc because an Apple compiler defines
338
 * ppc when compiling on PowerPC systems (!).
339
 */
340
static void
341
patch_interpolate_color(patch_color_t * ppcr, const patch_color_t * ppc0,
342
       const patch_color_t * ppc1, const patch_fill_state_t *pfs, double t)
343
88.9M
{
344
    /* The old code gives -IND on Intel. */
345
88.9M
    if (pfs->Function) {
346
15.9M
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
15.9M
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
15.9M
        patch_resolve_color_inline(ppcr, pfs);
349
72.9M
    } else {
350
72.9M
        int ci;
351
352
354M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
281M
            ppcr->cc.paint.values[ci] =
354
281M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
72.9M
    }
356
88.9M
}
357
358
/* ================ Specific shadings ================ */
359
360
/*
361
 * The curves are stored in a clockwise or counter-clockwise order that maps
362
 * to the patch definition in a non-intuitive way.  The documentation
363
 * (pp. 277-281 of the PostScript Language Reference Manual, Third Edition)
364
 * says that the curves are in the order D1, C2, D2, C1.
365
 */
366
/* The starting points of the curves: */
367
0
#define D1START 0
368
0
#define C2START 1
369
0
#define D2START 3
370
0
#define C1START 0
371
/* The control points of the curves (x means reversed order): */
372
0
#define D1CTRL 0
373
0
#define C2CTRL 1
374
0
#define D2XCTRL 2
375
0
#define C1XCTRL 3
376
/* The end points of the curves: */
377
0
#define D1END 1
378
0
#define C2END 2
379
0
#define D2END 2
380
0
#define C1END 3
381
382
/* ---------------- Common code ---------------- */
383
384
/* Evaluate a curve at a given point. */
385
static void
386
curve_eval(gs_fixed_point * pt, const gs_fixed_point * p0,
387
           const gs_fixed_point * p1, const gs_fixed_point * p2,
388
           const gs_fixed_point * p3, double t)
389
0
{
390
0
    fixed a, b, c, d;
391
0
    fixed t01, t12;
392
393
0
    d = p0->x;
394
0
    curve_points_to_coefficients(d, p1->x, p2->x, p3->x,
395
0
                                 a, b, c, t01, t12);
396
0
    pt->x = (fixed) (((a * t + b) * t + c) * t + d);
397
0
    d = p0->y;
398
0
    curve_points_to_coefficients(d, p1->y, p2->y, p3->y,
399
0
                                 a, b, c, t01, t12);
400
0
    pt->y = (fixed) (((a * t + b) * t + c) * t + d);
401
0
    if_debug3('2', "[2]t=%g => (%g,%g)\n", t, fixed2float(pt->x),
402
0
              fixed2float(pt->y));
403
0
}
404
405
/* ---------------- Coons patch shading ---------------- */
406
407
/* Calculate the device-space coordinate corresponding to (u,v). */
408
static void
409
Cp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
410
             const gs_fixed_point ignore_interior[4], double u, double v)
411
0
{
412
0
    double co_u = 1.0 - u, co_v = 1.0 - v;
413
0
    gs_fixed_point c1u, d1v, c2u, d2v;
414
415
0
    curve_eval(&c1u, &curve[C1START].vertex.p,
416
0
               &curve[C1XCTRL].control[1], &curve[C1XCTRL].control[0],
417
0
               &curve[C1END].vertex.p, u);
418
0
    curve_eval(&d1v, &curve[D1START].vertex.p,
419
0
               &curve[D1CTRL].control[0], &curve[D1CTRL].control[1],
420
0
               &curve[D1END].vertex.p, v);
421
0
    curve_eval(&c2u, &curve[C2START].vertex.p,
422
0
               &curve[C2CTRL].control[0], &curve[C2CTRL].control[1],
423
0
               &curve[C2END].vertex.p, u);
424
0
    curve_eval(&d2v, &curve[D2START].vertex.p,
425
0
               &curve[D2XCTRL].control[1], &curve[D2XCTRL].control[0],
426
0
               &curve[D2END].vertex.p, v);
427
0
#define COMPUTE_COORD(xy)\
428
0
    pt->xy = (fixed)\
429
0
        ((co_v * c1u.xy + v * c2u.xy) + (co_u * d1v.xy + u * d2v.xy) -\
430
0
         (co_v * (co_u * curve[C1START].vertex.p.xy +\
431
0
                  u * curve[C1END].vertex.p.xy) +\
432
0
          v * (co_u * curve[C2START].vertex.p.xy +\
433
0
               u * curve[C2END].vertex.p.xy)))
434
0
    COMPUTE_COORD(x);
435
0
    COMPUTE_COORD(y);
436
0
#undef COMPUTE_COORD
437
0
    if_debug4('2', "[2](u=%g,v=%g) => (%g,%g)\n",
438
0
              u, v, fixed2float(pt->x), fixed2float(pt->y));
439
0
}
440
441
int
442
gs_shading_Cp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
443
                             const gs_fixed_rect * rect_clip,
444
                             gx_device * dev, gs_gstate * pgs)
445
10
{
446
10
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
10
    patch_fill_state_t state;
448
10
    shade_coord_stream_t cs;
449
10
    patch_curve_t curve[4];
450
10
    int code;
451
452
10
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
10
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
10
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
10
    state.Function = psh->params.Function;
459
10
    code = init_patch_fill_state(&state);
460
10
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
10
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
10
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
45
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
45
                                    curve, NULL)) == 0 &&
469
45
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
35
        ) {
471
35
        DO_NOTHING;
472
35
    }
473
10
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
10
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
10
    return min(code, 0);
477
10
}
478
479
/* ---------------- Tensor product patch shading ---------------- */
480
481
/* Calculate the device-space coordinate corresponding to (u,v). */
482
static void
483
Tpp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
484
              const gs_fixed_point interior[4], double u, double v)
485
0
{
486
0
    double Bu[4], Bv[4];
487
0
    gs_fixed_point pts[4][4];
488
0
    int i, j;
489
0
    double x = 0, y = 0;
490
491
    /* Compute the Bernstein polynomials of u and v. */
492
0
    {
493
0
        double u2 = u * u, co_u = 1.0 - u, co_u2 = co_u * co_u;
494
0
        double v2 = v * v, co_v = 1.0 - v, co_v2 = co_v * co_v;
495
496
0
        Bu[0] = co_u * co_u2, Bu[1] = 3 * u * co_u2,
497
0
            Bu[2] = 3 * u2 * co_u, Bu[3] = u * u2;
498
0
        Bv[0] = co_v * co_v2, Bv[1] = 3 * v * co_v2,
499
0
            Bv[2] = 3 * v2 * co_v, Bv[3] = v * v2;
500
0
    }
501
502
    /* Arrange the points into an indexable order. */
503
0
    pts[0][0] = curve[0].vertex.p;
504
0
    pts[0][1] = curve[0].control[0];
505
0
    pts[0][2] = curve[0].control[1];
506
0
    pts[0][3] = curve[1].vertex.p;
507
0
    pts[1][3] = curve[1].control[0];
508
0
    pts[2][3] = curve[1].control[1];
509
0
    pts[3][3] = curve[2].vertex.p;
510
0
    pts[3][2] = curve[2].control[0];
511
0
    pts[3][1] = curve[2].control[1];
512
0
    pts[3][0] = curve[3].vertex.p;
513
0
    pts[2][0] = curve[3].control[0];
514
0
    pts[1][0] = curve[3].control[1];
515
0
    pts[1][1] = interior[0];
516
0
    pts[2][1] = interior[1];
517
0
    pts[2][2] = interior[2];
518
0
    pts[1][2] = interior[3];
519
520
    /* Now compute the actual point. */
521
0
    for (i = 0; i < 4; ++i)
522
0
        for (j = 0; j < 4; ++j) {
523
0
            double coeff = Bu[i] * Bv[j];
524
525
0
            x += pts[i][j].x * coeff, y += pts[i][j].y * coeff;
526
0
        }
527
0
    pt->x = (fixed)x, pt->y = (fixed)y;
528
0
}
529
530
int
531
gs_shading_Tpp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
532
                             const gs_fixed_rect * rect_clip,
533
                              gx_device * dev, gs_gstate * pgs)
534
303
{
535
303
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
303
    patch_fill_state_t state;
537
303
    shade_coord_stream_t cs;
538
303
    patch_curve_t curve[4];
539
303
    gs_fixed_point interior[4];
540
303
    int code;
541
542
303
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
303
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
303
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
303
    state.Function = psh->params.Function;
549
303
    code = init_patch_fill_state(&state);
550
303
    if(code < 0)
551
0
        return code;
552
303
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
303
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
100k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
100k
                                    curve, interior)) == 0) {
556
        /*
557
         * The order of points appears to be consistent with that for Coons
558
         * patches, which is different from that documented in Red Book 3.
559
         */
560
100k
        gs_fixed_point swapped_interior[4];
561
562
100k
        swapped_interior[0] = interior[0];
563
100k
        swapped_interior[1] = interior[3];
564
100k
        swapped_interior[2] = interior[2];
565
100k
        swapped_interior[3] = interior[1];
566
100k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
100k
        if (code < 0)
568
0
            break;
569
100k
    }
570
303
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
303
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
303
    return min(code, 0);
574
303
}
575
576
/*
577
    This algorithm performs a decomposition of the shading area
578
    into a set of constant color trapezoids, some of which
579
    may use the transpozed coordinate system.
580
581
    The target device assumes semi-open intrvals by X to be painted
582
    (See PLRM3, 7.5. Scan conversion details), i.e.
583
    it doesn't paint pixels which falls exactly to the right side.
584
    Note that with raster devices the algorithm doesn't paint pixels,
585
    whigh are partially covered by the shading area,
586
    but which's centers are outside the area.
587
588
    Pixels inside a monotonic part of the shading area are painted
589
    at once, but some exceptions may happen :
590
591
        - While flattening boundaries of a subpatch,
592
        to keep the plane coverage contiguity we insert wedges
593
        between neighbor subpatches, which use a different
594
        flattening factor. With non-monotonic curves
595
        those wedges may overlap or be self-overlapping, and a pixel
596
        is painted so many times as many wedges cover it. Fortunately
597
        the area of most wedges is zero or extremily small.
598
599
        - Since quazi-horizontal wedges may have a non-constant color,
600
        they can't decompose into constant color trapezoids with
601
        keeping the coverage contiguity. To represent them we
602
        apply the XY plane transposition. But with the transposition
603
        a semiopen interval can met a non-transposed one,
604
        so that some lines are not covered. Therefore we emulate
605
        closed intervals with expanding the transposed trapesoids in
606
        fixed_epsilon, and pixels at that boundary may be painted twice.
607
608
        - A boundary of a monotonic area can't compute in XY
609
        preciselly due to high order polynomial equations.
610
        Therefore the subdivision near the monotonity boundary
611
        may paint some pixels twice within same monotonic part.
612
613
    Non-monotonic areas slow down due to a tinny subdivision required.
614
615
    The target device may be either raster or vector.
616
    Vector devices should preciselly pass trapezoids to the output.
617
    Note that ends of sides of a trapesoid are not necessary
618
    the trapezoid's vertices. Converting this thing into
619
    an exact quadrangle may cause an arithmetic error,
620
    and the rounding must be done so that the coverage
621
    contiguity is not lost.
622
623
    When a device passes a trapezoid to it's output,
624
    a regular rounding would keep the coverage contiguity,
625
    except for the transposed trapesoids.
626
    If a transposed trapezoid is being transposed back,
627
    it doesn't become a canonic trapezoid, and a further
628
    decomposition is neccessary. But rounding errors here
629
    would break the coverage contiguity at boundaries
630
    of the tansposed part of the area.
631
632
    Devices, which have no transposed trapezoids and represent
633
    trapezoids only with 8 coordinates of vertices of the quadrangle
634
    (pclwrite is an example) may apply the backward transposition,
635
    and a clipping instead the further decomposition.
636
    Note that many clip regions may appear for all wedges.
637
    Note that in some cases the adjustment of the right side to be
638
    withdrown before the backward transposition.
639
 */
640
 /* We believe that a multiplication of 32-bit integers with a
641
    64-bit result is performed by modern platforms performs
642
    in hardware level. Therefore we widely use it here,
643
    but we minimize the usage of a multiplication of longer integers.
644
645
    Unfortunately we do need a multiplication of long integers
646
    in intersection_of_small_bars, because solving the linear system
647
    requires tripple multiples of 'fixed'. Therefore we retain
648
    of it's usage in the algorithm of the main branch.
649
    Configuration macro QUADRANGLES prevents it.
650
  */
651
652
typedef struct {
653
    gs_fixed_point pole[4][4]; /* [v][u] */
654
    patch_color_t *c[2][2];     /* [v][u] */
655
} tensor_patch;
656
657
typedef enum {
658
    interpatch_padding = 1, /* A Padding between patches for poorly designed documents. */
659
    inpatch_wedge = 2  /* Wedges while a patch decomposition. */
660
} wedge_type_t;
661
662
int
663
wedge_vertex_list_elem_buffer_alloc(patch_fill_state_t *pfs)
664
12.1k
{
665
12.1k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
12.1k
    gs_memory_t *memory = pfs->memory;
667
668
    /* We have 'max_level' levels, each of which divides 1 or 3 sides.
669
       LAZY_WEDGES stores all 2^level divisions until
670
       the other area of same bnoundary is processed.
671
       Thus the upper estimation of the buffer size is :
672
       max_level * (1 << max_level) * 3.
673
       Likely this estimation to be decreased to
674
       max_level * (1 << max_level) * 2.
675
       because 1 side of a triangle is always outside the division path.
676
       For now we set the smaller estimation for obtaining an experimental data
677
       from the wild. */
678
12.1k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
12.1k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
12.1k
            sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
681
12.1k
            "alloc_wedge_vertex_list_elem_buffer");
682
12.1k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
12.1k
    pfs->free_wedge_vertex = NULL;
685
12.1k
    pfs->wedge_vertex_list_elem_count = 0;
686
12.1k
    return 0;
687
12.1k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
12.1k
{
692
12.1k
    gs_memory_t *memory = pfs->memory;
693
694
12.1k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
12.1k
                "wedge_vertex_list_elem_buffer_free");
696
12.1k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
12.1k
    pfs->free_wedge_vertex = NULL;
698
12.1k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
8.58M
{
703
8.58M
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
8.58M
    if (e != NULL) {
706
8.36M
        pfs->free_wedge_vertex = e->next;
707
8.36M
        return e;
708
8.36M
    }
709
216k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
216k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
216k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
8.58M
{
717
8.58M
    e->next = pfs->free_wedge_vertex;
718
8.58M
    pfs->free_wedge_vertex = e;
719
8.58M
}
720
721
static inline void
722
release_wedge_vertex_list_interval(patch_fill_state_t *pfs,
723
    wedge_vertex_list_elem_t *beg, wedge_vertex_list_elem_t *end)
724
3.84M
{
725
3.84M
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
3.84M
    beg->next = end;
728
3.84M
    end->prev = beg;
729
7.74M
    for (; e != end; e = ee) {
730
3.90M
        ee = e->next;
731
3.90M
        wedge_vertex_list_elem_release(pfs, e);
732
3.90M
    }
733
3.84M
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
2.33M
{
738
2.33M
    int i;
739
740
4.67M
    for (i = 0; i < n; i++) {
741
2.33M
        wedge_vertex_list_t *l = ll + i;
742
743
2.33M
        if (l->beg != NULL) {
744
2.33M
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
2.33M
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
2.33M
            wedge_vertex_list_elem_release(pfs, l->beg);
748
2.33M
            wedge_vertex_list_elem_release(pfs, l->end);
749
2.33M
            l->beg = l->end = NULL;
750
2.33M
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
2.33M
    }
753
2.33M
    return 0;
754
2.33M
}
755
756
static inline wedge_vertex_list_elem_t *
757
wedge_vertex_list_find(wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
758
            int level)
759
1.95M
{
760
1.95M
    wedge_vertex_list_elem_t *e = beg;
761
762
1.95M
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
5.36M
    for (; e != end; e = e->next)
765
5.36M
        if (e->level == level)
766
1.95M
            return e;
767
0
    return NULL;
768
1.95M
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
14.3M
{
773
14.3M
    memset(l, 0, sizeof(*l) * n);
774
14.3M
}
775
776
/* For a given set of poles in the tensor patch (for instance
777
 * [0][0], [0][1], [0][2], [0][3] or [0][2], [1][2], [2][2], [3][2])
778
 * return the number of subdivisions required to flatten the bezier
779
 * given by those poles to the required flatness.
780
 */
781
static inline int
782
curve_samples(patch_fill_state_t *pfs,
783
                const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
784
5.03M
{
785
5.03M
    curve_segment s;
786
5.03M
    int k;
787
788
5.03M
    s.p1.x = pole[pole_step].x;
789
5.03M
    s.p1.y = pole[pole_step].y;
790
5.03M
    s.p2.x = pole[pole_step * 2].x;
791
5.03M
    s.p2.y = pole[pole_step * 2].y;
792
5.03M
    s.pt.x = pole[pole_step * 3].x;
793
5.03M
    s.pt.y = pole[pole_step * 3].y;
794
5.03M
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
5.03M
    {
796
5.03M
#       if LAZY_WEDGES || QUADRANGLES
797
5.03M
            int k1;
798
5.03M
            fixed L = any_abs(pole[pole_step * 1].x - pole[pole_step * 0].x) + any_abs(pole[pole_step * 1].y - pole[pole_step * 0].y) +
799
5.03M
                      any_abs(pole[pole_step * 2].x - pole[pole_step * 1].x) + any_abs(pole[pole_step * 2].y - pole[pole_step * 1].y) +
800
5.03M
                      any_abs(pole[pole_step * 3].x - pole[pole_step * 2].x) + any_abs(pole[pole_step * 3].y - pole[pole_step * 2].y);
801
5.03M
#       endif
802
803
5.03M
#       if LAZY_WEDGES
804
            /* Restrict lengths for a reasonable memory consumption : */
805
5.03M
            k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
806
5.03M
            k = max(k, k1);
807
5.03M
#       endif
808
#       if QUADRANGLES
809
            /* Restrict lengths for intersection_of_small_bars : */
810
            k = max(k, ilog2(L) - ilog2(pfs->max_small_coord));
811
#       endif
812
5.03M
    }
813
5.03M
    return 1 << k;
814
5.03M
}
815
816
static inline bool
817
intersection_of_small_bars(const gs_fixed_point q[4], int i0, int i1, int i2, int i3, fixed *ry, fixed *ey)
818
0
{
819
    /* This function is only used with QUADRANGLES. */
820
0
    return gx_intersect_small_bars(q[i0].x, q[i0].y, q[i1].x, q[i1].y, q[i2].x, q[i2].y, q[i3].x, q[i3].y, ry, ey);
821
0
}
822
823
static inline void
824
adjust_swapped_boundary(fixed *b, bool swap_axes)
825
30.5M
{
826
30.5M
    if (swap_axes) {
827
        /*  Sinse the rasterizer algorithm assumes semi-open interval
828
            when computing pixel coverage, we should expand
829
            the right side of the area. Otherwise a dropout can happen :
830
            if the left neighbour is painted with !swap_axes,
831
            the left side of this area appears to be the left side
832
            of the neighbour area, and the side is not included
833
            into both areas.
834
         */
835
13.6M
        *b += fixed_epsilon;
836
13.6M
    }
837
30.5M
}
838
839
static inline void
840
make_trapezoid(const gs_fixed_point q[4],
841
        int vi0, int vi1, int vi2, int vi3, fixed ybot, fixed ytop,
842
        bool swap_axes, bool orient, gs_fixed_edge *le, gs_fixed_edge *re)
843
8.36M
{
844
8.36M
    if (!orient) {
845
4.21M
        le->start = q[vi0];
846
4.21M
        le->end = q[vi1];
847
4.21M
        re->start = q[vi2];
848
4.21M
        re->end = q[vi3];
849
4.21M
    } else {
850
4.14M
        le->start = q[vi2];
851
4.14M
        le->end = q[vi3];
852
4.14M
        re->start = q[vi0];
853
4.14M
        re->end = q[vi1];
854
4.14M
    }
855
8.36M
    adjust_swapped_boundary(&re->start.x, swap_axes);
856
8.36M
    adjust_swapped_boundary(&re->end.x, swap_axes);
857
8.36M
}
858
859
static inline int
860
gx_shade_trapezoid(patch_fill_state_t *pfs, const gs_fixed_point q[4],
861
        int vi0, int vi1, int vi2, int vi3, fixed ybot0, fixed ytop0,
862
        bool swap_axes, const gx_device_color *pdevc, bool orient)
863
457k
{
864
457k
    gs_fixed_edge le, re;
865
457k
    int code;
866
457k
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
867
457k
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
868
457k
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
869
457k
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
870
871
457k
    if (ybot >= ytop)
872
195k
        return 0;
873
#   if NOFILL_TEST
874
        if (dbg_nofill)
875
            return 0;
876
#   endif
877
262k
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
878
262k
    if (!pfs->inside) {
879
111k
        bool clip = false;
880
881
        /* We are asked to clip a trapezoid to a rectangle. If the rectangle
882
         * is entirely contained within the rectangle, then no clipping is
883
         * actually required. If the left edge is entirely to the right of
884
         * the rectangle, or the right edge is entirely to the left, we
885
         * clip away to nothing. If the left edge is entirely to the left of
886
         * the rectangle, then we can simplify it to a vertical edge along
887
         * the edge of the rectangle. Likewise with the right edge if it's
888
         * entirely to the right of the rectangle.*/
889
111k
        if (le.start.x > xright) {
890
14.1k
            if (le.end.x > xright) {
891
0
                return 0;
892
0
            }
893
14.1k
            clip = true;
894
96.9k
        } else if (le.end.x > xright) {
895
7.95k
            clip = true;
896
7.95k
        }
897
111k
        if (le.start.x < xleft) {
898
25.3k
            if (le.end.x < xleft) {
899
17.0k
                le.start.x = xleft;
900
17.0k
                le.end.x   = xleft;
901
17.0k
                le.start.y = ybot;
902
17.0k
                le.end.y   = ytop;
903
17.0k
            } else {
904
8.26k
                clip = true;
905
8.26k
            }
906
85.6k
        } else if (le.end.x < xleft) {
907
13.7k
            clip = true;
908
13.7k
        }
909
111k
        if (re.start.x < xleft) {
910
8.84k
            if (re.end.x < xleft) {
911
0
                return 0;
912
0
            }
913
8.84k
            clip = true;
914
102k
        } else if (re.end.x < xleft) {
915
13.6k
            clip = true;
916
13.6k
        }
917
111k
        if (re.start.x > xright) {
918
26.4k
            if (re.end.x > xright) {
919
12.2k
                re.start.x = xright;
920
12.2k
                re.end.x   = xright;
921
12.2k
                re.start.y = ybot;
922
12.2k
                re.end.y   = ytop;
923
14.2k
            } else {
924
14.2k
                clip = true;
925
14.2k
            }
926
84.5k
        } else if (re.end.x > xright) {
927
7.32k
            clip = true;
928
7.32k
        }
929
111k
        if (clip)
930
47.9k
        {
931
            /* Some form of clipping seems to be required. A certain amount
932
             * of horridness goes on here to ensure that we round 'outwards'
933
             * in all cases. */
934
47.9k
            gs_fixed_edge lenew, renew;
935
47.9k
            fixed ybl, ybr, ytl, ytr, ymid;
936
937
            /* Reduce the clipping region horizontally if possible. */
938
47.9k
            if (re.start.x > re.end.x) {
939
20.6k
                if (re.start.x < xright)
940
6.35k
                    xright = re.start.x;
941
27.3k
            } else if (re.end.x < xright)
942
8.48k
                xright = re.end.x;
943
47.9k
            if (le.start.x > le.end.x) {
944
20.6k
                if (le.end.x > xleft)
945
6.86k
                    xleft = le.end.x;
946
27.3k
            } else if (le.start.x > xleft)
947
7.53k
                xleft = le.start.x;
948
949
47.9k
            ybot = max(ybot, min(le.start.y, re.start.y));
950
47.9k
            ytop = min(ytop, max(le.end.y, re.end.y));
951
#if 0
952
            /* RJW: I've disabled this code a) because it doesn't make any
953
             * difference in the cluster tests, and b) because I think it's wrong.
954
             * Taking the first case as an example; just because the le.start.x
955
             * is > xright, does not mean that we can simply truncate the edge at
956
             * xright, as this may throw away part of the trap between ybot and
957
             * the new le.start.y. */
958
            /* Reduce the edges to the left/right of the clipping region. */
959
            /* Only in the 4 cases which can bring ytop/ybot closer */
960
            if (le.start.x > xright) {
961
                le.start.y += (fixed)((int64_t)(le.end.y-le.start.y)*
962
                                      (int64_t)(le.start.x-xright)/
963
                                      (int64_t)(le.start.x-le.end.x));
964
                le.start.x = xright;
965
            }
966
            if (re.start.x < xleft) {
967
                re.start.y += (fixed)((int64_t)(re.end.y-re.start.y)*
968
                                      (int64_t)(xleft-re.start.x)/
969
                                      (int64_t)(re.end.x-re.start.x));
970
                re.start.x = xleft;
971
            }
972
            if (le.end.x > xright) {
973
                le.end.y -= (fixed)((int64_t)(le.end.y-le.start.y)*
974
                                    (int64_t)(le.end.x-xright)/
975
                                    (int64_t)(le.end.x-le.start.x));
976
                le.end.x = xright;
977
            }
978
            if (re.end.x < xleft) {
979
                re.end.y -= (fixed)((int64_t)(re.end.y-re.start.y)*
980
                                    (int64_t)(xleft-re.end.x)/
981
                                    (int64_t)(re.start.x-re.end.x));
982
                re.end.x = xleft;
983
            }
984
#endif
985
986
47.9k
            if (ybot >= ytop)
987
0
                return 0;
988
            /* Follow the edges in, so that le.start.y == ybot etc. */
989
47.9k
            if (le.start.y < ybot) {
990
19.4k
                int round = ((le.end.x < le.start.x) ?
991
11.0k
                             (le.end.y-le.start.y-1) : 0);
992
19.4k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
993
19.4k
                                       (int64_t)(le.end.x-le.start.x)-round)/
994
19.4k
                                      (int64_t)(le.end.y-le.start.y));
995
19.4k
                le.start.y = ybot;
996
19.4k
            }
997
47.9k
            if (le.end.y > ytop) {
998
19.6k
                int round = ((le.end.x > le.start.x) ?
999
9.97k
                             (le.end.y-le.start.y-1) : 0);
1000
19.6k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1001
19.6k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1002
19.6k
                                    (int64_t)(le.end.y-le.start.y));
1003
19.6k
                le.end.y = ytop;
1004
19.6k
            }
1005
47.9k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1006
1.93k
                le.start.x = xleft;
1007
1.93k
                le.end.x   = xleft;
1008
1.93k
                le.start.y = ybot;
1009
1.93k
                le.end.y   = ytop;
1010
1.93k
            }
1011
47.9k
            if (re.start.y < ybot) {
1012
19.4k
                int round = ((re.end.x > re.start.x) ?
1013
9.78k
                             (re.end.y-re.start.y-1) : 0);
1014
19.4k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1015
19.4k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1016
19.4k
                                      (int64_t)(re.end.y-re.start.y));
1017
19.4k
                re.start.y = ybot;
1018
19.4k
            }
1019
47.9k
            if (re.end.y > ytop) {
1020
19.7k
                int round = ((re.end.x < re.start.x) ?
1021
11.0k
                             (re.end.y-re.start.y-1) : 0);
1022
19.7k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1023
19.7k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1024
19.7k
                                    (int64_t)(re.end.y-re.start.y));
1025
19.7k
                re.end.y = ytop;
1026
19.7k
            }
1027
47.9k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1028
888
                re.start.x = xright;
1029
888
                re.end.x   = xright;
1030
888
                re.start.y = ybot;
1031
888
                re.end.y   = ytop;
1032
888
            }
1033
            /* Now, check whether the left and right edges cross. Previously
1034
             * this comment said: "This can only happen (for well formed
1035
             * input) in the case where one of the edges was completely out
1036
             * of range and has now been pulled in to the edge of the clip
1037
             * region." I now do not believe this to be true. */
1038
47.9k
            if (le.start.x > re.start.x) {
1039
18.2k
                if (le.start.x == le.end.x) {
1040
8.46k
                    if (re.start.x == re.end.x)
1041
0
                        return 0;
1042
8.46k
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1043
8.46k
                                    (int64_t)(le.start.x-re.start.x)/
1044
8.46k
                                    (int64_t)(re.end.x-re.start.x));
1045
8.46k
                    re.start.x = le.start.x;
1046
9.80k
                } else {
1047
9.80k
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1048
9.80k
                                    (int64_t)(le.start.x-re.start.x)/
1049
9.80k
                                    (int64_t)(le.start.x-le.end.x));
1050
9.80k
                    le.start.x = re.start.x;
1051
9.80k
                }
1052
18.2k
                if (ybot >= ytop)
1053
7.03k
                    return 0;
1054
11.2k
                le.start.y = ybot;
1055
11.2k
                re.start.y = ybot;
1056
11.2k
            }
1057
40.9k
            if (le.end.x > re.end.x) {
1058
11.4k
                if (le.start.x == le.end.x) {
1059
7.45k
                    if (re.start.x == re.end.x)
1060
0
                        return 0;
1061
7.45k
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1062
7.45k
                                    (int64_t)(le.end.x-re.end.x)/
1063
7.45k
                                    (int64_t)(re.start.x-re.end.x));
1064
7.45k
                    re.end.x = le.end.x;
1065
7.45k
                } else {
1066
3.97k
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1067
3.97k
                                    (int64_t)(le.end.x-re.end.x)/
1068
3.97k
                                    (int64_t)(le.end.x-le.start.x));
1069
3.97k
                    le.end.x = re.end.x;
1070
3.97k
                }
1071
11.4k
                if (ybot >= ytop)
1072
6.39k
                    return 0;
1073
5.03k
                le.end.y = ytop;
1074
5.03k
                re.end.y = ytop;
1075
5.03k
            }
1076
            /* At this point we are guaranteed that le and re are constrained
1077
             * as tightly as possible to the ybot/ytop range, and that the
1078
             * entire ybot/ytop range will be marked at least somewhere. All
1079
             * we need to do now is to actually fill the region.
1080
             */
1081
34.5k
            lenew.start.x = xleft;
1082
34.5k
            lenew.start.y = ybot;
1083
34.5k
            lenew.end.x   = xleft;
1084
34.5k
            lenew.end.y   = ytop;
1085
34.5k
            renew.start.x = xright;
1086
34.5k
            renew.start.y = ybot;
1087
34.5k
            renew.end.x   = xright;
1088
34.5k
            renew.end.y   = ytop;
1089
            /* Figure out where the left edge intersects with the left at
1090
             * the bottom */
1091
34.5k
            ybl = ybot;
1092
34.5k
            if (le.start.x > le.end.x) {
1093
15.0k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1094
15.0k
                               (int64_t)(le.end.y-le.start.y) /
1095
15.0k
                               (int64_t)(le.start.x-le.end.x));
1096
15.0k
                if (ybl > ytop)
1097
5.29k
                    ybl = ytop;
1098
15.0k
            }
1099
            /* Figure out where the right edge intersects with the right at
1100
             * the bottom */
1101
34.5k
            ybr = ybot;
1102
34.5k
            if (re.start.x < re.end.x) {
1103
12.6k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1104
12.6k
                               (int64_t)(re.end.y-re.start.y) /
1105
12.6k
                               (int64_t)(re.end.x-re.start.x));
1106
12.6k
                if (ybr > ytop)
1107
5.67k
                    ybr = ytop;
1108
12.6k
            }
1109
            /* Figure out where the left edge intersects with the left at
1110
             * the top */
1111
34.5k
            ytl = ytop;
1112
34.5k
            if (le.end.x > le.start.x) {
1113
12.8k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1114
12.8k
                               (int64_t)(le.end.y-le.start.y) /
1115
12.8k
                               (int64_t)(le.end.x-le.start.x));
1116
12.8k
                if (ytl < ybot)
1117
5.89k
                    ytl = ybot;
1118
12.8k
            }
1119
            /* Figure out where the right edge intersects with the right at
1120
             * the bottom */
1121
34.5k
            ytr = ytop;
1122
34.5k
            if (re.end.x < re.start.x) {
1123
16.0k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1124
16.0k
                               (int64_t)(re.end.y-re.start.y) /
1125
16.0k
                               (int64_t)(re.start.x-re.end.x));
1126
16.0k
                if (ytr < ybot)
1127
5.18k
                    ytr = ybot;
1128
16.0k
            }
1129
            /* Check for the 2 cases where top and bottom diagonal extents
1130
             * overlap, and deal with them explicitly. */
1131
34.5k
            if (ytl < ybr) {
1132
                /*     |     |
1133
                 *  ---+-----+---
1134
                 *     | /222|
1135
                 *     |/111/|
1136
                 *     |000/ |
1137
                 *  ---+-----+---
1138
                 *     |     |
1139
                 */
1140
6.91k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1141
6.91k
                                        &lenew, &re, ybot, ytl,
1142
6.91k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1143
6.91k
                if (code < 0)
1144
0
                    return code;
1145
6.91k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1146
6.91k
                                        &le, &re, ytl, ybr,
1147
6.91k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1148
6.91k
                if (code < 0)
1149
0
                    return code;
1150
6.91k
                ybot = ybr;
1151
6.91k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1152
6.91k
                                        &le, &renew, ybr, ytop,
1153
6.91k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1154
27.5k
            } else if (ytr < ybl) {
1155
                /*     |     |
1156
                 *  ---+-----+----
1157
                 *     |555\ |
1158
                 *     |\444\|
1159
                 *     | \333|
1160
                 *  ---+-----+---
1161
                 *     |     |
1162
                 */
1163
8.47k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
8.47k
                                        &le, &renew, ybot, ytr,
1165
8.47k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
8.47k
                if (code < 0)
1167
0
                    return code;
1168
8.47k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1169
8.47k
                                        &le, &re, ytr, ybl,
1170
8.47k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1171
8.47k
                if (code < 0)
1172
0
                    return code;
1173
8.47k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1174
8.47k
                                        &le, &re, ybl, ytop,
1175
8.47k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1176
8.47k
            }
1177
            /* Fill in any section where both left and right edges are
1178
             * diagonal at the bottom */
1179
19.1k
            ymid = ybl;
1180
19.1k
            if (ymid > ybr)
1181
4.37k
                ymid = ybr;
1182
19.1k
            if (ymid > ybot) {
1183
                /*     |\   |          |   /|
1184
                 *     | \6/|    or    |\6/ |
1185
                 *  ---+----+---    ---+----+---
1186
                 *     |    |          |    |
1187
                 */
1188
2.37k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1189
2.37k
                                        &le, &re, ybot, ymid,
1190
2.37k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1191
2.37k
                if (code < 0)
1192
0
                    return code;
1193
2.37k
                ybot = ymid;
1194
2.37k
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the top */
1197
19.1k
            ymid = ytl;
1198
19.1k
            if (ymid < ytr)
1199
3.30k
                ymid = ytr;
1200
19.1k
            if (ymid < ytop) {
1201
                /*     |    |          |    |
1202
                 *  ---+----+---    ---+----+---
1203
                 *     |/7\ |    or    | /7\|
1204
                 *     |   \|          |/   |
1205
                 */
1206
2.89k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
2.89k
                                        &le, &re, ymid, ytop,
1208
2.89k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
2.89k
                if (code < 0)
1210
0
                    return code;
1211
2.89k
                ytop = ymid;
1212
2.89k
            }
1213
            /* Now do the single diagonal cases at the bottom */
1214
19.1k
            if (ybl > ybot) {
1215
                /*     |    |
1216
                 *     |\666|
1217
                 *  ---+----+---
1218
                 *     |    |
1219
                 */
1220
4.37k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1221
4.37k
                                        &le, &renew, ybot, ybl,
1222
4.37k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1223
4.37k
                if (code < 0)
1224
0
                    return code;
1225
4.37k
                ybot = ybl;
1226
14.7k
            } else if (ybr > ybot) {
1227
                /*     |    |
1228
                 *     |777/|
1229
                 *  ---+----+---
1230
                 *     |    |
1231
                 */
1232
3.16k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1233
3.16k
                                        &lenew, &re, ybot, ybr,
1234
3.16k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1235
3.16k
                if (code < 0)
1236
0
                    return code;
1237
3.16k
                ybot = ybr;
1238
3.16k
            }
1239
            /* Now do the single diagonal cases at the top */
1240
19.1k
            if (ytl < ytop) {
1241
                /*     |    |
1242
                 *  ---+----+---
1243
                 *     |/888|
1244
                 *     |    |
1245
                 */
1246
3.30k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1247
3.30k
                                        &le, &renew, ytl, ytop,
1248
3.30k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1249
3.30k
                if (code < 0)
1250
0
                    return code;
1251
3.30k
                ytop = ytl;
1252
15.8k
            } else if (ytr < ytop) {
1253
                /*     |    |
1254
                 *  ---+----+---
1255
                 *     |999\|
1256
                 *     |    |
1257
                 */
1258
4.55k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1259
4.55k
                                        &lenew, &re, ytr, ytop,
1260
4.55k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1261
4.55k
                if (code < 0)
1262
0
                    return code;
1263
4.55k
                ytop = ytr;
1264
4.55k
            }
1265
            /* And finally just whatever rectangular section is left over in
1266
             * the middle */
1267
19.1k
            if (ybot > ytop)
1268
0
                return 0;
1269
19.1k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1270
19.1k
                                        &lenew, &renew, ybot, ytop,
1271
19.1k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1272
19.1k
        }
1273
111k
    }
1274
214k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1275
214k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1276
262k
}
1277
1278
static inline void
1279
dc2fc31(const patch_fill_state_t *pfs, gx_device_color *pdevc,
1280
            frac31 fc[GX_DEVICE_COLOR_MAX_COMPONENTS])
1281
0
{
1282
0
    int j;
1283
0
    const gx_device_color_info *cinfo = &pfs->trans_device->color_info;
1284
    /* Note trans device is actually either the transparency parent
1285
       device if transparency is present or the target device.  Basically
1286
       the device from which we want to get the color information from
1287
       for this */
1288
1289
0
    if (pdevc->type == &gx_dc_type_data_pure) {
1290
0
        for (j = 0; j < cinfo->num_components; j++) {
1291
0
                int shift = cinfo->comp_shift[j];
1292
0
                int bits = cinfo->comp_bits[j];
1293
1294
0
                fc[j] = ((pdevc->colors.pure >> shift) & ((1 << bits) - 1)) <<
1295
0
                        (sizeof(frac31) * 8 - 1 - bits);
1296
0
        }
1297
0
    } else {
1298
0
        for (j = 0; j < cinfo->num_components; j++) {
1299
0
                fc[j] = cv2frac31(pdevc->colors.devn.values[j]);
1300
0
        }
1301
0
    }
1302
0
}
1303
1304
152M
#define DEBUG_COLOR_INDEX_CACHE 0
1305
1306
static inline int
1307
patch_color_to_device_color_inline(const patch_fill_state_t *pfs,
1308
                                   const patch_color_t *c, gx_device_color *pdevc,
1309
                                   frac31 *frac_values)
1310
38.1M
{
1311
    /* Must return 2 if the color is not pure.
1312
       See try_device_linear_color.
1313
     */
1314
38.1M
    int code;
1315
38.1M
    gx_device_color devc;
1316
1317
38.1M
#ifdef PACIFY_VALGRIND
1318
    /* This is a hack to get us around some valgrind warnings seen
1319
     * when transparency is in use with the clist. We run through
1320
     * the shading code dealing with pfs->num_components components.
1321
     * I believe this is intended to match the source space of the
1322
     * shading, as we have to perform all shadings in the source
1323
     * space initially, and only convert after decomposition.
1324
     * When this reaches down to the clist writing phase, the
1325
     * clist writes pfs->dev->color_info.num_components color
1326
     * components to the clist. In the example I am using
1327
     *  pfs->num_components = 1
1328
     *  pfs->dev->color_info.num_components=3
1329
     * So valgrind complains that 2 of the 3 color components
1330
     * it is writing are uninitialised. Magically, it appears
1331
     * not to actually use them when read back though, so
1332
     * it suffices to blank them to kill the warnings now.
1333
     * If pfs->num_components > pfs->dev->color_info.num_components
1334
     * then we'll not be writing enough information to the clist
1335
     * and so hopefully we'll see bad rendering!
1336
     *
1337
     * An example that shows why this is required:
1338
     *  make gsdebugvg
1339
     *  valgrind --track-origins=yes debugbin/gs -sOutputFile=test.ps
1340
     *    -dMaxBitmap=1000 -sDEVICE=ps2write  -r300  -Z: -dNOPAUSE
1341
     *    -dBATCH -K2000000 -dClusterJob Bug693480.pdf
1342
     * (though ps2write is not implicated here).
1343
     */
1344
38.1M
     if (frac_values) {
1345
12.1M
        int i;
1346
12.1M
  int n = pfs->dev->color_info.num_components;
1347
15.0M
  for (i = pfs->num_components; i < n; i++) {
1348
2.89M
            frac_values[i] = 0;
1349
2.89M
  }
1350
12.1M
    }
1351
38.1M
#endif
1352
1353
38.1M
    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
1354
0
        pdevc = &devc;
1355
38.1M
    if (pfs->pcic) {
1356
12.3M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1357
12.3M
        if (code < 0)
1358
0
            return code;
1359
12.3M
    }
1360
38.1M
    if (DEBUG_COLOR_INDEX_CACHE || pfs->pcic == NULL) {
1361
#       if DEBUG_COLOR_INDEX_CACHE
1362
        gx_color_index cindex = pdevc->colors.pure;
1363
#       endif
1364
25.8M
        gs_client_color fcc;
1365
25.8M
        const gs_color_space *pcs = pfs->direct_space;
1366
1367
25.8M
        if (pcs != NULL) {
1368
1369
25.8M
            if (pdevc == NULL)
1370
0
                pdevc = &devc;
1371
25.8M
            memcpy(fcc.paint.values, c->cc.paint.values,
1372
25.8M
                        sizeof(fcc.paint.values[0]) * pfs->num_components);
1373
25.8M
            code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pgs,
1374
25.8M
                                      pfs->trans_device, gs_color_select_texture);
1375
25.8M
            if (code < 0)
1376
1
                return code;
1377
25.8M
            if (frac_values != NULL) {
1378
0
                if (!(pdevc->type == &gx_dc_type_data_devn ||
1379
0
                      pdevc->type == &gx_dc_type_data_pure))
1380
0
                    return 2;
1381
0
                dc2fc31(pfs, pdevc, frac_values);
1382
0
            }
1383
#           if DEBUG_COLOR_INDEX_CACHE
1384
            if (cindex != pdevc->colors.pure)
1385
                return_error(gs_error_unregistered);
1386
#           endif
1387
25.8M
        } else {
1388
            /* This is reserved for future extension,
1389
            when a linear color triangle with frac31 colors is being decomposed
1390
            during a clist rasterization. In this case frac31 colors are written into
1391
            the patch color, and pcs==NULL means an identity color mapping.
1392
            For a while we assume here pfs->pcic is also NULL. */
1393
0
            int j;
1394
0
            const gx_device_color_info *cinfo = &pfs->dev->color_info;
1395
1396
0
            for (j = 0; j < cinfo->num_components; j++)
1397
0
                frac_values[j] = (frac31)c->cc.paint.values[j];
1398
0
            pdevc->type = &gx_dc_type_data_pure;
1399
0
        }
1400
25.8M
    }
1401
38.1M
    return 0;
1402
38.1M
}
1403
1404
int
1405
patch_color_to_device_color(const patch_fill_state_t *pfs, const patch_color_t *c, gx_device_color *pdevc)
1406
0
{
1407
0
    return patch_color_to_device_color_inline(pfs, c, pdevc, NULL);
1408
0
}
1409
1410
static inline double
1411
color_span(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1412
85.9M
{
1413
85.9M
    int n = pfs->num_components, i;
1414
85.9M
    double m;
1415
1416
    /* Dont want to copy colors, which are big things. */
1417
85.9M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1418
328M
    for (i = 1; i < n; i++)
1419
242M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1420
85.9M
    return m;
1421
85.9M
}
1422
1423
static inline void
1424
color_diff(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1, patch_color_t *d)
1425
12.8M
{
1426
12.8M
    int n = pfs->num_components, i;
1427
1428
61.7M
    for (i = 0; i < n; i++)
1429
48.9M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1430
12.8M
}
1431
1432
static inline double
1433
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1434
11.4M
{
1435
11.4M
    int n = pfs->num_components, i;
1436
11.4M
    double m;
1437
1438
11.4M
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1439
44.0M
    for (i = 1; i < n; i++)
1440
32.6M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1441
11.4M
    return m;
1442
11.4M
}
1443
1444
static inline int
1445
isnt_color_monotonic(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1446
3.43M
{   /* checks whether the color is monotonic in the n-dimensional interval,
1447
       where n is the number of parameters in c0->t, c1->t.
1448
       returns : 0 = monotonic,
1449
       bit 0 = not or don't know by t0,
1450
       bit 1 = not or don't know by t1,
1451
       <0 = error. */
1452
    /* When pfs->Function is not set, the color is monotonic.
1453
       In this case do not call this function because
1454
       it doesn't check whether pfs->Function is set.
1455
       Actually pfs->monotonic_color prevents that.
1456
     */
1457
    /* This assumes that the color space is always monotonic.
1458
       Non-monotonic color spaces are not recommended by PLRM,
1459
       and the result with them may be imprecise.
1460
     */
1461
3.43M
    uint mask;
1462
3.43M
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1463
1464
3.43M
    if (code >= 0)
1465
3.43M
        return mask;
1466
3
    return code;
1467
3.43M
}
1468
1469
static inline bool
1470
covers_pixel_centers(fixed ybot, fixed ytop)
1471
10.1M
{
1472
10.1M
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1473
10.1M
}
1474
1475
static inline int
1476
constant_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1477
        fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c)
1478
7.54M
{
1479
7.54M
    gx_device_color dc;
1480
7.54M
    int code;
1481
1482
#   if NOFILL_TEST
1483
        /* if (dbg_nofill)
1484
                return 0; */
1485
#   endif
1486
1487
7.54M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1488
7.54M
    if (code < 0)
1489
1
        return code;
1490
1491
7.54M
    if (device_encodes_tags(pfs->dev)) {
1492
0
        dc.tag = (pfs->dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS);
1493
7.54M
    } else {
1494
7.54M
        dc.tag = 0;
1495
7.54M
    }
1496
1497
7.54M
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1498
7.54M
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1499
7.54M
}
1500
1501
static inline float
1502
function_linearity(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1503
14.5M
{
1504
14.5M
    float s = 0;
1505
1506
14.5M
    if (pfs->Function != NULL) {
1507
4.03M
        patch_color_t c;
1508
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1509
        /* unless it is 'static const' */
1510
4.03M
        static const float q[2] = {(float)0.3, (float)0.7};
1511
4.03M
        int i, j;
1512
1513
12.0M
        for (j = 0; j < count_of(q); j++) {
1514
8.02M
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1515
8.02M
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1516
8.02M
            patch_resolve_color_inline(&c, pfs);
1517
31.2M
            for (i = 0; i < pfs->num_components; i++) {
1518
23.2M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1519
23.2M
                float d = v - c.cc.paint.values[i];
1520
23.2M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1521
1522
23.2M
                if (s1 > pfs->smoothness)
1523
46.7k
                    return s1;
1524
23.1M
                if (s < s1)
1525
1.76M
                    s = s1;
1526
23.1M
            }
1527
8.02M
        }
1528
4.03M
    }
1529
14.4M
    return s;
1530
14.5M
}
1531
1532
static inline int
1533
is_color_linear(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1534
8.44M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1535
8.44M
    if (pfs->unlinear)
1536
4.46M
        return 1; /* Disable this check. */
1537
3.98M
    else {
1538
3.98M
        const gs_color_space *cs = pfs->direct_space;
1539
3.98M
        int code;
1540
3.98M
        float s = function_linearity(pfs, c0, c1);
1541
1542
3.98M
        if (s > pfs->smoothness)
1543
29.1k
            return 0;
1544
3.95M
        if (pfs->cs_always_linear)
1545
798k
            return 1;
1546
3.15M
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1547
3.15M
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1548
3.15M
        if (code <= 0)
1549
38.3k
            return code;
1550
3.11M
        return 1;
1551
3.15M
    }
1552
8.44M
}
1553
1554
static int
1555
decompose_linear_color(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1556
        fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0,
1557
        const patch_color_t *c1)
1558
21.2M
{
1559
    /* Assuming a very narrow trapezoid - ignore the transversal color variation. */
1560
    /* Assuming the XY span is restricted with curve_samples.
1561
       It is important for intersection_of_small_bars to compute faster. */
1562
21.2M
    int code;
1563
21.2M
    patch_color_t *c;
1564
21.2M
    byte *color_stack_ptr;
1565
21.2M
    bool save_inside = pfs->inside;
1566
1567
21.2M
    if (!pfs->inside) {
1568
17.7M
        gs_fixed_rect r, r1;
1569
1570
17.7M
        if(swap_axes) {
1571
7.74M
            r.p.y = min(le->start.x, le->end.x);
1572
7.74M
            r.p.x = min(le->start.y, le->end.y);
1573
7.74M
            r.q.y = max(re->start.x, re->end.x);
1574
7.74M
            r.q.x = max(re->start.y, re->end.y);
1575
10.0M
        } else {
1576
10.0M
            r.p.x = min(le->start.x, le->end.x);
1577
10.0M
            r.p.y = min(le->start.y, le->end.y);
1578
10.0M
            r.q.x = max(re->start.x, re->end.x);
1579
10.0M
            r.q.y = max(re->start.y, re->end.y);
1580
10.0M
        }
1581
17.7M
        r1 = r;
1582
17.7M
        rect_intersect(r, pfs->rect);
1583
17.7M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1584
9.72M
            return 0;
1585
8.04M
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1586
8.04M
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1587
2.49M
            pfs->inside = true;
1588
8.04M
    }
1589
11.4M
    color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
1590
11.4M
    if (color_stack_ptr == NULL)
1591
0
        return_error(gs_error_unregistered); /* Must not happen. */
1592
    /* Use the recursive decomposition due to isnt_color_monotonic
1593
       based on fn_is_monotonic_proc_t is_monotonic,
1594
       which applies to intervals. */
1595
11.4M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
1596
11.4M
    if (ytop - ybot < pfs->decomposition_limit) /* Prevent an infinite color decomposition. */
1597
791k
        code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1598
10.7M
    else {
1599
10.7M
        bool monotonic_color_save = pfs->monotonic_color;
1600
10.7M
        bool linear_color_save = pfs->linear_color;
1601
1602
10.7M
        if (!pfs->monotonic_color) {
1603
2.91M
            code = isnt_color_monotonic(pfs, c0, c1);
1604
2.91M
            if (code < 0)
1605
3
                goto out;
1606
2.91M
            if (!code)
1607
2.37M
                pfs->monotonic_color = true;
1608
2.91M
        }
1609
10.7M
        if (pfs->monotonic_color && !pfs->linear_color) {
1610
5.32M
            code = is_color_linear(pfs, c0, c1);
1611
5.32M
            if (code < 0)
1612
0
                goto out;
1613
5.32M
            if (code > 0)
1614
5.30M
                pfs->linear_color =  true;
1615
5.32M
        }
1616
10.7M
        if (!pfs->unlinear && pfs->linear_color) {
1617
846k
            gx_device *pdev = pfs->dev;
1618
846k
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1619
846k
            gs_fill_attributes fa;
1620
846k
            gs_fixed_rect clip;
1621
1622
846k
            memset(fc, 0x99, sizeof(fc));
1623
1624
846k
            clip = pfs->rect;
1625
846k
            if (swap_axes) {
1626
236k
                fixed v;
1627
1628
236k
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1629
236k
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1630
                /* Don't need adjust_swapped_boundary here. */
1631
236k
            }
1632
846k
            clip.p.y = max(clip.p.y, ybot);
1633
846k
            clip.q.y = min(clip.q.y, ytop);
1634
846k
            fa.clip = &clip;
1635
846k
            fa.ht = NULL;
1636
846k
            fa.swap_axes = swap_axes;
1637
846k
            fa.lop = 0;
1638
846k
            fa.ystart = ybot;
1639
846k
            fa.yend = ytop;
1640
846k
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1641
846k
            if (code < 0)
1642
0
                goto out;
1643
846k
            if (code == 2) {
1644
                /* Must not happen. */
1645
0
                code=gs_note_error(gs_error_unregistered);
1646
0
                goto out;
1647
0
            }
1648
846k
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1649
846k
            if (code < 0)
1650
0
                goto out;
1651
846k
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1652
846k
                            &le->start, &le->end, &re->start, &re->end,
1653
846k
                            fc[0], fc[1], NULL, NULL);
1654
846k
            if (code == 1) {
1655
846k
                pfs->monotonic_color = monotonic_color_save;
1656
846k
                pfs->linear_color = linear_color_save;
1657
846k
                code = 0; /* The area is filled. */
1658
846k
                goto out;
1659
846k
            }
1660
0
            if (code < 0)
1661
0
                goto out;
1662
0
            else {      /* code == 0, the device requested to decompose the area. */
1663
0
                code = gs_note_error(gs_error_unregistered); /* Must not happen. */
1664
0
                goto out;
1665
0
            }
1666
0
        }
1667
9.85M
        if (!pfs->unlinear || !pfs->linear_color ||
1668
9.85M
                color_span(pfs, c0, c1) > pfs->smoothness) {
1669
3.10M
            fixed y = (ybot + ytop) / 2;
1670
1671
3.10M
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1672
3.10M
            if (code >= 0)
1673
3.10M
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1674
3.10M
        } else
1675
6.75M
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1676
9.85M
        pfs->monotonic_color = monotonic_color_save;
1677
9.85M
        pfs->linear_color = linear_color_save;
1678
9.85M
    }
1679
11.4M
out:
1680
11.4M
    pfs->inside = save_inside;
1681
11.4M
    release_colors_inline(pfs, color_stack_ptr, 1);
1682
11.4M
    return code;
1683
11.4M
}
1684
1685
static inline int
1686
linear_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_point q[4], int i0, int i1, int i2, int i3,
1687
                fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0, const patch_color_t *c1,
1688
                bool orient)
1689
8.09M
{
1690
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1691
8.09M
    gs_fixed_edge le, re;
1692
1693
8.09M
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1694
8.09M
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1695
8.09M
}
1696
1697
static int
1698
wedge_trap_decompose(patch_fill_state_t *pfs, gs_fixed_point q[4],
1699
        fixed ybot, fixed ytop, const patch_color_t *c0, const patch_color_t *c1,
1700
        bool swap_axes, bool self_intersecting)
1701
10.1M
{
1702
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1703
10.1M
    fixed dx1, dy1, dx2, dy2;
1704
10.1M
    bool orient;
1705
1706
10.1M
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1707
2.03M
        return 0;
1708
8.09M
    if (ybot == ytop)
1709
0
        return 0;
1710
8.09M
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1711
8.09M
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1712
8.09M
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1713
4.04M
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1714
4.04M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1715
4.05M
    } else {
1716
4.05M
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1717
1718
4.05M
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1719
4.05M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1720
4.05M
    }
1721
8.09M
}
1722
1723
static inline int
1724
fill_wedge_trap(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
1725
            const gs_fixed_point *q0, const gs_fixed_point *q1, const patch_color_t *c0, const patch_color_t *c1,
1726
            bool swap_axes, bool self_intersecting)
1727
10.1M
{
1728
    /* We assume that the width of the wedge is close to zero,
1729
       so we can ignore the slope when computing transversal distances. */
1730
10.1M
    gs_fixed_point p[4];
1731
10.1M
    const patch_color_t *cc0, *cc1;
1732
1733
10.1M
    if (p0->y < p1->y) {
1734
4.63M
        p[2] = *p0;
1735
4.63M
        p[3] = *p1;
1736
4.63M
        cc0 = c0;
1737
4.63M
        cc1 = c1;
1738
5.49M
    } else {
1739
5.49M
        p[2] = *p1;
1740
5.49M
        p[3] = *p0;
1741
5.49M
        cc0 = c1;
1742
5.49M
        cc1 = c0;
1743
5.49M
    }
1744
10.1M
    p[0] = *q0;
1745
10.1M
    p[1] = *q1;
1746
10.1M
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1747
10.1M
}
1748
1749
static void
1750
split_curve_s(const gs_fixed_point *pole, gs_fixed_point *q0, gs_fixed_point *q1, int pole_step)
1751
41.8M
{
1752
    /*  This copies a code fragment from split_curve_midpoint,
1753
        substituting another data type.
1754
     */
1755
    /*
1756
     * We have to define midpoint carefully to avoid overflow.
1757
     * (If it overflows, something really pathological is going
1758
     * on, but we could get infinite recursion that way....)
1759
     */
1760
41.8M
#define midpoint(a,b)\
1761
502M
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1762
41.8M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1763
41.8M
    fixed y12 = midpoint(pole[1 * pole_step].y, pole[2 * pole_step].y);
1764
1765
    /* q[0] and q[1] must not be the same as pole. */
1766
41.8M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1767
41.8M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1768
41.8M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1769
41.8M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1770
41.8M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1771
41.8M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1772
41.8M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1773
41.8M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1774
41.8M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1775
41.8M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1776
41.8M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1777
41.8M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1778
41.8M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1779
41.8M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1780
41.8M
#undef midpoint
1781
41.8M
}
1782
1783
static void
1784
split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1785
715k
{
1786
715k
    split_curve_s(pole, q0, q1, 1);
1787
715k
}
1788
1789
#ifdef SHADING_SWAP_AXES_FOR_PRECISION
1790
static inline void
1791
do_swap_axes(gs_fixed_point *p, int k)
1792
{
1793
    int i;
1794
1795
    for (i = 0; i < k; i++) {
1796
        p[i].x ^= p[i].y; p[i].y ^= p[i].x; p[i].x ^= p[i].y;
1797
    }
1798
}
1799
1800
static inline fixed
1801
span_x(const gs_fixed_point *p, int k)
1802
{
1803
    int i;
1804
    fixed xmin = p[0].x, xmax = p[0].x;
1805
1806
    for (i = 1; i < k; i++) {
1807
        xmin = min(xmin, p[i].x);
1808
        xmax = max(xmax, p[i].x);
1809
    }
1810
    return xmax - xmin;
1811
}
1812
1813
static inline fixed
1814
span_y(const gs_fixed_point *p, int k)
1815
{
1816
    int i;
1817
    fixed ymin = p[0].y, ymax = p[0].y;
1818
1819
    for (i = 1; i < k; i++) {
1820
        ymin = min(ymin, p[i].y);
1821
        ymax = max(ymax, p[i].y);
1822
    }
1823
    return ymax - ymin;
1824
}
1825
#endif
1826
1827
static inline fixed
1828
manhattan_dist(const gs_fixed_point *p0, const gs_fixed_point *p1)
1829
8.31M
{
1830
8.31M
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1831
1832
8.31M
    return max(dx, dy);
1833
8.31M
}
1834
1835
static inline int
1836
create_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1837
        const gs_fixed_point *p0, const gs_fixed_point *p1)
1838
2.33M
{
1839
2.33M
    if (l->end != NULL)
1840
0
        return_error(gs_error_unregistered); /* Must not happen. */
1841
2.33M
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1842
2.33M
    l->end = wedge_vertex_list_elem_reserve(pfs);
1843
2.33M
    if (l->beg == NULL)
1844
0
        return_error(gs_error_unregistered); /* Must not happen. */
1845
2.33M
    if (l->end == NULL)
1846
0
        return_error(gs_error_unregistered); /* Must not happen. */
1847
2.33M
    l->beg->prev = l->end->next = NULL;
1848
2.33M
    l->beg->next = l->end;
1849
2.33M
    l->end->prev = l->beg;
1850
2.33M
    l->beg->p = *p0;
1851
2.33M
    l->end->p = *p1;
1852
2.33M
    l->beg->level = l->end->level = 0;
1853
2.33M
    return 0;
1854
2.33M
}
1855
1856
static inline int
1857
insert_wedge_vertex_list_elem(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1858
                              const gs_fixed_point *p, wedge_vertex_list_elem_t **r)
1859
3.90M
{
1860
3.90M
    wedge_vertex_list_elem_t *e = wedge_vertex_list_elem_reserve(pfs);
1861
1862
    /* We have got enough free elements due to the preliminary decomposition
1863
       of curves to LAZY_WEDGES_MAX_LEVEL, see curve_samples. */
1864
3.90M
    if (e == NULL)
1865
0
        return_error(gs_error_unregistered); /* Must not happen. */
1866
3.90M
    if (l->beg->next != l->end)
1867
0
        return_error(gs_error_unregistered); /* Must not happen. */
1868
3.90M
    if (l->end->prev != l->beg)
1869
0
        return_error(gs_error_unregistered); /* Must not happen. */
1870
3.90M
    e->next = l->end;
1871
3.90M
    e->prev = l->beg;
1872
3.90M
    e->p = *p;
1873
3.90M
    e->level = max(l->beg->level, l->end->level) + 1;
1874
3.90M
    e->divide_count = 0;
1875
3.90M
    l->beg->next = l->end->prev = e;
1876
3.90M
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1877
3.90M
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1878
1879
3.90M
        if ((p->x - l->beg->p.x) * sx < 0)
1880
0
            return_error(gs_error_unregistered); /* Must not happen. */
1881
3.90M
        if ((p->y - l->beg->p.y) * sy < 0)
1882
0
            return_error(gs_error_unregistered); /* Must not happen. */
1883
3.90M
        if ((l->end->p.x - p->x) * sx < 0)
1884
0
            return_error(gs_error_unregistered); /* Must not happen. */
1885
3.90M
        if ((l->end->p.y - p->y) * sy < 0)
1886
0
            return_error(gs_error_unregistered); /* Must not happen. */
1887
3.90M
    }
1888
3.90M
    *r = e;
1889
3.90M
    return 0;
1890
3.90M
}
1891
1892
static inline int
1893
open_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1894
        const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm,
1895
        wedge_vertex_list_elem_t **r)
1896
5.30M
{
1897
5.30M
    wedge_vertex_list_elem_t *e;
1898
5.30M
    int code;
1899
1900
5.30M
    if (!l->last_side) {
1901
3.79M
        if (l->beg == NULL) {
1902
2.26M
            code = create_wedge_vertex_list(pfs, l, p0, p1);
1903
2.26M
            if (code < 0)
1904
0
                return code;
1905
2.26M
        }
1906
3.79M
        if (l->beg->p.x != p0->x)
1907
0
            return_error(gs_error_unregistered); /* Must not happen. */
1908
3.79M
        if (l->beg->p.y != p0->y)
1909
0
            return_error(gs_error_unregistered); /* Must not happen. */
1910
3.79M
        if (l->end->p.x != p1->x)
1911
0
            return_error(gs_error_unregistered); /* Must not happen. */
1912
3.79M
        if (l->end->p.y != p1->y)
1913
0
            return_error(gs_error_unregistered); /* Must not happen. */
1914
3.79M
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1915
3.79M
        if (code < 0)
1916
0
            return code;
1917
3.79M
        e->divide_count++;
1918
3.79M
    } else if (l->beg == NULL) {
1919
70.3k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1920
70.3k
        if (code < 0)
1921
0
            return code;
1922
70.3k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1923
70.3k
        if (code < 0)
1924
0
            return code;
1925
70.3k
        e->divide_count++;
1926
1.43M
    } else {
1927
1.43M
        if (l->beg->p.x != p1->x)
1928
0
            return_error(gs_error_unregistered); /* Must not happen. */
1929
1.43M
        if (l->beg->p.y != p1->y)
1930
0
            return_error(gs_error_unregistered); /* Must not happen. */
1931
1.43M
        if (l->end->p.x != p0->x)
1932
0
            return_error(gs_error_unregistered); /* Must not happen. */
1933
1.43M
        if (l->end->p.y != p0->y)
1934
0
            return_error(gs_error_unregistered); /* Must not happen. */
1935
1.43M
        if (l->beg->next == l->end) {
1936
34.6k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1937
34.6k
            if (code < 0)
1938
0
                return code;
1939
34.6k
            e->divide_count++;
1940
1.40M
        } else {
1941
1.40M
            e = wedge_vertex_list_find(l->beg, l->end,
1942
1.40M
                        max(l->beg->level, l->end->level) + 1);
1943
1.40M
            if (e == NULL)
1944
0
                return_error(gs_error_unregistered); /* Must not happen. */
1945
1.40M
            if (e->p.x != pm->x || e->p.y != pm->y)
1946
0
                return_error(gs_error_unregistered); /* Must not happen. */
1947
1.40M
            e->divide_count++;
1948
1.40M
        }
1949
1.43M
    }
1950
5.30M
    *r = e;
1951
5.30M
    return 0;
1952
5.30M
}
1953
1954
static inline int
1955
make_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1956
        wedge_vertex_list_t *l0, bool forth,
1957
        const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm)
1958
5.30M
{
1959
5.30M
    int code;
1960
1961
5.30M
    l->last_side = l0->last_side;
1962
5.30M
    if (!l->last_side ^ !forth) {
1963
3.02M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1964
3.02M
        l->beg = l0->beg;
1965
3.02M
    } else {
1966
2.28M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1967
2.28M
        l->end = l0->end;
1968
2.28M
    }
1969
5.30M
    return code;
1970
5.30M
}
1971
1972
static int fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
1973
            const patch_color_t *c0, const patch_color_t *c1);
1974
1975
static inline int
1976
close_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1977
        const patch_color_t *c0, const patch_color_t *c1)
1978
5.30M
{
1979
5.30M
    int code;
1980
1981
5.30M
    if (!l->last_side)
1982
3.79M
        return 0;
1983
1.50M
    code = fill_wedge_from_list(pfs, l, c1, c0);
1984
1.50M
    if (code < 0)
1985
0
        return code;
1986
1.50M
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1987
1.50M
    return 0;
1988
1.50M
}
1989
1990
static inline void
1991
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1992
5.30M
{
1993
5.30M
    if (!l->last_side ^ !forth) {
1994
3.02M
        l->beg = l->end;
1995
3.02M
        l->end = l0->end;
1996
3.02M
    } else {
1997
2.28M
        l->end = l->beg;
1998
2.28M
        l->beg = l0->beg;
1999
2.28M
    }
2000
5.30M
}
2001
2002
static inline int
2003
fill_triangle_wedge_aux(patch_fill_state_t *pfs,
2004
            const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
2005
5.06M
{   int code;
2006
5.06M
    const gs_fixed_point *p0, *p1, *p2;
2007
5.06M
    gs_fixed_point qq0, qq1, qq2;
2008
5.06M
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2009
5.06M
    bool swap_axes;
2010
2011
#   if SKIP_TEST
2012
        dbg_wedge_triangle_cnt++;
2013
#   endif
2014
5.06M
    if (dx > dy) {
2015
2.76M
        swap_axes = true;
2016
2.76M
        qq0.x = q0->p.y;
2017
2.76M
        qq0.y = q0->p.x;
2018
2.76M
        qq1.x = q1->p.y;
2019
2.76M
        qq1.y = q1->p.x;
2020
2.76M
        qq2.x = q2->p.y;
2021
2.76M
        qq2.y = q2->p.x;
2022
2.76M
        p0 = &qq0;
2023
2.76M
        p1 = &qq1;
2024
2.76M
        p2 = &qq2;
2025
2.76M
    } else {
2026
2.29M
        swap_axes = false;
2027
2.29M
        p0 = &q0->p;
2028
2.29M
        p1 = &q1->p;
2029
2.29M
        p2 = &q2->p;
2030
2.29M
    }
2031
    /* We decompose the thin triangle into 2 thin trapezoids.
2032
       An optimization with decomposing into 2 triangles
2033
       appears low useful, because the self_intersecting argument
2034
       with inline expansion does that job perfectly. */
2035
5.06M
    if (p0->y < p1->y) {
2036
2.31M
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2037
2.31M
        if (code < 0)
2038
0
            return code;
2039
2.31M
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2040
2.74M
    } else {
2041
2.74M
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2042
2.74M
        if (code < 0)
2043
0
            return code;
2044
2.74M
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2045
2.74M
    }
2046
5.06M
}
2047
2048
static inline int
2049
try_device_linear_color(patch_fill_state_t *pfs, bool wedge,
2050
        const shading_vertex_t *p0, const shading_vertex_t *p1,
2051
        const shading_vertex_t *p2)
2052
21.7M
{
2053
    /*  Returns :
2054
        <0 - error;
2055
        0 - success;
2056
        1 - decompose to linear color areas;
2057
        2 - decompose to constant color areas;
2058
     */
2059
21.7M
    int code;
2060
2061
21.7M
    if (pfs->unlinear)
2062
18.2M
        return 2;
2063
3.52M
    if (!wedge) {
2064
3.52M
        const gs_color_space *cs = pfs->direct_space;
2065
2066
3.52M
        if (cs != NULL) {
2067
3.52M
            float s0, s1, s2, s01, s012;
2068
2069
3.52M
            s0 = function_linearity(pfs, p0->c, p1->c);
2070
3.52M
            if (s0 > pfs->smoothness)
2071
10.3k
                return 1;
2072
3.51M
            s1 = function_linearity(pfs, p1->c, p2->c);
2073
3.51M
            if (s1 > pfs->smoothness)
2074
7.08k
                return 1;
2075
3.50M
            s2 = function_linearity(pfs, p2->c, p0->c);
2076
3.50M
            if (s2 > pfs->smoothness)
2077
138
                return 1;
2078
            /* fixme: check an inner color ? */
2079
3.50M
            s01 = max(s0, s1);
2080
3.50M
            s012 = max(s01, s2);
2081
3.50M
            if (pfs->cs_always_linear)
2082
597k
                code = 1;
2083
2.90M
            else
2084
2.90M
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2085
3.50M
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2086
3.50M
                                  pfs->smoothness - s012, pfs->icclink);
2087
3.50M
            if (code < 0)
2088
0
                return code;
2089
3.50M
            if (code == 0)
2090
10.3k
                return 1;
2091
3.50M
        }
2092
3.52M
    }
2093
3.49M
    {   gx_device *pdev = pfs->dev;
2094
3.49M
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2095
3.49M
        gs_fill_attributes fa;
2096
3.49M
        gx_device_color dc[3];
2097
2098
3.49M
        fa.clip = &pfs->rect;
2099
3.49M
        fa.ht = NULL;
2100
3.49M
        fa.swap_axes = false;
2101
3.49M
        fa.lop = 0;
2102
3.49M
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2103
3.49M
        if (code != 0)
2104
0
            return code;
2105
3.49M
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2106
3.49M
            dc[0].type == &gx_dc_type_data_devn))
2107
0
            return 2;
2108
3.49M
        if (!wedge) {
2109
3.49M
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2110
3.49M
            if (code != 0)
2111
0
                return code;
2112
3.49M
        }
2113
3.49M
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2114
3.49M
        if (code != 0)
2115
0
            return code;
2116
3.49M
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2117
3.49M
                        &p0->p, &p1->p, &p2->p,
2118
3.49M
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2119
3.49M
        if (code == 1)
2120
3.49M
            return 0; /* The area is filled. */
2121
0
        if (code < 0)
2122
0
            return code;
2123
0
        else /* code == 0, the device requested to decompose the area. */
2124
0
            return 1;
2125
0
    }
2126
0
}
2127
2128
static inline int
2129
fill_triangle_wedge(patch_fill_state_t *pfs,
2130
            const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
2131
8.35M
{
2132
8.35M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2133
8.35M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2134
3.29M
        return 0; /* Zero area. */
2135
    /*
2136
        Can't apply try_device_linear_color here
2137
        because didn't check is_color_linear.
2138
        Maybe need a decomposition.
2139
        Do same as for 'unlinear', and branch later.
2140
     */
2141
5.06M
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2142
8.35M
}
2143
2144
static inline int
2145
fill_triangle_wedge_from_list(patch_fill_state_t *pfs,
2146
    const wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
2147
    const wedge_vertex_list_elem_t *mid,
2148
    const patch_color_t *c0, const patch_color_t *c1)
2149
2.50M
{
2150
2.50M
    shading_vertex_t p[3];
2151
2.50M
    patch_color_t *c;
2152
2.50M
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2153
2.50M
    int code;
2154
2155
2.50M
    if (color_stack_ptr == NULL)
2156
0
        return_error(gs_error_unregistered); /* Must not happen. */
2157
2.50M
    p[2].c = c;
2158
2.50M
    p[0].p = beg->p;
2159
2.50M
    p[0].c = c0;
2160
2.50M
    p[1].p = end->p;
2161
2.50M
    p[1].c = c1;
2162
2.50M
    p[2].p = mid->p;
2163
2.50M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2164
2.50M
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2165
2.50M
    release_colors_inline(pfs, color_stack_ptr, 1);
2166
2.50M
    return code;
2167
2.50M
}
2168
2169
static int
2170
fill_wedge_from_list_rec(patch_fill_state_t *pfs,
2171
            wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
2172
            int level, const patch_color_t *c0, const patch_color_t *c1)
2173
4.94M
{
2174
4.94M
    if (beg->next == end)
2175
1.04M
        return 0;
2176
3.90M
    else if (beg->next->next == end) {
2177
3.35M
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2178
0
            return_error(gs_error_unregistered); /* Must not happen. */
2179
3.35M
        if (beg->next->divide_count != 1)
2180
1.39M
            return 0;
2181
1.96M
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2182
3.35M
    } else {
2183
550k
        gs_fixed_point p;
2184
550k
        wedge_vertex_list_elem_t *e;
2185
550k
        patch_color_t *c;
2186
550k
        int code;
2187
550k
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2188
2189
550k
        if (color_stack_ptr == NULL)
2190
0
            return_error(gs_error_unregistered); /* Must not happen. */
2191
550k
        p.x = (beg->p.x + end->p.x) / 2;
2192
550k
        p.y = (beg->p.y + end->p.y) / 2;
2193
550k
        e = wedge_vertex_list_find(beg, end, level + 1);
2194
550k
        if (e == NULL)
2195
0
            return_error(gs_error_unregistered); /* Must not happen. */
2196
550k
        if (e->p.x != p.x || e->p.y != p.y)
2197
0
            return_error(gs_error_unregistered); /* Must not happen. */
2198
550k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2199
550k
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2200
550k
        if (code >= 0)
2201
550k
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2202
550k
        if (code >= 0) {
2203
550k
            if (e->divide_count != 1 && e->divide_count != 2)
2204
0
                return_error(gs_error_unregistered); /* Must not happen. */
2205
550k
            if (e->divide_count == 1)
2206
540k
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2207
550k
        }
2208
550k
        release_colors_inline(pfs, color_stack_ptr, 1);
2209
550k
        return code;
2210
550k
    }
2211
4.94M
}
2212
2213
static int
2214
fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
2215
            const patch_color_t *c0, const patch_color_t *c1)
2216
3.84M
{
2217
3.84M
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2218
3.84M
                    max(l->beg->level, l->end->level), c0, c1);
2219
3.84M
}
2220
2221
static inline int
2222
terminate_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
2223
        const patch_color_t *c0, const patch_color_t *c1)
2224
47.6M
{
2225
47.6M
    if (l->beg != NULL) {
2226
2.33M
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2227
2228
2.33M
        if (code < 0)
2229
0
            return code;
2230
2.33M
        return release_wedge_vertex_list(pfs, l, 1);
2231
2.33M
    }
2232
45.3M
    return 0;
2233
47.6M
}
2234
2235
static int
2236
wedge_by_triangles(patch_fill_state_t *pfs, int ka,
2237
        const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1)
2238
665k
{   /* Assuming ka >= 2, see fill_wedges. */
2239
665k
    gs_fixed_point q[2][4];
2240
665k
    patch_color_t *c;
2241
665k
    shading_vertex_t p[3];
2242
665k
    int code;
2243
665k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2244
2245
665k
    if (color_stack_ptr == NULL)
2246
0
        return_error(gs_error_unregistered); /* Must not happen. */
2247
665k
    p[2].c = c;
2248
665k
    split_curve(pole, q[0], q[1]);
2249
665k
    p[0].p = pole[0];
2250
665k
    p[0].c = c0;
2251
665k
    p[1].p = pole[3];
2252
665k
    p[1].c = c1;
2253
665k
    p[2].p = q[0][3];
2254
665k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2255
665k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2256
665k
    if (code >= 0) {
2257
665k
        if (ka == 2)
2258
343k
            goto out;
2259
322k
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2260
322k
    }
2261
322k
    if (code >= 0)
2262
322k
        code = wedge_by_triangles(pfs, ka / 2, q[1], p[2].c, c1);
2263
665k
out:
2264
665k
    release_colors_inline(pfs, color_stack_ptr, 1);
2265
665k
    return code;
2266
322k
}
2267
2268
int
2269
mesh_padding(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
2270
            const patch_color_t *c0, const patch_color_t *c1)
2271
6.91M
{
2272
6.91M
    gs_fixed_point q0, q1;
2273
6.91M
    const patch_color_t *cc0, *cc1;
2274
6.91M
    fixed dx = p1->x - p0->x;
2275
6.91M
    fixed dy = p1->y - p0->y;
2276
6.91M
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2277
6.91M
    gs_fixed_edge le, re;
2278
6.91M
    const fixed adjust = INTERPATCH_PADDING;
2279
2280
6.91M
    if (swap_axes) {
2281
2.56M
        if (p0->x < p1->x) {
2282
1.04M
            q0.x = p0->y;
2283
1.04M
            q0.y = p0->x;
2284
1.04M
            q1.x = p1->y;
2285
1.04M
            q1.y = p1->x;
2286
1.04M
            cc0 = c0;
2287
1.04M
            cc1 = c1;
2288
1.51M
        } else {
2289
1.51M
            q0.x = p1->y;
2290
1.51M
            q0.y = p1->x;
2291
1.51M
            q1.x = p0->y;
2292
1.51M
            q1.y = p0->x;
2293
1.51M
            cc0 = c1;
2294
1.51M
            cc1 = c0;
2295
1.51M
        }
2296
4.35M
    } else if (p0->y < p1->y) {
2297
630k
        q0 = *p0;
2298
630k
        q1 = *p1;
2299
630k
        cc0 = c0;
2300
630k
        cc1 = c1;
2301
3.72M
    } else {
2302
3.72M
        q0 = *p1;
2303
3.72M
        q1 = *p0;
2304
3.72M
        cc0 = c1;
2305
3.72M
        cc1 = c0;
2306
3.72M
    }
2307
6.91M
    le.start.x = q0.x - adjust;
2308
6.91M
    re.start.x = q0.x + adjust;
2309
6.91M
    le.start.y = re.start.y = q0.y - adjust;
2310
6.91M
    le.end.x = q1.x - adjust;
2311
6.91M
    re.end.x = q1.x + adjust;
2312
6.91M
    le.end.y = re.end.y = q1.y + adjust;
2313
6.91M
    adjust_swapped_boundary(&re.start.x, swap_axes);
2314
6.91M
    adjust_swapped_boundary(&re.end.x, swap_axes);
2315
6.91M
    return decompose_linear_color(pfs, &le, &re, le.start.y, le.end.y, swap_axes, cc0, cc1);
2316
    /* fixme : for a better performance and quality, we would like to
2317
       consider the bar as an oriented one and to know at what side of it the spot resides.
2318
       If we know that, we could expand only to outside the spot.
2319
       Note that if the boundary has a self-intersection,
2320
       we still need to expand to both directions.
2321
     */
2322
6.91M
}
2323
2324
static inline void
2325
bbox_of_points(gs_fixed_rect *r,
2326
        const gs_fixed_point *p0, const gs_fixed_point *p1,
2327
        const gs_fixed_point *p2, const gs_fixed_point *p3)
2328
8.91M
{
2329
8.91M
    r->p.x = r->q.x = p0->x;
2330
8.91M
    r->p.y = r->q.y = p0->y;
2331
2332
8.91M
    if (r->p.x > p1->x)
2333
3.62M
        r->p.x = p1->x;
2334
8.91M
    if (r->q.x < p1->x)
2335
3.75M
        r->q.x = p1->x;
2336
8.91M
    if (r->p.y > p1->y)
2337
3.68M
        r->p.y = p1->y;
2338
8.91M
    if (r->q.y < p1->y)
2339
3.59M
        r->q.y = p1->y;
2340
2341
8.91M
    if (r->p.x > p2->x)
2342
2.00M
        r->p.x = p2->x;
2343
8.91M
    if (r->q.x < p2->x)
2344
1.91M
        r->q.x = p2->x;
2345
8.91M
    if (r->p.y > p2->y)
2346
1.90M
        r->p.y = p2->y;
2347
8.91M
    if (r->q.y < p2->y)
2348
2.02M
        r->q.y = p2->y;
2349
2350
8.91M
    if (p3 == NULL)
2351
7.08M
        return;
2352
2353
1.82M
    if (r->p.x > p3->x)
2354
405k
        r->p.x = p3->x;
2355
1.82M
    if (r->q.x < p3->x)
2356
441k
        r->q.x = p3->x;
2357
1.82M
    if (r->p.y > p3->y)
2358
383k
        r->p.y = p3->y;
2359
1.82M
    if (r->q.y < p3->y)
2360
417k
        r->q.y = p3->y;
2361
1.82M
}
2362
2363
static int
2364
fill_wedges_aux(patch_fill_state_t *pfs, int k, int ka,
2365
        const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1,
2366
        int wedge_type)
2367
394k
{
2368
394k
    int code;
2369
2370
394k
    if (k > 1) {
2371
167k
        gs_fixed_point q[2][4];
2372
167k
        patch_color_t *c;
2373
167k
        bool save_inside = pfs->inside;
2374
167k
        byte *color_stack_ptr;
2375
2376
167k
        if (!pfs->inside) {
2377
149k
            gs_fixed_rect r, r1;
2378
2379
149k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2380
149k
            r.p.x -= INTERPATCH_PADDING;
2381
149k
            r.p.y -= INTERPATCH_PADDING;
2382
149k
            r.q.x += INTERPATCH_PADDING;
2383
149k
            r.q.y += INTERPATCH_PADDING;
2384
149k
            r1 = r;
2385
149k
            rect_intersect(r, pfs->rect);
2386
149k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2387
118k
                return 0;
2388
30.6k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2389
30.6k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2390
9.54k
                pfs->inside = true;
2391
30.6k
        }
2392
49.3k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2393
49.3k
        if (color_stack_ptr == NULL)
2394
0
            return_error(gs_error_unregistered); /* Must not happen. */
2395
49.3k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2396
49.3k
        split_curve(pole, q[0], q[1]);
2397
49.3k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2398
49.3k
        if (code >= 0)
2399
49.3k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2400
49.3k
        release_colors_inline(pfs, color_stack_ptr, 1);
2401
49.3k
        pfs->inside = save_inside;
2402
49.3k
        return code;
2403
226k
    } else {
2404
226k
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2405
214k
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2406
214k
            if (code < 0)
2407
1
                return code;
2408
214k
        }
2409
226k
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2410
21.5k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2411
204k
        return 0;
2412
226k
    }
2413
394k
}
2414
2415
static int
2416
fill_wedges(patch_fill_state_t *pfs, int k0, int k1,
2417
        const gs_fixed_point *pole, int pole_step,
2418
        const patch_color_t *c0, const patch_color_t *c1,
2419
        int wedge_type)
2420
4.16M
{
2421
    /* Generate wedges between 2 variants of a curve flattening. */
2422
    /* k0, k1 is a power of 2. */
2423
4.16M
    gs_fixed_point p[4];
2424
2425
4.16M
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2426
3.86M
        return 0; /* Wedges are zero area. */
2427
295k
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2428
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2429
0
    }
2430
295k
    p[0] = pole[0];
2431
295k
    p[1] = pole[pole_step];
2432
295k
    p[2] = pole[pole_step * 2];
2433
295k
    p[3] = pole[pole_step * 3];
2434
295k
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2435
4.16M
}
2436
2437
static inline void
2438
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2439
152k
{
2440
152k
    q[0] = p->p[0][0]->p;
2441
152k
    q[1] = p->p[0][1]->p;
2442
152k
    q[2] = p->p[1][1]->p;
2443
152k
    q[3] = p->p[1][0]->p;
2444
152k
}
2445
2446
static inline void
2447
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2448
152k
{
2449
152k
    fixed y = s[0].y;
2450
152k
    int i = 0;
2451
2452
152k
    if (y > s[1].y)
2453
28.9k
        i = 1, y = s[1].y;
2454
152k
    if (y > s[2].y)
2455
15.3k
        i = 2, y = s[2].y;
2456
152k
    if (y > s[3].y)
2457
9.64k
        i = 3, y = s[3].y;
2458
152k
    q[0] = s[(i + 0) % 4];
2459
152k
    q[1] = s[(i + 1) % 4];
2460
152k
    q[2] = s[(i + 2) % 4];
2461
152k
    q[3] = s[(i + 3) % 4];
2462
152k
}
2463
2464
static int
2465
ordered_triangle(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re, patch_color_t *c)
2466
18.2M
{
2467
18.2M
    gs_fixed_edge ue;
2468
18.2M
    int code;
2469
18.2M
    gx_device_color dc;
2470
2471
#   if NOFILL_TEST
2472
        if (dbg_nofill)
2473
            return 0;
2474
#   endif
2475
18.2M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2476
18.2M
    if (code < 0)
2477
0
        return code;
2478
18.2M
    if (le->end.y < re->end.y) {
2479
8.78M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2480
8.78M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2481
8.78M
        if (code >= 0) {
2482
8.78M
            ue.start = le->end;
2483
8.78M
            ue.end = re->end;
2484
8.78M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2485
8.78M
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2486
8.78M
        }
2487
9.48M
    } else if (le->end.y > re->end.y) {
2488
8.15M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2489
8.15M
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2490
8.15M
        if (code >= 0) {
2491
8.15M
            ue.start = re->end;
2492
8.15M
            ue.end = le->end;
2493
8.15M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2494
8.15M
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2495
8.15M
        }
2496
8.15M
    } else
2497
1.32M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2498
1.32M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2499
18.2M
    return code;
2500
18.2M
}
2501
2502
static int
2503
constant_color_triangle(patch_fill_state_t *pfs,
2504
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2505
17.0M
{
2506
17.0M
    patch_color_t *c[2];
2507
17.0M
    gs_fixed_edge le, re;
2508
17.0M
    fixed dx0, dy0, dx1, dy1;
2509
17.0M
    const shading_vertex_t *pp;
2510
17.0M
    int i, code = 0;
2511
17.0M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2512
2513
17.0M
    if (color_stack_ptr == NULL)
2514
0
        return_error(gs_error_unregistered); /* Must not happen. */
2515
17.0M
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2516
17.0M
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2517
68.3M
    for (i = 0; i < 3; i++) {
2518
        /* fixme : does optimizer compiler expand this cycle ? */
2519
51.2M
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2520
18.2M
            le.start = re.start = p0->p;
2521
18.2M
            le.end = p1->p;
2522
18.2M
            re.end = p2->p;
2523
2524
18.2M
            dx0 = le.end.x - le.start.x;
2525
18.2M
            dy0 = le.end.y - le.start.y;
2526
18.2M
            dx1 = re.end.x - re.start.x;
2527
18.2M
            dy1 = re.end.y - re.start.y;
2528
18.2M
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2529
8.40M
                code = ordered_triangle(pfs, &le, &re, c[1]);
2530
9.86M
            else
2531
9.86M
                code = ordered_triangle(pfs, &re, &le, c[1]);
2532
18.2M
            if (code < 0)
2533
0
                break;
2534
18.2M
        }
2535
51.2M
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2536
51.2M
    }
2537
17.0M
    release_colors_inline(pfs, color_stack_ptr, 2);
2538
17.0M
    return code;
2539
17.0M
}
2540
2541
static inline int
2542
constant_color_quadrangle_aux(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting,
2543
        patch_color_t *c[3])
2544
152k
{
2545
    /* Assuming the XY span is restricted with curve_samples.
2546
       It is important for intersection_of_small_bars to compute faster. */
2547
152k
    gs_fixed_point q[4];
2548
152k
    fixed ry, ey;
2549
152k
    int code;
2550
152k
    bool swap_axes = false;
2551
152k
    gx_device_color dc;
2552
152k
    bool orient;
2553
2554
152k
    if (device_encodes_tags(pfs->dev)) {
2555
0
        dc.tag = (pfs->dev->graphics_type_tag & ~GS_DEVICE_ENCODES_TAGS);
2556
152k
    } else {
2557
152k
        dc.tag = 0;
2558
152k
    }
2559
2560
152k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2561
152k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2562
152k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2563
152k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2564
152k
    if (code < 0)
2565
0
        return code;
2566
152k
    {   gs_fixed_point qq[4];
2567
2568
152k
        make_vertices(qq, p);
2569
#ifdef SHADING_SWAP_AXES_FOR_PRECISION
2570
             /* Swapping axes may improve the precision,
2571
                but slows down due to the area expansion needed
2572
                in gx_shade_trapezoid. */
2573
            dx = span_x(qq, 4);
2574
            dy = span_y(qq, 4);
2575
            if (dy < dx) {
2576
                do_swap_axes(qq, 4);
2577
                swap_axes = true;
2578
            }
2579
#endif
2580
152k
        wrap_vertices_by_y(q, qq);
2581
152k
    }
2582
152k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2583
152k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2584
152k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2585
2586
152k
        if (g13 == h13) {
2587
360
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2588
360
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2589
2590
360
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2591
0
                return 0;
2592
360
            if (g23 != h23) {
2593
360
                orient = (g23 > h23);
2594
360
                if (q[2].y <= q[3].y) {
2595
360
                    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2596
0
                        return code;
2597
360
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2598
360
                } else {
2599
0
                    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2600
0
                        return code;
2601
0
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2602
0
                }
2603
360
            } else {
2604
0
                int64_t g12 = (int64_t)dx1 * dy2, h12 = (int64_t)dy1 * dx2;
2605
2606
0
                if (dx3 == 0 && dy3 == 0 && g12 == h12)
2607
0
                    return 0;
2608
0
                orient = (g12 > h12);
2609
0
                if (q[1].y <= q[2].y) {
2610
0
                    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2611
0
                        return code;
2612
0
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2613
0
                } else {
2614
0
                    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2615
0
                        return code;
2616
0
                    return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2617
0
                }
2618
0
            }
2619
360
        }
2620
152k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2621
152k
    }
2622
152k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2623
77.3k
        if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2624
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2625
0
                return code;
2626
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2627
0
                return code;
2628
0
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2629
0
                return code;
2630
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2631
77.3k
        } else {
2632
77.3k
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2633
0
                return code;
2634
77.3k
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2635
0
                return code;
2636
77.3k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2637
77.3k
        }
2638
77.3k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2639
34.7k
        if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2640
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2641
0
                return code;
2642
0
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2643
0
                return code;
2644
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, ry, q[3].y, swap_axes, &dc, orient)) < 0)
2645
0
                return code;
2646
0
            return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2647
34.7k
        } else {
2648
34.7k
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2649
0
                return code;
2650
34.7k
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2651
0
                return code;
2652
34.7k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2653
34.7k
        }
2654
40.2k
    } else if (q[2].y <= q[1].y && q[1].y <= q[3].y) {
2655
0
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2656
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2657
0
                return code;
2658
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2659
0
                return code;
2660
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2661
0
                return code;
2662
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2663
0
        } else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2664
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2665
0
                return code;
2666
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2667
0
                return code;
2668
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2669
0
                return code;
2670
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2671
0
        } else {
2672
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2673
0
                return code;
2674
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient)) < 0)
2675
0
                return code;
2676
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient);
2677
0
        }
2678
40.2k
    } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2679
24
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2680
            /* Same code as someone above. */
2681
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2682
0
                return code;
2683
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2684
0
                return code;
2685
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2686
0
                return code;
2687
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2688
24
        } else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 2, 1, &ry, &ey)) {
2689
            /* Same code as someone above. */
2690
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2691
0
                return code;
2692
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2693
0
                return code;
2694
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2695
0
                return code;
2696
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2697
24
        } else {
2698
24
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2699
0
                return code;
2700
24
            if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient)) < 0)
2701
0
                return code;
2702
24
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2703
24
        }
2704
40.1k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2705
39.9k
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 3, 2, &ry, &ey)) {
2706
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2707
0
                return code;
2708
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2709
0
                return code;
2710
0
            if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2711
0
                return code;
2712
0
            return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2713
39.9k
        } else {
2714
39.9k
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2715
0
                return code;
2716
39.9k
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[1].y, swap_axes, &dc, orient)) < 0)
2717
0
                return code;
2718
39.9k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2719
39.9k
        }
2720
39.9k
    } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2721
276
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2722
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2723
0
                return code;
2724
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2725
0
                return code;
2726
0
            if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2727
0
                return code;
2728
0
            return gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2729
276
        } else {
2730
276
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2731
0
                return code;
2732
276
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient)) < 0)
2733
0
                return code;
2734
276
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2735
276
        }
2736
276
    } else {
2737
        /* Impossible. */
2738
0
        return_error(gs_error_unregistered);
2739
0
    }
2740
152k
}
2741
2742
int
2743
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2744
152k
{
2745
152k
    patch_color_t *c[3];
2746
152k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2747
152k
    int code;
2748
2749
152k
    if (color_stack_ptr == NULL)
2750
0
        return_error(gs_error_unregistered); /* Must not happen. */
2751
152k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2752
152k
    release_colors_inline(pfs, color_stack_ptr, 3);
2753
152k
    return code;
2754
152k
}
2755
2756
static inline void
2757
divide_quadrangle_by_v(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2758
            shading_vertex_t q[2], const quadrangle_patch *p, patch_color_t *c[2])
2759
183k
{
2760
183k
    q[0].c = c[0];
2761
183k
    q[1].c = c[1];
2762
183k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2763
183k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2764
183k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2765
183k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2766
183k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2767
183k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2768
183k
    s0->p[0][0] = p->p[0][0];
2769
183k
    s0->p[0][1] = p->p[0][1];
2770
183k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2771
183k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2772
183k
    s1->p[1][0] = p->p[1][0];
2773
183k
    s1->p[1][1] = p->p[1][1];
2774
183k
}
2775
2776
static inline void
2777
divide_quadrangle_by_u(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2778
            shading_vertex_t q[2], const quadrangle_patch *p, patch_color_t *c[2])
2779
712k
{
2780
712k
    q[0].c = c[0];
2781
712k
    q[1].c = c[1];
2782
712k
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2783
712k
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2784
712k
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2785
712k
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2786
712k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2787
712k
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2788
712k
    s0->p[0][0] = p->p[0][0];
2789
712k
    s0->p[1][0] = p->p[1][0];
2790
712k
    s0->p[0][1] = s1->p[0][0] = &q[0];
2791
712k
    s0->p[1][1] = s1->p[1][0] = &q[1];
2792
712k
    s1->p[0][1] = p->p[0][1];
2793
712k
    s1->p[1][1] = p->p[1][1];
2794
712k
}
2795
2796
static inline int
2797
is_quadrangle_color_monotonic(const patch_fill_state_t *pfs, const quadrangle_patch *p,
2798
                              bool *not_monotonic_by_u, bool *not_monotonic_by_v)
2799
517k
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2800
517k
    int code, r;
2801
2802
517k
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2803
517k
    if (code <= 0)
2804
497k
        return code;
2805
19.4k
    r = code << pfs->function_arg_shift;
2806
19.4k
    if (r & 1)
2807
0
        *not_monotonic_by_u = true;
2808
19.4k
    if (r & 2)
2809
19.4k
        *not_monotonic_by_v = true;
2810
19.4k
    return !code;
2811
517k
}
2812
2813
static inline void
2814
divide_bar(patch_fill_state_t *pfs,
2815
        const shading_vertex_t *p0, const shading_vertex_t *p1, int radix, shading_vertex_t *p,
2816
        patch_color_t *c)
2817
16.6M
{
2818
    /* Assuming p.c == c for providing a non-const access. */
2819
16.6M
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2820
16.6M
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2821
16.6M
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2822
16.6M
}
2823
2824
static int
2825
triangle_by_4(patch_fill_state_t *pfs,
2826
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2827
        wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20,
2828
        double cd, fixed sd)
2829
24.9M
{
2830
24.9M
    shading_vertex_t p01, p12, p20;
2831
24.9M
    patch_color_t *c[3];
2832
24.9M
    wedge_vertex_list_t L01, L12, L20, L[3];
2833
24.9M
    bool inside_save = pfs->inside;
2834
24.9M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2835
24.9M
    int code = 0;
2836
24.9M
    byte *color_stack_ptr;
2837
24.9M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2838
2839
24.9M
    if (!inside) {
2840
7.08M
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2841
7.08M
        r1 = r;
2842
7.08M
        rect_intersect(r, pfs->rect);
2843
7.08M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2844
3.22M
            return 0;
2845
7.08M
    }
2846
21.7M
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2847
21.7M
    if(color_stack_ptr == NULL)
2848
0
        return_error(gs_error_unregistered);
2849
21.7M
    p01.c = c[0];
2850
21.7M
    p12.c = c[1];
2851
21.7M
    p20.c = c[2];
2852
21.7M
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2853
21.7M
    switch(code) {
2854
3.49M
        case 0: /* The area is filled. */
2855
3.49M
            goto out;
2856
18.2M
        case 2: /* decompose to constant color areas */
2857
            /* Halftoned devices may do with some bigger areas
2858
               due to imprecise representation of a contone color.
2859
               So we multiply the decomposition limit by 4 for a faster rendering. */
2860
18.2M
            if (sd < pfs->decomposition_limit * 4) {
2861
5.81M
                code = constant_color_triangle(pfs, p2, p0, p1);
2862
5.81M
                goto out;
2863
5.81M
            }
2864
12.4M
            if (pfs->Function != NULL) {
2865
1.46M
                double d01 = color_span(pfs, p1->c, p0->c);
2866
1.46M
                double d12 = color_span(pfs, p2->c, p1->c);
2867
1.46M
                double d20 = color_span(pfs, p0->c, p2->c);
2868
2869
1.46M
                if (d01 <= pfs->smoothness / COLOR_CONTIGUITY &&
2870
1.46M
                    d12 <= pfs->smoothness / COLOR_CONTIGUITY &&
2871
1.46M
                    d20 <= pfs->smoothness / COLOR_CONTIGUITY) {
2872
1.05M
                    code = constant_color_triangle(pfs, p2, p0, p1);
2873
1.05M
                    goto out;
2874
1.05M
                }
2875
10.9M
            } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY) {
2876
10.2M
                code = constant_color_triangle(pfs, p2, p0, p1);
2877
10.2M
                goto out;
2878
10.2M
            }
2879
1.15M
            break;
2880
1.15M
        case 1: /* decompose to linear color areas */
2881
27.9k
            if (sd < pfs->decomposition_limit) {
2882
7.47k
                code = constant_color_triangle(pfs, p2, p0, p1);
2883
7.47k
                goto out;
2884
7.47k
            }
2885
20.4k
            break;
2886
20.4k
        default: /* Error. */
2887
0
            goto out;
2888
21.7M
    }
2889
1.17M
    if (!inside) {
2890
324k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2891
324k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
2892
27.5k
            pfs->inside = true;
2893
324k
    }
2894
1.17M
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2895
1.17M
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2896
1.17M
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2897
1.17M
    if (LAZY_WEDGES) {
2898
1.17M
        init_wedge_vertex_list(L, count_of(L));
2899
1.17M
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2900
1.17M
        if (code >= 0)
2901
1.17M
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2902
1.17M
        if (code >= 0)
2903
1.17M
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2904
1.17M
    } else {
2905
0
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
2906
0
        if (code >= 0)
2907
0
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
2908
0
        if (code >= 0)
2909
0
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
2910
0
    }
2911
1.17M
    if (code >= 0)
2912
1.17M
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2913
1.17M
    if (code >= 0) {
2914
1.17M
        if (LAZY_WEDGES) {
2915
1.17M
            move_wedge(&L01, l01, true);
2916
1.17M
            move_wedge(&L20, l20, false);
2917
1.17M
        }
2918
1.17M
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2919
1.17M
    }
2920
1.17M
    if (code >= 0) {
2921
1.17M
        if (LAZY_WEDGES)
2922
1.17M
            move_wedge(&L12, l12, true);
2923
1.17M
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2924
1.17M
    }
2925
1.17M
    if (code >= 0) {
2926
1.17M
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2927
1.17M
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2928
1.17M
    }
2929
1.17M
    if (LAZY_WEDGES) {
2930
1.17M
        if (code >= 0)
2931
1.17M
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2932
1.17M
        if (code >= 0)
2933
1.17M
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2934
1.17M
        if (code >= 0)
2935
1.17M
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2936
1.17M
        if (code >= 0)
2937
1.17M
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2938
1.17M
        if (code >= 0)
2939
1.17M
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2940
1.17M
        if (code >= 0)
2941
1.17M
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2942
1.17M
    }
2943
1.17M
    pfs->inside = inside_save;
2944
21.7M
out:
2945
21.7M
    release_colors_inline(pfs, color_stack_ptr, 3);
2946
21.7M
    return code;
2947
1.17M
}
2948
2949
static inline int
2950
fill_triangle(patch_fill_state_t *pfs,
2951
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2952
        wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20)
2953
20.2M
{
2954
20.2M
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2955
20.2M
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2956
20.2M
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2957
20.2M
    fixed sd1 = max(sd01, sd12);
2958
20.2M
    fixed sd = max(sd1, sd20);
2959
20.2M
    double cd = 0;
2960
2961
#   if SKIP_TEST
2962
        dbg_triangle_cnt++;
2963
#   endif
2964
20.2M
    if (pfs->Function == NULL) {
2965
16.4M
        double d01 = color_span(pfs, p1->c, p0->c);
2966
16.4M
        double d12 = color_span(pfs, p2->c, p1->c);
2967
16.4M
        double d20 = color_span(pfs, p0->c, p2->c);
2968
16.4M
        double cd1 = max(d01, d12);
2969
2970
16.4M
        cd = max(cd1, d20);
2971
16.4M
    }
2972
20.2M
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2973
20.2M
}
2974
2975
static int
2976
small_mesh_triangle(patch_fill_state_t *pfs,
2977
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2978
2.51M
{
2979
2.51M
    int code;
2980
2.51M
    wedge_vertex_list_t l[3];
2981
2982
2.51M
    init_wedge_vertex_list(l, count_of(l));
2983
2.51M
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2984
2.51M
    if (code < 0)
2985
0
        return code;
2986
2.51M
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2987
2.51M
    if (code < 0)
2988
0
        return code;
2989
2.51M
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2990
2.51M
    if (code < 0)
2991
0
        return code;
2992
2.51M
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
2993
2.51M
}
2994
2995
int
2996
gx_init_patch_fill_state_for_clist(gx_device *dev, patch_fill_state_t *pfs, gs_memory_t *memory)
2997
0
{
2998
0
    int i;
2999
3000
0
    pfs->dev = dev;
3001
0
    pfs->pgs = NULL;
3002
0
    pfs->direct_space = NULL;
3003
0
    pfs->num_components = dev->color_info.num_components;
3004
    /* pfs->cc_max_error[GS_CLIENT_COLOR_MAX_COMPONENTS] unused */
3005
0
    pfs->pshm = NULL;
3006
0
    pfs->Function = NULL;
3007
0
    pfs->function_arg_shift = 0;
3008
0
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
3009
0
    pfs->n_color_args = 1; /* unused. */
3010
0
    pfs->max_small_coord = 0; /* unused. */
3011
0
    pfs->wedge_vertex_list_elem_buffer = NULL; /* fixme */
3012
0
    pfs->free_wedge_vertex = NULL; /* fixme */
3013
0
    pfs->wedge_vertex_list_elem_count = 0; /* fixme */
3014
0
    pfs->wedge_vertex_list_elem_count_max = 0; /* fixme */
3015
0
    for (i = 0; i < pfs->num_components; i++)
3016
0
        pfs->color_domain.paint.values[i] = (float)0x7fffffff;
3017
    /* decomposition_limit must be same as one in init_patch_fill_state */
3018
#ifdef MAX_SHADING_RESOLUTION
3019
    pfs->decomposition_limit = float2fixed(min(pfs->dev->HWResolution[0],
3020
                                               pfs->dev->HWResolution[1]) / MAX_SHADING_RESOLUTION);
3021
    pfs->decomposition_limit = max(pfs->decomposition_limit, fixed_1);
3022
#else
3023
0
    pfs->decomposition_limit = fixed_1;
3024
0
#endif
3025
0
    pfs->fixed_flat = 0; /* unused */
3026
0
    pfs->smoothness = 0; /* unused */
3027
0
    pfs->maybe_self_intersecting = false; /* unused */
3028
0
    pfs->monotonic_color = true;
3029
0
    pfs->linear_color = true;
3030
0
    pfs->unlinear = false; /* Because it is used when fill_linear_color_triangle was called. */
3031
0
    pfs->inside = false;
3032
0
    pfs->color_stack_size = 0;
3033
0
    pfs->color_stack_step = dev->color_info.num_components;
3034
0
    pfs->color_stack_ptr = NULL; /* fixme */
3035
0
    pfs->color_stack = NULL; /* fixme */
3036
0
    pfs->color_stack_limit = NULL; /* fixme */
3037
0
    pfs->pcic = NULL; /* Will do someday. */
3038
0
    pfs->trans_device = NULL;
3039
0
    pfs->icclink = NULL;
3040
0
    return alloc_patch_fill_memory(pfs, memory, NULL);
3041
0
}
3042
3043
/* A method for filling a small triangle that the device can't handle.
3044
   Used by clist playback. */
3045
int
3046
gx_fill_triangle_small(gx_device *dev, const gs_fill_attributes *fa,
3047
        const gs_fixed_point *p0, const gs_fixed_point *p1,
3048
        const gs_fixed_point *p2,
3049
        const frac31 *c0, const frac31 *c1, const frac31 *c2)
3050
0
{
3051
0
    patch_fill_state_t *pfs = fa->pfs;
3052
0
    patch_color_t c[3];
3053
0
    shading_vertex_t p[3];
3054
0
    uchar i;
3055
3056
    /* pfs->rect = *fa->clip; unused ? */
3057
0
    p[0].p = *p0;
3058
0
    p[1].p = *p1;
3059
0
    p[2].p = *p2;
3060
0
    p[0].c = &c[0];
3061
0
    p[1].c = &c[1];
3062
0
    p[2].c = &c[2];
3063
0
    c[0].t[0] = c[0].t[1] = c[1].t[0] = c[1].t[1] = c[2].t[0] = c[2].t[1] = 0; /* Dummy - not used. */
3064
0
    for (i = 0; i < dev->color_info.num_components; i++) {
3065
0
        c[0].cc.paint.values[i] = (float)c0[i];
3066
0
        c[1].cc.paint.values[i] = (float)c1[i];
3067
0
        c[2].cc.paint.values[i] = (float)c2[i];
3068
0
    }
3069
    /* fixme: the cycle above converts frac31 values into floats.
3070
       We don't like this because (1) it misses lower bits,
3071
       and (2) fixed point values can be faster on some platforms.
3072
       We could fix it with coding a template for small_mesh_triangle
3073
       and its callees until patch_color_to_device_color_inline.
3074
    */
3075
    /* fixme : this function is called from gxclrast.c
3076
       after dev->procs.fill_linear_color_triangle returns 0 - "subdivide".
3077
       After few moments small_mesh_triangle indirectly calls
3078
       same function with same arguments as a part of
3079
       try_device_linear_color in triangle_by_4.
3080
       Obviusly it will return zero again.
3081
       Actually we don't need the second call,
3082
       so optimize with skipping the second call.
3083
     */
3084
0
    return small_mesh_triangle(pfs, &p[0], &p[1], &p[2]);
3085
0
}
3086
3087
static int
3088
mesh_triangle_rec(patch_fill_state_t *pfs,
3089
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
3090
3.03M
{
3091
3.03M
    pfs->unlinear = !is_linear_color_applicable(pfs);
3092
3.03M
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3093
3.03M
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3094
3.03M
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3095
2.51M
        return small_mesh_triangle(pfs, p0, p1, p2);
3096
522k
    else {
3097
        /* Subdivide into 4 triangles with 3 triangle non-lazy wedges.
3098
           Doing so against the wedge_vertex_list_elem_buffer overflow.
3099
           We could apply a smarter method, dividing long sides
3100
           with no wedges and short sides with lazy wedges.
3101
           This needs to start wedges dynamically when
3102
           a side becomes short. We don't do so because the
3103
           number of checks per call significantly increases
3104
           and the logics is complicated, but the performance
3105
           advantage appears small due to big meshes are rare.
3106
         */
3107
522k
        shading_vertex_t p01, p12, p20;
3108
522k
        patch_color_t *c[3];
3109
522k
        int code;
3110
522k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3111
3112
522k
        if (color_stack_ptr == NULL)
3113
0
            return_error(gs_error_unregistered); /* Must not happen. */
3114
522k
        p01.c = c[0];
3115
522k
        p12.c = c[1];
3116
522k
        p20.c = c[2];
3117
522k
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3118
522k
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3119
522k
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3120
522k
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3121
522k
        if (code >= 0)
3122
522k
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3123
522k
        if (code >= 0)
3124
522k
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3125
522k
        if (code >= 0)
3126
522k
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3127
522k
        if (code >= 0)
3128
522k
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3129
522k
        if (code >= 0)
3130
522k
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3131
522k
        if (code >= 0)
3132
522k
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3133
522k
        release_colors_inline(pfs, color_stack_ptr, 3);
3134
522k
        return code;
3135
522k
    }
3136
3.03M
}
3137
3138
int
3139
mesh_triangle(patch_fill_state_t *pfs,
3140
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
3141
943k
{
3142
943k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3143
943k
            gxdso_pattern_shading_area, NULL, 0) > 0) {
3144
        /* Inform the device with the shading coverage area.
3145
           First compute the sign of the area, because
3146
           all areas to be clipped in same direction. */
3147
0
        gx_device *pdev = pfs->dev;
3148
0
        gx_path path;
3149
0
        int code;
3150
0
        fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
3151
0
        fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
3152
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3153
3154
0
        gx_path_init_local(&path, pdev->memory);
3155
0
        code = gx_path_add_point(&path, p0->p.x, p0->p.y);
3156
0
        if (code >= 0 && s1 >= 0)
3157
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3158
0
        if (code >= 0)
3159
0
            code = gx_path_add_line(&path, p2->p.x, p2->p.y);
3160
0
        if (code >= 0 && s1 < 0)
3161
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3162
0
        if (code >= 0)
3163
0
            code = gx_path_close_subpath(&path);
3164
0
        if (code >= 0)
3165
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3166
0
        gx_path_free(&path, "mesh_triangle");
3167
0
        if (code < 0)
3168
0
            return code;
3169
0
    }
3170
943k
    return mesh_triangle_rec(pfs, p0, p1, p2);
3171
943k
}
3172
3173
static inline int
3174
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3175
3.85M
{
3176
3.85M
    shading_vertex_t p0001, p1011, q;
3177
3.85M
    patch_color_t *c[3];
3178
3.85M
    wedge_vertex_list_t l[4];
3179
3.85M
    int code;
3180
3.85M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3181
3182
3.85M
    if(color_stack_ptr == NULL)
3183
0
        return_error(gs_error_unregistered); /* Must not happen. */
3184
3.85M
    p0001.c = c[0];
3185
3.85M
    p1011.c = c[1];
3186
3.85M
    q.c = c[2];
3187
3.85M
    init_wedge_vertex_list(l, count_of(l));
3188
3.85M
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3189
3.85M
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3190
3.85M
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3191
3.85M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3192
3.85M
    if (code >= 0) {
3193
3.85M
        l[0].last_side = true;
3194
3.85M
        l[3].last_side = true;
3195
3.85M
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3196
3.85M
    }
3197
3.85M
    if (code >= 0) {
3198
3.85M
        l[1].last_side = true;
3199
3.85M
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3200
3.85M
    }
3201
3.85M
    if (code >= 0) {
3202
3.85M
        l[2].last_side = true;
3203
3.85M
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3204
3.85M
    }
3205
3.85M
    if (code >= 0)
3206
3.85M
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3207
3.85M
    if (code >= 0)
3208
3.85M
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3209
3.85M
    if (code >= 0)
3210
3.85M
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3211
3.85M
    if (code >= 0)
3212
3.85M
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3213
3.85M
    release_colors_inline(pfs, color_stack_ptr, 3);
3214
3.85M
    return code;
3215
3.85M
}
3216
3217
static inline int
3218
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3219
1.18M
{
3220
1.18M
    wedge_vertex_list_t l;
3221
1.18M
    int code;
3222
3223
1.18M
    init_wedge_vertex_list(&l, 1);
3224
1.18M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3225
1.18M
    if (code < 0)
3226
0
        return code;
3227
1.18M
    l.last_side = true;
3228
1.18M
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3229
1.18M
    if (code < 0)
3230
0
        return code;
3231
1.18M
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3232
1.18M
    if (code < 0)
3233
0
        return code;
3234
1.18M
    return 0;
3235
1.18M
}
3236
3237
static inline void
3238
make_quadrangle(const tensor_patch *p, shading_vertex_t qq[2][2],
3239
        wedge_vertex_list_t l[4], quadrangle_patch *q)
3240
4.77M
{
3241
4.77M
    qq[0][0].p = p->pole[0][0];
3242
4.77M
    qq[0][1].p = p->pole[0][3];
3243
4.77M
    qq[1][0].p = p->pole[3][0];
3244
4.77M
    qq[1][1].p = p->pole[3][3];
3245
4.77M
    qq[0][0].c = p->c[0][0];
3246
4.77M
    qq[0][1].c = p->c[0][1];
3247
4.77M
    qq[1][0].c = p->c[1][0];
3248
4.77M
    qq[1][1].c = p->c[1][1];
3249
4.77M
    q->p[0][0] = &qq[0][0];
3250
4.77M
    q->p[0][1] = &qq[0][1];
3251
4.77M
    q->p[1][0] = &qq[1][0];
3252
4.77M
    q->p[1][1] = &qq[1][1];
3253
4.77M
    q->l0001 = &l[0];
3254
4.77M
    q->l0111 = &l[1];
3255
4.77M
    q->l1110 = &l[2];
3256
4.77M
    q->l1000 = &l[3];
3257
4.77M
}
3258
3259
static inline int
3260
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3261
1.35M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3262
1.35M
    int code;
3263
3264
1.35M
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3265
1.35M
    if (code <= 0)
3266
0
        return code;
3267
1.35M
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3268
1.35M
}
3269
3270
static inline int
3271
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3272
117k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3273
117k
    int code;
3274
3275
117k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3276
117k
    if (code <= 0)
3277
25.2k
        return code;
3278
91.8k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3279
117k
}
3280
3281
static inline int
3282
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3283
108k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3284
108k
    int code;
3285
3286
108k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3287
108k
    if (code <= 0)
3288
19.0k
        return code;
3289
89.0k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3290
108k
}
3291
3292
typedef enum {
3293
    color_change_small,
3294
    color_change_gradient,
3295
    color_change_linear,
3296
    color_change_bilinear,
3297
    color_change_general
3298
} color_change_type_t;
3299
3300
static inline color_change_type_t
3301
quadrangle_color_change(const patch_fill_state_t *pfs, const quadrangle_patch *p,
3302
                        bool is_big_u, bool is_big_v, double size_u, double size_v,
3303
                        bool *divide_u, bool *divide_v)
3304
5.69M
{
3305
5.69M
    patch_color_t d0001, d1011, d;
3306
5.69M
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3307
5.69M
    double Du, Dv;
3308
3309
5.69M
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3310
5.69M
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3311
5.69M
    D0001 = color_norm(pfs, &d0001);
3312
5.69M
    D1011 = color_norm(pfs, &d1011);
3313
5.69M
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3314
5.69M
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3315
5.69M
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3316
5.69M
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3317
5.69M
    if (pfs->unlinear) {
3318
4.27M
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
3319
4.27M
            D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
3320
4.27M
            D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
3321
3.37M
            return color_change_small;
3322
903k
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
3323
190k
            if (!is_big_v) {
3324
                /* The color function looks uncontiguous. */
3325
47.3k
                return color_change_small;
3326
47.3k
            }
3327
143k
            *divide_v = true;
3328
143k
            return color_change_gradient;
3329
190k
        }
3330
713k
        if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
3331
697k
            if (!is_big_u) {
3332
                /* The color function looks uncontiguous. */
3333
3.49k
                return color_change_small;
3334
3.49k
            }
3335
693k
            *divide_u = true;
3336
693k
            return color_change_gradient;
3337
697k
        }
3338
713k
    }
3339
1.43M
    color_diff(pfs, &d0001, &d1011, &d);
3340
1.43M
    Du = max(D0001, D1011);
3341
1.43M
    Dv = max(D0010, D0111);
3342
1.43M
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3343
148k
        return color_change_small;
3344
1.28M
    if (Du <= pfs->smoothness / 8)
3345
22.8k
        return color_change_linear;
3346
1.26M
    if (Dv <= pfs->smoothness / 8)
3347
1.16M
        return color_change_linear;
3348
99.6k
    D = color_norm(pfs, &d);
3349
99.6k
    if (D <= pfs->smoothness)
3350
79.7k
        return color_change_bilinear;
3351
19.8k
#if 1
3352
19.8k
    if (Du > Dv && is_big_u)
3353
10.7k
        *divide_u = true;
3354
9.09k
    else if (Du < Dv && is_big_v)
3355
7.12k
        *divide_v = true;
3356
1.97k
    else if (is_big_u && size_u > size_v)
3357
837
        *divide_u = true;
3358
1.13k
    else if (is_big_v && size_v > size_u)
3359
1.13k
        *divide_v = true;
3360
0
    else if (is_big_u)
3361
0
        *divide_u = true;
3362
0
    else if (is_big_v)
3363
0
        *divide_v = true;
3364
0
    else {
3365
        /* The color function looks uncontiguous. */
3366
0
        return color_change_small;
3367
0
    }
3368
#else /* Disabled due to infinite recursion with -r200 09-57.PS
3369
         (Standard Test 6.4  - Range 6) (Test05). */
3370
    if (Du > Dv)
3371
        *divide_u = true;
3372
    else
3373
        *divide_v = true;
3374
#endif
3375
19.8k
    return color_change_general;
3376
19.8k
}
3377
3378
static int
3379
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3380
6.57M
{
3381
    /* The quadrangle is flattened enough by V and U, so ignore inner poles. */
3382
    /* Assuming the XY span is restricted with curve_samples.
3383
       It is important for intersection_of_small_bars to compute faster. */
3384
6.57M
    quadrangle_patch s0, s1;
3385
6.57M
    wedge_vertex_list_t l0, l1, l2;
3386
6.57M
    int code;
3387
6.57M
    bool divide_u = false, divide_v = false, big1 = big;
3388
6.57M
    shading_vertex_t q[2];
3389
6.57M
    bool monotonic_color_save = pfs->monotonic_color;
3390
6.57M
    bool linear_color_save = pfs->linear_color;
3391
6.57M
    bool inside_save = pfs->inside;
3392
6.57M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3393
6.57M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 = {{0,0},{0,0}};
3394
    /* Warning : pfs->monotonic_color is not restored on error. */
3395
3396
6.57M
    if (!inside) {
3397
1.67M
        bbox_of_points(&r, &p->p[0][0]->p, &p->p[0][1]->p, &p->p[1][0]->p, &p->p[1][1]->p);
3398
1.67M
        r1 = r;
3399
1.67M
        rect_intersect(r, pfs->rect);
3400
1.67M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3401
482k
            return 0; /* Outside. */
3402
1.67M
    }
3403
6.08M
    if (big) {
3404
        /* Likely 'big' is an unuseful rudiment due to curve_samples
3405
           restricts lengthes. We keep it for a while because its implementation
3406
           isn't obvious and its time consumption is invisibly small.
3407
         */
3408
4.34M
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3409
4.34M
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3410
4.34M
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3411
4.34M
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3412
4.34M
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3413
4.34M
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3414
4.34M
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3415
4.34M
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3416
3417
4.34M
        if (QUADRANGLES && pfs->maybe_self_intersecting) {
3418
0
            if (size_v > pfs->max_small_coord) {
3419
                /* constant_color_quadrangle can't handle big self-intersecting areas
3420
                   because we don't want int64_t in it. */
3421
0
                divide_v = true;
3422
0
            } else if (size_u > pfs->max_small_coord) {
3423
                /* constant_color_quadrangle can't handle big self-intersecting areas,
3424
                   because we don't want int64_t in it. */
3425
0
                divide_u = true;
3426
0
            } else
3427
0
                big1 = false;
3428
0
        } else
3429
4.34M
            big1 = false;
3430
4.34M
    }
3431
6.08M
    if (!big1) {
3432
6.08M
        bool is_big_u = false, is_big_v = false;
3433
6.08M
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3434
6.08M
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3435
6.08M
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3436
6.08M
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3437
6.08M
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3438
6.08M
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3439
6.08M
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3440
6.08M
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3441
6.08M
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3442
6.08M
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3443
3444
6.08M
        if (size_u > pfs->decomposition_limit)
3445
5.70M
            is_big_u = true;
3446
6.08M
        if (size_v > pfs->decomposition_limit)
3447
501k
            is_big_v = true;
3448
5.58M
        else if (!is_big_u)
3449
354k
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3450
339k
                        constant_color_quadrangle : triangles4)(pfs, p,
3451
354k
                            pfs->maybe_self_intersecting);
3452
5.73M
        if (!pfs->monotonic_color) {
3453
517k
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3454
3455
517k
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3456
517k
            if (code < 0)
3457
0
                return code;
3458
517k
            if (is_big_u)
3459
515k
                divide_u = not_monotonic_by_u;
3460
517k
            if (is_big_v)
3461
63.1k
                divide_v = not_monotonic_by_v;
3462
517k
            if (!divide_u && !divide_v)
3463
503k
                pfs->monotonic_color = true;
3464
517k
        }
3465
5.73M
        if (pfs->monotonic_color && !pfs->linear_color) {
3466
4.20M
            if (divide_v && divide_u) {
3467
0
                if (size_u > size_v)
3468
0
                    divide_v = false;
3469
0
                else
3470
0
                    divide_u = false;
3471
4.20M
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3472
1.41M
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3473
1.35M
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3474
1.35M
                    if (code < 0)
3475
0
                        return code;
3476
1.35M
                    divide_u = !code;
3477
1.35M
                }
3478
1.41M
                if (is_big_v) {
3479
117k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3480
117k
                    if (code < 0)
3481
0
                        return code;
3482
117k
                    divide_v = !code;
3483
117k
                }
3484
1.41M
                if (is_big_u && is_big_v) {
3485
108k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3486
108k
                    if (code < 0)
3487
0
                        return code;
3488
108k
                    if (!code) {
3489
19.0k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3490
6.65k
                            divide_u = true;
3491
6.65k
                            divide_v = false;
3492
12.4k
                        } else {
3493
12.4k
                            divide_v = true;
3494
12.4k
                            divide_u = false;
3495
12.4k
                        }
3496
19.0k
                    }
3497
108k
                }
3498
1.41M
            }
3499
4.20M
            if (!divide_u && !divide_v)
3500
4.18M
                pfs->linear_color = true;
3501
4.20M
        }
3502
5.73M
        if (!pfs->linear_color) {
3503
            /* go to divide. */
3504
5.69M
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3505
3.57M
            case color_change_small:
3506
3.57M
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3507
3.43M
                            constant_color_quadrangle : triangles4)(pfs, p,
3508
3.57M
                                pfs->maybe_self_intersecting);
3509
3.57M
                pfs->monotonic_color = monotonic_color_save;
3510
3.57M
                pfs->linear_color = linear_color_save;
3511
3.57M
                return code;
3512
79.7k
            case color_change_bilinear:
3513
79.7k
                if (!QUADRANGLES) {
3514
79.7k
                    code = triangles4(pfs, p, true);
3515
79.7k
                    pfs->monotonic_color = monotonic_color_save;
3516
79.7k
                    pfs->linear_color = linear_color_save;
3517
79.7k
                    return code;
3518
79.7k
                }
3519
1.18M
            case color_change_linear:
3520
1.18M
                if (!QUADRANGLES) {
3521
1.18M
                    code = triangles2(pfs, p, true);
3522
1.18M
                    pfs->monotonic_color = monotonic_color_save;
3523
1.18M
                    pfs->linear_color = linear_color_save;
3524
1.18M
                    return code;
3525
1.18M
                }
3526
837k
            case color_change_gradient:
3527
856k
            case color_change_general:
3528
856k
                ; /* goto divide. */
3529
5.69M
        }
3530
5.73M
    }
3531
895k
    if (!inside) {
3532
155k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3533
155k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3534
47.1k
            pfs->inside = true;
3535
155k
    }
3536
895k
    if (LAZY_WEDGES)
3537
895k
        init_wedge_vertex_list(&l0, 1);
3538
895k
    if (divide_v) {
3539
183k
        patch_color_t *c[2];
3540
183k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3541
3542
183k
        if(color_stack_ptr == NULL)
3543
0
            return_error(gs_error_unregistered); /* Must not happen. */
3544
183k
        q[0].c = c[0];
3545
183k
        q[1].c = c[1];
3546
183k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3547
183k
        if (LAZY_WEDGES) {
3548
183k
            code = make_wedge_median(pfs, &l1, p->l0111, true,  &p->p[0][1]->p, &p->p[1][1]->p, &s0.p[1][1]->p);
3549
183k
            if (code >= 0)
3550
183k
                code = make_wedge_median(pfs, &l2, p->l1000, false, &p->p[1][0]->p, &p->p[0][0]->p, &s0.p[1][0]->p);
3551
183k
            if (code >= 0) {
3552
183k
                s0.l1110 = s1.l0001 = &l0;
3553
183k
                s0.l0111 = s1.l0111 = &l1;
3554
183k
                s0.l1000 = s1.l1000 = &l2;
3555
183k
                s0.l0001 = p->l0001;
3556
183k
                s1.l1110 = p->l1110;
3557
183k
            }
3558
183k
        } else {
3559
0
            code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[1][0], s0.p[1][0]);
3560
0
            if (code >= 0)
3561
0
                code = fill_triangle_wedge(pfs, s0.p[0][1], s1.p[1][1], s0.p[1][1]);
3562
0
        }
3563
183k
        if (code >= 0)
3564
183k
            code = fill_quadrangle(pfs, &s0, big1);
3565
183k
        if (code >= 0) {
3566
183k
            if (LAZY_WEDGES) {
3567
183k
                l0.last_side = true;
3568
183k
                move_wedge(&l1, p->l0111, true);
3569
183k
                move_wedge(&l2, p->l1000, false);
3570
183k
            }
3571
183k
            code = fill_quadrangle(pfs, &s1, big1);
3572
183k
        }
3573
183k
        if (LAZY_WEDGES) {
3574
183k
            if (code >= 0)
3575
183k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3576
183k
            if (code >= 0)
3577
183k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3578
183k
            if (code >= 0)
3579
183k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3580
183k
            release_colors_inline(pfs, color_stack_ptr, 2);
3581
183k
        }
3582
712k
    } else if (divide_u) {
3583
712k
        patch_color_t *c[2];
3584
712k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3585
3586
712k
        if(color_stack_ptr == NULL)
3587
0
            return_error(gs_error_unregistered); /* Must not happen. */
3588
712k
        q[0].c = c[0];
3589
712k
        q[1].c = c[1];
3590
712k
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3591
712k
        if (LAZY_WEDGES) {
3592
712k
            code = make_wedge_median(pfs, &l1, p->l0001, true,  &p->p[0][0]->p, &p->p[0][1]->p, &s0.p[0][1]->p);
3593
712k
            if (code >= 0)
3594
712k
                code = make_wedge_median(pfs, &l2, p->l1110, false, &p->p[1][1]->p, &p->p[1][0]->p, &s0.p[1][1]->p);
3595
712k
            if (code >= 0) {
3596
712k
                s0.l0111 = s1.l1000 = &l0;
3597
712k
                s0.l0001 = s1.l0001 = &l1;
3598
712k
                s0.l1110 = s1.l1110 = &l2;
3599
712k
                s0.l1000 = p->l1000;
3600
712k
                s1.l0111 = p->l0111;
3601
712k
            }
3602
712k
        } else {
3603
0
            code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[0][1], s0.p[0][1]);
3604
0
            if (code >= 0)
3605
0
                code = fill_triangle_wedge(pfs, s0.p[1][0], s1.p[1][1], s0.p[1][1]);
3606
0
        }
3607
712k
        if (code >= 0)
3608
712k
            code = fill_quadrangle(pfs, &s0, big1);
3609
712k
        if (code >= 0) {
3610
712k
            if (LAZY_WEDGES) {
3611
712k
                l0.last_side = true;
3612
712k
                move_wedge(&l1, p->l0001, true);
3613
712k
                move_wedge(&l2, p->l1110, false);
3614
712k
            }
3615
712k
            code = fill_quadrangle(pfs, &s1, big1);
3616
712k
        }
3617
712k
        if (LAZY_WEDGES) {
3618
712k
            if (code >= 0)
3619
712k
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3620
712k
            if (code >= 0)
3621
712k
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3622
712k
            if (code >= 0)
3623
712k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3624
712k
            release_colors_inline(pfs, color_stack_ptr, 2);
3625
712k
        }
3626
712k
    } else
3627
0
        code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3628
0
                    constant_color_quadrangle : triangles4)(pfs, p,
3629
0
                        pfs->maybe_self_intersecting);
3630
895k
    pfs->monotonic_color = monotonic_color_save;
3631
895k
    pfs->linear_color = linear_color_save;
3632
895k
    pfs->inside = inside_save;
3633
895k
    return code;
3634
895k
}
3635
3636
/* This splits tensor patch p->pole[v][u] on u to give s0->pole[v][u] and s1->pole[v][u] */
3637
static inline void
3638
split_stripe(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p, patch_color_t *c[2])
3639
8.42M
{
3640
8.42M
    s0->c[0][1] = c[0];
3641
8.42M
    s0->c[1][1] = c[1];
3642
8.42M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3643
8.42M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3644
8.42M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3645
8.42M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3646
8.42M
    s0->c[0][0] = p->c[0][0];
3647
8.42M
    s0->c[1][0] = p->c[1][0];
3648
8.42M
    s1->c[0][0] = s0->c[0][1];
3649
8.42M
    s1->c[1][0] = s0->c[1][1];
3650
8.42M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3651
8.42M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3652
8.42M
    s1->c[0][1] = p->c[0][1];
3653
8.42M
    s1->c[1][1] = p->c[1][1];
3654
8.42M
}
3655
3656
/* This splits tensor patch p->pole[v][u] on v to give s0->pole[v][u] and s1->pole[v][u] */
3657
static inline void
3658
split_patch(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p, patch_color_t *c[2])
3659
1.86M
{
3660
1.86M
    s0->c[1][0] = c[0];
3661
1.86M
    s0->c[1][1] = c[1];
3662
1.86M
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3663
1.86M
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3664
1.86M
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3665
1.86M
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3666
1.86M
    s0->c[0][0] = p->c[0][0];
3667
1.86M
    s0->c[0][1] = p->c[0][1];
3668
1.86M
    s1->c[0][0] = s0->c[1][0];
3669
1.86M
    s1->c[0][1] = s0->c[1][1];
3670
1.86M
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3671
1.86M
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3672
1.86M
    s1->c[1][0] = p->c[1][0];
3673
1.86M
    s1->c[1][1] = p->c[1][1];
3674
1.86M
}
3675
3676
static inline void
3677
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3678
13.7M
{
3679
13.7M
    int i, j;
3680
3681
13.7M
    r->p.x = r->q.x = p->pole[0][0].x;
3682
13.7M
    r->p.y = r->q.y = p->pole[0][0].y;
3683
68.7M
    for (i = 0; i < 4; i++) {
3684
275M
        for (j = 0; j < 4; j++) {
3685
220M
            const gs_fixed_point *q = &p->pole[i][j];
3686
3687
220M
            if (r->p.x > q->x)
3688
37.6M
                r->p.x = q->x;
3689
220M
            if (r->p.y > q->y)
3690
33.7M
                r->p.y = q->y;
3691
220M
            if (r->q.x < q->x)
3692
36.9M
                r->q.x = q->x;
3693
220M
            if (r->q.y < q->y)
3694
35.7M
                r->q.y = q->y;
3695
220M
        }
3696
55.0M
    }
3697
13.7M
}
3698
3699
static int
3700
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3701
18.7M
{
3702
18.7M
    if (ku > 1) {
3703
14.0M
        tensor_patch s0, s1;
3704
14.0M
        patch_color_t *c[2];
3705
14.0M
        int code;
3706
14.0M
        byte *color_stack_ptr;
3707
14.0M
        bool save_inside = pfs->inside;
3708
3709
14.0M
        if (!pfs->inside) {
3710
11.8M
            gs_fixed_rect r, r1;
3711
3712
11.8M
            tensor_patch_bbox(&r, p);
3713
11.8M
            r1 = r;
3714
11.8M
            rect_intersect(r, pfs->rect);
3715
11.8M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3716
5.58M
                return 0;
3717
6.25M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3718
6.25M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3719
551k
                pfs->inside = true;
3720
6.25M
        }
3721
8.42M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3722
8.42M
        if(color_stack_ptr == NULL)
3723
0
            return_error(gs_error_unregistered); /* Must not happen. */
3724
8.42M
        split_stripe(pfs, &s0, &s1, p, c);
3725
8.42M
        code = decompose_stripe(pfs, &s0, ku / 2);
3726
8.42M
        if (code >= 0)
3727
8.42M
            code = decompose_stripe(pfs, &s1, ku / 2);
3728
8.42M
        release_colors_inline(pfs, color_stack_ptr, 2);
3729
8.42M
        pfs->inside = save_inside;
3730
8.42M
        return code;
3731
8.42M
    } else {
3732
4.77M
        quadrangle_patch q;
3733
4.77M
        shading_vertex_t qq[2][2];
3734
4.77M
        wedge_vertex_list_t l[4];
3735
4.77M
        int code;
3736
3737
4.77M
        init_wedge_vertex_list(l, count_of(l));
3738
4.77M
        make_quadrangle(p, qq, l, &q);
3739
#       if SKIP_TEST
3740
            dbg_quad_cnt++;
3741
#       endif
3742
4.77M
        code = fill_quadrangle(pfs, &q, true);
3743
4.77M
        if (code < 0)
3744
0
            return code;
3745
4.77M
        if (LAZY_WEDGES) {
3746
4.77M
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3747
4.77M
            if (code < 0)
3748
0
                return code;
3749
4.77M
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3750
4.77M
            if (code < 0)
3751
0
                return code;
3752
4.77M
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3753
4.77M
            if (code < 0)
3754
0
                return code;
3755
4.77M
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3756
4.77M
            if (code < 0)
3757
0
                return code;
3758
4.77M
        }
3759
4.77M
        return code;
3760
4.77M
    }
3761
18.7M
}
3762
3763
static int
3764
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3765
1.93M
{
3766
    /* The stripe is flattened enough by V, so ignore inner poles. */
3767
1.93M
    int ku[4], kum, code;
3768
3769
    /* We would like to apply iterations for enumerating the kum curve parts,
3770
       but the roundinmg errors would be too complicated due to
3771
       the dependence on the direction. Note that neigbour
3772
       patches may use the opposite direction for same bounding curve.
3773
       We apply the recursive dichotomy, in which
3774
       the rounding errors do not depend on the direction. */
3775
1.93M
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3776
1.93M
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3777
1.93M
    kum = max(ku[0], ku[3]);
3778
1.93M
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3779
1.93M
    if (code < 0)
3780
0
        return code;
3781
1.93M
    if (INTERPATCH_PADDING) {
3782
1.93M
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3783
1.93M
        if (code < 0)
3784
3
            return code;
3785
1.93M
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3786
1.93M
        if (code < 0)
3787
0
            return code;
3788
1.93M
    }
3789
1.93M
    code = decompose_stripe(pfs, p, kum);
3790
1.93M
    if (code < 0)
3791
0
        return code;
3792
1.93M
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3793
1.93M
}
3794
3795
static inline bool neqs(int *a, int b)
3796
4.34M
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3797
4.34M
    if (*a * b < 0)
3798
1.79M
        return true;
3799
2.55M
    if (!*a)
3800
38.8k
        *a = b;
3801
2.55M
    return false;
3802
4.34M
}
3803
3804
static inline int
3805
vector_pair_orientation(const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *p2)
3806
6.25M
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3807
6.25M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3808
6.25M
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3809
3810
6.25M
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3811
6.25M
}
3812
3813
static inline bool
3814
is_x_bended(const tensor_patch *p)
3815
1.90M
{
3816
1.90M
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3817
3818
1.90M
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3819
998k
        return true;
3820
904k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3821
651k
        return true;
3822
253k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3823
143k
        return true;
3824
3825
109k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3826
828
        return true;
3827
108k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3828
0
        return true;
3829
108k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3830
405
        return true;
3831
108k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3832
569
        return true;
3833
3834
107k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3835
640
        return true;
3836
107k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3837
0
        return true;
3838
107k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3839
624
        return true;
3840
106k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3841
481
        return true;
3842
3843
105k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3844
109
        return true;
3845
105k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3846
0
        return true;
3847
105k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3848
100
        return true;
3849
105k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3850
94
        return true;
3851
105k
    return false;
3852
105k
}
3853
3854
static inline bool
3855
is_y_bended(const tensor_patch *p)
3856
0
{
3857
0
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3858
3859
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3860
0
        return true;
3861
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3862
0
        return true;
3863
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3864
0
        return true;
3865
3866
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3867
0
        return true;
3868
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3869
0
        return true;
3870
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3871
0
        return true;
3872
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3873
0
        return true;
3874
3875
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3876
0
        return true;
3877
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3878
0
        return true;
3879
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3880
0
        return true;
3881
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3882
0
        return true;
3883
3884
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3885
0
        return true;
3886
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3887
0
        return true;
3888
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3889
0
        return true;
3890
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3891
0
        return true;
3892
0
    return false;
3893
0
}
3894
3895
static inline bool
3896
is_curve_x_small(const patch_fill_state_t *pfs, const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3897
11.3M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3898
11.3M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3899
11.3M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3900
11.3M
    fixed xmin =  min(xmin0, xmin1);
3901
11.3M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3902
11.3M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3903
11.3M
    fixed xmax =  max(xmax0, xmax1);
3904
3905
11.3M
    if(xmax - xmin <= pfs->decomposition_limit)
3906
9.73M
        return true;
3907
1.65M
    return false;
3908
11.3M
}
3909
3910
static inline bool
3911
is_curve_y_small(const patch_fill_state_t *pfs, const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3912
7.85M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3913
7.85M
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3914
7.85M
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3915
7.85M
    fixed ymin =  min(ymin0, ymin1);
3916
7.85M
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3917
7.85M
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3918
7.85M
    fixed ymax =  max(ymax0, ymax1);
3919
3920
7.85M
    if (ymax - ymin <= pfs->decomposition_limit)
3921
7.60M
        return true;
3922
243k
    return false;
3923
7.85M
}
3924
3925
static inline bool
3926
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3927
3.73M
{
3928
3.73M
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3929
853k
        return false;
3930
2.87M
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3931
368k
        return false;
3932
2.51M
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3933
237k
        return false;
3934
2.27M
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3935
199k
        return false;
3936
2.07M
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3937
84.8k
        return false;
3938
1.98M
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3939
71.3k
        return false;
3940
1.91M
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3941
48.0k
        return false;
3942
1.86M
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3943
39.3k
        return false;
3944
1.83M
    return true;
3945
1.86M
}
3946
3947
static int
3948
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3949
3.88M
{
3950
3.88M
    if (kv <= 1) {
3951
3.73M
        if (is_patch_narrow(pfs, p))
3952
1.83M
            return fill_stripe(pfs, p);
3953
1.90M
        if (!is_x_bended(p))
3954
105k
            return fill_stripe(pfs, p);
3955
1.90M
    }
3956
1.94M
    {   tensor_patch s0, s1;
3957
1.94M
        patch_color_t *c[2];
3958
1.94M
        shading_vertex_t q0, q1, q2;
3959
1.94M
        int code = 0;
3960
1.94M
        byte *color_stack_ptr;
3961
1.94M
        bool save_inside = pfs->inside;
3962
3963
1.94M
        if (!pfs->inside) {
3964
1.91M
            gs_fixed_rect r, r1;
3965
3966
1.91M
            tensor_patch_bbox(&r, p);
3967
1.91M
            r.p.x -= INTERPATCH_PADDING;
3968
1.91M
            r.p.y -= INTERPATCH_PADDING;
3969
1.91M
            r.q.x += INTERPATCH_PADDING;
3970
1.91M
            r.q.y += INTERPATCH_PADDING;
3971
1.91M
            r1 = r;
3972
1.91M
            rect_intersect(r, pfs->rect);
3973
1.91M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3974
77.5k
                return 0;
3975
1.83M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3976
1.83M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3977
8.73k
                pfs->inside = true;
3978
1.83M
        }
3979
1.86M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3980
1.86M
        if(color_stack_ptr == NULL)
3981
0
            return_error(gs_error_unregistered); /* Must not happen. */
3982
1.86M
        split_patch(pfs, &s0, &s1, p, c);
3983
1.86M
        if (kv0 <= 1) {
3984
1.81M
            q0.p = s0.pole[0][0];
3985
1.81M
            q0.c = s0.c[0][0];
3986
1.81M
            q1.p = s1.pole[3][0];
3987
1.81M
            q1.c = s1.c[1][0];
3988
1.81M
            q2.p = s0.pole[3][0];
3989
1.81M
            q2.c = s0.c[1][0];
3990
1.81M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3991
1.81M
        }
3992
1.86M
        if (kv1 <= 1 && code >= 0) {
3993
1.80M
            q0.p = s0.pole[0][3];
3994
1.80M
            q0.c = s0.c[0][1];
3995
1.80M
            q1.p = s1.pole[3][3];
3996
1.80M
            q1.c = s1.c[1][1];
3997
1.80M
            q2.p = s0.pole[3][3];
3998
1.80M
            q2.c = s0.c[1][1];
3999
1.80M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
4000
1.80M
        }
4001
1.86M
        if (code >= 0)
4002
1.86M
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
4003
1.86M
        if (code >= 0)
4004
1.86M
            code = fill_patch(pfs, &s1, kv / 2, kv0 / 2, kv1 / 2);
4005
        /* fixme : To provide the precise filling order, we must
4006
           decompose left and right wedges into pieces by intersections
4007
           with stripes, and fill each piece with its stripe.
4008
           A lazy wedge list would be fine for storing
4009
           the necessary information.
4010
4011
           If the patch is created from a radial shading,
4012
           the wedge color appears a constant, so the filling order
4013
           isn't important. The order is important for other
4014
           self-overlapping patches, but the visible effect is
4015
           just a slight narrowing of the patch (as its lower layer appears
4016
           visible through the upper layer near the side).
4017
           This kind of dropout isn't harmful, because
4018
           contacting self-overlapping patches are painted
4019
           one after one by definition, so that a side coverage break
4020
           appears unavoidable by definition.
4021
4022
           Delaying this improvement because it is low importance.
4023
         */
4024
1.86M
        release_colors_inline(pfs, color_stack_ptr, 2);
4025
1.86M
        pfs->inside = save_inside;
4026
1.86M
        return code;
4027
1.86M
    }
4028
1.86M
}
4029
4030
static inline int64_t
4031
lcp1(int64_t p0, int64_t p3)
4032
912k
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4033
912k
    return (p0 + p0 + p3);
4034
912k
}
4035
static inline int64_t
4036
lcp2(int64_t p0, int64_t p3)
4037
912k
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4038
912k
    return (p0 + p3 + p3);
4039
912k
}
4040
4041
static void
4042
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4043
583k
{
4044
583k
    if (pfs->Function) {
4045
182k
        c->t[0] = cc[0];
4046
182k
        c->t[1] = cc[1];
4047
182k
    } else
4048
401k
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4049
583k
}
4050
4051
static void
4052
make_tensor_patch(const patch_fill_state_t *pfs, tensor_patch *p, const patch_curve_t curve[4],
4053
           const gs_fixed_point interior[4])
4054
145k
{
4055
145k
    const gs_color_space *pcs = pfs->direct_space;
4056
4057
145k
    p->pole[0][0] = curve[0].vertex.p;
4058
145k
    p->pole[1][0] = curve[0].control[0];
4059
145k
    p->pole[2][0] = curve[0].control[1];
4060
145k
    p->pole[3][0] = curve[1].vertex.p;
4061
145k
    p->pole[3][1] = curve[1].control[0];
4062
145k
    p->pole[3][2] = curve[1].control[1];
4063
145k
    p->pole[3][3] = curve[2].vertex.p;
4064
145k
    p->pole[2][3] = curve[2].control[0];
4065
145k
    p->pole[1][3] = curve[2].control[1];
4066
145k
    p->pole[0][3] = curve[3].vertex.p;
4067
145k
    p->pole[0][2] = curve[3].control[0];
4068
145k
    p->pole[0][1] = curve[3].control[1];
4069
145k
    if (interior != NULL) {
4070
100k
        p->pole[1][1] = interior[0];
4071
100k
        p->pole[1][2] = interior[1];
4072
100k
        p->pole[2][2] = interior[2];
4073
100k
        p->pole[2][1] = interior[3];
4074
100k
    } else {
4075
45.6k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4076
45.6k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4077
45.6k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4078
45.6k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4079
45.6k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4080
45.6k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4081
45.6k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4082
45.6k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4083
45.6k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4084
45.6k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4085
45.6k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4086
45.6k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4087
45.6k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4088
45.6k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4089
45.6k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4090
45.6k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4091
4092
45.6k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4093
45.6k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4094
45.6k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4095
45.6k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4096
45.6k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4097
45.6k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4098
45.6k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4099
45.6k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4100
45.6k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4101
45.6k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4102
45.6k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4103
45.6k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4104
45.6k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4105
45.6k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4106
45.6k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4107
45.6k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4108
45.6k
    }
4109
145k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4110
145k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4111
145k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4112
145k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4113
145k
    patch_resolve_color_inline(p->c[0][0], pfs);
4114
145k
    patch_resolve_color_inline(p->c[0][1], pfs);
4115
145k
    patch_resolve_color_inline(p->c[1][0], pfs);
4116
145k
    patch_resolve_color_inline(p->c[1][1], pfs);
4117
145k
    if (!pfs->Function) {
4118
100k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4119
100k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4120
100k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4121
100k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4122
100k
    }
4123
145k
}
4124
4125
int
4126
gx_shade_background(gx_device *pdev, const gs_fixed_rect *rect,
4127
        const gx_device_color *pdevc, gs_logical_operation_t log_op)
4128
8
{
4129
8
    gs_fixed_edge le, re;
4130
4131
8
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4132
8
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4133
8
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4134
8
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4135
8
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4136
8
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4137
8
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4138
8
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4139
8
    return dev_proc(pdev, fill_trapezoid)(pdev,
4140
8
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4141
8
}
4142
4143
int
4144
patch_fill(patch_fill_state_t *pfs, const patch_curve_t curve[4],
4145
           const gs_fixed_point interior[4],
4146
           void (*transform) (gs_fixed_point *, const patch_curve_t[4],
4147
                              const gs_fixed_point[4], double, double))
4148
145k
{
4149
145k
    tensor_patch p;
4150
145k
    patch_color_t *c[4];
4151
145k
    int kv[4], kvm, ku[4], kum;
4152
145k
    int code = 0;
4153
145k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4154
4155
145k
    p.c[0][0] = c[0];
4156
145k
    p.c[0][1] = c[1];
4157
145k
    p.c[1][0] = c[2];
4158
145k
    p.c[1][1] = c[3];
4159
#if SKIP_TEST
4160
    dbg_patch_cnt++;
4161
    /*if (dbg_patch_cnt != 67 && dbg_patch_cnt != 78)
4162
        return 0;*/
4163
#endif
4164
    /* We decompose the patch into tiny quadrangles,
4165
       possibly inserting wedges between them against a dropout. */
4166
145k
    make_tensor_patch(pfs, &p, curve, interior);
4167
145k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4168
145k
    pfs->linear_color = false;
4169
145k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4170
145k
            gxdso_pattern_shading_area, NULL, 0) > 0) {
4171
        /* Inform the device with the shading coverage area.
4172
           First compute the sign of the area, because
4173
           all areas to be clipped in same direction. */
4174
0
        gx_device *pdev = pfs->dev;
4175
0
        gx_path path;
4176
0
        fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
4177
0
        fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
4178
0
        fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
4179
0
        fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
4180
0
        fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
4181
0
        fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
4182
0
        fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
4183
0
        fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
4184
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
4185
0
        int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
4186
0
        int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
4187
4188
0
        gx_path_init_local(&path, pdev->memory);
4189
0
        if (is_x_bended(&p) || is_y_bended(&p)) {
4190
            /* The patch possibly is self-overlapping,
4191
               so the patch coverage may fall outside the patch outline.
4192
               In this case we pass an empty path,
4193
               and the device must use a bitmap mask instead clipping. */
4194
0
        } else {
4195
0
            code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
4196
0
            for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
4197
0
                j = (i + s) % 4, jj = (s == 1 ? i : j);
4198
0
                if (curve[jj].straight)
4199
0
                    code = gx_path_add_line(&path, curve[j].vertex.p.x,
4200
0
                                                curve[j].vertex.p.y);
4201
0
                else
4202
0
                    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
4203
0
                                                    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
4204
0
                                                    curve[j].vertex.p.x,
4205
0
                                                    curve[j].vertex.p.y);
4206
0
            }
4207
0
            if (code >= 0)
4208
0
                code = gx_path_close_subpath(&path);
4209
0
        }
4210
0
        if (code >= 0)
4211
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
4212
0
        gx_path_free(&path, "patch_fill");
4213
0
        if (code < 0)
4214
0
            goto out;
4215
0
    }
4216
    /* How many subdividions of the patch in the u and v direction? */
4217
145k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4218
145k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4219
145k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4220
145k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4221
145k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4222
145k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4223
145k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4224
145k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4225
145k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4226
145k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4227
#   if NOFILL_TEST
4228
    dbg_nofill = false;
4229
#   endif
4230
145k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4231
145k
        interpatch_padding | inpatch_wedge);
4232
145k
    if (code >= 0) {
4233
        /* We would like to apply iterations for enumerating the kvm curve parts,
4234
           but the roundinmg errors would be too complicated due to
4235
           the dependence on the direction. Note that neigbour
4236
           patches may use the opposite direction for same bounding curve.
4237
           We apply the recursive dichotomy, in which
4238
           the rounding errors do not depend on the direction. */
4239
#       if NOFILL_TEST
4240
            dbg_nofill = false;
4241
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4242
            dbg_nofill = true;
4243
#       endif
4244
145k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4245
145k
    }
4246
145k
    if (code >= 0)
4247
145k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4248
145k
                interpatch_padding | inpatch_wedge);
4249
145k
out:
4250
145k
    release_colors_inline(pfs, color_stack_ptr, 4);
4251
145k
    return code;
4252
145k
}