Coverage Report

Created: 2025-06-10 07:17

/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
5.73k
{
87
5.73k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
5.73k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
5.73k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
5.73k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
5.73k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
5.73k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
5.73k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
5.73k
    pfs->color_stack_ptr = pfs->color_stack;
98
5.73k
    pfs->memory = memory;
99
5.73k
    return 0;
100
5.73k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
9.94M
{
105
9.94M
    int i;
106
9.94M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
33.6M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
23.7M
        c[i] = (patch_color_t *)ptr;
110
9.94M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
9.94M
    pfs->color_stack_ptr = ptr;
115
9.94M
    return ptr0;
116
9.94M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
38
{
121
38
    return reserve_colors_inline(pfs, c, n);
122
38
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
9.94M
{
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
9.94M
    pfs->color_stack_ptr = ptr;
132
9.94M
#endif
133
9.94M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
38
{
137
38
    release_colors_inline(pfs, ptr, n);
138
38
}
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
32.5k
{
145
32.5k
    int i, code = 0;
146
147
149k
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
116k
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
116k
        code = shade_next_color(cs, curves[i].vertex.cc);
150
116k
    }
151
32.5k
    return code;
152
32.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
91.0k
{
158
91.0k
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
91.0k
    if (code >= 0)
161
91.0k
        code = shade_next_coords(cs, curve->control,
162
91.0k
                                 countof(curve->control));
163
91.0k
    return code;
164
91.0k
}
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
32.7k
{
174
32.7k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
32.7k
    int num_colors, code;
176
177
32.7k
    if (flag < 0) {
178
130
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
130
        return 1;               /* no more data */
181
130
    }
182
32.6k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
32.6k
    cs->first_patch = 0;
186
32.6k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
25.8k
        case 0:
190
25.8k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
25.8k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
25.8k
                )
193
5
                return code;
194
25.8k
            num_colors = 4;
195
25.8k
            goto vx;
196
2.03k
        case 1:
197
2.03k
            curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
198
2.03k
            goto v3;
199
2.01k
        case 2:
200
2.01k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
2.01k
            goto v3;
202
2.71k
        case 3:
203
2.71k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
6.75k
v3:         num_colors = 2;
205
32.6k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
32.6k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
32.6k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
32.6k
                (interior != 0 &&
209
32.5k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
32.6k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
32.5k
                                          num_colors)) < 0
212
32.6k
                )
213
50
                return code;
214
32.5k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
32.6k
    }
216
32.5k
    return 0;
217
32.6k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
369k
{
222
369k
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
369k
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
0
        return false;
226
369k
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
0
        return false;
228
369k
    return true;
229
369k
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
5.73k
{
234
5.73k
    int code;
235
236
5.73k
    pfs->memory = memory;
237
5.73k
#   if LAZY_WEDGES
238
5.73k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
5.73k
        if (code < 0)
240
0
            return code;
241
5.73k
#   endif
242
5.73k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
5.73k
    code = allocate_color_stack(pfs, memory);
244
5.73k
    if (code < 0)
245
0
        return code;
246
5.73k
    if (pfs->unlinear || pcs == NULL)
247
0
        pfs->pcic = NULL;
248
5.73k
    else {
249
5.73k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
5.73k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
5.73k
    }
253
5.73k
    return 0;
254
5.73k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
5.73k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
5.73k
    const gs_color_space *pcs = pfs->direct_space;
261
5.73k
    gs_client_color fcc0, fcc1;
262
5.73k
    int i;
263
264
21.4k
    for (i = 0; i < pfs->num_components; i++) {
265
15.7k
        fcc0.paint.values[i] = -1000000;
266
15.7k
        fcc1.paint.values[i] = 1000000;
267
15.7k
    }
268
5.73k
    pcs->type->restrict_color(&fcc0, pcs);
269
5.73k
    pcs->type->restrict_color(&fcc1, pcs);
270
21.4k
    for (i = 0; i < pfs->num_components; i++)
271
15.7k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
5.73k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
5.73k
    pfs->maybe_self_intersecting = true;
274
5.73k
    pfs->monotonic_color = (pfs->Function == NULL);
275
5.73k
    pfs->function_arg_shift = 0;
276
5.73k
    pfs->linear_color = false;
277
5.73k
    pfs->inside = false;
278
5.73k
    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
5.73k
    pfs->decomposition_limit = fixed_1;
285
5.73k
#endif
286
5.73k
    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
5.73k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
5.73k
    pfs->color_stack_size = 0;
293
5.73k
    pfs->color_stack_step = 0;
294
5.73k
    pfs->color_stack_ptr = NULL;
295
5.73k
    pfs->color_stack = NULL;
296
5.73k
    pfs->color_stack_limit = NULL;
297
5.73k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
5.73k
    pfs->pcic = NULL;
299
5.73k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
5.73k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
5.73k
{
305
5.73k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
5.73k
#   if LAZY_WEDGES
307
5.73k
        wedge_vertex_list_elem_buffer_free(pfs);
308
5.73k
#   endif
309
5.73k
    if (pfs->color_stack)
310
5.73k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
5.73k
    if (pfs->pcic != NULL)
312
5.73k
        gs_color_index_cache_destroy(pfs->pcic);
313
5.73k
    return b;
314
5.73k
}
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.33M
{
320
4.33M
    if (pfs->Function) {
321
4.20M
        const gs_color_space *pcs = pfs->direct_space;
322
323
4.20M
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
4.20M
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
4.20M
    }
326
4.33M
}
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
9.61M
{
344
    /* The old code gives -IND on Intel. */
345
9.61M
    if (pfs->Function) {
346
1.09M
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
1.09M
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
1.09M
        patch_resolve_color_inline(ppcr, pfs);
349
8.51M
    } else {
350
8.51M
        int ci;
351
352
41.8M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
33.3M
            ppcr->cc.paint.values[ci] =
354
33.3M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
8.51M
    }
356
9.61M
}
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
3
{
446
3
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
3
    patch_fill_state_t state;
448
3
    shade_coord_stream_t cs;
449
3
    patch_curve_t curve[4];
450
3
    int code;
451
452
3
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
3
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
3
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
3
    state.Function = psh->params.Function;
459
3
    code = init_patch_fill_state(&state);
460
3
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
3
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
3
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
7
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
7
                                    curve, NULL)) == 0 &&
469
7
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
4
        ) {
471
4
        DO_NOTHING;
472
4
    }
473
3
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
3
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
3
    return min(code, 0);
477
3
}
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
182
{
535
182
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
182
    patch_fill_state_t state;
537
182
    shade_coord_stream_t cs;
538
182
    patch_curve_t curve[4];
539
182
    gs_fixed_point interior[4];
540
182
    int code;
541
542
182
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
182
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
182
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
182
    state.Function = psh->params.Function;
549
182
    code = init_patch_fill_state(&state);
550
182
    if(code < 0)
551
0
        return code;
552
182
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
182
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
32.7k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
32.7k
                                    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
32.5k
        gs_fixed_point swapped_interior[4];
561
562
32.5k
        swapped_interior[0] = interior[0];
563
32.5k
        swapped_interior[1] = interior[3];
564
32.5k
        swapped_interior[2] = interior[2];
565
32.5k
        swapped_interior[3] = interior[1];
566
32.5k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
32.5k
        if (code < 0)
568
0
            break;
569
32.5k
    }
570
182
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
182
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
182
    return min(code, 0);
574
182
}
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
5.73k
{
665
5.73k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
5.73k
    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
5.73k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
5.73k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
5.73k
            sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
681
5.73k
            "alloc_wedge_vertex_list_elem_buffer");
682
5.73k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
5.73k
    pfs->free_wedge_vertex = NULL;
685
5.73k
    pfs->wedge_vertex_list_elem_count = 0;
686
5.73k
    return 0;
687
5.73k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
5.73k
{
692
5.73k
    gs_memory_t *memory = pfs->memory;
693
694
5.73k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
5.73k
                "wedge_vertex_list_elem_buffer_free");
696
5.73k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
5.73k
    pfs->free_wedge_vertex = NULL;
698
5.73k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
197k
{
703
197k
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
197k
    if (e != NULL) {
706
156k
        pfs->free_wedge_vertex = e->next;
707
156k
        return e;
708
156k
    }
709
41.5k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
41.5k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
41.5k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
197k
{
717
197k
    e->next = pfs->free_wedge_vertex;
718
197k
    pfs->free_wedge_vertex = e;
719
197k
}
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
82.4k
{
725
82.4k
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
82.4k
    beg->next = end;
728
82.4k
    end->prev = beg;
729
181k
    for (; e != end; e = ee) {
730
98.5k
        ee = e->next;
731
98.5k
        wedge_vertex_list_elem_release(pfs, e);
732
98.5k
    }
733
82.4k
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
49.4k
{
738
49.4k
    int i;
739
740
98.9k
    for (i = 0; i < n; i++) {
741
49.4k
        wedge_vertex_list_t *l = ll + i;
742
743
49.4k
        if (l->beg != NULL) {
744
49.4k
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
49.4k
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
49.4k
            wedge_vertex_list_elem_release(pfs, l->beg);
748
49.4k
            wedge_vertex_list_elem_release(pfs, l->end);
749
49.4k
            l->beg = l->end = NULL;
750
49.4k
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
49.4k
    }
753
49.4k
    return 0;
754
49.4k
}
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
50.4k
{
760
50.4k
    wedge_vertex_list_elem_t *e = beg;
761
762
50.4k
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
159k
    for (; e != end; e = e->next)
765
159k
        if (e->level == level)
766
50.4k
            return e;
767
0
    return NULL;
768
50.4k
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
4.49M
{
773
4.49M
    memset(l, 0, sizeof(*l) * n);
774
4.49M
}
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
1.53M
{
785
1.53M
    curve_segment s;
786
1.53M
    int k;
787
788
1.53M
    s.p1.x = pole[pole_step].x;
789
1.53M
    s.p1.y = pole[pole_step].y;
790
1.53M
    s.p2.x = pole[pole_step * 2].x;
791
1.53M
    s.p2.y = pole[pole_step * 2].y;
792
1.53M
    s.pt.x = pole[pole_step * 3].x;
793
1.53M
    s.pt.y = pole[pole_step * 3].y;
794
1.53M
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
1.53M
    {
796
1.53M
#       if LAZY_WEDGES || QUADRANGLES
797
1.53M
            int k1;
798
1.53M
            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
1.53M
                      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
1.53M
                      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
1.53M
#       endif
802
803
1.53M
#       if LAZY_WEDGES
804
            /* Restrict lengths for a reasonable memory consumption : */
805
1.53M
            k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
806
1.53M
            k = max(k, k1);
807
1.53M
#       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
1.53M
    }
813
1.53M
    return 1 << k;
814
1.53M
}
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
5.74M
{
826
5.74M
    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
2.46M
        *b += fixed_epsilon;
836
2.46M
    }
837
5.74M
}
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.28M
{
844
1.28M
    if (!orient) {
845
898k
        le->start = q[vi0];
846
898k
        le->end = q[vi1];
847
898k
        re->start = q[vi2];
848
898k
        re->end = q[vi3];
849
898k
    } else {
850
391k
        le->start = q[vi2];
851
391k
        le->end = q[vi3];
852
391k
        re->start = q[vi0];
853
391k
        re->end = q[vi1];
854
391k
    }
855
1.28M
    adjust_swapped_boundary(&re->start.x, swap_axes);
856
1.28M
    adjust_swapped_boundary(&re->end.x, swap_axes);
857
1.28M
}
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
67.7k
{
864
67.7k
    gs_fixed_edge le, re;
865
67.7k
    int code;
866
67.7k
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
867
67.7k
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
868
67.7k
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
869
67.7k
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
870
871
67.7k
    if (ybot >= ytop)
872
21.8k
        return 0;
873
#   if NOFILL_TEST
874
        if (dbg_nofill)
875
            return 0;
876
#   endif
877
45.8k
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
878
45.8k
    if (!pfs->inside) {
879
16.3k
        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
16.3k
        if (le.start.x > xright) {
890
2.17k
            if (le.end.x > xright) {
891
0
                return 0;
892
0
            }
893
2.17k
            clip = true;
894
14.2k
        } else if (le.end.x > xright) {
895
1.24k
            clip = true;
896
1.24k
        }
897
16.3k
        if (le.start.x < xleft) {
898
3.58k
            if (le.end.x < xleft) {
899
2.29k
                le.start.x = xleft;
900
2.29k
                le.end.x   = xleft;
901
2.29k
                le.start.y = ybot;
902
2.29k
                le.end.y   = ytop;
903
2.29k
            } else {
904
1.29k
                clip = true;
905
1.29k
            }
906
12.8k
        } else if (le.end.x < xleft) {
907
1.98k
            clip = true;
908
1.98k
        }
909
16.3k
        if (re.start.x < xleft) {
910
1.64k
            if (re.end.x < xleft) {
911
0
                return 0;
912
0
            }
913
1.64k
            clip = true;
914
14.7k
        } else if (re.end.x < xleft) {
915
2.07k
            clip = true;
916
2.07k
        }
917
16.3k
        if (re.start.x > xright) {
918
4.04k
            if (re.end.x > xright) {
919
1.96k
                re.start.x = xright;
920
1.96k
                re.end.x   = xright;
921
1.96k
                re.start.y = ybot;
922
1.96k
                re.end.y   = ytop;
923
2.08k
            } else {
924
2.08k
                clip = true;
925
2.08k
            }
926
12.3k
        } else if (re.end.x > xright) {
927
1.16k
            clip = true;
928
1.16k
        }
929
16.3k
        if (clip)
930
7.90k
        {
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
7.90k
            gs_fixed_edge lenew, renew;
935
7.90k
            fixed ybl, ybr, ytl, ytr, ymid;
936
937
            /* Reduce the clipping region horizontally if possible. */
938
7.90k
            if (re.start.x > re.end.x) {
939
3.18k
                if (re.start.x < xright)
940
1.09k
                    xright = re.start.x;
941
4.72k
            } else if (re.end.x < xright)
942
1.68k
                xright = re.end.x;
943
7.90k
            if (le.start.x > le.end.x) {
944
3.24k
                if (le.end.x > xleft)
945
1.25k
                    xleft = le.end.x;
946
4.66k
            } else if (le.start.x > xleft)
947
1.31k
                xleft = le.start.x;
948
949
7.90k
            ybot = max(ybot, min(le.start.y, re.start.y));
950
7.90k
            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
7.90k
            if (ybot >= ytop)
987
0
                return 0;
988
            /* Follow the edges in, so that le.start.y == ybot etc. */
989
7.90k
            if (le.start.y < ybot) {
990
3.22k
                int round = ((le.end.x < le.start.x) ?
991
1.86k
                             (le.end.y-le.start.y-1) : 0);
992
3.22k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
993
3.22k
                                       (int64_t)(le.end.x-le.start.x)-round)/
994
3.22k
                                      (int64_t)(le.end.y-le.start.y));
995
3.22k
                le.start.y = ybot;
996
3.22k
            }
997
7.90k
            if (le.end.y > ytop) {
998
3.43k
                int round = ((le.end.x > le.start.x) ?
999
1.72k
                             (le.end.y-le.start.y-1) : 0);
1000
3.43k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1001
3.43k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1002
3.43k
                                    (int64_t)(le.end.y-le.start.y));
1003
3.43k
                le.end.y = ytop;
1004
3.43k
            }
1005
7.90k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1006
508
                le.start.x = xleft;
1007
508
                le.end.x   = xleft;
1008
508
                le.start.y = ybot;
1009
508
                le.end.y   = ytop;
1010
508
            }
1011
7.90k
            if (re.start.y < ybot) {
1012
3.36k
                int round = ((re.end.x > re.start.x) ?
1013
1.78k
                             (re.end.y-re.start.y-1) : 0);
1014
3.36k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1015
3.36k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1016
3.36k
                                      (int64_t)(re.end.y-re.start.y));
1017
3.36k
                re.start.y = ybot;
1018
3.36k
            }
1019
7.90k
            if (re.end.y > ytop) {
1020
3.59k
                int round = ((re.end.x < re.start.x) ?
1021
1.83k
                             (re.end.y-re.start.y-1) : 0);
1022
3.59k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1023
3.59k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1024
3.59k
                                    (int64_t)(re.end.y-re.start.y));
1025
3.59k
                re.end.y = ytop;
1026
3.59k
            }
1027
7.90k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1028
230
                re.start.x = xright;
1029
230
                re.end.x   = xright;
1030
230
                re.start.y = ybot;
1031
230
                re.end.y   = ytop;
1032
230
            }
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
7.90k
            if (le.start.x > re.start.x) {
1039
2.73k
                if (le.start.x == le.end.x) {
1040
1.36k
                    if (re.start.x == re.end.x)
1041
0
                        return 0;
1042
1.36k
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1043
1.36k
                                    (int64_t)(le.start.x-re.start.x)/
1044
1.36k
                                    (int64_t)(re.end.x-re.start.x));
1045
1.36k
                    re.start.x = le.start.x;
1046
1.36k
                } else {
1047
1.36k
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1048
1.36k
                                    (int64_t)(le.start.x-re.start.x)/
1049
1.36k
                                    (int64_t)(le.start.x-le.end.x));
1050
1.36k
                    le.start.x = re.start.x;
1051
1.36k
                }
1052
2.73k
                if (ybot >= ytop)
1053
870
                    return 0;
1054
1.86k
                le.start.y = ybot;
1055
1.86k
                re.start.y = ybot;
1056
1.86k
            }
1057
7.03k
            if (le.end.x > re.end.x) {
1058
1.79k
                if (le.start.x == le.end.x) {
1059
1.12k
                    if (re.start.x == re.end.x)
1060
0
                        return 0;
1061
1.12k
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1062
1.12k
                                    (int64_t)(le.end.x-re.end.x)/
1063
1.12k
                                    (int64_t)(re.start.x-re.end.x));
1064
1.12k
                    re.end.x = le.end.x;
1065
1.12k
                } else {
1066
669
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1067
669
                                    (int64_t)(le.end.x-re.end.x)/
1068
669
                                    (int64_t)(le.end.x-le.start.x));
1069
669
                    le.end.x = re.end.x;
1070
669
                }
1071
1.79k
                if (ybot >= ytop)
1072
679
                    return 0;
1073
1.11k
                le.end.y = ytop;
1074
1.11k
                re.end.y = ytop;
1075
1.11k
            }
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
6.35k
            lenew.start.x = xleft;
1082
6.35k
            lenew.start.y = ybot;
1083
6.35k
            lenew.end.x   = xleft;
1084
6.35k
            lenew.end.y   = ytop;
1085
6.35k
            renew.start.x = xright;
1086
6.35k
            renew.start.y = ybot;
1087
6.35k
            renew.end.x   = xright;
1088
6.35k
            renew.end.y   = ytop;
1089
            /* Figure out where the left edge intersects with the left at
1090
             * the bottom */
1091
6.35k
            ybl = ybot;
1092
6.35k
            if (le.start.x > le.end.x) {
1093
2.41k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1094
2.41k
                               (int64_t)(le.end.y-le.start.y) /
1095
2.41k
                               (int64_t)(le.start.x-le.end.x));
1096
2.41k
                if (ybl > ytop)
1097
1.12k
                    ybl = ytop;
1098
2.41k
            }
1099
            /* Figure out where the right edge intersects with the right at
1100
             * the bottom */
1101
6.35k
            ybr = ybot;
1102
6.35k
            if (re.start.x < re.end.x) {
1103
2.37k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1104
2.37k
                               (int64_t)(re.end.y-re.start.y) /
1105
2.37k
                               (int64_t)(re.end.x-re.start.x));
1106
2.37k
                if (ybr > ytop)
1107
1.30k
                    ybr = ytop;
1108
2.37k
            }
1109
            /* Figure out where the left edge intersects with the left at
1110
             * the top */
1111
6.35k
            ytl = ytop;
1112
6.35k
            if (le.end.x > le.start.x) {
1113
2.22k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1114
2.22k
                               (int64_t)(le.end.y-le.start.y) /
1115
2.22k
                               (int64_t)(le.end.x-le.start.x));
1116
2.22k
                if (ytl < ybot)
1117
1.08k
                    ytl = ybot;
1118
2.22k
            }
1119
            /* Figure out where the right edge intersects with the right at
1120
             * the bottom */
1121
6.35k
            ytr = ytop;
1122
6.35k
            if (re.end.x < re.start.x) {
1123
2.59k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1124
2.59k
                               (int64_t)(re.end.y-re.start.y) /
1125
2.59k
                               (int64_t)(re.start.x-re.end.x));
1126
2.59k
                if (ytr < ybot)
1127
1.00k
                    ytr = ybot;
1128
2.59k
            }
1129
            /* Check for the 2 cases where top and bottom diagonal extents
1130
             * overlap, and deal with them explicitly. */
1131
6.35k
            if (ytl < ybr) {
1132
                /*     |     |
1133
                 *  ---+-----+---
1134
                 *     | /222|
1135
                 *     |/111/|
1136
                 *     |000/ |
1137
                 *  ---+-----+---
1138
                 *     |     |
1139
                 */
1140
949
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1141
949
                                        &lenew, &re, ybot, ytl,
1142
949
                                        swap_axes, pdevc, pfs->pgs->log_op);
1143
949
                if (code < 0)
1144
0
                    return code;
1145
949
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1146
949
                                        &le, &re, ytl, ybr,
1147
949
                                        swap_axes, pdevc, pfs->pgs->log_op);
1148
949
                if (code < 0)
1149
0
                    return code;
1150
949
                ybot = ybr;
1151
949
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1152
949
                                        &le, &renew, ybr, ytop,
1153
949
                                        swap_axes, pdevc, pfs->pgs->log_op);
1154
5.40k
            } else if (ytr < ybl) {
1155
                /*     |     |
1156
                 *  ---+-----+----
1157
                 *     |555\ |
1158
                 *     |\444\|
1159
                 *     | \333|
1160
                 *  ---+-----+---
1161
                 *     |     |
1162
                 */
1163
1.01k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
1.01k
                                        &le, &renew, ybot, ytr,
1165
1.01k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
1.01k
                if (code < 0)
1167
0
                    return code;
1168
1.01k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1169
1.01k
                                        &le, &re, ytr, ybl,
1170
1.01k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1171
1.01k
                if (code < 0)
1172
0
                    return code;
1173
1.01k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1174
1.01k
                                        &le, &re, ybl, ytop,
1175
1.01k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1176
1.01k
            }
1177
            /* Fill in any section where both left and right edges are
1178
             * diagonal at the bottom */
1179
4.38k
            ymid = ybl;
1180
4.38k
            if (ymid > ybr)
1181
1.03k
                ymid = ybr;
1182
4.38k
            if (ymid > ybot) {
1183
                /*     |\   |          |   /|
1184
                 *     | \6/|    or    |\6/ |
1185
                 *  ---+----+---    ---+----+---
1186
                 *     |    |          |    |
1187
                 */
1188
255
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1189
255
                                        &le, &re, ybot, ymid,
1190
255
                                        swap_axes, pdevc, pfs->pgs->log_op);
1191
255
                if (code < 0)
1192
0
                    return code;
1193
255
                ybot = ymid;
1194
255
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the top */
1197
4.38k
            ymid = ytl;
1198
4.38k
            if (ymid < ytr)
1199
843
                ymid = ytr;
1200
4.38k
            if (ymid < ytop) {
1201
                /*     |    |          |    |
1202
                 *  ---+----+---    ---+----+---
1203
                 *     |/7\ |    or    | /7\|
1204
                 *     |   \|          |/   |
1205
                 */
1206
302
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
302
                                        &le, &re, ymid, ytop,
1208
302
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
302
                if (code < 0)
1210
0
                    return code;
1211
302
                ytop = ymid;
1212
302
            }
1213
            /* Now do the single diagonal cases at the bottom */
1214
4.38k
            if (ybl > ybot) {
1215
                /*     |    |
1216
                 *     |\666|
1217
                 *  ---+----+---
1218
                 *     |    |
1219
                 */
1220
1.03k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1221
1.03k
                                        &le, &renew, ybot, ybl,
1222
1.03k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1223
1.03k
                if (code < 0)
1224
0
                    return code;
1225
1.03k
                ybot = ybl;
1226
3.34k
            } else if (ybr > ybot) {
1227
                /*     |    |
1228
                 *     |777/|
1229
                 *  ---+----+---
1230
                 *     |    |
1231
                 */
1232
977
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1233
977
                                        &lenew, &re, ybot, ybr,
1234
977
                                        swap_axes, pdevc, pfs->pgs->log_op);
1235
977
                if (code < 0)
1236
0
                    return code;
1237
977
                ybot = ybr;
1238
977
            }
1239
            /* Now do the single diagonal cases at the top */
1240
4.38k
            if (ytl < ytop) {
1241
                /*     |    |
1242
                 *  ---+----+---
1243
                 *     |/888|
1244
                 *     |    |
1245
                 */
1246
843
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1247
843
                                        &le, &renew, ytl, ytop,
1248
843
                                        swap_axes, pdevc, pfs->pgs->log_op);
1249
843
                if (code < 0)
1250
0
                    return code;
1251
843
                ytop = ytl;
1252
3.54k
            } else if (ytr < ytop) {
1253
                /*     |    |
1254
                 *  ---+----+---
1255
                 *     |999\|
1256
                 *     |    |
1257
                 */
1258
1.11k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1259
1.11k
                                        &lenew, &re, ytr, ytop,
1260
1.11k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1261
1.11k
                if (code < 0)
1262
0
                    return code;
1263
1.11k
                ytop = ytr;
1264
1.11k
            }
1265
            /* And finally just whatever rectangular section is left over in
1266
             * the middle */
1267
4.38k
            if (ybot > ytop)
1268
0
                return 0;
1269
4.38k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1270
4.38k
                                        &lenew, &renew, ybot, ytop,
1271
4.38k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1272
4.38k
        }
1273
16.3k
    }
1274
37.9k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1275
37.9k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1276
45.8k
}
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
62.5M
#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
15.6M
{
1311
    /* Must return 2 if the color is not pure.
1312
       See try_device_linear_color.
1313
     */
1314
15.6M
    int code;
1315
15.6M
    gx_device_color devc;
1316
1317
15.6M
#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
15.6M
     if (frac_values) {
1345
15.5M
        int i;
1346
15.5M
  int n = pfs->dev->color_info.num_components;
1347
17.0M
  for (i = pfs->num_components; i < n; i++) {
1348
1.50M
            frac_values[i] = 0;
1349
1.50M
  }
1350
15.5M
    }
1351
15.6M
#endif
1352
1353
15.6M
    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
1354
0
        pdevc = &devc;
1355
15.6M
    if (pfs->pcic) {
1356
15.6M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1357
15.6M
        if (code < 0)
1358
0
            return code;
1359
15.6M
    }
1360
15.6M
    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
0
        gs_client_color fcc;
1365
0
        const gs_color_space *pcs = pfs->direct_space;
1366
1367
0
        if (pcs != NULL) {
1368
1369
0
            if (pdevc == NULL)
1370
0
                pdevc = &devc;
1371
0
            memcpy(fcc.paint.values, c->cc.paint.values,
1372
0
                        sizeof(fcc.paint.values[0]) * pfs->num_components);
1373
0
            code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pgs,
1374
0
                                      pfs->trans_device, gs_color_select_texture);
1375
0
            if (code < 0)
1376
0
                return code;
1377
0
            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
0
        } 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
0
    }
1401
15.6M
    return 0;
1402
15.6M
}
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
20.7M
{
1413
20.7M
    int n = pfs->num_components, i;
1414
20.7M
    double m;
1415
1416
    /* Dont want to copy colors, which are big things. */
1417
20.7M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1418
81.1M
    for (i = 1; i < n; i++)
1419
60.3M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1420
20.7M
    return m;
1421
20.7M
}
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
5.79M
{
1426
5.79M
    int n = pfs->num_components, i;
1427
1428
28.2M
    for (i = 0; i < n; i++)
1429
22.4M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1430
5.79M
}
1431
1432
static inline double
1433
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1434
3.97M
{
1435
3.97M
    int n = pfs->num_components, i;
1436
3.97M
    double m;
1437
1438
3.97M
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1439
15.3M
    for (i = 1; i < n; i++)
1440
11.4M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1441
3.97M
    return m;
1442
3.97M
}
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
467k
{   /* 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
467k
    uint mask;
1462
467k
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1463
1464
467k
    if (code >= 0)
1465
467k
        return mask;
1466
0
    return code;
1467
467k
}
1468
1469
static inline bool
1470
covers_pixel_centers(fixed ybot, fixed ytop)
1471
1.90M
{
1472
1.90M
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1473
1.90M
}
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
110k
{
1479
110k
    gx_device_color dc;
1480
110k
    int code;
1481
1482
#   if NOFILL_TEST
1483
        /* if (dbg_nofill)
1484
                return 0; */
1485
#   endif
1486
1487
110k
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1488
110k
    if (code < 0)
1489
0
        return code;
1490
1491
110k
    dc.tag = device_current_tag(pfs->dev);
1492
1493
110k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1494
110k
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1495
110k
}
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
18.8M
{
1500
18.8M
    float s = 0;
1501
1502
18.8M
    if (pfs->Function != NULL) {
1503
1.56M
        patch_color_t c;
1504
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1505
        /* unless it is 'static const' */
1506
1.56M
        static const float q[2] = {(float)0.3, (float)0.7};
1507
1.56M
        int i, j;
1508
1509
4.52M
        for (j = 0; j < count_of(q); j++) {
1510
3.04M
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1511
3.04M
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1512
3.04M
            patch_resolve_color_inline(&c, pfs);
1513
11.5M
            for (i = 0; i < pfs->num_components; i++) {
1514
8.58M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1515
8.58M
                float d = v - c.cc.paint.values[i];
1516
8.58M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1517
1518
8.58M
                if (s1 > pfs->smoothness)
1519
83.1k
                    return s1;
1520
8.50M
                if (s < s1)
1521
838k
                    s = s1;
1522
8.50M
            }
1523
3.04M
        }
1524
1.56M
    }
1525
18.7M
    return s;
1526
18.8M
}
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
4.89M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1531
4.89M
    if (pfs->unlinear)
1532
0
        return 1; /* Disable this check. */
1533
4.89M
    else {
1534
4.89M
        const gs_color_space *cs = pfs->direct_space;
1535
4.89M
        int code;
1536
4.89M
        float s = function_linearity(pfs, c0, c1);
1537
1538
4.89M
        if (s > pfs->smoothness)
1539
58.5k
            return 0;
1540
4.83M
        if (pfs->cs_always_linear)
1541
1.22M
            return 1;
1542
3.60M
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1543
3.60M
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1544
3.60M
        if (code <= 0)
1545
3.89k
            return code;
1546
3.60M
        return 1;
1547
3.60M
    }
1548
4.89M
}
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.10M
{
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.10M
    int code;
1559
3.10M
    patch_color_t *c;
1560
3.10M
    byte *color_stack_ptr;
1561
3.10M
    bool save_inside = pfs->inside;
1562
1563
3.10M
    if (!pfs->inside) {
1564
2.90M
        gs_fixed_rect r, r1;
1565
1566
2.90M
        if(swap_axes) {
1567
1.24M
            r.p.y = min(le->start.x, le->end.x);
1568
1.24M
            r.p.x = min(le->start.y, le->end.y);
1569
1.24M
            r.q.y = max(re->start.x, re->end.x);
1570
1.24M
            r.q.x = max(re->start.y, re->end.y);
1571
1.66M
        } else {
1572
1.66M
            r.p.x = min(le->start.x, le->end.x);
1573
1.66M
            r.p.y = min(le->start.y, le->end.y);
1574
1.66M
            r.q.x = max(re->start.x, re->end.x);
1575
1.66M
            r.q.y = max(re->start.y, re->end.y);
1576
1.66M
        }
1577
2.90M
        r1 = r;
1578
2.90M
        rect_intersect(r, pfs->rect);
1579
2.90M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1580
2.05M
            return 0;
1581
850k
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1582
850k
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1583
531k
            pfs->inside = true;
1584
850k
    }
1585
1.04M
    color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
1586
1.04M
    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
1.04M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
1592
1.04M
    if (ytop - ybot < pfs->decomposition_limit) /* Prevent an infinite color decomposition. */
1593
110k
        code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1594
938k
    else {
1595
938k
        bool monotonic_color_save = pfs->monotonic_color;
1596
938k
        bool linear_color_save = pfs->linear_color;
1597
1598
938k
        if (!pfs->monotonic_color) {
1599
342k
            code = isnt_color_monotonic(pfs, c0, c1);
1600
342k
            if (code < 0)
1601
0
                goto out;
1602
342k
            if (!code)
1603
244k
                pfs->monotonic_color = true;
1604
342k
        }
1605
938k
        if (pfs->monotonic_color && !pfs->linear_color) {
1606
837k
            code = is_color_linear(pfs, c0, c1);
1607
837k
            if (code < 0)
1608
0
                goto out;
1609
837k
            if (code > 0)
1610
797k
                pfs->linear_color =  true;
1611
837k
        }
1612
938k
        if (!pfs->unlinear && pfs->linear_color) {
1613
800k
            gx_device *pdev = pfs->dev;
1614
800k
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1615
800k
            gs_fill_attributes fa;
1616
800k
            gs_fixed_rect clip;
1617
1618
800k
            memset(fc, 0x99, sizeof(fc));
1619
1620
800k
            clip = pfs->rect;
1621
800k
            if (swap_axes) {
1622
349k
                fixed v;
1623
1624
349k
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1625
349k
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1626
                /* Don't need adjust_swapped_boundary here. */
1627
349k
            }
1628
800k
            clip.p.y = max(clip.p.y, ybot);
1629
800k
            clip.q.y = min(clip.q.y, ytop);
1630
800k
            fa.clip = &clip;
1631
800k
            fa.ht = NULL;
1632
800k
            fa.swap_axes = swap_axes;
1633
800k
            fa.lop = 0;
1634
800k
            fa.ystart = ybot;
1635
800k
            fa.yend = ytop;
1636
800k
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1637
800k
            if (code < 0)
1638
0
                goto out;
1639
800k
            if (code == 2) {
1640
                /* Must not happen. */
1641
0
                code=gs_note_error(gs_error_unregistered);
1642
0
                goto out;
1643
0
            }
1644
800k
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1645
800k
            if (code < 0)
1646
0
                goto out;
1647
800k
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1648
800k
                            &le->start, &le->end, &re->start, &re->end,
1649
800k
                            fc[0], fc[1], NULL, NULL);
1650
800k
            if (code == 1) {
1651
800k
                pfs->monotonic_color = monotonic_color_save;
1652
800k
                pfs->linear_color = linear_color_save;
1653
800k
                code = 0; /* The area is filled. */
1654
800k
                goto out;
1655
800k
            }
1656
9
            if (code < 0)
1657
9
                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
9
        }
1663
137k
        if (!pfs->unlinear || !pfs->linear_color ||
1664
137k
                color_span(pfs, c0, c1) > pfs->smoothness) {
1665
137k
            fixed y = (ybot + ytop) / 2;
1666
1667
137k
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1668
137k
            if (code >= 0)
1669
137k
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1670
137k
        } else
1671
0
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1672
137k
        pfs->monotonic_color = monotonic_color_save;
1673
137k
        pfs->linear_color = linear_color_save;
1674
137k
    }
1675
1.04M
out:
1676
1.04M
    pfs->inside = save_inside;
1677
1.04M
    release_colors_inline(pfs, color_stack_ptr, 1);
1678
1.04M
    return code;
1679
1.04M
}
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
1.24M
{
1686
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1687
1.24M
    gs_fixed_edge le, re;
1688
1689
1.24M
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1690
1.24M
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1691
1.24M
}
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.90M
{
1698
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1699
1.90M
    fixed dx1, dy1, dx2, dy2;
1700
1.90M
    bool orient;
1701
1702
1.90M
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1703
663k
        return 0;
1704
1.24M
    if (ybot == ytop)
1705
0
        return 0;
1706
1.24M
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1707
1.24M
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1708
1.24M
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1709
619k
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1710
619k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1711
623k
    } else {
1712
623k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1713
1714
623k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1715
623k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1716
623k
    }
1717
1.24M
}
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.90M
{
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.90M
    gs_fixed_point p[4];
1727
1.90M
    const patch_color_t *cc0, *cc1;
1728
1729
1.90M
    if (p0->y < p1->y) {
1730
930k
        p[2] = *p0;
1731
930k
        p[3] = *p1;
1732
930k
        cc0 = c0;
1733
930k
        cc1 = c1;
1734
977k
    } else {
1735
977k
        p[2] = *p1;
1736
977k
        p[3] = *p0;
1737
977k
        cc0 = c1;
1738
977k
        cc1 = c0;
1739
977k
    }
1740
1.90M
    p[0] = *q0;
1741
1.90M
    p[1] = *q1;
1742
1.90M
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1743
1.90M
}
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
14.3M
{
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
14.3M
#define midpoint(a,b)\
1757
172M
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1758
14.3M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1759
14.3M
    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
14.3M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1763
14.3M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1764
14.3M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1765
14.3M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1766
14.3M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1767
14.3M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1768
14.3M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1769
14.3M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1770
14.3M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1771
14.3M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1772
14.3M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1773
14.3M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1774
14.3M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1775
14.3M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1776
14.3M
#undef midpoint
1777
14.3M
}
1778
1779
static void
1780
split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1781
131k
{
1782
131k
    split_curve_s(pole, q0, q1, 1);
1783
131k
}
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
870k
{
1826
870k
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1827
1828
870k
    return max(dx, dy);
1829
870k
}
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
49.4k
{
1835
49.4k
    if (l->end != NULL)
1836
0
        return_error(gs_error_unregistered); /* Must not happen. */
1837
49.4k
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1838
49.4k
    l->end = wedge_vertex_list_elem_reserve(pfs);
1839
49.4k
    if (l->beg == NULL)
1840
0
        return_error(gs_error_unregistered); /* Must not happen. */
1841
49.4k
    if (l->end == NULL)
1842
0
        return_error(gs_error_unregistered); /* Must not happen. */
1843
49.4k
    l->beg->prev = l->end->next = NULL;
1844
49.4k
    l->beg->next = l->end;
1845
49.4k
    l->end->prev = l->beg;
1846
49.4k
    l->beg->p = *p0;
1847
49.4k
    l->end->p = *p1;
1848
49.4k
    l->beg->level = l->end->level = 0;
1849
49.4k
    return 0;
1850
49.4k
}
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
98.5k
{
1856
98.5k
    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
98.5k
    if (e == NULL)
1861
0
        return_error(gs_error_unregistered); /* Must not happen. */
1862
98.5k
    if (l->beg->next != l->end)
1863
0
        return_error(gs_error_unregistered); /* Must not happen. */
1864
98.5k
    if (l->end->prev != l->beg)
1865
0
        return_error(gs_error_unregistered); /* Must not happen. */
1866
98.5k
    e->next = l->end;
1867
98.5k
    e->prev = l->beg;
1868
98.5k
    e->p = *p;
1869
98.5k
    e->level = max(l->beg->level, l->end->level) + 1;
1870
98.5k
    e->divide_count = 0;
1871
98.5k
    l->beg->next = l->end->prev = e;
1872
98.5k
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1873
98.5k
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1874
1875
98.5k
        if ((p->x - l->beg->p.x) * sx < 0)
1876
0
            return_error(gs_error_unregistered); /* Must not happen. */
1877
98.5k
        if ((p->y - l->beg->p.y) * sy < 0)
1878
0
            return_error(gs_error_unregistered); /* Must not happen. */
1879
98.5k
        if ((l->end->p.x - p->x) * sx < 0)
1880
0
            return_error(gs_error_unregistered); /* Must not happen. */
1881
98.5k
        if ((l->end->p.y - p->y) * sy < 0)
1882
0
            return_error(gs_error_unregistered); /* Must not happen. */
1883
98.5k
    }
1884
98.5k
    *r = e;
1885
98.5k
    return 0;
1886
98.5k
}
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
122k
{
1893
122k
    wedge_vertex_list_elem_t *e;
1894
122k
    int code;
1895
1896
122k
    if (!l->last_side) {
1897
89.5k
        if (l->beg == NULL) {
1898
44.4k
            code = create_wedge_vertex_list(pfs, l, p0, p1);
1899
44.4k
            if (code < 0)
1900
0
                return code;
1901
44.4k
        }
1902
89.5k
        if (l->beg->p.x != p0->x)
1903
0
            return_error(gs_error_unregistered); /* Must not happen. */
1904
89.5k
        if (l->beg->p.y != p0->y)
1905
0
            return_error(gs_error_unregistered); /* Must not happen. */
1906
89.5k
        if (l->end->p.x != p1->x)
1907
0
            return_error(gs_error_unregistered); /* Must not happen. */
1908
89.5k
        if (l->end->p.y != p1->y)
1909
0
            return_error(gs_error_unregistered); /* Must not happen. */
1910
89.5k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1911
89.5k
        if (code < 0)
1912
0
            return code;
1913
89.5k
        e->divide_count++;
1914
89.5k
    } else if (l->beg == NULL) {
1915
5.06k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1916
5.06k
        if (code < 0)
1917
0
            return code;
1918
5.06k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1919
5.06k
        if (code < 0)
1920
0
            return code;
1921
5.06k
        e->divide_count++;
1922
27.9k
    } else {
1923
27.9k
        if (l->beg->p.x != p1->x)
1924
0
            return_error(gs_error_unregistered); /* Must not happen. */
1925
27.9k
        if (l->beg->p.y != p1->y)
1926
0
            return_error(gs_error_unregistered); /* Must not happen. */
1927
27.9k
        if (l->end->p.x != p0->x)
1928
0
            return_error(gs_error_unregistered); /* Must not happen. */
1929
27.9k
        if (l->end->p.y != p0->y)
1930
0
            return_error(gs_error_unregistered); /* Must not happen. */
1931
27.9k
        if (l->beg->next == l->end) {
1932
4.02k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1933
4.02k
            if (code < 0)
1934
0
                return code;
1935
4.02k
            e->divide_count++;
1936
23.9k
        } else {
1937
23.9k
            e = wedge_vertex_list_find(l->beg, l->end,
1938
23.9k
                        max(l->beg->level, l->end->level) + 1);
1939
23.9k
            if (e == NULL)
1940
0
                return_error(gs_error_unregistered); /* Must not happen. */
1941
23.9k
            if (e->p.x != pm->x || e->p.y != pm->y)
1942
0
                return_error(gs_error_unregistered); /* Must not happen. */
1943
23.9k
            e->divide_count++;
1944
23.9k
        }
1945
27.9k
    }
1946
122k
    *r = e;
1947
122k
    return 0;
1948
122k
}
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
122k
{
1955
122k
    int code;
1956
1957
122k
    l->last_side = l0->last_side;
1958
122k
    if (!l->last_side ^ !forth) {
1959
70.7k
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1960
70.7k
        l->beg = l0->beg;
1961
70.7k
    } else {
1962
51.7k
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1963
51.7k
        l->end = l0->end;
1964
51.7k
    }
1965
122k
    return code;
1966
122k
}
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
122k
{
1975
122k
    int code;
1976
1977
122k
    if (!l->last_side)
1978
89.5k
        return 0;
1979
33.0k
    code = fill_wedge_from_list(pfs, l, c1, c0);
1980
33.0k
    if (code < 0)
1981
0
        return code;
1982
33.0k
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1983
33.0k
    return 0;
1984
33.0k
}
1985
1986
static inline void
1987
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1988
122k
{
1989
122k
    if (!l->last_side ^ !forth) {
1990
70.7k
        l->beg = l->end;
1991
70.7k
        l->end = l0->end;
1992
70.7k
    } else {
1993
51.7k
        l->end = l->beg;
1994
51.7k
        l->beg = l0->beg;
1995
51.7k
    }
1996
122k
}
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
953k
{   int code;
2002
953k
    const gs_fixed_point *p0, *p1, *p2;
2003
953k
    gs_fixed_point qq0, qq1, qq2;
2004
953k
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2005
953k
    bool swap_axes;
2006
2007
#   if SKIP_TEST
2008
        dbg_wedge_triangle_cnt++;
2009
#   endif
2010
953k
    if (dx > dy) {
2011
475k
        swap_axes = true;
2012
475k
        qq0.x = q0->p.y;
2013
475k
        qq0.y = q0->p.x;
2014
475k
        qq1.x = q1->p.y;
2015
475k
        qq1.y = q1->p.x;
2016
475k
        qq2.x = q2->p.y;
2017
475k
        qq2.y = q2->p.x;
2018
475k
        p0 = &qq0;
2019
475k
        p1 = &qq1;
2020
475k
        p2 = &qq2;
2021
477k
    } else {
2022
477k
        swap_axes = false;
2023
477k
        p0 = &q0->p;
2024
477k
        p1 = &q1->p;
2025
477k
        p2 = &q2->p;
2026
477k
    }
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
953k
    if (p0->y < p1->y) {
2032
467k
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2033
467k
        if (code < 0)
2034
0
            return code;
2035
467k
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2036
486k
    } else {
2037
486k
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2038
486k
        if (code < 0)
2039
0
            return code;
2040
486k
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2041
486k
    }
2042
953k
}
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
4.66M
{
2049
    /*  Returns :
2050
        <0 - error;
2051
        0 - success;
2052
        1 - decompose to linear color areas;
2053
        2 - decompose to constant color areas;
2054
     */
2055
4.66M
    int code;
2056
2057
4.66M
    if (pfs->unlinear)
2058
0
        return 2;
2059
4.66M
    if (!wedge) {
2060
4.66M
        const gs_color_space *cs = pfs->direct_space;
2061
2062
4.66M
        if (cs != NULL) {
2063
4.66M
            float s0, s1, s2, s01, s012;
2064
2065
4.66M
            s0 = function_linearity(pfs, p0->c, p1->c);
2066
4.66M
            if (s0 > pfs->smoothness)
2067
14.8k
                return 1;
2068
4.64M
            s1 = function_linearity(pfs, p1->c, p2->c);
2069
4.64M
            if (s1 > pfs->smoothness)
2070
9.34k
                return 1;
2071
4.63M
            s2 = function_linearity(pfs, p2->c, p0->c);
2072
4.63M
            if (s2 > pfs->smoothness)
2073
393
                return 1;
2074
            /* fixme: check an inner color ? */
2075
4.63M
            s01 = max(s0, s1);
2076
4.63M
            s012 = max(s01, s2);
2077
4.63M
            if (pfs->cs_always_linear)
2078
1.15M
                code = 1;
2079
3.47M
            else
2080
3.47M
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2081
4.63M
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2082
4.63M
                                  pfs->smoothness - s012, pfs->icclink);
2083
4.63M
            if (code < 0)
2084
0
                return code;
2085
4.63M
            if (code == 0)
2086
1.69k
                return 1;
2087
4.63M
        }
2088
4.66M
    }
2089
4.63M
    {   gx_device *pdev = pfs->dev;
2090
4.63M
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2091
4.63M
        gs_fill_attributes fa;
2092
4.63M
        gx_device_color dc[3];
2093
2094
4.63M
        fa.clip = &pfs->rect;
2095
4.63M
        fa.ht = NULL;
2096
4.63M
        fa.swap_axes = false;
2097
4.63M
        fa.lop = 0;
2098
4.63M
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2099
4.63M
        if (code != 0)
2100
0
            return code;
2101
4.63M
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2102
4.63M
            dc[0].type == &gx_dc_type_data_devn))
2103
0
            return 2;
2104
4.63M
        if (!wedge) {
2105
4.63M
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2106
4.63M
            if (code != 0)
2107
0
                return code;
2108
4.63M
        }
2109
4.63M
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2110
4.63M
        if (code != 0)
2111
0
            return code;
2112
4.63M
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2113
4.63M
                        &p0->p, &p1->p, &p2->p,
2114
4.63M
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2115
4.63M
        if (code == 1)
2116
4.63M
            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.38M
{
2128
1.38M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2129
1.38M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2130
433k
        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
953k
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2138
1.38M
}
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
74.6k
{
2146
74.6k
    shading_vertex_t p[3];
2147
74.6k
    patch_color_t *c;
2148
74.6k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2149
74.6k
    int code;
2150
2151
74.6k
    if (color_stack_ptr == NULL)
2152
0
        return_error(gs_error_unregistered); /* Must not happen. */
2153
74.6k
    p[2].c = c;
2154
74.6k
    p[0].p = beg->p;
2155
74.6k
    p[0].c = c0;
2156
74.6k
    p[1].p = end->p;
2157
74.6k
    p[1].c = c1;
2158
74.6k
    p[2].p = mid->p;
2159
74.6k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2160
74.6k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2161
74.6k
    release_colors_inline(pfs, color_stack_ptr, 1);
2162
74.6k
    return code;
2163
74.6k
}
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
135k
{
2170
135k
    if (beg->next == end)
2171
37.0k
        return 0;
2172
98.5k
    else if (beg->next->next == end) {
2173
72.0k
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2174
0
            return_error(gs_error_unregistered); /* Must not happen. */
2175
72.0k
        if (beg->next->divide_count != 1)
2176
23.5k
            return 0;
2177
48.4k
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2178
72.0k
    } else {
2179
26.5k
        gs_fixed_point p;
2180
26.5k
        wedge_vertex_list_elem_t *e;
2181
26.5k
        patch_color_t *c;
2182
26.5k
        int code;
2183
26.5k
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2184
2185
26.5k
        if (color_stack_ptr == NULL)
2186
0
            return_error(gs_error_unregistered); /* Must not happen. */
2187
26.5k
        p.x = (beg->p.x + end->p.x) / 2;
2188
26.5k
        p.y = (beg->p.y + end->p.y) / 2;
2189
26.5k
        e = wedge_vertex_list_find(beg, end, level + 1);
2190
26.5k
        if (e == NULL)
2191
0
            return_error(gs_error_unregistered); /* Must not happen. */
2192
26.5k
        if (e->p.x != p.x || e->p.y != p.y)
2193
0
            return_error(gs_error_unregistered); /* Must not happen. */
2194
26.5k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2195
26.5k
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2196
26.5k
        if (code >= 0)
2197
26.5k
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2198
26.5k
        if (code >= 0) {
2199
26.5k
            if (e->divide_count != 1 && e->divide_count != 2)
2200
0
                return_error(gs_error_unregistered); /* Must not happen. */
2201
26.5k
            if (e->divide_count == 1)
2202
26.2k
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2203
26.5k
        }
2204
26.5k
        release_colors_inline(pfs, color_stack_ptr, 1);
2205
26.5k
        return code;
2206
26.5k
    }
2207
135k
}
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
82.4k
{
2213
82.4k
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2214
82.4k
                    max(l->beg->level, l->end->level), c0, c1);
2215
82.4k
}
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
12.4M
{
2221
12.4M
    if (l->beg != NULL) {
2222
49.4k
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2223
2224
49.4k
        if (code < 0)
2225
0
            return code;
2226
49.4k
        return release_wedge_vertex_list(pfs, l, 1);
2227
49.4k
    }
2228
12.3M
    return 0;
2229
12.4M
}
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
108k
{   /* Assuming ka >= 2, see fill_wedges. */
2235
108k
    gs_fixed_point q[2][4];
2236
108k
    patch_color_t *c;
2237
108k
    shading_vertex_t p[3];
2238
108k
    int code;
2239
108k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2240
2241
108k
    if (color_stack_ptr == NULL)
2242
0
        return_error(gs_error_unregistered); /* Must not happen. */
2243
108k
    p[2].c = c;
2244
108k
    split_curve(pole, q[0], q[1]);
2245
108k
    p[0].p = pole[0];
2246
108k
    p[0].c = c0;
2247
108k
    p[1].p = pole[3];
2248
108k
    p[1].c = c1;
2249
108k
    p[2].p = q[0][3];
2250
108k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2251
108k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2252
108k
    if (code >= 0) {
2253
108k
        if (ka == 2)
2254
59.3k
            goto out;
2255
49.3k
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2256
49.3k
    }
2257
49.3k
    if (code >= 0)
2258
49.3k
        code = wedge_by_triangles(pfs, ka / 2, q[1], p[2].c, c1);
2259
108k
out:
2260
108k
    release_colors_inline(pfs, color_stack_ptr, 1);
2261
108k
    return code;
2262
49.3k
}
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
1.58M
{
2268
1.58M
    gs_fixed_point q0, q1;
2269
1.58M
    const patch_color_t *cc0, *cc1;
2270
1.58M
    fixed dx = p1->x - p0->x;
2271
1.58M
    fixed dy = p1->y - p0->y;
2272
1.58M
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2273
1.58M
    gs_fixed_edge le, re;
2274
1.58M
    const fixed adjust = INTERPATCH_PADDING;
2275
2276
1.58M
    if (swap_axes) {
2277
619k
        if (p0->x < p1->x) {
2278
313k
            q0.x = p0->y;
2279
313k
            q0.y = p0->x;
2280
313k
            q1.x = p1->y;
2281
313k
            q1.y = p1->x;
2282
313k
            cc0 = c0;
2283
313k
            cc1 = c1;
2284
313k
        } else {
2285
305k
            q0.x = p1->y;
2286
305k
            q0.y = p1->x;
2287
305k
            q1.x = p0->y;
2288
305k
            q1.y = p0->x;
2289
305k
            cc0 = c1;
2290
305k
            cc1 = c0;
2291
305k
        }
2292
962k
    } else if (p0->y < p1->y) {
2293
262k
        q0 = *p0;
2294
262k
        q1 = *p1;
2295
262k
        cc0 = c0;
2296
262k
        cc1 = c1;
2297
699k
    } else {
2298
699k
        q0 = *p1;
2299
699k
        q1 = *p0;
2300
699k
        cc0 = c1;
2301
699k
        cc1 = c0;
2302
699k
    }
2303
1.58M
    le.start.x = q0.x - adjust;
2304
1.58M
    re.start.x = q0.x + adjust;
2305
1.58M
    le.start.y = re.start.y = q0.y - adjust;
2306
1.58M
    le.end.x = q1.x - adjust;
2307
1.58M
    re.end.x = q1.x + adjust;
2308
1.58M
    le.end.y = re.end.y = q1.y + adjust;
2309
1.58M
    adjust_swapped_boundary(&re.start.x, swap_axes);
2310
1.58M
    adjust_swapped_boundary(&re.end.x, swap_axes);
2311
1.58M
    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
1.58M
}
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.78M
{
2325
1.78M
    r->p.x = r->q.x = p0->x;
2326
1.78M
    r->p.y = r->q.y = p0->y;
2327
2328
1.78M
    if (r->p.x > p1->x)
2329
782k
        r->p.x = p1->x;
2330
1.78M
    if (r->q.x < p1->x)
2331
859k
        r->q.x = p1->x;
2332
1.78M
    if (r->p.y > p1->y)
2333
860k
        r->p.y = p1->y;
2334
1.78M
    if (r->q.y < p1->y)
2335
777k
        r->q.y = p1->y;
2336
2337
1.78M
    if (r->p.x > p2->x)
2338
427k
        r->p.x = p2->x;
2339
1.78M
    if (r->q.x < p2->x)
2340
405k
        r->q.x = p2->x;
2341
1.78M
    if (r->p.y > p2->y)
2342
387k
        r->p.y = p2->y;
2343
1.78M
    if (r->q.y < p2->y)
2344
435k
        r->q.y = p2->y;
2345
2346
1.78M
    if (p3 == NULL)
2347
1.16M
        return;
2348
2349
626k
    if (r->p.x > p3->x)
2350
124k
        r->p.x = p3->x;
2351
626k
    if (r->q.x < p3->x)
2352
156k
        r->q.x = p3->x;
2353
626k
    if (r->p.y > p3->y)
2354
144k
        r->p.y = p3->y;
2355
626k
    if (r->q.y < p3->y)
2356
128k
        r->q.y = p3->y;
2357
626k
}
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
142k
{
2364
142k
    int code;
2365
2366
142k
    if (k > 1) {
2367
43.7k
        gs_fixed_point q[2][4];
2368
43.7k
        patch_color_t *c;
2369
43.7k
        bool save_inside = pfs->inside;
2370
43.7k
        byte *color_stack_ptr;
2371
2372
43.7k
        if (!pfs->inside) {
2373
36.0k
            gs_fixed_rect r, r1;
2374
2375
36.0k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2376
36.0k
            r.p.x -= INTERPATCH_PADDING;
2377
36.0k
            r.p.y -= INTERPATCH_PADDING;
2378
36.0k
            r.q.x += INTERPATCH_PADDING;
2379
36.0k
            r.q.y += INTERPATCH_PADDING;
2380
36.0k
            r1 = r;
2381
36.0k
            rect_intersect(r, pfs->rect);
2382
36.0k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2383
20.5k
                return 0;
2384
15.4k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2385
15.4k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2386
6.31k
                pfs->inside = true;
2387
15.4k
        }
2388
23.1k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2389
23.1k
        if (color_stack_ptr == NULL)
2390
0
            return_error(gs_error_unregistered); /* Must not happen. */
2391
23.1k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2392
23.1k
        split_curve(pole, q[0], q[1]);
2393
23.1k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2394
23.1k
        if (code >= 0)
2395
23.1k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2396
23.1k
        release_colors_inline(pfs, color_stack_ptr, 1);
2397
23.1k
        pfs->inside = save_inside;
2398
23.1k
        return code;
2399
99.2k
    } else {
2400
99.2k
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2401
93.2k
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2402
93.2k
            if (code < 0)
2403
0
                return code;
2404
93.2k
        }
2405
99.2k
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2406
10.0k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2407
89.1k
        return 0;
2408
99.2k
    }
2409
142k
}
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
1.25M
{
2417
    /* Generate wedges between 2 variants of a curve flattening. */
2418
    /* k0, k1 is a power of 2. */
2419
1.25M
    gs_fixed_point p[4];
2420
2421
1.25M
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2422
1.15M
        return 0; /* Wedges are zero area. */
2423
96.5k
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2424
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2425
0
    }
2426
96.5k
    p[0] = pole[0];
2427
96.5k
    p[1] = pole[pole_step];
2428
96.5k
    p[2] = pole[pole_step * 2];
2429
96.5k
    p[3] = pole[pole_step * 3];
2430
96.5k
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2431
1.25M
}
2432
2433
static inline void
2434
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2435
22.5k
{
2436
22.5k
    q[0] = p->p[0][0]->p;
2437
22.5k
    q[1] = p->p[0][1]->p;
2438
22.5k
    q[2] = p->p[1][1]->p;
2439
22.5k
    q[3] = p->p[1][0]->p;
2440
22.5k
}
2441
2442
static inline void
2443
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2444
22.5k
{
2445
22.5k
    fixed y = s[0].y;
2446
22.5k
    int i = 0;
2447
2448
22.5k
    if (y > s[1].y)
2449
12.7k
        i = 1, y = s[1].y;
2450
22.5k
    if (y > s[2].y)
2451
10.1k
        i = 2, y = s[2].y;
2452
22.5k
    if (y > s[3].y)
2453
408
        i = 3, y = s[3].y;
2454
22.5k
    q[0] = s[(i + 0) % 4];
2455
22.5k
    q[1] = s[(i + 1) % 4];
2456
22.5k
    q[2] = s[(i + 2) % 4];
2457
22.5k
    q[3] = s[(i + 3) % 4];
2458
22.5k
}
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
11.4k
{
2463
11.4k
    gs_fixed_edge ue;
2464
11.4k
    int code;
2465
11.4k
    gx_device_color dc;
2466
2467
#   if NOFILL_TEST
2468
        if (dbg_nofill)
2469
            return 0;
2470
#   endif
2471
11.4k
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2472
11.4k
    if (code < 0)
2473
0
        return code;
2474
11.4k
    if (le->end.y < re->end.y) {
2475
4.26k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2476
4.26k
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2477
4.26k
        if (code >= 0) {
2478
4.26k
            ue.start = le->end;
2479
4.26k
            ue.end = re->end;
2480
4.26k
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2481
4.26k
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2482
4.26k
        }
2483
7.17k
    } else if (le->end.y > re->end.y) {
2484
4.25k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2485
4.25k
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2486
4.25k
        if (code >= 0) {
2487
4.25k
            ue.start = re->end;
2488
4.25k
            ue.end = le->end;
2489
4.25k
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2490
4.25k
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2491
4.25k
        }
2492
4.25k
    } else
2493
2.92k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2494
2.92k
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2495
11.4k
    return code;
2496
11.4k
}
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
8.52k
{
2502
8.52k
    patch_color_t *c[2];
2503
8.52k
    gs_fixed_edge le, re;
2504
8.52k
    fixed dx0, dy0, dx1, dy1;
2505
8.52k
    const shading_vertex_t *pp;
2506
8.52k
    int i, code = 0;
2507
8.52k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2508
2509
8.52k
    if (color_stack_ptr == NULL)
2510
0
        return_error(gs_error_unregistered); /* Must not happen. */
2511
8.52k
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2512
8.52k
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2513
34.0k
    for (i = 0; i < 3; i++) {
2514
        /* fixme : does optimizer compiler expand this cycle ? */
2515
25.5k
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2516
11.4k
            le.start = re.start = p0->p;
2517
11.4k
            le.end = p1->p;
2518
11.4k
            re.end = p2->p;
2519
2520
11.4k
            dx0 = le.end.x - le.start.x;
2521
11.4k
            dy0 = le.end.y - le.start.y;
2522
11.4k
            dx1 = re.end.x - re.start.x;
2523
11.4k
            dy1 = re.end.y - re.start.y;
2524
11.4k
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2525
2.66k
                code = ordered_triangle(pfs, &le, &re, c[1]);
2526
8.78k
            else
2527
8.78k
                code = ordered_triangle(pfs, &re, &le, c[1]);
2528
11.4k
            if (code < 0)
2529
0
                break;
2530
11.4k
        }
2531
25.5k
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2532
25.5k
    }
2533
8.52k
    release_colors_inline(pfs, color_stack_ptr, 2);
2534
8.52k
    return code;
2535
8.52k
}
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
22.5k
{
2541
    /* Assuming the XY span is restricted with curve_samples.
2542
       It is important for intersection_of_small_bars to compute faster. */
2543
22.5k
    gs_fixed_point q[4];
2544
22.5k
    fixed ry, ey;
2545
22.5k
    int code;
2546
22.5k
    bool swap_axes = false;
2547
22.5k
    gx_device_color dc;
2548
22.5k
    bool orient;
2549
2550
22.5k
    dc.tag = device_current_tag(pfs->dev);
2551
2552
22.5k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2553
22.5k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2554
22.5k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2555
22.5k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2556
22.5k
    if (code < 0)
2557
0
        return code;
2558
22.5k
    {   gs_fixed_point qq[4];
2559
2560
22.5k
        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
22.5k
        wrap_vertices_by_y(q, qq);
2573
22.5k
    }
2574
22.5k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2575
22.5k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2576
22.5k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2577
2578
22.5k
        if (g13 == h13) {
2579
60
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2580
60
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2581
2582
60
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2583
0
                return 0;
2584
60
            if (g23 != h23) {
2585
60
                orient = (g23 > h23);
2586
60
                if (q[2].y <= q[3].y) {
2587
60
                    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
60
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2590
60
                } else {
2591
0
                    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
0
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2594
0
                }
2595
60
            } 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
60
        }
2612
22.5k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2613
22.5k
    }
2614
22.5k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2615
9.38k
        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
9.38k
        } else {
2624
9.38k
            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
9.38k
            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
9.38k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2629
9.38k
        }
2630
13.1k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2631
10.6k
        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
10.6k
        } else {
2640
10.6k
            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
10.6k
            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
10.6k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2645
10.6k
        }
2646
10.6k
    } 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
2.45k
    } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2671
4
        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
4
        } 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
4
        } else {
2690
4
            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
4
            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
4
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2695
4
        }
2696
2.45k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2697
2.44k
        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
2.44k
        } else {
2706
2.44k
            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
2.44k
            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
2.44k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2711
2.44k
        }
2712
2.44k
    } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2713
4
        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
4
        } else {
2722
4
            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
4
            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
4
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2727
4
        }
2728
4
    } else {
2729
        /* Impossible. */
2730
0
        return_error(gs_error_unregistered);
2731
0
    }
2732
22.5k
}
2733
2734
int
2735
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2736
22.5k
{
2737
22.5k
    patch_color_t *c[3];
2738
22.5k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2739
22.5k
    int code;
2740
2741
22.5k
    if (color_stack_ptr == NULL)
2742
0
        return_error(gs_error_unregistered); /* Must not happen. */
2743
22.5k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2744
22.5k
    release_colors_inline(pfs, color_stack_ptr, 3);
2745
22.5k
    return code;
2746
22.5k
}
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
21.6k
{
2752
21.6k
    q[0].c = c[0];
2753
21.6k
    q[1].c = c[1];
2754
21.6k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2755
21.6k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2756
21.6k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2757
21.6k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2758
21.6k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2759
21.6k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2760
21.6k
    s0->p[0][0] = p->p[0][0];
2761
21.6k
    s0->p[0][1] = p->p[0][1];
2762
21.6k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2763
21.6k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2764
21.6k
    s1->p[1][0] = p->p[1][0];
2765
21.6k
    s1->p[1][1] = p->p[1][1];
2766
21.6k
}
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
12.9k
{
2772
12.9k
    q[0].c = c[0];
2773
12.9k
    q[1].c = c[1];
2774
12.9k
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2775
12.9k
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2776
12.9k
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2777
12.9k
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2778
12.9k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2779
12.9k
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2780
12.9k
    s0->p[0][0] = p->p[0][0];
2781
12.9k
    s0->p[1][0] = p->p[1][0];
2782
12.9k
    s0->p[0][1] = s1->p[0][0] = &q[0];
2783
12.9k
    s0->p[1][1] = s1->p[1][0] = &q[1];
2784
12.9k
    s1->p[0][1] = p->p[0][1];
2785
12.9k
    s1->p[1][1] = p->p[1][1];
2786
12.9k
}
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
125k
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2792
125k
    int code, r;
2793
2794
125k
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2795
125k
    if (code <= 0)
2796
114k
        return code;
2797
10.4k
    r = code << pfs->function_arg_shift;
2798
10.4k
    if (r & 1)
2799
0
        *not_monotonic_by_u = true;
2800
10.4k
    if (r & 2)
2801
10.4k
        *not_monotonic_by_v = true;
2802
10.4k
    return !code;
2803
125k
}
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
1.05M
{
2810
    /* Assuming p.c == c for providing a non-const access. */
2811
1.05M
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2812
1.05M
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2813
1.05M
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2814
1.05M
}
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
4.93M
{
2822
4.93M
    shading_vertex_t p01, p12, p20;
2823
4.93M
    patch_color_t *c[3];
2824
4.93M
    wedge_vertex_list_t L01, L12, L20, L[3];
2825
4.93M
    bool inside_save = pfs->inside;
2826
4.93M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2827
4.93M
    int code = 0;
2828
4.93M
    byte *color_stack_ptr;
2829
4.93M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2830
2831
4.93M
    if (!inside) {
2832
1.16M
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2833
1.16M
        r1 = r;
2834
1.16M
        rect_intersect(r, pfs->rect);
2835
1.16M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2836
270k
            return 0;
2837
1.16M
    }
2838
4.66M
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2839
4.66M
    if(color_stack_ptr == NULL)
2840
0
        return_error(gs_error_unregistered);
2841
4.66M
    p01.c = c[0];
2842
4.66M
    p12.c = c[1];
2843
4.66M
    p20.c = c[2];
2844
4.66M
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2845
4.66M
    switch(code) {
2846
4.63M
        case 0: /* The area is filled. */
2847
4.63M
            goto out;
2848
0
        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
0
            if (sd < pfs->decomposition_limit * 4) {
2853
0
                code = constant_color_triangle(pfs, p2, p0, p1);
2854
0
                goto out;
2855
0
            }
2856
0
            if (pfs->Function != NULL) {
2857
0
                double d01 = color_span(pfs, p1->c, p0->c);
2858
0
                double d12 = color_span(pfs, p2->c, p1->c);
2859
0
                double d20 = color_span(pfs, p0->c, p2->c);
2860
2861
0
                if (d01 <= pfs->smoothness / COLOR_CONTIGUITY &&
2862
0
                    d12 <= pfs->smoothness / COLOR_CONTIGUITY &&
2863
0
                    d20 <= pfs->smoothness / COLOR_CONTIGUITY) {
2864
0
                    code = constant_color_triangle(pfs, p2, p0, p1);
2865
0
                    goto out;
2866
0
                }
2867
0
            } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY) {
2868
0
                code = constant_color_triangle(pfs, p2, p0, p1);
2869
0
                goto out;
2870
0
            }
2871
0
            break;
2872
26.2k
        case 1: /* decompose to linear color areas */
2873
26.2k
            if (sd < pfs->decomposition_limit) {
2874
8.52k
                code = constant_color_triangle(pfs, p2, p0, p1);
2875
8.52k
                goto out;
2876
8.52k
            }
2877
17.7k
            break;
2878
17.7k
        default: /* Error. */
2879
0
            goto out;
2880
4.66M
    }
2881
17.7k
    if (!inside) {
2882
5.69k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2883
5.69k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
2884
1.13k
            pfs->inside = true;
2885
5.69k
    }
2886
17.7k
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2887
17.7k
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2888
17.7k
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2889
17.7k
    if (LAZY_WEDGES) {
2890
17.7k
        init_wedge_vertex_list(L, count_of(L));
2891
17.7k
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2892
17.7k
        if (code >= 0)
2893
17.7k
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2894
17.7k
        if (code >= 0)
2895
17.7k
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2896
17.7k
    } 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
17.7k
    if (code >= 0)
2904
17.7k
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2905
17.7k
    if (code >= 0) {
2906
17.7k
        if (LAZY_WEDGES) {
2907
17.7k
            move_wedge(&L01, l01, true);
2908
17.7k
            move_wedge(&L20, l20, false);
2909
17.7k
        }
2910
17.7k
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2911
17.7k
    }
2912
17.7k
    if (code >= 0) {
2913
17.7k
        if (LAZY_WEDGES)
2914
17.7k
            move_wedge(&L12, l12, true);
2915
17.7k
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2916
17.7k
    }
2917
17.7k
    if (code >= 0) {
2918
17.7k
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2919
17.7k
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2920
17.7k
    }
2921
17.7k
    if (LAZY_WEDGES) {
2922
17.7k
        if (code >= 0)
2923
17.7k
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2924
17.7k
        if (code >= 0)
2925
17.7k
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2926
17.7k
        if (code >= 0)
2927
17.7k
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2928
17.7k
        if (code >= 0)
2929
17.7k
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2930
17.7k
        if (code >= 0)
2931
17.7k
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2932
17.7k
        if (code >= 0)
2933
17.7k
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2934
17.7k
    }
2935
17.7k
    pfs->inside = inside_save;
2936
4.66M
out:
2937
4.66M
    release_colors_inline(pfs, color_stack_ptr, 3);
2938
4.66M
    return code;
2939
17.7k
}
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
4.86M
{
2946
4.86M
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2947
4.86M
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2948
4.86M
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2949
4.86M
    fixed sd1 = max(sd01, sd12);
2950
4.86M
    fixed sd = max(sd1, sd20);
2951
4.86M
    double cd = 0;
2952
2953
#   if SKIP_TEST
2954
        dbg_triangle_cnt++;
2955
#   endif
2956
4.86M
    if (pfs->Function == NULL) {
2957
4.35M
        double d01 = color_span(pfs, p1->c, p0->c);
2958
4.35M
        double d12 = color_span(pfs, p2->c, p1->c);
2959
4.35M
        double d20 = color_span(pfs, p0->c, p2->c);
2960
4.35M
        double cd1 = max(d01, d12);
2961
2962
4.35M
        cd = max(cd1, d20);
2963
4.35M
    }
2964
4.86M
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2965
4.86M
}
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
264k
{
2971
264k
    int code;
2972
264k
    wedge_vertex_list_t l[3];
2973
2974
264k
    init_wedge_vertex_list(l, count_of(l));
2975
264k
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2976
264k
    if (code < 0)
2977
0
        return code;
2978
264k
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2979
264k
    if (code < 0)
2980
0
        return code;
2981
264k
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2982
264k
    if (code < 0)
2983
0
        return code;
2984
264k
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
2985
264k
}
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
316k
{
3083
316k
    pfs->unlinear = !is_linear_color_applicable(pfs);
3084
316k
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3085
316k
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3086
316k
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3087
264k
        return small_mesh_triangle(pfs, p0, p1, p2);
3088
51.8k
    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
51.8k
        shading_vertex_t p01, p12, p20;
3100
51.8k
        patch_color_t *c[3];
3101
51.8k
        int code;
3102
51.8k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3103
3104
51.8k
        if (color_stack_ptr == NULL)
3105
0
            return_error(gs_error_unregistered); /* Must not happen. */
3106
51.8k
        p01.c = c[0];
3107
51.8k
        p12.c = c[1];
3108
51.8k
        p20.c = c[2];
3109
51.8k
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3110
51.8k
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3111
51.8k
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3112
51.8k
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3113
51.8k
        if (code >= 0)
3114
51.8k
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3115
51.8k
        if (code >= 0)
3116
51.8k
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3117
51.8k
        if (code >= 0)
3118
51.8k
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3119
51.8k
        if (code >= 0)
3120
51.8k
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3121
51.8k
        if (code >= 0)
3122
51.8k
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3123
51.8k
        if (code >= 0)
3124
51.8k
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3125
51.8k
        release_colors_inline(pfs, color_stack_ptr, 3);
3126
51.8k
        return code;
3127
51.8k
    }
3128
316k
}
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
109k
{
3134
109k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3135
109k
            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
109k
    return mesh_triangle_rec(pfs, p0, p1, p2);
3163
109k
}
3164
3165
static inline int
3166
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3167
283k
{
3168
283k
    shading_vertex_t p0001, p1011, q;
3169
283k
    patch_color_t *c[3];
3170
283k
    wedge_vertex_list_t l[4];
3171
283k
    int code;
3172
283k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3173
3174
283k
    if(color_stack_ptr == NULL)
3175
0
        return_error(gs_error_unregistered); /* Must not happen. */
3176
283k
    p0001.c = c[0];
3177
283k
    p1011.c = c[1];
3178
283k
    q.c = c[2];
3179
283k
    init_wedge_vertex_list(l, count_of(l));
3180
283k
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3181
283k
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3182
283k
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3183
283k
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3184
283k
    if (code >= 0) {
3185
283k
        l[0].last_side = true;
3186
283k
        l[3].last_side = true;
3187
283k
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3188
283k
    }
3189
283k
    if (code >= 0) {
3190
283k
        l[1].last_side = true;
3191
283k
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3192
283k
    }
3193
283k
    if (code >= 0) {
3194
283k
        l[2].last_side = true;
3195
283k
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3196
283k
    }
3197
283k
    if (code >= 0)
3198
283k
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3199
283k
    if (code >= 0)
3200
283k
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3201
283k
    if (code >= 0)
3202
283k
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3203
283k
    if (code >= 0)
3204
283k
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3205
283k
    release_colors_inline(pfs, color_stack_ptr, 3);
3206
283k
    return code;
3207
283k
}
3208
3209
static inline int
3210
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3211
1.73M
{
3212
1.73M
    wedge_vertex_list_t l;
3213
1.73M
    int code;
3214
3215
1.73M
    init_wedge_vertex_list(&l, 1);
3216
1.73M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3217
1.73M
    if (code < 0)
3218
0
        return code;
3219
1.73M
    l.last_side = true;
3220
1.73M
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3221
1.73M
    if (code < 0)
3222
0
        return code;
3223
1.73M
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3224
1.73M
    if (code < 0)
3225
0
        return code;
3226
1.73M
    return 0;
3227
1.73M
}
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
2.16M
{
3233
2.16M
    qq[0][0].p = p->pole[0][0];
3234
2.16M
    qq[0][1].p = p->pole[0][3];
3235
2.16M
    qq[1][0].p = p->pole[3][0];
3236
2.16M
    qq[1][1].p = p->pole[3][3];
3237
2.16M
    qq[0][0].c = p->c[0][0];
3238
2.16M
    qq[0][1].c = p->c[0][1];
3239
2.16M
    qq[1][0].c = p->c[1][0];
3240
2.16M
    qq[1][1].c = p->c[1][1];
3241
2.16M
    q->p[0][0] = &qq[0][0];
3242
2.16M
    q->p[0][1] = &qq[0][1];
3243
2.16M
    q->p[1][0] = &qq[1][0];
3244
2.16M
    q->p[1][1] = &qq[1][1];
3245
2.16M
    q->l0001 = &l[0];
3246
2.16M
    q->l0111 = &l[1];
3247
2.16M
    q->l1110 = &l[2];
3248
2.16M
    q->l1000 = &l[3];
3249
2.16M
}
3250
3251
static inline int
3252
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3253
1.88M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3254
1.88M
    int code;
3255
3256
1.88M
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3257
1.88M
    if (code <= 0)
3258
2
        return code;
3259
1.88M
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3260
1.88M
}
3261
3262
static inline int
3263
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3264
83.9k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3265
83.9k
    int code;
3266
3267
83.9k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3268
83.9k
    if (code <= 0)
3269
13.6k
        return code;
3270
70.2k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3271
83.9k
}
3272
3273
static inline int
3274
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3275
75.9k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3276
75.9k
    int code;
3277
3278
75.9k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3279
75.9k
    if (code <= 0)
3280
9.45k
        return code;
3281
66.5k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3282
75.9k
}
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
1.93M
{
3297
1.93M
    patch_color_t d0001, d1011, d;
3298
1.93M
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3299
1.93M
    double Du, Dv;
3300
3301
1.93M
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3302
1.93M
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3303
1.93M
    D0001 = color_norm(pfs, &d0001);
3304
1.93M
    D1011 = color_norm(pfs, &d1011);
3305
1.93M
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3306
1.93M
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3307
1.93M
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3308
1.93M
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3309
1.93M
    if (pfs->unlinear) {
3310
0
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
3311
0
            D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
3312
0
            D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
3313
0
            return color_change_small;
3314
0
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
3315
0
            if (!is_big_v) {
3316
                /* The color function looks uncontiguous. */
3317
0
                return color_change_small;
3318
0
            }
3319
0
            *divide_v = true;
3320
0
            return color_change_gradient;
3321
0
        }
3322
0
        if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
3323
0
            if (!is_big_u) {
3324
                /* The color function looks uncontiguous. */
3325
0
                return color_change_small;
3326
0
            }
3327
0
            *divide_u = true;
3328
0
            return color_change_gradient;
3329
0
        }
3330
0
    }
3331
1.93M
    color_diff(pfs, &d0001, &d1011, &d);
3332
1.93M
    Du = max(D0001, D1011);
3333
1.93M
    Dv = max(D0010, D0111);
3334
1.93M
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3335
96.1k
        return color_change_small;
3336
1.83M
    if (Du <= pfs->smoothness / 8)
3337
15.8k
        return color_change_linear;
3338
1.82M
    if (Dv <= pfs->smoothness / 8)
3339
1.71M
        return color_change_linear;
3340
106k
    D = color_norm(pfs, &d);
3341
106k
    if (D <= pfs->smoothness)
3342
92.5k
        return color_change_bilinear;
3343
13.7k
#if 1
3344
13.7k
    if (Du > Dv && is_big_u)
3345
7.67k
        *divide_u = true;
3346
6.12k
    else if (Du < Dv && is_big_v)
3347
4.86k
        *divide_v = true;
3348
1.25k
    else if (is_big_u && size_u > size_v)
3349
460
        *divide_u = true;
3350
797
    else if (is_big_v && size_v > size_u)
3351
797
        *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
13.7k
    return color_change_general;
3368
13.7k
}
3369
3370
static int
3371
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3372
2.23M
{
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
2.23M
    quadrangle_patch s0, s1;
3377
2.23M
    wedge_vertex_list_t l0, l1, l2;
3378
2.23M
    int code;
3379
2.23M
    bool divide_u = false, divide_v = false, big1 = big;
3380
2.23M
    shading_vertex_t q[2];
3381
2.23M
    bool monotonic_color_save = pfs->monotonic_color;
3382
2.23M
    bool linear_color_save = pfs->linear_color;
3383
2.23M
    bool inside_save = pfs->inside;
3384
2.23M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3385
2.23M
    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
2.23M
    if (!inside) {
3389
590k
        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
590k
        r1 = r;
3391
590k
        rect_intersect(r, pfs->rect);
3392
590k
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3393
162k
            return 0; /* Outside. */
3394
590k
    }
3395
2.07M
    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
2.00M
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3401
2.00M
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3402
2.00M
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3403
2.00M
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3404
2.00M
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3405
2.00M
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3406
2.00M
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3407
2.00M
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3408
3409
2.00M
        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
2.00M
            big1 = false;
3422
2.00M
    }
3423
2.07M
    if (!big1) {
3424
2.07M
        bool is_big_u = false, is_big_v = false;
3425
2.07M
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3426
2.07M
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3427
2.07M
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3428
2.07M
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3429
2.07M
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3430
2.07M
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3431
2.07M
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3432
2.07M
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3433
2.07M
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3434
2.07M
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3435
3436
2.07M
        if (size_u > pfs->decomposition_limit)
3437
1.94M
            is_big_u = true;
3438
2.07M
        if (size_v > pfs->decomposition_limit)
3439
117k
            is_big_v = true;
3440
1.95M
        else if (!is_big_u)
3441
117k
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3442
108k
                        constant_color_quadrangle : triangles4)(pfs, p,
3443
117k
                            pfs->maybe_self_intersecting);
3444
1.95M
        if (!pfs->monotonic_color) {
3445
125k
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3446
3447
125k
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3448
125k
            if (code < 0)
3449
0
                return code;
3450
125k
            if (is_big_u)
3451
124k
                divide_u = not_monotonic_by_u;
3452
125k
            if (is_big_v)
3453
18.5k
                divide_v = not_monotonic_by_v;
3454
125k
            if (!divide_u && !divide_v)
3455
118k
                pfs->monotonic_color = true;
3456
125k
        }
3457
1.95M
        if (pfs->monotonic_color && !pfs->linear_color) {
3458
1.91M
            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
1.91M
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3464
1.91M
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3465
1.88M
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3466
1.88M
                    if (code < 0)
3467
0
                        return code;
3468
1.88M
                    divide_u = !code;
3469
1.88M
                }
3470
1.91M
                if (is_big_v) {
3471
83.9k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3472
83.9k
                    if (code < 0)
3473
0
                        return code;
3474
83.9k
                    divide_v = !code;
3475
83.9k
                }
3476
1.91M
                if (is_big_u && is_big_v) {
3477
75.9k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3478
75.9k
                    if (code < 0)
3479
0
                        return code;
3480
75.9k
                    if (!code) {
3481
9.45k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3482
4.86k
                            divide_u = true;
3483
4.86k
                            divide_v = false;
3484
4.86k
                        } else {
3485
4.59k
                            divide_v = true;
3486
4.59k
                            divide_u = false;
3487
4.59k
                        }
3488
9.45k
                    }
3489
75.9k
                }
3490
1.91M
            }
3491
1.91M
            if (!divide_u && !divide_v)
3492
1.90M
                pfs->linear_color = true;
3493
1.91M
        }
3494
1.95M
        if (!pfs->linear_color) {
3495
            /* go to divide. */
3496
1.93M
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3497
96.1k
            case color_change_small:
3498
96.1k
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3499
82.5k
                            constant_color_quadrangle : triangles4)(pfs, p,
3500
96.1k
                                pfs->maybe_self_intersecting);
3501
96.1k
                pfs->monotonic_color = monotonic_color_save;
3502
96.1k
                pfs->linear_color = linear_color_save;
3503
96.1k
                return code;
3504
92.5k
            case color_change_bilinear:
3505
92.5k
                if (!QUADRANGLES) {
3506
92.5k
                    code = triangles4(pfs, p, true);
3507
92.5k
                    pfs->monotonic_color = monotonic_color_save;
3508
92.5k
                    pfs->linear_color = linear_color_save;
3509
92.5k
                    return code;
3510
92.5k
                }
3511
1.73M
            case color_change_linear:
3512
1.73M
                if (!QUADRANGLES) {
3513
1.73M
                    code = triangles2(pfs, p, true);
3514
1.73M
                    pfs->monotonic_color = monotonic_color_save;
3515
1.73M
                    pfs->linear_color = linear_color_save;
3516
1.73M
                    return code;
3517
1.73M
                }
3518
0
            case color_change_gradient:
3519
13.7k
            case color_change_general:
3520
13.7k
                ; /* goto divide. */
3521
1.93M
        }
3522
1.95M
    }
3523
34.6k
    if (!inside) {
3524
8.04k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3525
8.04k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3526
3.31k
            pfs->inside = true;
3527
8.04k
    }
3528
34.6k
    if (LAZY_WEDGES)
3529
34.6k
        init_wedge_vertex_list(&l0, 1);
3530
34.6k
    if (divide_v) {
3531
21.6k
        patch_color_t *c[2];
3532
21.6k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3533
3534
21.6k
        if(color_stack_ptr == NULL)
3535
0
            return_error(gs_error_unregistered); /* Must not happen. */
3536
21.6k
        q[0].c = c[0];
3537
21.6k
        q[1].c = c[1];
3538
21.6k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3539
21.6k
        if (LAZY_WEDGES) {
3540
21.6k
            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
21.6k
            if (code >= 0)
3542
21.6k
                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
21.6k
            if (code >= 0) {
3544
21.6k
                s0.l1110 = s1.l0001 = &l0;
3545
21.6k
                s0.l0111 = s1.l0111 = &l1;
3546
21.6k
                s0.l1000 = s1.l1000 = &l2;
3547
21.6k
                s0.l0001 = p->l0001;
3548
21.6k
                s1.l1110 = p->l1110;
3549
21.6k
            }
3550
21.6k
        } 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
21.6k
        if (code >= 0)
3556
21.6k
            code = fill_quadrangle(pfs, &s0, big1);
3557
21.6k
        if (code >= 0) {
3558
21.6k
            if (LAZY_WEDGES) {
3559
21.6k
                l0.last_side = true;
3560
21.6k
                move_wedge(&l1, p->l0111, true);
3561
21.6k
                move_wedge(&l2, p->l1000, false);
3562
21.6k
            }
3563
21.6k
            code = fill_quadrangle(pfs, &s1, big1);
3564
21.6k
        }
3565
21.6k
        if (LAZY_WEDGES) {
3566
21.6k
            if (code >= 0)
3567
21.6k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3568
21.6k
            if (code >= 0)
3569
21.6k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3570
21.6k
            if (code >= 0)
3571
21.6k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3572
21.6k
            release_colors_inline(pfs, color_stack_ptr, 2);
3573
21.6k
        }
3574
21.6k
    } else if (divide_u) {
3575
12.9k
        patch_color_t *c[2];
3576
12.9k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3577
3578
12.9k
        if(color_stack_ptr == NULL)
3579
0
            return_error(gs_error_unregistered); /* Must not happen. */
3580
12.9k
        q[0].c = c[0];
3581
12.9k
        q[1].c = c[1];
3582
12.9k
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3583
12.9k
        if (LAZY_WEDGES) {
3584
12.9k
            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
12.9k
            if (code >= 0)
3586
12.9k
                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
12.9k
            if (code >= 0) {
3588
12.9k
                s0.l0111 = s1.l1000 = &l0;
3589
12.9k
                s0.l0001 = s1.l0001 = &l1;
3590
12.9k
                s0.l1110 = s1.l1110 = &l2;
3591
12.9k
                s0.l1000 = p->l1000;
3592
12.9k
                s1.l0111 = p->l0111;
3593
12.9k
            }
3594
12.9k
        } 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
12.9k
        if (code >= 0)
3600
12.9k
            code = fill_quadrangle(pfs, &s0, big1);
3601
12.9k
        if (code >= 0) {
3602
12.9k
            if (LAZY_WEDGES) {
3603
12.9k
                l0.last_side = true;
3604
12.9k
                move_wedge(&l1, p->l0001, true);
3605
12.9k
                move_wedge(&l2, p->l1110, false);
3606
12.9k
            }
3607
12.9k
            code = fill_quadrangle(pfs, &s1, big1);
3608
12.9k
        }
3609
12.9k
        if (LAZY_WEDGES) {
3610
12.9k
            if (code >= 0)
3611
12.9k
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3612
12.9k
            if (code >= 0)
3613
12.9k
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3614
12.9k
            if (code >= 0)
3615
12.9k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3616
12.9k
            release_colors_inline(pfs, color_stack_ptr, 2);
3617
12.9k
        }
3618
12.9k
    } else
3619
0
        code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3620
0
                    constant_color_quadrangle : triangles4)(pfs, p,
3621
0
                        pfs->maybe_self_intersecting);
3622
34.6k
    pfs->monotonic_color = monotonic_color_save;
3623
34.6k
    pfs->linear_color = linear_color_save;
3624
34.6k
    pfs->inside = inside_save;
3625
34.6k
    return code;
3626
34.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
3.00M
{
3632
3.00M
    s0->c[0][1] = c[0];
3633
3.00M
    s0->c[1][1] = c[1];
3634
3.00M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3635
3.00M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3636
3.00M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3637
3.00M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3638
3.00M
    s0->c[0][0] = p->c[0][0];
3639
3.00M
    s0->c[1][0] = p->c[1][0];
3640
3.00M
    s1->c[0][0] = s0->c[0][1];
3641
3.00M
    s1->c[1][0] = s0->c[1][1];
3642
3.00M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3643
3.00M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3644
3.00M
    s1->c[0][1] = p->c[0][1];
3645
3.00M
    s1->c[1][1] = p->c[1][1];
3646
3.00M
}
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
550k
{
3652
550k
    s0->c[1][0] = c[0];
3653
550k
    s0->c[1][1] = c[1];
3654
550k
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3655
550k
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3656
550k
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3657
550k
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3658
550k
    s0->c[0][0] = p->c[0][0];
3659
550k
    s0->c[0][1] = p->c[0][1];
3660
550k
    s1->c[0][0] = s0->c[1][0];
3661
550k
    s1->c[0][1] = s0->c[1][1];
3662
550k
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3663
550k
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3664
550k
    s1->c[1][0] = p->c[1][0];
3665
550k
    s1->c[1][1] = p->c[1][1];
3666
550k
}
3667
3668
static inline void
3669
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3670
3.95M
{
3671
3.95M
    int i, j;
3672
3673
3.95M
    r->p.x = r->q.x = p->pole[0][0].x;
3674
3.95M
    r->p.y = r->q.y = p->pole[0][0].y;
3675
19.7M
    for (i = 0; i < 4; i++) {
3676
79.0M
        for (j = 0; j < 4; j++) {
3677
63.2M
            const gs_fixed_point *q = &p->pole[i][j];
3678
3679
63.2M
            if (r->p.x > q->x)
3680
10.1M
                r->p.x = q->x;
3681
63.2M
            if (r->p.y > q->y)
3682
10.8M
                r->p.y = q->y;
3683
63.2M
            if (r->q.x < q->x)
3684
11.2M
                r->q.x = q->x;
3685
63.2M
            if (r->q.y < q->y)
3686
9.51M
                r->q.y = q->y;
3687
63.2M
        }
3688
15.8M
    }
3689
3.95M
}
3690
3691
static int
3692
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3693
6.59M
{
3694
6.59M
    if (ku > 1) {
3695
4.43M
        tensor_patch s0, s1;
3696
4.43M
        patch_color_t *c[2];
3697
4.43M
        int code;
3698
4.43M
        byte *color_stack_ptr;
3699
4.43M
        bool save_inside = pfs->inside;
3700
3701
4.43M
        if (!pfs->inside) {
3702
3.39M
            gs_fixed_rect r, r1;
3703
3704
3.39M
            tensor_patch_bbox(&r, p);
3705
3.39M
            r1 = r;
3706
3.39M
            rect_intersect(r, pfs->rect);
3707
3.39M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3708
1.42M
                return 0;
3709
1.97M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3710
1.97M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3711
261k
                pfs->inside = true;
3712
1.97M
        }
3713
3.00M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3714
3.00M
        if(color_stack_ptr == NULL)
3715
0
            return_error(gs_error_unregistered); /* Must not happen. */
3716
3.00M
        split_stripe(pfs, &s0, &s1, p, c);
3717
3.00M
        code = decompose_stripe(pfs, &s0, ku / 2);
3718
3.00M
        if (code >= 0)
3719
3.00M
            code = decompose_stripe(pfs, &s1, ku / 2);
3720
3.00M
        release_colors_inline(pfs, color_stack_ptr, 2);
3721
3.00M
        pfs->inside = save_inside;
3722
3.00M
        return code;
3723
3.00M
    } else {
3724
2.16M
        quadrangle_patch q;
3725
2.16M
        shading_vertex_t qq[2][2];
3726
2.16M
        wedge_vertex_list_t l[4];
3727
2.16M
        int code;
3728
3729
2.16M
        init_wedge_vertex_list(l, count_of(l));
3730
2.16M
        make_quadrangle(p, qq, l, &q);
3731
#       if SKIP_TEST
3732
            dbg_quad_cnt++;
3733
#       endif
3734
2.16M
        code = fill_quadrangle(pfs, &q, true);
3735
2.16M
        if (code < 0)
3736
0
            return code;
3737
2.16M
        if (LAZY_WEDGES) {
3738
2.16M
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3739
2.16M
            if (code < 0)
3740
0
                return code;
3741
2.16M
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3742
2.16M
            if (code < 0)
3743
0
                return code;
3744
2.16M
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3745
2.16M
            if (code < 0)
3746
0
                return code;
3747
2.16M
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3748
2.16M
            if (code < 0)
3749
0
                return code;
3750
2.16M
        }
3751
2.16M
        return code;
3752
2.16M
    }
3753
6.59M
}
3754
3755
static int
3756
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3757
580k
{
3758
    /* The stripe is flattened enough by V, so ignore inner poles. */
3759
580k
    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
580k
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3768
580k
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3769
580k
    kum = max(ku[0], ku[3]);
3770
580k
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3771
580k
    if (code < 0)
3772
0
        return code;
3773
580k
    if (INTERPATCH_PADDING) {
3774
580k
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3775
580k
        if (code < 0)
3776
0
            return code;
3777
580k
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3778
580k
        if (code < 0)
3779
0
            return code;
3780
580k
    }
3781
580k
    code = decompose_stripe(pfs, p, kum);
3782
580k
    if (code < 0)
3783
0
        return code;
3784
580k
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3785
580k
}
3786
3787
static inline bool neqs(int *a, int b)
3788
1.48M
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3789
1.48M
    if (*a * b < 0)
3790
517k
        return true;
3791
963k
    if (!*a)
3792
8.21k
        *a = b;
3793
963k
    return false;
3794
1.48M
}
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
2.04M
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3799
2.04M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3800
2.04M
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3801
3802
2.04M
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3803
2.04M
}
3804
3805
static inline bool
3806
is_x_bended(const tensor_patch *p)
3807
562k
{
3808
562k
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3809
3810
562k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3811
307k
        return true;
3812
255k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3813
152k
        return true;
3814
103k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3815
55.7k
        return true;
3816
3817
47.6k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3818
316
        return true;
3819
47.3k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3820
0
        return true;
3821
47.3k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3822
178
        return true;
3823
47.1k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3824
284
        return true;
3825
3826
46.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3827
281
        return true;
3828
46.5k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3829
0
        return true;
3830
46.5k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3831
317
        return true;
3832
46.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3833
269
        return true;
3834
3835
45.9k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3836
92
        return true;
3837
45.9k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3838
0
        return true;
3839
45.9k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3840
62
        return true;
3841
45.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3842
38
        return true;
3843
45.8k
    return false;
3844
45.8k
}
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
3.40M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3890
3.40M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3891
3.40M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3892
3.40M
    fixed xmin =  min(xmin0, xmin1);
3893
3.40M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3894
3.40M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3895
3.40M
    fixed xmax =  max(xmax0, xmax1);
3896
3897
3.40M
    if(xmax - xmin <= pfs->decomposition_limit)
3898
2.94M
        return true;
3899
455k
    return false;
3900
3.40M
}
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
2.37M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3905
2.37M
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3906
2.37M
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3907
2.37M
    fixed ymin =  min(ymin0, ymin1);
3908
2.37M
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3909
2.37M
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3910
2.37M
    fixed ymax =  max(ymax0, ymax1);
3911
3912
2.37M
    if (ymax - ymin <= pfs->decomposition_limit)
3913
2.26M
        return true;
3914
107k
    return false;
3915
2.37M
}
3916
3917
static inline bool
3918
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3919
1.09M
{
3920
1.09M
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3921
211k
        return false;
3922
885k
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3923
141k
        return false;
3924
744k
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3925
71.3k
        return false;
3926
672k
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3927
30.8k
        return false;
3928
641k
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3929
35.5k
        return false;
3930
606k
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3931
34.1k
        return false;
3932
572k
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3933
21.0k
        return false;
3934
551k
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3935
16.4k
        return false;
3936
534k
    return true;
3937
551k
}
3938
3939
static int
3940
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3941
1.14M
{
3942
1.14M
    if (kv <= 1) {
3943
1.09M
        if (is_patch_narrow(pfs, p))
3944
534k
            return fill_stripe(pfs, p);
3945
562k
        if (!is_x_bended(p))
3946
45.8k
            return fill_stripe(pfs, p);
3947
562k
    }
3948
567k
    {   tensor_patch s0, s1;
3949
567k
        patch_color_t *c[2];
3950
567k
        shading_vertex_t q0, q1, q2;
3951
567k
        int code = 0;
3952
567k
        byte *color_stack_ptr;
3953
567k
        bool save_inside = pfs->inside;
3954
3955
567k
        if (!pfs->inside) {
3956
551k
            gs_fixed_rect r, r1;
3957
3958
551k
            tensor_patch_bbox(&r, p);
3959
551k
            r.p.x -= INTERPATCH_PADDING;
3960
551k
            r.p.y -= INTERPATCH_PADDING;
3961
551k
            r.q.x += INTERPATCH_PADDING;
3962
551k
            r.q.y += INTERPATCH_PADDING;
3963
551k
            r1 = r;
3964
551k
            rect_intersect(r, pfs->rect);
3965
551k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3966
17.1k
                return 0;
3967
534k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3968
534k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3969
6.47k
                pfs->inside = true;
3970
534k
        }
3971
550k
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3972
550k
        if(color_stack_ptr == NULL)
3973
0
            return_error(gs_error_unregistered); /* Must not happen. */
3974
550k
        split_patch(pfs, &s0, &s1, p, c);
3975
550k
        if (kv0 <= 1) {
3976
523k
            q0.p = s0.pole[0][0];
3977
523k
            q0.c = s0.c[0][0];
3978
523k
            q1.p = s1.pole[3][0];
3979
523k
            q1.c = s1.c[1][0];
3980
523k
            q2.p = s0.pole[3][0];
3981
523k
            q2.c = s0.c[1][0];
3982
523k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3983
523k
        }
3984
550k
        if (kv1 <= 1 && code >= 0) {
3985
524k
            q0.p = s0.pole[0][3];
3986
524k
            q0.c = s0.c[0][1];
3987
524k
            q1.p = s1.pole[3][3];
3988
524k
            q1.c = s1.c[1][1];
3989
524k
            q2.p = s0.pole[3][3];
3990
524k
            q2.c = s0.c[1][1];
3991
524k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3992
524k
        }
3993
550k
        if (code >= 0)
3994
550k
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
3995
550k
        if (code >= 0)
3996
550k
            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
550k
        release_colors_inline(pfs, color_stack_ptr, 2);
4017
550k
        pfs->inside = save_inside;
4018
550k
        return code;
4019
550k
    }
4020
550k
}
4021
4022
static inline int64_t
4023
lcp1(int64_t p0, int64_t p3)
4024
291k
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4025
291k
    return (p0 + p0 + p3);
4026
291k
}
4027
static inline int64_t
4028
lcp2(int64_t p0, int64_t p3)
4029
291k
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4030
291k
    return (p0 + p3 + p3);
4031
291k
}
4032
4033
static void
4034
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4035
188k
{
4036
188k
    if (pfs->Function) {
4037
58.2k
        c->t[0] = cc[0];
4038
58.2k
        c->t[1] = cc[1];
4039
58.2k
    } else
4040
130k
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4041
188k
}
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
47.1k
{
4047
47.1k
    const gs_color_space *pcs = pfs->direct_space;
4048
4049
47.1k
    p->pole[0][0] = curve[0].vertex.p;
4050
47.1k
    p->pole[1][0] = curve[0].control[0];
4051
47.1k
    p->pole[2][0] = curve[0].control[1];
4052
47.1k
    p->pole[3][0] = curve[1].vertex.p;
4053
47.1k
    p->pole[3][1] = curve[1].control[0];
4054
47.1k
    p->pole[3][2] = curve[1].control[1];
4055
47.1k
    p->pole[3][3] = curve[2].vertex.p;
4056
47.1k
    p->pole[2][3] = curve[2].control[0];
4057
47.1k
    p->pole[1][3] = curve[2].control[1];
4058
47.1k
    p->pole[0][3] = curve[3].vertex.p;
4059
47.1k
    p->pole[0][2] = curve[3].control[0];
4060
47.1k
    p->pole[0][1] = curve[3].control[1];
4061
47.1k
    if (interior != NULL) {
4062
32.5k
        p->pole[1][1] = interior[0];
4063
32.5k
        p->pole[1][2] = interior[1];
4064
32.5k
        p->pole[2][2] = interior[2];
4065
32.5k
        p->pole[2][1] = interior[3];
4066
32.5k
    } else {
4067
14.5k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4068
14.5k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4069
14.5k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4070
14.5k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4071
14.5k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4072
14.5k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4073
14.5k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4074
14.5k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4075
14.5k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4076
14.5k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4077
14.5k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4078
14.5k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4079
14.5k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4080
14.5k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4081
14.5k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4082
14.5k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4083
4084
14.5k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4085
14.5k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4086
14.5k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4087
14.5k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4088
14.5k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4089
14.5k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4090
14.5k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4091
14.5k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4092
14.5k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4093
14.5k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4094
14.5k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4095
14.5k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4096
14.5k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4097
14.5k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4098
14.5k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4099
14.5k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4100
14.5k
    }
4101
47.1k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4102
47.1k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4103
47.1k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4104
47.1k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4105
47.1k
    patch_resolve_color_inline(p->c[0][0], pfs);
4106
47.1k
    patch_resolve_color_inline(p->c[0][1], pfs);
4107
47.1k
    patch_resolve_color_inline(p->c[1][0], pfs);
4108
47.1k
    patch_resolve_color_inline(p->c[1][1], pfs);
4109
47.1k
    if (!pfs->Function) {
4110
32.5k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4111
32.5k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4112
32.5k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4113
32.5k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4114
32.5k
    }
4115
47.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
1
{
4121
1
    gs_fixed_edge le, re;
4122
4123
1
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4124
1
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4125
1
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4126
1
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4127
1
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4128
1
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4129
1
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4130
1
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4131
1
    return dev_proc(pdev, fill_trapezoid)(pdev,
4132
1
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4133
1
}
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
47.1k
{
4141
47.1k
    tensor_patch p;
4142
47.1k
    patch_color_t *c[4];
4143
47.1k
    int kv[4], kvm, ku[4], kum;
4144
47.1k
    int code = 0;
4145
47.1k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4146
4147
47.1k
    p.c[0][0] = c[0];
4148
47.1k
    p.c[0][1] = c[1];
4149
47.1k
    p.c[1][0] = c[2];
4150
47.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
47.1k
    make_tensor_patch(pfs, &p, curve, interior);
4159
47.1k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4160
47.1k
    pfs->linear_color = false;
4161
47.1k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4162
47.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
47.1k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4210
47.1k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4211
47.1k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4212
47.1k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4213
47.1k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4214
47.1k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4215
47.1k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4216
47.1k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4217
47.1k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4218
47.1k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4219
#   if NOFILL_TEST
4220
    dbg_nofill = false;
4221
#   endif
4222
47.1k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4223
47.1k
        interpatch_padding | inpatch_wedge);
4224
47.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
47.1k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4237
47.1k
    }
4238
47.1k
    if (code >= 0)
4239
47.1k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4240
47.1k
                interpatch_padding | inpatch_wedge);
4241
47.1k
out:
4242
47.1k
    release_colors_inline(pfs, color_stack_ptr, 4);
4243
47.1k
    return code;
4244
47.1k
}