Coverage Report

Created: 2025-06-10 07:27

/src/ghostpdl/base/gxshade6.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Rendering for Coons and tensor patch shadings */
18
/*
19
   A contiguous non-overlapping decomposition
20
   of a tensor shading into linear color triangles.
21
 */
22
#include "memory_.h"
23
#include "gx.h"
24
#include "gserrors.h"
25
#include "gsmatrix.h"           /* for gscoord.h */
26
#include "gscoord.h"
27
#include "gscicach.h"
28
#include "gxcspace.h"
29
#include "gxdcolor.h"
30
#include "gxgstate.h"
31
#include "gxshade.h"
32
#include "gxdevcli.h"
33
#include "gxshade4.h"
34
#include "gxarith.h"
35
#include "gzpath.h"
36
#include "stdint_.h"
37
#include "math_.h"
38
#include "gsicc_cache.h"
39
#include "gxdevsop.h"
40
41
/* The original version of the shading code 'decompose's shadings into
42
 * smaller and smaller regions until they are smaller than 1 pixel, and then
43
 * fills them. (Either with a constant colour, or with a linear filled trap).
44
 *
45
 * Previous versions of the code (from svn revision 7936 until June 2011
46
 * (shortly after the switch to git)) changed this limit to be 1 point or 1
47
 * pixel (whichever is larger) (on the grounds that as resolution increases,
48
 * we are unlikely to be able to notice increasingly small inaccuracies in
49
 * the shading). Given how people abuse the resolution at which things are
50
 * rendered (especially when rendering to images that can subsequently be
51
 * zoomed), this seems a poor trade off. See bug 691152.
52
 *
53
 * The code has now been changed back to operate with the proper 1 pixel
54
 * decomposition, which will cost us performance in some cases. Should
55
 * people want to restore the previous operation, they should build with
56
 * MAX_SHADING_RESOLUTION predefined to 72. In general, this symbol can be
57
 * set to the maximum dpi that shading should ever be performed at. Leaving
58
 * it undefined will leave the default (1 pixel limit) in place.
59
 *
60
 * A possible future optimisation here may be to use different max shading
61
 * resolutions for linear and non-linear shadings; linear shadings appear to
62
 * result in calls to "fill linear traps", and non linear ones appear to
63
 * result in calls to "fill constant color". As such linear shadings are much
64
 * more forgiving of a higher decomposition threshold.
65
 */
66
67
#if NOFILL_TEST
68
static bool dbg_nofill = false;
69
#endif
70
#if SKIP_TEST
71
static int dbg_patch_cnt = 0;
72
static int dbg_quad_cnt = 0;
73
static int dbg_triangle_cnt = 0;
74
static int dbg_wedge_triangle_cnt = 0;
75
#endif
76
77
enum {
78
    min_linear_grades = 255 /* The minimal number of device color grades,
79
            required to apply linear color device functions. */
80
};
81
82
/* ================ Utilities ================ */
83
84
static int
85
allocate_color_stack(patch_fill_state_t *pfs, gs_memory_t *memory)
86
137k
{
87
137k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
137k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
137k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
137k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
137k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
137k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
137k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
137k
    pfs->color_stack_ptr = pfs->color_stack;
98
137k
    pfs->memory = memory;
99
137k
    return 0;
100
137k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
213M
{
105
213M
    int i;
106
213M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
682M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
468M
        c[i] = (patch_color_t *)ptr;
110
213M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
213M
    pfs->color_stack_ptr = ptr;
115
213M
    return ptr0;
116
213M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
698
{
121
698
    return reserve_colors_inline(pfs, c, n);
122
698
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
213M
{
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
213M
    pfs->color_stack_ptr = ptr;
132
213M
#endif
133
213M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
698
{
137
698
    release_colors_inline(pfs, ptr, n);
138
698
}
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
634k
{
145
634k
    int i, code = 0;
146
147
2.66M
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
2.03M
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
2.03M
        code = shade_next_color(cs, curves[i].vertex.cc);
150
2.03M
    }
151
634k
    return code;
152
634k
}
153
154
/* Get a Bezier or tensor patch element. */
155
static int
156
shade_next_curve(shade_coord_stream_t * cs, patch_curve_t * curve)
157
1.65M
{
158
1.65M
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
1.65M
    if (code >= 0)
161
1.65M
        code = shade_next_coords(cs, curve->control,
162
1.65M
                                 countof(curve->control));
163
1.65M
    return code;
164
1.65M
}
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
635k
{
174
635k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
635k
    int num_colors, code;
176
177
635k
    if (flag < 0) {
178
1.05k
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
1.05k
        return 1;               /* no more data */
181
1.05k
    }
182
634k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
634k
    cs->first_patch = 0;
186
634k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
382k
        case 0:
190
382k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
382k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
382k
                )
193
53
                return code;
194
382k
            num_colors = 4;
195
382k
            goto vx;
196
69.9k
        case 1:
197
69.9k
            curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
198
69.9k
            goto v3;
199
74.4k
        case 2:
200
74.4k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
74.4k
            goto v3;
202
107k
        case 3:
203
107k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
252k
v3:         num_colors = 2;
205
634k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
634k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
634k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
634k
                (interior != 0 &&
209
634k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
634k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
634k
                                          num_colors)) < 0
212
634k
                )
213
636
                return code;
214
633k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
634k
    }
216
633k
    return 0;
217
634k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
9.70M
{
222
9.70M
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
9.70M
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
5.48M
        return false;
226
4.21M
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
395k
        return false;
228
3.82M
    return true;
229
4.21M
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
137k
{
234
137k
    int code;
235
236
137k
    pfs->memory = memory;
237
137k
#   if LAZY_WEDGES
238
137k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
137k
        if (code < 0)
240
0
            return code;
241
137k
#   endif
242
137k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
137k
    code = allocate_color_stack(pfs, memory);
244
137k
    if (code < 0)
245
0
        return code;
246
137k
    if (pfs->unlinear || pcs == NULL)
247
12.6k
        pfs->pcic = NULL;
248
125k
    else {
249
125k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
125k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
125k
    }
253
137k
    return 0;
254
137k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
137k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
137k
    const gs_color_space *pcs = pfs->direct_space;
261
137k
    gs_client_color fcc0, fcc1;
262
137k
    int i;
263
264
529k
    for (i = 0; i < pfs->num_components; i++) {
265
392k
        fcc0.paint.values[i] = -1000000;
266
392k
        fcc1.paint.values[i] = 1000000;
267
392k
    }
268
137k
    pcs->type->restrict_color(&fcc0, pcs);
269
137k
    pcs->type->restrict_color(&fcc1, pcs);
270
529k
    for (i = 0; i < pfs->num_components; i++)
271
392k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
137k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
137k
    pfs->maybe_self_intersecting = true;
274
137k
    pfs->monotonic_color = (pfs->Function == NULL);
275
137k
    pfs->function_arg_shift = 0;
276
137k
    pfs->linear_color = false;
277
137k
    pfs->inside = false;
278
137k
    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
137k
    pfs->decomposition_limit = fixed_1;
285
137k
#endif
286
137k
    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
137k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
137k
    pfs->color_stack_size = 0;
293
137k
    pfs->color_stack_step = 0;
294
137k
    pfs->color_stack_ptr = NULL;
295
137k
    pfs->color_stack = NULL;
296
137k
    pfs->color_stack_limit = NULL;
297
137k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
137k
    pfs->pcic = NULL;
299
137k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
137k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
137k
{
305
137k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
137k
#   if LAZY_WEDGES
307
137k
        wedge_vertex_list_elem_buffer_free(pfs);
308
137k
#   endif
309
137k
    if (pfs->color_stack)
310
137k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
137k
    if (pfs->pcic != NULL)
312
125k
        gs_color_index_cache_destroy(pfs->pcic);
313
137k
    return b;
314
137k
}
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
96.6M
{
320
96.6M
    if (pfs->Function) {
321
94.1M
        const gs_color_space *pcs = pfs->direct_space;
322
323
94.1M
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
94.1M
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
94.1M
    }
326
96.6M
}
327
328
void
329
patch_resolve_color(patch_color_t * ppcr, const patch_fill_state_t *pfs)
330
0
{
331
0
    patch_resolve_color_inline(ppcr, pfs);
332
0
}
333
334
/*
335
 * Calculate the interpolated color at a given point.
336
 * Note that we must do this twice for bilinear interpolation.
337
 * We use the name ppcr rather than ppc because an Apple compiler defines
338
 * ppc when compiling on PowerPC systems (!).
339
 */
340
static void
341
patch_interpolate_color(patch_color_t * ppcr, const patch_color_t * ppc0,
342
       const patch_color_t * ppc1, const patch_fill_state_t *pfs, double t)
343
255M
{
344
    /* The old code gives -IND on Intel. */
345
255M
    if (pfs->Function) {
346
62.3M
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
62.3M
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
62.3M
        patch_resolve_color_inline(ppcr, pfs);
349
193M
    } else {
350
193M
        int ci;
351
352
924M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
730M
            ppcr->cc.paint.values[ci] =
354
730M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
193M
    }
356
255M
}
357
358
/* ================ Specific shadings ================ */
359
360
/*
361
 * The curves are stored in a clockwise or counter-clockwise order that maps
362
 * to the patch definition in a non-intuitive way.  The documentation
363
 * (pp. 277-281 of the PostScript Language Reference Manual, Third Edition)
364
 * says that the curves are in the order D1, C2, D2, C1.
365
 */
366
/* The starting points of the curves: */
367
0
#define D1START 0
368
0
#define C2START 1
369
0
#define D2START 3
370
0
#define C1START 0
371
/* The control points of the curves (x means reversed order): */
372
0
#define D1CTRL 0
373
0
#define C2CTRL 1
374
0
#define D2XCTRL 2
375
0
#define C1XCTRL 3
376
/* The end points of the curves: */
377
0
#define D1END 1
378
0
#define C2END 2
379
0
#define D2END 2
380
0
#define C1END 3
381
382
/* ---------------- Common code ---------------- */
383
384
/* Evaluate a curve at a given point. */
385
static void
386
curve_eval(gs_fixed_point * pt, const gs_fixed_point * p0,
387
           const gs_fixed_point * p1, const gs_fixed_point * p2,
388
           const gs_fixed_point * p3, double t)
389
0
{
390
0
    fixed a, b, c, d;
391
0
    fixed t01, t12;
392
393
0
    d = p0->x;
394
0
    curve_points_to_coefficients(d, p1->x, p2->x, p3->x,
395
0
                                 a, b, c, t01, t12);
396
0
    pt->x = (fixed) (((a * t + b) * t + c) * t + d);
397
0
    d = p0->y;
398
0
    curve_points_to_coefficients(d, p1->y, p2->y, p3->y,
399
0
                                 a, b, c, t01, t12);
400
0
    pt->y = (fixed) (((a * t + b) * t + c) * t + d);
401
0
    if_debug3('2', "[2]t=%g => (%g,%g)\n", t, fixed2float(pt->x),
402
0
              fixed2float(pt->y));
403
0
}
404
405
/* ---------------- Coons patch shading ---------------- */
406
407
/* Calculate the device-space coordinate corresponding to (u,v). */
408
static void
409
Cp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
410
             const gs_fixed_point ignore_interior[4], double u, double v)
411
0
{
412
0
    double co_u = 1.0 - u, co_v = 1.0 - v;
413
0
    gs_fixed_point c1u, d1v, c2u, d2v;
414
415
0
    curve_eval(&c1u, &curve[C1START].vertex.p,
416
0
               &curve[C1XCTRL].control[1], &curve[C1XCTRL].control[0],
417
0
               &curve[C1END].vertex.p, u);
418
0
    curve_eval(&d1v, &curve[D1START].vertex.p,
419
0
               &curve[D1CTRL].control[0], &curve[D1CTRL].control[1],
420
0
               &curve[D1END].vertex.p, v);
421
0
    curve_eval(&c2u, &curve[C2START].vertex.p,
422
0
               &curve[C2CTRL].control[0], &curve[C2CTRL].control[1],
423
0
               &curve[C2END].vertex.p, u);
424
0
    curve_eval(&d2v, &curve[D2START].vertex.p,
425
0
               &curve[D2XCTRL].control[1], &curve[D2XCTRL].control[0],
426
0
               &curve[D2END].vertex.p, v);
427
0
#define COMPUTE_COORD(xy)\
428
0
    pt->xy = (fixed)\
429
0
        ((co_v * c1u.xy + v * c2u.xy) + (co_u * d1v.xy + u * d2v.xy) -\
430
0
         (co_v * (co_u * curve[C1START].vertex.p.xy +\
431
0
                  u * curve[C1END].vertex.p.xy) +\
432
0
          v * (co_u * curve[C2START].vertex.p.xy +\
433
0
               u * curve[C2END].vertex.p.xy)))
434
0
    COMPUTE_COORD(x);
435
0
    COMPUTE_COORD(y);
436
0
#undef COMPUTE_COORD
437
0
    if_debug4('2', "[2](u=%g,v=%g) => (%g,%g)\n",
438
0
              u, v, fixed2float(pt->x), fixed2float(pt->y));
439
0
}
440
441
int
442
gs_shading_Cp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
443
                             const gs_fixed_rect * rect_clip,
444
                             gx_device * dev, gs_gstate * pgs)
445
49
{
446
49
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
49
    patch_fill_state_t state;
448
49
    shade_coord_stream_t cs;
449
49
    patch_curve_t curve[4];
450
49
    int code;
451
452
49
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
49
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
49
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
49
    state.Function = psh->params.Function;
459
49
    code = init_patch_fill_state(&state);
460
49
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
49
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
49
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
228
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
228
                                    curve, NULL)) == 0 &&
469
228
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
179
        ) {
471
179
        DO_NOTHING;
472
179
    }
473
49
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
49
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
49
    return min(code, 0);
477
49
}
478
479
/* ---------------- Tensor product patch shading ---------------- */
480
481
/* Calculate the device-space coordinate corresponding to (u,v). */
482
static void
483
Tpp_transform(gs_fixed_point * pt, const patch_curve_t curve[4],
484
              const gs_fixed_point interior[4], double u, double v)
485
0
{
486
0
    double Bu[4], Bv[4];
487
0
    gs_fixed_point pts[4][4];
488
0
    int i, j;
489
0
    double x = 0, y = 0;
490
491
    /* Compute the Bernstein polynomials of u and v. */
492
0
    {
493
0
        double u2 = u * u, co_u = 1.0 - u, co_u2 = co_u * co_u;
494
0
        double v2 = v * v, co_v = 1.0 - v, co_v2 = co_v * co_v;
495
496
0
        Bu[0] = co_u * co_u2, Bu[1] = 3 * u * co_u2,
497
0
            Bu[2] = 3 * u2 * co_u, Bu[3] = u * u2;
498
0
        Bv[0] = co_v * co_v2, Bv[1] = 3 * v * co_v2,
499
0
            Bv[2] = 3 * v2 * co_v, Bv[3] = v * v2;
500
0
    }
501
502
    /* Arrange the points into an indexable order. */
503
0
    pts[0][0] = curve[0].vertex.p;
504
0
    pts[0][1] = curve[0].control[0];
505
0
    pts[0][2] = curve[0].control[1];
506
0
    pts[0][3] = curve[1].vertex.p;
507
0
    pts[1][3] = curve[1].control[0];
508
0
    pts[2][3] = curve[1].control[1];
509
0
    pts[3][3] = curve[2].vertex.p;
510
0
    pts[3][2] = curve[2].control[0];
511
0
    pts[3][1] = curve[2].control[1];
512
0
    pts[3][0] = curve[3].vertex.p;
513
0
    pts[2][0] = curve[3].control[0];
514
0
    pts[1][0] = curve[3].control[1];
515
0
    pts[1][1] = interior[0];
516
0
    pts[2][1] = interior[1];
517
0
    pts[2][2] = interior[2];
518
0
    pts[1][2] = interior[3];
519
520
    /* Now compute the actual point. */
521
0
    for (i = 0; i < 4; ++i)
522
0
        for (j = 0; j < 4; ++j) {
523
0
            double coeff = Bu[i] * Bv[j];
524
525
0
            x += pts[i][j].x * coeff, y += pts[i][j].y * coeff;
526
0
        }
527
0
    pt->x = (fixed)x, pt->y = (fixed)y;
528
0
}
529
530
int
531
gs_shading_Tpp_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
532
                             const gs_fixed_rect * rect_clip,
533
                              gx_device * dev, gs_gstate * pgs)
534
1.69k
{
535
1.69k
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
1.69k
    patch_fill_state_t state;
537
1.69k
    shade_coord_stream_t cs;
538
1.69k
    patch_curve_t curve[4];
539
1.69k
    gs_fixed_point interior[4];
540
1.69k
    int code;
541
542
1.69k
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
1.69k
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
1.69k
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
1.69k
    state.Function = psh->params.Function;
549
1.69k
    code = init_patch_fill_state(&state);
550
1.69k
    if(code < 0)
551
0
        return code;
552
1.69k
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
1.69k
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
635k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
635k
                                    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
633k
        gs_fixed_point swapped_interior[4];
561
562
633k
        swapped_interior[0] = interior[0];
563
633k
        swapped_interior[1] = interior[3];
564
633k
        swapped_interior[2] = interior[2];
565
633k
        swapped_interior[3] = interior[1];
566
633k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
633k
        if (code < 0)
568
0
            break;
569
633k
    }
570
1.69k
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
1.69k
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
1.69k
    return min(code, 0);
574
1.69k
}
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
137k
{
665
137k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
137k
    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
137k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
137k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
137k
            sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
681
137k
            "alloc_wedge_vertex_list_elem_buffer");
682
137k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
137k
    pfs->free_wedge_vertex = NULL;
685
137k
    pfs->wedge_vertex_list_elem_count = 0;
686
137k
    return 0;
687
137k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
137k
{
692
137k
    gs_memory_t *memory = pfs->memory;
693
694
137k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
137k
                "wedge_vertex_list_elem_buffer_free");
696
137k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
137k
    pfs->free_wedge_vertex = NULL;
698
137k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
25.5M
{
703
25.5M
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
25.5M
    if (e != NULL) {
706
24.6M
        pfs->free_wedge_vertex = e->next;
707
24.6M
        return e;
708
24.6M
    }
709
837k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
837k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
837k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
25.5M
{
717
25.5M
    e->next = pfs->free_wedge_vertex;
718
25.5M
    pfs->free_wedge_vertex = e;
719
25.5M
}
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
13.5M
{
725
13.5M
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
13.5M
    beg->next = end;
728
13.5M
    end->prev = beg;
729
26.0M
    for (; e != end; e = ee) {
730
12.4M
        ee = e->next;
731
12.4M
        wedge_vertex_list_elem_release(pfs, e);
732
12.4M
    }
733
13.5M
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
6.52M
{
738
6.52M
    int i;
739
740
13.0M
    for (i = 0; i < n; i++) {
741
6.52M
        wedge_vertex_list_t *l = ll + i;
742
743
6.52M
        if (l->beg != NULL) {
744
6.52M
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
6.52M
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
6.52M
            wedge_vertex_list_elem_release(pfs, l->beg);
748
6.52M
            wedge_vertex_list_elem_release(pfs, l->end);
749
6.52M
            l->beg = l->end = NULL;
750
6.52M
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
6.52M
    }
753
6.52M
    return 0;
754
6.52M
}
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
8.42M
{
760
8.42M
    wedge_vertex_list_elem_t *e = beg;
761
762
8.42M
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
22.9M
    for (; e != end; e = e->next)
765
22.9M
        if (e->level == level)
766
8.42M
            return e;
767
0
    return NULL;
768
8.42M
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
55.5M
{
773
55.5M
    memset(l, 0, sizeof(*l) * n);
774
55.5M
}
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
24.2M
{
785
24.2M
    curve_segment s;
786
24.2M
    int k;
787
788
24.2M
    s.p1.x = pole[pole_step].x;
789
24.2M
    s.p1.y = pole[pole_step].y;
790
24.2M
    s.p2.x = pole[pole_step * 2].x;
791
24.2M
    s.p2.y = pole[pole_step * 2].y;
792
24.2M
    s.pt.x = pole[pole_step * 3].x;
793
24.2M
    s.pt.y = pole[pole_step * 3].y;
794
24.2M
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
24.2M
    {
796
24.2M
#       if LAZY_WEDGES || QUADRANGLES
797
24.2M
            int k1;
798
24.2M
            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
24.2M
                      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
24.2M
                      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
24.2M
#       endif
802
803
24.2M
#       if LAZY_WEDGES
804
            /* Restrict lengths for a reasonable memory consumption : */
805
24.2M
            k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
806
24.2M
            k = max(k, k1);
807
24.2M
#       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
24.2M
    }
813
24.2M
    return 1 << k;
814
24.2M
}
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
107M
{
826
107M
    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
45.3M
        *b += fixed_epsilon;
836
45.3M
    }
837
107M
}
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
23.9M
{
844
23.9M
    if (!orient) {
845
13.5M
        le->start = q[vi0];
846
13.5M
        le->end = q[vi1];
847
13.5M
        re->start = q[vi2];
848
13.5M
        re->end = q[vi3];
849
13.5M
    } else {
850
10.4M
        le->start = q[vi2];
851
10.4M
        le->end = q[vi3];
852
10.4M
        re->start = q[vi0];
853
10.4M
        re->end = q[vi1];
854
10.4M
    }
855
23.9M
    adjust_swapped_boundary(&re->start.x, swap_axes);
856
23.9M
    adjust_swapped_boundary(&re->end.x, swap_axes);
857
23.9M
}
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.72M
{
864
1.72M
    gs_fixed_edge le, re;
865
1.72M
    int code;
866
1.72M
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
867
1.72M
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
868
1.72M
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
869
1.72M
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
870
871
1.72M
    if (ybot >= ytop)
872
619k
        return 0;
873
#   if NOFILL_TEST
874
        if (dbg_nofill)
875
            return 0;
876
#   endif
877
1.10M
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
878
1.10M
    if (!pfs->inside) {
879
455k
        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
455k
        if (le.start.x > xright) {
890
48.0k
            if (le.end.x > xright) {
891
110
                return 0;
892
110
            }
893
47.9k
            clip = true;
894
407k
        } else if (le.end.x > xright) {
895
30.9k
            clip = true;
896
30.9k
        }
897
455k
        if (le.start.x < xleft) {
898
154k
            if (le.end.x < xleft) {
899
55.1k
                le.start.x = xleft;
900
55.1k
                le.end.x   = xleft;
901
55.1k
                le.start.y = ybot;
902
55.1k
                le.end.y   = ytop;
903
99.0k
            } else {
904
99.0k
                clip = true;
905
99.0k
            }
906
301k
        } else if (le.end.x < xleft) {
907
80.3k
            clip = true;
908
80.3k
        }
909
455k
        if (re.start.x < xleft) {
910
35.4k
            if (re.end.x < xleft) {
911
38
                return 0;
912
38
            }
913
35.4k
            clip = true;
914
420k
        } else if (re.end.x < xleft) {
915
47.4k
            clip = true;
916
47.4k
        }
917
455k
        if (re.start.x > xright) {
918
126k
            if (re.end.x > xright) {
919
44.6k
                re.start.x = xright;
920
44.6k
                re.end.x   = xright;
921
44.6k
                re.start.y = ybot;
922
44.6k
                re.end.y   = ytop;
923
81.5k
            } else {
924
81.5k
                clip = true;
925
81.5k
            }
926
329k
        } else if (re.end.x > xright) {
927
97.0k
            clip = true;
928
97.0k
        }
929
455k
        if (clip)
930
281k
        {
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
281k
            gs_fixed_edge lenew, renew;
935
281k
            fixed ybl, ybr, ytl, ytr, ymid;
936
937
            /* Reduce the clipping region horizontally if possible. */
938
281k
            if (re.start.x > re.end.x) {
939
108k
                if (re.start.x < xright)
940
26.5k
                    xright = re.start.x;
941
173k
            } else if (re.end.x < xright)
942
34.1k
                xright = re.end.x;
943
281k
            if (le.start.x > le.end.x) {
944
107k
                if (le.end.x > xleft)
945
27.5k
                    xleft = le.end.x;
946
173k
            } else if (le.start.x > xleft)
947
30.1k
                xleft = le.start.x;
948
949
281k
            ybot = max(ybot, min(le.start.y, re.start.y));
950
281k
            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
281k
            if (ybot >= ytop)
987
0
                return 0;
988
            /* Follow the edges in, so that le.start.y == ybot etc. */
989
281k
            if (le.start.y < ybot) {
990
140k
                int round = ((le.end.x < le.start.x) ?
991
74.8k
                             (le.end.y-le.start.y-1) : 0);
992
140k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
993
140k
                                       (int64_t)(le.end.x-le.start.x)-round)/
994
140k
                                      (int64_t)(le.end.y-le.start.y));
995
140k
                le.start.y = ybot;
996
140k
            }
997
281k
            if (le.end.y > ytop) {
998
142k
                int round = ((le.end.x > le.start.x) ?
999
106k
                             (le.end.y-le.start.y-1) : 0);
1000
142k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1001
142k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1002
142k
                                    (int64_t)(le.end.y-le.start.y));
1003
142k
                le.end.y = ytop;
1004
142k
            }
1005
281k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1006
105k
                le.start.x = xleft;
1007
105k
                le.end.x   = xleft;
1008
105k
                le.start.y = ybot;
1009
105k
                le.end.y   = ytop;
1010
105k
            }
1011
281k
            if (re.start.y < ybot) {
1012
142k
                int round = ((re.end.x > re.start.x) ?
1013
106k
                             (re.end.y-re.start.y-1) : 0);
1014
142k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1015
142k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1016
142k
                                      (int64_t)(re.end.y-re.start.y));
1017
142k
                re.start.y = ybot;
1018
142k
            }
1019
281k
            if (re.end.y > ytop) {
1020
144k
                int round = ((re.end.x < re.start.x) ?
1021
74.8k
                             (re.end.y-re.start.y-1) : 0);
1022
144k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1023
144k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1024
144k
                                    (int64_t)(re.end.y-re.start.y));
1025
144k
                re.end.y = ytop;
1026
144k
            }
1027
281k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1028
38.3k
                re.start.x = xright;
1029
38.3k
                re.end.x   = xright;
1030
38.3k
                re.start.y = ybot;
1031
38.3k
                re.end.y   = ytop;
1032
38.3k
            }
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
281k
            if (le.start.x > re.start.x) {
1039
64.3k
                if (le.start.x == le.end.x) {
1040
31.1k
                    if (re.start.x == re.end.x)
1041
0
                        return 0;
1042
31.1k
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1043
31.1k
                                    (int64_t)(le.start.x-re.start.x)/
1044
31.1k
                                    (int64_t)(re.end.x-re.start.x));
1045
31.1k
                    re.start.x = le.start.x;
1046
33.1k
                } else {
1047
33.1k
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1048
33.1k
                                    (int64_t)(le.start.x-re.start.x)/
1049
33.1k
                                    (int64_t)(le.start.x-le.end.x));
1050
33.1k
                    le.start.x = re.start.x;
1051
33.1k
                }
1052
64.3k
                if (ybot >= ytop)
1053
21.9k
                    return 0;
1054
42.3k
                le.start.y = ybot;
1055
42.3k
                re.start.y = ybot;
1056
42.3k
            }
1057
259k
            if (le.end.x > re.end.x) {
1058
41.8k
                if (le.start.x == le.end.x) {
1059
25.6k
                    if (re.start.x == re.end.x)
1060
0
                        return 0;
1061
25.6k
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1062
25.6k
                                    (int64_t)(le.end.x-re.end.x)/
1063
25.6k
                                    (int64_t)(re.start.x-re.end.x));
1064
25.6k
                    re.end.x = le.end.x;
1065
25.6k
                } else {
1066
16.1k
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1067
16.1k
                                    (int64_t)(le.end.x-re.end.x)/
1068
16.1k
                                    (int64_t)(le.end.x-le.start.x));
1069
16.1k
                    le.end.x = re.end.x;
1070
16.1k
                }
1071
41.8k
                if (ybot >= ytop)
1072
20.0k
                    return 0;
1073
21.7k
                le.end.y = ytop;
1074
21.7k
                re.end.y = ytop;
1075
21.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
239k
            lenew.start.x = xleft;
1082
239k
            lenew.start.y = ybot;
1083
239k
            lenew.end.x   = xleft;
1084
239k
            lenew.end.y   = ytop;
1085
239k
            renew.start.x = xright;
1086
239k
            renew.start.y = ybot;
1087
239k
            renew.end.x   = xright;
1088
239k
            renew.end.y   = ytop;
1089
            /* Figure out where the left edge intersects with the left at
1090
             * the bottom */
1091
239k
            ybl = ybot;
1092
239k
            if (le.start.x > le.end.x) {
1093
55.9k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1094
55.9k
                               (int64_t)(le.end.y-le.start.y) /
1095
55.9k
                               (int64_t)(le.start.x-le.end.x));
1096
55.9k
                if (ybl > ytop)
1097
22.3k
                    ybl = ytop;
1098
55.9k
            }
1099
            /* Figure out where the right edge intersects with the right at
1100
             * the bottom */
1101
239k
            ybr = ybot;
1102
239k
            if (re.start.x < re.end.x) {
1103
85.1k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1104
85.1k
                               (int64_t)(re.end.y-re.start.y) /
1105
85.1k
                               (int64_t)(re.end.x-re.start.x));
1106
85.1k
                if (ybr > ytop)
1107
24.5k
                    ybr = ytop;
1108
85.1k
            }
1109
            /* Figure out where the left edge intersects with the left at
1110
             * the top */
1111
239k
            ytl = ytop;
1112
239k
            if (le.end.x > le.start.x) {
1113
55.4k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1114
55.4k
                               (int64_t)(le.end.y-le.start.y) /
1115
55.4k
                               (int64_t)(le.end.x-le.start.x));
1116
55.4k
                if (ytl < ybot)
1117
22.8k
                    ytl = ybot;
1118
55.4k
            }
1119
            /* Figure out where the right edge intersects with the right at
1120
             * the bottom */
1121
239k
            ytr = ytop;
1122
239k
            if (re.end.x < re.start.x) {
1123
93.5k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1124
93.5k
                               (int64_t)(re.end.y-re.start.y) /
1125
93.5k
                               (int64_t)(re.start.x-re.end.x));
1126
93.5k
                if (ytr < ybot)
1127
21.7k
                    ytr = ybot;
1128
93.5k
            }
1129
            /* Check for the 2 cases where top and bottom diagonal extents
1130
             * overlap, and deal with them explicitly. */
1131
239k
            if (ytl < ybr) {
1132
                /*     |     |
1133
                 *  ---+-----+---
1134
                 *     | /222|
1135
                 *     |/111/|
1136
                 *     |000/ |
1137
                 *  ---+-----+---
1138
                 *     |     |
1139
                 */
1140
24.3k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1141
24.3k
                                        &lenew, &re, ybot, ytl,
1142
24.3k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1143
24.3k
                if (code < 0)
1144
0
                    return code;
1145
24.3k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1146
24.3k
                                        &le, &re, ytl, ybr,
1147
24.3k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1148
24.3k
                if (code < 0)
1149
0
                    return code;
1150
24.3k
                ybot = ybr;
1151
24.3k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1152
24.3k
                                        &le, &renew, ybr, ytop,
1153
24.3k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1154
215k
            } else if (ytr < ybl) {
1155
                /*     |     |
1156
                 *  ---+-----+----
1157
                 *     |555\ |
1158
                 *     |\444\|
1159
                 *     | \333|
1160
                 *  ---+-----+---
1161
                 *     |     |
1162
                 */
1163
28.2k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
28.2k
                                        &le, &renew, ybot, ytr,
1165
28.2k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
28.2k
                if (code < 0)
1167
0
                    return code;
1168
28.2k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1169
28.2k
                                        &le, &re, ytr, ybl,
1170
28.2k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1171
28.2k
                if (code < 0)
1172
0
                    return code;
1173
28.2k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1174
28.2k
                                        &le, &re, ybl, ytop,
1175
28.2k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1176
28.2k
            }
1177
            /* Fill in any section where both left and right edges are
1178
             * diagonal at the bottom */
1179
187k
            ymid = ybl;
1180
187k
            if (ymid > ybr)
1181
19.0k
                ymid = ybr;
1182
187k
            if (ymid > ybot) {
1183
                /*     |\   |          |   /|
1184
                 *     | \6/|    or    |\6/ |
1185
                 *  ---+----+---    ---+----+---
1186
                 *     |    |          |    |
1187
                 */
1188
7.61k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1189
7.61k
                                        &le, &re, ybot, ymid,
1190
7.61k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1191
7.61k
                if (code < 0)
1192
0
                    return code;
1193
7.61k
                ybot = ymid;
1194
7.61k
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the top */
1197
187k
            ymid = ytl;
1198
187k
            if (ymid < ytr)
1199
15.6k
                ymid = ytr;
1200
187k
            if (ymid < ytop) {
1201
                /*     |    |          |    |
1202
                 *  ---+----+---    ---+----+---
1203
                 *     |/7\ |    or    | /7\|
1204
                 *     |   \|          |/   |
1205
                 */
1206
8.97k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
8.97k
                                        &le, &re, ymid, ytop,
1208
8.97k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
8.97k
                if (code < 0)
1210
0
                    return code;
1211
8.97k
                ytop = ymid;
1212
8.97k
            }
1213
            /* Now do the single diagonal cases at the bottom */
1214
187k
            if (ybl > ybot) {
1215
                /*     |    |
1216
                 *     |\666|
1217
                 *  ---+----+---
1218
                 *     |    |
1219
                 */
1220
19.0k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1221
19.0k
                                        &le, &renew, ybot, ybl,
1222
19.0k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1223
19.0k
                if (code < 0)
1224
0
                    return code;
1225
19.0k
                ybot = ybl;
1226
167k
            } else if (ybr > ybot) {
1227
                /*     |    |
1228
                 *     |777/|
1229
                 *  ---+----+---
1230
                 *     |    |
1231
                 */
1232
16.7k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1233
16.7k
                                        &lenew, &re, ybot, ybr,
1234
16.7k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1235
16.7k
                if (code < 0)
1236
0
                    return code;
1237
16.7k
                ybot = ybr;
1238
16.7k
            }
1239
            /* Now do the single diagonal cases at the top */
1240
187k
            if (ytl < ytop) {
1241
                /*     |    |
1242
                 *  ---+----+---
1243
                 *     |/888|
1244
                 *     |    |
1245
                 */
1246
15.6k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1247
15.6k
                                        &le, &renew, ytl, ytop,
1248
15.6k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1249
15.6k
                if (code < 0)
1250
0
                    return code;
1251
15.6k
                ytop = ytl;
1252
171k
            } else if (ytr < ytop) {
1253
                /*     |    |
1254
                 *  ---+----+---
1255
                 *     |999\|
1256
                 *     |    |
1257
                 */
1258
20.5k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1259
20.5k
                                        &lenew, &re, ytr, ytop,
1260
20.5k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1261
20.5k
                if (code < 0)
1262
0
                    return code;
1263
20.5k
                ytop = ytr;
1264
20.5k
            }
1265
            /* And finally just whatever rectangular section is left over in
1266
             * the middle */
1267
187k
            if (ybot > ytop)
1268
0
                return 0;
1269
187k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1270
187k
                                        &lenew, &renew, ybot, ytop,
1271
187k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1272
187k
        }
1273
455k
    }
1274
819k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1275
819k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1276
1.10M
}
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
706M
#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
176M
{
1311
    /* Must return 2 if the color is not pure.
1312
       See try_device_linear_color.
1313
     */
1314
176M
    int code;
1315
176M
    gx_device_color devc;
1316
1317
176M
#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
176M
     if (frac_values) {
1345
117M
        int i;
1346
117M
  int n = pfs->dev->color_info.num_components;
1347
130M
  for (i = pfs->num_components; i < n; i++) {
1348
12.8M
            frac_values[i] = 0;
1349
12.8M
  }
1350
117M
    }
1351
176M
#endif
1352
1353
176M
    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
1354
0
        pdevc = &devc;
1355
176M
    if (pfs->pcic) {
1356
118M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1357
118M
        if (code < 0)
1358
0
            return code;
1359
118M
    }
1360
176M
    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
57.8M
        gs_client_color fcc;
1365
57.8M
        const gs_color_space *pcs = pfs->direct_space;
1366
1367
57.8M
        if (pcs != NULL) {
1368
1369
57.8M
            if (pdevc == NULL)
1370
0
                pdevc = &devc;
1371
57.8M
            memcpy(fcc.paint.values, c->cc.paint.values,
1372
57.8M
                        sizeof(fcc.paint.values[0]) * pfs->num_components);
1373
57.8M
            code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pgs,
1374
57.8M
                                      pfs->trans_device, gs_color_select_texture);
1375
57.8M
            if (code < 0)
1376
0
                return code;
1377
57.8M
            if (frac_values != NULL) {
1378
0
                if (!(pdevc->type == &gx_dc_type_data_devn ||
1379
0
                      pdevc->type == &gx_dc_type_data_pure))
1380
0
                    return 2;
1381
0
                dc2fc31(pfs, pdevc, frac_values);
1382
0
            }
1383
#           if DEBUG_COLOR_INDEX_CACHE
1384
            if (cindex != pdevc->colors.pure)
1385
                return_error(gs_error_unregistered);
1386
#           endif
1387
57.8M
        } else {
1388
            /* This is reserved for future extension,
1389
            when a linear color triangle with frac31 colors is being decomposed
1390
            during a clist rasterization. In this case frac31 colors are written into
1391
            the patch color, and pcs==NULL means an identity color mapping.
1392
            For a while we assume here pfs->pcic is also NULL. */
1393
0
            int j;
1394
0
            const gx_device_color_info *cinfo = &pfs->dev->color_info;
1395
1396
0
            for (j = 0; j < cinfo->num_components; j++)
1397
0
                frac_values[j] = (frac31)c->cc.paint.values[j];
1398
0
            pdevc->type = &gx_dc_type_data_pure;
1399
0
        }
1400
57.8M
    }
1401
176M
    return 0;
1402
176M
}
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
274M
{
1413
274M
    int n = pfs->num_components, i;
1414
274M
    double m;
1415
1416
    /* Dont want to copy colors, which are big things. */
1417
274M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1418
1.03G
    for (i = 1; i < n; i++)
1419
757M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1420
274M
    return m;
1421
274M
}
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
56.0M
{
1426
56.0M
    int n = pfs->num_components, i;
1427
1428
268M
    for (i = 0; i < n; i++)
1429
212M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1430
56.0M
}
1431
1432
static inline double
1433
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1434
42.6M
{
1435
42.6M
    int n = pfs->num_components, i;
1436
42.6M
    double m;
1437
1438
42.6M
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1439
161M
    for (i = 1; i < n; i++)
1440
119M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1441
42.6M
    return m;
1442
42.6M
}
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
13.3M
{   /* 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
13.3M
    uint mask;
1462
13.3M
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1463
1464
13.3M
    if (code >= 0)
1465
13.3M
        return mask;
1466
17
    return code;
1467
13.3M
}
1468
1469
static inline bool
1470
covers_pixel_centers(fixed ybot, fixed ytop)
1471
31.1M
{
1472
31.1M
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1473
31.1M
}
1474
1475
static inline int
1476
constant_color_trapezoid(patch_fill_state_t *pfs, gs_fixed_edge *le, gs_fixed_edge *re,
1477
        fixed ybot, fixed ytop, bool swap_axes, const patch_color_t *c)
1478
16.5M
{
1479
16.5M
    gx_device_color dc;
1480
16.5M
    int code;
1481
1482
#   if NOFILL_TEST
1483
        /* if (dbg_nofill)
1484
                return 0; */
1485
#   endif
1486
1487
16.5M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1488
16.5M
    if (code < 0)
1489
0
        return code;
1490
1491
16.5M
    dc.tag = device_current_tag(pfs->dev);
1492
1493
16.5M
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1494
16.5M
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1495
16.5M
}
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
139M
{
1500
139M
    float s = 0;
1501
1502
139M
    if (pfs->Function != NULL) {
1503
15.7M
        patch_color_t c;
1504
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1505
        /* unless it is 'static const' */
1506
15.7M
        static const float q[2] = {(float)0.3, (float)0.7};
1507
15.7M
        int i, j;
1508
1509
46.0M
        for (j = 0; j < count_of(q); j++) {
1510
30.9M
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1511
30.9M
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1512
30.9M
            patch_resolve_color_inline(&c, pfs);
1513
117M
            for (i = 0; i < pfs->num_components; i++) {
1514
86.9M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1515
86.9M
                float d = v - c.cc.paint.values[i];
1516
86.9M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1517
1518
86.9M
                if (s1 > pfs->smoothness)
1519
702k
                    return s1;
1520
86.2M
                if (s < s1)
1521
7.85M
                    s = s1;
1522
86.2M
            }
1523
30.9M
        }
1524
15.7M
    }
1525
139M
    return s;
1526
139M
}
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
47.0M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1531
47.0M
    if (pfs->unlinear)
1532
8.32M
        return 1; /* Disable this check. */
1533
38.7M
    else {
1534
38.7M
        const gs_color_space *cs = pfs->direct_space;
1535
38.7M
        int code;
1536
38.7M
        float s = function_linearity(pfs, c0, c1);
1537
1538
38.7M
        if (s > pfs->smoothness)
1539
403k
            return 0;
1540
38.3M
        if (pfs->cs_always_linear)
1541
16.0M
            return 1;
1542
22.2M
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1543
22.2M
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1544
22.2M
        if (code <= 0)
1545
93.0k
            return code;
1546
22.2M
        return 1;
1547
22.2M
    }
1548
47.0M
}
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
70.6M
{
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
70.6M
    int code;
1559
70.6M
    patch_color_t *c;
1560
70.6M
    byte *color_stack_ptr;
1561
70.6M
    bool save_inside = pfs->inside;
1562
1563
70.6M
    if (!pfs->inside) {
1564
62.3M
        gs_fixed_rect r, r1;
1565
1566
62.3M
        if(swap_axes) {
1567
26.0M
            r.p.y = min(le->start.x, le->end.x);
1568
26.0M
            r.p.x = min(le->start.y, le->end.y);
1569
26.0M
            r.q.y = max(re->start.x, re->end.x);
1570
26.0M
            r.q.x = max(re->start.y, re->end.y);
1571
36.3M
        } else {
1572
36.3M
            r.p.x = min(le->start.x, le->end.x);
1573
36.3M
            r.p.y = min(le->start.y, le->end.y);
1574
36.3M
            r.q.x = max(re->start.x, re->end.x);
1575
36.3M
            r.q.y = max(re->start.y, re->end.y);
1576
36.3M
        }
1577
62.3M
        r1 = r;
1578
62.3M
        rect_intersect(r, pfs->rect);
1579
62.3M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1580
36.7M
            return 0;
1581
25.5M
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1582
25.5M
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1583
9.37M
            pfs->inside = true;
1584
25.5M
    }
1585
33.8M
    color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
1586
33.8M
    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
33.8M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
1592
33.8M
    if (ytop - ybot < pfs->decomposition_limit) /* Prevent an infinite color decomposition. */
1593
2.47M
        code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1594
31.4M
    else {
1595
31.4M
        bool monotonic_color_save = pfs->monotonic_color;
1596
31.4M
        bool linear_color_save = pfs->linear_color;
1597
1598
31.4M
        if (!pfs->monotonic_color) {
1599
11.2M
            code = isnt_color_monotonic(pfs, c0, c1);
1600
11.2M
            if (code < 0)
1601
17
                goto out;
1602
11.2M
            if (!code)
1603
8.83M
                pfs->monotonic_color = true;
1604
11.2M
        }
1605
31.4M
        if (pfs->monotonic_color && !pfs->linear_color) {
1606
16.8M
            code = is_color_linear(pfs, c0, c1);
1607
16.8M
            if (code < 0)
1608
0
                goto out;
1609
16.8M
            if (code > 0)
1610
16.6M
                pfs->linear_color =  true;
1611
16.8M
        }
1612
31.4M
        if (!pfs->unlinear && pfs->linear_color) {
1613
8.35M
            gx_device *pdev = pfs->dev;
1614
8.35M
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1615
8.35M
            gs_fill_attributes fa;
1616
8.35M
            gs_fixed_rect clip;
1617
1618
8.35M
            memset(fc, 0x99, sizeof(fc));
1619
1620
8.35M
            clip = pfs->rect;
1621
8.35M
            if (swap_axes) {
1622
2.67M
                fixed v;
1623
1624
2.67M
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1625
2.67M
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1626
                /* Don't need adjust_swapped_boundary here. */
1627
2.67M
            }
1628
8.35M
            clip.p.y = max(clip.p.y, ybot);
1629
8.35M
            clip.q.y = min(clip.q.y, ytop);
1630
8.35M
            fa.clip = &clip;
1631
8.35M
            fa.ht = NULL;
1632
8.35M
            fa.swap_axes = swap_axes;
1633
8.35M
            fa.lop = 0;
1634
8.35M
            fa.ystart = ybot;
1635
8.35M
            fa.yend = ytop;
1636
8.35M
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1637
8.35M
            if (code < 0)
1638
0
                goto out;
1639
8.35M
            if (code == 2) {
1640
                /* Must not happen. */
1641
0
                code=gs_note_error(gs_error_unregistered);
1642
0
                goto out;
1643
0
            }
1644
8.35M
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1645
8.35M
            if (code < 0)
1646
0
                goto out;
1647
8.35M
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1648
8.35M
                            &le->start, &le->end, &re->start, &re->end,
1649
8.35M
                            fc[0], fc[1], NULL, NULL);
1650
8.35M
            if (code == 1) {
1651
8.35M
                pfs->monotonic_color = monotonic_color_save;
1652
8.35M
                pfs->linear_color = linear_color_save;
1653
8.35M
                code = 0; /* The area is filled. */
1654
8.35M
                goto out;
1655
8.35M
            }
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
23.0M
        if (!pfs->unlinear || !pfs->linear_color ||
1664
23.0M
                color_span(pfs, c0, c1) > pfs->smoothness) {
1665
8.96M
            fixed y = (ybot + ytop) / 2;
1666
1667
8.96M
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1668
8.96M
            if (code >= 0)
1669
8.96M
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1670
8.96M
        } else
1671
14.0M
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1672
23.0M
        pfs->monotonic_color = monotonic_color_save;
1673
23.0M
        pfs->linear_color = linear_color_save;
1674
23.0M
    }
1675
33.8M
out:
1676
33.8M
    pfs->inside = save_inside;
1677
33.8M
    release_colors_inline(pfs, color_stack_ptr, 1);
1678
33.8M
    return code;
1679
33.8M
}
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
22.8M
{
1686
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1687
22.8M
    gs_fixed_edge le, re;
1688
1689
22.8M
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1690
22.8M
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1691
22.8M
}
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
31.1M
{
1698
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1699
31.1M
    fixed dx1, dy1, dx2, dy2;
1700
31.1M
    bool orient;
1701
1702
31.1M
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1703
8.30M
        return 0;
1704
22.8M
    if (ybot == ytop)
1705
0
        return 0;
1706
22.8M
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1707
22.8M
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1708
22.8M
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1709
11.3M
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1710
11.3M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1711
11.4M
    } else {
1712
11.4M
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1713
1714
11.4M
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1715
11.4M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1716
11.4M
    }
1717
22.8M
}
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
31.1M
{
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
31.1M
    gs_fixed_point p[4];
1727
31.1M
    const patch_color_t *cc0, *cc1;
1728
1729
31.1M
    if (p0->y < p1->y) {
1730
15.4M
        p[2] = *p0;
1731
15.4M
        p[3] = *p1;
1732
15.4M
        cc0 = c0;
1733
15.4M
        cc1 = c1;
1734
15.7M
    } else {
1735
15.7M
        p[2] = *p1;
1736
15.7M
        p[3] = *p0;
1737
15.7M
        cc0 = c1;
1738
15.7M
        cc1 = c0;
1739
15.7M
    }
1740
31.1M
    p[0] = *q0;
1741
31.1M
    p[1] = *q1;
1742
31.1M
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1743
31.1M
}
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
182M
{
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
182M
#define midpoint(a,b)\
1757
2.18G
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1758
182M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1759
182M
    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
182M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1763
182M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1764
182M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1765
182M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1766
182M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1767
182M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1768
182M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1769
182M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1770
182M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1771
182M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1772
182M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1773
182M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1774
182M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1775
182M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1776
182M
#undef midpoint
1777
182M
}
1778
1779
static void
1780
split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1781
4.56M
{
1782
4.56M
    split_curve_s(pole, q0, q1, 1);
1783
4.56M
}
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
24.2M
{
1826
24.2M
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1827
1828
24.2M
    return max(dx, dy);
1829
24.2M
}
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
6.52M
{
1835
6.52M
    if (l->end != NULL)
1836
0
        return_error(gs_error_unregistered); /* Must not happen. */
1837
6.52M
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1838
6.52M
    l->end = wedge_vertex_list_elem_reserve(pfs);
1839
6.52M
    if (l->beg == NULL)
1840
0
        return_error(gs_error_unregistered); /* Must not happen. */
1841
6.52M
    if (l->end == NULL)
1842
0
        return_error(gs_error_unregistered); /* Must not happen. */
1843
6.52M
    l->beg->prev = l->end->next = NULL;
1844
6.52M
    l->beg->next = l->end;
1845
6.52M
    l->end->prev = l->beg;
1846
6.52M
    l->beg->p = *p0;
1847
6.52M
    l->end->p = *p1;
1848
6.52M
    l->beg->level = l->end->level = 0;
1849
6.52M
    return 0;
1850
6.52M
}
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
12.4M
{
1856
12.4M
    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
12.4M
    if (e == NULL)
1861
0
        return_error(gs_error_unregistered); /* Must not happen. */
1862
12.4M
    if (l->beg->next != l->end)
1863
0
        return_error(gs_error_unregistered); /* Must not happen. */
1864
12.4M
    if (l->end->prev != l->beg)
1865
0
        return_error(gs_error_unregistered); /* Must not happen. */
1866
12.4M
    e->next = l->end;
1867
12.4M
    e->prev = l->beg;
1868
12.4M
    e->p = *p;
1869
12.4M
    e->level = max(l->beg->level, l->end->level) + 1;
1870
12.4M
    e->divide_count = 0;
1871
12.4M
    l->beg->next = l->end->prev = e;
1872
12.4M
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1873
12.4M
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1874
1875
12.4M
        if ((p->x - l->beg->p.x) * sx < 0)
1876
0
            return_error(gs_error_unregistered); /* Must not happen. */
1877
12.4M
        if ((p->y - l->beg->p.y) * sy < 0)
1878
0
            return_error(gs_error_unregistered); /* Must not happen. */
1879
12.4M
        if ((l->end->p.x - p->x) * sx < 0)
1880
0
            return_error(gs_error_unregistered); /* Must not happen. */
1881
12.4M
        if ((l->end->p.y - p->y) * sy < 0)
1882
0
            return_error(gs_error_unregistered); /* Must not happen. */
1883
12.4M
    }
1884
12.4M
    *r = e;
1885
12.4M
    return 0;
1886
12.4M
}
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
19.2M
{
1893
19.2M
    wedge_vertex_list_elem_t *e;
1894
19.2M
    int code;
1895
1896
19.2M
    if (!l->last_side) {
1897
12.1M
        if (l->beg == NULL) {
1898
6.31M
            code = create_wedge_vertex_list(pfs, l, p0, p1);
1899
6.31M
            if (code < 0)
1900
0
                return code;
1901
6.31M
        }
1902
12.1M
        if (l->beg->p.x != p0->x)
1903
0
            return_error(gs_error_unregistered); /* Must not happen. */
1904
12.1M
        if (l->beg->p.y != p0->y)
1905
0
            return_error(gs_error_unregistered); /* Must not happen. */
1906
12.1M
        if (l->end->p.x != p1->x)
1907
0
            return_error(gs_error_unregistered); /* Must not happen. */
1908
12.1M
        if (l->end->p.y != p1->y)
1909
0
            return_error(gs_error_unregistered); /* Must not happen. */
1910
12.1M
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1911
12.1M
        if (code < 0)
1912
0
            return code;
1913
12.1M
        e->divide_count++;
1914
12.1M
    } else if (l->beg == NULL) {
1915
202k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1916
202k
        if (code < 0)
1917
0
            return code;
1918
202k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1919
202k
        if (code < 0)
1920
0
            return code;
1921
202k
        e->divide_count++;
1922
6.87M
    } else {
1923
6.87M
        if (l->beg->p.x != p1->x)
1924
0
            return_error(gs_error_unregistered); /* Must not happen. */
1925
6.87M
        if (l->beg->p.y != p1->y)
1926
0
            return_error(gs_error_unregistered); /* Must not happen. */
1927
6.87M
        if (l->end->p.x != p0->x)
1928
0
            return_error(gs_error_unregistered); /* Must not happen. */
1929
6.87M
        if (l->end->p.y != p0->y)
1930
0
            return_error(gs_error_unregistered); /* Must not happen. */
1931
6.87M
        if (l->beg->next == l->end) {
1932
115k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1933
115k
            if (code < 0)
1934
0
                return code;
1935
115k
            e->divide_count++;
1936
6.75M
        } else {
1937
6.75M
            e = wedge_vertex_list_find(l->beg, l->end,
1938
6.75M
                        max(l->beg->level, l->end->level) + 1);
1939
6.75M
            if (e == NULL)
1940
0
                return_error(gs_error_unregistered); /* Must not happen. */
1941
6.75M
            if (e->p.x != pm->x || e->p.y != pm->y)
1942
0
                return_error(gs_error_unregistered); /* Must not happen. */
1943
6.75M
            e->divide_count++;
1944
6.75M
        }
1945
6.87M
    }
1946
19.2M
    *r = e;
1947
19.2M
    return 0;
1948
19.2M
}
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
19.2M
{
1955
19.2M
    int code;
1956
1957
19.2M
    l->last_side = l0->last_side;
1958
19.2M
    if (!l->last_side ^ !forth) {
1959
11.0M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1960
11.0M
        l->beg = l0->beg;
1961
11.0M
    } else {
1962
8.15M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1963
8.15M
        l->end = l0->end;
1964
8.15M
    }
1965
19.2M
    return code;
1966
19.2M
}
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
19.2M
{
1975
19.2M
    int code;
1976
1977
19.2M
    if (!l->last_side)
1978
12.1M
        return 0;
1979
7.07M
    code = fill_wedge_from_list(pfs, l, c1, c0);
1980
7.07M
    if (code < 0)
1981
0
        return code;
1982
7.07M
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1983
7.07M
    return 0;
1984
7.07M
}
1985
1986
static inline void
1987
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1988
19.2M
{
1989
19.2M
    if (!l->last_side ^ !forth) {
1990
11.0M
        l->beg = l->end;
1991
11.0M
        l->end = l0->end;
1992
11.0M
    } else {
1993
8.15M
        l->end = l->beg;
1994
8.15M
        l->beg = l0->beg;
1995
8.15M
    }
1996
19.2M
}
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
15.5M
{   int code;
2002
15.5M
    const gs_fixed_point *p0, *p1, *p2;
2003
15.5M
    gs_fixed_point qq0, qq1, qq2;
2004
15.5M
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2005
15.5M
    bool swap_axes;
2006
2007
#   if SKIP_TEST
2008
        dbg_wedge_triangle_cnt++;
2009
#   endif
2010
15.5M
    if (dx > dy) {
2011
8.68M
        swap_axes = true;
2012
8.68M
        qq0.x = q0->p.y;
2013
8.68M
        qq0.y = q0->p.x;
2014
8.68M
        qq1.x = q1->p.y;
2015
8.68M
        qq1.y = q1->p.x;
2016
8.68M
        qq2.x = q2->p.y;
2017
8.68M
        qq2.y = q2->p.x;
2018
8.68M
        p0 = &qq0;
2019
8.68M
        p1 = &qq1;
2020
8.68M
        p2 = &qq2;
2021
8.68M
    } else {
2022
6.89M
        swap_axes = false;
2023
6.89M
        p0 = &q0->p;
2024
6.89M
        p1 = &q1->p;
2025
6.89M
        p2 = &q2->p;
2026
6.89M
    }
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
15.5M
    if (p0->y < p1->y) {
2032
7.74M
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2033
7.74M
        if (code < 0)
2034
1
            return code;
2035
7.74M
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2036
7.82M
    } else {
2037
7.82M
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2038
7.82M
        if (code < 0)
2039
5
            return code;
2040
7.82M
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2041
7.82M
    }
2042
15.5M
}
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
74.9M
{
2049
    /*  Returns :
2050
        <0 - error;
2051
        0 - success;
2052
        1 - decompose to linear color areas;
2053
        2 - decompose to constant color areas;
2054
     */
2055
74.9M
    int code;
2056
2057
74.9M
    if (pfs->unlinear)
2058
41.1M
        return 2;
2059
33.8M
    if (!wedge) {
2060
33.8M
        const gs_color_space *cs = pfs->direct_space;
2061
2062
33.8M
        if (cs != NULL) {
2063
33.8M
            float s0, s1, s2, s01, s012;
2064
2065
33.8M
            s0 = function_linearity(pfs, p0->c, p1->c);
2066
33.8M
            if (s0 > pfs->smoothness)
2067
180k
                return 1;
2068
33.6M
            s1 = function_linearity(pfs, p1->c, p2->c);
2069
33.6M
            if (s1 > pfs->smoothness)
2070
116k
                return 1;
2071
33.5M
            s2 = function_linearity(pfs, p2->c, p0->c);
2072
33.5M
            if (s2 > pfs->smoothness)
2073
1.63k
                return 1;
2074
            /* fixme: check an inner color ? */
2075
33.5M
            s01 = max(s0, s1);
2076
33.5M
            s012 = max(s01, s2);
2077
33.5M
            if (pfs->cs_always_linear)
2078
12.1M
                code = 1;
2079
21.3M
            else
2080
21.3M
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2081
33.5M
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2082
33.5M
                                  pfs->smoothness - s012, pfs->icclink);
2083
33.5M
            if (code < 0)
2084
0
                return code;
2085
33.5M
            if (code == 0)
2086
18.7k
                return 1;
2087
33.5M
        }
2088
33.8M
    }
2089
33.5M
    {   gx_device *pdev = pfs->dev;
2090
33.5M
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2091
33.5M
        gs_fill_attributes fa;
2092
33.5M
        gx_device_color dc[3];
2093
2094
33.5M
        fa.clip = &pfs->rect;
2095
33.5M
        fa.ht = NULL;
2096
33.5M
        fa.swap_axes = false;
2097
33.5M
        fa.lop = 0;
2098
33.5M
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2099
33.5M
        if (code != 0)
2100
0
            return code;
2101
33.5M
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2102
33.5M
            dc[0].type == &gx_dc_type_data_devn))
2103
0
            return 2;
2104
33.5M
        if (!wedge) {
2105
33.5M
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2106
33.5M
            if (code != 0)
2107
0
                return code;
2108
33.5M
        }
2109
33.5M
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2110
33.5M
        if (code != 0)
2111
0
            return code;
2112
33.5M
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2113
33.5M
                        &p0->p, &p1->p, &p2->p,
2114
33.5M
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2115
33.5M
        if (code == 1)
2116
33.5M
            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
29.7M
{
2128
29.7M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2129
29.7M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2130
14.1M
        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
15.5M
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2138
29.7M
}
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
5.72M
{
2146
5.72M
    shading_vertex_t p[3];
2147
5.72M
    patch_color_t *c;
2148
5.72M
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2149
5.72M
    int code;
2150
2151
5.72M
    if (color_stack_ptr == NULL)
2152
0
        return_error(gs_error_unregistered); /* Must not happen. */
2153
5.72M
    p[2].c = c;
2154
5.72M
    p[0].p = beg->p;
2155
5.72M
    p[0].c = c0;
2156
5.72M
    p[1].p = end->p;
2157
5.72M
    p[1].c = c1;
2158
5.72M
    p[2].p = mid->p;
2159
5.72M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2160
5.72M
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2161
5.72M
    release_colors_inline(pfs, color_stack_ptr, 1);
2162
5.72M
    return code;
2163
5.72M
}
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
16.9M
{
2170
16.9M
    if (beg->next == end)
2171
4.44M
        return 0;
2172
12.4M
    else if (beg->next->next == end) {
2173
10.8M
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2174
0
            return_error(gs_error_unregistered); /* Must not happen. */
2175
10.8M
        if (beg->next->divide_count != 1)
2176
6.73M
            return 0;
2177
4.07M
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2178
10.8M
    } else {
2179
1.66M
        gs_fixed_point p;
2180
1.66M
        wedge_vertex_list_elem_t *e;
2181
1.66M
        patch_color_t *c;
2182
1.66M
        int code;
2183
1.66M
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2184
2185
1.66M
        if (color_stack_ptr == NULL)
2186
0
            return_error(gs_error_unregistered); /* Must not happen. */
2187
1.66M
        p.x = (beg->p.x + end->p.x) / 2;
2188
1.66M
        p.y = (beg->p.y + end->p.y) / 2;
2189
1.66M
        e = wedge_vertex_list_find(beg, end, level + 1);
2190
1.66M
        if (e == NULL)
2191
0
            return_error(gs_error_unregistered); /* Must not happen. */
2192
1.66M
        if (e->p.x != p.x || e->p.y != p.y)
2193
0
            return_error(gs_error_unregistered); /* Must not happen. */
2194
1.66M
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2195
1.66M
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2196
1.66M
        if (code >= 0)
2197
1.66M
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2198
1.66M
        if (code >= 0) {
2199
1.66M
            if (e->divide_count != 1 && e->divide_count != 2)
2200
0
                return_error(gs_error_unregistered); /* Must not happen. */
2201
1.66M
            if (e->divide_count == 1)
2202
1.64M
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2203
1.66M
        }
2204
1.66M
        release_colors_inline(pfs, color_stack_ptr, 1);
2205
1.66M
        return code;
2206
1.66M
    }
2207
16.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
13.5M
{
2213
13.5M
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2214
13.5M
                    max(l->beg->level, l->end->level), c0, c1);
2215
13.5M
}
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
167M
{
2221
167M
    if (l->beg != NULL) {
2222
6.52M
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2223
2224
6.52M
        if (code < 0)
2225
0
            return code;
2226
6.52M
        return release_wedge_vertex_list(pfs, l, 1);
2227
6.52M
    }
2228
161M
    return 0;
2229
167M
}
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
4.34M
{   /* Assuming ka >= 2, see fill_wedges. */
2235
4.34M
    gs_fixed_point q[2][4];
2236
4.34M
    patch_color_t *c;
2237
4.34M
    shading_vertex_t p[3];
2238
4.34M
    int code;
2239
4.34M
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2240
2241
4.34M
    if (color_stack_ptr == NULL)
2242
0
        return_error(gs_error_unregistered); /* Must not happen. */
2243
4.34M
    p[2].c = c;
2244
4.34M
    split_curve(pole, q[0], q[1]);
2245
4.34M
    p[0].p = pole[0];
2246
4.34M
    p[0].c = c0;
2247
4.34M
    p[1].p = pole[3];
2248
4.34M
    p[1].c = c1;
2249
4.34M
    p[2].p = q[0][3];
2250
4.34M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2251
4.34M
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2252
4.34M
    if (code >= 0) {
2253
4.34M
        if (ka == 2)
2254
2.21M
            goto out;
2255
2.12M
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2256
2.12M
    }
2257
2.12M
    if (code >= 0)
2258
2.12M
        code = wedge_by_triangles(pfs, ka / 2, q[1], p[2].c, c1);
2259
4.34M
out:
2260
4.34M
    release_colors_inline(pfs, color_stack_ptr, 1);
2261
4.34M
    return code;
2262
2.12M
}
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
29.8M
{
2268
29.8M
    gs_fixed_point q0, q1;
2269
29.8M
    const patch_color_t *cc0, *cc1;
2270
29.8M
    fixed dx = p1->x - p0->x;
2271
29.8M
    fixed dy = p1->y - p0->y;
2272
29.8M
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2273
29.8M
    gs_fixed_edge le, re;
2274
29.8M
    const fixed adjust = INTERPATCH_PADDING;
2275
2276
29.8M
    if (swap_axes) {
2277
10.1M
        if (p0->x < p1->x) {
2278
5.00M
            q0.x = p0->y;
2279
5.00M
            q0.y = p0->x;
2280
5.00M
            q1.x = p1->y;
2281
5.00M
            q1.y = p1->x;
2282
5.00M
            cc0 = c0;
2283
5.00M
            cc1 = c1;
2284
5.17M
        } else {
2285
5.17M
            q0.x = p1->y;
2286
5.17M
            q0.y = p1->x;
2287
5.17M
            q1.x = p0->y;
2288
5.17M
            q1.y = p0->x;
2289
5.17M
            cc0 = c1;
2290
5.17M
            cc1 = c0;
2291
5.17M
        }
2292
19.7M
    } else if (p0->y < p1->y) {
2293
3.06M
        q0 = *p0;
2294
3.06M
        q1 = *p1;
2295
3.06M
        cc0 = c0;
2296
3.06M
        cc1 = c1;
2297
16.6M
    } else {
2298
16.6M
        q0 = *p1;
2299
16.6M
        q1 = *p0;
2300
16.6M
        cc0 = c1;
2301
16.6M
        cc1 = c0;
2302
16.6M
    }
2303
29.8M
    le.start.x = q0.x - adjust;
2304
29.8M
    re.start.x = q0.x + adjust;
2305
29.8M
    le.start.y = re.start.y = q0.y - adjust;
2306
29.8M
    le.end.x = q1.x - adjust;
2307
29.8M
    re.end.x = q1.x + adjust;
2308
29.8M
    le.end.y = re.end.y = q1.y + adjust;
2309
29.8M
    adjust_swapped_boundary(&re.start.x, swap_axes);
2310
29.8M
    adjust_swapped_boundary(&re.end.x, swap_axes);
2311
29.8M
    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
29.8M
}
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
31.7M
{
2325
31.7M
    r->p.x = r->q.x = p0->x;
2326
31.7M
    r->p.y = r->q.y = p0->y;
2327
2328
31.7M
    if (r->p.x > p1->x)
2329
12.7M
        r->p.x = p1->x;
2330
31.7M
    if (r->q.x < p1->x)
2331
13.3M
        r->q.x = p1->x;
2332
31.7M
    if (r->p.y > p1->y)
2333
13.1M
        r->p.y = p1->y;
2334
31.7M
    if (r->q.y < p1->y)
2335
12.5M
        r->q.y = p1->y;
2336
2337
31.7M
    if (r->p.x > p2->x)
2338
6.83M
        r->p.x = p2->x;
2339
31.7M
    if (r->q.x < p2->x)
2340
6.85M
        r->q.x = p2->x;
2341
31.7M
    if (r->p.y > p2->y)
2342
6.52M
        r->p.y = p2->y;
2343
31.7M
    if (r->q.y < p2->y)
2344
6.90M
        r->q.y = p2->y;
2345
2346
31.7M
    if (p3 == NULL)
2347
23.4M
        return;
2348
2349
8.30M
    if (r->p.x > p3->x)
2350
1.72M
        r->p.x = p3->x;
2351
8.30M
    if (r->q.x < p3->x)
2352
2.17M
        r->q.x = p3->x;
2353
8.30M
    if (r->p.y > p3->y)
2354
1.80M
        r->p.y = p3->y;
2355
8.30M
    if (r->q.y < p3->y)
2356
1.83M
        r->q.y = p3->y;
2357
8.30M
}
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
2.18M
{
2364
2.18M
    int code;
2365
2366
2.18M
    if (k > 1) {
2367
857k
        gs_fixed_point q[2][4];
2368
857k
        patch_color_t *c;
2369
857k
        bool save_inside = pfs->inside;
2370
857k
        byte *color_stack_ptr;
2371
2372
857k
        if (!pfs->inside) {
2373
790k
            gs_fixed_rect r, r1;
2374
2375
790k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2376
790k
            r.p.x -= INTERPATCH_PADDING;
2377
790k
            r.p.y -= INTERPATCH_PADDING;
2378
790k
            r.q.x += INTERPATCH_PADDING;
2379
790k
            r.q.y += INTERPATCH_PADDING;
2380
790k
            r1 = r;
2381
790k
            rect_intersect(r, pfs->rect);
2382
790k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2383
631k
                return 0;
2384
159k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2385
159k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2386
51.3k
                pfs->inside = true;
2387
159k
        }
2388
226k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2389
226k
        if (color_stack_ptr == NULL)
2390
0
            return_error(gs_error_unregistered); /* Must not happen. */
2391
226k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2392
226k
        split_curve(pole, q[0], q[1]);
2393
226k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2394
226k
        if (code >= 0)
2395
226k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2396
226k
        release_colors_inline(pfs, color_stack_ptr, 1);
2397
226k
        pfs->inside = save_inside;
2398
226k
        return code;
2399
1.32M
    } else {
2400
1.32M
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2401
1.27M
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2402
1.27M
            if (code < 0)
2403
0
                return code;
2404
1.27M
        }
2405
1.32M
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2406
99.5k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2407
1.22M
        return 0;
2408
1.32M
    }
2409
2.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
19.1M
{
2417
    /* Generate wedges between 2 variants of a curve flattening. */
2418
    /* k0, k1 is a power of 2. */
2419
19.1M
    gs_fixed_point p[4];
2420
2421
19.1M
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2422
17.3M
        return 0; /* Wedges are zero area. */
2423
1.73M
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2424
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2425
0
    }
2426
1.73M
    p[0] = pole[0];
2427
1.73M
    p[1] = pole[pole_step];
2428
1.73M
    p[2] = pole[pole_step * 2];
2429
1.73M
    p[3] = pole[pole_step * 3];
2430
1.73M
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2431
19.1M
}
2432
2433
static inline void
2434
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2435
573k
{
2436
573k
    q[0] = p->p[0][0]->p;
2437
573k
    q[1] = p->p[0][1]->p;
2438
573k
    q[2] = p->p[1][1]->p;
2439
573k
    q[3] = p->p[1][0]->p;
2440
573k
}
2441
2442
static inline void
2443
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2444
573k
{
2445
573k
    fixed y = s[0].y;
2446
573k
    int i = 0;
2447
2448
573k
    if (y > s[1].y)
2449
210k
        i = 1, y = s[1].y;
2450
573k
    if (y > s[2].y)
2451
103k
        i = 2, y = s[2].y;
2452
573k
    if (y > s[3].y)
2453
46.6k
        i = 3, y = s[3].y;
2454
573k
    q[0] = s[(i + 0) % 4];
2455
573k
    q[1] = s[(i + 1) % 4];
2456
573k
    q[2] = s[(i + 2) % 4];
2457
573k
    q[3] = s[(i + 3) % 4];
2458
573k
}
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
42.1M
{
2463
42.1M
    gs_fixed_edge ue;
2464
42.1M
    int code;
2465
42.1M
    gx_device_color dc;
2466
2467
#   if NOFILL_TEST
2468
        if (dbg_nofill)
2469
            return 0;
2470
#   endif
2471
42.1M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2472
42.1M
    if (code < 0)
2473
0
        return code;
2474
42.1M
    if (le->end.y < re->end.y) {
2475
18.7M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2476
18.7M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2477
18.7M
        if (code >= 0) {
2478
18.7M
            ue.start = le->end;
2479
18.7M
            ue.end = re->end;
2480
18.7M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2481
18.7M
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2482
18.7M
        }
2483
23.4M
    } else if (le->end.y > re->end.y) {
2484
17.3M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2485
17.3M
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2486
17.3M
        if (code >= 0) {
2487
17.3M
            ue.start = re->end;
2488
17.3M
            ue.end = le->end;
2489
17.3M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2490
17.3M
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2491
17.3M
        }
2492
17.3M
    } else
2493
6.07M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2494
6.07M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2495
42.1M
    return code;
2496
42.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
36.2M
{
2502
36.2M
    patch_color_t *c[2];
2503
36.2M
    gs_fixed_edge le, re;
2504
36.2M
    fixed dx0, dy0, dx1, dy1;
2505
36.2M
    const shading_vertex_t *pp;
2506
36.2M
    int i, code = 0;
2507
36.2M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2508
2509
36.2M
    if (color_stack_ptr == NULL)
2510
0
        return_error(gs_error_unregistered); /* Must not happen. */
2511
36.2M
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2512
36.2M
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2513
144M
    for (i = 0; i < 3; i++) {
2514
        /* fixme : does optimizer compiler expand this cycle ? */
2515
108M
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2516
42.1M
            le.start = re.start = p0->p;
2517
42.1M
            le.end = p1->p;
2518
42.1M
            re.end = p2->p;
2519
2520
42.1M
            dx0 = le.end.x - le.start.x;
2521
42.1M
            dy0 = le.end.y - le.start.y;
2522
42.1M
            dx1 = re.end.x - re.start.x;
2523
42.1M
            dy1 = re.end.y - re.start.y;
2524
42.1M
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2525
20.1M
                code = ordered_triangle(pfs, &le, &re, c[1]);
2526
21.9M
            else
2527
21.9M
                code = ordered_triangle(pfs, &re, &le, c[1]);
2528
42.1M
            if (code < 0)
2529
0
                break;
2530
42.1M
        }
2531
108M
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2532
108M
    }
2533
36.2M
    release_colors_inline(pfs, color_stack_ptr, 2);
2534
36.2M
    return code;
2535
36.2M
}
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
573k
{
2541
    /* Assuming the XY span is restricted with curve_samples.
2542
       It is important for intersection_of_small_bars to compute faster. */
2543
573k
    gs_fixed_point q[4];
2544
573k
    fixed ry, ey;
2545
573k
    int code;
2546
573k
    bool swap_axes = false;
2547
573k
    gx_device_color dc;
2548
573k
    bool orient;
2549
2550
573k
    dc.tag = device_current_tag(pfs->dev);
2551
2552
573k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2553
573k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2554
573k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2555
573k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2556
573k
    if (code < 0)
2557
0
        return code;
2558
573k
    {   gs_fixed_point qq[4];
2559
2560
573k
        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
573k
        wrap_vertices_by_y(q, qq);
2573
573k
    }
2574
573k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2575
573k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2576
573k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2577
2578
573k
        if (g13 == h13) {
2579
1.17k
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2580
1.17k
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2581
2582
1.17k
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2583
0
                return 0;
2584
1.17k
            if (g23 != h23) {
2585
1.17k
                orient = (g23 > h23);
2586
1.17k
                if (q[2].y <= q[3].y) {
2587
992
                    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
992
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2590
992
                } else {
2591
184
                    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
184
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2594
184
                }
2595
1.17k
            } 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.17k
        }
2612
572k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2613
572k
    }
2614
572k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2615
218k
        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
218k
        } else {
2624
218k
            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
218k
            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
218k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2629
218k
        }
2630
353k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2631
164k
        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
164k
        } else {
2640
164k
            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
164k
            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
164k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2645
164k
        }
2646
189k
    } 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
189k
    } 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
189k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2697
186k
        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
186k
        } else {
2706
186k
            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
186k
            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
186k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2711
186k
        }
2712
186k
    } 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
572k
}
2733
2734
int
2735
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2736
573k
{
2737
573k
    patch_color_t *c[3];
2738
573k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2739
573k
    int code;
2740
2741
573k
    if (color_stack_ptr == NULL)
2742
0
        return_error(gs_error_unregistered); /* Must not happen. */
2743
573k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2744
573k
    release_colors_inline(pfs, color_stack_ptr, 3);
2745
573k
    return code;
2746
573k
}
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
565k
{
2752
565k
    q[0].c = c[0];
2753
565k
    q[1].c = c[1];
2754
565k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2755
565k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2756
565k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2757
565k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2758
565k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2759
565k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2760
565k
    s0->p[0][0] = p->p[0][0];
2761
565k
    s0->p[0][1] = p->p[0][1];
2762
565k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2763
565k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2764
565k
    s1->p[1][0] = p->p[1][0];
2765
565k
    s1->p[1][1] = p->p[1][1];
2766
565k
}
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.25M
{
2772
1.25M
    q[0].c = c[0];
2773
1.25M
    q[1].c = c[1];
2774
1.25M
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2775
1.25M
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2776
1.25M
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2777
1.25M
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2778
1.25M
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2779
1.25M
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2780
1.25M
    s0->p[0][0] = p->p[0][0];
2781
1.25M
    s0->p[1][0] = p->p[1][0];
2782
1.25M
    s0->p[0][1] = s1->p[0][0] = &q[0];
2783
1.25M
    s0->p[1][1] = s1->p[1][0] = &q[1];
2784
1.25M
    s1->p[0][1] = p->p[0][1];
2785
1.25M
    s1->p[1][1] = p->p[1][1];
2786
1.25M
}
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.11M
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2792
2.11M
    int code, r;
2793
2794
2.11M
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2795
2.11M
    if (code <= 0)
2796
1.95M
        return code;
2797
155k
    r = code << pfs->function_arg_shift;
2798
155k
    if (r & 1)
2799
0
        *not_monotonic_by_u = true;
2800
155k
    if (r & 2)
2801
155k
        *not_monotonic_by_v = true;
2802
155k
    return !code;
2803
2.11M
}
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
43.1M
{
2810
    /* Assuming p.c == c for providing a non-const access. */
2811
43.1M
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2812
43.1M
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2813
43.1M
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2814
43.1M
}
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
84.0M
{
2822
84.0M
    shading_vertex_t p01, p12, p20;
2823
84.0M
    patch_color_t *c[3];
2824
84.0M
    wedge_vertex_list_t L01, L12, L20, L[3];
2825
84.0M
    bool inside_save = pfs->inside;
2826
84.0M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2827
84.0M
    int code = 0;
2828
84.0M
    byte *color_stack_ptr;
2829
84.0M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2830
2831
84.0M
    if (!inside) {
2832
23.4M
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2833
23.4M
        r1 = r;
2834
23.4M
        rect_intersect(r, pfs->rect);
2835
23.4M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2836
9.16M
            return 0;
2837
23.4M
    }
2838
74.9M
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2839
74.9M
    if(color_stack_ptr == NULL)
2840
0
        return_error(gs_error_unregistered);
2841
74.9M
    p01.c = c[0];
2842
74.9M
    p12.c = c[1];
2843
74.9M
    p20.c = c[2];
2844
74.9M
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2845
74.9M
    switch(code) {
2846
33.5M
        case 0: /* The area is filled. */
2847
33.5M
            goto out;
2848
41.1M
        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
41.1M
            if (sd < pfs->decomposition_limit * 4) {
2853
9.54M
                code = constant_color_triangle(pfs, p2, p0, p1);
2854
9.54M
                goto out;
2855
9.54M
            }
2856
31.5M
            if (pfs->Function != NULL) {
2857
7.33M
                double d01 = color_span(pfs, p1->c, p0->c);
2858
7.33M
                double d12 = color_span(pfs, p2->c, p1->c);
2859
7.33M
                double d20 = color_span(pfs, p0->c, p2->c);
2860
2861
7.33M
                if (d01 <= pfs->smoothness / COLOR_CONTIGUITY &&
2862
7.33M
                    d12 <= pfs->smoothness / COLOR_CONTIGUITY &&
2863
7.33M
                    d20 <= pfs->smoothness / COLOR_CONTIGUITY) {
2864
5.92M
                    code = constant_color_triangle(pfs, p2, p0, p1);
2865
5.92M
                    goto out;
2866
5.92M
                }
2867
24.2M
            } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY) {
2868
20.6M
                code = constant_color_triangle(pfs, p2, p0, p1);
2869
20.6M
                goto out;
2870
20.6M
            }
2871
5.00M
            break;
2872
5.00M
        case 1: /* decompose to linear color areas */
2873
317k
            if (sd < pfs->decomposition_limit) {
2874
120k
                code = constant_color_triangle(pfs, p2, p0, p1);
2875
120k
                goto out;
2876
120k
            }
2877
196k
            break;
2878
196k
        default: /* Error. */
2879
0
            goto out;
2880
74.9M
    }
2881
5.19M
    if (!inside) {
2882
837k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2883
837k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
2884
77.5k
            pfs->inside = true;
2885
837k
    }
2886
5.19M
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2887
5.19M
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2888
5.19M
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2889
5.19M
    if (LAZY_WEDGES) {
2890
5.19M
        init_wedge_vertex_list(L, count_of(L));
2891
5.19M
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2892
5.19M
        if (code >= 0)
2893
5.19M
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2894
5.19M
        if (code >= 0)
2895
5.19M
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2896
5.19M
    } 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.19M
    if (code >= 0)
2904
5.19M
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2905
5.19M
    if (code >= 0) {
2906
5.19M
        if (LAZY_WEDGES) {
2907
5.19M
            move_wedge(&L01, l01, true);
2908
5.19M
            move_wedge(&L20, l20, false);
2909
5.19M
        }
2910
5.19M
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2911
5.19M
    }
2912
5.19M
    if (code >= 0) {
2913
5.19M
        if (LAZY_WEDGES)
2914
5.19M
            move_wedge(&L12, l12, true);
2915
5.19M
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2916
5.19M
    }
2917
5.19M
    if (code >= 0) {
2918
5.19M
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2919
5.19M
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2920
5.19M
    }
2921
5.19M
    if (LAZY_WEDGES) {
2922
5.19M
        if (code >= 0)
2923
5.19M
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2924
5.19M
        if (code >= 0)
2925
5.19M
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2926
5.19M
        if (code >= 0)
2927
5.19M
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2928
5.19M
        if (code >= 0)
2929
5.19M
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2930
5.19M
        if (code >= 0)
2931
5.19M
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2932
5.19M
        if (code >= 0)
2933
5.19M
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2934
5.19M
    }
2935
5.19M
    pfs->inside = inside_save;
2936
74.9M
out:
2937
74.9M
    release_colors_inline(pfs, color_stack_ptr, 3);
2938
74.9M
    return code;
2939
5.19M
}
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
63.2M
{
2946
63.2M
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2947
63.2M
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2948
63.2M
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2949
63.2M
    fixed sd1 = max(sd01, sd12);
2950
63.2M
    fixed sd = max(sd1, sd20);
2951
63.2M
    double cd = 0;
2952
2953
#   if SKIP_TEST
2954
        dbg_triangle_cnt++;
2955
#   endif
2956
63.2M
    if (pfs->Function == NULL) {
2957
49.4M
        double d01 = color_span(pfs, p1->c, p0->c);
2958
49.4M
        double d12 = color_span(pfs, p2->c, p1->c);
2959
49.4M
        double d20 = color_span(pfs, p0->c, p2->c);
2960
49.4M
        double cd1 = max(d01, d12);
2961
2962
49.4M
        cd = max(cd1, d20);
2963
49.4M
    }
2964
63.2M
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2965
63.2M
}
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
7.46M
{
2971
7.46M
    int code;
2972
7.46M
    wedge_vertex_list_t l[3];
2973
2974
7.46M
    init_wedge_vertex_list(l, count_of(l));
2975
7.46M
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2976
7.46M
    if (code < 0)
2977
0
        return code;
2978
7.46M
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2979
7.46M
    if (code < 0)
2980
0
        return code;
2981
7.46M
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2982
7.46M
    if (code < 0)
2983
0
        return code;
2984
7.46M
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
2985
7.46M
}
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
8.70M
{
3083
8.70M
    pfs->unlinear = !is_linear_color_applicable(pfs);
3084
8.70M
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3085
8.70M
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3086
8.70M
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3087
7.46M
        return small_mesh_triangle(pfs, p0, p1, p2);
3088
1.24M
    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.24M
        shading_vertex_t p01, p12, p20;
3100
1.24M
        patch_color_t *c[3];
3101
1.24M
        int code;
3102
1.24M
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3103
3104
1.24M
        if (color_stack_ptr == NULL)
3105
0
            return_error(gs_error_unregistered); /* Must not happen. */
3106
1.24M
        p01.c = c[0];
3107
1.24M
        p12.c = c[1];
3108
1.24M
        p20.c = c[2];
3109
1.24M
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3110
1.24M
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3111
1.24M
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3112
1.24M
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3113
1.24M
        if (code >= 0)
3114
1.24M
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3115
1.24M
        if (code >= 0)
3116
1.24M
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3117
1.24M
        if (code >= 0)
3118
1.24M
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3119
1.24M
        if (code >= 0)
3120
1.24M
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3121
1.24M
        if (code >= 0)
3122
1.24M
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3123
1.24M
        if (code >= 0)
3124
1.24M
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3125
1.24M
        release_colors_inline(pfs, color_stack_ptr, 3);
3126
1.24M
        return code;
3127
1.24M
    }
3128
8.70M
}
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
3.74M
{
3134
3.74M
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3135
3.74M
            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.48M
        gx_device *pdev = pfs->dev;
3140
1.48M
        gx_path path;
3141
1.48M
        int code;
3142
1.48M
        fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
3143
1.48M
        fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
3144
1.48M
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3145
3146
1.48M
        gx_path_init_local(&path, pdev->memory);
3147
1.48M
        code = gx_path_add_point(&path, p0->p.x, p0->p.y);
3148
1.48M
        if (code >= 0 && s1 >= 0)
3149
1.47M
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3150
1.48M
        if (code >= 0)
3151
1.48M
            code = gx_path_add_line(&path, p2->p.x, p2->p.y);
3152
1.48M
        if (code >= 0 && s1 < 0)
3153
8.43k
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3154
1.48M
        if (code >= 0)
3155
1.48M
            code = gx_path_close_subpath(&path);
3156
1.48M
        if (code >= 0)
3157
1.48M
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3158
1.48M
        gx_path_free(&path, "mesh_triangle");
3159
1.48M
        if (code < 0)
3160
0
            return code;
3161
1.48M
    }
3162
3.74M
    return mesh_triangle_rec(pfs, p0, p1, p2);
3163
3.74M
}
3164
3165
static inline int
3166
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3167
7.94M
{
3168
7.94M
    shading_vertex_t p0001, p1011, q;
3169
7.94M
    patch_color_t *c[3];
3170
7.94M
    wedge_vertex_list_t l[4];
3171
7.94M
    int code;
3172
7.94M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3173
3174
7.94M
    if(color_stack_ptr == NULL)
3175
0
        return_error(gs_error_unregistered); /* Must not happen. */
3176
7.94M
    p0001.c = c[0];
3177
7.94M
    p1011.c = c[1];
3178
7.94M
    q.c = c[2];
3179
7.94M
    init_wedge_vertex_list(l, count_of(l));
3180
7.94M
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3181
7.94M
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3182
7.94M
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3183
7.94M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3184
7.94M
    if (code >= 0) {
3185
7.94M
        l[0].last_side = true;
3186
7.94M
        l[3].last_side = true;
3187
7.94M
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3188
7.94M
    }
3189
7.94M
    if (code >= 0) {
3190
7.94M
        l[1].last_side = true;
3191
7.94M
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3192
7.94M
    }
3193
7.94M
    if (code >= 0) {
3194
7.94M
        l[2].last_side = true;
3195
7.94M
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3196
7.94M
    }
3197
7.94M
    if (code >= 0)
3198
7.94M
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3199
7.94M
    if (code >= 0)
3200
7.94M
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3201
7.94M
    if (code >= 0)
3202
7.94M
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3203
7.94M
    if (code >= 0)
3204
7.94M
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3205
7.94M
    release_colors_inline(pfs, color_stack_ptr, 3);
3206
7.94M
    return code;
3207
7.94M
}
3208
3209
static inline int
3210
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3211
12.0M
{
3212
12.0M
    wedge_vertex_list_t l;
3213
12.0M
    int code;
3214
3215
12.0M
    init_wedge_vertex_list(&l, 1);
3216
12.0M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3217
12.0M
    if (code < 0)
3218
0
        return code;
3219
12.0M
    l.last_side = true;
3220
12.0M
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3221
12.0M
    if (code < 0)
3222
0
        return code;
3223
12.0M
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3224
12.0M
    if (code < 0)
3225
0
        return code;
3226
12.0M
    return 0;
3227
12.0M
}
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
21.0M
{
3233
21.0M
    qq[0][0].p = p->pole[0][0];
3234
21.0M
    qq[0][1].p = p->pole[0][3];
3235
21.0M
    qq[1][0].p = p->pole[3][0];
3236
21.0M
    qq[1][1].p = p->pole[3][3];
3237
21.0M
    qq[0][0].c = p->c[0][0];
3238
21.0M
    qq[0][1].c = p->c[0][1];
3239
21.0M
    qq[1][0].c = p->c[1][0];
3240
21.0M
    qq[1][1].c = p->c[1][1];
3241
21.0M
    q->p[0][0] = &qq[0][0];
3242
21.0M
    q->p[0][1] = &qq[0][1];
3243
21.0M
    q->p[1][0] = &qq[1][0];
3244
21.0M
    q->p[1][1] = &qq[1][1];
3245
21.0M
    q->l0001 = &l[0];
3246
21.0M
    q->l0111 = &l[1];
3247
21.0M
    q->l1110 = &l[2];
3248
21.0M
    q->l1000 = &l[3];
3249
21.0M
}
3250
3251
static inline int
3252
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3253
13.6M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3254
13.6M
    int code;
3255
3256
13.6M
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3257
13.6M
    if (code <= 0)
3258
784
        return code;
3259
13.6M
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3260
13.6M
}
3261
3262
static inline int
3263
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3264
831k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3265
831k
    int code;
3266
3267
831k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3268
831k
    if (code <= 0)
3269
171k
        return code;
3270
660k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3271
831k
}
3272
3273
static inline int
3274
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3275
751k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3276
751k
    int code;
3277
3278
751k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3279
751k
    if (code <= 0)
3280
128k
        return code;
3281
622k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3282
751k
}
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
20.9M
{
3297
20.9M
    patch_color_t d0001, d1011, d;
3298
20.9M
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3299
20.9M
    double Du, Dv;
3300
3301
20.9M
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3302
20.9M
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3303
20.9M
    D0001 = color_norm(pfs, &d0001);
3304
20.9M
    D1011 = color_norm(pfs, &d1011);
3305
20.9M
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3306
20.9M
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3307
20.9M
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3308
20.9M
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3309
20.9M
    if (pfs->unlinear) {
3310
6.96M
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
3311
6.96M
            D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
3312
6.96M
            D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
3313
5.41M
            return color_change_small;
3314
1.55M
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
3315
381k
            if (!is_big_v) {
3316
                /* The color function looks uncontiguous. */
3317
73.3k
                return color_change_small;
3318
73.3k
            }
3319
307k
            *divide_v = true;
3320
307k
            return color_change_gradient;
3321
381k
        }
3322
1.17M
        if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
3323
1.14M
            if (!is_big_u) {
3324
                /* The color function looks uncontiguous. */
3325
8.12k
                return color_change_small;
3326
8.12k
            }
3327
1.13M
            *divide_u = true;
3328
1.13M
            return color_change_gradient;
3329
1.14M
        }
3330
1.17M
    }
3331
14.0M
    color_diff(pfs, &d0001, &d1011, &d);
3332
14.0M
    Du = max(D0001, D1011);
3333
14.0M
    Dv = max(D0010, D0111);
3334
14.0M
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3335
1.30M
        return color_change_small;
3336
12.7M
    if (Du <= pfs->smoothness / 8)
3337
246k
        return color_change_linear;
3338
12.4M
    if (Dv <= pfs->smoothness / 8)
3339
11.7M
        return color_change_linear;
3340
717k
    D = color_norm(pfs, &d);
3341
717k
    if (D <= pfs->smoothness)
3342
617k
        return color_change_bilinear;
3343
100k
#if 1
3344
100k
    if (Du > Dv && is_big_u)
3345
51.8k
        *divide_u = true;
3346
48.2k
    else if (Du < Dv && is_big_v)
3347
35.9k
        *divide_v = true;
3348
12.3k
    else if (is_big_u && size_u > size_v)
3349
4.89k
        *divide_u = true;
3350
7.44k
    else if (is_big_v && size_v > size_u)
3351
7.44k
        *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
100k
    return color_change_general;
3368
100k
}
3369
3370
static int
3371
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3372
24.6M
{
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
24.6M
    quadrangle_patch s0, s1;
3377
24.6M
    wedge_vertex_list_t l0, l1, l2;
3378
24.6M
    int code;
3379
24.6M
    bool divide_u = false, divide_v = false, big1 = big;
3380
24.6M
    shading_vertex_t q[2];
3381
24.6M
    bool monotonic_color_save = pfs->monotonic_color;
3382
24.6M
    bool linear_color_save = pfs->linear_color;
3383
24.6M
    bool inside_save = pfs->inside;
3384
24.6M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3385
24.6M
    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
24.6M
    if (!inside) {
3389
7.51M
        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
7.51M
        r1 = r;
3391
7.51M
        rect_intersect(r, pfs->rect);
3392
7.51M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3393
2.32M
            return 0; /* Outside. */
3394
7.51M
    }
3395
22.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
18.8M
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3401
18.8M
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3402
18.8M
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3403
18.8M
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3404
18.8M
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3405
18.8M
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3406
18.8M
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3407
18.8M
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3408
3409
18.8M
        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
18.8M
            big1 = false;
3422
18.8M
    }
3423
22.3M
    if (!big1) {
3424
22.3M
        bool is_big_u = false, is_big_v = false;
3425
22.3M
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3426
22.3M
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3427
22.3M
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3428
22.3M
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3429
22.3M
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3430
22.3M
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3431
22.3M
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3432
22.3M
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3433
22.3M
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3434
22.3M
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3435
3436
22.3M
        if (size_u > pfs->decomposition_limit)
3437
21.1M
            is_big_u = true;
3438
22.3M
        if (size_v > pfs->decomposition_limit)
3439
1.82M
            is_big_v = true;
3440
20.5M
        else if (!is_big_u)
3441
1.10M
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3442
1.00M
                        constant_color_quadrangle : triangles4)(pfs, p,
3443
1.10M
                            pfs->maybe_self_intersecting);
3444
21.2M
        if (!pfs->monotonic_color) {
3445
2.11M
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3446
3447
2.11M
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3448
2.11M
            if (code < 0)
3449
0
                return code;
3450
2.11M
            if (is_big_u)
3451
2.10M
                divide_u = not_monotonic_by_u;
3452
2.11M
            if (is_big_v)
3453
382k
                divide_v = not_monotonic_by_v;
3454
2.11M
            if (!divide_u && !divide_v)
3455
2.00M
                pfs->monotonic_color = true;
3456
2.11M
        }
3457
21.2M
        if (pfs->monotonic_color && !pfs->linear_color) {
3458
18.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
18.4M
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3464
14.0M
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3465
13.6M
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3466
13.6M
                    if (code < 0)
3467
0
                        return code;
3468
13.6M
                    divide_u = !code;
3469
13.6M
                }
3470
14.0M
                if (is_big_v) {
3471
831k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3472
831k
                    if (code < 0)
3473
0
                        return code;
3474
831k
                    divide_v = !code;
3475
831k
                }
3476
14.0M
                if (is_big_u && is_big_v) {
3477
751k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3478
751k
                    if (code < 0)
3479
0
                        return code;
3480
751k
                    if (!code) {
3481
129k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3482
66.0k
                            divide_u = true;
3483
66.0k
                            divide_v = false;
3484
66.0k
                        } else {
3485
63.2k
                            divide_v = true;
3486
63.2k
                            divide_u = false;
3487
63.2k
                        }
3488
129k
                    }
3489
751k
                }
3490
14.0M
            }
3491
18.4M
            if (!divide_u && !divide_v)
3492
18.2M
                pfs->linear_color = true;
3493
18.4M
        }
3494
21.2M
        if (!pfs->linear_color) {
3495
            /* go to divide. */
3496
20.9M
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3497
6.79M
            case color_change_small:
3498
6.79M
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3499
6.32M
                            constant_color_quadrangle : triangles4)(pfs, p,
3500
6.79M
                                pfs->maybe_self_intersecting);
3501
6.79M
                pfs->monotonic_color = monotonic_color_save;
3502
6.79M
                pfs->linear_color = linear_color_save;
3503
6.79M
                return code;
3504
617k
            case color_change_bilinear:
3505
617k
                if (!QUADRANGLES) {
3506
617k
                    code = triangles4(pfs, p, true);
3507
617k
                    pfs->monotonic_color = monotonic_color_save;
3508
617k
                    pfs->linear_color = linear_color_save;
3509
617k
                    return code;
3510
617k
                }
3511
12.0M
            case color_change_linear:
3512
12.0M
                if (!QUADRANGLES) {
3513
12.0M
                    code = triangles2(pfs, p, true);
3514
12.0M
                    pfs->monotonic_color = monotonic_color_save;
3515
12.0M
                    pfs->linear_color = linear_color_save;
3516
12.0M
                    return code;
3517
12.0M
                }
3518
1.44M
            case color_change_gradient:
3519
1.54M
            case color_change_general:
3520
1.54M
                ; /* goto divide. */
3521
20.9M
        }
3522
21.2M
    }
3523
1.82M
    if (!inside) {
3524
355k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3525
355k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3526
101k
            pfs->inside = true;
3527
355k
    }
3528
1.82M
    if (LAZY_WEDGES)
3529
1.82M
        init_wedge_vertex_list(&l0, 1);
3530
1.82M
    if (divide_v) {
3531
565k
        patch_color_t *c[2];
3532
565k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3533
3534
565k
        if(color_stack_ptr == NULL)
3535
0
            return_error(gs_error_unregistered); /* Must not happen. */
3536
565k
        q[0].c = c[0];
3537
565k
        q[1].c = c[1];
3538
565k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3539
565k
        if (LAZY_WEDGES) {
3540
565k
            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
565k
            if (code >= 0)
3542
565k
                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
565k
            if (code >= 0) {
3544
565k
                s0.l1110 = s1.l0001 = &l0;
3545
565k
                s0.l0111 = s1.l0111 = &l1;
3546
565k
                s0.l1000 = s1.l1000 = &l2;
3547
565k
                s0.l0001 = p->l0001;
3548
565k
                s1.l1110 = p->l1110;
3549
565k
            }
3550
565k
        } 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
565k
        if (code >= 0)
3556
565k
            code = fill_quadrangle(pfs, &s0, big1);
3557
565k
        if (code >= 0) {
3558
565k
            if (LAZY_WEDGES) {
3559
565k
                l0.last_side = true;
3560
565k
                move_wedge(&l1, p->l0111, true);
3561
565k
                move_wedge(&l2, p->l1000, false);
3562
565k
            }
3563
565k
            code = fill_quadrangle(pfs, &s1, big1);
3564
565k
        }
3565
565k
        if (LAZY_WEDGES) {
3566
565k
            if (code >= 0)
3567
565k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3568
565k
            if (code >= 0)
3569
565k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3570
565k
            if (code >= 0)
3571
565k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3572
565k
            release_colors_inline(pfs, color_stack_ptr, 2);
3573
565k
        }
3574
1.25M
    } else if (divide_u) {
3575
1.25M
        patch_color_t *c[2];
3576
1.25M
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3577
3578
1.25M
        if(color_stack_ptr == NULL)
3579
0
            return_error(gs_error_unregistered); /* Must not happen. */
3580
1.25M
        q[0].c = c[0];
3581
1.25M
        q[1].c = c[1];
3582
1.25M
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3583
1.25M
        if (LAZY_WEDGES) {
3584
1.25M
            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.25M
            if (code >= 0)
3586
1.25M
                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.25M
            if (code >= 0) {
3588
1.25M
                s0.l0111 = s1.l1000 = &l0;
3589
1.25M
                s0.l0001 = s1.l0001 = &l1;
3590
1.25M
                s0.l1110 = s1.l1110 = &l2;
3591
1.25M
                s0.l1000 = p->l1000;
3592
1.25M
                s1.l0111 = p->l0111;
3593
1.25M
            }
3594
1.25M
        } 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.25M
        if (code >= 0)
3600
1.25M
            code = fill_quadrangle(pfs, &s0, big1);
3601
1.25M
        if (code >= 0) {
3602
1.25M
            if (LAZY_WEDGES) {
3603
1.25M
                l0.last_side = true;
3604
1.25M
                move_wedge(&l1, p->l0001, true);
3605
1.25M
                move_wedge(&l2, p->l1110, false);
3606
1.25M
            }
3607
1.25M
            code = fill_quadrangle(pfs, &s1, big1);
3608
1.25M
        }
3609
1.25M
        if (LAZY_WEDGES) {
3610
1.25M
            if (code >= 0)
3611
1.25M
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3612
1.25M
            if (code >= 0)
3613
1.25M
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3614
1.25M
            if (code >= 0)
3615
1.25M
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3616
1.25M
            release_colors_inline(pfs, color_stack_ptr, 2);
3617
1.25M
        }
3618
1.25M
    } 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.82M
    pfs->monotonic_color = monotonic_color_save;
3623
1.82M
    pfs->linear_color = linear_color_save;
3624
1.82M
    pfs->inside = inside_save;
3625
1.82M
    return code;
3626
1.82M
}
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
36.2M
{
3632
36.2M
    s0->c[0][1] = c[0];
3633
36.2M
    s0->c[1][1] = c[1];
3634
36.2M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3635
36.2M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3636
36.2M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3637
36.2M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3638
36.2M
    s0->c[0][0] = p->c[0][0];
3639
36.2M
    s0->c[1][0] = p->c[1][0];
3640
36.2M
    s1->c[0][0] = s0->c[0][1];
3641
36.2M
    s1->c[1][0] = s0->c[1][1];
3642
36.2M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3643
36.2M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3644
36.2M
    s1->c[0][1] = p->c[0][1];
3645
36.2M
    s1->c[1][1] = p->c[1][1];
3646
36.2M
}
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
8.26M
{
3652
8.26M
    s0->c[1][0] = c[0];
3653
8.26M
    s0->c[1][1] = c[1];
3654
8.26M
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3655
8.26M
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3656
8.26M
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3657
8.26M
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3658
8.26M
    s0->c[0][0] = p->c[0][0];
3659
8.26M
    s0->c[0][1] = p->c[0][1];
3660
8.26M
    s1->c[0][0] = s0->c[1][0];
3661
8.26M
    s1->c[0][1] = s0->c[1][1];
3662
8.26M
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3663
8.26M
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3664
8.26M
    s1->c[1][0] = p->c[1][0];
3665
8.26M
    s1->c[1][1] = p->c[1][1];
3666
8.26M
}
3667
3668
static inline void
3669
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3670
59.3M
{
3671
59.3M
    int i, j;
3672
3673
59.3M
    r->p.x = r->q.x = p->pole[0][0].x;
3674
59.3M
    r->p.y = r->q.y = p->pole[0][0].y;
3675
296M
    for (i = 0; i < 4; i++) {
3676
1.18G
        for (j = 0; j < 4; j++) {
3677
950M
            const gs_fixed_point *q = &p->pole[i][j];
3678
3679
950M
            if (r->p.x > q->x)
3680
148M
                r->p.x = q->x;
3681
950M
            if (r->p.y > q->y)
3682
141M
                r->p.y = q->y;
3683
950M
            if (r->q.x < q->x)
3684
173M
                r->q.x = q->x;
3685
950M
            if (r->q.y < q->y)
3686
135M
                r->q.y = q->y;
3687
950M
        }
3688
237M
    }
3689
59.3M
}
3690
3691
static int
3692
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3693
81.1M
{
3694
81.1M
    if (ku > 1) {
3695
60.0M
        tensor_patch s0, s1;
3696
60.0M
        patch_color_t *c[2];
3697
60.0M
        int code;
3698
60.0M
        byte *color_stack_ptr;
3699
60.0M
        bool save_inside = pfs->inside;
3700
3701
60.0M
        if (!pfs->inside) {
3702
50.8M
            gs_fixed_rect r, r1;
3703
3704
50.8M
            tensor_patch_bbox(&r, p);
3705
50.8M
            r1 = r;
3706
50.8M
            rect_intersect(r, pfs->rect);
3707
50.8M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3708
23.8M
                return 0;
3709
26.9M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3710
26.9M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3711
2.29M
                pfs->inside = true;
3712
26.9M
        }
3713
36.2M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3714
36.2M
        if(color_stack_ptr == NULL)
3715
0
            return_error(gs_error_unregistered); /* Must not happen. */
3716
36.2M
        split_stripe(pfs, &s0, &s1, p, c);
3717
36.2M
        code = decompose_stripe(pfs, &s0, ku / 2);
3718
36.2M
        if (code >= 0)
3719
36.2M
            code = decompose_stripe(pfs, &s1, ku / 2);
3720
36.2M
        release_colors_inline(pfs, color_stack_ptr, 2);
3721
36.2M
        pfs->inside = save_inside;
3722
36.2M
        return code;
3723
36.2M
    } else {
3724
21.0M
        quadrangle_patch q;
3725
21.0M
        shading_vertex_t qq[2][2];
3726
21.0M
        wedge_vertex_list_t l[4];
3727
21.0M
        int code;
3728
3729
21.0M
        init_wedge_vertex_list(l, count_of(l));
3730
21.0M
        make_quadrangle(p, qq, l, &q);
3731
#       if SKIP_TEST
3732
            dbg_quad_cnt++;
3733
#       endif
3734
21.0M
        code = fill_quadrangle(pfs, &q, true);
3735
21.0M
        if (code < 0)
3736
0
            return code;
3737
21.0M
        if (LAZY_WEDGES) {
3738
21.0M
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3739
21.0M
            if (code < 0)
3740
0
                return code;
3741
21.0M
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3742
21.0M
            if (code < 0)
3743
0
                return code;
3744
21.0M
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3745
21.0M
            if (code < 0)
3746
0
                return code;
3747
21.0M
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3748
21.0M
            if (code < 0)
3749
0
                return code;
3750
21.0M
        }
3751
21.0M
        return code;
3752
21.0M
    }
3753
81.1M
}
3754
3755
static int
3756
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3757
8.69M
{
3758
    /* The stripe is flattened enough by V, so ignore inner poles. */
3759
8.69M
    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
8.69M
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3768
8.69M
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3769
8.69M
    kum = max(ku[0], ku[3]);
3770
8.69M
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3771
8.69M
    if (code < 0)
3772
0
        return code;
3773
8.69M
    if (INTERPATCH_PADDING) {
3774
8.69M
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3775
8.69M
        if (code < 0)
3776
11
            return code;
3777
8.69M
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3778
8.69M
        if (code < 0)
3779
0
            return code;
3780
8.69M
    }
3781
8.69M
    code = decompose_stripe(pfs, p, kum);
3782
8.69M
    if (code < 0)
3783
0
        return code;
3784
8.69M
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3785
8.69M
}
3786
3787
static inline bool neqs(int *a, int b)
3788
23.9M
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3789
23.9M
    if (*a * b < 0)
3790
7.97M
        return true;
3791
15.9M
    if (!*a)
3792
1.24M
        *a = b;
3793
15.9M
    return false;
3794
23.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
32.6M
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3799
32.6M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3800
32.6M
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3801
3802
32.6M
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3803
32.6M
}
3804
3805
static inline bool
3806
is_x_bended(const tensor_patch *p)
3807
8.73M
{
3808
8.73M
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3809
3810
8.73M
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3811
4.67M
        return true;
3812
4.05M
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3813
2.51M
        return true;
3814
1.54M
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3815
761k
        return true;
3816
3817
784k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3818
7.50k
        return true;
3819
776k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3820
0
        return true;
3821
776k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3822
3.64k
        return true;
3823
773k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3824
3.62k
        return true;
3825
3826
769k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3827
3.90k
        return true;
3828
765k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3829
0
        return true;
3830
765k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3831
3.14k
        return true;
3832
762k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3833
3.18k
        return true;
3834
3835
759k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3836
799
        return true;
3837
758k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3838
0
        return true;
3839
758k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3840
743
        return true;
3841
757k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3842
540
        return true;
3843
757k
    return false;
3844
757k
}
3845
3846
static inline bool
3847
is_y_bended(const tensor_patch *p)
3848
24.4k
{
3849
24.4k
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3850
3851
24.4k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3852
195
        return true;
3853
24.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3854
113
        return true;
3855
24.1k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3856
22
        return true;
3857
3858
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3859
0
        return true;
3860
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3861
0
        return true;
3862
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3863
2
        return true;
3864
24.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3865
1
        return true;
3866
3867
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3868
4
        return true;
3869
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3870
0
        return true;
3871
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3872
0
        return true;
3873
24.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3874
0
        return true;
3875
3876
24.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3877
0
        return true;
3878
24.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3879
0
        return true;
3880
24.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3881
0
        return true;
3882
24.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3883
0
        return true;
3884
24.0k
    return false;
3885
24.0k
}
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
51.1M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3890
51.1M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3891
51.1M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3892
51.1M
    fixed xmin =  min(xmin0, xmin1);
3893
51.1M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3894
51.1M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3895
51.1M
    fixed xmax =  max(xmax0, xmax1);
3896
3897
51.1M
    if(xmax - xmin <= pfs->decomposition_limit)
3898
43.5M
        return true;
3899
7.59M
    return false;
3900
51.1M
}
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
34.1M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3905
34.1M
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3906
34.1M
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3907
34.1M
    fixed ymin =  min(ymin0, ymin1);
3908
34.1M
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3909
34.1M
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3910
34.1M
    fixed ymax =  max(ymax0, ymax1);
3911
3912
34.1M
    if (ymax - ymin <= pfs->decomposition_limit)
3913
33.0M
        return true;
3914
1.07M
    return false;
3915
34.1M
}
3916
3917
static inline bool
3918
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3919
16.6M
{
3920
16.6M
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3921
3.09M
        return false;
3922
13.5M
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3923
2.32M
        return false;
3924
11.2M
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3925
1.47M
        return false;
3926
9.73M
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3927
702k
        return false;
3928
9.03M
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3929
376k
        return false;
3930
8.65M
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3931
312k
        return false;
3932
8.34M
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3933
209k
        return false;
3934
8.13M
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3935
173k
        return false;
3936
7.96M
    return true;
3937
8.13M
}
3938
3939
static int
3940
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3941
17.3M
{
3942
17.3M
    if (kv <= 1) {
3943
16.6M
        if (is_patch_narrow(pfs, p))
3944
7.96M
            return fill_stripe(pfs, p);
3945
8.66M
        if (!is_x_bended(p))
3946
732k
            return fill_stripe(pfs, p);
3947
8.66M
    }
3948
8.69M
    {   tensor_patch s0, s1;
3949
8.69M
        patch_color_t *c[2];
3950
8.69M
        shading_vertex_t q0, q1, q2;
3951
8.69M
        int code = 0;
3952
8.69M
        byte *color_stack_ptr;
3953
8.69M
        bool save_inside = pfs->inside;
3954
3955
8.69M
        if (!pfs->inside) {
3956
8.55M
            gs_fixed_rect r, r1;
3957
3958
8.55M
            tensor_patch_bbox(&r, p);
3959
8.55M
            r.p.x -= INTERPATCH_PADDING;
3960
8.55M
            r.p.y -= INTERPATCH_PADDING;
3961
8.55M
            r.q.x += INTERPATCH_PADDING;
3962
8.55M
            r.q.y += INTERPATCH_PADDING;
3963
8.55M
            r1 = r;
3964
8.55M
            rect_intersect(r, pfs->rect);
3965
8.55M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3966
428k
                return 0;
3967
8.13M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3968
8.13M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3969
49.6k
                pfs->inside = true;
3970
8.13M
        }
3971
8.26M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3972
8.26M
        if(color_stack_ptr == NULL)
3973
0
            return_error(gs_error_unregistered); /* Must not happen. */
3974
8.26M
        split_patch(pfs, &s0, &s1, p, c);
3975
8.26M
        if (kv0 <= 1) {
3976
7.98M
            q0.p = s0.pole[0][0];
3977
7.98M
            q0.c = s0.c[0][0];
3978
7.98M
            q1.p = s1.pole[3][0];
3979
7.98M
            q1.c = s1.c[1][0];
3980
7.98M
            q2.p = s0.pole[3][0];
3981
7.98M
            q2.c = s0.c[1][0];
3982
7.98M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3983
7.98M
        }
3984
8.26M
        if (kv1 <= 1 && code >= 0) {
3985
7.97M
            q0.p = s0.pole[0][3];
3986
7.97M
            q0.c = s0.c[0][1];
3987
7.97M
            q1.p = s1.pole[3][3];
3988
7.97M
            q1.c = s1.c[1][1];
3989
7.97M
            q2.p = s0.pole[3][3];
3990
7.97M
            q2.c = s0.c[1][1];
3991
7.97M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3992
7.97M
        }
3993
8.26M
        if (code >= 0)
3994
8.26M
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
3995
8.26M
        if (code >= 0)
3996
8.26M
            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
8.26M
        release_colors_inline(pfs, color_stack_ptr, 2);
4017
8.26M
        pfs->inside = save_inside;
4018
8.26M
        return code;
4019
8.26M
    }
4020
8.26M
}
4021
4022
static inline int64_t
4023
lcp1(int64_t p0, int64_t p3)
4024
4.44M
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4025
4.44M
    return (p0 + p0 + p3);
4026
4.44M
}
4027
static inline int64_t
4028
lcp2(int64_t p0, int64_t p3)
4029
4.44M
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4030
4.44M
    return (p0 + p3 + p3);
4031
4.44M
}
4032
4033
static void
4034
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4035
3.42M
{
4036
3.42M
    if (pfs->Function) {
4037
888k
        c->t[0] = cc[0];
4038
888k
        c->t[1] = cc[1];
4039
888k
    } else
4040
2.53M
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4041
3.42M
}
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
855k
{
4047
855k
    const gs_color_space *pcs = pfs->direct_space;
4048
4049
855k
    p->pole[0][0] = curve[0].vertex.p;
4050
855k
    p->pole[1][0] = curve[0].control[0];
4051
855k
    p->pole[2][0] = curve[0].control[1];
4052
855k
    p->pole[3][0] = curve[1].vertex.p;
4053
855k
    p->pole[3][1] = curve[1].control[0];
4054
855k
    p->pole[3][2] = curve[1].control[1];
4055
855k
    p->pole[3][3] = curve[2].vertex.p;
4056
855k
    p->pole[2][3] = curve[2].control[0];
4057
855k
    p->pole[1][3] = curve[2].control[1];
4058
855k
    p->pole[0][3] = curve[3].vertex.p;
4059
855k
    p->pole[0][2] = curve[3].control[0];
4060
855k
    p->pole[0][1] = curve[3].control[1];
4061
855k
    if (interior != NULL) {
4062
633k
        p->pole[1][1] = interior[0];
4063
633k
        p->pole[1][2] = interior[1];
4064
633k
        p->pole[2][2] = interior[2];
4065
633k
        p->pole[2][1] = interior[3];
4066
633k
    } else {
4067
222k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4068
222k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4069
222k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4070
222k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4071
222k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4072
222k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4073
222k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4074
222k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4075
222k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4076
222k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4077
222k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4078
222k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4079
222k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4080
222k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4081
222k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4082
222k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4083
4084
222k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4085
222k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4086
222k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4087
222k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4088
222k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4089
222k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4090
222k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4091
222k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4092
222k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4093
222k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4094
222k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4095
222k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4096
222k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4097
222k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4098
222k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4099
222k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4100
222k
    }
4101
855k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4102
855k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4103
855k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4104
855k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4105
855k
    patch_resolve_color_inline(p->c[0][0], pfs);
4106
855k
    patch_resolve_color_inline(p->c[0][1], pfs);
4107
855k
    patch_resolve_color_inline(p->c[1][0], pfs);
4108
855k
    patch_resolve_color_inline(p->c[1][1], pfs);
4109
855k
    if (!pfs->Function) {
4110
633k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4111
633k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4112
633k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4113
633k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4114
633k
    }
4115
855k
}
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
77.6k
{
4121
77.6k
    gs_fixed_edge le, re;
4122
4123
77.6k
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4124
77.6k
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4125
77.6k
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4126
77.6k
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4127
77.6k
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4128
77.6k
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4129
77.6k
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4130
77.6k
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4131
77.6k
    return dev_proc(pdev, fill_trapezoid)(pdev,
4132
77.6k
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4133
77.6k
}
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
855k
{
4141
855k
    tensor_patch p;
4142
855k
    patch_color_t *c[4];
4143
855k
    int kv[4], kvm, ku[4], kum;
4144
855k
    int code = 0;
4145
855k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4146
4147
855k
    p.c[0][0] = c[0];
4148
855k
    p.c[0][1] = c[1];
4149
855k
    p.c[1][0] = c[2];
4150
855k
    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
855k
    make_tensor_patch(pfs, &p, curve, interior);
4159
855k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4160
855k
    pfs->linear_color = false;
4161
855k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4162
855k
            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
65.1k
        gx_device *pdev = pfs->dev;
4167
65.1k
        gx_path path;
4168
65.1k
        fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
4169
65.1k
        fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
4170
65.1k
        fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
4171
65.1k
        fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
4172
65.1k
        fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
4173
65.1k
        fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
4174
65.1k
        fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
4175
65.1k
        fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
4176
65.1k
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
4177
65.1k
        int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
4178
65.1k
        int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
4179
4180
65.1k
        gx_path_init_local(&path, pdev->memory);
4181
65.1k
        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
41.0k
        } else {
4187
24.0k
            code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
4188
120k
            for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
4189
96.3k
                j = (i + s) % 4, jj = (s == 1 ? i : j);
4190
96.3k
                if (curve[jj].straight)
4191
20.7k
                    code = gx_path_add_line(&path, curve[j].vertex.p.x,
4192
96.3k
                                                curve[j].vertex.p.y);
4193
75.5k
                else
4194
75.5k
                    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
4195
96.3k
                                                    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
4196
96.3k
                                                    curve[j].vertex.p.x,
4197
96.3k
                                                    curve[j].vertex.p.y);
4198
96.3k
            }
4199
24.0k
            if (code >= 0)
4200
24.0k
                code = gx_path_close_subpath(&path);
4201
24.0k
        }
4202
65.1k
        if (code >= 0)
4203
65.1k
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
4204
65.1k
        gx_path_free(&path, "patch_fill");
4205
65.1k
        if (code < 0)
4206
0
            goto out;
4207
65.1k
    }
4208
    /* How many subdivisions of the patch in the u and v direction? */
4209
855k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4210
855k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4211
855k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4212
855k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4213
855k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4214
855k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4215
855k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4216
855k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4217
855k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4218
855k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4219
#   if NOFILL_TEST
4220
    dbg_nofill = false;
4221
#   endif
4222
855k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4223
855k
        interpatch_padding | inpatch_wedge);
4224
855k
    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
855k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4237
855k
    }
4238
855k
    if (code >= 0)
4239
855k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4240
855k
                interpatch_padding | inpatch_wedge);
4241
855k
out:
4242
855k
    release_colors_inline(pfs, color_stack_ptr, 4);
4243
855k
    return code;
4244
855k
}