Coverage Report

Created: 2025-06-10 06:56

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