Coverage Report

Created: 2025-08-28 07:06

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