Coverage Report

Created: 2025-06-10 07:15

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