Coverage Report

Created: 2025-06-10 06:58

/src/ghostpdl/base/gxshade6.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 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.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, 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
1.86k
{
87
1.86k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
1.86k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
1.86k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
1.86k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
1.86k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
1.86k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
1.86k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
1.86k
    pfs->color_stack_ptr = pfs->color_stack;
98
1.86k
    pfs->memory = memory;
99
1.86k
    return 0;
100
1.86k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
15.2M
{
105
15.2M
    int i;
106
15.2M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
49.1M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
33.9M
        c[i] = (patch_color_t *)ptr;
110
15.2M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
15.2M
    pfs->color_stack_ptr = ptr;
115
15.2M
    return ptr0;
116
15.2M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
42
{
121
42
    return reserve_colors_inline(pfs, c, n);
122
42
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
15.2M
{
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
15.2M
    pfs->color_stack_ptr = ptr;
132
15.2M
#endif
133
15.2M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
42
{
137
42
    release_colors_inline(pfs, ptr, n);
138
42
}
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
14.5k
{
145
14.5k
    int i, code = 0;
146
147
60.3k
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
45.8k
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
45.8k
        code = shade_next_color(cs, curves[i].vertex.cc);
150
45.8k
    }
151
14.5k
    return code;
152
14.5k
}
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
37.5k
{
158
37.5k
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
37.5k
    if (code >= 0)
161
37.5k
        code = shade_next_coords(cs, curve->control,
162
37.5k
                                 countof(curve->control));
163
37.5k
    return code;
164
37.5k
}
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
14.6k
{
174
14.6k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
14.6k
    int num_colors, code;
176
177
14.6k
    if (flag < 0) {
178
22
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
22
        return 1;               /* no more data */
181
22
    }
182
14.5k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
14.5k
    cs->first_patch = 0;
186
14.5k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
8.34k
        case 0:
190
8.34k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
8.34k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
8.34k
                )
193
1
                return code;
194
8.33k
            num_colors = 4;
195
8.33k
            goto vx;
196
1.85k
        case 1:
197
1.85k
            curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
198
1.85k
            goto v3;
199
2.02k
        case 2:
200
2.02k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
2.02k
            goto v3;
202
2.37k
        case 3:
203
2.37k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
6.24k
v3:         num_colors = 2;
205
14.5k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
14.5k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
14.5k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
14.5k
                (interior != 0 &&
209
14.5k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
14.5k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
14.5k
                                          num_colors)) < 0
212
14.5k
                )
213
23
                return code;
214
14.5k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
14.5k
    }
216
14.5k
    return 0;
217
14.5k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
406k
{
222
406k
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
406k
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
0
        return false;
226
406k
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
395k
        return false;
228
10.4k
    return true;
229
406k
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
1.86k
{
234
1.86k
    int code;
235
236
1.86k
    pfs->memory = memory;
237
1.86k
#   if LAZY_WEDGES
238
1.86k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
1.86k
        if (code < 0)
240
0
            return code;
241
1.86k
#   endif
242
1.86k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
1.86k
    code = allocate_color_stack(pfs, memory);
244
1.86k
    if (code < 0)
245
0
        return code;
246
1.86k
    if (pfs->unlinear || pcs == NULL)
247
456
        pfs->pcic = NULL;
248
1.41k
    else {
249
1.41k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
1.41k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
1.41k
    }
253
1.86k
    return 0;
254
1.86k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
1.86k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
1.86k
    const gs_color_space *pcs = pfs->direct_space;
261
1.86k
    gs_client_color fcc0, fcc1;
262
1.86k
    int i;
263
264
6.53k
    for (i = 0; i < pfs->num_components; i++) {
265
4.66k
        fcc0.paint.values[i] = -1000000;
266
4.66k
        fcc1.paint.values[i] = 1000000;
267
4.66k
    }
268
1.86k
    pcs->type->restrict_color(&fcc0, pcs);
269
1.86k
    pcs->type->restrict_color(&fcc1, pcs);
270
6.53k
    for (i = 0; i < pfs->num_components; i++)
271
4.66k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
1.86k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
1.86k
    pfs->maybe_self_intersecting = true;
274
1.86k
    pfs->monotonic_color = (pfs->Function == NULL);
275
1.86k
    pfs->function_arg_shift = 0;
276
1.86k
    pfs->linear_color = false;
277
1.86k
    pfs->inside = false;
278
1.86k
    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
1.86k
    pfs->decomposition_limit = fixed_1;
285
1.86k
#endif
286
1.86k
    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
1.86k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
1.86k
    pfs->color_stack_size = 0;
293
1.86k
    pfs->color_stack_step = 0;
294
1.86k
    pfs->color_stack_ptr = NULL;
295
1.86k
    pfs->color_stack = NULL;
296
1.86k
    pfs->color_stack_limit = NULL;
297
1.86k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
1.86k
    pfs->pcic = NULL;
299
1.86k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
1.86k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
1.86k
{
305
1.86k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
1.86k
#   if LAZY_WEDGES
307
1.86k
        wedge_vertex_list_elem_buffer_free(pfs);
308
1.86k
#   endif
309
1.86k
    if (pfs->color_stack)
310
1.86k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
1.86k
    if (pfs->pcic != NULL)
312
1.41k
        gs_color_index_cache_destroy(pfs->pcic);
313
1.86k
    return b;
314
1.86k
}
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
4.51M
{
320
4.51M
    if (pfs->Function) {
321
4.45M
        const gs_color_space *pcs = pfs->direct_space;
322
323
4.45M
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
4.45M
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
4.45M
    }
326
4.51M
}
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
19.2M
{
344
    /* The old code gives -IND on Intel. */
345
19.2M
    if (pfs->Function) {
346
3.86M
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
3.86M
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
3.86M
        patch_resolve_color_inline(ppcr, pfs);
349
15.4M
    } else {
350
15.4M
        int ci;
351
352
67.8M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
52.4M
            ppcr->cc.paint.values[ci] =
354
52.4M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
15.4M
    }
356
19.2M
}
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
2
{
446
2
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
2
    patch_fill_state_t state;
448
2
    shade_coord_stream_t cs;
449
2
    patch_curve_t curve[4];
450
2
    int code;
451
452
2
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
2
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
2
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
2
    state.Function = psh->params.Function;
459
2
    code = init_patch_fill_state(&state);
460
2
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
2
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
2
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
4
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
4
                                    curve, NULL)) == 0 &&
469
4
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
2
        ) {
471
2
        DO_NOTHING;
472
2
    }
473
2
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
2
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
2
    return min(code, 0);
477
2
}
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
44
{
535
44
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
44
    patch_fill_state_t state;
537
44
    shade_coord_stream_t cs;
538
44
    patch_curve_t curve[4];
539
44
    gs_fixed_point interior[4];
540
44
    int code;
541
542
44
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
44
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
44
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
44
    state.Function = psh->params.Function;
549
44
    code = init_patch_fill_state(&state);
550
44
    if(code < 0)
551
0
        return code;
552
44
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
44
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
14.6k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
14.6k
                                    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
14.5k
        gs_fixed_point swapped_interior[4];
561
562
14.5k
        swapped_interior[0] = interior[0];
563
14.5k
        swapped_interior[1] = interior[3];
564
14.5k
        swapped_interior[2] = interior[2];
565
14.5k
        swapped_interior[3] = interior[1];
566
14.5k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
14.5k
        if (code < 0)
568
0
            break;
569
14.5k
    }
570
44
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
44
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
44
    return min(code, 0);
574
44
}
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
1.86k
{
665
1.86k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
1.86k
    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
1.86k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
1.86k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
1.86k
            sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
681
1.86k
            "alloc_wedge_vertex_list_elem_buffer");
682
1.86k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
1.86k
    pfs->free_wedge_vertex = NULL;
685
1.86k
    pfs->wedge_vertex_list_elem_count = 0;
686
1.86k
    return 0;
687
1.86k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
1.86k
{
692
1.86k
    gs_memory_t *memory = pfs->memory;
693
694
1.86k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
1.86k
                "wedge_vertex_list_elem_buffer_free");
696
1.86k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
1.86k
    pfs->free_wedge_vertex = NULL;
698
1.86k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
3.87M
{
703
3.87M
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
3.87M
    if (e != NULL) {
706
3.82M
        pfs->free_wedge_vertex = e->next;
707
3.82M
        return e;
708
3.82M
    }
709
45.7k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
45.7k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
45.7k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
3.87M
{
717
3.87M
    e->next = pfs->free_wedge_vertex;
718
3.87M
    pfs->free_wedge_vertex = e;
719
3.87M
}
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
2.50M
{
725
2.50M
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
2.50M
    beg->next = end;
728
2.50M
    end->prev = beg;
729
4.48M
    for (; e != end; e = ee) {
730
1.98M
        ee = e->next;
731
1.98M
        wedge_vertex_list_elem_release(pfs, e);
732
1.98M
    }
733
2.50M
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
945k
{
738
945k
    int i;
739
740
1.89M
    for (i = 0; i < n; i++) {
741
945k
        wedge_vertex_list_t *l = ll + i;
742
743
945k
        if (l->beg != NULL) {
744
945k
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
945k
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
945k
            wedge_vertex_list_elem_release(pfs, l->beg);
748
945k
            wedge_vertex_list_elem_release(pfs, l->end);
749
945k
            l->beg = l->end = NULL;
750
945k
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
945k
    }
753
945k
    return 0;
754
945k
}
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.71M
{
760
1.71M
    wedge_vertex_list_elem_t *e = beg;
761
762
1.71M
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
4.58M
    for (; e != end; e = e->next)
765
4.58M
        if (e->level == level)
766
1.71M
            return e;
767
0
    return NULL;
768
1.71M
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
2.56M
{
773
2.56M
    memset(l, 0, sizeof(*l) * n);
774
2.56M
}
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
592k
{
785
592k
    curve_segment s;
786
592k
    int k;
787
788
592k
    s.p1.x = pole[pole_step].x;
789
592k
    s.p1.y = pole[pole_step].y;
790
592k
    s.p2.x = pole[pole_step * 2].x;
791
592k
    s.p2.y = pole[pole_step * 2].y;
792
592k
    s.pt.x = pole[pole_step * 3].x;
793
592k
    s.pt.y = pole[pole_step * 3].y;
794
592k
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
592k
    {
796
592k
#       if LAZY_WEDGES || QUADRANGLES
797
592k
            int k1;
798
592k
            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
592k
                      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
592k
                      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
592k
#       endif
802
803
592k
#       if LAZY_WEDGES
804
            /* Restrict lengths for a reasonable memory consumption : */
805
592k
            k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
806
592k
            k = max(k, k1);
807
592k
#       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
592k
    }
813
592k
    return 1 << k;
814
592k
}
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
3.72M
{
826
3.72M
    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
1.49M
        *b += fixed_epsilon;
836
1.49M
    }
837
3.72M
}
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
1.07M
{
844
1.07M
    if (!orient) {
845
498k
        le->start = q[vi0];
846
498k
        le->end = q[vi1];
847
498k
        re->start = q[vi2];
848
498k
        re->end = q[vi3];
849
572k
    } else {
850
572k
        le->start = q[vi2];
851
572k
        le->end = q[vi3];
852
572k
        re->start = q[vi0];
853
572k
        re->end = q[vi1];
854
572k
    }
855
1.07M
    adjust_swapped_boundary(&re->start.x, swap_axes);
856
1.07M
    adjust_swapped_boundary(&re->end.x, swap_axes);
857
1.07M
}
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
221k
{
864
221k
    gs_fixed_edge le, re;
865
221k
    int code;
866
221k
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
867
221k
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
868
221k
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
869
221k
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
870
871
221k
    if (ybot >= ytop)
872
49.8k
        return 0;
873
#   if NOFILL_TEST
874
        if (dbg_nofill)
875
            return 0;
876
#   endif
877
171k
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
878
171k
    if (!pfs->inside) {
879
50.2k
        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
50.2k
        if (le.start.x > xright) {
890
1.55k
            if (le.end.x > xright) {
891
7
                return 0;
892
7
            }
893
1.54k
            clip = true;
894
48.6k
        } else if (le.end.x > xright) {
895
1.18k
            clip = true;
896
1.18k
        }
897
50.2k
        if (le.start.x < xleft) {
898
3.36k
            if (le.end.x < xleft) {
899
2.14k
                le.start.x = xleft;
900
2.14k
                le.end.x   = xleft;
901
2.14k
                le.start.y = ybot;
902
2.14k
                le.end.y   = ytop;
903
2.14k
            } else {
904
1.21k
                clip = true;
905
1.21k
            }
906
46.8k
        } else if (le.end.x < xleft) {
907
1.43k
            clip = true;
908
1.43k
        }
909
50.2k
        if (re.start.x < xleft) {
910
1.47k
            if (re.end.x < xleft) {
911
0
                return 0;
912
0
            }
913
1.47k
            clip = true;
914
48.7k
        } else if (re.end.x < xleft) {
915
1.47k
            clip = true;
916
1.47k
        }
917
50.2k
        if (re.start.x > xright) {
918
3.13k
            if (re.end.x > xright) {
919
1.62k
                re.start.x = xright;
920
1.62k
                re.end.x   = xright;
921
1.62k
                re.start.y = ybot;
922
1.62k
                re.end.y   = ytop;
923
1.62k
            } else {
924
1.51k
                clip = true;
925
1.51k
            }
926
47.0k
        } else if (re.end.x > xright) {
927
1.07k
            clip = true;
928
1.07k
        }
929
50.2k
        if (clip)
930
6.96k
        {
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
6.96k
            gs_fixed_edge lenew, renew;
935
6.96k
            fixed ybl, ybr, ytl, ytr, ymid;
936
937
            /* Reduce the clipping region horizontally if possible. */
938
6.96k
            if (re.start.x > re.end.x) {
939
2.69k
                if (re.start.x < xright)
940
1.17k
                    xright = re.start.x;
941
4.27k
            } else if (re.end.x < xright)
942
1.68k
                xright = re.end.x;
943
6.96k
            if (le.start.x > le.end.x) {
944
2.65k
                if (le.end.x > xleft)
945
1.21k
                    xleft = le.end.x;
946
4.30k
            } else if (le.start.x > xleft)
947
1.43k
                xleft = le.start.x;
948
949
6.96k
            ybot = max(ybot, min(le.start.y, re.start.y));
950
6.96k
            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
6.96k
            if (ybot >= ytop)
987
0
                return 0;
988
            /* Follow the edges in, so that le.start.y == ybot etc. */
989
6.96k
            if (le.start.y < ybot) {
990
2.68k
                int round = ((le.end.x < le.start.x) ?
991
1.37k
                             (le.end.y-le.start.y-1) : 0);
992
2.68k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
993
2.68k
                                       (int64_t)(le.end.x-le.start.x)-round)/
994
2.68k
                                      (int64_t)(le.end.y-le.start.y));
995
2.68k
                le.start.y = ybot;
996
2.68k
            }
997
6.96k
            if (le.end.y > ytop) {
998
2.77k
                int round = ((le.end.x > le.start.x) ?
999
1.52k
                             (le.end.y-le.start.y-1) : 0);
1000
2.77k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1001
2.77k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1002
2.77k
                                    (int64_t)(le.end.y-le.start.y));
1003
2.77k
                le.end.y = ytop;
1004
2.77k
            }
1005
6.96k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1006
409
                le.start.x = xleft;
1007
409
                le.end.x   = xleft;
1008
409
                le.start.y = ybot;
1009
409
                le.end.y   = ytop;
1010
409
            }
1011
6.96k
            if (re.start.y < ybot) {
1012
2.78k
                int round = ((re.end.x > re.start.x) ?
1013
1.55k
                             (re.end.y-re.start.y-1) : 0);
1014
2.78k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1015
2.78k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1016
2.78k
                                      (int64_t)(re.end.y-re.start.y));
1017
2.78k
                re.start.y = ybot;
1018
2.78k
            }
1019
6.96k
            if (re.end.y > ytop) {
1020
2.89k
                int round = ((re.end.x < re.start.x) ?
1021
1.53k
                             (re.end.y-re.start.y-1) : 0);
1022
2.89k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1023
2.89k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1024
2.89k
                                    (int64_t)(re.end.y-re.start.y));
1025
2.89k
                re.end.y = ytop;
1026
2.89k
            }
1027
6.96k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1028
214
                re.start.x = xright;
1029
214
                re.end.x   = xright;
1030
214
                re.start.y = ybot;
1031
214
                re.end.y   = ytop;
1032
214
            }
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
6.96k
            if (le.start.x > re.start.x) {
1039
2.33k
                if (le.start.x == le.end.x) {
1040
1.21k
                    if (re.start.x == re.end.x)
1041
0
                        return 0;
1042
1.21k
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1043
1.21k
                                    (int64_t)(le.start.x-re.start.x)/
1044
1.21k
                                    (int64_t)(re.end.x-re.start.x));
1045
1.21k
                    re.start.x = le.start.x;
1046
1.21k
                } else {
1047
1.12k
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1048
1.12k
                                    (int64_t)(le.start.x-re.start.x)/
1049
1.12k
                                    (int64_t)(le.start.x-le.end.x));
1050
1.12k
                    le.start.x = re.start.x;
1051
1.12k
                }
1052
2.33k
                if (ybot >= ytop)
1053
742
                    return 0;
1054
1.59k
                le.start.y = ybot;
1055
1.59k
                re.start.y = ybot;
1056
1.59k
            }
1057
6.22k
            if (le.end.x > re.end.x) {
1058
1.51k
                if (le.start.x == le.end.x) {
1059
845
                    if (re.start.x == re.end.x)
1060
0
                        return 0;
1061
845
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1062
845
                                    (int64_t)(le.end.x-re.end.x)/
1063
845
                                    (int64_t)(re.start.x-re.end.x));
1064
845
                    re.end.x = le.end.x;
1065
845
                } else {
1066
665
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1067
665
                                    (int64_t)(le.end.x-re.end.x)/
1068
665
                                    (int64_t)(le.end.x-le.start.x));
1069
665
                    le.end.x = re.end.x;
1070
665
                }
1071
1.51k
                if (ybot >= ytop)
1072
633
                    return 0;
1073
877
                le.end.y = ytop;
1074
877
                re.end.y = ytop;
1075
877
            }
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
5.58k
            lenew.start.x = xleft;
1082
5.58k
            lenew.start.y = ybot;
1083
5.58k
            lenew.end.x   = xleft;
1084
5.58k
            lenew.end.y   = ytop;
1085
5.58k
            renew.start.x = xright;
1086
5.58k
            renew.start.y = ybot;
1087
5.58k
            renew.end.x   = xright;
1088
5.58k
            renew.end.y   = ytop;
1089
            /* Figure out where the left edge intersects with the left at
1090
             * the bottom */
1091
5.58k
            ybl = ybot;
1092
5.58k
            if (le.start.x > le.end.x) {
1093
2.02k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1094
2.02k
                               (int64_t)(le.end.y-le.start.y) /
1095
2.02k
                               (int64_t)(le.start.x-le.end.x));
1096
2.02k
                if (ybl > ytop)
1097
765
                    ybl = ytop;
1098
2.02k
            }
1099
            /* Figure out where the right edge intersects with the right at
1100
             * the bottom */
1101
5.58k
            ybr = ybot;
1102
5.58k
            if (re.start.x < re.end.x) {
1103
2.29k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1104
2.29k
                               (int64_t)(re.end.y-re.start.y) /
1105
2.29k
                               (int64_t)(re.end.x-re.start.x));
1106
2.29k
                if (ybr > ytop)
1107
1.08k
                    ybr = ytop;
1108
2.29k
            }
1109
            /* Figure out where the left edge intersects with the left at
1110
             * the top */
1111
5.58k
            ytl = ytop;
1112
5.58k
            if (le.end.x > le.start.x) {
1113
2.21k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1114
2.21k
                               (int64_t)(le.end.y-le.start.y) /
1115
2.21k
                               (int64_t)(le.end.x-le.start.x));
1116
2.21k
                if (ytl < ybot)
1117
962
                    ytl = ybot;
1118
2.21k
            }
1119
            /* Figure out where the right edge intersects with the right at
1120
             * the bottom */
1121
5.58k
            ytr = ytop;
1122
5.58k
            if (re.end.x < re.start.x) {
1123
2.21k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1124
2.21k
                               (int64_t)(re.end.y-re.start.y) /
1125
2.21k
                               (int64_t)(re.start.x-re.end.x));
1126
2.21k
                if (ytr < ybot)
1127
759
                    ytr = ybot;
1128
2.21k
            }
1129
            /* Check for the 2 cases where top and bottom diagonal extents
1130
             * overlap, and deal with them explicitly. */
1131
5.58k
            if (ytl < ybr) {
1132
                /*     |     |
1133
                 *  ---+-----+---
1134
                 *     | /222|
1135
                 *     |/111/|
1136
                 *     |000/ |
1137
                 *  ---+-----+---
1138
                 *     |     |
1139
                 */
1140
871
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1141
871
                                        &lenew, &re, ybot, ytl,
1142
871
                                        swap_axes, pdevc, pfs->pgs->log_op);
1143
871
                if (code < 0)
1144
0
                    return code;
1145
871
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1146
871
                                        &le, &re, ytl, ybr,
1147
871
                                        swap_axes, pdevc, pfs->pgs->log_op);
1148
871
                if (code < 0)
1149
0
                    return code;
1150
871
                ybot = ybr;
1151
871
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1152
871
                                        &le, &renew, ybr, ytop,
1153
871
                                        swap_axes, pdevc, pfs->pgs->log_op);
1154
4.71k
            } else if (ytr < ybl) {
1155
                /*     |     |
1156
                 *  ---+-----+----
1157
                 *     |555\ |
1158
                 *     |\444\|
1159
                 *     | \333|
1160
                 *  ---+-----+---
1161
                 *     |     |
1162
                 */
1163
817
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
817
                                        &le, &renew, ybot, ytr,
1165
817
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
817
                if (code < 0)
1167
0
                    return code;
1168
817
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1169
817
                                        &le, &re, ytr, ybl,
1170
817
                                        swap_axes, pdevc, pfs->pgs->log_op);
1171
817
                if (code < 0)
1172
0
                    return code;
1173
817
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1174
817
                                        &le, &re, ybl, ytop,
1175
817
                                        swap_axes, pdevc, pfs->pgs->log_op);
1176
817
            }
1177
            /* Fill in any section where both left and right edges are
1178
             * diagonal at the bottom */
1179
3.90k
            ymid = ybl;
1180
3.90k
            if (ymid > ybr)
1181
741
                ymid = ybr;
1182
3.90k
            if (ymid > ybot) {
1183
                /*     |\   |          |   /|
1184
                 *     | \6/|    or    |\6/ |
1185
                 *  ---+----+---    ---+----+---
1186
                 *     |    |          |    |
1187
                 */
1188
466
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1189
466
                                        &le, &re, ybot, ymid,
1190
466
                                        swap_axes, pdevc, pfs->pgs->log_op);
1191
466
                if (code < 0)
1192
0
                    return code;
1193
466
                ybot = ymid;
1194
466
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the top */
1197
3.90k
            ymid = ytl;
1198
3.90k
            if (ymid < ytr)
1199
772
                ymid = ytr;
1200
3.90k
            if (ymid < ytop) {
1201
                /*     |    |          |    |
1202
                 *  ---+----+---    ---+----+---
1203
                 *     |/7\ |    or    | /7\|
1204
                 *     |   \|          |/   |
1205
                 */
1206
557
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
557
                                        &le, &re, ymid, ytop,
1208
557
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
557
                if (code < 0)
1210
0
                    return code;
1211
557
                ytop = ymid;
1212
557
            }
1213
            /* Now do the single diagonal cases at the bottom */
1214
3.90k
            if (ybl > ybot) {
1215
                /*     |    |
1216
                 *     |\666|
1217
                 *  ---+----+---
1218
                 *     |    |
1219
                 */
1220
741
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1221
741
                                        &le, &renew, ybot, ybl,
1222
741
                                        swap_axes, pdevc, pfs->pgs->log_op);
1223
741
                if (code < 0)
1224
0
                    return code;
1225
741
                ybot = ybl;
1226
3.15k
            } else if (ybr > ybot) {
1227
                /*     |    |
1228
                 *     |777/|
1229
                 *  ---+----+---
1230
                 *     |    |
1231
                 */
1232
927
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1233
927
                                        &lenew, &re, ybot, ybr,
1234
927
                                        swap_axes, pdevc, pfs->pgs->log_op);
1235
927
                if (code < 0)
1236
0
                    return code;
1237
927
                ybot = ybr;
1238
927
            }
1239
            /* Now do the single diagonal cases at the top */
1240
3.90k
            if (ytl < ytop) {
1241
                /*     |    |
1242
                 *  ---+----+---
1243
                 *     |/888|
1244
                 *     |    |
1245
                 */
1246
772
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1247
772
                                        &le, &renew, ytl, ytop,
1248
772
                                        swap_axes, pdevc, pfs->pgs->log_op);
1249
772
                if (code < 0)
1250
0
                    return code;
1251
772
                ytop = ytl;
1252
3.12k
            } else if (ytr < ytop) {
1253
                /*     |    |
1254
                 *  ---+----+---
1255
                 *     |999\|
1256
                 *     |    |
1257
                 */
1258
847
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1259
847
                                        &lenew, &re, ytr, ytop,
1260
847
                                        swap_axes, pdevc, pfs->pgs->log_op);
1261
847
                if (code < 0)
1262
0
                    return code;
1263
847
                ytop = ytr;
1264
847
            }
1265
            /* And finally just whatever rectangular section is left over in
1266
             * the middle */
1267
3.90k
            if (ybot > ytop)
1268
0
                return 0;
1269
3.90k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1270
3.90k
                                        &lenew, &renew, ybot, ytop,
1271
3.90k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1272
3.90k
        }
1273
50.2k
    }
1274
164k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1275
164k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1276
171k
}
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
35.0M
#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
8.77M
{
1311
    /* Must return 2 if the color is not pure.
1312
       See try_device_linear_color.
1313
     */
1314
8.77M
    int code;
1315
8.77M
    gx_device_color devc;
1316
1317
8.77M
#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
8.77M
     if (frac_values) {
1345
1.43M
        int i;
1346
1.43M
  int n = pfs->dev->color_info.num_components;
1347
1.70M
  for (i = pfs->num_components; i < n; i++) {
1348
277k
            frac_values[i] = 0;
1349
277k
  }
1350
1.43M
    }
1351
8.77M
#endif
1352
1353
8.77M
    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
1354
0
        pdevc = &devc;
1355
8.77M
    if (pfs->pcic) {
1356
1.48M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1357
1.48M
        if (code < 0)
1358
0
            return code;
1359
1.48M
    }
1360
8.77M
    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
7.28M
        gs_client_color fcc;
1365
7.28M
        const gs_color_space *pcs = pfs->direct_space;
1366
1367
7.28M
        if (pcs != NULL) {
1368
1369
7.28M
            if (pdevc == NULL)
1370
0
                pdevc = &devc;
1371
7.28M
            memcpy(fcc.paint.values, c->cc.paint.values,
1372
7.28M
                        sizeof(fcc.paint.values[0]) * pfs->num_components);
1373
7.28M
            code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pgs,
1374
7.28M
                                      pfs->trans_device, gs_color_select_texture);
1375
7.28M
            if (code < 0)
1376
0
                return code;
1377
7.28M
            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
7.28M
        } 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
7.28M
    }
1401
8.77M
    return 0;
1402
8.77M
}
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
10.3M
{
1413
10.3M
    int n = pfs->num_components, i;
1414
10.3M
    double m;
1415
1416
    /* Dont want to copy colors, which are big things. */
1417
10.3M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1418
38.0M
    for (i = 1; i < n; i++)
1419
27.6M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1420
10.3M
    return m;
1421
10.3M
}
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
1.40M
{
1426
1.40M
    int n = pfs->num_components, i;
1427
1428
6.72M
    for (i = 0; i < n; i++)
1429
5.31M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1430
1.40M
}
1431
1432
static inline double
1433
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1434
1.23M
{
1435
1.23M
    int n = pfs->num_components, i;
1436
1.23M
    double m;
1437
1438
1.23M
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1439
4.64M
    for (i = 1; i < n; i++)
1440
3.41M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1441
1.23M
    return m;
1442
1.23M
}
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
529k
{   /* 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
529k
    uint mask;
1462
529k
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1463
1464
529k
    if (code >= 0)
1465
529k
        return mask;
1466
0
    return code;
1467
529k
}
1468
1469
static inline bool
1470
covers_pixel_centers(fixed ybot, fixed ytop)
1471
1.09M
{
1472
1.09M
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1473
1.09M
}
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
1.31M
{
1479
1.31M
    gx_device_color dc;
1480
1.31M
    int code;
1481
1482
#   if NOFILL_TEST
1483
        /* if (dbg_nofill)
1484
                return 0; */
1485
#   endif
1486
1487
1.31M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1488
1.31M
    if (code < 0)
1489
0
        return code;
1490
1491
1.31M
    dc.tag = device_current_tag(pfs->dev);
1492
1493
1.31M
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1494
1.31M
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1495
1.31M
}
1496
1497
static inline float
1498
function_linearity(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1499
1.84M
{
1500
1.84M
    float s = 0;
1501
1502
1.84M
    if (pfs->Function != NULL) {
1503
294k
        patch_color_t c;
1504
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1505
        /* unless it is 'static const' */
1506
294k
        static const float q[2] = {(float)0.3, (float)0.7};
1507
294k
        int i, j;
1508
1509
845k
        for (j = 0; j < count_of(q); j++) {
1510
571k
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1511
571k
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1512
571k
            patch_resolve_color_inline(&c, pfs);
1513
1.93M
            for (i = 0; i < pfs->num_components; i++) {
1514
1.38M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1515
1.38M
                float d = v - c.cc.paint.values[i];
1516
1.38M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1517
1518
1.38M
                if (s1 > pfs->smoothness)
1519
19.7k
                    return s1;
1520
1.36M
                if (s < s1)
1521
219k
                    s = s1;
1522
1.36M
            }
1523
571k
        }
1524
294k
    }
1525
1.82M
    return s;
1526
1.84M
}
1527
1528
static inline int
1529
is_color_linear(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1)
1530
1.12M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1531
1.12M
    if (pfs->unlinear)
1532
527k
        return 1; /* Disable this check. */
1533
595k
    else {
1534
595k
        const gs_color_space *cs = pfs->direct_space;
1535
595k
        int code;
1536
595k
        float s = function_linearity(pfs, c0, c1);
1537
1538
595k
        if (s > pfs->smoothness)
1539
10.2k
            return 0;
1540
585k
        if (pfs->cs_always_linear)
1541
0
            return 1;
1542
585k
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1543
585k
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1544
585k
        if (code <= 0)
1545
2.16k
            return code;
1546
583k
        return 1;
1547
585k
    }
1548
1.12M
}
1549
1550
static int
1551
decompose_linear_color(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1552
        fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0,
1553
        const patch_color_t *c1)
1554
3.36M
{
1555
    /* Assuming a very narrow trapezoid - ignore the transversal color variation. */
1556
    /* Assuming the XY span is restricted with curve_samples.
1557
       It is important for intersection_of_small_bars to compute faster. */
1558
3.36M
    int code;
1559
3.36M
    patch_color_t *c;
1560
3.36M
    byte *color_stack_ptr;
1561
3.36M
    bool save_inside = pfs->inside;
1562
1563
3.36M
    if (!pfs->inside) {
1564
2.59M
        gs_fixed_rect r, r1;
1565
1566
2.59M
        if(swap_axes) {
1567
1.05M
            r.p.y = min(le->start.x, le->end.x);
1568
1.05M
            r.p.x = min(le->start.y, le->end.y);
1569
1.05M
            r.q.y = max(re->start.x, re->end.x);
1570
1.05M
            r.q.x = max(re->start.y, re->end.y);
1571
1.54M
        } else {
1572
1.54M
            r.p.x = min(le->start.x, le->end.x);
1573
1.54M
            r.p.y = min(le->start.y, le->end.y);
1574
1.54M
            r.q.x = max(re->start.x, re->end.x);
1575
1.54M
            r.q.y = max(re->start.y, re->end.y);
1576
1.54M
        }
1577
2.59M
        r1 = r;
1578
2.59M
        rect_intersect(r, pfs->rect);
1579
2.59M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1580
1.11M
            return 0;
1581
1.47M
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1582
1.47M
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1583
295k
            pfs->inside = true;
1584
1.47M
    }
1585
2.24M
    color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
1586
2.24M
    if (color_stack_ptr == NULL)
1587
0
        return_error(gs_error_unregistered); /* Must not happen. */
1588
    /* Use the recursive decomposition due to isnt_color_monotonic
1589
       based on fn_is_monotonic_proc_t is_monotonic,
1590
       which applies to intervals. */
1591
2.24M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
1592
2.24M
    if (ytop - ybot < pfs->decomposition_limit) /* Prevent an infinite color decomposition. */
1593
73.1k
        code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1594
2.17M
    else {
1595
2.17M
        bool monotonic_color_save = pfs->monotonic_color;
1596
2.17M
        bool linear_color_save = pfs->linear_color;
1597
1598
2.17M
        if (!pfs->monotonic_color) {
1599
493k
            code = isnt_color_monotonic(pfs, c0, c1);
1600
493k
            if (code < 0)
1601
0
                goto out;
1602
493k
            if (!code)
1603
391k
                pfs->monotonic_color = true;
1604
493k
        }
1605
2.17M
        if (pfs->monotonic_color && !pfs->linear_color) {
1606
623k
            code = is_color_linear(pfs, c0, c1);
1607
623k
            if (code < 0)
1608
0
                goto out;
1609
623k
            if (code > 0)
1610
622k
                pfs->linear_color =  true;
1611
623k
        }
1612
2.17M
        if (!pfs->unlinear && pfs->linear_color) {
1613
96.7k
            gx_device *pdev = pfs->dev;
1614
96.7k
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1615
96.7k
            gs_fill_attributes fa;
1616
96.7k
            gs_fixed_rect clip;
1617
1618
96.7k
            memset(fc, 0x99, sizeof(fc));
1619
1620
96.7k
            clip = pfs->rect;
1621
96.7k
            if (swap_axes) {
1622
32.9k
                fixed v;
1623
1624
32.9k
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1625
32.9k
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1626
                /* Don't need adjust_swapped_boundary here. */
1627
32.9k
            }
1628
96.7k
            clip.p.y = max(clip.p.y, ybot);
1629
96.7k
            clip.q.y = min(clip.q.y, ytop);
1630
96.7k
            fa.clip = &clip;
1631
96.7k
            fa.ht = NULL;
1632
96.7k
            fa.swap_axes = swap_axes;
1633
96.7k
            fa.lop = 0;
1634
96.7k
            fa.ystart = ybot;
1635
96.7k
            fa.yend = ytop;
1636
96.7k
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1637
96.7k
            if (code < 0)
1638
0
                goto out;
1639
96.7k
            if (code == 2) {
1640
                /* Must not happen. */
1641
0
                code=gs_note_error(gs_error_unregistered);
1642
0
                goto out;
1643
0
            }
1644
96.7k
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1645
96.7k
            if (code < 0)
1646
0
                goto out;
1647
96.7k
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1648
96.7k
                            &le->start, &le->end, &re->start, &re->end,
1649
96.7k
                            fc[0], fc[1], NULL, NULL);
1650
96.7k
            if (code == 1) {
1651
96.7k
                pfs->monotonic_color = monotonic_color_save;
1652
96.7k
                pfs->linear_color = linear_color_save;
1653
96.7k
                code = 0; /* The area is filled. */
1654
96.7k
                goto out;
1655
96.7k
            }
1656
0
            if (code < 0)
1657
0
                goto out;
1658
0
            else {      /* code == 0, the device requested to decompose the area. */
1659
0
                code = gs_note_error(gs_error_unregistered); /* Must not happen. */
1660
0
                goto out;
1661
0
            }
1662
0
        }
1663
2.07M
        if (!pfs->unlinear || !pfs->linear_color ||
1664
2.07M
                color_span(pfs, c0, c1) > pfs->smoothness) {
1665
834k
            fixed y = (ybot + ytop) / 2;
1666
1667
834k
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1668
834k
            if (code >= 0)
1669
834k
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1670
834k
        } else
1671
1.24M
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1672
2.07M
        pfs->monotonic_color = monotonic_color_save;
1673
2.07M
        pfs->linear_color = linear_color_save;
1674
2.07M
    }
1675
2.24M
out:
1676
2.24M
    pfs->inside = save_inside;
1677
2.24M
    release_colors_inline(pfs, color_stack_ptr, 1);
1678
2.24M
    return code;
1679
2.24M
}
1680
1681
static inline int
1682
linear_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_point q[4], int i0, int i1, int i2, int i3,
1683
                fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c0, const patch_color_t *c1,
1684
                bool orient)
1685
899k
{
1686
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1687
899k
    gs_fixed_edge le, re;
1688
1689
899k
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1690
899k
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1691
899k
}
1692
1693
static int
1694
wedge_trap_decompose(patch_fill_state_t *pfs, gs_fixed_point q[4],
1695
        fixed ybot, fixed ytop, const patch_color_t *c0, const patch_color_t *c1,
1696
        bool swap_axes, bool self_intersecting)
1697
1.09M
{
1698
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1699
1.09M
    fixed dx1, dy1, dx2, dy2;
1700
1.09M
    bool orient;
1701
1702
1.09M
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1703
193k
        return 0;
1704
899k
    if (ybot == ytop)
1705
0
        return 0;
1706
899k
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1707
899k
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1708
899k
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1709
448k
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1710
448k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1711
450k
    } else {
1712
450k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1713
1714
450k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1715
450k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1716
450k
    }
1717
899k
}
1718
1719
static inline int
1720
fill_wedge_trap(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
1721
            const gs_fixed_point *q0, const gs_fixed_point *q1, const patch_color_t *c0, const patch_color_t *c1,
1722
            bool swap_axes, bool self_intersecting)
1723
1.09M
{
1724
    /* We assume that the width of the wedge is close to zero,
1725
       so we can ignore the slope when computing transversal distances. */
1726
1.09M
    gs_fixed_point p[4];
1727
1.09M
    const patch_color_t *cc0, *cc1;
1728
1729
1.09M
    if (p0->y < p1->y) {
1730
523k
        p[2] = *p0;
1731
523k
        p[3] = *p1;
1732
523k
        cc0 = c0;
1733
523k
        cc1 = c1;
1734
569k
    } else {
1735
569k
        p[2] = *p1;
1736
569k
        p[3] = *p0;
1737
569k
        cc0 = c1;
1738
569k
        cc1 = c0;
1739
569k
    }
1740
1.09M
    p[0] = *q0;
1741
1.09M
    p[1] = *q1;
1742
1.09M
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1743
1.09M
}
1744
1745
static void
1746
split_curve_s(const gs_fixed_point *pole, gs_fixed_point *q0, gs_fixed_point *q1, int pole_step)
1747
4.98M
{
1748
    /*  This copies a code fragment from split_curve_midpoint,
1749
        substituting another data type.
1750
     */
1751
    /*
1752
     * We have to define midpoint carefully to avoid overflow.
1753
     * (If it overflows, something really pathological is going
1754
     * on, but we could get infinite recursion that way....)
1755
     */
1756
4.98M
#define midpoint(a,b)\
1757
59.8M
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1758
4.98M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1759
4.98M
    fixed y12 = midpoint(pole[1 * pole_step].y, pole[2 * pole_step].y);
1760
1761
    /* q[0] and q[1] must not be the same as pole. */
1762
4.98M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1763
4.98M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1764
4.98M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1765
4.98M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1766
4.98M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1767
4.98M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1768
4.98M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1769
4.98M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1770
4.98M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1771
4.98M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1772
4.98M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1773
4.98M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1774
4.98M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1775
4.98M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1776
4.98M
#undef midpoint
1777
4.98M
}
1778
1779
static void
1780
split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1781
95.1k
{
1782
95.1k
    split_curve_s(pole, q0, q1, 1);
1783
95.1k
}
1784
1785
#ifdef SHADING_SWAP_AXES_FOR_PRECISION
1786
static inline void
1787
do_swap_axes(gs_fixed_point *p, int k)
1788
{
1789
    int i;
1790
1791
    for (i = 0; i < k; i++) {
1792
        p[i].x ^= p[i].y; p[i].y ^= p[i].x; p[i].x ^= p[i].y;
1793
    }
1794
}
1795
1796
static inline fixed
1797
span_x(const gs_fixed_point *p, int k)
1798
{
1799
    int i;
1800
    fixed xmin = p[0].x, xmax = p[0].x;
1801
1802
    for (i = 1; i < k; i++) {
1803
        xmin = min(xmin, p[i].x);
1804
        xmax = max(xmax, p[i].x);
1805
    }
1806
    return xmax - xmin;
1807
}
1808
1809
static inline fixed
1810
span_y(const gs_fixed_point *p, int k)
1811
{
1812
    int i;
1813
    fixed ymin = p[0].y, ymax = p[0].y;
1814
1815
    for (i = 1; i < k; i++) {
1816
        ymin = min(ymin, p[i].y);
1817
        ymax = max(ymax, p[i].y);
1818
    }
1819
    return ymax - ymin;
1820
}
1821
#endif
1822
1823
static inline fixed
1824
manhattan_dist(const gs_fixed_point *p0, const gs_fixed_point *p1)
1825
1.05M
{
1826
1.05M
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1827
1828
1.05M
    return max(dx, dy);
1829
1.05M
}
1830
1831
static inline int
1832
create_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1833
        const gs_fixed_point *p0, const gs_fixed_point *p1)
1834
945k
{
1835
945k
    if (l->end != NULL)
1836
0
        return_error(gs_error_unregistered); /* Must not happen. */
1837
945k
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1838
945k
    l->end = wedge_vertex_list_elem_reserve(pfs);
1839
945k
    if (l->beg == NULL)
1840
0
        return_error(gs_error_unregistered); /* Must not happen. */
1841
945k
    if (l->end == NULL)
1842
0
        return_error(gs_error_unregistered); /* Must not happen. */
1843
945k
    l->beg->prev = l->end->next = NULL;
1844
945k
    l->beg->next = l->end;
1845
945k
    l->end->prev = l->beg;
1846
945k
    l->beg->p = *p0;
1847
945k
    l->end->p = *p1;
1848
945k
    l->beg->level = l->end->level = 0;
1849
945k
    return 0;
1850
945k
}
1851
1852
static inline int
1853
insert_wedge_vertex_list_elem(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1854
                              const gs_fixed_point *p, wedge_vertex_list_elem_t **r)
1855
1.98M
{
1856
1.98M
    wedge_vertex_list_elem_t *e = wedge_vertex_list_elem_reserve(pfs);
1857
1858
    /* We have got enough free elements due to the preliminary decomposition
1859
       of curves to LAZY_WEDGES_MAX_LEVEL, see curve_samples. */
1860
1.98M
    if (e == NULL)
1861
0
        return_error(gs_error_unregistered); /* Must not happen. */
1862
1.98M
    if (l->beg->next != l->end)
1863
0
        return_error(gs_error_unregistered); /* Must not happen. */
1864
1.98M
    if (l->end->prev != l->beg)
1865
0
        return_error(gs_error_unregistered); /* Must not happen. */
1866
1.98M
    e->next = l->end;
1867
1.98M
    e->prev = l->beg;
1868
1.98M
    e->p = *p;
1869
1.98M
    e->level = max(l->beg->level, l->end->level) + 1;
1870
1.98M
    e->divide_count = 0;
1871
1.98M
    l->beg->next = l->end->prev = e;
1872
1.98M
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1873
1.98M
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1874
1875
1.98M
        if ((p->x - l->beg->p.x) * sx < 0)
1876
0
            return_error(gs_error_unregistered); /* Must not happen. */
1877
1.98M
        if ((p->y - l->beg->p.y) * sy < 0)
1878
0
            return_error(gs_error_unregistered); /* Must not happen. */
1879
1.98M
        if ((l->end->p.x - p->x) * sx < 0)
1880
0
            return_error(gs_error_unregistered); /* Must not happen. */
1881
1.98M
        if ((l->end->p.y - p->y) * sy < 0)
1882
0
            return_error(gs_error_unregistered); /* Must not happen. */
1883
1.98M
    }
1884
1.98M
    *r = e;
1885
1.98M
    return 0;
1886
1.98M
}
1887
1888
static inline int
1889
open_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1890
        const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm,
1891
        wedge_vertex_list_elem_t **r)
1892
3.52M
{
1893
3.52M
    wedge_vertex_list_elem_t *e;
1894
3.52M
    int code;
1895
1896
3.52M
    if (!l->last_side) {
1897
1.96M
        if (l->beg == NULL) {
1898
930k
            code = create_wedge_vertex_list(pfs, l, p0, p1);
1899
930k
            if (code < 0)
1900
0
                return code;
1901
930k
        }
1902
1.96M
        if (l->beg->p.x != p0->x)
1903
0
            return_error(gs_error_unregistered); /* Must not happen. */
1904
1.96M
        if (l->beg->p.y != p0->y)
1905
0
            return_error(gs_error_unregistered); /* Must not happen. */
1906
1.96M
        if (l->end->p.x != p1->x)
1907
0
            return_error(gs_error_unregistered); /* Must not happen. */
1908
1.96M
        if (l->end->p.y != p1->y)
1909
0
            return_error(gs_error_unregistered); /* Must not happen. */
1910
1.96M
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1911
1.96M
        if (code < 0)
1912
0
            return code;
1913
1.96M
        e->divide_count++;
1914
1.96M
    } else if (l->beg == NULL) {
1915
14.8k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1916
14.8k
        if (code < 0)
1917
0
            return code;
1918
14.8k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1919
14.8k
        if (code < 0)
1920
0
            return code;
1921
14.8k
        e->divide_count++;
1922
1.54M
    } else {
1923
1.54M
        if (l->beg->p.x != p1->x)
1924
0
            return_error(gs_error_unregistered); /* Must not happen. */
1925
1.54M
        if (l->beg->p.y != p1->y)
1926
0
            return_error(gs_error_unregistered); /* Must not happen. */
1927
1.54M
        if (l->end->p.x != p0->x)
1928
0
            return_error(gs_error_unregistered); /* Must not happen. */
1929
1.54M
        if (l->end->p.y != p0->y)
1930
0
            return_error(gs_error_unregistered); /* Must not happen. */
1931
1.54M
        if (l->beg->next == l->end) {
1932
5.41k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1933
5.41k
            if (code < 0)
1934
0
                return code;
1935
5.41k
            e->divide_count++;
1936
1.53M
        } else {
1937
1.53M
            e = wedge_vertex_list_find(l->beg, l->end,
1938
1.53M
                        max(l->beg->level, l->end->level) + 1);
1939
1.53M
            if (e == NULL)
1940
0
                return_error(gs_error_unregistered); /* Must not happen. */
1941
1.53M
            if (e->p.x != pm->x || e->p.y != pm->y)
1942
0
                return_error(gs_error_unregistered); /* Must not happen. */
1943
1.53M
            e->divide_count++;
1944
1.53M
        }
1945
1.54M
    }
1946
3.52M
    *r = e;
1947
3.52M
    return 0;
1948
3.52M
}
1949
1950
static inline int
1951
make_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1952
        wedge_vertex_list_t *l0, bool forth,
1953
        const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *pm)
1954
3.52M
{
1955
3.52M
    int code;
1956
1957
3.52M
    l->last_side = l0->last_side;
1958
3.52M
    if (!l->last_side ^ !forth) {
1959
2.04M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1960
2.04M
        l->beg = l0->beg;
1961
2.04M
    } else {
1962
1.47M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1963
1.47M
        l->end = l0->end;
1964
1.47M
    }
1965
3.52M
    return code;
1966
3.52M
}
1967
1968
static int fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
1969
            const patch_color_t *c0, const patch_color_t *c1);
1970
1971
static inline int
1972
close_wedge_median(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
1973
        const patch_color_t *c0, const patch_color_t *c1)
1974
3.52M
{
1975
3.52M
    int code;
1976
1977
3.52M
    if (!l->last_side)
1978
1.96M
        return 0;
1979
1.55M
    code = fill_wedge_from_list(pfs, l, c1, c0);
1980
1.55M
    if (code < 0)
1981
0
        return code;
1982
1.55M
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1983
1.55M
    return 0;
1984
1.55M
}
1985
1986
static inline void
1987
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1988
3.52M
{
1989
3.52M
    if (!l->last_side ^ !forth) {
1990
2.04M
        l->beg = l->end;
1991
2.04M
        l->end = l0->end;
1992
2.04M
    } else {
1993
1.47M
        l->end = l->beg;
1994
1.47M
        l->beg = l0->beg;
1995
1.47M
    }
1996
3.52M
}
1997
1998
static inline int
1999
fill_triangle_wedge_aux(patch_fill_state_t *pfs,
2000
            const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
2001
546k
{   int code;
2002
546k
    const gs_fixed_point *p0, *p1, *p2;
2003
546k
    gs_fixed_point qq0, qq1, qq2;
2004
546k
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2005
546k
    bool swap_axes;
2006
2007
#   if SKIP_TEST
2008
        dbg_wedge_triangle_cnt++;
2009
#   endif
2010
546k
    if (dx > dy) {
2011
297k
        swap_axes = true;
2012
297k
        qq0.x = q0->p.y;
2013
297k
        qq0.y = q0->p.x;
2014
297k
        qq1.x = q1->p.y;
2015
297k
        qq1.y = q1->p.x;
2016
297k
        qq2.x = q2->p.y;
2017
297k
        qq2.y = q2->p.x;
2018
297k
        p0 = &qq0;
2019
297k
        p1 = &qq1;
2020
297k
        p2 = &qq2;
2021
297k
    } else {
2022
249k
        swap_axes = false;
2023
249k
        p0 = &q0->p;
2024
249k
        p1 = &q1->p;
2025
249k
        p2 = &q2->p;
2026
249k
    }
2027
    /* We decompose the thin triangle into 2 thin trapezoids.
2028
       An optimization with decomposing into 2 triangles
2029
       appears low useful, because the self_intersecting argument
2030
       with inline expansion does that job perfectly. */
2031
546k
    if (p0->y < p1->y) {
2032
262k
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2033
262k
        if (code < 0)
2034
0
            return code;
2035
262k
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2036
284k
    } else {
2037
284k
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2038
284k
        if (code < 0)
2039
0
            return code;
2040
284k
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2041
284k
    }
2042
546k
}
2043
2044
static inline int
2045
try_device_linear_color(patch_fill_state_t *pfs, bool wedge,
2046
        const shading_vertex_t *p0, const shading_vertex_t *p1,
2047
        const shading_vertex_t *p2)
2048
5.97M
{
2049
    /*  Returns :
2050
        <0 - error;
2051
        0 - success;
2052
        1 - decompose to linear color areas;
2053
        2 - decompose to constant color areas;
2054
     */
2055
5.97M
    int code;
2056
2057
5.97M
    if (pfs->unlinear)
2058
5.55M
        return 2;
2059
422k
    if (!wedge) {
2060
422k
        const gs_color_space *cs = pfs->direct_space;
2061
2062
422k
        if (cs != NULL) {
2063
422k
            float s0, s1, s2, s01, s012;
2064
2065
422k
            s0 = function_linearity(pfs, p0->c, p1->c);
2066
422k
            if (s0 > pfs->smoothness)
2067
5.24k
                return 1;
2068
416k
            s1 = function_linearity(pfs, p1->c, p2->c);
2069
416k
            if (s1 > pfs->smoothness)
2070
4.25k
                return 1;
2071
412k
            s2 = function_linearity(pfs, p2->c, p0->c);
2072
412k
            if (s2 > pfs->smoothness)
2073
0
                return 1;
2074
            /* fixme: check an inner color ? */
2075
412k
            s01 = max(s0, s1);
2076
412k
            s012 = max(s01, s2);
2077
412k
            if (pfs->cs_always_linear)
2078
0
                code = 1;
2079
412k
            else
2080
412k
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2081
412k
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2082
412k
                                  pfs->smoothness - s012, pfs->icclink);
2083
412k
            if (code < 0)
2084
0
                return code;
2085
412k
            if (code == 0)
2086
112
                return 1;
2087
412k
        }
2088
422k
    }
2089
412k
    {   gx_device *pdev = pfs->dev;
2090
412k
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2091
412k
        gs_fill_attributes fa;
2092
412k
        gx_device_color dc[3];
2093
2094
412k
        fa.clip = &pfs->rect;
2095
412k
        fa.ht = NULL;
2096
412k
        fa.swap_axes = false;
2097
412k
        fa.lop = 0;
2098
412k
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2099
412k
        if (code != 0)
2100
0
            return code;
2101
412k
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2102
412k
            dc[0].type == &gx_dc_type_data_devn))
2103
0
            return 2;
2104
412k
        if (!wedge) {
2105
412k
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2106
412k
            if (code != 0)
2107
0
                return code;
2108
412k
        }
2109
412k
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2110
412k
        if (code != 0)
2111
0
            return code;
2112
412k
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2113
412k
                        &p0->p, &p1->p, &p2->p,
2114
412k
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2115
412k
        if (code == 1)
2116
412k
            return 0; /* The area is filled. */
2117
0
        if (code < 0)
2118
0
            return code;
2119
0
        else /* code == 0, the device requested to decompose the area. */
2120
0
            return 1;
2121
0
    }
2122
0
}
2123
2124
static inline int
2125
fill_triangle_wedge(patch_fill_state_t *pfs,
2126
            const shading_vertex_t *q0, const shading_vertex_t *q1, const shading_vertex_t *q2)
2127
1.14M
{
2128
1.14M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2129
1.14M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2130
598k
        return 0; /* Zero area. */
2131
    /*
2132
        Can't apply try_device_linear_color here
2133
        because didn't check is_color_linear.
2134
        Maybe need a decomposition.
2135
        Do same as for 'unlinear', and branch later.
2136
     */
2137
546k
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2138
1.14M
}
2139
2140
static inline int
2141
fill_triangle_wedge_from_list(patch_fill_state_t *pfs,
2142
    const wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
2143
    const wedge_vertex_list_elem_t *mid,
2144
    const patch_color_t *c0, const patch_color_t *c1)
2145
448k
{
2146
448k
    shading_vertex_t p[3];
2147
448k
    patch_color_t *c;
2148
448k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2149
448k
    int code;
2150
2151
448k
    if (color_stack_ptr == NULL)
2152
0
        return_error(gs_error_unregistered); /* Must not happen. */
2153
448k
    p[2].c = c;
2154
448k
    p[0].p = beg->p;
2155
448k
    p[0].c = c0;
2156
448k
    p[1].p = end->p;
2157
448k
    p[1].c = c1;
2158
448k
    p[2].p = mid->p;
2159
448k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2160
448k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2161
448k
    release_colors_inline(pfs, color_stack_ptr, 1);
2162
448k
    return code;
2163
448k
}
2164
2165
static int
2166
fill_wedge_from_list_rec(patch_fill_state_t *pfs,
2167
            wedge_vertex_list_elem_t *beg, const wedge_vertex_list_elem_t *end,
2168
            int level, const patch_color_t *c0, const patch_color_t *c1)
2169
2.85M
{
2170
2.85M
    if (beg->next == end)
2171
872k
        return 0;
2172
1.98M
    else if (beg->next->next == end) {
2173
1.80M
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2174
0
            return_error(gs_error_unregistered); /* Must not happen. */
2175
1.80M
        if (beg->next->divide_count != 1)
2176
1.53M
            return 0;
2177
271k
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2178
1.80M
    } else {
2179
177k
        gs_fixed_point p;
2180
177k
        wedge_vertex_list_elem_t *e;
2181
177k
        patch_color_t *c;
2182
177k
        int code;
2183
177k
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2184
2185
177k
        if (color_stack_ptr == NULL)
2186
0
            return_error(gs_error_unregistered); /* Must not happen. */
2187
177k
        p.x = (beg->p.x + end->p.x) / 2;
2188
177k
        p.y = (beg->p.y + end->p.y) / 2;
2189
177k
        e = wedge_vertex_list_find(beg, end, level + 1);
2190
177k
        if (e == NULL)
2191
0
            return_error(gs_error_unregistered); /* Must not happen. */
2192
177k
        if (e->p.x != p.x || e->p.y != p.y)
2193
0
            return_error(gs_error_unregistered); /* Must not happen. */
2194
177k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2195
177k
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2196
177k
        if (code >= 0)
2197
177k
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2198
177k
        if (code >= 0) {
2199
177k
            if (e->divide_count != 1 && e->divide_count != 2)
2200
0
                return_error(gs_error_unregistered); /* Must not happen. */
2201
177k
            if (e->divide_count == 1)
2202
177k
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2203
177k
        }
2204
177k
        release_colors_inline(pfs, color_stack_ptr, 1);
2205
177k
        return code;
2206
177k
    }
2207
2.85M
}
2208
2209
static int
2210
fill_wedge_from_list(patch_fill_state_t *pfs, const wedge_vertex_list_t *l,
2211
            const patch_color_t *c0, const patch_color_t *c1)
2212
2.50M
{
2213
2.50M
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2214
2.50M
                    max(l->beg->level, l->end->level), c0, c1);
2215
2.50M
}
2216
2217
static inline int
2218
terminate_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *l,
2219
        const patch_color_t *c0, const patch_color_t *c1)
2220
8.11M
{
2221
8.11M
    if (l->beg != NULL) {
2222
945k
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2223
2224
945k
        if (code < 0)
2225
0
            return code;
2226
945k
        return release_wedge_vertex_list(pfs, l, 1);
2227
945k
    }
2228
7.16M
    return 0;
2229
8.11M
}
2230
2231
static int
2232
wedge_by_triangles(patch_fill_state_t *pfs, int ka,
2233
        const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1)
2234
87.3k
{   /* Assuming ka >= 2, see fill_wedges. */
2235
87.3k
    gs_fixed_point q[2][4];
2236
87.3k
    patch_color_t *c;
2237
87.3k
    shading_vertex_t p[3];
2238
87.3k
    int code;
2239
87.3k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2240
2241
87.3k
    if (color_stack_ptr == NULL)
2242
0
        return_error(gs_error_unregistered); /* Must not happen. */
2243
87.3k
    p[2].c = c;
2244
87.3k
    split_curve(pole, q[0], q[1]);
2245
87.3k
    p[0].p = pole[0];
2246
87.3k
    p[0].c = c0;
2247
87.3k
    p[1].p = pole[3];
2248
87.3k
    p[1].c = c1;
2249
87.3k
    p[2].p = q[0][3];
2250
87.3k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2251
87.3k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2252
87.3k
    if (code >= 0) {
2253
87.3k
        if (ka == 2)
2254
45.1k
            goto out;
2255
42.2k
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2256
42.2k
    }
2257
42.2k
    if (code >= 0)
2258
42.2k
        code = wedge_by_triangles(pfs, ka / 2, q[1], p[2].c, c1);
2259
87.3k
out:
2260
87.3k
    release_colors_inline(pfs, color_stack_ptr, 1);
2261
87.3k
    return code;
2262
42.2k
}
2263
2264
int
2265
mesh_padding(patch_fill_state_t *pfs, const gs_fixed_point *p0, const gs_fixed_point *p1,
2266
            const patch_color_t *c0, const patch_color_t *c1)
2267
792k
{
2268
792k
    gs_fixed_point q0, q1;
2269
792k
    const patch_color_t *cc0, *cc1;
2270
792k
    fixed dx = p1->x - p0->x;
2271
792k
    fixed dy = p1->y - p0->y;
2272
792k
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2273
792k
    gs_fixed_edge le, re;
2274
792k
    const fixed adjust = INTERPATCH_PADDING;
2275
2276
792k
    if (swap_axes) {
2277
257k
        if (p0->x < p1->x) {
2278
114k
            q0.x = p0->y;
2279
114k
            q0.y = p0->x;
2280
114k
            q1.x = p1->y;
2281
114k
            q1.y = p1->x;
2282
114k
            cc0 = c0;
2283
114k
            cc1 = c1;
2284
143k
        } else {
2285
143k
            q0.x = p1->y;
2286
143k
            q0.y = p1->x;
2287
143k
            q1.x = p0->y;
2288
143k
            q1.y = p0->x;
2289
143k
            cc0 = c1;
2290
143k
            cc1 = c0;
2291
143k
        }
2292
534k
    } else if (p0->y < p1->y) {
2293
87.6k
        q0 = *p0;
2294
87.6k
        q1 = *p1;
2295
87.6k
        cc0 = c0;
2296
87.6k
        cc1 = c1;
2297
447k
    } else {
2298
447k
        q0 = *p1;
2299
447k
        q1 = *p0;
2300
447k
        cc0 = c1;
2301
447k
        cc1 = c0;
2302
447k
    }
2303
792k
    le.start.x = q0.x - adjust;
2304
792k
    re.start.x = q0.x + adjust;
2305
792k
    le.start.y = re.start.y = q0.y - adjust;
2306
792k
    le.end.x = q1.x - adjust;
2307
792k
    re.end.x = q1.x + adjust;
2308
792k
    le.end.y = re.end.y = q1.y + adjust;
2309
792k
    adjust_swapped_boundary(&re.start.x, swap_axes);
2310
792k
    adjust_swapped_boundary(&re.end.x, swap_axes);
2311
792k
    return decompose_linear_color(pfs, &le, &re, le.start.y, le.end.y, swap_axes, cc0, cc1);
2312
    /* fixme : for a better performance and quality, we would like to
2313
       consider the bar as an oriented one and to know at what side of it the spot resides.
2314
       If we know that, we could expand only to outside the spot.
2315
       Note that if the boundary has a self-intersection,
2316
       we still need to expand to both directions.
2317
     */
2318
792k
}
2319
2320
static inline void
2321
bbox_of_points(gs_fixed_rect *r,
2322
        const gs_fixed_point *p0, const gs_fixed_point *p1,
2323
        const gs_fixed_point *p2, const gs_fixed_point *p3)
2324
1.45M
{
2325
1.45M
    r->p.x = r->q.x = p0->x;
2326
1.45M
    r->p.y = r->q.y = p0->y;
2327
2328
1.45M
    if (r->p.x > p1->x)
2329
563k
        r->p.x = p1->x;
2330
1.45M
    if (r->q.x < p1->x)
2331
653k
        r->q.x = p1->x;
2332
1.45M
    if (r->p.y > p1->y)
2333
620k
        r->p.y = p1->y;
2334
1.45M
    if (r->q.y < p1->y)
2335
566k
        r->q.y = p1->y;
2336
2337
1.45M
    if (r->p.x > p2->x)
2338
325k
        r->p.x = p2->x;
2339
1.45M
    if (r->q.x < p2->x)
2340
307k
        r->q.x = p2->x;
2341
1.45M
    if (r->p.y > p2->y)
2342
308k
        r->p.y = p2->y;
2343
1.45M
    if (r->q.y < p2->y)
2344
308k
        r->q.y = p2->y;
2345
2346
1.45M
    if (p3 == NULL)
2347
1.14M
        return;
2348
2349
313k
    if (r->p.x > p3->x)
2350
54.1k
        r->p.x = p3->x;
2351
313k
    if (r->q.x < p3->x)
2352
128k
        r->q.x = p3->x;
2353
313k
    if (r->p.y > p3->y)
2354
84.8k
        r->p.y = p3->y;
2355
313k
    if (r->q.y < p3->y)
2356
72.2k
        r->q.y = p3->y;
2357
313k
}
2358
2359
static int
2360
fill_wedges_aux(patch_fill_state_t *pfs, int k, int ka,
2361
        const gs_fixed_point pole[4], const patch_color_t *c0, const patch_color_t *c1,
2362
        int wedge_type)
2363
54.5k
{
2364
54.5k
    int code;
2365
2366
54.5k
    if (k > 1) {
2367
25.2k
        gs_fixed_point q[2][4];
2368
25.2k
        patch_color_t *c;
2369
25.2k
        bool save_inside = pfs->inside;
2370
25.2k
        byte *color_stack_ptr;
2371
2372
25.2k
        if (!pfs->inside) {
2373
22.6k
            gs_fixed_rect r, r1;
2374
2375
22.6k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2376
22.6k
            r.p.x -= INTERPATCH_PADDING;
2377
22.6k
            r.p.y -= INTERPATCH_PADDING;
2378
22.6k
            r.q.x += INTERPATCH_PADDING;
2379
22.6k
            r.q.y += INTERPATCH_PADDING;
2380
22.6k
            r1 = r;
2381
22.6k
            rect_intersect(r, pfs->rect);
2382
22.6k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2383
17.4k
                return 0;
2384
5.21k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2385
5.21k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2386
1.47k
                pfs->inside = true;
2387
5.21k
        }
2388
7.83k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2389
7.83k
        if (color_stack_ptr == NULL)
2390
0
            return_error(gs_error_unregistered); /* Must not happen. */
2391
7.83k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2392
7.83k
        split_curve(pole, q[0], q[1]);
2393
7.83k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2394
7.83k
        if (code >= 0)
2395
7.83k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2396
7.83k
        release_colors_inline(pfs, color_stack_ptr, 1);
2397
7.83k
        pfs->inside = save_inside;
2398
7.83k
        return code;
2399
29.2k
    } else {
2400
29.2k
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2401
27.5k
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2402
27.5k
            if (code < 0)
2403
0
                return code;
2404
27.5k
        }
2405
29.2k
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2406
2.87k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2407
26.3k
        return 0;
2408
29.2k
    }
2409
54.5k
}
2410
2411
static int
2412
fill_wedges(patch_fill_state_t *pfs, int k0, int k1,
2413
        const gs_fixed_point *pole, int pole_step,
2414
        const patch_color_t *c0, const patch_color_t *c1,
2415
        int wedge_type)
2416
477k
{
2417
    /* Generate wedges between 2 variants of a curve flattening. */
2418
    /* k0, k1 is a power of 2. */
2419
477k
    gs_fixed_point p[4];
2420
2421
477k
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2422
438k
        return 0; /* Wedges are zero area. */
2423
38.8k
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2424
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2425
0
    }
2426
38.8k
    p[0] = pole[0];
2427
38.8k
    p[1] = pole[pole_step];
2428
38.8k
    p[2] = pole[pole_step * 2];
2429
38.8k
    p[3] = pole[pole_step * 3];
2430
38.8k
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2431
477k
}
2432
2433
static inline void
2434
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2435
73.7k
{
2436
73.7k
    q[0] = p->p[0][0]->p;
2437
73.7k
    q[1] = p->p[0][1]->p;
2438
73.7k
    q[2] = p->p[1][1]->p;
2439
73.7k
    q[3] = p->p[1][0]->p;
2440
73.7k
}
2441
2442
static inline void
2443
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2444
73.7k
{
2445
73.7k
    fixed y = s[0].y;
2446
73.7k
    int i = 0;
2447
2448
73.7k
    if (y > s[1].y)
2449
19.9k
        i = 1, y = s[1].y;
2450
73.7k
    if (y > s[2].y)
2451
10.5k
        i = 2, y = s[2].y;
2452
73.7k
    if (y > s[3].y)
2453
13.8k
        i = 3, y = s[3].y;
2454
73.7k
    q[0] = s[(i + 0) % 4];
2455
73.7k
    q[1] = s[(i + 1) % 4];
2456
73.7k
    q[2] = s[(i + 2) % 4];
2457
73.7k
    q[3] = s[(i + 3) % 4];
2458
73.7k
}
2459
2460
static int
2461
ordered_triangle(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re, patch_color_t *c)
2462
5.95M
{
2463
5.95M
    gs_fixed_edge ue;
2464
5.95M
    int code;
2465
5.95M
    gx_device_color dc;
2466
2467
#   if NOFILL_TEST
2468
        if (dbg_nofill)
2469
            return 0;
2470
#   endif
2471
5.95M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2472
5.95M
    if (code < 0)
2473
0
        return code;
2474
5.95M
    if (le->end.y < re->end.y) {
2475
2.26M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2476
2.26M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2477
2.26M
        if (code >= 0) {
2478
2.26M
            ue.start = le->end;
2479
2.26M
            ue.end = re->end;
2480
2.26M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2481
2.26M
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2482
2.26M
        }
2483
3.68M
    } else if (le->end.y > re->end.y) {
2484
2.17M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2485
2.17M
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2486
2.17M
        if (code >= 0) {
2487
2.17M
            ue.start = re->end;
2488
2.17M
            ue.end = le->end;
2489
2.17M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2490
2.17M
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2491
2.17M
        }
2492
2.17M
    } else
2493
1.51M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2494
1.51M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2495
5.95M
    return code;
2496
5.95M
}
2497
2498
static int
2499
constant_color_triangle(patch_fill_state_t *pfs,
2500
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2501
4.45M
{
2502
4.45M
    patch_color_t *c[2];
2503
4.45M
    gs_fixed_edge le, re;
2504
4.45M
    fixed dx0, dy0, dx1, dy1;
2505
4.45M
    const shading_vertex_t *pp;
2506
4.45M
    int i, code = 0;
2507
4.45M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2508
2509
4.45M
    if (color_stack_ptr == NULL)
2510
0
        return_error(gs_error_unregistered); /* Must not happen. */
2511
4.45M
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2512
4.45M
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2513
17.8M
    for (i = 0; i < 3; i++) {
2514
        /* fixme : does optimizer compiler expand this cycle ? */
2515
13.3M
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2516
5.95M
            le.start = re.start = p0->p;
2517
5.95M
            le.end = p1->p;
2518
5.95M
            re.end = p2->p;
2519
2520
5.95M
            dx0 = le.end.x - le.start.x;
2521
5.95M
            dy0 = le.end.y - le.start.y;
2522
5.95M
            dx1 = re.end.x - re.start.x;
2523
5.95M
            dy1 = re.end.y - re.start.y;
2524
5.95M
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2525
2.82M
                code = ordered_triangle(pfs, &le, &re, c[1]);
2526
3.12M
            else
2527
3.12M
                code = ordered_triangle(pfs, &re, &le, c[1]);
2528
5.95M
            if (code < 0)
2529
0
                break;
2530
5.95M
        }
2531
13.3M
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2532
13.3M
    }
2533
4.45M
    release_colors_inline(pfs, color_stack_ptr, 2);
2534
4.45M
    return code;
2535
4.45M
}
2536
2537
static inline int
2538
constant_color_quadrangle_aux(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting,
2539
        patch_color_t *c[3])
2540
73.7k
{
2541
    /* Assuming the XY span is restricted with curve_samples.
2542
       It is important for intersection_of_small_bars to compute faster. */
2543
73.7k
    gs_fixed_point q[4];
2544
73.7k
    fixed ry, ey;
2545
73.7k
    int code;
2546
73.7k
    bool swap_axes = false;
2547
73.7k
    gx_device_color dc;
2548
73.7k
    bool orient;
2549
2550
73.7k
    dc.tag = device_current_tag(pfs->dev);
2551
2552
73.7k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2553
73.7k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2554
73.7k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2555
73.7k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2556
73.7k
    if (code < 0)
2557
0
        return code;
2558
73.7k
    {   gs_fixed_point qq[4];
2559
2560
73.7k
        make_vertices(qq, p);
2561
#ifdef SHADING_SWAP_AXES_FOR_PRECISION
2562
             /* Swapping axes may improve the precision,
2563
                but slows down due to the area expansion needed
2564
                in gx_shade_trapezoid. */
2565
            dx = span_x(qq, 4);
2566
            dy = span_y(qq, 4);
2567
            if (dy < dx) {
2568
                do_swap_axes(qq, 4);
2569
                swap_axes = true;
2570
            }
2571
#endif
2572
73.7k
        wrap_vertices_by_y(q, qq);
2573
73.7k
    }
2574
73.7k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2575
73.7k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2576
73.7k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2577
2578
73.7k
        if (g13 == h13) {
2579
180
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2580
180
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2581
2582
180
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2583
0
                return 0;
2584
180
            if (g23 != h23) {
2585
180
                orient = (g23 > h23);
2586
180
                if (q[2].y <= q[3].y) {
2587
165
                    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2588
0
                        return code;
2589
165
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2590
165
                } else {
2591
15
                    if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2592
0
                        return code;
2593
15
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2594
15
                }
2595
180
            } else {
2596
0
                int64_t g12 = (int64_t)dx1 * dy2, h12 = (int64_t)dy1 * dx2;
2597
2598
0
                if (dx3 == 0 && dy3 == 0 && g12 == h12)
2599
0
                    return 0;
2600
0
                orient = (g12 > h12);
2601
0
                if (q[1].y <= q[2].y) {
2602
0
                    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2603
0
                        return code;
2604
0
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2605
0
                } else {
2606
0
                    if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2607
0
                        return code;
2608
0
                    return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2609
0
                }
2610
0
            }
2611
180
        }
2612
73.6k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2613
73.6k
    }
2614
73.6k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2615
11.0k
        if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2616
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2617
0
                return code;
2618
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2619
0
                return code;
2620
0
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2621
0
                return code;
2622
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2623
11.0k
        } else {
2624
11.0k
            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
11.0k
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[2].y, swap_axes, &dc, orient)) < 0)
2627
0
                return code;
2628
11.0k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2629
11.0k
        }
2630
62.5k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2631
26.3k
        if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &ry, &ey)) {
2632
0
            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
0
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, ry + ey, swap_axes, &dc, orient)) < 0)
2635
0
                return code;
2636
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 3, 1, 2, ry, q[3].y, swap_axes, &dc, orient)) < 0)
2637
0
                return code;
2638
0
            return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2639
26.3k
        } else {
2640
26.3k
            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
26.3k
            if ((code = gx_shade_trapezoid(pfs, q, 1, 2, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient)) < 0)
2643
0
                return code;
2644
26.3k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2645
26.3k
        }
2646
36.2k
    } else if (q[2].y <= q[1].y && q[1].y <= q[3].y) {
2647
0
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2648
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2649
0
                return code;
2650
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2651
0
                return code;
2652
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2653
0
                return code;
2654
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2655
0
        } else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 1, 2, &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, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2661
0
                return code;
2662
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2663
0
        } else {
2664
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[1].y, swap_axes, &dc, orient)) < 0)
2665
0
                return code;
2666
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient)) < 0)
2667
0
                return code;
2668
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[1].y, q[3].y, swap_axes, &dc, orient);
2669
0
        }
2670
36.2k
    } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2671
12
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2672
            /* Same code as someone above. */
2673
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2674
0
                return code;
2675
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2676
0
                return code;
2677
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2678
0
                return code;
2679
0
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, ry, q[3].y, swap_axes, &dc, orient);
2680
12
        } else if (self_intersecting && intersection_of_small_bars(q, 0, 3, 2, 1, &ry, &ey)) {
2681
            /* Same code as someone above. */
2682
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, ry + ey, swap_axes, &dc, orient)) < 0)
2683
0
                return code;
2684
0
            if ((code = gx_shade_trapezoid(pfs, q, 2, 1, 2, 3, q[2].y, ry + ey, swap_axes, &dc, orient)) < 0)
2685
0
                return code;
2686
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2687
0
                return code;
2688
0
            return gx_shade_trapezoid(pfs, q, 0, 3, 2, 3, ry, q[3].y, swap_axes, &dc, orient);
2689
12
        } else {
2690
12
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[2].y, swap_axes, &dc, orient)) < 0)
2691
0
                return code;
2692
12
            if ((code = gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient)) < 0)
2693
0
                return code;
2694
12
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2695
12
        }
2696
36.2k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2697
35.4k
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 3, 2, &ry, &ey)) {
2698
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 0, 3, q[0].y, q[3].y, swap_axes, &dc, orient)) < 0)
2699
0
                return code;
2700
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2701
0
                return code;
2702
0
            if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[1].y, swap_axes, &dc, orient)) < 0)
2703
0
                return code;
2704
0
            return gx_shade_trapezoid(pfs, q, 3, 2, 1, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2705
35.4k
        } else {
2706
35.4k
            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
35.4k
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[1].y, swap_axes, &dc, orient)) < 0)
2709
0
                return code;
2710
35.4k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2711
35.4k
        }
2712
35.4k
    } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2713
857
        if (self_intersecting && intersection_of_small_bars(q, 0, 1, 2, 3, &ry, &ey)) {
2714
0
            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
0
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, ry + ey, swap_axes, &dc, orient)) < 0)
2717
0
                return code;
2718
0
            if ((code = gx_shade_trapezoid(pfs, q, 3, 2, 0, 1, ry, q[2].y, swap_axes, &dc, orient)) < 0)
2719
0
                return code;
2720
0
            return gx_shade_trapezoid(pfs, q, 2, 1, 0, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2721
857
        } else {
2722
857
            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
857
            if ((code = gx_shade_trapezoid(pfs, q, 0, 1, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient)) < 0)
2725
0
                return code;
2726
857
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2727
857
        }
2728
857
    } else {
2729
        /* Impossible. */
2730
0
        return_error(gs_error_unregistered);
2731
0
    }
2732
73.6k
}
2733
2734
int
2735
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2736
73.7k
{
2737
73.7k
    patch_color_t *c[3];
2738
73.7k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2739
73.7k
    int code;
2740
2741
73.7k
    if (color_stack_ptr == NULL)
2742
0
        return_error(gs_error_unregistered); /* Must not happen. */
2743
73.7k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2744
73.7k
    release_colors_inline(pfs, color_stack_ptr, 3);
2745
73.7k
    return code;
2746
73.7k
}
2747
2748
static inline void
2749
divide_quadrangle_by_v(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2750
            shading_vertex_t q[2], const quadrangle_patch *p, patch_color_t *c[2])
2751
55.1k
{
2752
55.1k
    q[0].c = c[0];
2753
55.1k
    q[1].c = c[1];
2754
55.1k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2755
55.1k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2756
55.1k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2757
55.1k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2758
55.1k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2759
55.1k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2760
55.1k
    s0->p[0][0] = p->p[0][0];
2761
55.1k
    s0->p[0][1] = p->p[0][1];
2762
55.1k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2763
55.1k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2764
55.1k
    s1->p[1][0] = p->p[1][0];
2765
55.1k
    s1->p[1][1] = p->p[1][1];
2766
55.1k
}
2767
2768
static inline void
2769
divide_quadrangle_by_u(patch_fill_state_t *pfs, quadrangle_patch *s0, quadrangle_patch *s1,
2770
            shading_vertex_t q[2], const quadrangle_patch *p, patch_color_t *c[2])
2771
31.4k
{
2772
31.4k
    q[0].c = c[0];
2773
31.4k
    q[1].c = c[1];
2774
31.4k
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2775
31.4k
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2776
31.4k
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2777
31.4k
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2778
31.4k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2779
31.4k
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2780
31.4k
    s0->p[0][0] = p->p[0][0];
2781
31.4k
    s0->p[1][0] = p->p[1][0];
2782
31.4k
    s0->p[0][1] = s1->p[0][0] = &q[0];
2783
31.4k
    s0->p[1][1] = s1->p[1][0] = &q[1];
2784
31.4k
    s1->p[0][1] = p->p[0][1];
2785
31.4k
    s1->p[1][1] = p->p[1][1];
2786
31.4k
}
2787
2788
static inline int
2789
is_quadrangle_color_monotonic(const patch_fill_state_t *pfs, const quadrangle_patch *p,
2790
                              bool *not_monotonic_by_u, bool *not_monotonic_by_v)
2791
36.2k
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2792
36.2k
    int code, r;
2793
2794
36.2k
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2795
36.2k
    if (code <= 0)
2796
28.4k
        return code;
2797
7.78k
    r = code << pfs->function_arg_shift;
2798
7.78k
    if (r & 1)
2799
0
        *not_monotonic_by_u = true;
2800
7.78k
    if (r & 2)
2801
7.78k
        *not_monotonic_by_v = true;
2802
7.78k
    return !code;
2803
36.2k
}
2804
2805
static inline void
2806
divide_bar(patch_fill_state_t *pfs,
2807
        const shading_vertex_t *p0, const shading_vertex_t *p1, int radix, shading_vertex_t *p,
2808
        patch_color_t *c)
2809
4.56M
{
2810
    /* Assuming p.c == c for providing a non-const access. */
2811
4.56M
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2812
4.56M
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2813
4.56M
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2814
4.56M
}
2815
2816
static int
2817
triangle_by_4(patch_fill_state_t *pfs,
2818
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2819
        wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20,
2820
        double cd, fixed sd)
2821
6.42M
{
2822
6.42M
    shading_vertex_t p01, p12, p20;
2823
6.42M
    patch_color_t *c[3];
2824
6.42M
    wedge_vertex_list_t L01, L12, L20, L[3];
2825
6.42M
    bool inside_save = pfs->inside;
2826
6.42M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2827
6.42M
    int code = 0;
2828
6.42M
    byte *color_stack_ptr;
2829
6.42M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2830
2831
6.42M
    if (!inside) {
2832
1.14M
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2833
1.14M
        r1 = r;
2834
1.14M
        rect_intersect(r, pfs->rect);
2835
1.14M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2836
449k
            return 0;
2837
1.14M
    }
2838
5.97M
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2839
5.97M
    if(color_stack_ptr == NULL)
2840
0
        return_error(gs_error_unregistered);
2841
5.97M
    p01.c = c[0];
2842
5.97M
    p12.c = c[1];
2843
5.97M
    p20.c = c[2];
2844
5.97M
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2845
5.97M
    switch(code) {
2846
412k
        case 0: /* The area is filled. */
2847
412k
            goto out;
2848
5.55M
        case 2: /* decompose to constant color areas */
2849
            /* Halftoned devices may do with some bigger areas
2850
               due to imprecise representation of a contone color.
2851
               So we multiply the decomposition limit by 4 for a faster rendering. */
2852
5.55M
            if (sd < pfs->decomposition_limit * 4) {
2853
429k
                code = constant_color_triangle(pfs, p2, p0, p1);
2854
429k
                goto out;
2855
429k
            }
2856
5.12M
            if (pfs->Function != NULL) {
2857
348k
                double d01 = color_span(pfs, p1->c, p0->c);
2858
348k
                double d12 = color_span(pfs, p2->c, p1->c);
2859
348k
                double d20 = color_span(pfs, p0->c, p2->c);
2860
2861
348k
                if (d01 <= pfs->smoothness / COLOR_CONTIGUITY &&
2862
348k
                    d12 <= pfs->smoothness / COLOR_CONTIGUITY &&
2863
348k
                    d20 <= pfs->smoothness / COLOR_CONTIGUITY) {
2864
203k
                    code = constant_color_triangle(pfs, p2, p0, p1);
2865
203k
                    goto out;
2866
203k
                }
2867
4.78M
            } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY) {
2868
3.81M
                code = constant_color_triangle(pfs, p2, p0, p1);
2869
3.81M
                goto out;
2870
3.81M
            }
2871
1.11M
            break;
2872
1.11M
        case 1: /* decompose to linear color areas */
2873
9.60k
            if (sd < pfs->decomposition_limit) {
2874
4.08k
                code = constant_color_triangle(pfs, p2, p0, p1);
2875
4.08k
                goto out;
2876
4.08k
            }
2877
5.52k
            break;
2878
5.52k
        default: /* Error. */
2879
0
            goto out;
2880
5.97M
    }
2881
1.11M
    if (!inside) {
2882
72.6k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2883
72.6k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
2884
6.11k
            pfs->inside = true;
2885
72.6k
    }
2886
1.11M
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2887
1.11M
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2888
1.11M
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2889
1.11M
    if (LAZY_WEDGES) {
2890
1.11M
        init_wedge_vertex_list(L, count_of(L));
2891
1.11M
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2892
1.11M
        if (code >= 0)
2893
1.11M
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2894
1.11M
        if (code >= 0)
2895
1.11M
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2896
1.11M
    } else {
2897
0
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
2898
0
        if (code >= 0)
2899
0
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
2900
0
        if (code >= 0)
2901
0
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
2902
0
    }
2903
1.11M
    if (code >= 0)
2904
1.11M
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2905
1.11M
    if (code >= 0) {
2906
1.11M
        if (LAZY_WEDGES) {
2907
1.11M
            move_wedge(&L01, l01, true);
2908
1.11M
            move_wedge(&L20, l20, false);
2909
1.11M
        }
2910
1.11M
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2911
1.11M
    }
2912
1.11M
    if (code >= 0) {
2913
1.11M
        if (LAZY_WEDGES)
2914
1.11M
            move_wedge(&L12, l12, true);
2915
1.11M
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2916
1.11M
    }
2917
1.11M
    if (code >= 0) {
2918
1.11M
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2919
1.11M
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2920
1.11M
    }
2921
1.11M
    if (LAZY_WEDGES) {
2922
1.11M
        if (code >= 0)
2923
1.11M
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2924
1.11M
        if (code >= 0)
2925
1.11M
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2926
1.11M
        if (code >= 0)
2927
1.11M
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2928
1.11M
        if (code >= 0)
2929
1.11M
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2930
1.11M
        if (code >= 0)
2931
1.11M
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2932
1.11M
        if (code >= 0)
2933
1.11M
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2934
1.11M
    }
2935
1.11M
    pfs->inside = inside_save;
2936
5.97M
out:
2937
5.97M
    release_colors_inline(pfs, color_stack_ptr, 3);
2938
5.97M
    return code;
2939
1.11M
}
2940
2941
static inline int
2942
fill_triangle(patch_fill_state_t *pfs,
2943
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2,
2944
        wedge_vertex_list_t *l01, wedge_vertex_list_t *l12, wedge_vertex_list_t *l20)
2945
1.96M
{
2946
1.96M
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2947
1.96M
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2948
1.96M
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2949
1.96M
    fixed sd1 = max(sd01, sd12);
2950
1.96M
    fixed sd = max(sd1, sd20);
2951
1.96M
    double cd = 0;
2952
2953
#   if SKIP_TEST
2954
        dbg_triangle_cnt++;
2955
#   endif
2956
1.96M
    if (pfs->Function == NULL) {
2957
1.63M
        double d01 = color_span(pfs, p1->c, p0->c);
2958
1.63M
        double d12 = color_span(pfs, p2->c, p1->c);
2959
1.63M
        double d20 = color_span(pfs, p0->c, p2->c);
2960
1.63M
        double cd1 = max(d01, d12);
2961
2962
1.63M
        cd = max(cd1, d20);
2963
1.63M
    }
2964
1.96M
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2965
1.96M
}
2966
2967
static int
2968
small_mesh_triangle(patch_fill_state_t *pfs,
2969
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
2970
316k
{
2971
316k
    int code;
2972
316k
    wedge_vertex_list_t l[3];
2973
2974
316k
    init_wedge_vertex_list(l, count_of(l));
2975
316k
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2976
316k
    if (code < 0)
2977
0
        return code;
2978
316k
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2979
316k
    if (code < 0)
2980
0
        return code;
2981
316k
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2982
316k
    if (code < 0)
2983
0
        return code;
2984
316k
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
2985
316k
}
2986
2987
int
2988
gx_init_patch_fill_state_for_clist(gx_device *dev, patch_fill_state_t *pfs, gs_memory_t *memory)
2989
0
{
2990
0
    int i;
2991
2992
0
    pfs->dev = dev;
2993
0
    pfs->pgs = NULL;
2994
0
    pfs->direct_space = NULL;
2995
0
    pfs->num_components = dev->color_info.num_components;
2996
    /* pfs->cc_max_error[GS_CLIENT_COLOR_MAX_COMPONENTS] unused */
2997
0
    pfs->pshm = NULL;
2998
0
    pfs->Function = NULL;
2999
0
    pfs->function_arg_shift = 0;
3000
0
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
3001
0
    pfs->n_color_args = 1; /* unused. */
3002
0
    pfs->max_small_coord = 0; /* unused. */
3003
0
    pfs->wedge_vertex_list_elem_buffer = NULL; /* fixme */
3004
0
    pfs->free_wedge_vertex = NULL; /* fixme */
3005
0
    pfs->wedge_vertex_list_elem_count = 0; /* fixme */
3006
0
    pfs->wedge_vertex_list_elem_count_max = 0; /* fixme */
3007
0
    for (i = 0; i < pfs->num_components; i++)
3008
0
        pfs->color_domain.paint.values[i] = (float)0x7fffffff;
3009
    /* decomposition_limit must be same as one in init_patch_fill_state */
3010
#ifdef MAX_SHADING_RESOLUTION
3011
    pfs->decomposition_limit = float2fixed(min(pfs->dev->HWResolution[0],
3012
                                               pfs->dev->HWResolution[1]) / MAX_SHADING_RESOLUTION);
3013
    pfs->decomposition_limit = max(pfs->decomposition_limit, fixed_1);
3014
#else
3015
0
    pfs->decomposition_limit = fixed_1;
3016
0
#endif
3017
0
    pfs->fixed_flat = 0; /* unused */
3018
0
    pfs->smoothness = 0; /* unused */
3019
0
    pfs->maybe_self_intersecting = false; /* unused */
3020
0
    pfs->monotonic_color = true;
3021
0
    pfs->linear_color = true;
3022
0
    pfs->unlinear = false; /* Because it is used when fill_linear_color_triangle was called. */
3023
0
    pfs->inside = false;
3024
0
    pfs->color_stack_size = 0;
3025
0
    pfs->color_stack_step = dev->color_info.num_components;
3026
0
    pfs->color_stack_ptr = NULL; /* fixme */
3027
0
    pfs->color_stack = NULL; /* fixme */
3028
0
    pfs->color_stack_limit = NULL; /* fixme */
3029
0
    pfs->pcic = NULL; /* Will do someday. */
3030
0
    pfs->trans_device = NULL;
3031
0
    pfs->icclink = NULL;
3032
0
    return alloc_patch_fill_memory(pfs, memory, NULL);
3033
0
}
3034
3035
/* A method for filling a small triangle that the device can't handle.
3036
   Used by clist playback. */
3037
int
3038
gx_fill_triangle_small(gx_device *dev, const gs_fill_attributes *fa,
3039
        const gs_fixed_point *p0, const gs_fixed_point *p1,
3040
        const gs_fixed_point *p2,
3041
        const frac31 *c0, const frac31 *c1, const frac31 *c2)
3042
0
{
3043
0
    patch_fill_state_t *pfs = fa->pfs;
3044
0
    patch_color_t c[3];
3045
0
    shading_vertex_t p[3];
3046
0
    uchar i;
3047
3048
    /* pfs->rect = *fa->clip; unused ? */
3049
0
    p[0].p = *p0;
3050
0
    p[1].p = *p1;
3051
0
    p[2].p = *p2;
3052
0
    p[0].c = &c[0];
3053
0
    p[1].c = &c[1];
3054
0
    p[2].c = &c[2];
3055
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. */
3056
0
    for (i = 0; i < dev->color_info.num_components; i++) {
3057
0
        c[0].cc.paint.values[i] = (float)c0[i];
3058
0
        c[1].cc.paint.values[i] = (float)c1[i];
3059
0
        c[2].cc.paint.values[i] = (float)c2[i];
3060
0
    }
3061
    /* fixme: the cycle above converts frac31 values into floats.
3062
       We don't like this because (1) it misses lower bits,
3063
       and (2) fixed point values can be faster on some platforms.
3064
       We could fix it with coding a template for small_mesh_triangle
3065
       and its callees until patch_color_to_device_color_inline.
3066
    */
3067
    /* fixme : this function is called from gxclrast.c
3068
       after dev->procs.fill_linear_color_triangle returns 0 - "subdivide".
3069
       After few moments small_mesh_triangle indirectly calls
3070
       same function with same arguments as a part of
3071
       try_device_linear_color in triangle_by_4.
3072
       Obviusly it will return zero again.
3073
       Actually we don't need the second call,
3074
       so optimize with skipping the second call.
3075
     */
3076
0
    return small_mesh_triangle(pfs, &p[0], &p[1], &p[2]);
3077
0
}
3078
3079
static int
3080
mesh_triangle_rec(patch_fill_state_t *pfs,
3081
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
3082
385k
{
3083
385k
    pfs->unlinear = !is_linear_color_applicable(pfs);
3084
385k
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3085
385k
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3086
385k
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3087
316k
        return small_mesh_triangle(pfs, p0, p1, p2);
3088
69.1k
    else {
3089
        /* Subdivide into 4 triangles with 3 triangle non-lazy wedges.
3090
           Doing so against the wedge_vertex_list_elem_buffer overflow.
3091
           We could apply a smarter method, dividing long sides
3092
           with no wedges and short sides with lazy wedges.
3093
           This needs to start wedges dynamically when
3094
           a side becomes short. We don't do so because the
3095
           number of checks per call significantly increases
3096
           and the logics is complicated, but the performance
3097
           advantage appears small due to big meshes are rare.
3098
         */
3099
69.1k
        shading_vertex_t p01, p12, p20;
3100
69.1k
        patch_color_t *c[3];
3101
69.1k
        int code;
3102
69.1k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3103
3104
69.1k
        if (color_stack_ptr == NULL)
3105
0
            return_error(gs_error_unregistered); /* Must not happen. */
3106
69.1k
        p01.c = c[0];
3107
69.1k
        p12.c = c[1];
3108
69.1k
        p20.c = c[2];
3109
69.1k
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3110
69.1k
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3111
69.1k
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3112
69.1k
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3113
69.1k
        if (code >= 0)
3114
69.1k
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3115
69.1k
        if (code >= 0)
3116
69.1k
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3117
69.1k
        if (code >= 0)
3118
69.1k
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3119
69.1k
        if (code >= 0)
3120
69.1k
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3121
69.1k
        if (code >= 0)
3122
69.1k
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3123
69.1k
        if (code >= 0)
3124
69.1k
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3125
69.1k
        release_colors_inline(pfs, color_stack_ptr, 3);
3126
69.1k
        return code;
3127
69.1k
    }
3128
385k
}
3129
3130
int
3131
mesh_triangle(patch_fill_state_t *pfs,
3132
        const shading_vertex_t *p0, const shading_vertex_t *p1, const shading_vertex_t *p2)
3133
108k
{
3134
108k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3135
108k
            gxdso_pattern_shading_area, NULL, 0) > 0) {
3136
        /* Inform the device with the shading coverage area.
3137
           First compute the sign of the area, because
3138
           all areas to be clipped in same direction. */
3139
0
        gx_device *pdev = pfs->dev;
3140
0
        gx_path path;
3141
0
        int code;
3142
0
        fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
3143
0
        fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
3144
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3145
3146
0
        gx_path_init_local(&path, pdev->memory);
3147
0
        code = gx_path_add_point(&path, p0->p.x, p0->p.y);
3148
0
        if (code >= 0 && s1 >= 0)
3149
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3150
0
        if (code >= 0)
3151
0
            code = gx_path_add_line(&path, p2->p.x, p2->p.y);
3152
0
        if (code >= 0 && s1 < 0)
3153
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3154
0
        if (code >= 0)
3155
0
            code = gx_path_close_subpath(&path);
3156
0
        if (code >= 0)
3157
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3158
0
        gx_path_free(&path, "mesh_triangle");
3159
0
        if (code < 0)
3160
0
            return code;
3161
0
    }
3162
108k
    return mesh_triangle_rec(pfs, p0, p1, p2);
3163
108k
}
3164
3165
static inline int
3166
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3167
335k
{
3168
335k
    shading_vertex_t p0001, p1011, q;
3169
335k
    patch_color_t *c[3];
3170
335k
    wedge_vertex_list_t l[4];
3171
335k
    int code;
3172
335k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3173
3174
335k
    if(color_stack_ptr == NULL)
3175
0
        return_error(gs_error_unregistered); /* Must not happen. */
3176
335k
    p0001.c = c[0];
3177
335k
    p1011.c = c[1];
3178
335k
    q.c = c[2];
3179
335k
    init_wedge_vertex_list(l, count_of(l));
3180
335k
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3181
335k
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3182
335k
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3183
335k
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3184
335k
    if (code >= 0) {
3185
335k
        l[0].last_side = true;
3186
335k
        l[3].last_side = true;
3187
335k
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3188
335k
    }
3189
335k
    if (code >= 0) {
3190
335k
        l[1].last_side = true;
3191
335k
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3192
335k
    }
3193
335k
    if (code >= 0) {
3194
335k
        l[2].last_side = true;
3195
335k
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3196
335k
    }
3197
335k
    if (code >= 0)
3198
335k
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3199
335k
    if (code >= 0)
3200
335k
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3201
335k
    if (code >= 0)
3202
335k
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3203
335k
    if (code >= 0)
3204
335k
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3205
335k
    release_colors_inline(pfs, color_stack_ptr, 3);
3206
335k
    return code;
3207
335k
}
3208
3209
static inline int
3210
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3211
152k
{
3212
152k
    wedge_vertex_list_t l;
3213
152k
    int code;
3214
3215
152k
    init_wedge_vertex_list(&l, 1);
3216
152k
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3217
152k
    if (code < 0)
3218
0
        return code;
3219
152k
    l.last_side = true;
3220
152k
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3221
152k
    if (code < 0)
3222
0
        return code;
3223
152k
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3224
152k
    if (code < 0)
3225
0
        return code;
3226
152k
    return 0;
3227
152k
}
3228
3229
static inline void
3230
make_quadrangle(const tensor_patch *p, shading_vertex_t qq[2][2],
3231
        wedge_vertex_list_t l[4], quadrangle_patch *q)
3232
558k
{
3233
558k
    qq[0][0].p = p->pole[0][0];
3234
558k
    qq[0][1].p = p->pole[0][3];
3235
558k
    qq[1][0].p = p->pole[3][0];
3236
558k
    qq[1][1].p = p->pole[3][3];
3237
558k
    qq[0][0].c = p->c[0][0];
3238
558k
    qq[0][1].c = p->c[0][1];
3239
558k
    qq[1][0].c = p->c[1][0];
3240
558k
    qq[1][1].c = p->c[1][1];
3241
558k
    q->p[0][0] = &qq[0][0];
3242
558k
    q->p[0][1] = &qq[0][1];
3243
558k
    q->p[1][0] = &qq[1][0];
3244
558k
    q->p[1][1] = &qq[1][1];
3245
558k
    q->l0001 = &l[0];
3246
558k
    q->l0111 = &l[1];
3247
558k
    q->l1110 = &l[2];
3248
558k
    q->l1000 = &l[3];
3249
558k
}
3250
3251
static inline int
3252
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3253
182k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3254
182k
    int code;
3255
3256
182k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3257
182k
    if (code <= 0)
3258
0
        return code;
3259
182k
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3260
182k
}
3261
3262
static inline int
3263
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3264
38.3k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3265
38.3k
    int code;
3266
3267
38.3k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3268
38.3k
    if (code <= 0)
3269
6.95k
        return code;
3270
31.4k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3271
38.3k
}
3272
3273
static inline int
3274
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3275
34.1k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3276
34.1k
    int code;
3277
3278
34.1k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3279
34.1k
    if (code <= 0)
3280
4.80k
        return code;
3281
29.3k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3282
34.1k
}
3283
3284
typedef enum {
3285
    color_change_small,
3286
    color_change_gradient,
3287
    color_change_linear,
3288
    color_change_bilinear,
3289
    color_change_general
3290
} color_change_type_t;
3291
3292
static inline color_change_type_t
3293
quadrangle_color_change(const patch_fill_state_t *pfs, const quadrangle_patch *p,
3294
                        bool is_big_u, bool is_big_v, double size_u, double size_v,
3295
                        bool *divide_u, bool *divide_v)
3296
609k
{
3297
609k
    patch_color_t d0001, d1011, d;
3298
609k
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3299
609k
    double Du, Dv;
3300
3301
609k
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3302
609k
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3303
609k
    D0001 = color_norm(pfs, &d0001);
3304
609k
    D1011 = color_norm(pfs, &d1011);
3305
609k
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3306
609k
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3307
609k
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3308
609k
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3309
609k
    if (pfs->unlinear) {
3310
420k
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
3311
420k
            D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
3312
420k
            D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
3313
344k
            return color_change_small;
3314
76.3k
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
3315
47.1k
            if (!is_big_v) {
3316
                /* The color function looks uncontiguous. */
3317
2.64k
                return color_change_small;
3318
2.64k
            }
3319
44.4k
            *divide_v = true;
3320
44.4k
            return color_change_gradient;
3321
47.1k
        }
3322
29.2k
        if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
3323
28.4k
            if (!is_big_u) {
3324
                /* The color function looks uncontiguous. */
3325
191
                return color_change_small;
3326
191
            }
3327
28.2k
            *divide_u = true;
3328
28.2k
            return color_change_gradient;
3329
28.4k
        }
3330
29.2k
    }
3331
190k
    color_diff(pfs, &d0001, &d1011, &d);
3332
190k
    Du = max(D0001, D1011);
3333
190k
    Dv = max(D0010, D0111);
3334
190k
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3335
25.6k
        return color_change_small;
3336
164k
    if (Du <= pfs->smoothness / 8)
3337
7.37k
        return color_change_linear;
3338
157k
    if (Dv <= pfs->smoothness / 8)
3339
144k
        return color_change_linear;
3340
12.2k
    D = color_norm(pfs, &d);
3341
12.2k
    if (D <= pfs->smoothness)
3342
10.7k
        return color_change_bilinear;
3343
1.49k
#if 1
3344
1.49k
    if (Du > Dv && is_big_u)
3345
599
        *divide_u = true;
3346
900
    else if (Du < Dv && is_big_v)
3347
554
        *divide_v = true;
3348
346
    else if (is_big_u && size_u > size_v)
3349
147
        *divide_u = true;
3350
199
    else if (is_big_v && size_v > size_u)
3351
199
        *divide_v = true;
3352
0
    else if (is_big_u)
3353
0
        *divide_u = true;
3354
0
    else if (is_big_v)
3355
0
        *divide_v = true;
3356
0
    else {
3357
        /* The color function looks uncontiguous. */
3358
0
        return color_change_small;
3359
0
    }
3360
#else /* Disabled due to infinite recursion with -r200 09-57.PS
3361
         (Standard Test 6.4  - Range 6) (Test05). */
3362
    if (Du > Dv)
3363
        *divide_u = true;
3364
    else
3365
        *divide_v = true;
3366
#endif
3367
1.49k
    return color_change_general;
3368
1.49k
}
3369
3370
static int
3371
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3372
731k
{
3373
    /* The quadrangle is flattened enough by V and U, so ignore inner poles. */
3374
    /* Assuming the XY span is restricted with curve_samples.
3375
       It is important for intersection_of_small_bars to compute faster. */
3376
731k
    quadrangle_patch s0, s1;
3377
731k
    wedge_vertex_list_t l0, l1, l2;
3378
731k
    int code;
3379
731k
    bool divide_u = false, divide_v = false, big1 = big;
3380
731k
    shading_vertex_t q[2];
3381
731k
    bool monotonic_color_save = pfs->monotonic_color;
3382
731k
    bool linear_color_save = pfs->linear_color;
3383
731k
    bool inside_save = pfs->inside;
3384
731k
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3385
731k
    gs_fixed_rect r = {{0,0},{0,0}}, r1 = {{0,0},{0,0}};
3386
    /* Warning : pfs->monotonic_color is not restored on error. */
3387
3388
731k
    if (!inside) {
3389
290k
        bbox_of_points(&r, &p->p[0][0]->p, &p->p[0][1]->p, &p->p[1][0]->p, &p->p[1][1]->p);
3390
290k
        r1 = r;
3391
290k
        rect_intersect(r, pfs->rect);
3392
290k
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3393
83.1k
            return 0; /* Outside. */
3394
290k
    }
3395
648k
    if (big) {
3396
        /* Likely 'big' is an unuseful rudiment due to curve_samples
3397
           restricts lengthes. We keep it for a while because its implementation
3398
           isn't obvious and its time consumption is invisibly small.
3399
         */
3400
480k
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3401
480k
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3402
480k
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3403
480k
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3404
480k
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3405
480k
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3406
480k
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3407
480k
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3408
3409
480k
        if (QUADRANGLES && pfs->maybe_self_intersecting) {
3410
0
            if (size_v > pfs->max_small_coord) {
3411
                /* constant_color_quadrangle can't handle big self-intersecting areas
3412
                   because we don't want int64_t in it. */
3413
0
                divide_v = true;
3414
0
            } else if (size_u > pfs->max_small_coord) {
3415
                /* constant_color_quadrangle can't handle big self-intersecting areas,
3416
                   because we don't want int64_t in it. */
3417
0
                divide_u = true;
3418
0
            } else
3419
0
                big1 = false;
3420
0
        } else
3421
480k
            big1 = false;
3422
480k
    }
3423
648k
    if (!big1) {
3424
648k
        bool is_big_u = false, is_big_v = false;
3425
648k
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3426
648k
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3427
648k
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3428
648k
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3429
648k
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3430
648k
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3431
648k
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3432
648k
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3433
648k
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3434
648k
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3435
3436
648k
        if (size_u > pfs->decomposition_limit)
3437
615k
            is_big_u = true;
3438
648k
        if (size_v > pfs->decomposition_limit)
3439
138k
            is_big_v = true;
3440
509k
        else if (!is_big_u)
3441
25.9k
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3442
20.9k
                        constant_color_quadrangle : triangles4)(pfs, p,
3443
25.9k
                            pfs->maybe_self_intersecting);
3444
622k
        if (!pfs->monotonic_color) {
3445
36.2k
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3446
3447
36.2k
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3448
36.2k
            if (code < 0)
3449
0
                return code;
3450
36.2k
            if (is_big_u)
3451
35.6k
                divide_u = not_monotonic_by_u;
3452
36.2k
            if (is_big_v)
3453
31.2k
                divide_v = not_monotonic_by_v;
3454
36.2k
            if (!divide_u && !divide_v)
3455
30.7k
                pfs->monotonic_color = true;
3456
36.2k
        }
3457
622k
        if (pfs->monotonic_color && !pfs->linear_color) {
3458
478k
            if (divide_v && divide_u) {
3459
0
                if (size_u > size_v)
3460
0
                    divide_v = false;
3461
0
                else
3462
0
                    divide_u = false;
3463
478k
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3464
193k
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3465
182k
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3466
182k
                    if (code < 0)
3467
0
                        return code;
3468
182k
                    divide_u = !code;
3469
182k
                }
3470
193k
                if (is_big_v) {
3471
38.3k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3472
38.3k
                    if (code < 0)
3473
0
                        return code;
3474
38.3k
                    divide_v = !code;
3475
38.3k
                }
3476
193k
                if (is_big_u && is_big_v) {
3477
34.1k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3478
34.1k
                    if (code < 0)
3479
0
                        return code;
3480
34.1k
                    if (!code) {
3481
4.80k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3482
2.51k
                            divide_u = true;
3483
2.51k
                            divide_v = false;
3484
2.51k
                        } else {
3485
2.29k
                            divide_v = true;
3486
2.29k
                            divide_u = false;
3487
2.29k
                        }
3488
4.80k
                    }
3489
34.1k
                }
3490
193k
            }
3491
478k
            if (!divide_u && !divide_v)
3492
471k
                pfs->linear_color = true;
3493
478k
        }
3494
622k
        if (!pfs->linear_color) {
3495
            /* go to divide. */
3496
609k
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3497
372k
            case color_change_small:
3498
372k
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3499
303k
                            constant_color_quadrangle : triangles4)(pfs, p,
3500
372k
                                pfs->maybe_self_intersecting);
3501
372k
                pfs->monotonic_color = monotonic_color_save;
3502
372k
                pfs->linear_color = linear_color_save;
3503
372k
                return code;
3504
10.7k
            case color_change_bilinear:
3505
10.7k
                if (!QUADRANGLES) {
3506
10.7k
                    code = triangles4(pfs, p, true);
3507
10.7k
                    pfs->monotonic_color = monotonic_color_save;
3508
10.7k
                    pfs->linear_color = linear_color_save;
3509
10.7k
                    return code;
3510
10.7k
                }
3511
152k
            case color_change_linear:
3512
152k
                if (!QUADRANGLES) {
3513
152k
                    code = triangles2(pfs, p, true);
3514
152k
                    pfs->monotonic_color = monotonic_color_save;
3515
152k
                    pfs->linear_color = linear_color_save;
3516
152k
                    return code;
3517
152k
                }
3518
72.7k
            case color_change_gradient:
3519
74.2k
            case color_change_general:
3520
74.2k
                ; /* goto divide. */
3521
609k
        }
3522
622k
    }
3523
86.6k
    if (!inside) {
3524
18.4k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3525
18.4k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3526
4.28k
            pfs->inside = true;
3527
18.4k
    }
3528
86.6k
    if (LAZY_WEDGES)
3529
86.6k
        init_wedge_vertex_list(&l0, 1);
3530
86.6k
    if (divide_v) {
3531
55.1k
        patch_color_t *c[2];
3532
55.1k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3533
3534
55.1k
        if(color_stack_ptr == NULL)
3535
0
            return_error(gs_error_unregistered); /* Must not happen. */
3536
55.1k
        q[0].c = c[0];
3537
55.1k
        q[1].c = c[1];
3538
55.1k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3539
55.1k
        if (LAZY_WEDGES) {
3540
55.1k
            code = make_wedge_median(pfs, &l1, p->l0111, true,  &p->p[0][1]->p, &p->p[1][1]->p, &s0.p[1][1]->p);
3541
55.1k
            if (code >= 0)
3542
55.1k
                code = make_wedge_median(pfs, &l2, p->l1000, false, &p->p[1][0]->p, &p->p[0][0]->p, &s0.p[1][0]->p);
3543
55.1k
            if (code >= 0) {
3544
55.1k
                s0.l1110 = s1.l0001 = &l0;
3545
55.1k
                s0.l0111 = s1.l0111 = &l1;
3546
55.1k
                s0.l1000 = s1.l1000 = &l2;
3547
55.1k
                s0.l0001 = p->l0001;
3548
55.1k
                s1.l1110 = p->l1110;
3549
55.1k
            }
3550
55.1k
        } else {
3551
0
            code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[1][0], s0.p[1][0]);
3552
0
            if (code >= 0)
3553
0
                code = fill_triangle_wedge(pfs, s0.p[0][1], s1.p[1][1], s0.p[1][1]);
3554
0
        }
3555
55.1k
        if (code >= 0)
3556
55.1k
            code = fill_quadrangle(pfs, &s0, big1);
3557
55.1k
        if (code >= 0) {
3558
55.1k
            if (LAZY_WEDGES) {
3559
55.1k
                l0.last_side = true;
3560
55.1k
                move_wedge(&l1, p->l0111, true);
3561
55.1k
                move_wedge(&l2, p->l1000, false);
3562
55.1k
            }
3563
55.1k
            code = fill_quadrangle(pfs, &s1, big1);
3564
55.1k
        }
3565
55.1k
        if (LAZY_WEDGES) {
3566
55.1k
            if (code >= 0)
3567
55.1k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3568
55.1k
            if (code >= 0)
3569
55.1k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3570
55.1k
            if (code >= 0)
3571
55.1k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3572
55.1k
            release_colors_inline(pfs, color_stack_ptr, 2);
3573
55.1k
        }
3574
55.1k
    } else if (divide_u) {
3575
31.4k
        patch_color_t *c[2];
3576
31.4k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3577
3578
31.4k
        if(color_stack_ptr == NULL)
3579
0
            return_error(gs_error_unregistered); /* Must not happen. */
3580
31.4k
        q[0].c = c[0];
3581
31.4k
        q[1].c = c[1];
3582
31.4k
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3583
31.4k
        if (LAZY_WEDGES) {
3584
31.4k
            code = make_wedge_median(pfs, &l1, p->l0001, true,  &p->p[0][0]->p, &p->p[0][1]->p, &s0.p[0][1]->p);
3585
31.4k
            if (code >= 0)
3586
31.4k
                code = make_wedge_median(pfs, &l2, p->l1110, false, &p->p[1][1]->p, &p->p[1][0]->p, &s0.p[1][1]->p);
3587
31.4k
            if (code >= 0) {
3588
31.4k
                s0.l0111 = s1.l1000 = &l0;
3589
31.4k
                s0.l0001 = s1.l0001 = &l1;
3590
31.4k
                s0.l1110 = s1.l1110 = &l2;
3591
31.4k
                s0.l1000 = p->l1000;
3592
31.4k
                s1.l0111 = p->l0111;
3593
31.4k
            }
3594
31.4k
        } else {
3595
0
            code = fill_triangle_wedge(pfs, s0.p[0][0], s1.p[0][1], s0.p[0][1]);
3596
0
            if (code >= 0)
3597
0
                code = fill_triangle_wedge(pfs, s0.p[1][0], s1.p[1][1], s0.p[1][1]);
3598
0
        }
3599
31.4k
        if (code >= 0)
3600
31.4k
            code = fill_quadrangle(pfs, &s0, big1);
3601
31.4k
        if (code >= 0) {
3602
31.4k
            if (LAZY_WEDGES) {
3603
31.4k
                l0.last_side = true;
3604
31.4k
                move_wedge(&l1, p->l0001, true);
3605
31.4k
                move_wedge(&l2, p->l1110, false);
3606
31.4k
            }
3607
31.4k
            code = fill_quadrangle(pfs, &s1, big1);
3608
31.4k
        }
3609
31.4k
        if (LAZY_WEDGES) {
3610
31.4k
            if (code >= 0)
3611
31.4k
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3612
31.4k
            if (code >= 0)
3613
31.4k
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3614
31.4k
            if (code >= 0)
3615
31.4k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3616
31.4k
            release_colors_inline(pfs, color_stack_ptr, 2);
3617
31.4k
        }
3618
31.4k
    } else
3619
0
        code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3620
0
                    constant_color_quadrangle : triangles4)(pfs, p,
3621
0
                        pfs->maybe_self_intersecting);
3622
86.6k
    pfs->monotonic_color = monotonic_color_save;
3623
86.6k
    pfs->linear_color = linear_color_save;
3624
86.6k
    pfs->inside = inside_save;
3625
86.6k
    return code;
3626
86.6k
}
3627
3628
/* This splits tensor patch p->pole[v][u] on u to give s0->pole[v][u] and s1->pole[v][u] */
3629
static inline void
3630
split_stripe(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p, patch_color_t *c[2])
3631
1.01M
{
3632
1.01M
    s0->c[0][1] = c[0];
3633
1.01M
    s0->c[1][1] = c[1];
3634
1.01M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3635
1.01M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3636
1.01M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3637
1.01M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3638
1.01M
    s0->c[0][0] = p->c[0][0];
3639
1.01M
    s0->c[1][0] = p->c[1][0];
3640
1.01M
    s1->c[0][0] = s0->c[0][1];
3641
1.01M
    s1->c[1][0] = s0->c[1][1];
3642
1.01M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3643
1.01M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3644
1.01M
    s1->c[0][1] = p->c[0][1];
3645
1.01M
    s1->c[1][1] = p->c[1][1];
3646
1.01M
}
3647
3648
/* This splits tensor patch p->pole[v][u] on v to give s0->pole[v][u] and s1->pole[v][u] */
3649
static inline void
3650
split_patch(patch_fill_state_t *pfs, tensor_patch *s0, tensor_patch *s1, const tensor_patch *p, patch_color_t *c[2])
3651
212k
{
3652
212k
    s0->c[1][0] = c[0];
3653
212k
    s0->c[1][1] = c[1];
3654
212k
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3655
212k
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3656
212k
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3657
212k
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3658
212k
    s0->c[0][0] = p->c[0][0];
3659
212k
    s0->c[0][1] = p->c[0][1];
3660
212k
    s1->c[0][0] = s0->c[1][0];
3661
212k
    s1->c[0][1] = s0->c[1][1];
3662
212k
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3663
212k
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3664
212k
    s1->c[1][0] = p->c[1][0];
3665
212k
    s1->c[1][1] = p->c[1][1];
3666
212k
}
3667
3668
static inline void
3669
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3670
1.73M
{
3671
1.73M
    int i, j;
3672
3673
1.73M
    r->p.x = r->q.x = p->pole[0][0].x;
3674
1.73M
    r->p.y = r->q.y = p->pole[0][0].y;
3675
8.68M
    for (i = 0; i < 4; i++) {
3676
34.7M
        for (j = 0; j < 4; j++) {
3677
27.8M
            const gs_fixed_point *q = &p->pole[i][j];
3678
3679
27.8M
            if (r->p.x > q->x)
3680
3.72M
                r->p.x = q->x;
3681
27.8M
            if (r->p.y > q->y)
3682
4.32M
                r->p.y = q->y;
3683
27.8M
            if (r->q.x < q->x)
3684
5.69M
                r->q.x = q->x;
3685
27.8M
            if (r->q.y < q->y)
3686
3.72M
                r->q.y = q->y;
3687
27.8M
        }
3688
6.95M
    }
3689
1.73M
}
3690
3691
static int
3692
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3693
2.24M
{
3694
2.24M
    if (ku > 1) {
3695
1.68M
        tensor_patch s0, s1;
3696
1.68M
        patch_color_t *c[2];
3697
1.68M
        int code;
3698
1.68M
        byte *color_stack_ptr;
3699
1.68M
        bool save_inside = pfs->inside;
3700
3701
1.68M
        if (!pfs->inside) {
3702
1.51M
            gs_fixed_rect r, r1;
3703
3704
1.51M
            tensor_patch_bbox(&r, p);
3705
1.51M
            r1 = r;
3706
1.51M
            rect_intersect(r, pfs->rect);
3707
1.51M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3708
672k
                return 0;
3709
843k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3710
843k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3711
62.1k
                pfs->inside = true;
3712
843k
        }
3713
1.01M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3714
1.01M
        if(color_stack_ptr == NULL)
3715
0
            return_error(gs_error_unregistered); /* Must not happen. */
3716
1.01M
        split_stripe(pfs, &s0, &s1, p, c);
3717
1.01M
        code = decompose_stripe(pfs, &s0, ku / 2);
3718
1.01M
        if (code >= 0)
3719
1.01M
            code = decompose_stripe(pfs, &s1, ku / 2);
3720
1.01M
        release_colors_inline(pfs, color_stack_ptr, 2);
3721
1.01M
        pfs->inside = save_inside;
3722
1.01M
        return code;
3723
1.01M
    } else {
3724
558k
        quadrangle_patch q;
3725
558k
        shading_vertex_t qq[2][2];
3726
558k
        wedge_vertex_list_t l[4];
3727
558k
        int code;
3728
3729
558k
        init_wedge_vertex_list(l, count_of(l));
3730
558k
        make_quadrangle(p, qq, l, &q);
3731
#       if SKIP_TEST
3732
            dbg_quad_cnt++;
3733
#       endif
3734
558k
        code = fill_quadrangle(pfs, &q, true);
3735
558k
        if (code < 0)
3736
0
            return code;
3737
558k
        if (LAZY_WEDGES) {
3738
558k
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3739
558k
            if (code < 0)
3740
0
                return code;
3741
558k
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3742
558k
            if (code < 0)
3743
0
                return code;
3744
558k
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3745
558k
            if (code < 0)
3746
0
                return code;
3747
558k
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3748
558k
            if (code < 0)
3749
0
                return code;
3750
558k
        }
3751
558k
        return code;
3752
558k
    }
3753
2.24M
}
3754
3755
static int
3756
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3757
219k
{
3758
    /* The stripe is flattened enough by V, so ignore inner poles. */
3759
219k
    int ku[4], kum, code;
3760
3761
    /* We would like to apply iterations for enumerating the kum curve parts,
3762
       but the roundinmg errors would be too complicated due to
3763
       the dependence on the direction. Note that neigbour
3764
       patches may use the opposite direction for same bounding curve.
3765
       We apply the recursive dichotomy, in which
3766
       the rounding errors do not depend on the direction. */
3767
219k
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3768
219k
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3769
219k
    kum = max(ku[0], ku[3]);
3770
219k
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3771
219k
    if (code < 0)
3772
0
        return code;
3773
219k
    if (INTERPATCH_PADDING) {
3774
219k
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3775
219k
        if (code < 0)
3776
0
            return code;
3777
219k
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3778
219k
        if (code < 0)
3779
0
            return code;
3780
219k
    }
3781
219k
    code = decompose_stripe(pfs, p, kum);
3782
219k
    if (code < 0)
3783
0
        return code;
3784
219k
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3785
219k
}
3786
3787
static inline bool neqs(int *a, int b)
3788
557k
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3789
557k
    if (*a * b < 0)
3790
199k
        return true;
3791
358k
    if (!*a)
3792
6.97k
        *a = b;
3793
358k
    return false;
3794
557k
}
3795
3796
static inline int
3797
vector_pair_orientation(const gs_fixed_point *p0, const gs_fixed_point *p1, const gs_fixed_point *p2)
3798
773k
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3799
773k
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3800
773k
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3801
3802
773k
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3803
773k
}
3804
3805
static inline bool
3806
is_x_bended(const tensor_patch *p)
3807
216k
{
3808
216k
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3809
3810
216k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3811
112k
        return true;
3812
103k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3813
68.6k
        return true;
3814
35.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3815
17.8k
        return true;
3816
3817
17.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3818
145
        return true;
3819
17.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3820
0
        return true;
3821
17.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3822
64
        return true;
3823
17.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3824
39
        return true;
3825
3826
16.9k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3827
106
        return true;
3828
16.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3829
0
        return true;
3830
16.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3831
76
        return true;
3832
16.7k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3833
64
        return true;
3834
3835
16.7k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3836
21
        return true;
3837
16.7k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3838
0
        return true;
3839
16.7k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3840
27
        return true;
3841
16.6k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3842
16
        return true;
3843
16.6k
    return false;
3844
16.6k
}
3845
3846
static inline bool
3847
is_y_bended(const tensor_patch *p)
3848
0
{
3849
0
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3850
3851
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3852
0
        return true;
3853
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3854
0
        return true;
3855
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3856
0
        return true;
3857
3858
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3859
0
        return true;
3860
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3861
0
        return true;
3862
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3863
0
        return true;
3864
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3865
0
        return true;
3866
3867
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3868
0
        return true;
3869
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3870
0
        return true;
3871
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3872
0
        return true;
3873
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3874
0
        return true;
3875
3876
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3877
0
        return true;
3878
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3879
0
        return true;
3880
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3881
0
        return true;
3882
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3883
0
        return true;
3884
0
    return false;
3885
0
}
3886
3887
static inline bool
3888
is_curve_x_small(const patch_fill_state_t *pfs, const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3889
1.32M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3890
1.32M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3891
1.32M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3892
1.32M
    fixed xmin =  min(xmin0, xmin1);
3893
1.32M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3894
1.32M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3895
1.32M
    fixed xmax =  max(xmax0, xmax1);
3896
3897
1.32M
    if(xmax - xmin <= pfs->decomposition_limit)
3898
1.14M
        return true;
3899
187k
    return false;
3900
1.32M
}
3901
3902
static inline bool
3903
is_curve_y_small(const patch_fill_state_t *pfs, const gs_fixed_point *pole, int pole_step, fixed fixed_flat)
3904
869k
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3905
869k
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3906
869k
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3907
869k
    fixed ymin =  min(ymin0, ymin1);
3908
869k
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3909
869k
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3910
869k
    fixed ymax =  max(ymax0, ymax1);
3911
3912
869k
    if (ymax - ymin <= pfs->decomposition_limit)
3913
840k
        return true;
3914
29.0k
    return false;
3915
869k
}
3916
3917
static inline bool
3918
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3919
419k
{
3920
419k
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3921
68.4k
        return false;
3922
350k
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3923
48.7k
        return false;
3924
301k
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3925
43.9k
        return false;
3926
257k
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3927
25.9k
        return false;
3928
231k
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3929
12.6k
        return false;
3930
219k
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3931
7.52k
        return false;
3932
211k
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3933
5.27k
        return false;
3934
206k
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3935
3.52k
        return false;
3936
202k
    return true;
3937
206k
}
3938
3939
static int
3940
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3941
443k
{
3942
443k
    if (kv <= 1) {
3943
419k
        if (is_patch_narrow(pfs, p))
3944
202k
            return fill_stripe(pfs, p);
3945
216k
        if (!is_x_bended(p))
3946
16.6k
            return fill_stripe(pfs, p);
3947
216k
    }
3948
223k
    {   tensor_patch s0, s1;
3949
223k
        patch_color_t *c[2];
3950
223k
        shading_vertex_t q0, q1, q2;
3951
223k
        int code = 0;
3952
223k
        byte *color_stack_ptr;
3953
223k
        bool save_inside = pfs->inside;
3954
3955
223k
        if (!pfs->inside) {
3956
221k
            gs_fixed_rect r, r1;
3957
3958
221k
            tensor_patch_bbox(&r, p);
3959
221k
            r.p.x -= INTERPATCH_PADDING;
3960
221k
            r.p.y -= INTERPATCH_PADDING;
3961
221k
            r.q.x += INTERPATCH_PADDING;
3962
221k
            r.q.y += INTERPATCH_PADDING;
3963
221k
            r1 = r;
3964
221k
            rect_intersect(r, pfs->rect);
3965
221k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3966
11.7k
                return 0;
3967
209k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3968
209k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3969
1.14k
                pfs->inside = true;
3970
209k
        }
3971
212k
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3972
212k
        if(color_stack_ptr == NULL)
3973
0
            return_error(gs_error_unregistered); /* Must not happen. */
3974
212k
        split_patch(pfs, &s0, &s1, p, c);
3975
212k
        if (kv0 <= 1) {
3976
200k
            q0.p = s0.pole[0][0];
3977
200k
            q0.c = s0.c[0][0];
3978
200k
            q1.p = s1.pole[3][0];
3979
200k
            q1.c = s1.c[1][0];
3980
200k
            q2.p = s0.pole[3][0];
3981
200k
            q2.c = s0.c[1][0];
3982
200k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3983
200k
        }
3984
212k
        if (kv1 <= 1 && code >= 0) {
3985
200k
            q0.p = s0.pole[0][3];
3986
200k
            q0.c = s0.c[0][1];
3987
200k
            q1.p = s1.pole[3][3];
3988
200k
            q1.c = s1.c[1][1];
3989
200k
            q2.p = s0.pole[3][3];
3990
200k
            q2.c = s0.c[1][1];
3991
200k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3992
200k
        }
3993
212k
        if (code >= 0)
3994
212k
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
3995
212k
        if (code >= 0)
3996
212k
            code = fill_patch(pfs, &s1, kv / 2, kv0 / 2, kv1 / 2);
3997
        /* fixme : To provide the precise filling order, we must
3998
           decompose left and right wedges into pieces by intersections
3999
           with stripes, and fill each piece with its stripe.
4000
           A lazy wedge list would be fine for storing
4001
           the necessary information.
4002
4003
           If the patch is created from a radial shading,
4004
           the wedge color appears a constant, so the filling order
4005
           isn't important. The order is important for other
4006
           self-overlapping patches, but the visible effect is
4007
           just a slight narrowing of the patch (as its lower layer appears
4008
           visible through the upper layer near the side).
4009
           This kind of dropout isn't harmful, because
4010
           contacting self-overlapping patches are painted
4011
           one after one by definition, so that a side coverage break
4012
           appears unavoidable by definition.
4013
4014
           Delaying this improvement because it is low importance.
4015
         */
4016
212k
        release_colors_inline(pfs, color_stack_ptr, 2);
4017
212k
        pfs->inside = save_inside;
4018
212k
        return code;
4019
212k
    }
4020
212k
}
4021
4022
static inline int64_t
4023
lcp1(int64_t p0, int64_t p3)
4024
92.5k
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4025
92.5k
    return (p0 + p0 + p3);
4026
92.5k
}
4027
static inline int64_t
4028
lcp2(int64_t p0, int64_t p3)
4029
92.5k
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4030
92.5k
    return (p0 + p3 + p3);
4031
92.5k
}
4032
4033
static void
4034
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4035
76.7k
{
4036
76.7k
    if (pfs->Function) {
4037
18.5k
        c->t[0] = cc[0];
4038
18.5k
        c->t[1] = cc[1];
4039
18.5k
    } else
4040
58.2k
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4041
76.7k
}
4042
4043
static void
4044
make_tensor_patch(const patch_fill_state_t *pfs, tensor_patch *p, const patch_curve_t curve[4],
4045
           const gs_fixed_point interior[4])
4046
19.1k
{
4047
19.1k
    const gs_color_space *pcs = pfs->direct_space;
4048
4049
19.1k
    p->pole[0][0] = curve[0].vertex.p;
4050
19.1k
    p->pole[1][0] = curve[0].control[0];
4051
19.1k
    p->pole[2][0] = curve[0].control[1];
4052
19.1k
    p->pole[3][0] = curve[1].vertex.p;
4053
19.1k
    p->pole[3][1] = curve[1].control[0];
4054
19.1k
    p->pole[3][2] = curve[1].control[1];
4055
19.1k
    p->pole[3][3] = curve[2].vertex.p;
4056
19.1k
    p->pole[2][3] = curve[2].control[0];
4057
19.1k
    p->pole[1][3] = curve[2].control[1];
4058
19.1k
    p->pole[0][3] = curve[3].vertex.p;
4059
19.1k
    p->pole[0][2] = curve[3].control[0];
4060
19.1k
    p->pole[0][1] = curve[3].control[1];
4061
19.1k
    if (interior != NULL) {
4062
14.5k
        p->pole[1][1] = interior[0];
4063
14.5k
        p->pole[1][2] = interior[1];
4064
14.5k
        p->pole[2][2] = interior[2];
4065
14.5k
        p->pole[2][1] = interior[3];
4066
14.5k
    } else {
4067
4.62k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4068
4.62k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4069
4.62k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4070
4.62k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4071
4.62k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4072
4.62k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4073
4.62k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4074
4.62k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4075
4.62k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4076
4.62k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4077
4.62k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4078
4.62k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4079
4.62k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4080
4.62k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4081
4.62k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4082
4.62k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4083
4084
4.62k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4085
4.62k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4086
4.62k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4087
4.62k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4088
4.62k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4089
4.62k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4090
4.62k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4091
4.62k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4092
4.62k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4093
4.62k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4094
4.62k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4095
4.62k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4096
4.62k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4097
4.62k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4098
4.62k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4099
4.62k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4100
4.62k
    }
4101
19.1k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4102
19.1k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4103
19.1k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4104
19.1k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4105
19.1k
    patch_resolve_color_inline(p->c[0][0], pfs);
4106
19.1k
    patch_resolve_color_inline(p->c[0][1], pfs);
4107
19.1k
    patch_resolve_color_inline(p->c[1][0], pfs);
4108
19.1k
    patch_resolve_color_inline(p->c[1][1], pfs);
4109
19.1k
    if (!pfs->Function) {
4110
14.5k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4111
14.5k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4112
14.5k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4113
14.5k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4114
14.5k
    }
4115
19.1k
}
4116
4117
int
4118
gx_shade_background(gx_device *pdev, const gs_fixed_rect *rect,
4119
        const gx_device_color *pdevc, gs_logical_operation_t log_op)
4120
2
{
4121
2
    gs_fixed_edge le, re;
4122
4123
2
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4124
2
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4125
2
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4126
2
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4127
2
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4128
2
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4129
2
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4130
2
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4131
2
    return dev_proc(pdev, fill_trapezoid)(pdev,
4132
2
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4133
2
}
4134
4135
int
4136
patch_fill(patch_fill_state_t *pfs, const patch_curve_t curve[4],
4137
           const gs_fixed_point interior[4],
4138
           void (*transform) (gs_fixed_point *, const patch_curve_t[4],
4139
                              const gs_fixed_point[4], double, double))
4140
19.1k
{
4141
19.1k
    tensor_patch p;
4142
19.1k
    patch_color_t *c[4];
4143
19.1k
    int kv[4], kvm, ku[4], kum;
4144
19.1k
    int code = 0;
4145
19.1k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4146
4147
19.1k
    p.c[0][0] = c[0];
4148
19.1k
    p.c[0][1] = c[1];
4149
19.1k
    p.c[1][0] = c[2];
4150
19.1k
    p.c[1][1] = c[3];
4151
#if SKIP_TEST
4152
    dbg_patch_cnt++;
4153
    /*if (dbg_patch_cnt != 67 && dbg_patch_cnt != 78)
4154
        return 0;*/
4155
#endif
4156
    /* We decompose the patch into tiny quadrangles,
4157
       possibly inserting wedges between them against a dropout. */
4158
19.1k
    make_tensor_patch(pfs, &p, curve, interior);
4159
19.1k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4160
19.1k
    pfs->linear_color = false;
4161
19.1k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4162
19.1k
            gxdso_pattern_shading_area, NULL, 0) > 0) {
4163
        /* Inform the device with the shading coverage area.
4164
           First compute the sign of the area, because
4165
           all areas to be clipped in same direction. */
4166
0
        gx_device *pdev = pfs->dev;
4167
0
        gx_path path;
4168
0
        fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
4169
0
        fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
4170
0
        fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
4171
0
        fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
4172
0
        fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
4173
0
        fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
4174
0
        fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
4175
0
        fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
4176
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
4177
0
        int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
4178
0
        int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
4179
4180
0
        gx_path_init_local(&path, pdev->memory);
4181
0
        if (is_x_bended(&p) || is_y_bended(&p)) {
4182
            /* The patch possibly is self-overlapping,
4183
               so the patch coverage may fall outside the patch outline.
4184
               In this case we pass an empty path,
4185
               and the device must use a bitmap mask instead clipping. */
4186
0
        } else {
4187
0
            code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
4188
0
            for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
4189
0
                j = (i + s) % 4, jj = (s == 1 ? i : j);
4190
0
                if (curve[jj].straight)
4191
0
                    code = gx_path_add_line(&path, curve[j].vertex.p.x,
4192
0
                                                curve[j].vertex.p.y);
4193
0
                else
4194
0
                    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
4195
0
                                                    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
4196
0
                                                    curve[j].vertex.p.x,
4197
0
                                                    curve[j].vertex.p.y);
4198
0
            }
4199
0
            if (code >= 0)
4200
0
                code = gx_path_close_subpath(&path);
4201
0
        }
4202
0
        if (code >= 0)
4203
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
4204
0
        gx_path_free(&path, "patch_fill");
4205
0
        if (code < 0)
4206
0
            goto out;
4207
0
    }
4208
    /* How many subdivisions of the patch in the u and v direction? */
4209
19.1k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4210
19.1k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4211
19.1k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4212
19.1k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4213
19.1k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4214
19.1k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4215
19.1k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4216
19.1k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4217
19.1k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4218
19.1k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4219
#   if NOFILL_TEST
4220
    dbg_nofill = false;
4221
#   endif
4222
19.1k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4223
19.1k
        interpatch_padding | inpatch_wedge);
4224
19.1k
    if (code >= 0) {
4225
        /* We would like to apply iterations for enumerating the kvm curve parts,
4226
           but the roundinmg errors would be too complicated due to
4227
           the dependence on the direction. Note that neigbour
4228
           patches may use the opposite direction for same bounding curve.
4229
           We apply the recursive dichotomy, in which
4230
           the rounding errors do not depend on the direction. */
4231
#       if NOFILL_TEST
4232
            dbg_nofill = false;
4233
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4234
            dbg_nofill = true;
4235
#       endif
4236
19.1k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4237
19.1k
    }
4238
19.1k
    if (code >= 0)
4239
19.1k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4240
19.1k
                interpatch_padding | inpatch_wedge);
4241
19.1k
out:
4242
19.1k
    release_colors_inline(pfs, color_stack_ptr, 4);
4243
19.1k
    return code;
4244
19.1k
}