Coverage Report

Created: 2026-10-28 08:05

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