Coverage Report

Created: 2026-08-08 08:00

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