Coverage Report

Created: 2026-02-14 07:09

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