Coverage Report

Created: 2026-09-14 07:34

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