Coverage Report

Created: 2025-06-10 06:59

/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
2.20k
{
87
2.20k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
2.20k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
2.20k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
2.20k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
2.20k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
2.20k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
2.20k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
2.20k
    pfs->color_stack_ptr = pfs->color_stack;
98
2.20k
    pfs->memory = memory;
99
2.20k
    return 0;
100
2.20k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
3.15M
{
105
3.15M
    int i;
106
3.15M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
9.86M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
6.71M
        c[i] = (patch_color_t *)ptr;
110
3.15M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
3.15M
    pfs->color_stack_ptr = ptr;
115
3.15M
    return ptr0;
116
3.15M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
15
{
121
15
    return reserve_colors_inline(pfs, c, n);
122
15
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
3.15M
{
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
3.15M
    pfs->color_stack_ptr = ptr;
132
3.15M
#endif
133
3.15M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
15
{
137
15
    release_colors_inline(pfs, ptr, n);
138
15
}
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
54.6k
{
145
54.6k
    int i, code = 0;
146
147
230k
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
175k
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
175k
        code = shade_next_color(cs, curves[i].vertex.cc);
150
175k
    }
151
54.6k
    return code;
152
54.6k
}
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
142k
{
158
142k
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
142k
    if (code >= 0)
161
142k
        code = shade_next_coords(cs, curve->control,
162
142k
                                 countof(curve->control));
163
142k
    return code;
164
142k
}
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
54.7k
{
174
54.7k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
54.7k
    int num_colors, code;
176
177
54.7k
    if (flag < 0) {
178
68
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
68
        return 1;               /* no more data */
181
68
    }
182
54.7k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
54.7k
    cs->first_patch = 0;
186
54.7k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
33.1k
        case 0:
190
33.1k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
33.1k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
33.1k
                )
193
2
                return code;
194
33.1k
            num_colors = 4;
195
33.1k
            goto vx;
196
5.62k
        case 1:
197
5.62k
            curve[0] = curve[1], curve[1].vertex = curve[2].vertex;
198
5.62k
            goto v3;
199
6.07k
        case 2:
200
6.07k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
6.07k
            goto v3;
202
9.85k
        case 3:
203
9.85k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
21.5k
v3:         num_colors = 2;
205
54.7k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
54.7k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
54.7k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
54.7k
                (interior != 0 &&
209
54.6k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
54.7k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
54.6k
                                          num_colors)) < 0
212
54.7k
                )
213
32
                return code;
214
54.6k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
54.7k
    }
216
54.6k
    return 0;
217
54.7k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
63.6k
{
222
63.6k
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
63.6k
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
0
        return false;
226
63.6k
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
0
        return false;
228
63.6k
    return true;
229
63.6k
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
2.20k
{
234
2.20k
    int code;
235
236
2.20k
    pfs->memory = memory;
237
2.20k
#   if LAZY_WEDGES
238
2.20k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
2.20k
        if (code < 0)
240
0
            return code;
241
2.20k
#   endif
242
2.20k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
2.20k
    code = allocate_color_stack(pfs, memory);
244
2.20k
    if (code < 0)
245
0
        return code;
246
2.20k
    if (pfs->unlinear || pcs == NULL)
247
0
        pfs->pcic = NULL;
248
2.20k
    else {
249
2.20k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
2.20k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
2.20k
    }
253
2.20k
    return 0;
254
2.20k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
2.20k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
2.20k
    const gs_color_space *pcs = pfs->direct_space;
261
2.20k
    gs_client_color fcc0, fcc1;
262
2.20k
    int i;
263
264
8.05k
    for (i = 0; i < pfs->num_components; i++) {
265
5.85k
        fcc0.paint.values[i] = -1000000;
266
5.85k
        fcc1.paint.values[i] = 1000000;
267
5.85k
    }
268
2.20k
    pcs->type->restrict_color(&fcc0, pcs);
269
2.20k
    pcs->type->restrict_color(&fcc1, pcs);
270
8.05k
    for (i = 0; i < pfs->num_components; i++)
271
5.85k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
2.20k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
2.20k
    pfs->maybe_self_intersecting = true;
274
2.20k
    pfs->monotonic_color = (pfs->Function == NULL);
275
2.20k
    pfs->function_arg_shift = 0;
276
2.20k
    pfs->linear_color = false;
277
2.20k
    pfs->inside = false;
278
2.20k
    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
2.20k
    pfs->decomposition_limit = fixed_1;
285
2.20k
#endif
286
2.20k
    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
2.20k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
2.20k
    pfs->color_stack_size = 0;
293
2.20k
    pfs->color_stack_step = 0;
294
2.20k
    pfs->color_stack_ptr = NULL;
295
2.20k
    pfs->color_stack = NULL;
296
2.20k
    pfs->color_stack_limit = NULL;
297
2.20k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
2.20k
    pfs->pcic = NULL;
299
2.20k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
2.20k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
2.20k
{
305
2.20k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
2.20k
#   if LAZY_WEDGES
307
2.20k
        wedge_vertex_list_elem_buffer_free(pfs);
308
2.20k
#   endif
309
2.20k
    if (pfs->color_stack)
310
2.20k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
2.20k
    if (pfs->pcic != NULL)
312
2.20k
        gs_color_index_cache_destroy(pfs->pcic);
313
2.20k
    return b;
314
2.20k
}
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
851k
{
320
851k
    if (pfs->Function) {
321
632k
        const gs_color_space *pcs = pfs->direct_space;
322
323
632k
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
632k
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
632k
    }
326
851k
}
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
3.75M
{
344
    /* The old code gives -IND on Intel. */
345
3.75M
    if (pfs->Function) {
346
195k
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
195k
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
195k
        patch_resolve_color_inline(ppcr, pfs);
349
3.56M
    } else {
350
3.56M
        int ci;
351
352
17.5M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
14.0M
            ppcr->cc.paint.values[ci] =
354
14.0M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
3.56M
    }
356
3.75M
}
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
2
{
446
2
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
2
    patch_fill_state_t state;
448
2
    shade_coord_stream_t cs;
449
2
    patch_curve_t curve[4];
450
2
    int code;
451
452
2
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
2
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
2
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
2
    state.Function = psh->params.Function;
459
2
    code = init_patch_fill_state(&state);
460
2
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
2
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
2
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
2
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
2
                                    curve, NULL)) == 0 &&
469
2
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
2
        ) {
471
0
        DO_NOTHING;
472
0
    }
473
2
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
2
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
2
    return min(code, 0);
477
2
}
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
100
{
535
100
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
100
    patch_fill_state_t state;
537
100
    shade_coord_stream_t cs;
538
100
    patch_curve_t curve[4];
539
100
    gs_fixed_point interior[4];
540
100
    int code;
541
542
100
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
100
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
100
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
100
    state.Function = psh->params.Function;
549
100
    code = init_patch_fill_state(&state);
550
100
    if(code < 0)
551
0
        return code;
552
100
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
100
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
54.7k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
54.7k
                                    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
54.6k
        gs_fixed_point swapped_interior[4];
561
562
54.6k
        swapped_interior[0] = interior[0];
563
54.6k
        swapped_interior[1] = interior[3];
564
54.6k
        swapped_interior[2] = interior[2];
565
54.6k
        swapped_interior[3] = interior[1];
566
54.6k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
54.6k
        if (code < 0)
568
0
            break;
569
54.6k
    }
570
100
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
100
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
100
    return min(code, 0);
574
100
}
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
2.20k
{
665
2.20k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
2.20k
    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
2.20k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
2.20k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
2.20k
            sizeof(wedge_vertex_list_elem_t) * pfs->wedge_vertex_list_elem_count_max,
681
2.20k
            "alloc_wedge_vertex_list_elem_buffer");
682
2.20k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
2.20k
    pfs->free_wedge_vertex = NULL;
685
2.20k
    pfs->wedge_vertex_list_elem_count = 0;
686
2.20k
    return 0;
687
2.20k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
2.20k
{
692
2.20k
    gs_memory_t *memory = pfs->memory;
693
694
2.20k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
2.20k
                "wedge_vertex_list_elem_buffer_free");
696
2.20k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
2.20k
    pfs->free_wedge_vertex = NULL;
698
2.20k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
84.5k
{
703
84.5k
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
84.5k
    if (e != NULL) {
706
62.0k
        pfs->free_wedge_vertex = e->next;
707
62.0k
        return e;
708
62.0k
    }
709
22.4k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
22.4k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
22.4k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
84.5k
{
717
84.5k
    e->next = pfs->free_wedge_vertex;
718
84.5k
    pfs->free_wedge_vertex = e;
719
84.5k
}
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
35.6k
{
725
35.6k
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
35.6k
    beg->next = end;
728
35.6k
    end->prev = beg;
729
78.4k
    for (; e != end; e = ee) {
730
42.7k
        ee = e->next;
731
42.7k
        wedge_vertex_list_elem_release(pfs, e);
732
42.7k
    }
733
35.6k
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
20.8k
{
738
20.8k
    int i;
739
740
41.7k
    for (i = 0; i < n; i++) {
741
20.8k
        wedge_vertex_list_t *l = ll + i;
742
743
20.8k
        if (l->beg != NULL) {
744
20.8k
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
20.8k
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
20.8k
            wedge_vertex_list_elem_release(pfs, l->beg);
748
20.8k
            wedge_vertex_list_elem_release(pfs, l->end);
749
20.8k
            l->beg = l->end = NULL;
750
20.8k
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
20.8k
    }
753
20.8k
    return 0;
754
20.8k
}
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
22.2k
{
760
22.2k
    wedge_vertex_list_elem_t *e = beg;
761
762
22.2k
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
68.5k
    for (; e != end; e = e->next)
765
68.5k
        if (e->level == level)
766
22.2k
            return e;
767
0
    return NULL;
768
22.2k
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
790k
{
773
790k
    memset(l, 0, sizeof(*l) * n);
774
790k
}
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
1.13M
{
785
1.13M
    curve_segment s;
786
1.13M
    int k;
787
788
1.13M
    s.p1.x = pole[pole_step].x;
789
1.13M
    s.p1.y = pole[pole_step].y;
790
1.13M
    s.p2.x = pole[pole_step * 2].x;
791
1.13M
    s.p2.y = pole[pole_step * 2].y;
792
1.13M
    s.pt.x = pole[pole_step * 3].x;
793
1.13M
    s.pt.y = pole[pole_step * 3].y;
794
1.13M
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
1.13M
    {
796
1.13M
#       if LAZY_WEDGES || QUADRANGLES
797
1.13M
            int k1;
798
1.13M
            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
1.13M
                      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
1.13M
                      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
1.13M
#       endif
802
803
1.13M
#       if LAZY_WEDGES
804
            /* Restrict lengths for a reasonable memory consumption : */
805
1.13M
            k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
806
1.13M
            k = max(k, k1);
807
1.13M
#       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
1.13M
    }
813
1.13M
    return 1 << k;
814
1.13M
}
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
2.33M
{
826
2.33M
    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
1.60M
        *b += fixed_epsilon;
836
1.60M
    }
837
2.33M
}
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
426k
{
844
426k
    if (!orient) {
845
339k
        le->start = q[vi0];
846
339k
        le->end = q[vi1];
847
339k
        re->start = q[vi2];
848
339k
        re->end = q[vi3];
849
339k
    } else {
850
87.3k
        le->start = q[vi2];
851
87.3k
        le->end = q[vi3];
852
87.3k
        re->start = q[vi0];
853
87.3k
        re->end = q[vi1];
854
87.3k
    }
855
426k
    adjust_swapped_boundary(&re->start.x, swap_axes);
856
426k
    adjust_swapped_boundary(&re->end.x, swap_axes);
857
426k
}
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
29.5k
{
864
29.5k
    gs_fixed_edge le, re;
865
29.5k
    int code;
866
29.5k
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
867
29.5k
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
868
29.5k
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
869
29.5k
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
870
871
29.5k
    if (ybot >= ytop)
872
9.02k
        return 0;
873
#   if NOFILL_TEST
874
        if (dbg_nofill)
875
            return 0;
876
#   endif
877
20.5k
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
878
20.5k
    if (!pfs->inside) {
879
8.80k
        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
8.80k
        if (le.start.x > xright) {
890
1.39k
            if (le.end.x > xright) {
891
7
                return 0;
892
7
            }
893
1.38k
            clip = true;
894
7.41k
        } else if (le.end.x > xright) {
895
746
            clip = true;
896
746
        }
897
8.79k
        if (le.start.x < xleft) {
898
2.14k
            if (le.end.x < xleft) {
899
1.36k
                le.start.x = xleft;
900
1.36k
                le.end.x   = xleft;
901
1.36k
                le.start.y = ybot;
902
1.36k
                le.end.y   = ytop;
903
1.36k
            } else {
904
788
                clip = true;
905
788
            }
906
6.65k
        } else if (le.end.x < xleft) {
907
1.25k
            clip = true;
908
1.25k
        }
909
8.79k
        if (re.start.x < xleft) {
910
979
            if (re.end.x < xleft) {
911
0
                return 0;
912
0
            }
913
979
            clip = true;
914
7.81k
        } else if (re.end.x < xleft) {
915
1.30k
            clip = true;
916
1.30k
        }
917
8.79k
        if (re.start.x > xright) {
918
2.57k
            if (re.end.x > xright) {
919
1.24k
                re.start.x = xright;
920
1.24k
                re.end.x   = xright;
921
1.24k
                re.start.y = ybot;
922
1.24k
                re.end.y   = ytop;
923
1.32k
            } else {
924
1.32k
                clip = true;
925
1.32k
            }
926
6.22k
        } else if (re.end.x > xright) {
927
703
            clip = true;
928
703
        }
929
8.79k
        if (clip)
930
5.11k
        {
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
5.11k
            gs_fixed_edge lenew, renew;
935
5.11k
            fixed ybl, ybr, ytl, ytr, ymid;
936
937
            /* Reduce the clipping region horizontally if possible. */
938
5.11k
            if (re.start.x > re.end.x) {
939
2.17k
                if (re.start.x < xright)
940
844
                    xright = re.start.x;
941
2.93k
            } else if (re.end.x < xright)
942
1.05k
                xright = re.end.x;
943
5.11k
            if (le.start.x > le.end.x) {
944
2.20k
                if (le.end.x > xleft)
945
949
                    xleft = le.end.x;
946
2.90k
            } else if (le.start.x > xleft)
947
839
                xleft = le.start.x;
948
949
5.11k
            ybot = max(ybot, min(le.start.y, re.start.y));
950
5.11k
            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
5.11k
            if (ybot >= ytop)
987
0
                return 0;
988
            /* Follow the edges in, so that le.start.y == ybot etc. */
989
5.11k
            if (le.start.y < ybot) {
990
1.95k
                int round = ((le.end.x < le.start.x) ?
991
1.12k
                             (le.end.y-le.start.y-1) : 0);
992
1.95k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
993
1.95k
                                       (int64_t)(le.end.x-le.start.x)-round)/
994
1.95k
                                      (int64_t)(le.end.y-le.start.y));
995
1.95k
                le.start.y = ybot;
996
1.95k
            }
997
5.11k
            if (le.end.y > ytop) {
998
2.07k
                int round = ((le.end.x > le.start.x) ?
999
1.03k
                             (le.end.y-le.start.y-1) : 0);
1000
2.07k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1001
2.07k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1002
2.07k
                                    (int64_t)(le.end.y-le.start.y));
1003
2.07k
                le.end.y = ytop;
1004
2.07k
            }
1005
5.11k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1006
304
                le.start.x = xleft;
1007
304
                le.end.x   = xleft;
1008
304
                le.start.y = ybot;
1009
304
                le.end.y   = ytop;
1010
304
            }
1011
5.11k
            if (re.start.y < ybot) {
1012
2.01k
                int round = ((re.end.x > re.start.x) ?
1013
1.06k
                             (re.end.y-re.start.y-1) : 0);
1014
2.01k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1015
2.01k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1016
2.01k
                                      (int64_t)(re.end.y-re.start.y));
1017
2.01k
                re.start.y = ybot;
1018
2.01k
            }
1019
5.11k
            if (re.end.y > ytop) {
1020
2.15k
                int round = ((re.end.x < re.start.x) ?
1021
1.09k
                             (re.end.y-re.start.y-1) : 0);
1022
2.15k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1023
2.15k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1024
2.15k
                                    (int64_t)(re.end.y-re.start.y));
1025
2.15k
                re.end.y = ytop;
1026
2.15k
            }
1027
5.11k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1028
166
                re.start.x = xright;
1029
166
                re.end.x   = xright;
1030
166
                re.start.y = ybot;
1031
166
                re.end.y   = ytop;
1032
166
            }
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
5.11k
            if (le.start.x > re.start.x) {
1039
1.74k
                if (le.start.x == le.end.x) {
1040
831
                    if (re.start.x == re.end.x)
1041
0
                        return 0;
1042
831
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1043
831
                                    (int64_t)(le.start.x-re.start.x)/
1044
831
                                    (int64_t)(re.end.x-re.start.x));
1045
831
                    re.start.x = le.start.x;
1046
916
                } else {
1047
916
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1048
916
                                    (int64_t)(le.start.x-re.start.x)/
1049
916
                                    (int64_t)(le.start.x-le.end.x));
1050
916
                    le.start.x = re.start.x;
1051
916
                }
1052
1.74k
                if (ybot >= ytop)
1053
542
                    return 0;
1054
1.20k
                le.start.y = ybot;
1055
1.20k
                re.start.y = ybot;
1056
1.20k
            }
1057
4.56k
            if (le.end.x > re.end.x) {
1058
1.16k
                if (le.start.x == le.end.x) {
1059
751
                    if (re.start.x == re.end.x)
1060
0
                        return 0;
1061
751
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1062
751
                                    (int64_t)(le.end.x-re.end.x)/
1063
751
                                    (int64_t)(re.start.x-re.end.x));
1064
751
                    re.end.x = le.end.x;
1065
751
                } else {
1066
412
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1067
412
                                    (int64_t)(le.end.x-re.end.x)/
1068
412
                                    (int64_t)(le.end.x-le.start.x));
1069
412
                    le.end.x = re.end.x;
1070
412
                }
1071
1.16k
                if (ybot >= ytop)
1072
432
                    return 0;
1073
731
                le.end.y = ytop;
1074
731
                re.end.y = ytop;
1075
731
            }
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
4.13k
            lenew.start.x = xleft;
1082
4.13k
            lenew.start.y = ybot;
1083
4.13k
            lenew.end.x   = xleft;
1084
4.13k
            lenew.end.y   = ytop;
1085
4.13k
            renew.start.x = xright;
1086
4.13k
            renew.start.y = ybot;
1087
4.13k
            renew.end.x   = xright;
1088
4.13k
            renew.end.y   = ytop;
1089
            /* Figure out where the left edge intersects with the left at
1090
             * the bottom */
1091
4.13k
            ybl = ybot;
1092
4.13k
            if (le.start.x > le.end.x) {
1093
1.70k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1094
1.70k
                               (int64_t)(le.end.y-le.start.y) /
1095
1.70k
                               (int64_t)(le.start.x-le.end.x));
1096
1.70k
                if (ybl > ytop)
1097
669
                    ybl = ytop;
1098
1.70k
            }
1099
            /* Figure out where the right edge intersects with the right at
1100
             * the bottom */
1101
4.13k
            ybr = ybot;
1102
4.13k
            if (re.start.x < re.end.x) {
1103
1.44k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1104
1.44k
                               (int64_t)(re.end.y-re.start.y) /
1105
1.44k
                               (int64_t)(re.end.x-re.start.x));
1106
1.44k
                if (ybr > ytop)
1107
756
                    ybr = ytop;
1108
1.44k
            }
1109
            /* Figure out where the left edge intersects with the left at
1110
             * the top */
1111
4.13k
            ytl = ytop;
1112
4.13k
            if (le.end.x > le.start.x) {
1113
1.37k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1114
1.37k
                               (int64_t)(le.end.y-le.start.y) /
1115
1.37k
                               (int64_t)(le.end.x-le.start.x));
1116
1.37k
                if (ytl < ybot)
1117
636
                    ytl = ybot;
1118
1.37k
            }
1119
            /* Figure out where the right edge intersects with the right at
1120
             * the bottom */
1121
4.13k
            ytr = ytop;
1122
4.13k
            if (re.end.x < re.start.x) {
1123
1.79k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1124
1.79k
                               (int64_t)(re.end.y-re.start.y) /
1125
1.79k
                               (int64_t)(re.start.x-re.end.x));
1126
1.79k
                if (ytr < ybot)
1127
590
                    ytr = ybot;
1128
1.79k
            }
1129
            /* Check for the 2 cases where top and bottom diagonal extents
1130
             * overlap, and deal with them explicitly. */
1131
4.13k
            if (ytl < ybr) {
1132
                /*     |     |
1133
                 *  ---+-----+---
1134
                 *     | /222|
1135
                 *     |/111/|
1136
                 *     |000/ |
1137
                 *  ---+-----+---
1138
                 *     |     |
1139
                 */
1140
569
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1141
569
                                        &lenew, &re, ybot, ytl,
1142
569
                                        swap_axes, pdevc, pfs->pgs->log_op);
1143
569
                if (code < 0)
1144
0
                    return code;
1145
569
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1146
569
                                        &le, &re, ytl, ybr,
1147
569
                                        swap_axes, pdevc, pfs->pgs->log_op);
1148
569
                if (code < 0)
1149
0
                    return code;
1150
569
                ybot = ybr;
1151
569
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1152
569
                                        &le, &renew, ybr, ytop,
1153
569
                                        swap_axes, pdevc, pfs->pgs->log_op);
1154
3.56k
            } else if (ytr < ybl) {
1155
                /*     |     |
1156
                 *  ---+-----+----
1157
                 *     |555\ |
1158
                 *     |\444\|
1159
                 *     | \333|
1160
                 *  ---+-----+---
1161
                 *     |     |
1162
                 */
1163
752
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
752
                                        &le, &renew, ybot, ytr,
1165
752
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
752
                if (code < 0)
1167
0
                    return code;
1168
752
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1169
752
                                        &le, &re, ytr, ybl,
1170
752
                                        swap_axes, pdevc, pfs->pgs->log_op);
1171
752
                if (code < 0)
1172
0
                    return code;
1173
752
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1174
752
                                        &le, &re, ybl, ytop,
1175
752
                                        swap_axes, pdevc, pfs->pgs->log_op);
1176
752
            }
1177
            /* Fill in any section where both left and right edges are
1178
             * diagonal at the bottom */
1179
2.81k
            ymid = ybl;
1180
2.81k
            if (ymid > ybr)
1181
690
                ymid = ybr;
1182
2.81k
            if (ymid > ybot) {
1183
                /*     |\   |          |   /|
1184
                 *     | \6/|    or    |\6/ |
1185
                 *  ---+----+---    ---+----+---
1186
                 *     |    |          |    |
1187
                 */
1188
216
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1189
216
                                        &le, &re, ybot, ymid,
1190
216
                                        swap_axes, pdevc, pfs->pgs->log_op);
1191
216
                if (code < 0)
1192
0
                    return code;
1193
216
                ybot = ymid;
1194
216
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the top */
1197
2.81k
            ymid = ytl;
1198
2.81k
            if (ymid < ytr)
1199
517
                ymid = ytr;
1200
2.81k
            if (ymid < ytop) {
1201
                /*     |    |          |    |
1202
                 *  ---+----+---    ---+----+---
1203
                 *     |/7\ |    or    | /7\|
1204
                 *     |   \|          |/   |
1205
                 */
1206
241
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
241
                                        &le, &re, ymid, ytop,
1208
241
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
241
                if (code < 0)
1210
0
                    return code;
1211
241
                ytop = ymid;
1212
241
            }
1213
            /* Now do the single diagonal cases at the bottom */
1214
2.81k
            if (ybl > ybot) {
1215
                /*     |    |
1216
                 *     |\666|
1217
                 *  ---+----+---
1218
                 *     |    |
1219
                 */
1220
690
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1221
690
                                        &le, &renew, ybot, ybl,
1222
690
                                        swap_axes, pdevc, pfs->pgs->log_op);
1223
690
                if (code < 0)
1224
0
                    return code;
1225
690
                ybot = ybl;
1226
2.12k
            } else if (ybr > ybot) {
1227
                /*     |    |
1228
                 *     |777/|
1229
                 *  ---+----+---
1230
                 *     |    |
1231
                 */
1232
586
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1233
586
                                        &lenew, &re, ybot, ybr,
1234
586
                                        swap_axes, pdevc, pfs->pgs->log_op);
1235
586
                if (code < 0)
1236
0
                    return code;
1237
586
                ybot = ybr;
1238
586
            }
1239
            /* Now do the single diagonal cases at the top */
1240
2.81k
            if (ytl < ytop) {
1241
                /*     |    |
1242
                 *  ---+----+---
1243
                 *     |/888|
1244
                 *     |    |
1245
                 */
1246
517
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1247
517
                                        &le, &renew, ytl, ytop,
1248
517
                                        swap_axes, pdevc, pfs->pgs->log_op);
1249
517
                if (code < 0)
1250
0
                    return code;
1251
517
                ytop = ytl;
1252
2.29k
            } else if (ytr < ytop) {
1253
                /*     |    |
1254
                 *  ---+----+---
1255
                 *     |999\|
1256
                 *     |    |
1257
                 */
1258
729
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1259
729
                                        &lenew, &re, ytr, ytop,
1260
729
                                        swap_axes, pdevc, pfs->pgs->log_op);
1261
729
                if (code < 0)
1262
0
                    return code;
1263
729
                ytop = ytr;
1264
729
            }
1265
            /* And finally just whatever rectangular section is left over in
1266
             * the middle */
1267
2.81k
            if (ybot > ytop)
1268
0
                return 0;
1269
2.81k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1270
2.81k
                                        &lenew, &renew, ybot, ytop,
1271
2.81k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1272
2.81k
        }
1273
8.79k
    }
1274
15.4k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1275
15.4k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1276
20.5k
}
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
12.5M
#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
3.14M
{
1311
    /* Must return 2 if the color is not pure.
1312
       See try_device_linear_color.
1313
     */
1314
3.14M
    int code;
1315
3.14M
    gx_device_color devc;
1316
1317
3.14M
#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
3.14M
     if (frac_values) {
1345
3.09M
        int i;
1346
3.09M
  int n = pfs->dev->color_info.num_components;
1347
3.60M
  for (i = pfs->num_components; i < n; i++) {
1348
508k
            frac_values[i] = 0;
1349
508k
  }
1350
3.09M
    }
1351
3.14M
#endif
1352
1353
3.14M
    if (DEBUG_COLOR_INDEX_CACHE && pdevc == NULL)
1354
0
        pdevc = &devc;
1355
3.14M
    if (pfs->pcic) {
1356
3.14M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1357
3.14M
        if (code < 0)
1358
0
            return code;
1359
3.14M
    }
1360
3.14M
    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
3.14M
    return 0;
1402
3.14M
}
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
4.02M
{
1413
4.02M
    int n = pfs->num_components, i;
1414
4.02M
    double m;
1415
1416
    /* Dont want to copy colors, which are big things. */
1417
4.02M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1418
15.5M
    for (i = 1; i < n; i++)
1419
11.5M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1420
4.02M
    return m;
1421
4.02M
}
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
1.03M
{
1426
1.03M
    int n = pfs->num_components, i;
1427
1428
4.98M
    for (i = 0; i < n; i++)
1429
3.95M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1430
1.03M
}
1431
1432
static inline double
1433
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1434
722k
{
1435
722k
    int n = pfs->num_components, i;
1436
722k
    double m;
1437
1438
722k
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1439
2.76M
    for (i = 1; i < n; i++)
1440
2.04M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1441
722k
    return m;
1442
722k
}
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
71.9k
{   /* 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
71.9k
    uint mask;
1462
71.9k
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1463
1464
71.9k
    if (code >= 0)
1465
71.9k
        return mask;
1466
0
    return code;
1467
71.9k
}
1468
1469
static inline bool
1470
covers_pixel_centers(fixed ybot, fixed ytop)
1471
654k
{
1472
654k
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1473
654k
}
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
30.1k
{
1479
30.1k
    gx_device_color dc;
1480
30.1k
    int code;
1481
1482
#   if NOFILL_TEST
1483
        /* if (dbg_nofill)
1484
                return 0; */
1485
#   endif
1486
1487
30.1k
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1488
30.1k
    if (code < 0)
1489
0
        return code;
1490
1491
30.1k
    dc.tag = device_current_tag(pfs->dev);
1492
1493
30.1k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1494
30.1k
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1495
30.1k
}
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
3.67M
{
1500
3.67M
    float s = 0;
1501
1502
3.67M
    if (pfs->Function != NULL) {
1503
217k
        patch_color_t c;
1504
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1505
        /* unless it is 'static const' */
1506
217k
        static const float q[2] = {(float)0.3, (float)0.7};
1507
217k
        int i, j;
1508
1509
613k
        for (j = 0; j < count_of(q); j++) {
1510
417k
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1511
417k
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1512
417k
            patch_resolve_color_inline(&c, pfs);
1513
1.40M
            for (i = 0; i < pfs->num_components; i++) {
1514
1.00M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1515
1.00M
                float d = v - c.cc.paint.values[i];
1516
1.00M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1517
1518
1.00M
                if (s1 > pfs->smoothness)
1519
20.9k
                    return s1;
1520
988k
                if (s < s1)
1521
158k
                    s = s1;
1522
988k
            }
1523
417k
        }
1524
217k
    }
1525
3.65M
    return s;
1526
3.67M
}
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
959k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1531
959k
    if (pfs->unlinear)
1532
0
        return 1; /* Disable this check. */
1533
959k
    else {
1534
959k
        const gs_color_space *cs = pfs->direct_space;
1535
959k
        int code;
1536
959k
        float s = function_linearity(pfs, c0, c1);
1537
1538
959k
        if (s > pfs->smoothness)
1539
8.18k
            return 0;
1540
951k
        if (pfs->cs_always_linear)
1541
686k
            return 1;
1542
264k
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1543
264k
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1544
264k
        if (code <= 0)
1545
566
            return code;
1546
263k
        return 1;
1547
264k
    }
1548
959k
}
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
1.18M
{
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
1.18M
    int code;
1559
1.18M
    patch_color_t *c;
1560
1.18M
    byte *color_stack_ptr;
1561
1.18M
    bool save_inside = pfs->inside;
1562
1563
1.18M
    if (!pfs->inside) {
1564
1.12M
        gs_fixed_rect r, r1;
1565
1566
1.12M
        if(swap_axes) {
1567
788k
            r.p.y = min(le->start.x, le->end.x);
1568
788k
            r.p.x = min(le->start.y, le->end.y);
1569
788k
            r.q.y = max(re->start.x, re->end.x);
1570
788k
            r.q.x = max(re->start.y, re->end.y);
1571
788k
        } else {
1572
338k
            r.p.x = min(le->start.x, le->end.x);
1573
338k
            r.p.y = min(le->start.y, le->end.y);
1574
338k
            r.q.x = max(re->start.x, re->end.x);
1575
338k
            r.q.y = max(re->start.y, re->end.y);
1576
338k
        }
1577
1.12M
        r1 = r;
1578
1.12M
        rect_intersect(r, pfs->rect);
1579
1.12M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1580
936k
            return 0;
1581
190k
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1582
190k
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1583
134k
            pfs->inside = true;
1584
190k
    }
1585
247k
    color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
1586
247k
    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
247k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
1592
247k
    if (ytop - ybot < pfs->decomposition_limit) /* Prevent an infinite color decomposition. */
1593
30.1k
        code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1594
217k
    else {
1595
217k
        bool monotonic_color_save = pfs->monotonic_color;
1596
217k
        bool linear_color_save = pfs->linear_color;
1597
1598
217k
        if (!pfs->monotonic_color) {
1599
56.1k
            code = isnt_color_monotonic(pfs, c0, c1);
1600
56.1k
            if (code < 0)
1601
0
                goto out;
1602
56.1k
            if (!code)
1603
38.2k
                pfs->monotonic_color = true;
1604
56.1k
        }
1605
217k
        if (pfs->monotonic_color && !pfs->linear_color) {
1606
198k
            code = is_color_linear(pfs, c0, c1);
1607
198k
            if (code < 0)
1608
0
                goto out;
1609
198k
            if (code > 0)
1610
197k
                pfs->linear_color =  true;
1611
198k
        }
1612
217k
        if (!pfs->unlinear && pfs->linear_color) {
1613
199k
            gx_device *pdev = pfs->dev;
1614
199k
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1615
199k
            gs_fill_attributes fa;
1616
199k
            gs_fixed_rect clip;
1617
1618
199k
            memset(fc, 0x99, sizeof(fc));
1619
1620
199k
            clip = pfs->rect;
1621
199k
            if (swap_axes) {
1622
100k
                fixed v;
1623
1624
100k
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1625
100k
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1626
                /* Don't need adjust_swapped_boundary here. */
1627
100k
            }
1628
199k
            clip.p.y = max(clip.p.y, ybot);
1629
199k
            clip.q.y = min(clip.q.y, ytop);
1630
199k
            fa.clip = &clip;
1631
199k
            fa.ht = NULL;
1632
199k
            fa.swap_axes = swap_axes;
1633
199k
            fa.lop = 0;
1634
199k
            fa.ystart = ybot;
1635
199k
            fa.yend = ytop;
1636
199k
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1637
199k
            if (code < 0)
1638
0
                goto out;
1639
199k
            if (code == 2) {
1640
                /* Must not happen. */
1641
0
                code=gs_note_error(gs_error_unregistered);
1642
0
                goto out;
1643
0
            }
1644
199k
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1645
199k
            if (code < 0)
1646
0
                goto out;
1647
199k
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1648
199k
                            &le->start, &le->end, &re->start, &re->end,
1649
199k
                            fc[0], fc[1], NULL, NULL);
1650
199k
            if (code == 1) {
1651
199k
                pfs->monotonic_color = monotonic_color_save;
1652
199k
                pfs->linear_color = linear_color_save;
1653
199k
                code = 0; /* The area is filled. */
1654
199k
                goto out;
1655
199k
            }
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
18.3k
        if (!pfs->unlinear || !pfs->linear_color ||
1664
18.3k
                color_span(pfs, c0, c1) > pfs->smoothness) {
1665
18.3k
            fixed y = (ybot + ytop) / 2;
1666
1667
18.3k
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1668
18.3k
            if (code >= 0)
1669
18.3k
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1670
18.3k
        } else
1671
0
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1672
18.3k
        pfs->monotonic_color = monotonic_color_save;
1673
18.3k
        pfs->linear_color = linear_color_save;
1674
18.3k
    }
1675
247k
out:
1676
247k
    pfs->inside = save_inside;
1677
247k
    release_colors_inline(pfs, color_stack_ptr, 1);
1678
247k
    return code;
1679
247k
}
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
406k
{
1686
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1687
406k
    gs_fixed_edge le, re;
1688
1689
406k
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1690
406k
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1691
406k
}
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
654k
{
1698
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1699
654k
    fixed dx1, dy1, dx2, dy2;
1700
654k
    bool orient;
1701
1702
654k
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1703
248k
        return 0;
1704
406k
    if (ybot == ytop)
1705
0
        return 0;
1706
406k
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1707
406k
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1708
406k
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1709
202k
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1710
202k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1711
203k
    } else {
1712
203k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1713
1714
203k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1715
203k
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1716
203k
    }
1717
406k
}
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
654k
{
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
654k
    gs_fixed_point p[4];
1727
654k
    const patch_color_t *cc0, *cc1;
1728
1729
654k
    if (p0->y < p1->y) {
1730
311k
        p[2] = *p0;
1731
311k
        p[3] = *p1;
1732
311k
        cc0 = c0;
1733
311k
        cc1 = c1;
1734
343k
    } else {
1735
343k
        p[2] = *p1;
1736
343k
        p[3] = *p0;
1737
343k
        cc0 = c1;
1738
343k
        cc1 = c0;
1739
343k
    }
1740
654k
    p[0] = *q0;
1741
654k
    p[1] = *q1;
1742
654k
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1743
654k
}
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
5.66M
{
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
5.66M
#define midpoint(a,b)\
1757
67.9M
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1758
5.66M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1759
5.66M
    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
5.66M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1763
5.66M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1764
5.66M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1765
5.66M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1766
5.66M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1767
5.66M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1768
5.66M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1769
5.66M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1770
5.66M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1771
5.66M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1772
5.66M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1773
5.66M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1774
5.66M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1775
5.66M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1776
5.66M
#undef midpoint
1777
5.66M
}
1778
1779
static void
1780
split_curve(const gs_fixed_point pole[4], gs_fixed_point q0[4], gs_fixed_point q1[4])
1781
445k
{
1782
445k
    split_curve_s(pole, q0, q1, 1);
1783
445k
}
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
4.58k
{
1826
4.58k
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1827
1828
4.58k
    return max(dx, dy);
1829
4.58k
}
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
20.8k
{
1835
20.8k
    if (l->end != NULL)
1836
0
        return_error(gs_error_unregistered); /* Must not happen. */
1837
20.8k
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1838
20.8k
    l->end = wedge_vertex_list_elem_reserve(pfs);
1839
20.8k
    if (l->beg == NULL)
1840
0
        return_error(gs_error_unregistered); /* Must not happen. */
1841
20.8k
    if (l->end == NULL)
1842
0
        return_error(gs_error_unregistered); /* Must not happen. */
1843
20.8k
    l->beg->prev = l->end->next = NULL;
1844
20.8k
    l->beg->next = l->end;
1845
20.8k
    l->end->prev = l->beg;
1846
20.8k
    l->beg->p = *p0;
1847
20.8k
    l->end->p = *p1;
1848
20.8k
    l->beg->level = l->end->level = 0;
1849
20.8k
    return 0;
1850
20.8k
}
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
42.7k
{
1856
42.7k
    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
42.7k
    if (e == NULL)
1861
0
        return_error(gs_error_unregistered); /* Must not happen. */
1862
42.7k
    if (l->beg->next != l->end)
1863
0
        return_error(gs_error_unregistered); /* Must not happen. */
1864
42.7k
    if (l->end->prev != l->beg)
1865
0
        return_error(gs_error_unregistered); /* Must not happen. */
1866
42.7k
    e->next = l->end;
1867
42.7k
    e->prev = l->beg;
1868
42.7k
    e->p = *p;
1869
42.7k
    e->level = max(l->beg->level, l->end->level) + 1;
1870
42.7k
    e->divide_count = 0;
1871
42.7k
    l->beg->next = l->end->prev = e;
1872
42.7k
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1873
42.7k
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1874
1875
42.7k
        if ((p->x - l->beg->p.x) * sx < 0)
1876
0
            return_error(gs_error_unregistered); /* Must not happen. */
1877
42.7k
        if ((p->y - l->beg->p.y) * sy < 0)
1878
0
            return_error(gs_error_unregistered); /* Must not happen. */
1879
42.7k
        if ((l->end->p.x - p->x) * sx < 0)
1880
0
            return_error(gs_error_unregistered); /* Must not happen. */
1881
42.7k
        if ((l->end->p.y - p->y) * sy < 0)
1882
0
            return_error(gs_error_unregistered); /* Must not happen. */
1883
42.7k
    }
1884
42.7k
    *r = e;
1885
42.7k
    return 0;
1886
42.7k
}
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
53.6k
{
1893
53.6k
    wedge_vertex_list_elem_t *e;
1894
53.6k
    int code;
1895
1896
53.6k
    if (!l->last_side) {
1897
38.9k
        if (l->beg == NULL) {
1898
18.7k
            code = create_wedge_vertex_list(pfs, l, p0, p1);
1899
18.7k
            if (code < 0)
1900
0
                return code;
1901
18.7k
        }
1902
38.9k
        if (l->beg->p.x != p0->x)
1903
0
            return_error(gs_error_unregistered); /* Must not happen. */
1904
38.9k
        if (l->beg->p.y != p0->y)
1905
0
            return_error(gs_error_unregistered); /* Must not happen. */
1906
38.9k
        if (l->end->p.x != p1->x)
1907
0
            return_error(gs_error_unregistered); /* Must not happen. */
1908
38.9k
        if (l->end->p.y != p1->y)
1909
0
            return_error(gs_error_unregistered); /* Must not happen. */
1910
38.9k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1911
38.9k
        if (code < 0)
1912
0
            return code;
1913
38.9k
        e->divide_count++;
1914
38.9k
    } else if (l->beg == NULL) {
1915
2.12k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1916
2.12k
        if (code < 0)
1917
0
            return code;
1918
2.12k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1919
2.12k
        if (code < 0)
1920
0
            return code;
1921
2.12k
        e->divide_count++;
1922
12.6k
    } else {
1923
12.6k
        if (l->beg->p.x != p1->x)
1924
0
            return_error(gs_error_unregistered); /* Must not happen. */
1925
12.6k
        if (l->beg->p.y != p1->y)
1926
0
            return_error(gs_error_unregistered); /* Must not happen. */
1927
12.6k
        if (l->end->p.x != p0->x)
1928
0
            return_error(gs_error_unregistered); /* Must not happen. */
1929
12.6k
        if (l->end->p.y != p0->y)
1930
0
            return_error(gs_error_unregistered); /* Must not happen. */
1931
12.6k
        if (l->beg->next == l->end) {
1932
1.77k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1933
1.77k
            if (code < 0)
1934
0
                return code;
1935
1.77k
            e->divide_count++;
1936
10.8k
        } else {
1937
10.8k
            e = wedge_vertex_list_find(l->beg, l->end,
1938
10.8k
                        max(l->beg->level, l->end->level) + 1);
1939
10.8k
            if (e == NULL)
1940
0
                return_error(gs_error_unregistered); /* Must not happen. */
1941
10.8k
            if (e->p.x != pm->x || e->p.y != pm->y)
1942
0
                return_error(gs_error_unregistered); /* Must not happen. */
1943
10.8k
            e->divide_count++;
1944
10.8k
        }
1945
12.6k
    }
1946
53.6k
    *r = e;
1947
53.6k
    return 0;
1948
53.6k
}
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
53.6k
{
1955
53.6k
    int code;
1956
1957
53.6k
    l->last_side = l0->last_side;
1958
53.6k
    if (!l->last_side ^ !forth) {
1959
30.3k
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1960
30.3k
        l->beg = l0->beg;
1961
30.3k
    } else {
1962
23.3k
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1963
23.3k
        l->end = l0->end;
1964
23.3k
    }
1965
53.6k
    return code;
1966
53.6k
}
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
53.6k
{
1975
53.6k
    int code;
1976
1977
53.6k
    if (!l->last_side)
1978
38.9k
        return 0;
1979
14.7k
    code = fill_wedge_from_list(pfs, l, c1, c0);
1980
14.7k
    if (code < 0)
1981
0
        return code;
1982
14.7k
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1983
14.7k
    return 0;
1984
14.7k
}
1985
1986
static inline void
1987
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
1988
53.6k
{
1989
53.6k
    if (!l->last_side ^ !forth) {
1990
30.3k
        l->beg = l->end;
1991
30.3k
        l->end = l0->end;
1992
30.3k
    } else {
1993
23.3k
        l->end = l->beg;
1994
23.3k
        l->beg = l0->beg;
1995
23.3k
    }
1996
53.6k
}
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
327k
{   int code;
2002
327k
    const gs_fixed_point *p0, *p1, *p2;
2003
327k
    gs_fixed_point qq0, qq1, qq2;
2004
327k
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2005
327k
    bool swap_axes;
2006
2007
#   if SKIP_TEST
2008
        dbg_wedge_triangle_cnt++;
2009
#   endif
2010
327k
    if (dx > dy) {
2011
258k
        swap_axes = true;
2012
258k
        qq0.x = q0->p.y;
2013
258k
        qq0.y = q0->p.x;
2014
258k
        qq1.x = q1->p.y;
2015
258k
        qq1.y = q1->p.x;
2016
258k
        qq2.x = q2->p.y;
2017
258k
        qq2.y = q2->p.x;
2018
258k
        p0 = &qq0;
2019
258k
        p1 = &qq1;
2020
258k
        p2 = &qq2;
2021
258k
    } else {
2022
69.3k
        swap_axes = false;
2023
69.3k
        p0 = &q0->p;
2024
69.3k
        p1 = &q1->p;
2025
69.3k
        p2 = &q2->p;
2026
69.3k
    }
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
327k
    if (p0->y < p1->y) {
2032
155k
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2033
155k
        if (code < 0)
2034
0
            return code;
2035
155k
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2036
171k
    } else {
2037
171k
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2038
171k
        if (code < 0)
2039
0
            return code;
2040
171k
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2041
171k
    }
2042
327k
}
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
913k
{
2049
    /*  Returns :
2050
        <0 - error;
2051
        0 - success;
2052
        1 - decompose to linear color areas;
2053
        2 - decompose to constant color areas;
2054
     */
2055
913k
    int code;
2056
2057
913k
    if (pfs->unlinear)
2058
0
        return 2;
2059
913k
    if (!wedge) {
2060
913k
        const gs_color_space *cs = pfs->direct_space;
2061
2062
913k
        if (cs != NULL) {
2063
913k
            float s0, s1, s2, s01, s012;
2064
2065
913k
            s0 = function_linearity(pfs, p0->c, p1->c);
2066
913k
            if (s0 > pfs->smoothness)
2067
7.39k
                return 1;
2068
905k
            s1 = function_linearity(pfs, p1->c, p2->c);
2069
905k
            if (s1 > pfs->smoothness)
2070
5.25k
                return 1;
2071
900k
            s2 = function_linearity(pfs, p2->c, p0->c);
2072
900k
            if (s2 > pfs->smoothness)
2073
97
                return 1;
2074
            /* fixme: check an inner color ? */
2075
900k
            s01 = max(s0, s1);
2076
900k
            s012 = max(s01, s2);
2077
900k
            if (pfs->cs_always_linear)
2078
549k
                code = 1;
2079
351k
            else
2080
351k
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2081
900k
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2082
900k
                                  pfs->smoothness - s012, pfs->icclink);
2083
900k
            if (code < 0)
2084
0
                return code;
2085
900k
            if (code == 0)
2086
29
                return 1;
2087
900k
        }
2088
913k
    }
2089
900k
    {   gx_device *pdev = pfs->dev;
2090
900k
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2091
900k
        gs_fill_attributes fa;
2092
900k
        gx_device_color dc[3];
2093
2094
900k
        fa.clip = &pfs->rect;
2095
900k
        fa.ht = NULL;
2096
900k
        fa.swap_axes = false;
2097
900k
        fa.lop = 0;
2098
900k
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2099
900k
        if (code != 0)
2100
0
            return code;
2101
900k
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2102
900k
            dc[0].type == &gx_dc_type_data_devn))
2103
0
            return 2;
2104
900k
        if (!wedge) {
2105
900k
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2106
900k
            if (code != 0)
2107
0
                return code;
2108
900k
        }
2109
900k
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2110
900k
        if (code != 0)
2111
0
            return code;
2112
900k
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2113
900k
                        &p0->p, &p1->p, &p2->p,
2114
900k
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2115
900k
        if (code == 1)
2116
900k
            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
1.04M
{
2128
1.04M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2129
1.04M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2130
719k
        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
327k
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2138
1.04M
}
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
31.9k
{
2146
31.9k
    shading_vertex_t p[3];
2147
31.9k
    patch_color_t *c;
2148
31.9k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2149
31.9k
    int code;
2150
2151
31.9k
    if (color_stack_ptr == NULL)
2152
0
        return_error(gs_error_unregistered); /* Must not happen. */
2153
31.9k
    p[2].c = c;
2154
31.9k
    p[0].p = beg->p;
2155
31.9k
    p[0].c = c0;
2156
31.9k
    p[1].p = end->p;
2157
31.9k
    p[1].c = c1;
2158
31.9k
    p[2].p = mid->p;
2159
31.9k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2160
31.9k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2161
31.9k
    release_colors_inline(pfs, color_stack_ptr, 1);
2162
31.9k
    return code;
2163
31.9k
}
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
58.4k
{
2170
58.4k
    if (beg->next == end)
2171
15.6k
        return 0;
2172
42.7k
    else if (beg->next->next == end) {
2173
31.3k
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2174
0
            return_error(gs_error_unregistered); /* Must not happen. */
2175
31.3k
        if (beg->next->divide_count != 1)
2176
10.7k
            return 0;
2177
20.6k
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2178
31.3k
    } else {
2179
11.4k
        gs_fixed_point p;
2180
11.4k
        wedge_vertex_list_elem_t *e;
2181
11.4k
        patch_color_t *c;
2182
11.4k
        int code;
2183
11.4k
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2184
2185
11.4k
        if (color_stack_ptr == NULL)
2186
0
            return_error(gs_error_unregistered); /* Must not happen. */
2187
11.4k
        p.x = (beg->p.x + end->p.x) / 2;
2188
11.4k
        p.y = (beg->p.y + end->p.y) / 2;
2189
11.4k
        e = wedge_vertex_list_find(beg, end, level + 1);
2190
11.4k
        if (e == NULL)
2191
0
            return_error(gs_error_unregistered); /* Must not happen. */
2192
11.4k
        if (e->p.x != p.x || e->p.y != p.y)
2193
0
            return_error(gs_error_unregistered); /* Must not happen. */
2194
11.4k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2195
11.4k
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2196
11.4k
        if (code >= 0)
2197
11.4k
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2198
11.4k
        if (code >= 0) {
2199
11.4k
            if (e->divide_count != 1 && e->divide_count != 2)
2200
0
                return_error(gs_error_unregistered); /* Must not happen. */
2201
11.4k
            if (e->divide_count == 1)
2202
11.3k
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2203
11.4k
        }
2204
11.4k
        release_colors_inline(pfs, color_stack_ptr, 1);
2205
11.4k
        return code;
2206
11.4k
    }
2207
58.4k
}
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
35.6k
{
2213
35.6k
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2214
35.6k
                    max(l->beg->level, l->end->level), c0, c1);
2215
35.6k
}
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
2.39M
{
2221
2.39M
    if (l->beg != NULL) {
2222
20.8k
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2223
2224
20.8k
        if (code < 0)
2225
0
            return code;
2226
20.8k
        return release_wedge_vertex_list(pfs, l, 1);
2227
20.8k
    }
2228
2.37M
    return 0;
2229
2.39M
}
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
437k
{   /* Assuming ka >= 2, see fill_wedges. */
2235
437k
    gs_fixed_point q[2][4];
2236
437k
    patch_color_t *c;
2237
437k
    shading_vertex_t p[3];
2238
437k
    int code;
2239
437k
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2240
2241
437k
    if (color_stack_ptr == NULL)
2242
0
        return_error(gs_error_unregistered); /* Must not happen. */
2243
437k
    p[2].c = c;
2244
437k
    split_curve(pole, q[0], q[1]);
2245
437k
    p[0].p = pole[0];
2246
437k
    p[0].c = c0;
2247
437k
    p[1].p = pole[3];
2248
437k
    p[1].c = c1;
2249
437k
    p[2].p = q[0][3];
2250
437k
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2251
437k
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2252
437k
    if (code >= 0) {
2253
437k
        if (ka == 2)
2254
220k
            goto out;
2255
216k
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2256
216k
    }
2257
216k
    if (code >= 0)
2258
216k
        code = wedge_by_triangles(pfs, ka / 2, q[1], p[2].c, c1);
2259
437k
out:
2260
437k
    release_colors_inline(pfs, color_stack_ptr, 1);
2261
437k
    return code;
2262
216k
}
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
741k
{
2268
741k
    gs_fixed_point q0, q1;
2269
741k
    const patch_color_t *cc0, *cc1;
2270
741k
    fixed dx = p1->x - p0->x;
2271
741k
    fixed dy = p1->y - p0->y;
2272
741k
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2273
741k
    gs_fixed_edge le, re;
2274
741k
    const fixed adjust = INTERPATCH_PADDING;
2275
2276
741k
    if (swap_axes) {
2277
480k
        if (p0->x < p1->x) {
2278
217k
            q0.x = p0->y;
2279
217k
            q0.y = p0->x;
2280
217k
            q1.x = p1->y;
2281
217k
            q1.y = p1->x;
2282
217k
            cc0 = c0;
2283
217k
            cc1 = c1;
2284
263k
        } else {
2285
263k
            q0.x = p1->y;
2286
263k
            q0.y = p1->x;
2287
263k
            q1.x = p0->y;
2288
263k
            q1.y = p0->x;
2289
263k
            cc0 = c1;
2290
263k
            cc1 = c0;
2291
263k
        }
2292
480k
    } else if (p0->y < p1->y) {
2293
50.4k
        q0 = *p0;
2294
50.4k
        q1 = *p1;
2295
50.4k
        cc0 = c0;
2296
50.4k
        cc1 = c1;
2297
210k
    } else {
2298
210k
        q0 = *p1;
2299
210k
        q1 = *p0;
2300
210k
        cc0 = c1;
2301
210k
        cc1 = c0;
2302
210k
    }
2303
741k
    le.start.x = q0.x - adjust;
2304
741k
    re.start.x = q0.x + adjust;
2305
741k
    le.start.y = re.start.y = q0.y - adjust;
2306
741k
    le.end.x = q1.x - adjust;
2307
741k
    re.end.x = q1.x + adjust;
2308
741k
    le.end.y = re.end.y = q1.y + adjust;
2309
741k
    adjust_swapped_boundary(&re.start.x, swap_axes);
2310
741k
    adjust_swapped_boundary(&re.end.x, swap_axes);
2311
741k
    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
741k
}
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
610k
{
2325
610k
    r->p.x = r->q.x = p0->x;
2326
610k
    r->p.y = r->q.y = p0->y;
2327
2328
610k
    if (r->p.x > p1->x)
2329
238k
        r->p.x = p1->x;
2330
610k
    if (r->q.x < p1->x)
2331
308k
        r->q.x = p1->x;
2332
610k
    if (r->p.y > p1->y)
2333
299k
        r->p.y = p1->y;
2334
610k
    if (r->q.y < p1->y)
2335
220k
        r->q.y = p1->y;
2336
2337
610k
    if (r->p.x > p2->x)
2338
148k
        r->p.x = p2->x;
2339
610k
    if (r->q.x < p2->x)
2340
135k
        r->q.x = p2->x;
2341
610k
    if (r->p.y > p2->y)
2342
130k
        r->p.y = p2->y;
2343
610k
    if (r->q.y < p2->y)
2344
138k
        r->q.y = p2->y;
2345
2346
610k
    if (p3 == NULL)
2347
346k
        return;
2348
2349
264k
    if (r->p.x > p3->x)
2350
51.1k
        r->p.x = p3->x;
2351
264k
    if (r->q.x < p3->x)
2352
71.0k
        r->q.x = p3->x;
2353
264k
    if (r->p.y > p3->y)
2354
64.1k
        r->p.y = p3->y;
2355
264k
    if (r->q.y < p3->y)
2356
42.7k
        r->q.y = p3->y;
2357
264k
}
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
137k
{
2364
137k
    int code;
2365
2366
137k
    if (k > 1) {
2367
56.2k
        gs_fixed_point q[2][4];
2368
56.2k
        patch_color_t *c;
2369
56.2k
        bool save_inside = pfs->inside;
2370
56.2k
        byte *color_stack_ptr;
2371
2372
56.2k
        if (!pfs->inside) {
2373
53.9k
            gs_fixed_rect r, r1;
2374
2375
53.9k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2376
53.9k
            r.p.x -= INTERPATCH_PADDING;
2377
53.9k
            r.p.y -= INTERPATCH_PADDING;
2378
53.9k
            r.q.x += INTERPATCH_PADDING;
2379
53.9k
            r.q.y += INTERPATCH_PADDING;
2380
53.9k
            r1 = r;
2381
53.9k
            rect_intersect(r, pfs->rect);
2382
53.9k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2383
47.9k
                return 0;
2384
5.99k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2385
5.99k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2386
2.88k
                pfs->inside = true;
2387
5.99k
        }
2388
8.33k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2389
8.33k
        if (color_stack_ptr == NULL)
2390
0
            return_error(gs_error_unregistered); /* Must not happen. */
2391
8.33k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2392
8.33k
        split_curve(pole, q[0], q[1]);
2393
8.33k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2394
8.33k
        if (code >= 0)
2395
8.33k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2396
8.33k
        release_colors_inline(pfs, color_stack_ptr, 1);
2397
8.33k
        pfs->inside = save_inside;
2398
8.33k
        return code;
2399
80.9k
    } else {
2400
80.9k
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2401
79.2k
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2402
79.2k
            if (code < 0)
2403
0
                return code;
2404
79.2k
        }
2405
80.9k
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2406
4.19k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2407
76.7k
        return 0;
2408
80.9k
    }
2409
137k
}
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
778k
{
2417
    /* Generate wedges between 2 variants of a curve flattening. */
2418
    /* k0, k1 is a power of 2. */
2419
778k
    gs_fixed_point p[4];
2420
2421
778k
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2422
658k
        return 0; /* Wedges are zero area. */
2423
120k
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2424
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2425
0
    }
2426
120k
    p[0] = pole[0];
2427
120k
    p[1] = pole[pole_step];
2428
120k
    p[2] = pole[pole_step * 2];
2429
120k
    p[3] = pole[pole_step * 3];
2430
120k
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2431
778k
}
2432
2433
static inline void
2434
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2435
9.88k
{
2436
9.88k
    q[0] = p->p[0][0]->p;
2437
9.88k
    q[1] = p->p[0][1]->p;
2438
9.88k
    q[2] = p->p[1][1]->p;
2439
9.88k
    q[3] = p->p[1][0]->p;
2440
9.88k
}
2441
2442
static inline void
2443
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2444
9.88k
{
2445
9.88k
    fixed y = s[0].y;
2446
9.88k
    int i = 0;
2447
2448
9.88k
    if (y > s[1].y)
2449
5.53k
        i = 1, y = s[1].y;
2450
9.88k
    if (y > s[2].y)
2451
4.63k
        i = 2, y = s[2].y;
2452
9.88k
    if (y > s[3].y)
2453
534
        i = 3, y = s[3].y;
2454
9.88k
    q[0] = s[(i + 0) % 4];
2455
9.88k
    q[1] = s[(i + 1) % 4];
2456
9.88k
    q[2] = s[(i + 2) % 4];
2457
9.88k
    q[3] = s[(i + 3) % 4];
2458
9.88k
}
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
6.88k
{
2463
6.88k
    gs_fixed_edge ue;
2464
6.88k
    int code;
2465
6.88k
    gx_device_color dc;
2466
2467
#   if NOFILL_TEST
2468
        if (dbg_nofill)
2469
            return 0;
2470
#   endif
2471
6.88k
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2472
6.88k
    if (code < 0)
2473
0
        return code;
2474
6.88k
    if (le->end.y < re->end.y) {
2475
2.55k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2476
2.55k
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2477
2.55k
        if (code >= 0) {
2478
2.55k
            ue.start = le->end;
2479
2.55k
            ue.end = re->end;
2480
2.55k
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2481
2.55k
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2482
2.55k
        }
2483
4.33k
    } else if (le->end.y > re->end.y) {
2484
2.54k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2485
2.54k
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2486
2.54k
        if (code >= 0) {
2487
2.54k
            ue.start = re->end;
2488
2.54k
            ue.end = le->end;
2489
2.54k
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2490
2.54k
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2491
2.54k
        }
2492
2.54k
    } else
2493
1.78k
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2494
1.78k
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2495
6.88k
    return code;
2496
6.88k
}
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
5.10k
{
2502
5.10k
    patch_color_t *c[2];
2503
5.10k
    gs_fixed_edge le, re;
2504
5.10k
    fixed dx0, dy0, dx1, dy1;
2505
5.10k
    const shading_vertex_t *pp;
2506
5.10k
    int i, code = 0;
2507
5.10k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2508
2509
5.10k
    if (color_stack_ptr == NULL)
2510
0
        return_error(gs_error_unregistered); /* Must not happen. */
2511
5.10k
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2512
5.10k
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2513
20.4k
    for (i = 0; i < 3; i++) {
2514
        /* fixme : does optimizer compiler expand this cycle ? */
2515
15.3k
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2516
6.88k
            le.start = re.start = p0->p;
2517
6.88k
            le.end = p1->p;
2518
6.88k
            re.end = p2->p;
2519
2520
6.88k
            dx0 = le.end.x - le.start.x;
2521
6.88k
            dy0 = le.end.y - le.start.y;
2522
6.88k
            dx1 = re.end.x - re.start.x;
2523
6.88k
            dy1 = re.end.y - re.start.y;
2524
6.88k
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2525
1.53k
                code = ordered_triangle(pfs, &le, &re, c[1]);
2526
5.35k
            else
2527
5.35k
                code = ordered_triangle(pfs, &re, &le, c[1]);
2528
6.88k
            if (code < 0)
2529
0
                break;
2530
6.88k
        }
2531
15.3k
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2532
15.3k
    }
2533
5.10k
    release_colors_inline(pfs, color_stack_ptr, 2);
2534
5.10k
    return code;
2535
5.10k
}
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
9.88k
{
2541
    /* Assuming the XY span is restricted with curve_samples.
2542
       It is important for intersection_of_small_bars to compute faster. */
2543
9.88k
    gs_fixed_point q[4];
2544
9.88k
    fixed ry, ey;
2545
9.88k
    int code;
2546
9.88k
    bool swap_axes = false;
2547
9.88k
    gx_device_color dc;
2548
9.88k
    bool orient;
2549
2550
9.88k
    dc.tag = device_current_tag(pfs->dev);
2551
2552
9.88k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2553
9.88k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2554
9.88k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2555
9.88k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2556
9.88k
    if (code < 0)
2557
0
        return code;
2558
9.88k
    {   gs_fixed_point qq[4];
2559
2560
9.88k
        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
9.88k
        wrap_vertices_by_y(q, qq);
2573
9.88k
    }
2574
9.88k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2575
9.88k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2576
9.88k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2577
2578
9.88k
        if (g13 == h13) {
2579
60
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2580
60
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2581
2582
60
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2583
0
                return 0;
2584
60
            if (g23 != h23) {
2585
60
                orient = (g23 > h23);
2586
60
                if (q[2].y <= q[3].y) {
2587
60
                    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
60
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2590
60
                } else {
2591
0
                    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
0
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2594
0
                }
2595
60
            } 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
60
        }
2612
9.82k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2613
9.82k
    }
2614
9.82k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2615
3.38k
        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
3.38k
        } else {
2624
3.38k
            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
3.38k
            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
3.38k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2629
3.38k
        }
2630
6.44k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2631
4.66k
        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
4.66k
        } else {
2640
4.66k
            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
4.66k
            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
4.66k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2645
4.66k
        }
2646
4.66k
    } 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
1.77k
    } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2671
4
        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
4
        } 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
4
        } else {
2690
4
            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
4
            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
4
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2695
4
        }
2696
1.77k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2697
1.76k
        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
1.76k
        } else {
2706
1.76k
            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
1.76k
            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
1.76k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2711
1.76k
        }
2712
1.76k
    } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2713
4
        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
4
        } else {
2722
4
            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
4
            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
4
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2727
4
        }
2728
4
    } else {
2729
        /* Impossible. */
2730
0
        return_error(gs_error_unregistered);
2731
0
    }
2732
9.82k
}
2733
2734
int
2735
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2736
9.88k
{
2737
9.88k
    patch_color_t *c[3];
2738
9.88k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2739
9.88k
    int code;
2740
2741
9.88k
    if (color_stack_ptr == NULL)
2742
0
        return_error(gs_error_unregistered); /* Must not happen. */
2743
9.88k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2744
9.88k
    release_colors_inline(pfs, color_stack_ptr, 3);
2745
9.88k
    return code;
2746
9.88k
}
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
9.86k
{
2752
9.86k
    q[0].c = c[0];
2753
9.86k
    q[1].c = c[1];
2754
9.86k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2755
9.86k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2756
9.86k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2757
9.86k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2758
9.86k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2759
9.86k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2760
9.86k
    s0->p[0][0] = p->p[0][0];
2761
9.86k
    s0->p[0][1] = p->p[0][1];
2762
9.86k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2763
9.86k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2764
9.86k
    s1->p[1][0] = p->p[1][0];
2765
9.86k
    s1->p[1][1] = p->p[1][1];
2766
9.86k
}
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
5.46k
{
2772
5.46k
    q[0].c = c[0];
2773
5.46k
    q[1].c = c[1];
2774
5.46k
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2775
5.46k
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2776
5.46k
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2777
5.46k
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2778
5.46k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2779
5.46k
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2780
5.46k
    s0->p[0][0] = p->p[0][0];
2781
5.46k
    s0->p[1][0] = p->p[1][0];
2782
5.46k
    s0->p[0][1] = s1->p[0][0] = &q[0];
2783
5.46k
    s0->p[1][1] = s1->p[1][0] = &q[1];
2784
5.46k
    s1->p[0][1] = p->p[0][1];
2785
5.46k
    s1->p[1][1] = p->p[1][1];
2786
5.46k
}
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
15.8k
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2792
15.8k
    int code, r;
2793
2794
15.8k
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2795
15.8k
    if (code <= 0)
2796
9.96k
        return code;
2797
5.92k
    r = code << pfs->function_arg_shift;
2798
5.92k
    if (r & 1)
2799
0
        *not_monotonic_by_u = true;
2800
5.92k
    if (r & 2)
2801
5.92k
        *not_monotonic_by_v = true;
2802
5.92k
    return !code;
2803
15.8k
}
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
343k
{
2810
    /* Assuming p.c == c for providing a non-const access. */
2811
343k
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2812
343k
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2813
343k
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2814
343k
}
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
930k
{
2822
930k
    shading_vertex_t p01, p12, p20;
2823
930k
    patch_color_t *c[3];
2824
930k
    wedge_vertex_list_t L01, L12, L20, L[3];
2825
930k
    bool inside_save = pfs->inside;
2826
930k
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2827
930k
    int code = 0;
2828
930k
    byte *color_stack_ptr;
2829
930k
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2830
2831
930k
    if (!inside) {
2832
346k
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2833
346k
        r1 = r;
2834
346k
        rect_intersect(r, pfs->rect);
2835
346k
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2836
17.1k
            return 0;
2837
346k
    }
2838
913k
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2839
913k
    if(color_stack_ptr == NULL)
2840
0
        return_error(gs_error_unregistered);
2841
913k
    p01.c = c[0];
2842
913k
    p12.c = c[1];
2843
913k
    p20.c = c[2];
2844
913k
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2845
913k
    switch(code) {
2846
900k
        case 0: /* The area is filled. */
2847
900k
            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
12.7k
        case 1: /* decompose to linear color areas */
2873
12.7k
            if (sd < pfs->decomposition_limit) {
2874
5.10k
                code = constant_color_triangle(pfs, p2, p0, p1);
2875
5.10k
                goto out;
2876
5.10k
            }
2877
7.66k
            break;
2878
7.66k
        default: /* Error. */
2879
0
            goto out;
2880
913k
    }
2881
7.66k
    if (!inside) {
2882
2.57k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
2883
2.57k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
2884
422
            pfs->inside = true;
2885
2.57k
    }
2886
7.66k
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2887
7.66k
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2888
7.66k
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2889
7.66k
    if (LAZY_WEDGES) {
2890
7.66k
        init_wedge_vertex_list(L, count_of(L));
2891
7.66k
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2892
7.66k
        if (code >= 0)
2893
7.66k
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2894
7.66k
        if (code >= 0)
2895
7.66k
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2896
7.66k
    } 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
7.66k
    if (code >= 0)
2904
7.66k
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2905
7.66k
    if (code >= 0) {
2906
7.66k
        if (LAZY_WEDGES) {
2907
7.66k
            move_wedge(&L01, l01, true);
2908
7.66k
            move_wedge(&L20, l20, false);
2909
7.66k
        }
2910
7.66k
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2911
7.66k
    }
2912
7.66k
    if (code >= 0) {
2913
7.66k
        if (LAZY_WEDGES)
2914
7.66k
            move_wedge(&L12, l12, true);
2915
7.66k
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2916
7.66k
    }
2917
7.66k
    if (code >= 0) {
2918
7.66k
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2919
7.66k
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2920
7.66k
    }
2921
7.66k
    if (LAZY_WEDGES) {
2922
7.66k
        if (code >= 0)
2923
7.66k
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2924
7.66k
        if (code >= 0)
2925
7.66k
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2926
7.66k
        if (code >= 0)
2927
7.66k
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2928
7.66k
        if (code >= 0)
2929
7.66k
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2930
7.66k
        if (code >= 0)
2931
7.66k
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2932
7.66k
        if (code >= 0)
2933
7.66k
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2934
7.66k
    }
2935
7.66k
    pfs->inside = inside_save;
2936
913k
out:
2937
913k
    release_colors_inline(pfs, color_stack_ptr, 3);
2938
913k
    return code;
2939
7.66k
}
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
899k
{
2946
899k
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2947
899k
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2948
899k
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2949
899k
    fixed sd1 = max(sd01, sd12);
2950
899k
    fixed sd = max(sd1, sd20);
2951
899k
    double cd = 0;
2952
2953
#   if SKIP_TEST
2954
        dbg_triangle_cnt++;
2955
#   endif
2956
899k
    if (pfs->Function == NULL) {
2957
883k
        double d01 = color_span(pfs, p1->c, p0->c);
2958
883k
        double d12 = color_span(pfs, p2->c, p1->c);
2959
883k
        double d20 = color_span(pfs, p0->c, p2->c);
2960
883k
        double cd1 = max(d01, d12);
2961
2962
883k
        cd = max(cd1, d20);
2963
883k
    }
2964
899k
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2965
899k
}
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
1.46k
{
2971
1.46k
    int code;
2972
1.46k
    wedge_vertex_list_t l[3];
2973
2974
1.46k
    init_wedge_vertex_list(l, count_of(l));
2975
1.46k
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2976
1.46k
    if (code < 0)
2977
0
        return code;
2978
1.46k
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2979
1.46k
    if (code < 0)
2980
0
        return code;
2981
1.46k
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2982
1.46k
    if (code < 0)
2983
0
        return code;
2984
1.46k
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
2985
1.46k
}
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.61k
{
3083
1.61k
    pfs->unlinear = !is_linear_color_applicable(pfs);
3084
1.61k
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3085
1.61k
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3086
1.61k
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3087
1.46k
        return small_mesh_triangle(pfs, p0, p1, p2);
3088
146
    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
146
        shading_vertex_t p01, p12, p20;
3100
146
        patch_color_t *c[3];
3101
146
        int code;
3102
146
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3103
3104
146
        if (color_stack_ptr == NULL)
3105
0
            return_error(gs_error_unregistered); /* Must not happen. */
3106
146
        p01.c = c[0];
3107
146
        p12.c = c[1];
3108
146
        p20.c = c[2];
3109
146
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3110
146
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3111
146
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3112
146
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3113
146
        if (code >= 0)
3114
146
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3115
146
        if (code >= 0)
3116
146
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3117
146
        if (code >= 0)
3118
146
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3119
146
        if (code >= 0)
3120
146
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3121
146
        if (code >= 0)
3122
146
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3123
146
        if (code >= 0)
3124
146
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3125
146
        release_colors_inline(pfs, color_stack_ptr, 3);
3126
146
        return code;
3127
146
    }
3128
1.61k
}
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
1.02k
{
3134
1.02k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3135
1.02k
            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
0
        gx_device *pdev = pfs->dev;
3140
0
        gx_path path;
3141
0
        int code;
3142
0
        fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
3143
0
        fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
3144
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3145
3146
0
        gx_path_init_local(&path, pdev->memory);
3147
0
        code = gx_path_add_point(&path, p0->p.x, p0->p.y);
3148
0
        if (code >= 0 && s1 >= 0)
3149
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3150
0
        if (code >= 0)
3151
0
            code = gx_path_add_line(&path, p2->p.x, p2->p.y);
3152
0
        if (code >= 0 && s1 < 0)
3153
0
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3154
0
        if (code >= 0)
3155
0
            code = gx_path_close_subpath(&path);
3156
0
        if (code >= 0)
3157
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3158
0
        gx_path_free(&path, "mesh_triangle");
3159
0
        if (code < 0)
3160
0
            return code;
3161
0
    }
3162
1.02k
    return mesh_triangle_rec(pfs, p0, p1, p2);
3163
1.02k
}
3164
3165
static inline int
3166
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3167
106k
{
3168
106k
    shading_vertex_t p0001, p1011, q;
3169
106k
    patch_color_t *c[3];
3170
106k
    wedge_vertex_list_t l[4];
3171
106k
    int code;
3172
106k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3173
3174
106k
    if(color_stack_ptr == NULL)
3175
0
        return_error(gs_error_unregistered); /* Must not happen. */
3176
106k
    p0001.c = c[0];
3177
106k
    p1011.c = c[1];
3178
106k
    q.c = c[2];
3179
106k
    init_wedge_vertex_list(l, count_of(l));
3180
106k
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3181
106k
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3182
106k
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3183
106k
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3184
106k
    if (code >= 0) {
3185
106k
        l[0].last_side = true;
3186
106k
        l[3].last_side = true;
3187
106k
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3188
106k
    }
3189
106k
    if (code >= 0) {
3190
106k
        l[1].last_side = true;
3191
106k
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3192
106k
    }
3193
106k
    if (code >= 0) {
3194
106k
        l[2].last_side = true;
3195
106k
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3196
106k
    }
3197
106k
    if (code >= 0)
3198
106k
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3199
106k
    if (code >= 0)
3200
106k
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3201
106k
    if (code >= 0)
3202
106k
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3203
106k
    if (code >= 0)
3204
106k
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3205
106k
    release_colors_inline(pfs, color_stack_ptr, 3);
3206
106k
    return code;
3207
106k
}
3208
3209
static inline int
3210
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3211
235k
{
3212
235k
    wedge_vertex_list_t l;
3213
235k
    int code;
3214
3215
235k
    init_wedge_vertex_list(&l, 1);
3216
235k
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3217
235k
    if (code < 0)
3218
0
        return code;
3219
235k
    l.last_side = true;
3220
235k
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3221
235k
    if (code < 0)
3222
0
        return code;
3223
235k
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3224
235k
    if (code < 0)
3225
0
        return code;
3226
235k
    return 0;
3227
235k
}
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
423k
{
3233
423k
    qq[0][0].p = p->pole[0][0];
3234
423k
    qq[0][1].p = p->pole[0][3];
3235
423k
    qq[1][0].p = p->pole[3][0];
3236
423k
    qq[1][1].p = p->pole[3][3];
3237
423k
    qq[0][0].c = p->c[0][0];
3238
423k
    qq[0][1].c = p->c[0][1];
3239
423k
    qq[1][0].c = p->c[1][0];
3240
423k
    qq[1][1].c = p->c[1][1];
3241
423k
    q->p[0][0] = &qq[0][0];
3242
423k
    q->p[0][1] = &qq[0][1];
3243
423k
    q->p[1][0] = &qq[1][0];
3244
423k
    q->p[1][1] = &qq[1][1];
3245
423k
    q->l0001 = &l[0];
3246
423k
    q->l0111 = &l[1];
3247
423k
    q->l1110 = &l[2];
3248
423k
    q->l1000 = &l[3];
3249
423k
}
3250
3251
static inline int
3252
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3253
319k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3254
319k
    int code;
3255
3256
319k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3257
319k
    if (code <= 0)
3258
37
        return code;
3259
319k
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3260
319k
}
3261
3262
static inline int
3263
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3264
34.3k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3265
34.3k
    int code;
3266
3267
34.3k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3268
34.3k
    if (code <= 0)
3269
4.86k
        return code;
3270
29.4k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3271
34.3k
}
3272
3273
static inline int
3274
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3275
30.8k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3276
30.8k
    int code;
3277
3278
30.8k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3279
30.8k
    if (code <= 0)
3280
3.34k
        return code;
3281
27.5k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3282
30.8k
}
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
344k
{
3297
344k
    patch_color_t d0001, d1011, d;
3298
344k
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3299
344k
    double Du, Dv;
3300
3301
344k
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3302
344k
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3303
344k
    D0001 = color_norm(pfs, &d0001);
3304
344k
    D1011 = color_norm(pfs, &d1011);
3305
344k
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3306
344k
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3307
344k
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3308
344k
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3309
344k
    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
344k
    color_diff(pfs, &d0001, &d1011, &d);
3332
344k
    Du = max(D0001, D1011);
3333
344k
    Dv = max(D0010, D0111);
3334
344k
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3335
74.0k
        return color_change_small;
3336
270k
    if (Du <= pfs->smoothness / 8)
3337
7.42k
        return color_change_linear;
3338
262k
    if (Dv <= pfs->smoothness / 8)
3339
228k
        return color_change_linear;
3340
34.3k
    D = color_norm(pfs, &d);
3341
34.3k
    if (D <= pfs->smoothness)
3342
27.9k
        return color_change_bilinear;
3343
6.32k
#if 1
3344
6.32k
    if (Du > Dv && is_big_u)
3345
3.29k
        *divide_u = true;
3346
3.02k
    else if (Du < Dv && is_big_v)
3347
2.26k
        *divide_v = true;
3348
762
    else if (is_big_u && size_u > size_v)
3349
324
        *divide_u = true;
3350
438
    else if (is_big_v && size_v > size_u)
3351
438
        *divide_v = true;
3352
0
    else if (is_big_u)
3353
0
        *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
6.32k
    return color_change_general;
3368
6.32k
}
3369
3370
static int
3371
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3372
454k
{
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
454k
    quadrangle_patch s0, s1;
3377
454k
    wedge_vertex_list_t l0, l1, l2;
3378
454k
    int code;
3379
454k
    bool divide_u = false, divide_v = false, big1 = big;
3380
454k
    shading_vertex_t q[2];
3381
454k
    bool monotonic_color_save = pfs->monotonic_color;
3382
454k
    bool linear_color_save = pfs->linear_color;
3383
454k
    bool inside_save = pfs->inside;
3384
454k
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3385
454k
    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
454k
    if (!inside) {
3389
210k
        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
210k
        r1 = r;
3391
210k
        rect_intersect(r, pfs->rect);
3392
210k
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3393
86.6k
            return 0; /* Outside. */
3394
210k
    }
3395
367k
    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
337k
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3401
337k
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3402
337k
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3403
337k
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3404
337k
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3405
337k
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3406
337k
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3407
337k
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3408
3409
337k
        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
337k
            big1 = false;
3422
337k
    }
3423
367k
    if (!big1) {
3424
367k
        bool is_big_u = false, is_big_v = false;
3425
367k
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3426
367k
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3427
367k
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3428
367k
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3429
367k
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3430
367k
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3431
367k
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3432
367k
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3433
367k
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3434
367k
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3435
3436
367k
        if (size_u > pfs->decomposition_limit)
3437
348k
            is_big_u = true;
3438
367k
        if (size_v > pfs->decomposition_limit)
3439
50.0k
            is_big_v = true;
3440
317k
        else if (!is_big_u)
3441
14.3k
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3442
10.9k
                        constant_color_quadrangle : triangles4)(pfs, p,
3443
14.3k
                            pfs->maybe_self_intersecting);
3444
353k
        if (!pfs->monotonic_color) {
3445
15.8k
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3446
3447
15.8k
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3448
15.8k
            if (code < 0)
3449
0
                return code;
3450
15.8k
            if (is_big_u)
3451
15.3k
                divide_u = not_monotonic_by_u;
3452
15.8k
            if (is_big_v)
3453
11.1k
                divide_v = not_monotonic_by_v;
3454
15.8k
            if (!divide_u && !divide_v)
3455
11.8k
                pfs->monotonic_color = true;
3456
15.8k
        }
3457
353k
        if (pfs->monotonic_color && !pfs->linear_color) {
3458
336k
            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
336k
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3464
336k
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3465
319k
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3466
319k
                    if (code < 0)
3467
0
                        return code;
3468
319k
                    divide_u = !code;
3469
319k
                }
3470
336k
                if (is_big_v) {
3471
34.3k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3472
34.3k
                    if (code < 0)
3473
0
                        return code;
3474
34.3k
                    divide_v = !code;
3475
34.3k
                }
3476
336k
                if (is_big_u && is_big_v) {
3477
30.8k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3478
30.8k
                    if (code < 0)
3479
0
                        return code;
3480
30.8k
                    if (!code) {
3481
3.37k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3482
1.83k
                            divide_u = true;
3483
1.83k
                            divide_v = false;
3484
1.83k
                        } else {
3485
1.54k
                            divide_v = true;
3486
1.54k
                            divide_u = false;
3487
1.54k
                        }
3488
3.37k
                    }
3489
30.8k
                }
3490
336k
            }
3491
336k
            if (!divide_u && !divide_v)
3492
332k
                pfs->linear_color = true;
3493
336k
        }
3494
353k
        if (!pfs->linear_color) {
3495
            /* go to divide. */
3496
344k
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3497
74.0k
            case color_change_small:
3498
74.0k
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3499
67.6k
                            constant_color_quadrangle : triangles4)(pfs, p,
3500
74.0k
                                pfs->maybe_self_intersecting);
3501
74.0k
                pfs->monotonic_color = monotonic_color_save;
3502
74.0k
                pfs->linear_color = linear_color_save;
3503
74.0k
                return code;
3504
27.9k
            case color_change_bilinear:
3505
27.9k
                if (!QUADRANGLES) {
3506
27.9k
                    code = triangles4(pfs, p, true);
3507
27.9k
                    pfs->monotonic_color = monotonic_color_save;
3508
27.9k
                    pfs->linear_color = linear_color_save;
3509
27.9k
                    return code;
3510
27.9k
                }
3511
235k
            case color_change_linear:
3512
235k
                if (!QUADRANGLES) {
3513
235k
                    code = triangles2(pfs, p, true);
3514
235k
                    pfs->monotonic_color = monotonic_color_save;
3515
235k
                    pfs->linear_color = linear_color_save;
3516
235k
                    return code;
3517
235k
                }
3518
0
            case color_change_gradient:
3519
6.32k
            case color_change_general:
3520
6.32k
                ; /* goto divide. */
3521
344k
        }
3522
353k
    }
3523
15.3k
    if (!inside) {
3524
4.21k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3525
4.21k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3526
1.65k
            pfs->inside = true;
3527
4.21k
    }
3528
15.3k
    if (LAZY_WEDGES)
3529
15.3k
        init_wedge_vertex_list(&l0, 1);
3530
15.3k
    if (divide_v) {
3531
9.86k
        patch_color_t *c[2];
3532
9.86k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3533
3534
9.86k
        if(color_stack_ptr == NULL)
3535
0
            return_error(gs_error_unregistered); /* Must not happen. */
3536
9.86k
        q[0].c = c[0];
3537
9.86k
        q[1].c = c[1];
3538
9.86k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3539
9.86k
        if (LAZY_WEDGES) {
3540
9.86k
            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
9.86k
            if (code >= 0)
3542
9.86k
                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
9.86k
            if (code >= 0) {
3544
9.86k
                s0.l1110 = s1.l0001 = &l0;
3545
9.86k
                s0.l0111 = s1.l0111 = &l1;
3546
9.86k
                s0.l1000 = s1.l1000 = &l2;
3547
9.86k
                s0.l0001 = p->l0001;
3548
9.86k
                s1.l1110 = p->l1110;
3549
9.86k
            }
3550
9.86k
        } 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
9.86k
        if (code >= 0)
3556
9.86k
            code = fill_quadrangle(pfs, &s0, big1);
3557
9.86k
        if (code >= 0) {
3558
9.86k
            if (LAZY_WEDGES) {
3559
9.86k
                l0.last_side = true;
3560
9.86k
                move_wedge(&l1, p->l0111, true);
3561
9.86k
                move_wedge(&l2, p->l1000, false);
3562
9.86k
            }
3563
9.86k
            code = fill_quadrangle(pfs, &s1, big1);
3564
9.86k
        }
3565
9.86k
        if (LAZY_WEDGES) {
3566
9.86k
            if (code >= 0)
3567
9.86k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3568
9.86k
            if (code >= 0)
3569
9.86k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3570
9.86k
            if (code >= 0)
3571
9.86k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3572
9.86k
            release_colors_inline(pfs, color_stack_ptr, 2);
3573
9.86k
        }
3574
9.86k
    } else if (divide_u) {
3575
5.46k
        patch_color_t *c[2];
3576
5.46k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3577
3578
5.46k
        if(color_stack_ptr == NULL)
3579
0
            return_error(gs_error_unregistered); /* Must not happen. */
3580
5.46k
        q[0].c = c[0];
3581
5.46k
        q[1].c = c[1];
3582
5.46k
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3583
5.46k
        if (LAZY_WEDGES) {
3584
5.46k
            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
5.46k
            if (code >= 0)
3586
5.46k
                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
5.46k
            if (code >= 0) {
3588
5.46k
                s0.l0111 = s1.l1000 = &l0;
3589
5.46k
                s0.l0001 = s1.l0001 = &l1;
3590
5.46k
                s0.l1110 = s1.l1110 = &l2;
3591
5.46k
                s0.l1000 = p->l1000;
3592
5.46k
                s1.l0111 = p->l0111;
3593
5.46k
            }
3594
5.46k
        } 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
5.46k
        if (code >= 0)
3600
5.46k
            code = fill_quadrangle(pfs, &s0, big1);
3601
5.46k
        if (code >= 0) {
3602
5.46k
            if (LAZY_WEDGES) {
3603
5.46k
                l0.last_side = true;
3604
5.46k
                move_wedge(&l1, p->l0001, true);
3605
5.46k
                move_wedge(&l2, p->l1110, false);
3606
5.46k
            }
3607
5.46k
            code = fill_quadrangle(pfs, &s1, big1);
3608
5.46k
        }
3609
5.46k
        if (LAZY_WEDGES) {
3610
5.46k
            if (code >= 0)
3611
5.46k
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3612
5.46k
            if (code >= 0)
3613
5.46k
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3614
5.46k
            if (code >= 0)
3615
5.46k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3616
5.46k
            release_colors_inline(pfs, color_stack_ptr, 2);
3617
5.46k
        }
3618
5.46k
    } else
3619
0
        code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3620
0
                    constant_color_quadrangle : triangles4)(pfs, p,
3621
0
                        pfs->maybe_self_intersecting);
3622
15.3k
    pfs->monotonic_color = monotonic_color_save;
3623
15.3k
    pfs->linear_color = linear_color_save;
3624
15.3k
    pfs->inside = inside_save;
3625
15.3k
    return code;
3626
15.3k
}
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
1.00M
{
3632
1.00M
    s0->c[0][1] = c[0];
3633
1.00M
    s0->c[1][1] = c[1];
3634
1.00M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3635
1.00M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3636
1.00M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3637
1.00M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3638
1.00M
    s0->c[0][0] = p->c[0][0];
3639
1.00M
    s0->c[1][0] = p->c[1][0];
3640
1.00M
    s1->c[0][0] = s0->c[0][1];
3641
1.00M
    s1->c[1][0] = s0->c[1][1];
3642
1.00M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3643
1.00M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3644
1.00M
    s1->c[0][1] = p->c[0][1];
3645
1.00M
    s1->c[1][1] = p->c[1][1];
3646
1.00M
}
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
298k
{
3652
298k
    s0->c[1][0] = c[0];
3653
298k
    s0->c[1][1] = c[1];
3654
298k
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3655
298k
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3656
298k
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3657
298k
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3658
298k
    s0->c[0][0] = p->c[0][0];
3659
298k
    s0->c[0][1] = p->c[0][1];
3660
298k
    s1->c[0][0] = s0->c[1][0];
3661
298k
    s1->c[0][1] = s0->c[1][1];
3662
298k
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3663
298k
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3664
298k
    s1->c[1][0] = p->c[1][0];
3665
298k
    s1->c[1][1] = p->c[1][1];
3666
298k
}
3667
3668
static inline void
3669
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3670
2.09M
{
3671
2.09M
    int i, j;
3672
3673
2.09M
    r->p.x = r->q.x = p->pole[0][0].x;
3674
2.09M
    r->p.y = r->q.y = p->pole[0][0].y;
3675
10.4M
    for (i = 0; i < 4; i++) {
3676
41.9M
        for (j = 0; j < 4; j++) {
3677
33.5M
            const gs_fixed_point *q = &p->pole[i][j];
3678
3679
33.5M
            if (r->p.x > q->x)
3680
4.55M
                r->p.x = q->x;
3681
33.5M
            if (r->p.y > q->y)
3682
5.13M
                r->p.y = q->y;
3683
33.5M
            if (r->q.x < q->x)
3684
7.16M
                r->q.x = q->x;
3685
33.5M
            if (r->q.y < q->y)
3686
3.33M
                r->q.y = q->y;
3687
33.5M
        }
3688
8.38M
    }
3689
2.09M
}
3690
3691
static int
3692
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3693
2.34M
{
3694
2.34M
    if (ku > 1) {
3695
1.91M
        tensor_patch s0, s1;
3696
1.91M
        patch_color_t *c[2];
3697
1.91M
        int code;
3698
1.91M
        byte *color_stack_ptr;
3699
1.91M
        bool save_inside = pfs->inside;
3700
3701
1.91M
        if (!pfs->inside) {
3702
1.77M
            gs_fixed_rect r, r1;
3703
3704
1.77M
            tensor_patch_bbox(&r, p);
3705
1.77M
            r1 = r;
3706
1.77M
            rect_intersect(r, pfs->rect);
3707
1.77M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3708
911k
                return 0;
3709
860k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3710
860k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3711
31.5k
                pfs->inside = true;
3712
860k
        }
3713
1.00M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3714
1.00M
        if(color_stack_ptr == NULL)
3715
0
            return_error(gs_error_unregistered); /* Must not happen. */
3716
1.00M
        split_stripe(pfs, &s0, &s1, p, c);
3717
1.00M
        code = decompose_stripe(pfs, &s0, ku / 2);
3718
1.00M
        if (code >= 0)
3719
1.00M
            code = decompose_stripe(pfs, &s1, ku / 2);
3720
1.00M
        release_colors_inline(pfs, color_stack_ptr, 2);
3721
1.00M
        pfs->inside = save_inside;
3722
1.00M
        return code;
3723
1.00M
    } else {
3724
423k
        quadrangle_patch q;
3725
423k
        shading_vertex_t qq[2][2];
3726
423k
        wedge_vertex_list_t l[4];
3727
423k
        int code;
3728
3729
423k
        init_wedge_vertex_list(l, count_of(l));
3730
423k
        make_quadrangle(p, qq, l, &q);
3731
#       if SKIP_TEST
3732
            dbg_quad_cnt++;
3733
#       endif
3734
423k
        code = fill_quadrangle(pfs, &q, true);
3735
423k
        if (code < 0)
3736
0
            return code;
3737
423k
        if (LAZY_WEDGES) {
3738
423k
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3739
423k
            if (code < 0)
3740
0
                return code;
3741
423k
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3742
423k
            if (code < 0)
3743
0
                return code;
3744
423k
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3745
423k
            if (code < 0)
3746
0
                return code;
3747
423k
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3748
423k
            if (code < 0)
3749
0
                return code;
3750
423k
        }
3751
423k
        return code;
3752
423k
    }
3753
2.34M
}
3754
3755
static int
3756
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3757
329k
{
3758
    /* The stripe is flattened enough by V, so ignore inner poles. */
3759
329k
    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
329k
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3768
329k
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3769
329k
    kum = max(ku[0], ku[3]);
3770
329k
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3771
329k
    if (code < 0)
3772
0
        return code;
3773
329k
    if (INTERPATCH_PADDING) {
3774
329k
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3775
329k
        if (code < 0)
3776
0
            return code;
3777
329k
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3778
329k
        if (code < 0)
3779
0
            return code;
3780
329k
    }
3781
329k
    code = decompose_stripe(pfs, p, kum);
3782
329k
    if (code < 0)
3783
0
        return code;
3784
329k
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3785
329k
}
3786
3787
static inline bool neqs(int *a, int b)
3788
1.03M
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3789
1.03M
    if (*a * b < 0)
3790
287k
        return true;
3791
746k
    if (!*a)
3792
19.0k
        *a = b;
3793
746k
    return false;
3794
1.03M
}
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
1.36M
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3799
1.36M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3800
1.36M
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3801
3802
1.36M
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3803
1.36M
}
3804
3805
static inline bool
3806
is_x_bended(const tensor_patch *p)
3807
328k
{
3808
328k
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3809
3810
328k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3811
178k
        return true;
3812
149k
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3813
83.5k
        return true;
3814
66.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3815
24.8k
        return true;
3816
3817
41.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3818
161
        return true;
3819
41.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3820
0
        return true;
3821
41.0k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3822
40
        return true;
3823
41.0k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3824
50
        return true;
3825
3826
40.9k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3827
110
        return true;
3828
40.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3829
0
        return true;
3830
40.8k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3831
132
        return true;
3832
40.7k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3833
73
        return true;
3834
3835
40.6k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3836
18
        return true;
3837
40.6k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3838
0
        return true;
3839
40.6k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3840
29
        return true;
3841
40.6k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3842
12
        return true;
3843
40.6k
    return false;
3844
40.6k
}
3845
3846
static inline bool
3847
is_y_bended(const tensor_patch *p)
3848
0
{
3849
0
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3850
3851
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3852
0
        return true;
3853
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3854
0
        return true;
3855
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3856
0
        return true;
3857
3858
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3859
0
        return true;
3860
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3861
0
        return true;
3862
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3863
0
        return true;
3864
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3865
0
        return true;
3866
3867
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3868
0
        return true;
3869
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3870
0
        return true;
3871
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3872
0
        return true;
3873
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3874
0
        return true;
3875
3876
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3877
0
        return true;
3878
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3879
0
        return true;
3880
0
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3881
0
        return true;
3882
0
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3883
0
        return true;
3884
0
    return false;
3885
0
}
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
1.86M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3890
1.86M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3891
1.86M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3892
1.86M
    fixed xmin =  min(xmin0, xmin1);
3893
1.86M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3894
1.86M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3895
1.86M
    fixed xmax =  max(xmax0, xmax1);
3896
3897
1.86M
    if(xmax - xmin <= pfs->decomposition_limit)
3898
1.55M
        return true;
3899
312k
    return false;
3900
1.86M
}
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
1.18M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3905
1.18M
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3906
1.18M
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3907
1.18M
    fixed ymin =  min(ymin0, ymin1);
3908
1.18M
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3909
1.18M
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3910
1.18M
    fixed ymax =  max(ymax0, ymax1);
3911
3912
1.18M
    if (ymax - ymin <= pfs->decomposition_limit)
3913
1.17M
        return true;
3914
15.6k
    return false;
3915
1.18M
}
3916
3917
static inline bool
3918
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3919
617k
{
3920
617k
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3921
127k
        return false;
3922
489k
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3923
76.7k
        return false;
3924
413k
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3925
68.6k
        return false;
3926
344k
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3927
39.9k
        return false;
3928
304k
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3929
6.85k
        return false;
3930
297k
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3931
3.24k
        return false;
3932
294k
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3933
3.07k
        return false;
3934
291k
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3935
2.51k
        return false;
3936
288k
    return true;
3937
291k
}
3938
3939
static int
3940
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3941
656k
{
3942
656k
    if (kv <= 1) {
3943
617k
        if (is_patch_narrow(pfs, p))
3944
288k
            return fill_stripe(pfs, p);
3945
328k
        if (!is_x_bended(p))
3946
40.6k
            return fill_stripe(pfs, p);
3947
328k
    }
3948
327k
    {   tensor_patch s0, s1;
3949
327k
        patch_color_t *c[2];
3950
327k
        shading_vertex_t q0, q1, q2;
3951
327k
        int code = 0;
3952
327k
        byte *color_stack_ptr;
3953
327k
        bool save_inside = pfs->inside;
3954
3955
327k
        if (!pfs->inside) {
3956
324k
            gs_fixed_rect r, r1;
3957
3958
324k
            tensor_patch_bbox(&r, p);
3959
324k
            r.p.x -= INTERPATCH_PADDING;
3960
324k
            r.p.y -= INTERPATCH_PADDING;
3961
324k
            r.q.x += INTERPATCH_PADDING;
3962
324k
            r.q.y += INTERPATCH_PADDING;
3963
324k
            r1 = r;
3964
324k
            rect_intersect(r, pfs->rect);
3965
324k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3966
28.7k
                return 0;
3967
295k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3968
295k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3969
3.17k
                pfs->inside = true;
3970
295k
        }
3971
298k
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3972
298k
        if(color_stack_ptr == NULL)
3973
0
            return_error(gs_error_unregistered); /* Must not happen. */
3974
298k
        split_patch(pfs, &s0, &s1, p, c);
3975
298k
        if (kv0 <= 1) {
3976
288k
            q0.p = s0.pole[0][0];
3977
288k
            q0.c = s0.c[0][0];
3978
288k
            q1.p = s1.pole[3][0];
3979
288k
            q1.c = s1.c[1][0];
3980
288k
            q2.p = s0.pole[3][0];
3981
288k
            q2.c = s0.c[1][0];
3982
288k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3983
288k
        }
3984
298k
        if (kv1 <= 1 && code >= 0) {
3985
288k
            q0.p = s0.pole[0][3];
3986
288k
            q0.c = s0.c[0][1];
3987
288k
            q1.p = s1.pole[3][3];
3988
288k
            q1.c = s1.c[1][1];
3989
288k
            q2.p = s0.pole[3][3];
3990
288k
            q2.c = s0.c[1][1];
3991
288k
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3992
288k
        }
3993
298k
        if (code >= 0)
3994
298k
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
3995
298k
        if (code >= 0)
3996
298k
            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
298k
        release_colors_inline(pfs, color_stack_ptr, 2);
4017
298k
        pfs->inside = save_inside;
4018
298k
        return code;
4019
298k
    }
4020
298k
}
4021
4022
static inline int64_t
4023
lcp1(int64_t p0, int64_t p3)
4024
104k
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4025
104k
    return (p0 + p0 + p3);
4026
104k
}
4027
static inline int64_t
4028
lcp2(int64_t p0, int64_t p3)
4029
104k
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4030
104k
    return (p0 + p3 + p3);
4031
104k
}
4032
4033
static void
4034
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4035
239k
{
4036
239k
    if (pfs->Function) {
4037
20.8k
        c->t[0] = cc[0];
4038
20.8k
        c->t[1] = cc[1];
4039
20.8k
    } else
4040
218k
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4041
239k
}
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
59.8k
{
4047
59.8k
    const gs_color_space *pcs = pfs->direct_space;
4048
4049
59.8k
    p->pole[0][0] = curve[0].vertex.p;
4050
59.8k
    p->pole[1][0] = curve[0].control[0];
4051
59.8k
    p->pole[2][0] = curve[0].control[1];
4052
59.8k
    p->pole[3][0] = curve[1].vertex.p;
4053
59.8k
    p->pole[3][1] = curve[1].control[0];
4054
59.8k
    p->pole[3][2] = curve[1].control[1];
4055
59.8k
    p->pole[3][3] = curve[2].vertex.p;
4056
59.8k
    p->pole[2][3] = curve[2].control[0];
4057
59.8k
    p->pole[1][3] = curve[2].control[1];
4058
59.8k
    p->pole[0][3] = curve[3].vertex.p;
4059
59.8k
    p->pole[0][2] = curve[3].control[0];
4060
59.8k
    p->pole[0][1] = curve[3].control[1];
4061
59.8k
    if (interior != NULL) {
4062
54.6k
        p->pole[1][1] = interior[0];
4063
54.6k
        p->pole[1][2] = interior[1];
4064
54.6k
        p->pole[2][2] = interior[2];
4065
54.6k
        p->pole[2][1] = interior[3];
4066
54.6k
    } else {
4067
5.20k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4068
5.20k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4069
5.20k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4070
5.20k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4071
5.20k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4072
5.20k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4073
5.20k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4074
5.20k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4075
5.20k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4076
5.20k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4077
5.20k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4078
5.20k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4079
5.20k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4080
5.20k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4081
5.20k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4082
5.20k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4083
4084
5.20k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4085
5.20k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4086
5.20k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4087
5.20k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4088
5.20k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4089
5.20k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4090
5.20k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4091
5.20k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4092
5.20k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4093
5.20k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4094
5.20k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4095
5.20k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4096
5.20k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4097
5.20k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4098
5.20k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4099
5.20k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4100
5.20k
    }
4101
59.8k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4102
59.8k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4103
59.8k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4104
59.8k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4105
59.8k
    patch_resolve_color_inline(p->c[0][0], pfs);
4106
59.8k
    patch_resolve_color_inline(p->c[0][1], pfs);
4107
59.8k
    patch_resolve_color_inline(p->c[1][0], pfs);
4108
59.8k
    patch_resolve_color_inline(p->c[1][1], pfs);
4109
59.8k
    if (!pfs->Function) {
4110
54.6k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4111
54.6k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4112
54.6k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4113
54.6k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4114
54.6k
    }
4115
59.8k
}
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
4
{
4121
4
    gs_fixed_edge le, re;
4122
4123
4
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4124
4
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4125
4
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4126
4
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4127
4
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4128
4
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4129
4
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4130
4
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4131
4
    return dev_proc(pdev, fill_trapezoid)(pdev,
4132
4
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4133
4
}
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
59.8k
{
4141
59.8k
    tensor_patch p;
4142
59.8k
    patch_color_t *c[4];
4143
59.8k
    int kv[4], kvm, ku[4], kum;
4144
59.8k
    int code = 0;
4145
59.8k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4146
4147
59.8k
    p.c[0][0] = c[0];
4148
59.8k
    p.c[0][1] = c[1];
4149
59.8k
    p.c[1][0] = c[2];
4150
59.8k
    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
59.8k
    make_tensor_patch(pfs, &p, curve, interior);
4159
59.8k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4160
59.8k
    pfs->linear_color = false;
4161
59.8k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4162
59.8k
            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
0
        gx_device *pdev = pfs->dev;
4167
0
        gx_path path;
4168
0
        fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
4169
0
        fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
4170
0
        fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
4171
0
        fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
4172
0
        fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
4173
0
        fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
4174
0
        fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
4175
0
        fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
4176
0
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
4177
0
        int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
4178
0
        int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
4179
4180
0
        gx_path_init_local(&path, pdev->memory);
4181
0
        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
0
        } else {
4187
0
            code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
4188
0
            for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
4189
0
                j = (i + s) % 4, jj = (s == 1 ? i : j);
4190
0
                if (curve[jj].straight)
4191
0
                    code = gx_path_add_line(&path, curve[j].vertex.p.x,
4192
0
                                                curve[j].vertex.p.y);
4193
0
                else
4194
0
                    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
4195
0
                                                    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
4196
0
                                                    curve[j].vertex.p.x,
4197
0
                                                    curve[j].vertex.p.y);
4198
0
            }
4199
0
            if (code >= 0)
4200
0
                code = gx_path_close_subpath(&path);
4201
0
        }
4202
0
        if (code >= 0)
4203
0
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
4204
0
        gx_path_free(&path, "patch_fill");
4205
0
        if (code < 0)
4206
0
            goto out;
4207
0
    }
4208
    /* How many subdivisions of the patch in the u and v direction? */
4209
59.8k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4210
59.8k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4211
59.8k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4212
59.8k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4213
59.8k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4214
59.8k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4215
59.8k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4216
59.8k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4217
59.8k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4218
59.8k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4219
#   if NOFILL_TEST
4220
    dbg_nofill = false;
4221
#   endif
4222
59.8k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4223
59.8k
        interpatch_padding | inpatch_wedge);
4224
59.8k
    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
59.8k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4237
59.8k
    }
4238
59.8k
    if (code >= 0)
4239
59.8k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4240
59.8k
                interpatch_padding | inpatch_wedge);
4241
59.8k
out:
4242
59.8k
    release_colors_inline(pfs, color_stack_ptr, 4);
4243
59.8k
    return code;
4244
59.8k
}