Coverage Report

Created: 2026-04-01 07:17

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