Coverage Report

Created: 2026-07-24 07:44

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
27.7k
{
87
27.7k
    if (pfs->color_stack != NULL)
88
0
        return 0;
89
27.7k
    pfs->color_stack_step = offset_of(patch_color_t, cc.paint.values[pfs->num_components]);
90
27.7k
    pfs->color_stack_step = (pfs->color_stack_step + sizeof(void *) - 1) / sizeof(void *) * sizeof(void *); /* Alignment */
91
92
27.7k
    pfs->color_stack_size = pfs->color_stack_step * SHADING_COLOR_STACK_SIZE;
93
27.7k
    pfs->color_stack = gs_alloc_bytes(memory, pfs->color_stack_size, "allocate_color_stack");
94
27.7k
    if (pfs->color_stack == NULL)
95
0
        return_error(gs_error_VMerror);
96
27.7k
    pfs->color_stack_limit = pfs->color_stack + pfs->color_stack_size;
97
27.7k
    pfs->color_stack_ptr = pfs->color_stack;
98
27.7k
    pfs->memory = memory;
99
27.7k
    return 0;
100
27.7k
}
101
102
static inline byte *
103
reserve_colors_inline(patch_fill_state_t *pfs, patch_color_t *c[], int n)
104
128M
{
105
128M
    int i;
106
128M
    byte *ptr0 = pfs->color_stack_ptr, *ptr = ptr0;
107
108
416M
    for (i = 0; i < n; i++, ptr += pfs->color_stack_step)
109
287M
        c[i] = (patch_color_t *)ptr;
110
128M
    if (ptr > pfs->color_stack_limit) {
111
0
        c[0] = NULL; /* safety. */
112
0
        return NULL;
113
0
    }
114
128M
    pfs->color_stack_ptr = ptr;
115
128M
    return ptr0;
116
128M
}
117
118
byte *
119
reserve_colors(patch_fill_state_t *pfs, patch_color_t *c[], int n)
120
599
{
121
599
    return reserve_colors_inline(pfs, c, n);
122
599
}
123
124
static inline void
125
release_colors_inline(patch_fill_state_t *pfs, byte *ptr, int n)
126
128M
{
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
128M
    pfs->color_stack_ptr = ptr;
132
128M
#endif
133
128M
}
134
void
135
release_colors(patch_fill_state_t *pfs, byte *ptr, int n)
136
599
{
137
599
    release_colors_inline(pfs, ptr, n);
138
599
}
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
445k
{
145
445k
    int i, code = 0;
146
147
1.75M
    for (i = 0; i < num_vertices && code >= 0; ++i) {
148
1.30M
        curves[i].vertex.cc[1] = 0; /* safety. (patch_fill may assume 2 arguments) */
149
1.30M
        code = shade_next_color(cs, curves[i].vertex.cc);
150
1.30M
    }
151
445k
    return code;
152
445k
}
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.10M
{
158
1.10M
    int code = shade_next_coords(cs, &curve->vertex.p, 1);
159
160
1.10M
    if (code >= 0)
161
1.10M
        code = shade_next_coords(cs, curve->control,
162
1.10M
                                 countof(curve->control));
163
1.10M
    return code;
164
1.10M
}
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
445k
{
174
445k
    int flag = shade_next_flag(cs, BitsPerFlag);
175
445k
    int num_colors, code;
176
177
445k
    if (flag < 0) {
178
238
        if (!cs->is_eod(cs))
179
0
            return_error(gs_error_rangecheck);
180
238
        return 1;               /* no more data */
181
238
    }
182
445k
    if (cs->first_patch && (flag & 3) != 0) {
183
0
        return_error(gs_error_rangecheck);
184
0
    }
185
445k
    cs->first_patch = 0;
186
445k
    switch (flag & 3) {
187
0
        default:
188
0
            return_error(gs_error_rangecheck);  /* not possible */
189
209k
        case 0:
190
209k
            if ((code = shade_next_curve(cs, &curve[0])) < 0 ||
191
209k
                (code = shade_next_coords(cs, &curve[1].vertex.p, 1)) < 0
192
209k
                )
193
38
                return code;
194
209k
            num_colors = 4;
195
209k
            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.4k
        case 2:
200
71.4k
            curve[0] = curve[2], curve[1].vertex = curve[3].vertex;
201
71.4k
            goto v3;
202
100k
        case 3:
203
100k
            curve[1].vertex = curve[0].vertex, curve[0] = curve[3];
204
235k
v3:         num_colors = 2;
205
445k
vx:         if ((code = shade_next_coords(cs, curve[1].control, 2)) < 0 ||
206
445k
                (code = shade_next_curve(cs, &curve[2])) < 0 ||
207
445k
                (code = shade_next_curve(cs, &curve[3])) < 0 ||
208
445k
                (interior != 0 &&
209
445k
                 (code = shade_next_coords(cs, interior, 4)) < 0) ||
210
445k
                (code = shade_next_colors(cs, &curve[4 - num_colors],
211
445k
                                          num_colors)) < 0
212
445k
                )
213
383
                return code;
214
445k
            cs->align(cs, 8); /* See shade_next_vertex. */
215
445k
    }
216
445k
    return 0;
217
445k
}
218
219
static inline bool
220
is_linear_color_applicable(const patch_fill_state_t *pfs)
221
6.00M
{
222
6.00M
    if (!USE_LINEAR_COLOR_PROCS)
223
0
        return false;
224
6.00M
    if (!colors_are_separable_and_linear(&pfs->dev->color_info))
225
2.98M
        return false;
226
3.02M
    if (gx_get_cmap_procs(pfs->pgs, pfs->dev)->is_halftoned(pfs->pgs, pfs->dev))
227
316k
        return false;
228
2.70M
    return true;
229
3.02M
}
230
231
static int
232
alloc_patch_fill_memory(patch_fill_state_t *pfs, gs_memory_t *memory, const gs_color_space *pcs)
233
27.7k
{
234
27.7k
    int code;
235
236
27.7k
    pfs->memory = memory;
237
27.7k
#   if LAZY_WEDGES
238
27.7k
        code = wedge_vertex_list_elem_buffer_alloc(pfs);
239
27.7k
        if (code < 0)
240
0
            return code;
241
27.7k
#   endif
242
27.7k
    pfs->max_small_coord = 1 << ((sizeof(int64_t) * 8 - 1/*sign*/) / 3);
243
27.7k
    code = allocate_color_stack(pfs, memory);
244
27.7k
    if (code < 0)
245
0
        return code;
246
27.7k
    if (pfs->unlinear || pcs == NULL)
247
4.21k
        pfs->pcic = NULL;
248
23.5k
    else {
249
23.5k
        pfs->pcic = gs_color_index_cache_create(memory, pcs, pfs->dev, pfs->pgs, true, pfs->trans_device);
250
23.5k
        if (pfs->pcic == NULL)
251
0
            return_error(gs_error_VMerror);
252
23.5k
    }
253
27.7k
    return 0;
254
27.7k
}
255
256
int
257
init_patch_fill_state(patch_fill_state_t *pfs)
258
27.7k
{
259
    /* Warning : pfs->Function must be set in advance. */
260
27.7k
    const gs_color_space *pcs = pfs->direct_space;
261
27.7k
    gs_client_color fcc0, fcc1;
262
27.7k
    int i;
263
264
108k
    for (i = 0; i < pfs->num_components; i++) {
265
80.5k
        fcc0.paint.values[i] = -1000000;
266
80.5k
        fcc1.paint.values[i] = 1000000;
267
80.5k
    }
268
27.7k
    pcs->type->restrict_color(&fcc0, pcs);
269
27.7k
    pcs->type->restrict_color(&fcc1, pcs);
270
108k
    for (i = 0; i < pfs->num_components; i++)
271
80.5k
        pfs->color_domain.paint.values[i] = max(fcc1.paint.values[i] - fcc0.paint.values[i], 1);
272
27.7k
    pfs->vectorization = false; /* A stub for a while. Will use with pclwrite. */
273
27.7k
    pfs->maybe_self_intersecting = true;
274
27.7k
    pfs->monotonic_color = (pfs->Function == NULL);
275
27.7k
    pfs->function_arg_shift = 0;
276
27.7k
    pfs->linear_color = false;
277
27.7k
    pfs->inside = false;
278
27.7k
    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
27.7k
    pfs->decomposition_limit = fixed_1;
285
27.7k
#endif
286
27.7k
    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
27.7k
    pfs->smoothness = max(pfs->pgs->smoothness, 1.0 / min_linear_grades);
292
27.7k
    pfs->color_stack_size = 0;
293
27.7k
    pfs->color_stack_step = 0;
294
27.7k
    pfs->color_stack_ptr = NULL;
295
27.7k
    pfs->color_stack = NULL;
296
27.7k
    pfs->color_stack_limit = NULL;
297
27.7k
    pfs->unlinear = !is_linear_color_applicable(pfs);
298
27.7k
    pfs->pcic = NULL;
299
27.7k
    return alloc_patch_fill_memory(pfs, pfs->pgs->memory, pcs);
300
27.7k
}
301
302
bool
303
term_patch_fill_state(patch_fill_state_t *pfs)
304
27.7k
{
305
27.7k
    bool b = (pfs->color_stack_ptr != pfs->color_stack);
306
27.7k
#   if LAZY_WEDGES
307
27.7k
        wedge_vertex_list_elem_buffer_free(pfs);
308
27.7k
#   endif
309
27.7k
    if (pfs->color_stack)
310
27.7k
        gs_free_object(pfs->memory, pfs->color_stack, "term_patch_fill_state");
311
27.7k
    if (pfs->pcic != NULL)
312
23.5k
        gs_color_index_cache_destroy(pfs->pcic);
313
27.7k
    return b;
314
27.7k
}
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
72.3M
{
320
72.3M
    if (pfs->Function) {
321
70.6M
        const gs_color_space *pcs = pfs->direct_space;
322
323
70.6M
        gs_function_evaluate(pfs->Function, ppcr->t, ppcr->cc.paint.values);
324
70.6M
        pcs->type->restrict_color(&ppcr->cc, pcs);
325
70.6M
    }
326
72.3M
}
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
156M
{
344
    /* The old code gives -IND on Intel. */
345
156M
    if (pfs->Function) {
346
60.4M
        ppcr->t[0] = ppc0->t[0] * (1 - t) + t * ppc1->t[0];
347
60.4M
        ppcr->t[1] = ppc0->t[1] * (1 - t) + t * ppc1->t[1];
348
60.4M
        patch_resolve_color_inline(ppcr, pfs);
349
96.4M
    } else {
350
96.4M
        int ci;
351
352
438M
        for (ci = pfs->num_components - 1; ci >= 0; --ci)
353
341M
            ppcr->cc.paint.values[ci] =
354
341M
                ppc0->cc.paint.values[ci] * (1 - t) + t * ppc1->cc.paint.values[ci];
355
96.4M
    }
356
156M
}
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
35
{
446
35
    const gs_shading_Cp_t * const psh = (const gs_shading_Cp_t *)psh0;
447
35
    patch_fill_state_t state;
448
35
    shade_coord_stream_t cs;
449
35
    patch_curve_t curve[4];
450
35
    int code;
451
452
35
    code = mesh_init_fill_state((mesh_fill_state_t *) &state,
453
35
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
454
35
    if (code < 0) {
455
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
456
0
        return code;
457
0
    }
458
35
    state.Function = psh->params.Function;
459
35
    code = init_patch_fill_state(&state);
460
35
    if(code < 0) {
461
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
462
0
        return code;
463
0
    }
464
465
35
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
466
35
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
467
125
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
468
125
                                    curve, NULL)) == 0 &&
469
90
           (code = patch_fill(&state, curve, NULL, Cp_transform)) >= 0
470
90
        ) {
471
90
        DO_NOTHING;
472
90
    }
473
35
    if (term_patch_fill_state(&state))
474
0
        return_error(gs_error_unregistered); /* Must not happen. */
475
35
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
476
35
    return min(code, 0);
477
35
}
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
624
{
535
624
    const gs_shading_Tpp_t * const psh = (const gs_shading_Tpp_t *)psh0;
536
624
    patch_fill_state_t state;
537
624
    shade_coord_stream_t cs;
538
624
    patch_curve_t curve[4];
539
624
    gs_fixed_point interior[4];
540
624
    int code;
541
542
624
    code = mesh_init_fill_state((mesh_fill_state_t *) & state,
543
624
                         (const gs_shading_mesh_t *)psh0, rect_clip, dev, pgs);
544
624
    if (code < 0) {
545
0
        if (state.icclink != NULL) gsicc_release_link(state.icclink);
546
0
        return code;
547
0
    }
548
624
    state.Function = psh->params.Function;
549
624
    code = init_patch_fill_state(&state);
550
624
    if(code < 0)
551
0
        return code;
552
624
    curve[0].straight = curve[1].straight = curve[2].straight = curve[3].straight = false;
553
624
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params, pgs);
554
445k
    while ((code = shade_next_patch(&cs, psh->params.BitsPerFlag,
555
445k
                                    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
445k
        gs_fixed_point swapped_interior[4];
561
562
445k
        swapped_interior[0] = interior[0];
563
445k
        swapped_interior[1] = interior[3];
564
445k
        swapped_interior[2] = interior[2];
565
445k
        swapped_interior[3] = interior[1];
566
445k
        code = patch_fill(&state, curve, swapped_interior, Tpp_transform);
567
445k
        if (code < 0)
568
0
            break;
569
445k
    }
570
624
    if (term_patch_fill_state(&state))
571
0
        return_error(gs_error_unregistered); /* Must not happen. */
572
624
    if (state.icclink != NULL) gsicc_release_link(state.icclink);
573
624
    return min(code, 0);
574
624
}
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
27.7k
{
665
27.7k
    const int max_level = LAZY_WEDGES_MAX_LEVEL;
666
27.7k
    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
27.7k
    pfs->wedge_vertex_list_elem_count_max = max_level * (1 << max_level) * 2;
679
27.7k
    pfs->wedge_vertex_list_elem_buffer = (wedge_vertex_list_elem_t *)gs_alloc_bytes(memory,
680
27.7k
            sizeof(wedge_vertex_list_elem_t) * (size_t)pfs->wedge_vertex_list_elem_count_max,
681
27.7k
            "alloc_wedge_vertex_list_elem_buffer");
682
27.7k
    if (pfs->wedge_vertex_list_elem_buffer == NULL)
683
0
        return_error(gs_error_VMerror);
684
27.7k
    pfs->free_wedge_vertex = NULL;
685
27.7k
    pfs->wedge_vertex_list_elem_count = 0;
686
27.7k
    return 0;
687
27.7k
}
688
689
void
690
wedge_vertex_list_elem_buffer_free(patch_fill_state_t *pfs)
691
27.7k
{
692
27.7k
    gs_memory_t *memory = pfs->memory;
693
694
27.7k
    gs_free_object(memory, pfs->wedge_vertex_list_elem_buffer,
695
27.7k
                "wedge_vertex_list_elem_buffer_free");
696
27.7k
    pfs->wedge_vertex_list_elem_buffer = NULL;
697
27.7k
    pfs->free_wedge_vertex = NULL;
698
27.7k
}
699
700
static inline wedge_vertex_list_elem_t *
701
wedge_vertex_list_elem_reserve(patch_fill_state_t *pfs)
702
14.2M
{
703
14.2M
    wedge_vertex_list_elem_t *e = pfs->free_wedge_vertex;
704
705
14.2M
    if (e != NULL) {
706
13.9M
        pfs->free_wedge_vertex = e->next;
707
13.9M
        return e;
708
13.9M
    }
709
242k
    if (pfs->wedge_vertex_list_elem_count < pfs->wedge_vertex_list_elem_count_max)
710
242k
        return pfs->wedge_vertex_list_elem_buffer + pfs->wedge_vertex_list_elem_count++;
711
0
    return NULL;
712
242k
}
713
714
static inline void
715
wedge_vertex_list_elem_release(patch_fill_state_t *pfs, wedge_vertex_list_elem_t *e)
716
14.2M
{
717
14.2M
    e->next = pfs->free_wedge_vertex;
718
14.2M
    pfs->free_wedge_vertex = e;
719
14.2M
}
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.46M
{
725
8.46M
    wedge_vertex_list_elem_t *e = beg->next, *ee;
726
727
8.46M
    beg->next = end;
728
8.46M
    end->prev = beg;
729
15.5M
    for (; e != end; e = ee) {
730
7.12M
        ee = e->next;
731
7.12M
        wedge_vertex_list_elem_release(pfs, e);
732
7.12M
    }
733
8.46M
}
734
735
static inline int
736
release_wedge_vertex_list(patch_fill_state_t *pfs, wedge_vertex_list_t *ll, int n)
737
3.54M
{
738
3.54M
    int i;
739
740
7.09M
    for (i = 0; i < n; i++) {
741
3.54M
        wedge_vertex_list_t *l = ll + i;
742
743
3.54M
        if (l->beg != NULL) {
744
3.54M
            if (l->end == NULL)
745
0
                return_error(gs_error_unregistered); /* Must not happen. */
746
3.54M
            release_wedge_vertex_list_interval(pfs, l->beg, l->end);
747
3.54M
            wedge_vertex_list_elem_release(pfs, l->beg);
748
3.54M
            wedge_vertex_list_elem_release(pfs, l->end);
749
3.54M
            l->beg = l->end = NULL;
750
3.54M
        } else if (l->end != NULL)
751
0
            return_error(gs_error_unregistered); /* Must not happen. */
752
3.54M
    }
753
3.54M
    return 0;
754
3.54M
}
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.55M
{
760
5.55M
    wedge_vertex_list_elem_t *e = beg;
761
762
5.55M
    if (beg == NULL || end == NULL)
763
0
        return NULL; /* Must not happen. */
764
14.8M
    for (; e != end; e = e->next)
765
14.8M
        if (e->level == level)
766
5.55M
            return e;
767
0
    return NULL;
768
5.55M
}
769
770
static inline void
771
init_wedge_vertex_list(wedge_vertex_list_t *l, int n)
772
31.3M
{
773
31.3M
    memset(l, 0, sizeof(*l) * n);
774
31.3M
}
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
13.8M
{
785
13.8M
    curve_segment s;
786
13.8M
    int k;
787
788
13.8M
    s.p1.x = pole[pole_step].x;
789
13.8M
    s.p1.y = pole[pole_step].y;
790
13.8M
    s.p2.x = pole[pole_step * 2].x;
791
13.8M
    s.p2.y = pole[pole_step * 2].y;
792
13.8M
    s.pt.x = pole[pole_step * 3].x;
793
13.8M
    s.pt.y = pole[pole_step * 3].y;
794
13.8M
    k = gx_curve_log2_samples(pole[0].x, pole[0].y, &s, fixed_flat);
795
13.8M
    {
796
13.8M
#       if LAZY_WEDGES || QUADRANGLES
797
13.8M
            int k1;
798
13.8M
            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
13.8M
                      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
13.8M
                      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
13.8M
#       endif
802
803
13.8M
#       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
13.8M
            if (pfs->ShadingType == 1) {
818
                /* New 'smoothness based' logic. */
819
0
                k1 = ilog2(L / fixed_1 / (1 << ((int)ceil(pfs->smoothness * 30)) ));
820
13.8M
            } else {
821
                /* Igor's original logic. */
822
13.8M
                k1 = ilog2(L / fixed_1 / (1 << (LAZY_WEDGES_MAX_LEVEL - 1)));
823
13.8M
            }
824
13.8M
            k = max(k, k1);
825
13.8M
#       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
13.8M
    }
831
13.8M
    return 1 << k;
832
13.8M
}
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
60.0M
{
844
60.0M
    if (swap_axes) {
845
        /*  Sinse the rasterizer algorithm assumes semi-open interval
846
            when computing pixel coverage, we should expand
847
            the right side of the area. Otherwise a dropout can happen :
848
            if the left neighbour is painted with !swap_axes,
849
            the left side of this area appears to be the left side
850
            of the neighbour area, and the side is not included
851
            into both areas.
852
         */
853
27.7M
        *b += fixed_epsilon;
854
27.7M
    }
855
60.0M
}
856
857
static inline void
858
make_trapezoid(const gs_fixed_point q[4],
859
        int vi0, int vi1, int vi2, int vi3, fixed ybot, fixed ytop,
860
        bool swap_axes, bool orient, gs_fixed_edge *le, gs_fixed_edge *re)
861
11.3M
{
862
11.3M
    if (!orient) {
863
7.00M
        le->start = q[vi0];
864
7.00M
        le->end = q[vi1];
865
7.00M
        re->start = q[vi2];
866
7.00M
        re->end = q[vi3];
867
7.00M
    } else {
868
4.34M
        le->start = q[vi2];
869
4.34M
        le->end = q[vi3];
870
4.34M
        re->start = q[vi0];
871
4.34M
        re->end = q[vi1];
872
4.34M
    }
873
11.3M
    adjust_swapped_boundary(&re->start.x, swap_axes);
874
11.3M
    adjust_swapped_boundary(&re->end.x, swap_axes);
875
11.3M
}
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
572k
{
882
572k
    gs_fixed_edge le, re;
883
572k
    int code;
884
572k
    fixed ybot = max(ybot0, swap_axes ? pfs->rect.p.x : pfs->rect.p.y);
885
572k
    fixed ytop = min(ytop0, swap_axes ? pfs->rect.q.x : pfs->rect.q.y);
886
572k
    fixed xleft  = (swap_axes ? pfs->rect.p.y : pfs->rect.p.x);
887
572k
    fixed xright = (swap_axes ? pfs->rect.q.y : pfs->rect.q.x);
888
889
572k
    if (ybot >= ytop)
890
228k
        return 0;
891
#   if NOFILL_TEST
892
        if (dbg_nofill)
893
            return 0;
894
#   endif
895
343k
    make_trapezoid(q, vi0, vi1, vi2, vi3, ybot, ytop, swap_axes, orient, &le, &re);
896
343k
    if (!pfs->inside) {
897
120k
        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
120k
        if (le.start.x > xright) {
908
10.3k
            if (le.end.x > xright) {
909
31
                return 0;
910
31
            }
911
10.3k
            clip = true;
912
109k
        } else if (le.end.x > xright) {
913
6.78k
            clip = true;
914
6.78k
        }
915
120k
        if (le.start.x < xleft) {
916
26.5k
            if (le.end.x < xleft) {
917
11.8k
                le.start.x = xleft;
918
11.8k
                le.end.x   = xleft;
919
11.8k
                le.start.y = ybot;
920
11.8k
                le.end.y   = ytop;
921
14.7k
            } else {
922
14.7k
                clip = true;
923
14.7k
            }
924
93.7k
        } else if (le.end.x < xleft) {
925
13.4k
            clip = true;
926
13.4k
        }
927
120k
        if (re.start.x < xleft) {
928
7.31k
            if (re.end.x < xleft) {
929
17
                return 0;
930
17
            }
931
7.29k
            clip = true;
932
113k
        } else if (re.end.x < xleft) {
933
9.50k
            clip = true;
934
9.50k
        }
935
120k
        if (re.start.x > xright) {
936
23.9k
            if (re.end.x > xright) {
937
9.58k
                re.start.x = xright;
938
9.58k
                re.end.x   = xright;
939
9.58k
                re.start.y = ybot;
940
9.58k
                re.end.y   = ytop;
941
14.3k
            } else {
942
14.3k
                clip = true;
943
14.3k
            }
944
96.3k
        } else if (re.end.x > xright) {
945
14.2k
            clip = true;
946
14.2k
        }
947
120k
        if (clip)
948
50.9k
        {
949
            /* Some form of clipping seems to be required. A certain amount
950
             * of horridness goes on here to ensure that we round 'outwards'
951
             * in all cases. */
952
50.9k
            gs_fixed_edge lenew, renew;
953
50.9k
            fixed ybl, ybr, ytl, ytr, ymid;
954
955
            /* Reduce the clipping region horizontally if possible. */
956
50.9k
            if (re.start.x > re.end.x) {
957
20.1k
                if (re.start.x < xright)
958
5.76k
                    xright = re.start.x;
959
30.8k
            } else if (re.end.x < xright)
960
7.53k
                xright = re.end.x;
961
50.9k
            if (le.start.x > le.end.x) {
962
20.1k
                if (le.end.x > xleft)
963
6.73k
                    xleft = le.end.x;
964
30.7k
            } else if (le.start.x > xleft)
965
7.19k
                xleft = le.start.x;
966
967
50.9k
            ybot = max(ybot, min(le.start.y, re.start.y));
968
50.9k
            ytop = min(ytop, max(le.end.y, re.end.y));
969
#if 0
970
            /* RJW: I've disabled this code a) because it doesn't make any
971
             * difference in the cluster tests, and b) because I think it's wrong.
972
             * Taking the first case as an example; just because the le.start.x
973
             * is > xright, does not mean that we can simply truncate the edge at
974
             * xright, as this may throw away part of the trap between ybot and
975
             * the new le.start.y. */
976
            /* Reduce the edges to the left/right of the clipping region. */
977
            /* Only in the 4 cases which can bring ytop/ybot closer */
978
            if (le.start.x > xright) {
979
                le.start.y += (fixed)((int64_t)(le.end.y-le.start.y)*
980
                                      (int64_t)(le.start.x-xright)/
981
                                      (int64_t)(le.start.x-le.end.x));
982
                le.start.x = xright;
983
            }
984
            if (re.start.x < xleft) {
985
                re.start.y += (fixed)((int64_t)(re.end.y-re.start.y)*
986
                                      (int64_t)(xleft-re.start.x)/
987
                                      (int64_t)(re.end.x-re.start.x));
988
                re.start.x = xleft;
989
            }
990
            if (le.end.x > xright) {
991
                le.end.y -= (fixed)((int64_t)(le.end.y-le.start.y)*
992
                                    (int64_t)(le.end.x-xright)/
993
                                    (int64_t)(le.end.x-le.start.x));
994
                le.end.x = xright;
995
            }
996
            if (re.end.x < xleft) {
997
                re.end.y -= (fixed)((int64_t)(re.end.y-re.start.y)*
998
                                    (int64_t)(xleft-re.end.x)/
999
                                    (int64_t)(re.start.x-re.end.x));
1000
                re.end.x = xleft;
1001
            }
1002
#endif
1003
1004
50.9k
            if (ybot >= ytop)
1005
0
                return 0;
1006
            /* Follow the edges in, so that le.start.y == ybot etc. */
1007
50.9k
            if (le.start.y < ybot) {
1008
23.6k
                int round = ((le.end.x < le.start.x) ?
1009
12.4k
                             (le.end.y-le.start.y-1) : 0);
1010
23.6k
                le.start.x += (fixed)(((int64_t)(ybot-le.start.y)*
1011
23.6k
                                       (int64_t)(le.end.x-le.start.x)-round)/
1012
23.6k
                                      (int64_t)(le.end.y-le.start.y));
1013
23.6k
                le.start.y = ybot;
1014
23.6k
            }
1015
50.9k
            if (le.end.y > ytop) {
1016
23.6k
                int round = ((le.end.x > le.start.x) ?
1017
16.0k
                             (le.end.y-le.start.y-1) : 0);
1018
23.6k
                le.end.x += (fixed)(((int64_t)(le.end.y-ytop)*
1019
23.6k
                                     (int64_t)(le.start.x-le.end.x)-round)/
1020
23.6k
                                    (int64_t)(le.end.y-le.start.y));
1021
23.6k
                le.end.y = ytop;
1022
23.6k
            }
1023
50.9k
            if ((le.start.x < xleft) && (le.end.x < xleft)) {
1024
13.3k
                le.start.x = xleft;
1025
13.3k
                le.end.x   = xleft;
1026
13.3k
                le.start.y = ybot;
1027
13.3k
                le.end.y   = ytop;
1028
13.3k
            }
1029
50.9k
            if (re.start.y < ybot) {
1030
23.8k
                int round = ((re.end.x > re.start.x) ?
1031
16.1k
                             (re.end.y-re.start.y-1) : 0);
1032
23.8k
                re.start.x += (fixed)(((int64_t)(ybot-re.start.y)*
1033
23.8k
                                       (int64_t)(re.end.x-re.start.x)+round)/
1034
23.8k
                                      (int64_t)(re.end.y-re.start.y));
1035
23.8k
                re.start.y = ybot;
1036
23.8k
            }
1037
50.9k
            if (re.end.y > ytop) {
1038
23.8k
                int round = ((re.end.x < re.start.x) ?
1039
12.4k
                             (re.end.y-re.start.y-1) : 0);
1040
23.8k
                re.end.x += (fixed)(((int64_t)(re.end.y-ytop)*
1041
23.8k
                                     (int64_t)(re.start.x-re.end.x)+round)/
1042
23.8k
                                    (int64_t)(re.end.y-re.start.y));
1043
23.8k
                re.end.y = ytop;
1044
23.8k
            }
1045
50.9k
            if ((re.start.x > xright) && (re.end.x > xright)) {
1046
5.06k
                re.start.x = xright;
1047
5.06k
                re.end.x   = xright;
1048
5.06k
                re.start.y = ybot;
1049
5.06k
                re.end.y   = ytop;
1050
5.06k
            }
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
50.9k
            if (le.start.x > re.start.x) {
1057
13.5k
                if (le.start.x == le.end.x) {
1058
6.49k
                    if (re.start.x == re.end.x)
1059
0
                        return 0;
1060
6.49k
                    ybot += (fixed)((int64_t)(re.end.y-re.start.y)*
1061
6.49k
                                    (int64_t)(le.start.x-re.start.x)/
1062
6.49k
                                    (int64_t)(re.end.x-re.start.x));
1063
6.49k
                    re.start.x = le.start.x;
1064
7.07k
                } else {
1065
7.07k
                    ybot += (fixed)((int64_t)(le.end.y-le.start.y)*
1066
7.07k
                                    (int64_t)(le.start.x-re.start.x)/
1067
7.07k
                                    (int64_t)(le.start.x-le.end.x));
1068
7.07k
                    le.start.x = re.start.x;
1069
7.07k
                }
1070
13.5k
                if (ybot >= ytop)
1071
4.70k
                    return 0;
1072
8.86k
                le.start.y = ybot;
1073
8.86k
                re.start.y = ybot;
1074
8.86k
            }
1075
46.2k
            if (le.end.x > re.end.x) {
1076
8.62k
                if (le.start.x == le.end.x) {
1077
5.16k
                    if (re.start.x == re.end.x)
1078
0
                        return 0;
1079
5.16k
                    ytop -= (fixed)((int64_t)(re.end.y-re.start.y)*
1080
5.16k
                                    (int64_t)(le.end.x-re.end.x)/
1081
5.16k
                                    (int64_t)(re.start.x-re.end.x));
1082
5.16k
                    re.end.x = le.end.x;
1083
5.16k
                } else {
1084
3.45k
                    ytop -= (fixed)((int64_t)(le.end.y-le.start.y)*
1085
3.45k
                                    (int64_t)(le.end.x-re.end.x)/
1086
3.45k
                                    (int64_t)(le.end.x-le.start.x));
1087
3.45k
                    le.end.x = re.end.x;
1088
3.45k
                }
1089
8.62k
                if (ybot >= ytop)
1090
4.21k
                    return 0;
1091
4.40k
                le.end.y = ytop;
1092
4.40k
                re.end.y = ytop;
1093
4.40k
            }
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
42.0k
            lenew.start.x = xleft;
1100
42.0k
            lenew.start.y = ybot;
1101
42.0k
            lenew.end.x   = xleft;
1102
42.0k
            lenew.end.y   = ytop;
1103
42.0k
            renew.start.x = xright;
1104
42.0k
            renew.start.y = ybot;
1105
42.0k
            renew.end.x   = xright;
1106
42.0k
            renew.end.y   = ytop;
1107
            /* Figure out where the left edge intersects with the left at
1108
             * the bottom */
1109
42.0k
            ybl = ybot;
1110
42.0k
            if (le.start.x > le.end.x) {
1111
12.1k
                ybl += (fixed)((int64_t)(le.start.x-xleft) *
1112
12.1k
                               (int64_t)(le.end.y-le.start.y) /
1113
12.1k
                               (int64_t)(le.start.x-le.end.x));
1114
12.1k
                if (ybl > ytop)
1115
4.29k
                    ybl = ytop;
1116
12.1k
            }
1117
            /* Figure out where the right edge intersects with the right at
1118
             * the bottom */
1119
42.0k
            ybr = ybot;
1120
42.0k
            if (re.start.x < re.end.x) {
1121
15.4k
                ybr += (fixed)((int64_t)(xright-re.start.x) *
1122
15.4k
                               (int64_t)(re.end.y-re.start.y) /
1123
15.4k
                               (int64_t)(re.end.x-re.start.x));
1124
15.4k
                if (ybr > ytop)
1125
5.22k
                    ybr = ytop;
1126
15.4k
            }
1127
            /* Figure out where the left edge intersects with the left at
1128
             * the top */
1129
42.0k
            ytl = ytop;
1130
42.0k
            if (le.end.x > le.start.x) {
1131
12.1k
                ytl -= (fixed)((int64_t)(le.end.x-xleft) *
1132
12.1k
                               (int64_t)(le.end.y-le.start.y) /
1133
12.1k
                               (int64_t)(le.end.x-le.start.x));
1134
12.1k
                if (ytl < ybot)
1135
5.29k
                    ytl = ybot;
1136
12.1k
            }
1137
            /* Figure out where the right edge intersects with the right at
1138
             * the bottom */
1139
42.0k
            ytr = ytop;
1140
42.0k
            if (re.end.x < re.start.x) {
1141
16.8k
                ytr -= (fixed)((int64_t)(xright-re.end.x) *
1142
16.8k
                               (int64_t)(re.end.y-re.start.y) /
1143
16.8k
                               (int64_t)(re.start.x-re.end.x));
1144
16.8k
                if (ytr < ybot)
1145
4.40k
                    ytr = ybot;
1146
16.8k
            }
1147
            /* Check for the 2 cases where top and bottom diagonal extents
1148
             * overlap, and deal with them explicitly. */
1149
42.0k
            if (ytl < ybr) {
1150
                /*     |     |
1151
                 *  ---+-----+---
1152
                 *     | /222|
1153
                 *     |/111/|
1154
                 *     |000/ |
1155
                 *  ---+-----+---
1156
                 *     |     |
1157
                 */
1158
5.26k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1159
5.26k
                                        &lenew, &re, ybot, ytl,
1160
5.26k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1161
5.26k
                if (code < 0)
1162
0
                    return code;
1163
5.26k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1164
5.26k
                                        &le, &re, ytl, ybr,
1165
5.26k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1166
5.26k
                if (code < 0)
1167
0
                    return code;
1168
5.26k
                ybot = ybr;
1169
5.26k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1170
5.26k
                                        &le, &renew, ybr, ytop,
1171
5.26k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1172
36.7k
            } else if (ytr < ybl) {
1173
                /*     |     |
1174
                 *  ---+-----+----
1175
                 *     |555\ |
1176
                 *     |\444\|
1177
                 *     | \333|
1178
                 *  ---+-----+---
1179
                 *     |     |
1180
                 */
1181
6.03k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1182
6.03k
                                        &le, &renew, ybot, ytr,
1183
6.03k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1184
6.03k
                if (code < 0)
1185
0
                    return code;
1186
6.03k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1187
6.03k
                                        &le, &re, ytr, ybl,
1188
6.03k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1189
6.03k
                if (code < 0)
1190
0
                    return code;
1191
6.03k
                return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1192
6.03k
                                        &le, &re, ybl, ytop,
1193
6.03k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1194
6.03k
            }
1195
            /* Fill in any section where both left and right edges are
1196
             * diagonal at the bottom */
1197
30.7k
            ymid = ybl;
1198
30.7k
            if (ymid > ybr)
1199
3.91k
                ymid = ybr;
1200
30.7k
            if (ymid > ybot) {
1201
                /*     |\   |          |   /|
1202
                 *     | \6/|    or    |\6/ |
1203
                 *  ---+----+---    ---+----+---
1204
                 *     |    |          |    |
1205
                 */
1206
2.21k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1207
2.21k
                                        &le, &re, ybot, ymid,
1208
2.21k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1209
2.21k
                if (code < 0)
1210
0
                    return code;
1211
2.21k
                ybot = ymid;
1212
2.21k
            }
1213
            /* Fill in any section where both left and right edges are
1214
             * diagonal at the top */
1215
30.7k
            ymid = ytl;
1216
30.7k
            if (ymid < ytr)
1217
3.71k
                ymid = ytr;
1218
30.7k
            if (ymid < ytop) {
1219
                /*     |    |          |    |
1220
                 *  ---+----+---    ---+----+---
1221
                 *     |/7\ |    or    | /7\|
1222
                 *     |   \|          |/   |
1223
                 */
1224
2.81k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1225
2.81k
                                        &le, &re, ymid, ytop,
1226
2.81k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1227
2.81k
                if (code < 0)
1228
0
                    return code;
1229
2.81k
                ytop = ymid;
1230
2.81k
            }
1231
            /* Now do the single diagonal cases at the bottom */
1232
30.7k
            if (ybl > ybot) {
1233
                /*     |    |
1234
                 *     |\666|
1235
                 *  ---+----+---
1236
                 *     |    |
1237
                 */
1238
3.91k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1239
3.91k
                                        &le, &renew, ybot, ybl,
1240
3.91k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1241
3.91k
                if (code < 0)
1242
0
                    return code;
1243
3.91k
                ybot = ybl;
1244
26.8k
            } else if (ybr > ybot) {
1245
                /*     |    |
1246
                 *     |777/|
1247
                 *  ---+----+---
1248
                 *     |    |
1249
                 */
1250
3.76k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1251
3.76k
                                        &lenew, &re, ybot, ybr,
1252
3.76k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1253
3.76k
                if (code < 0)
1254
0
                    return code;
1255
3.76k
                ybot = ybr;
1256
3.76k
            }
1257
            /* Now do the single diagonal cases at the top */
1258
30.7k
            if (ytl < ytop) {
1259
                /*     |    |
1260
                 *  ---+----+---
1261
                 *     |/888|
1262
                 *     |    |
1263
                 */
1264
3.71k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1265
3.71k
                                        &le, &renew, ytl, ytop,
1266
3.71k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1267
3.71k
                if (code < 0)
1268
0
                    return code;
1269
3.71k
                ytop = ytl;
1270
27.0k
            } else if (ytr < ytop) {
1271
                /*     |    |
1272
                 *  ---+----+---
1273
                 *     |999\|
1274
                 *     |    |
1275
                 */
1276
3.92k
                code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1277
3.92k
                                        &lenew, &re, ytr, ytop,
1278
3.92k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1279
3.92k
                if (code < 0)
1280
0
                    return code;
1281
3.92k
                ytop = ytr;
1282
3.92k
            }
1283
            /* And finally just whatever rectangular section is left over in
1284
             * the middle */
1285
30.7k
            if (ybot > ytop)
1286
0
                return 0;
1287
30.7k
            return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1288
30.7k
                                        &lenew, &renew, ybot, ytop,
1289
30.7k
                                        swap_axes, pdevc, pfs->pgs->log_op);
1290
30.7k
        }
1291
120k
    }
1292
292k
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1293
292k
            &le, &re, ybot, ytop, swap_axes, pdevc, pfs->pgs->log_op);
1294
343k
}
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
207M
#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
103M
{
1329
    /* Must return 2 if the color is not pure.
1330
       See try_device_linear_color.
1331
     */
1332
103M
    int code;
1333
103M
    gx_device_color devc;
1334
1335
103M
#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
103M
     if (frac_values) {
1363
67.4M
        int i;
1364
67.4M
        int n = pfs->dev->color_info.num_components;
1365
82.8M
        for (i = pfs->num_components; i < n; i++) {
1366
15.3M
            frac_values[i] = 0;
1367
15.3M
        }
1368
67.4M
    }
1369
103M
#endif
1370
1371
103M
    if (pdevc == NULL)
1372
8.78M
        pdevc = &devc;
1373
103M
    pdevc->tag = pfs->dev->graphics_type_tag;
1374
103M
    if (pfs->pcic) {
1375
68.1M
        code = gs_cached_color_index(pfs->pcic, c->cc.paint.values, pdevc, frac_values);
1376
68.1M
        if (code < 0)
1377
0
            return code;
1378
68.1M
    }
1379
103M
    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.6M
        gs_client_color fcc;
1384
35.6M
        const gs_color_space *pcs = pfs->direct_space;
1385
1386
35.6M
        if (pcs != NULL) {
1387
35.6M
            memcpy(fcc.paint.values, c->cc.paint.values,
1388
35.6M
                        sizeof(fcc.paint.values[0]) * pfs->num_components);
1389
35.6M
            code = pcs->type->remap_color(&fcc, pcs, pdevc, pfs->pgs,
1390
35.6M
                                      pfs->trans_device, gs_color_select_texture);
1391
35.6M
            if (code < 0)
1392
0
                return code;
1393
35.6M
            if (frac_values != NULL) {
1394
0
                if (!(pdevc->type == &gx_dc_type_data_devn ||
1395
0
                      pdevc->type == &gx_dc_type_data_pure))
1396
0
                    return 2;
1397
0
                dc2fc31(pfs, pdevc, frac_values);
1398
0
            }
1399
#           if DEBUG_COLOR_INDEX_CACHE
1400
            if (cindex != pdevc->colors.pure)
1401
                return_error(gs_error_unregistered);
1402
#           endif
1403
35.6M
        } else {
1404
            /* This is reserved for future extension,
1405
            when a linear color triangle with frac31 colors is being decomposed
1406
            during a clist rasterization. In this case frac31 colors are written into
1407
            the patch color, and pcs==NULL means an identity color mapping.
1408
            For a while we assume here pfs->pcic is also NULL. */
1409
0
            int j;
1410
0
            const gx_device_color_info *cinfo = &pfs->dev->color_info;
1411
1412
0
            for (j = 0; j < cinfo->num_components; j++)
1413
0
                frac_values[j] = (frac31)c->cc.paint.values[j];
1414
0
            pdevc->type = &gx_dc_type_data_pure;
1415
0
        }
1416
35.6M
    }
1417
103M
    return 0;
1418
103M
}
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
159M
{
1429
159M
    int n = pfs->num_components, i;
1430
159M
    double m;
1431
1432
    /* Dont want to copy colors, which are big things. */
1433
159M
    m = any_abs(c1->cc.paint.values[0] - c0->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1434
550M
    for (i = 1; i < n; i++)
1435
391M
        m = max(m, any_abs(c1->cc.paint.values[i] - c0->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1436
159M
    return m;
1437
159M
}
1438
1439
static inline void
1440
color_diff(const patch_fill_state_t *pfs, const patch_color_t *c0, const patch_color_t *c1, patch_color_t *d)
1441
29.8M
{
1442
29.8M
    int n = pfs->num_components, i;
1443
1444
137M
    for (i = 0; i < n; i++)
1445
107M
        d->cc.paint.values[i] = c1->cc.paint.values[i] - c0->cc.paint.values[i];
1446
29.8M
}
1447
1448
static inline double
1449
color_norm(const patch_fill_state_t *pfs, const patch_color_t *c)
1450
22.5M
{
1451
22.5M
    int n = pfs->num_components, i;
1452
22.5M
    double m;
1453
1454
22.5M
    m = any_abs(c->cc.paint.values[0]) / pfs->color_domain.paint.values[0];
1455
80.4M
    for (i = 1; i < n; i++)
1456
57.8M
        m = max(m, any_abs(c->cc.paint.values[i]) / pfs->color_domain.paint.values[i]);
1457
22.5M
    return m;
1458
22.5M
}
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.35M
{   /* 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.35M
    uint mask;
1478
9.35M
    int code = gs_function_is_monotonic(pfs->Function, c0->t, c1->t, &mask);
1479
1480
9.35M
    if (code >= 0)
1481
9.35M
        return mask;
1482
20
    return code;
1483
9.35M
}
1484
1485
static inline bool
1486
covers_pixel_centers(fixed ybot, fixed ytop)
1487
15.0M
{
1488
15.0M
    return fixed_pixround(ybot) < fixed_pixround(ytop);
1489
15.0M
}
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.96M
{
1495
7.96M
    gx_device_color dc;
1496
7.96M
    int code;
1497
1498
#   if NOFILL_TEST
1499
        /* if (dbg_nofill)
1500
                return 0; */
1501
#   endif
1502
1503
7.96M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
1504
7.96M
    if (code < 0)
1505
0
        return code;
1506
1507
7.96M
    dc.tag = device_current_tag(pfs->dev);
1508
1509
7.96M
    return dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
1510
7.96M
        le, re, ybot, ytop, swap_axes, &dc, pfs->pgs->log_op);
1511
7.96M
}
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
79.3M
{
1516
79.3M
    float s = 0;
1517
1518
79.3M
    if (pfs->Function != NULL) {
1519
5.13M
        patch_color_t c;
1520
        /* Solaris 9 (Sun C 5.5) compiler cannot initialize a 'const' */
1521
        /* unless it is 'static const' */
1522
5.13M
        static const float q[2] = {(float)0.3, (float)0.7};
1523
5.13M
        int i, j;
1524
1525
14.8M
        for (j = 0; j < count_of(q); j++) {
1526
10.0M
            c.t[0] = c0->t[0] * (1 - q[j]) + c1->t[0] * q[j];
1527
10.0M
            c.t[1] = c0->t[1] * (1 - q[j]) + c1->t[1] * q[j];
1528
10.0M
            patch_resolve_color_inline(&c, pfs);
1529
38.5M
            for (i = 0; i < pfs->num_components; i++) {
1530
28.7M
                float v = c0->cc.paint.values[i] * (1 - q[j]) + c1->cc.paint.values[i] * q[j];
1531
28.7M
                float d = v - c.cc.paint.values[i];
1532
28.7M
                float s1 = any_abs(d) / pfs->color_domain.paint.values[i];
1533
1534
28.7M
                if (s1 > pfs->smoothness)
1535
268k
                    return s1;
1536
28.4M
                if (s < s1)
1537
2.65M
                    s = s1;
1538
28.4M
            }
1539
10.0M
        }
1540
5.13M
    }
1541
79.0M
    return s;
1542
79.3M
}
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
23.9M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
1547
23.9M
    if (pfs->unlinear)
1548
3.79M
        return 1; /* Disable this check. */
1549
20.2M
    else {
1550
20.2M
        const gs_color_space *cs = pfs->direct_space;
1551
20.2M
        int code;
1552
20.2M
        float s = function_linearity(pfs, c0, c1);
1553
1554
20.2M
        if (s > pfs->smoothness)
1555
179k
            return 0;
1556
20.0M
        if (pfs->cs_always_linear)
1557
5.57M
            return 1;
1558
14.4M
        code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
1559
14.4M
                &c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
1560
14.4M
        if (code <= 0)
1561
93.8k
            return code;
1562
14.3M
        return 1;
1563
14.4M
    }
1564
23.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
39.6M
{
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
39.6M
    int code;
1575
39.6M
    patch_color_t *c;
1576
39.6M
    byte *color_stack_ptr;
1577
39.6M
    bool save_inside = pfs->inside;
1578
1579
39.6M
    if (!pfs->inside) {
1580
36.2M
        gs_fixed_rect r, r1;
1581
1582
36.2M
        if(swap_axes) {
1583
16.4M
            r.p.y = min(le->start.x, le->end.x);
1584
16.4M
            r.p.x = min(le->start.y, le->end.y);
1585
16.4M
            r.q.y = max(re->start.x, re->end.x);
1586
16.4M
            r.q.x = max(re->start.y, re->end.y);
1587
19.8M
        } else {
1588
19.8M
            r.p.x = min(le->start.x, le->end.x);
1589
19.8M
            r.p.y = min(le->start.y, le->end.y);
1590
19.8M
            r.q.x = max(re->start.x, re->end.x);
1591
19.8M
            r.q.y = max(re->start.y, re->end.y);
1592
19.8M
        }
1593
36.2M
        r1 = r;
1594
36.2M
        rect_intersect(r, pfs->rect);
1595
36.2M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
1596
22.3M
            return 0;
1597
13.9M
        if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
1598
6.46M
            r1.q.x == r.q.x && r1.q.y == r.q.y)
1599
5.27M
            pfs->inside = true;
1600
13.9M
    }
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
925k
        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
6.81M
            code = isnt_color_monotonic(pfs, c0, c1);
1616
6.81M
            if (code < 0)
1617
20
                goto out;
1618
6.81M
            if (!code)
1619
5.38M
                pfs->monotonic_color = true;
1620
6.81M
        }
1621
16.4M
        if (pfs->monotonic_color && !pfs->linear_color) {
1622
8.29M
            code = is_color_linear(pfs, c0, c1);
1623
8.29M
            if (code < 0)
1624
0
                goto out;
1625
8.29M
            if (code > 0)
1626
8.17M
                pfs->linear_color =  true;
1627
8.29M
        }
1628
16.4M
        if (!pfs->unlinear && pfs->linear_color) {
1629
4.39M
            gx_device *pdev = pfs->dev;
1630
4.39M
            frac31 fc[2][GX_DEVICE_COLOR_MAX_COMPONENTS];
1631
4.39M
            gs_fill_attributes fa;
1632
4.39M
            gs_fixed_rect clip;
1633
1634
4.39M
            memset(fc, 0x99, sizeof(fc));
1635
1636
4.39M
            clip = pfs->rect;
1637
4.39M
            if (swap_axes) {
1638
1.08M
                fixed v;
1639
1640
1.08M
                v = clip.p.x; clip.p.x = clip.p.y; clip.p.y = v;
1641
1.08M
                v = clip.q.x; clip.q.x = clip.q.y; clip.q.y = v;
1642
                /* Don't need adjust_swapped_boundary here. */
1643
1.08M
            }
1644
4.39M
            clip.p.y = max(clip.p.y, ybot);
1645
4.39M
            clip.q.y = min(clip.q.y, ytop);
1646
4.39M
            fa.clip = &clip;
1647
4.39M
            fa.ht = NULL;
1648
4.39M
            fa.swap_axes = swap_axes;
1649
4.39M
            fa.lop = 0;
1650
4.39M
            fa.ystart = ybot;
1651
4.39M
            fa.yend = ytop;
1652
4.39M
            code = patch_color_to_device_color_inline(pfs, c0, NULL, fc[0]);
1653
4.39M
            if (code < 0)
1654
0
                goto out;
1655
4.39M
            if (code == 2) {
1656
                /* Must not happen. */
1657
0
                code=gs_note_error(gs_error_unregistered);
1658
0
                goto out;
1659
0
            }
1660
4.39M
            code = patch_color_to_device_color_inline(pfs, c1, NULL, fc[1]);
1661
4.39M
            if (code < 0)
1662
0
                goto out;
1663
4.39M
            code = dev_proc(pdev, fill_linear_color_trapezoid)(pdev, &fa,
1664
4.39M
                            &le->start, &le->end, &re->start, &re->end,
1665
4.39M
                            fc[0], fc[1], NULL, NULL);
1666
4.39M
            if (code == 1) {
1667
4.39M
                pfs->monotonic_color = monotonic_color_save;
1668
4.39M
                pfs->linear_color = linear_color_save;
1669
4.39M
                code = 0; /* The area is filled. */
1670
4.39M
                goto out;
1671
4.39M
            }
1672
17
            if (code < 0)
1673
17
                goto out;
1674
0
            else {      /* code == 0, the device requested to decompose the area. */
1675
0
                code = gs_note_error(gs_error_unregistered); /* Must not happen. */
1676
0
                goto out;
1677
0
            }
1678
17
        }
1679
12.0M
        if (!pfs->unlinear || !pfs->linear_color ||
1680
10.5M
                color_span(pfs, c0, c1) > pfs->smoothness) {
1681
5.00M
            fixed y = (ybot + ytop) / 2;
1682
1683
5.00M
            code = decompose_linear_color(pfs, le, re, ybot, y, swap_axes, c0, c);
1684
5.00M
            if (code >= 0)
1685
5.00M
                code = decompose_linear_color(pfs, le, re, y, ytop, swap_axes, c, c1);
1686
5.00M
        } else
1687
7.04M
            code = constant_color_trapezoid(pfs, le, re, ybot, ytop, swap_axes, c);
1688
12.0M
        pfs->monotonic_color = monotonic_color_save;
1689
12.0M
        pfs->linear_color = linear_color_save;
1690
12.0M
    }
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
11.0M
{
1702
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1703
11.0M
    gs_fixed_edge le, re;
1704
1705
11.0M
    make_trapezoid(q, i0, i1, i2, i3, ybot, ytop, swap_axes, orient, &le, &re);
1706
11.0M
    return decompose_linear_color(pfs, &le, &re, ybot, ytop, swap_axes, c0, c1);
1707
11.0M
}
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
15.0M
{
1714
    /* Assuming a very narrow trapezoid - ignore the transversal color change. */
1715
15.0M
    fixed dx1, dy1, dx2, dy2;
1716
15.0M
    bool orient;
1717
1718
15.0M
    if (!pfs->vectorization && !covers_pixel_centers(ybot, ytop))
1719
4.01M
        return 0;
1720
11.0M
    if (ybot == ytop)
1721
0
        return 0;
1722
11.0M
    dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
1723
11.0M
    dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
1724
11.0M
    if ((int64_t)dx1 * dy2 != (int64_t)dy1 * dx2) {
1725
5.49M
        orient = ((int64_t)dx1 * dy2 > (int64_t)dy1 * dx2);
1726
5.49M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1727
5.51M
    } else {
1728
5.51M
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
1729
1730
5.51M
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
1731
5.51M
        return linear_color_trapezoid(pfs, q, 0, 1, 2, 3, ybot, ytop, swap_axes, c0, c1, orient);
1732
5.51M
    }
1733
11.0M
}
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
15.0M
{
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
15.0M
    gs_fixed_point p[4];
1743
15.0M
    const patch_color_t *cc0, *cc1;
1744
1745
15.0M
    if (p0->y < p1->y) {
1746
6.97M
        p[2] = *p0;
1747
6.97M
        p[3] = *p1;
1748
6.97M
        cc0 = c0;
1749
6.97M
        cc1 = c1;
1750
8.05M
    } else {
1751
8.05M
        p[2] = *p1;
1752
8.05M
        p[3] = *p0;
1753
8.05M
        cc0 = c1;
1754
8.05M
        cc1 = c0;
1755
8.05M
    }
1756
15.0M
    p[0] = *q0;
1757
15.0M
    p[1] = *q1;
1758
15.0M
    return wedge_trap_decompose(pfs, p, p[2].y, p[3].y, cc0, cc1, swap_axes, self_intersecting);
1759
15.0M
}
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
111M
{
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
111M
#define midpoint(a,b)\
1773
1.34G
  (arith_rshift_1(a) + arith_rshift_1(b) + (((a) | (b)) & 1))
1774
111M
    fixed x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
1775
111M
    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
111M
    q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
1779
111M
    q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
1780
111M
    q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
1781
111M
    q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
1782
111M
    q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
1783
111M
    q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
1784
111M
    q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
1785
111M
    q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
1786
111M
    q0[0 * pole_step].x = pole[0 * pole_step].x;
1787
111M
    q0[0 * pole_step].y = pole[0 * pole_step].y;
1788
111M
    q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
1789
111M
    q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
1790
111M
    q1[3 * pole_step].x = pole[3 * pole_step].x;
1791
111M
    q1[3 * pole_step].y = pole[3 * pole_step].y;
1792
111M
#undef midpoint
1793
111M
}
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.02M
{
1798
4.02M
    split_curve_s(pole, q0, q1, 1);
1799
4.02M
}
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
15.4M
{
1842
15.4M
    fixed dx = any_abs(p1->x - p0->x), dy = any_abs(p1->y - p0->y);
1843
1844
15.4M
    return max(dx, dy);
1845
15.4M
}
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.54M
{
1851
3.54M
    if (l->end != NULL)
1852
0
        return_error(gs_error_unregistered); /* Must not happen. */
1853
3.54M
    l->beg = wedge_vertex_list_elem_reserve(pfs);
1854
3.54M
    l->end = wedge_vertex_list_elem_reserve(pfs);
1855
3.54M
    if (l->beg == NULL)
1856
0
        return_error(gs_error_unregistered); /* Must not happen. */
1857
3.54M
    if (l->end == NULL)
1858
0
        return_error(gs_error_unregistered); /* Must not happen. */
1859
3.54M
    l->beg->prev = l->end->next = NULL;
1860
3.54M
    l->beg->next = l->end;
1861
3.54M
    l->end->prev = l->beg;
1862
3.54M
    l->beg->p = *p0;
1863
3.54M
    l->end->p = *p1;
1864
3.54M
    l->beg->level = l->end->level = 0;
1865
3.54M
    return 0;
1866
3.54M
}
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.12M
{
1872
7.12M
    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.12M
    if (e == NULL)
1877
0
        return_error(gs_error_unregistered); /* Must not happen. */
1878
7.12M
    if (l->beg->next != l->end)
1879
0
        return_error(gs_error_unregistered); /* Must not happen. */
1880
7.12M
    if (l->end->prev != l->beg)
1881
0
        return_error(gs_error_unregistered); /* Must not happen. */
1882
7.12M
    e->next = l->end;
1883
7.12M
    e->prev = l->beg;
1884
7.12M
    e->p = *p;
1885
7.12M
    e->level = max(l->beg->level, l->end->level) + 1;
1886
7.12M
    e->divide_count = 0;
1887
7.12M
    l->beg->next = l->end->prev = e;
1888
7.12M
    {   int sx = l->beg->p.x < l->end->p.x ? 1 : -1;
1889
7.12M
        int sy = l->beg->p.y < l->end->p.y ? 1 : -1;
1890
1891
7.12M
        if ((p->x - l->beg->p.x) * sx < 0)
1892
0
            return_error(gs_error_unregistered); /* Must not happen. */
1893
7.12M
        if ((p->y - l->beg->p.y) * sy < 0)
1894
0
            return_error(gs_error_unregistered); /* Must not happen. */
1895
7.12M
        if ((l->end->p.x - p->x) * sx < 0)
1896
0
            return_error(gs_error_unregistered); /* Must not happen. */
1897
7.12M
        if ((l->end->p.y - p->y) * sy < 0)
1898
0
            return_error(gs_error_unregistered); /* Must not happen. */
1899
7.12M
    }
1900
7.12M
    *r = e;
1901
7.12M
    return 0;
1902
7.12M
}
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
11.8M
{
1909
11.8M
    wedge_vertex_list_elem_t *e;
1910
11.8M
    int code;
1911
1912
11.8M
    if (!l->last_side) {
1913
6.96M
        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
6.96M
        if (l->beg->p.x != p0->x)
1919
0
            return_error(gs_error_unregistered); /* Must not happen. */
1920
6.96M
        if (l->beg->p.y != p0->y)
1921
0
            return_error(gs_error_unregistered); /* Must not happen. */
1922
6.96M
        if (l->end->p.x != p1->x)
1923
0
            return_error(gs_error_unregistered); /* Must not happen. */
1924
6.96M
        if (l->end->p.y != p1->y)
1925
0
            return_error(gs_error_unregistered); /* Must not happen. */
1926
6.96M
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1927
6.96M
        if (code < 0)
1928
0
            return code;
1929
6.96M
        e->divide_count++;
1930
6.96M
    } else if (l->beg == NULL) {
1931
99.3k
        code = create_wedge_vertex_list(pfs, l, p1, p0);
1932
99.3k
        if (code < 0)
1933
0
            return code;
1934
99.3k
        code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1935
99.3k
        if (code < 0)
1936
0
            return code;
1937
99.3k
        e->divide_count++;
1938
4.81M
    } else {
1939
4.81M
        if (l->beg->p.x != p1->x)
1940
0
            return_error(gs_error_unregistered); /* Must not happen. */
1941
4.81M
        if (l->beg->p.y != p1->y)
1942
0
            return_error(gs_error_unregistered); /* Must not happen. */
1943
4.81M
        if (l->end->p.x != p0->x)
1944
0
            return_error(gs_error_unregistered); /* Must not happen. */
1945
4.81M
        if (l->end->p.y != p0->y)
1946
0
            return_error(gs_error_unregistered); /* Must not happen. */
1947
4.81M
        if (l->beg->next == l->end) {
1948
54.8k
            code = insert_wedge_vertex_list_elem(pfs, l, pm, &e);
1949
54.8k
            if (code < 0)
1950
0
                return code;
1951
54.8k
            e->divide_count++;
1952
4.76M
        } else {
1953
4.76M
            e = wedge_vertex_list_find(l->beg, l->end,
1954
4.76M
                        max(l->beg->level, l->end->level) + 1);
1955
4.76M
            if (e == NULL)
1956
0
                return_error(gs_error_unregistered); /* Must not happen. */
1957
4.76M
            if (e->p.x != pm->x || e->p.y != pm->y)
1958
0
                return_error(gs_error_unregistered); /* Must not happen. */
1959
4.76M
            e->divide_count++;
1960
4.76M
        }
1961
4.81M
    }
1962
11.8M
    *r = e;
1963
11.8M
    return 0;
1964
11.8M
}
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
11.8M
{
1971
11.8M
    int code;
1972
1973
11.8M
    l->last_side = l0->last_side;
1974
11.8M
    if (!l->last_side ^ !forth) {
1975
6.91M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->end);
1976
6.91M
        l->beg = l0->beg;
1977
6.91M
    } else {
1978
4.97M
        code = open_wedge_median(pfs, l0, p0, p1, pm, &l->beg);
1979
4.97M
        l->end = l0->end;
1980
4.97M
    }
1981
11.8M
    return code;
1982
11.8M
}
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
11.8M
{
1991
11.8M
    int code;
1992
1993
11.8M
    if (!l->last_side)
1994
6.96M
        return 0;
1995
4.91M
    code = fill_wedge_from_list(pfs, l, c1, c0);
1996
4.91M
    if (code < 0)
1997
0
        return code;
1998
4.91M
    release_wedge_vertex_list_interval(pfs, l->beg, l->end);
1999
4.91M
    return 0;
2000
4.91M
}
2001
2002
static inline void
2003
move_wedge(wedge_vertex_list_t *l, const wedge_vertex_list_t *l0, bool forth)
2004
11.8M
{
2005
11.8M
    if (!l->last_side ^ !forth) {
2006
6.91M
        l->beg = l->end;
2007
6.91M
        l->end = l0->end;
2008
6.91M
    } else {
2009
4.97M
        l->end = l->beg;
2010
4.97M
        l->beg = l0->beg;
2011
4.97M
    }
2012
11.8M
}
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.51M
{   int code;
2018
7.51M
    const gs_fixed_point *p0, *p1, *p2;
2019
7.51M
    gs_fixed_point qq0, qq1, qq2;
2020
7.51M
    fixed dx = any_abs(q0->p.x - q1->p.x), dy = any_abs(q0->p.y - q1->p.y);
2021
7.51M
    bool swap_axes;
2022
2023
#   if SKIP_TEST
2024
        dbg_wedge_triangle_cnt++;
2025
#   endif
2026
7.51M
    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.45M
        swap_axes = false;
2039
2.45M
        p0 = &q0->p;
2040
2.45M
        p1 = &q1->p;
2041
2.45M
        p2 = &q2->p;
2042
2.45M
    }
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.51M
    if (p0->y < p1->y) {
2048
3.49M
        code = fill_wedge_trap(pfs, p0, p2, p0, p1, q0->c, q2->c, swap_axes, false);
2049
3.49M
        if (code < 0)
2050
2
            return code;
2051
3.49M
        return fill_wedge_trap(pfs, p2, p1, p0, p1, q2->c, q1->c, swap_axes, false);
2052
4.01M
    } else {
2053
4.01M
        code = fill_wedge_trap(pfs, p0, p2, p1, p0, q0->c, q2->c, swap_axes, false);
2054
4.01M
        if (code < 0)
2055
3
            return code;
2056
4.01M
        return fill_wedge_trap(pfs, p2, p1, p1, p0, q2->c, q1->c, swap_axes, false);
2057
4.01M
    }
2058
7.51M
}
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
46.4M
{
2065
    /*  Returns :
2066
        <0 - error;
2067
        0 - success;
2068
        1 - decompose to linear color areas;
2069
        2 - decompose to constant color areas;
2070
     */
2071
46.4M
    int code;
2072
2073
46.4M
    if (pfs->unlinear)
2074
26.7M
        return 2;
2075
19.7M
    if (!wedge) {
2076
19.7M
        const gs_color_space *cs = pfs->direct_space;
2077
2078
19.7M
        if (cs != NULL) {
2079
19.7M
            float s0, s1, s2, s01, s012;
2080
2081
19.7M
            s0 = function_linearity(pfs, p0->c, p1->c);
2082
19.7M
            if (s0 > pfs->smoothness)
2083
57.2k
                return 1;
2084
19.7M
            s1 = function_linearity(pfs, p1->c, p2->c);
2085
19.7M
            if (s1 > pfs->smoothness)
2086
31.1k
                return 1;
2087
19.6M
            s2 = function_linearity(pfs, p2->c, p0->c);
2088
19.6M
            if (s2 > pfs->smoothness)
2089
1.16k
                return 1;
2090
            /* fixme: check an inner color ? */
2091
19.6M
            s01 = max(s0, s1);
2092
19.6M
            s012 = max(s01, s2);
2093
19.6M
            if (pfs->cs_always_linear)
2094
4.43M
                code = 1;
2095
15.2M
            else
2096
15.2M
                code = cs_is_linear(cs, pfs->pgs, pfs->trans_device,
2097
19.6M
                                  &p0->c->cc, &p1->c->cc, &p2->c->cc, NULL,
2098
19.6M
                                  pfs->smoothness - s012, pfs->icclink);
2099
19.6M
            if (code < 0)
2100
0
                return code;
2101
19.6M
            if (code == 0)
2102
106k
                return 1;
2103
19.6M
        }
2104
19.7M
    }
2105
19.5M
    {   gx_device *pdev = pfs->dev;
2106
19.5M
        frac31 fc[3][GX_DEVICE_COLOR_MAX_COMPONENTS];
2107
19.5M
        gs_fill_attributes fa;
2108
19.5M
        gx_device_color dc[3];
2109
2110
19.5M
        fa.clip = &pfs->rect;
2111
19.5M
        fa.ht = NULL;
2112
19.5M
        fa.swap_axes = false;
2113
19.5M
        fa.lop = 0;
2114
19.5M
        code = patch_color_to_device_color_inline(pfs, p0->c, &dc[0], fc[0]);
2115
19.5M
        if (code != 0)
2116
0
            return code;
2117
19.5M
        if (!(dc[0].type == &gx_dc_type_data_pure ||
2118
8.97M
            dc[0].type == &gx_dc_type_data_devn))
2119
0
            return 2;
2120
19.5M
        if (!wedge) {
2121
19.5M
            code = patch_color_to_device_color_inline(pfs, p1->c, &dc[1], fc[1]);
2122
19.5M
            if (code != 0)
2123
0
                return code;
2124
19.5M
        }
2125
19.5M
        code = patch_color_to_device_color_inline(pfs, p2->c, &dc[2], fc[2]);
2126
19.5M
        if (code != 0)
2127
0
            return code;
2128
19.5M
        code = dev_proc(pdev, fill_linear_color_triangle)(pdev, &fa,
2129
19.5M
                        &p0->p, &p1->p, &p2->p,
2130
19.5M
                        fc[0], (wedge ? NULL : fc[1]), fc[2]);
2131
19.5M
        if (code == 1)
2132
19.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
17.8M
{
2144
17.8M
    if ((int64_t)(q1->p.x - q0->p.x) * (q2->p.y - q0->p.y) ==
2145
17.8M
        (int64_t)(q1->p.y - q0->p.y) * (q2->p.x - q0->p.x))
2146
10.3M
        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.51M
    return fill_triangle_wedge_aux(pfs, q0, q1, q2);
2154
17.8M
}
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.35M
{
2162
2.35M
    shading_vertex_t p[3];
2163
2.35M
    patch_color_t *c;
2164
2.35M
    byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2165
2.35M
    int code;
2166
2167
2.35M
    if (color_stack_ptr == NULL)
2168
0
        return_error(gs_error_unregistered); /* Must not happen. */
2169
2.35M
    p[2].c = c;
2170
2.35M
    p[0].p = beg->p;
2171
2.35M
    p[0].c = c0;
2172
2.35M
    p[1].p = end->p;
2173
2.35M
    p[1].c = c1;
2174
2.35M
    p[2].p = mid->p;
2175
2.35M
    patch_interpolate_color(c, c0, c1, pfs, 0.5);
2176
2.35M
    code = fill_triangle_wedge(pfs, &p[0], &p[1], &p[2]);
2177
2.35M
    release_colors_inline(pfs, color_stack_ptr, 1);
2178
2.35M
    return code;
2179
2.35M
}
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.0M
{
2186
10.0M
    if (beg->next == end)
2187
2.92M
        return 0;
2188
7.12M
    else if (beg->next->next == end) {
2189
6.33M
        if (beg->next->divide_count != 1 && beg->next->divide_count != 2)
2190
0
            return_error(gs_error_unregistered); /* Must not happen. */
2191
6.33M
        if (beg->next->divide_count != 1)
2192
4.75M
            return 0;
2193
1.57M
        return fill_triangle_wedge_from_list(pfs, beg, end, beg->next, c0, c1);
2194
6.33M
    } else {
2195
790k
        gs_fixed_point p;
2196
790k
        wedge_vertex_list_elem_t *e;
2197
790k
        patch_color_t *c;
2198
790k
        int code;
2199
790k
        byte *color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2200
2201
790k
        if (color_stack_ptr == NULL)
2202
0
            return_error(gs_error_unregistered); /* Must not happen. */
2203
790k
        p.x = (beg->p.x + end->p.x) / 2;
2204
790k
        p.y = (beg->p.y + end->p.y) / 2;
2205
790k
        e = wedge_vertex_list_find(beg, end, level + 1);
2206
790k
        if (e == NULL)
2207
0
            return_error(gs_error_unregistered); /* Must not happen. */
2208
790k
        if (e->p.x != p.x || e->p.y != p.y)
2209
0
            return_error(gs_error_unregistered); /* Must not happen. */
2210
790k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2211
790k
        code = fill_wedge_from_list_rec(pfs, beg, e, level + 1, c0, c);
2212
790k
        if (code >= 0)
2213
790k
            code = fill_wedge_from_list_rec(pfs, e, end, level + 1, c, c1);
2214
790k
        if (code >= 0) {
2215
790k
            if (e->divide_count != 1 && e->divide_count != 2)
2216
0
                return_error(gs_error_unregistered); /* Must not happen. */
2217
790k
            if (e->divide_count == 1)
2218
781k
                code = fill_triangle_wedge_from_list(pfs, beg, end, e, c0, c1);
2219
790k
        }
2220
790k
        release_colors_inline(pfs, color_stack_ptr, 1);
2221
790k
        return code;
2222
790k
    }
2223
10.0M
}
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.46M
{
2229
8.46M
    return fill_wedge_from_list_rec(pfs, l->beg, l->end,
2230
8.46M
                    max(l->beg->level, l->end->level), c0, c1);
2231
8.46M
}
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
99.9M
{
2237
99.9M
    if (l->beg != NULL) {
2238
3.54M
        int code = fill_wedge_from_list(pfs, l, c0, c1);
2239
2240
3.54M
        if (code < 0)
2241
0
            return code;
2242
3.54M
        return release_wedge_vertex_list(pfs, l, 1);
2243
3.54M
    }
2244
96.4M
    return 0;
2245
99.9M
}
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
1.99M
            goto out;
2271
1.96M
        code = wedge_by_triangles(pfs, ka / 2, q[0], c0, p[2].c);
2272
1.96M
    }
2273
1.96M
    if (code >= 0)
2274
1.96M
        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.96M
}
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
18.6M
{
2284
18.6M
    gs_fixed_point q0, q1;
2285
18.6M
    const patch_color_t *cc0, *cc1;
2286
18.6M
    fixed dx = p1->x - p0->x;
2287
18.6M
    fixed dy = p1->y - p0->y;
2288
18.6M
    bool swap_axes = (any_abs(dx) > any_abs(dy));
2289
18.6M
    gs_fixed_edge le, re;
2290
18.6M
    const fixed adjust = INTERPATCH_PADDING;
2291
2292
18.6M
    if (swap_axes) {
2293
6.85M
        if (p0->x < p1->x) {
2294
2.93M
            q0.x = p0->y;
2295
2.93M
            q0.y = p0->x;
2296
2.93M
            q1.x = p1->y;
2297
2.93M
            q1.y = p1->x;
2298
2.93M
            cc0 = c0;
2299
2.93M
            cc1 = c1;
2300
3.91M
        } else {
2301
3.91M
            q0.x = p1->y;
2302
3.91M
            q0.y = p1->x;
2303
3.91M
            q1.x = p0->y;
2304
3.91M
            q1.y = p0->x;
2305
3.91M
            cc0 = c1;
2306
3.91M
            cc1 = c0;
2307
3.91M
        }
2308
11.8M
    } else if (p0->y < p1->y) {
2309
730k
        q0 = *p0;
2310
730k
        q1 = *p1;
2311
730k
        cc0 = c0;
2312
730k
        cc1 = c1;
2313
11.0M
    } else {
2314
11.0M
        q0 = *p1;
2315
11.0M
        q1 = *p0;
2316
11.0M
        cc0 = c1;
2317
11.0M
        cc1 = c0;
2318
11.0M
    }
2319
18.6M
    le.start.x = q0.x - adjust;
2320
18.6M
    re.start.x = q0.x + adjust;
2321
18.6M
    le.start.y = re.start.y = q0.y - adjust;
2322
18.6M
    le.end.x = q1.x - adjust;
2323
18.6M
    re.end.x = q1.x + adjust;
2324
18.6M
    le.end.y = re.end.y = q1.y + adjust;
2325
18.6M
    adjust_swapped_boundary(&re.start.x, swap_axes);
2326
18.6M
    adjust_swapped_boundary(&re.end.x, swap_axes);
2327
18.6M
    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
18.6M
}
2335
2336
static inline void
2337
bbox_of_points(gs_fixed_rect *r,
2338
        const gs_fixed_point *p0, const gs_fixed_point *p1,
2339
        const gs_fixed_point *p2, const gs_fixed_point *p3)
2340
17.7M
{
2341
17.7M
    r->p.x = r->q.x = p0->x;
2342
17.7M
    r->p.y = r->q.y = p0->y;
2343
2344
17.7M
    if (r->p.x > p1->x)
2345
7.17M
        r->p.x = p1->x;
2346
17.7M
    if (r->q.x < p1->x)
2347
5.88M
        r->q.x = p1->x;
2348
17.7M
    if (r->p.y > p1->y)
2349
6.64M
        r->p.y = p1->y;
2350
17.7M
    if (r->q.y < p1->y)
2351
6.88M
        r->q.y = p1->y;
2352
2353
17.7M
    if (r->p.x > p2->x)
2354
3.58M
        r->p.x = p2->x;
2355
17.7M
    if (r->q.x < p2->x)
2356
3.64M
        r->q.x = p2->x;
2357
17.7M
    if (r->p.y > p2->y)
2358
3.42M
        r->p.y = p2->y;
2359
17.7M
    if (r->q.y < p2->y)
2360
3.82M
        r->q.y = p2->y;
2361
2362
17.7M
    if (p3 == NULL)
2363
13.7M
        return;
2364
2365
4.02M
    if (r->p.x > p3->x)
2366
971k
        r->p.x = p3->x;
2367
4.02M
    if (r->q.x < p3->x)
2368
561k
        r->q.x = p3->x;
2369
4.02M
    if (r->p.y > p3->y)
2370
588k
        r->p.y = p3->y;
2371
4.02M
    if (r->q.y < p3->y)
2372
1.08M
        r->q.y = p3->y;
2373
4.02M
}
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.11M
{
2380
1.11M
    int code;
2381
2382
1.11M
    if (k > 1) {
2383
620k
        gs_fixed_point q[2][4];
2384
620k
        patch_color_t *c;
2385
620k
        bool save_inside = pfs->inside;
2386
620k
        byte *color_stack_ptr;
2387
2388
620k
        if (!pfs->inside) {
2389
599k
            gs_fixed_rect r, r1;
2390
2391
599k
            bbox_of_points(&r, &pole[0], &pole[1], &pole[2], &pole[3]);
2392
599k
            r.p.x -= INTERPATCH_PADDING;
2393
599k
            r.p.y -= INTERPATCH_PADDING;
2394
599k
            r.q.x += INTERPATCH_PADDING;
2395
599k
            r.q.y += INTERPATCH_PADDING;
2396
599k
            r1 = r;
2397
599k
            rect_intersect(r, pfs->rect);
2398
599k
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2399
552k
                return 0;
2400
47.8k
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
2401
22.8k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
2402
12.1k
                pfs->inside = true;
2403
47.8k
        }
2404
68.2k
        color_stack_ptr = reserve_colors_inline(pfs, &c, 1);
2405
68.2k
        if (color_stack_ptr == NULL)
2406
0
            return_error(gs_error_unregistered); /* Must not happen. */
2407
68.2k
        patch_interpolate_color(c, c0, c1, pfs, 0.5);
2408
68.2k
        split_curve(pole, q[0], q[1]);
2409
68.2k
        code = fill_wedges_aux(pfs, k / 2, ka, q[0], c0, c, wedge_type);
2410
68.2k
        if (code >= 0)
2411
68.2k
            code = fill_wedges_aux(pfs, k / 2, ka, q[1], c, c1, wedge_type);
2412
68.2k
        release_colors_inline(pfs, color_stack_ptr, 1);
2413
68.2k
        pfs->inside = save_inside;
2414
68.2k
        return code;
2415
492k
    } else {
2416
492k
        if ((INTERPATCH_PADDING != 0) && (wedge_type & interpatch_padding)) {
2417
477k
            code = mesh_padding(pfs, &pole[0], &pole[3], c0, c1);
2418
477k
            if (code < 0)
2419
0
                return code;
2420
477k
        }
2421
492k
        if (ka >= 2 && (wedge_type & inpatch_wedge))
2422
36.4k
            return wedge_by_triangles(pfs, ka, pole, c0, c1);
2423
455k
        return 0;
2424
492k
    }
2425
1.11M
}
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
10.9M
{
2433
    /* Generate wedges between 2 variants of a curve flattening. */
2434
    /* k0, k1 is a power of 2. */
2435
10.9M
    gs_fixed_point p[4];
2436
2437
10.9M
    if (!(wedge_type & interpatch_padding) && k0 == k1)
2438
9.99M
        return 0; /* Wedges are zero area. */
2439
976k
    if (k0 > k1) { /* Swap if required, so that k0 <= k1 */
2440
0
        k0 ^= k1; k1 ^= k0; k0 ^= k1;
2441
0
    }
2442
976k
    p[0] = pole[0];
2443
976k
    p[1] = pole[pole_step];
2444
976k
    p[2] = pole[pole_step * 2];
2445
976k
    p[3] = pole[pole_step * 3];
2446
976k
    return fill_wedges_aux(pfs, k0, k1 / k0, p, c0, c1, wedge_type);
2447
10.9M
}
2448
2449
static inline void
2450
make_vertices(gs_fixed_point q[4], const quadrangle_patch *p)
2451
191k
{
2452
191k
    q[0] = p->p[0][0]->p;
2453
191k
    q[1] = p->p[0][1]->p;
2454
191k
    q[2] = p->p[1][1]->p;
2455
191k
    q[3] = p->p[1][0]->p;
2456
191k
}
2457
2458
static inline void
2459
wrap_vertices_by_y(gs_fixed_point q[4], const gs_fixed_point s[4])
2460
191k
{
2461
191k
    fixed y = s[0].y;
2462
191k
    int i = 0;
2463
2464
191k
    if (y > s[1].y)
2465
58.1k
        i = 1, y = s[1].y;
2466
191k
    if (y > s[2].y)
2467
19.4k
        i = 2, y = s[2].y;
2468
191k
    if (y > s[3].y)
2469
16.6k
        i = 3, y = s[3].y;
2470
191k
    q[0] = s[(i + 0) % 4];
2471
191k
    q[1] = s[(i + 1) % 4];
2472
191k
    q[2] = s[(i + 2) % 4];
2473
191k
    q[3] = s[(i + 3) % 4];
2474
191k
}
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
28.1M
{
2479
28.1M
    gs_fixed_edge ue;
2480
28.1M
    int code;
2481
28.1M
    gx_device_color dc;
2482
2483
#   if NOFILL_TEST
2484
        if (dbg_nofill)
2485
            return 0;
2486
#   endif
2487
28.1M
    code = patch_color_to_device_color_inline(pfs, c, &dc, NULL);
2488
28.1M
    if (code < 0)
2489
0
        return code;
2490
28.1M
    if (le->end.y < re->end.y) {
2491
11.8M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2492
11.8M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2493
11.8M
        if (code >= 0) {
2494
11.8M
            ue.start = le->end;
2495
11.8M
            ue.end = re->end;
2496
11.8M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2497
11.8M
                &ue, re, le->end.y, re->end.y, false, &dc, pfs->pgs->log_op);
2498
11.8M
        }
2499
16.2M
    } else if (le->end.y > re->end.y) {
2500
11.5M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2501
11.5M
            le, re, le->start.y, re->end.y, false, &dc, pfs->pgs->log_op);
2502
11.5M
        if (code >= 0) {
2503
11.5M
            ue.start = re->end;
2504
11.5M
            ue.end = le->end;
2505
11.5M
            code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2506
11.5M
                le, &ue, re->end.y, le->end.y, false, &dc, pfs->pgs->log_op);
2507
11.5M
        }
2508
11.5M
    } else
2509
4.78M
        code = dev_proc(pfs->dev, fill_trapezoid)(pfs->dev,
2510
4.78M
            le, re, le->start.y, le->end.y, false, &dc, pfs->pgs->log_op);
2511
28.1M
    return code;
2512
28.1M
}
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.3M
{
2518
23.3M
    patch_color_t *c[2];
2519
23.3M
    gs_fixed_edge le, re;
2520
23.3M
    fixed dx0, dy0, dx1, dy1;
2521
23.3M
    const shading_vertex_t *pp;
2522
23.3M
    int i, code = 0;
2523
23.3M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
2524
2525
23.3M
    if (color_stack_ptr == NULL)
2526
0
        return_error(gs_error_unregistered); /* Must not happen. */
2527
23.3M
    patch_interpolate_color(c[0], p0->c, p1->c, pfs, 0.5);
2528
23.3M
    patch_interpolate_color(c[1], p2->c, c[0], pfs, 0.5);
2529
93.2M
    for (i = 0; i < 3; i++) {
2530
        /* fixme : does optimizer compiler expand this cycle ? */
2531
69.9M
        if (p0->p.y <= p1->p.y && p0->p.y <= p2->p.y) {
2532
28.1M
            le.start = re.start = p0->p;
2533
28.1M
            le.end = p1->p;
2534
28.1M
            re.end = p2->p;
2535
2536
28.1M
            dx0 = le.end.x - le.start.x;
2537
28.1M
            dy0 = le.end.y - le.start.y;
2538
28.1M
            dx1 = re.end.x - re.start.x;
2539
28.1M
            dy1 = re.end.y - re.start.y;
2540
28.1M
            if ((int64_t)dx0 * dy1 < (int64_t)dy0 * dx1)
2541
12.3M
                code = ordered_triangle(pfs, &le, &re, c[1]);
2542
15.7M
            else
2543
15.7M
                code = ordered_triangle(pfs, &re, &le, c[1]);
2544
28.1M
            if (code < 0)
2545
0
                break;
2546
28.1M
        }
2547
69.9M
        pp = p0; p0 = p1; p1 = p2; p2 = pp;
2548
69.9M
    }
2549
23.3M
    release_colors_inline(pfs, color_stack_ptr, 2);
2550
23.3M
    return code;
2551
23.3M
}
2552
2553
static inline int
2554
constant_color_quadrangle_aux(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting,
2555
        patch_color_t *c[3])
2556
191k
{
2557
    /* Assuming the XY span is restricted with curve_samples.
2558
       It is important for intersection_of_small_bars to compute faster. */
2559
191k
    gs_fixed_point q[4];
2560
191k
    fixed ry, ey;
2561
191k
    int code;
2562
191k
    bool swap_axes = false;
2563
191k
    gx_device_color dc;
2564
191k
    bool orient;
2565
2566
191k
    dc.tag = device_current_tag(pfs->dev);
2567
2568
191k
    patch_interpolate_color(c[1], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2569
191k
    patch_interpolate_color(c[2], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2570
191k
    patch_interpolate_color(c[0], c[1], c[2], pfs, 0.5);
2571
191k
    code = patch_color_to_device_color_inline(pfs, c[0], &dc, NULL);
2572
191k
    if (code < 0)
2573
0
        return code;
2574
191k
    {   gs_fixed_point qq[4];
2575
2576
191k
        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
191k
        wrap_vertices_by_y(q, qq);
2589
191k
    }
2590
191k
    {   fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y;
2591
191k
        fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y;
2592
191k
        int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
2593
2594
191k
        if (g13 == h13) {
2595
615
            fixed dx2 = q[2].x - q[0].x, dy2 = q[2].y - q[0].y;
2596
615
            int64_t g23 = (int64_t)dx2 * dy3, h23 = (int64_t)dy2 * dx3;
2597
2598
615
            if (dx1 == 0 && dy1 == 0 && g23 == h23)
2599
0
                return 0;
2600
615
            if (g23 != h23) {
2601
615
                orient = (g23 > h23);
2602
615
                if (q[2].y <= q[3].y) {
2603
480
                    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
480
                    return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2606
480
                } else {
2607
135
                    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
135
                    return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2610
135
                }
2611
615
            } 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
615
        }
2628
190k
        orient = ((int64_t)dx1 * dy3 > (int64_t)dy1 * dx3);
2629
190k
    }
2630
190k
    if (q[1].y <= q[2].y && q[2].y <= q[3].y) {
2631
76.1k
        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
76.1k
        } else {
2640
76.1k
            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
76.1k
            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
76.1k
            return gx_shade_trapezoid(pfs, q, 2, 3, 0, 3, q[2].y, q[3].y, swap_axes, &dc, orient);
2645
76.1k
        }
2646
114k
    } else if (q[1].y <= q[3].y && q[3].y <= q[2].y) {
2647
45.9k
        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
45.9k
        } else {
2656
45.9k
            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
45.9k
            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
45.9k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[3].y, q[2].y, swap_axes, &dc, orient);
2661
45.9k
        }
2662
68.2k
    } 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
68.2k
    } else if (q[2].y <= q[3].y && q[3].y <= q[1].y) {
2687
32
        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
32
        } 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
32
        } else {
2706
32
            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
32
            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
32
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2711
32
        }
2712
68.2k
    } else if (q[3].y <= q[1].y && q[1].y <= q[2].y) {
2713
66.7k
        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
66.7k
        } else {
2722
66.7k
            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
66.7k
            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
66.7k
            return gx_shade_trapezoid(pfs, q, 1, 2, 3, 2, q[1].y, q[2].y, swap_axes, &dc, orient);
2727
66.7k
        }
2728
66.7k
    } else if (q[3].y <= q[2].y && q[2].y <= q[1].y) {
2729
1.49k
        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.49k
        } else {
2738
1.49k
            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.49k
            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.49k
            return gx_shade_trapezoid(pfs, q, 0, 1, 2, 1, q[2].y, q[1].y, swap_axes, &dc, orient);
2743
1.49k
        }
2744
1.49k
    } else {
2745
        /* Impossible. */
2746
0
        return_error(gs_error_unregistered);
2747
0
    }
2748
190k
}
2749
2750
int
2751
constant_color_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool self_intersecting)
2752
191k
{
2753
191k
    patch_color_t *c[3];
2754
191k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2755
191k
    int code;
2756
2757
191k
    if (color_stack_ptr == NULL)
2758
0
        return_error(gs_error_unregistered); /* Must not happen. */
2759
191k
    code = constant_color_quadrangle_aux(pfs, p, self_intersecting, c);
2760
191k
    release_colors_inline(pfs, color_stack_ptr, 3);
2761
191k
    return code;
2762
191k
}
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
196k
{
2768
196k
    q[0].c = c[0];
2769
196k
    q[1].c = c[1];
2770
196k
    q[0].p.x = (p->p[0][0]->p.x + p->p[1][0]->p.x) / 2;
2771
196k
    q[1].p.x = (p->p[0][1]->p.x + p->p[1][1]->p.x) / 2;
2772
196k
    q[0].p.y = (p->p[0][0]->p.y + p->p[1][0]->p.y) / 2;
2773
196k
    q[1].p.y = (p->p[0][1]->p.y + p->p[1][1]->p.y) / 2;
2774
196k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[1][0]->c, pfs, 0.5);
2775
196k
    patch_interpolate_color(c[1], p->p[0][1]->c, p->p[1][1]->c, pfs, 0.5);
2776
196k
    s0->p[0][0] = p->p[0][0];
2777
196k
    s0->p[0][1] = p->p[0][1];
2778
196k
    s0->p[1][0] = s1->p[0][0] = &q[0];
2779
196k
    s0->p[1][1] = s1->p[0][1] = &q[1];
2780
196k
    s1->p[1][0] = p->p[1][0];
2781
196k
    s1->p[1][1] = p->p[1][1];
2782
196k
}
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
345k
{
2788
345k
    q[0].c = c[0];
2789
345k
    q[1].c = c[1];
2790
345k
    q[0].p.x = (p->p[0][0]->p.x + p->p[0][1]->p.x) / 2;
2791
345k
    q[1].p.x = (p->p[1][0]->p.x + p->p[1][1]->p.x) / 2;
2792
345k
    q[0].p.y = (p->p[0][0]->p.y + p->p[0][1]->p.y) / 2;
2793
345k
    q[1].p.y = (p->p[1][0]->p.y + p->p[1][1]->p.y) / 2;
2794
345k
    patch_interpolate_color(c[0], p->p[0][0]->c, p->p[0][1]->c, pfs, 0.5);
2795
345k
    patch_interpolate_color(c[1], p->p[1][0]->c, p->p[1][1]->c, pfs, 0.5);
2796
345k
    s0->p[0][0] = p->p[0][0];
2797
345k
    s0->p[1][0] = p->p[1][0];
2798
345k
    s0->p[0][1] = s1->p[0][0] = &q[0];
2799
345k
    s0->p[1][1] = s1->p[1][0] = &q[1];
2800
345k
    s1->p[0][1] = p->p[0][1];
2801
345k
    s1->p[1][1] = p->p[1][1];
2802
345k
}
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.53M
{   /* returns : 1 = monotonic, 0 = don't know, <0 = error. */
2808
2.53M
    int code, r;
2809
2810
2.53M
    code = isnt_color_monotonic(pfs, p->p[0][0]->c, p->p[1][1]->c);
2811
2.53M
    if (code <= 0)
2812
2.50M
        return code;
2813
27.8k
    r = code << pfs->function_arg_shift;
2814
27.8k
    if (r & 1)
2815
0
        *not_monotonic_by_u = true;
2816
27.8k
    if (r & 2)
2817
27.8k
        *not_monotonic_by_v = true;
2818
27.8k
    return !code;
2819
2.53M
}
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
30.0M
{
2826
    /* Assuming p.c == c for providing a non-const access. */
2827
30.0M
    p->p.x = (fixed)((int64_t)p0->p.x * (radix - 1) + p1->p.x) / radix;
2828
30.0M
    p->p.y = (fixed)((int64_t)p0->p.y * (radix - 1) + p1->p.y) / radix;
2829
30.0M
    patch_interpolate_color(c, p0->c, p1->c, pfs, (double)(radix - 1) / radix);
2830
30.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
52.3M
{
2838
52.3M
    shading_vertex_t p01, p12, p20;
2839
52.3M
    patch_color_t *c[3];
2840
52.3M
    wedge_vertex_list_t L01, L12, L20, L[3];
2841
52.3M
    bool inside_save = pfs->inside;
2842
52.3M
    gs_fixed_rect r = {{0,0},{0,0}}, r1 =  {{0,0},{0,0}};
2843
52.3M
    int code = 0;
2844
52.3M
    byte *color_stack_ptr;
2845
52.3M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
2846
2847
52.3M
    if (!inside) {
2848
13.7M
        bbox_of_points(&r, &p0->p, &p1->p, &p2->p, NULL);
2849
13.7M
        r1 = r;
2850
13.7M
        rect_intersect(r, pfs->rect);
2851
13.7M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
2852
5.82M
            return 0;
2853
13.7M
    }
2854
46.4M
    color_stack_ptr = reserve_colors_inline(pfs, c, 3);
2855
46.4M
    if(color_stack_ptr == NULL)
2856
0
        return_error(gs_error_unregistered);
2857
46.4M
    p01.c = c[0];
2858
46.4M
    p12.c = c[1];
2859
46.4M
    p20.c = c[2];
2860
46.4M
    code = try_device_linear_color(pfs, false, p0, p1, p2);
2861
46.4M
    switch(code) {
2862
19.5M
        case 0: /* The area is filled. */
2863
19.5M
            goto out;
2864
26.7M
        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.7M
            if (sd < pfs->decomposition_limit * 4) {
2869
3.07M
                code = constant_color_triangle(pfs, p2, p0, p1);
2870
3.07M
                goto out;
2871
3.07M
            }
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.9M
            } else if (cd <= pfs->smoothness / COLOR_CONTIGUITY) {
2884
9.40M
                code = constant_color_triangle(pfs, p2, p0, p1);
2885
9.40M
                goto out;
2886
9.40M
            }
2887
3.49M
            break;
2888
3.49M
        case 1: /* decompose to linear color areas */
2889
196k
            if (sd < pfs->decomposition_limit) {
2890
91.4k
                code = constant_color_triangle(pfs, p2, p0, p1);
2891
91.4k
                goto out;
2892
91.4k
            }
2893
104k
            break;
2894
104k
        default: /* Error. */
2895
0
            goto out;
2896
46.4M
    }
2897
3.60M
    if (!inside) {
2898
443k
        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.8k
            pfs->inside = true;
2901
443k
    }
2902
3.60M
    divide_bar(pfs, p0, p1, 2, &p01, c[0]);
2903
3.60M
    divide_bar(pfs, p1, p2, 2, &p12, c[1]);
2904
3.60M
    divide_bar(pfs, p2, p0, 2, &p20, c[2]);
2905
3.60M
    if (LAZY_WEDGES) {
2906
3.60M
        init_wedge_vertex_list(L, count_of(L));
2907
3.60M
        code = make_wedge_median(pfs, &L01, l01, true,  &p0->p, &p1->p, &p01.p);
2908
3.60M
        if (code >= 0)
2909
3.60M
            code = make_wedge_median(pfs, &L12, l12, true,  &p1->p, &p2->p, &p12.p);
2910
3.60M
        if (code >= 0)
2911
3.60M
            code = make_wedge_median(pfs, &L20, l20, false, &p2->p, &p0->p, &p20.p);
2912
3.60M
    } 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.60M
    if (code >= 0)
2920
3.60M
        code = triangle_by_4(pfs, p0, &p01, &p20, &L01, &L[0], &L20, cd / 2, sd / 2);
2921
3.60M
    if (code >= 0) {
2922
3.60M
        if (LAZY_WEDGES) {
2923
3.60M
            move_wedge(&L01, l01, true);
2924
3.60M
            move_wedge(&L20, l20, false);
2925
3.60M
        }
2926
3.60M
        code = triangle_by_4(pfs, p1, &p12, &p01, &L12, &L[1], &L01, cd / 2, sd / 2);
2927
3.60M
    }
2928
3.60M
    if (code >= 0) {
2929
3.60M
        if (LAZY_WEDGES)
2930
3.60M
            move_wedge(&L12, l12, true);
2931
3.60M
        code = triangle_by_4(pfs, p2, &p20, &p12, &L20, &L[2], &L12, cd / 2, sd / 2);
2932
3.60M
    }
2933
3.60M
    if (code >= 0) {
2934
3.60M
        L[0].last_side = L[1].last_side = L[2].last_side = true;
2935
3.60M
        code = triangle_by_4(pfs, &p01, &p12, &p20, &L[1], &L[2], &L[0], cd / 2, sd / 2);
2936
3.60M
    }
2937
3.60M
    if (LAZY_WEDGES) {
2938
3.60M
        if (code >= 0)
2939
3.60M
            code = close_wedge_median(pfs, l01, p0->c, p1->c);
2940
3.60M
        if (code >= 0)
2941
3.60M
            code = close_wedge_median(pfs, l12, p1->c, p2->c);
2942
3.60M
        if (code >= 0)
2943
3.60M
            code = close_wedge_median(pfs, l20, p2->c, p0->c);
2944
3.60M
        if (code >= 0)
2945
3.60M
            code = terminate_wedge_vertex_list(pfs, &L[0], p01.c, p20.c);
2946
3.60M
        if (code >= 0)
2947
3.60M
            code = terminate_wedge_vertex_list(pfs, &L[1], p12.c, p01.c);
2948
3.60M
        if (code >= 0)
2949
3.60M
            code = terminate_wedge_vertex_list(pfs, &L[2], p20.c, p12.c);
2950
3.60M
    }
2951
3.60M
    pfs->inside = inside_save;
2952
46.4M
out:
2953
46.4M
    release_colors_inline(pfs, color_stack_ptr, 3);
2954
46.4M
    return code;
2955
3.60M
}
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
37.9M
{
2962
37.9M
    fixed sd01 = max(any_abs(p1->p.x - p0->p.x), any_abs(p1->p.y - p0->p.y));
2963
37.9M
    fixed sd12 = max(any_abs(p2->p.x - p1->p.x), any_abs(p2->p.y - p1->p.y));
2964
37.9M
    fixed sd20 = max(any_abs(p0->p.x - p2->p.x), any_abs(p0->p.y - p2->p.y));
2965
37.9M
    fixed sd1 = max(sd01, sd12);
2966
37.9M
    fixed sd = max(sd1, sd20);
2967
37.9M
    double cd = 0;
2968
2969
#   if SKIP_TEST
2970
        dbg_triangle_cnt++;
2971
#   endif
2972
37.9M
    if (pfs->Function == NULL) {
2973
23.0M
        double d01 = color_span(pfs, p1->c, p0->c);
2974
23.0M
        double d12 = color_span(pfs, p2->c, p1->c);
2975
23.0M
        double d20 = color_span(pfs, p0->c, p2->c);
2976
23.0M
        double cd1 = max(d01, d12);
2977
2978
23.0M
        cd = max(cd1, d20);
2979
23.0M
    }
2980
37.9M
    return triangle_by_4(pfs, p0, p1, p2, l01, l12, l20, cd, sd);
2981
37.9M
}
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.80M
{
2987
4.80M
    int code;
2988
4.80M
    wedge_vertex_list_t l[3];
2989
2990
4.80M
    init_wedge_vertex_list(l, count_of(l));
2991
4.80M
    code = fill_triangle(pfs, p0, p1, p2, &l[0], &l[1], &l[2]);
2992
4.80M
    if (code < 0)
2993
0
        return code;
2994
4.80M
    code = terminate_wedge_vertex_list(pfs, &l[0], p0->c, p1->c);
2995
4.80M
    if (code < 0)
2996
0
        return code;
2997
4.80M
    code = terminate_wedge_vertex_list(pfs, &l[1], p1->c, p2->c);
2998
4.80M
    if (code < 0)
2999
0
        return code;
3000
4.80M
    return terminate_wedge_vertex_list(pfs, &l[2], p2->c, p0->c);
3001
4.80M
}
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.49M
{
3099
5.49M
    pfs->unlinear = !is_linear_color_applicable(pfs);
3100
5.49M
    if (manhattan_dist(&p0->p, &p1->p) < pfs->max_small_coord &&
3101
5.07M
        manhattan_dist(&p1->p, &p2->p) < pfs->max_small_coord &&
3102
4.87M
        manhattan_dist(&p2->p, &p0->p) < pfs->max_small_coord)
3103
4.80M
        return small_mesh_triangle(pfs, p0, p1, p2);
3104
690k
    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
690k
        shading_vertex_t p01, p12, p20;
3116
690k
        patch_color_t *c[3];
3117
690k
        int code;
3118
690k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3119
3120
690k
        if (color_stack_ptr == NULL)
3121
0
            return_error(gs_error_unregistered); /* Must not happen. */
3122
690k
        p01.c = c[0];
3123
690k
        p12.c = c[1];
3124
690k
        p20.c = c[2];
3125
690k
        divide_bar(pfs, p0, p1, 2, &p01, c[0]);
3126
690k
        divide_bar(pfs, p1, p2, 2, &p12, c[1]);
3127
690k
        divide_bar(pfs, p2, p0, 2, &p20, c[2]);
3128
690k
        code = fill_triangle_wedge(pfs, p0, p1, &p01);
3129
690k
        if (code >= 0)
3130
690k
            code = fill_triangle_wedge(pfs, p1, p2, &p12);
3131
690k
        if (code >= 0)
3132
690k
            code = fill_triangle_wedge(pfs, p2, p0, &p20);
3133
690k
        if (code >= 0)
3134
690k
            code = mesh_triangle_rec(pfs, p0, &p01, &p20);
3135
690k
        if (code >= 0)
3136
690k
            code = mesh_triangle_rec(pfs, p1, &p12, &p01);
3137
690k
        if (code >= 0)
3138
690k
            code = mesh_triangle_rec(pfs, p2, &p20, &p12);
3139
690k
        if (code >= 0)
3140
690k
            code = mesh_triangle_rec(pfs, &p01, &p12, &p20);
3141
690k
        release_colors_inline(pfs, color_stack_ptr, 3);
3142
690k
        return code;
3143
690k
    }
3144
5.49M
}
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.73M
{
3150
2.73M
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
3151
2.73M
            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.37M
        gx_device *pdev = pfs->dev;
3156
1.37M
        gx_path path;
3157
1.37M
        int code;
3158
1.37M
        fixed d01x = p1->p.x - p0->p.x, d01y = p1->p.y - p0->p.y;
3159
1.37M
        fixed d12x = p2->p.x - p1->p.x, d12y = p2->p.y - p1->p.y;
3160
1.37M
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
3161
3162
1.37M
        gx_path_init_local(&path, pdev->memory);
3163
1.37M
        code = gx_path_add_point(&path, p0->p.x, p0->p.y);
3164
1.37M
        if (code >= 0 && s1 >= 0)
3165
1.37M
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3166
1.37M
        if (code >= 0)
3167
1.37M
            code = gx_path_add_line(&path, p2->p.x, p2->p.y);
3168
1.37M
        if (code >= 0 && s1 < 0)
3169
6.36k
            code = gx_path_add_line(&path, p1->p.x, p1->p.y);
3170
1.37M
        if (code >= 0)
3171
1.37M
            code = gx_path_close_subpath(&path);
3172
1.37M
        if (code >= 0)
3173
1.37M
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
3174
1.37M
        gx_path_free(&path, "mesh_triangle");
3175
1.37M
        if (code < 0)
3176
0
            return code;
3177
1.37M
    }
3178
2.73M
    return mesh_triangle_rec(pfs, p0, p1, p2);
3179
2.73M
}
3180
3181
static inline int
3182
triangles4(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3183
5.74M
{
3184
5.74M
    shading_vertex_t p0001, p1011, q;
3185
5.74M
    patch_color_t *c[3];
3186
5.74M
    wedge_vertex_list_t l[4];
3187
5.74M
    int code;
3188
5.74M
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 3);
3189
3190
5.74M
    if(color_stack_ptr == NULL)
3191
0
        return_error(gs_error_unregistered); /* Must not happen. */
3192
5.74M
    p0001.c = c[0];
3193
5.74M
    p1011.c = c[1];
3194
5.74M
    q.c = c[2];
3195
5.74M
    init_wedge_vertex_list(l, count_of(l));
3196
5.74M
    divide_bar(pfs, p->p[0][0], p->p[0][1], 2, &p0001, c[0]);
3197
5.74M
    divide_bar(pfs, p->p[1][0], p->p[1][1], 2, &p1011, c[1]);
3198
5.74M
    divide_bar(pfs, &p0001, &p1011, 2, &q, c[2]);
3199
5.74M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], &q, p->l0001, &l[0], &l[3]);
3200
5.74M
    if (code >= 0) {
3201
5.74M
        l[0].last_side = true;
3202
5.74M
        l[3].last_side = true;
3203
5.74M
        code = fill_triangle(pfs, p->p[0][1], p->p[1][1], &q, p->l0111, &l[1], &l[0]);
3204
5.74M
    }
3205
5.74M
    if (code >= 0) {
3206
5.74M
        l[1].last_side = true;
3207
5.74M
        code = fill_triangle(pfs, p->p[1][1], p->p[1][0], &q, p->l1110, &l[2], &l[1]);
3208
5.74M
    }
3209
5.74M
    if (code >= 0) {
3210
5.74M
        l[2].last_side = true;
3211
5.74M
        code = fill_triangle(pfs, p->p[1][0], p->p[0][0], &q, p->l1000, &l[3], &l[2]);
3212
5.74M
    }
3213
5.74M
    if (code >= 0)
3214
5.74M
        code = terminate_wedge_vertex_list(pfs, &l[0], p->p[0][1]->c, q.c);
3215
5.74M
    if (code >= 0)
3216
5.74M
        code = terminate_wedge_vertex_list(pfs, &l[1], p->p[1][1]->c, q.c);
3217
5.74M
    if (code >= 0)
3218
5.74M
        code = terminate_wedge_vertex_list(pfs, &l[2], p->p[1][0]->c, q.c);
3219
5.74M
    if (code >= 0)
3220
5.74M
        code = terminate_wedge_vertex_list(pfs, &l[3], q.c, p->p[0][0]->c);
3221
5.74M
    release_colors_inline(pfs, color_stack_ptr, 3);
3222
5.74M
    return code;
3223
5.74M
}
3224
3225
static inline int
3226
triangles2(patch_fill_state_t *pfs, const quadrangle_patch *p, bool dummy_argument)
3227
5.07M
{
3228
5.07M
    wedge_vertex_list_t l;
3229
5.07M
    int code;
3230
3231
5.07M
    init_wedge_vertex_list(&l, 1);
3232
5.07M
    code = fill_triangle(pfs, p->p[0][0], p->p[0][1], p->p[1][1], p->l0001, p->l0111, &l);
3233
5.07M
    if (code < 0)
3234
0
        return code;
3235
5.07M
    l.last_side = true;
3236
5.07M
    code = fill_triangle(pfs, p->p[1][1], p->p[1][0], p->p[0][0], p->l1110, p->l1000, &l);
3237
5.07M
    if (code < 0)
3238
0
        return code;
3239
5.07M
    code = terminate_wedge_vertex_list(pfs, &l, p->p[1][1]->c, p->p[0][0]->c);
3240
5.07M
    if (code < 0)
3241
0
        return code;
3242
5.07M
    return 0;
3243
5.07M
}
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
11.5M
{
3249
11.5M
    qq[0][0].p = p->pole[0][0];
3250
11.5M
    qq[0][1].p = p->pole[0][3];
3251
11.5M
    qq[1][0].p = p->pole[3][0];
3252
11.5M
    qq[1][1].p = p->pole[3][3];
3253
11.5M
    qq[0][0].c = p->c[0][0];
3254
11.5M
    qq[0][1].c = p->c[0][1];
3255
11.5M
    qq[1][0].c = p->c[1][0];
3256
11.5M
    qq[1][1].c = p->c[1][1];
3257
11.5M
    q->p[0][0] = &qq[0][0];
3258
11.5M
    q->p[0][1] = &qq[0][1];
3259
11.5M
    q->p[1][0] = &qq[1][0];
3260
11.5M
    q->p[1][1] = &qq[1][1];
3261
11.5M
    q->l0001 = &l[0];
3262
11.5M
    q->l0111 = &l[1];
3263
11.5M
    q->l1110 = &l[2];
3264
11.5M
    q->l1000 = &l[3];
3265
11.5M
}
3266
3267
static inline int
3268
is_quadrangle_color_linear_by_u(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3269
7.36M
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3270
7.36M
    int code;
3271
3272
7.36M
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[0][1]->c);
3273
7.36M
    if (code <= 0)
3274
390
        return code;
3275
7.36M
    return is_color_linear(pfs, p->p[1][0]->c, p->p[1][1]->c);
3276
7.36M
}
3277
3278
static inline int
3279
is_quadrangle_color_linear_by_v(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3280
293k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3281
293k
    int code;
3282
3283
293k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][0]->c);
3284
293k
    if (code <= 0)
3285
88.6k
        return code;
3286
204k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][1]->c);
3287
293k
}
3288
3289
static inline int
3290
is_quadrangle_color_linear_by_diagonals(const patch_fill_state_t *pfs, const quadrangle_patch *p)
3291
268k
{   /* returns : 1 = linear, 0 = unlinear, <0 = error. */
3292
268k
    int code;
3293
3294
268k
    code = is_color_linear(pfs, p->p[0][0]->c, p->p[1][1]->c);
3295
268k
    if (code <= 0)
3296
69.3k
        return code;
3297
198k
    return is_color_linear(pfs, p->p[0][1]->c, p->p[1][0]->c);
3298
268k
}
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
11.2M
{
3313
11.2M
    patch_color_t d0001, d1011, d;
3314
11.2M
    double D, D0001, D1011, D0010, D0111, D0011, D0110;
3315
11.2M
    double Du, Dv;
3316
3317
11.2M
    color_diff(pfs, p->p[0][0]->c, p->p[0][1]->c, &d0001);
3318
11.2M
    color_diff(pfs, p->p[1][0]->c, p->p[1][1]->c, &d1011);
3319
11.2M
    D0001 = color_norm(pfs, &d0001);
3320
11.2M
    D1011 = color_norm(pfs, &d1011);
3321
11.2M
    D0010 = color_span(pfs, p->p[0][0]->c, p->p[1][0]->c);
3322
11.2M
    D0111 = color_span(pfs, p->p[0][1]->c, p->p[1][1]->c);
3323
11.2M
    D0011 = color_span(pfs, p->p[0][0]->c, p->p[1][1]->c);
3324
11.2M
    D0110 = color_span(pfs, p->p[0][1]->c, p->p[1][0]->c);
3325
11.2M
    if (pfs->unlinear) {
3326
3.78M
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness &&
3327
3.47M
            D0010 <= pfs->smoothness && D0111 <= pfs->smoothness &&
3328
3.38M
            D0011 <= pfs->smoothness && D0110 <= pfs->smoothness)
3329
3.34M
            return color_change_small;
3330
436k
        if (D0001 <= pfs->smoothness && D1011 <= pfs->smoothness) {
3331
130k
            if (!is_big_v) {
3332
                /* The color function looks uncontiguous. */
3333
16.9k
                return color_change_small;
3334
16.9k
            }
3335
113k
            *divide_v = true;
3336
113k
            return color_change_gradient;
3337
130k
        }
3338
306k
        if (D0010 <= pfs->smoothness && D0111 <= pfs->smoothness) {
3339
297k
            if (!is_big_u) {
3340
                /* The color function looks uncontiguous. */
3341
1.84k
                return color_change_small;
3342
1.84k
            }
3343
296k
            *divide_u = true;
3344
296k
            return color_change_gradient;
3345
297k
        }
3346
306k
    }
3347
7.43M
    color_diff(pfs, &d0001, &d1011, &d);
3348
7.43M
    Du = max(D0001, D1011);
3349
7.43M
    Dv = max(D0010, D0111);
3350
7.43M
    if (Du <= pfs->smoothness / 8 && Dv <= pfs->smoothness / 8)
3351
2.19M
        return color_change_small;
3352
5.24M
    if (Du <= pfs->smoothness / 8)
3353
77.5k
        return color_change_linear;
3354
5.16M
    if (Dv <= pfs->smoothness / 8)
3355
4.99M
        return color_change_linear;
3356
166k
    D = color_norm(pfs, &d);
3357
166k
    if (D <= pfs->smoothness)
3358
144k
        return color_change_bilinear;
3359
22.3k
#if 1
3360
22.3k
    if (Du > Dv && is_big_u)
3361
11.8k
        *divide_u = true;
3362
10.4k
    else if (Du < Dv && is_big_v)
3363
8.25k
        *divide_v = true;
3364
2.18k
    else if (is_big_u && size_u > size_v)
3365
864
        *divide_u = true;
3366
1.31k
    else if (is_big_v && size_v > size_u)
3367
1.31k
        *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
22.3k
    return color_change_general;
3384
22.3k
}
3385
3386
static int
3387
fill_quadrangle(patch_fill_state_t *pfs, const quadrangle_patch *p, bool big)
3388
12.6M
{
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
12.6M
    quadrangle_patch s0, s1;
3393
12.6M
    wedge_vertex_list_t l0, l1, l2;
3394
12.6M
    int code;
3395
12.6M
    bool divide_u = false, divide_v = false, big1 = big;
3396
12.6M
    shading_vertex_t q[2];
3397
12.6M
    bool monotonic_color_save = pfs->monotonic_color;
3398
12.6M
    bool linear_color_save = pfs->linear_color;
3399
12.6M
    bool inside_save = pfs->inside;
3400
12.6M
    const bool inside = pfs->inside; /* 'const' should help compiler to analyze initializations. */
3401
12.6M
    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
12.6M
    if (!inside) {
3405
3.42M
        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.42M
        r1 = r;
3407
3.42M
        rect_intersect(r, pfs->rect);
3408
3.42M
        if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3409
1.08M
            return 0; /* Outside. */
3410
3.42M
    }
3411
11.5M
    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
10.4M
        fixed size_u = max(max(any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x),
3417
10.4M
                               any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x)),
3418
10.4M
                           max(any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y),
3419
10.4M
                               any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y)));
3420
10.4M
        fixed size_v = max(max(any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x),
3421
10.4M
                               any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x)),
3422
10.4M
                           max(any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y),
3423
10.4M
                               any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y)));
3424
3425
10.4M
        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
10.4M
            big1 = false;
3438
10.4M
    }
3439
11.5M
    if (!big1) {
3440
11.5M
        bool is_big_u = false, is_big_v = false;
3441
11.5M
        double d0001x = any_abs(p->p[0][0]->p.x - p->p[0][1]->p.x);
3442
11.5M
        double d1011x = any_abs(p->p[1][0]->p.x - p->p[1][1]->p.x);
3443
11.5M
        double d0001y = any_abs(p->p[0][0]->p.y - p->p[0][1]->p.y);
3444
11.5M
        double d1011y = any_abs(p->p[1][0]->p.y - p->p[1][1]->p.y);
3445
11.5M
        double d0010x = any_abs(p->p[0][0]->p.x - p->p[1][0]->p.x);
3446
11.5M
        double d0111x = any_abs(p->p[0][1]->p.x - p->p[1][1]->p.x);
3447
11.5M
        double d0010y = any_abs(p->p[0][0]->p.y - p->p[1][0]->p.y);
3448
11.5M
        double d0111y = any_abs(p->p[0][1]->p.y - p->p[1][1]->p.y);
3449
11.5M
        double size_u = max(max(d0001x, d1011x), max(d0001y, d1011y));
3450
11.5M
        double size_v = max(max(d0010x, d0111x), max(d0010y, d0111y));
3451
3452
11.5M
        if (size_u > pfs->decomposition_limit)
3453
11.2M
            is_big_u = true;
3454
11.5M
        if (size_v > pfs->decomposition_limit)
3455
625k
            is_big_v = true;
3456
10.9M
        else if (!is_big_u)
3457
229k
            return (QUADRANGLES || !pfs->maybe_self_intersecting ?
3458
189k
                        constant_color_quadrangle : triangles4)(pfs, p,
3459
229k
                            pfs->maybe_self_intersecting);
3460
11.3M
        if (!pfs->monotonic_color) {
3461
2.53M
            bool not_monotonic_by_u = false, not_monotonic_by_v = false;
3462
3463
2.53M
            code = is_quadrangle_color_monotonic(pfs, p, &not_monotonic_by_u, &not_monotonic_by_v);
3464
2.53M
            if (code < 0)
3465
0
                return code;
3466
2.53M
            if (is_big_u)
3467
2.53M
                divide_u = not_monotonic_by_u;
3468
2.53M
            if (is_big_v)
3469
97.5k
                divide_v = not_monotonic_by_v;
3470
2.53M
            if (!divide_u && !divide_v)
3471
2.51M
                pfs->monotonic_color = true;
3472
2.53M
        }
3473
11.3M
        if (pfs->monotonic_color && !pfs->linear_color) {
3474
10.5M
            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
10.5M
            } else if (!divide_u && !divide_v && !pfs->unlinear) {
3480
7.47M
                if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3481
7.36M
                    code = is_quadrangle_color_linear_by_u(pfs, p);
3482
7.36M
                    if (code < 0)
3483
0
                        return code;
3484
7.36M
                    divide_u = !code;
3485
7.36M
                }
3486
7.47M
                if (is_big_v) {
3487
293k
                    code = is_quadrangle_color_linear_by_v(pfs, p);
3488
293k
                    if (code < 0)
3489
0
                        return code;
3490
293k
                    divide_v = !code;
3491
293k
                }
3492
7.47M
                if (is_big_u && is_big_v) {
3493
268k
                    code = is_quadrangle_color_linear_by_diagonals(pfs, p);
3494
268k
                    if (code < 0)
3495
0
                        return code;
3496
268k
                    if (!code) {
3497
69.4k
                        if (d0001x + d1011x + d0001y + d1011y > d0010x + d0111x + d0010y + d0111y) { /* fixme: use size_u, size_v */
3498
36.2k
                            divide_u = true;
3499
36.2k
                            divide_v = false;
3500
36.2k
                        } else {
3501
33.2k
                            divide_v = true;
3502
33.2k
                            divide_u = false;
3503
33.2k
                        }
3504
69.4k
                    }
3505
268k
                }
3506
7.47M
            }
3507
10.5M
            if (!divide_u && !divide_v)
3508
10.4M
                pfs->linear_color = true;
3509
10.5M
        }
3510
11.3M
        if (!pfs->linear_color) {
3511
            /* go to divide. */
3512
11.2M
        } else switch(quadrangle_color_change(pfs, p, is_big_u, is_big_v, size_u, size_v, &divide_u, &divide_v)) {
3513
5.55M
            case color_change_small:
3514
5.55M
                code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3515
5.40M
                            constant_color_quadrangle : triangles4)(pfs, p,
3516
5.55M
                                pfs->maybe_self_intersecting);
3517
5.55M
                pfs->monotonic_color = monotonic_color_save;
3518
5.55M
                pfs->linear_color = linear_color_save;
3519
5.55M
                return code;
3520
144k
            case color_change_bilinear:
3521
144k
                if (!QUADRANGLES) {
3522
144k
                    code = triangles4(pfs, p, true);
3523
144k
                    pfs->monotonic_color = monotonic_color_save;
3524
144k
                    pfs->linear_color = linear_color_save;
3525
144k
                    return code;
3526
144k
                }
3527
5.07M
            case color_change_linear:
3528
5.07M
                if (!QUADRANGLES) {
3529
5.07M
                    code = triangles2(pfs, p, true);
3530
5.07M
                    pfs->monotonic_color = monotonic_color_save;
3531
5.07M
                    pfs->linear_color = linear_color_save;
3532
5.07M
                    return code;
3533
5.07M
                }
3534
409k
            case color_change_gradient:
3535
431k
            case color_change_general:
3536
431k
                ; /* goto divide. */
3537
11.2M
        }
3538
11.3M
    }
3539
541k
    if (!inside) {
3540
75.3k
        if (r.p.x == r1.p.x && r.p.y == r1.p.y &&
3541
43.5k
            r.q.x == r1.q.x && r.q.y == r1.q.y)
3542
20.8k
            pfs->inside = true;
3543
75.3k
    }
3544
541k
    if (LAZY_WEDGES)
3545
541k
        init_wedge_vertex_list(&l0, 1);
3546
541k
    if (divide_v) {
3547
196k
        patch_color_t *c[2];
3548
196k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3549
3550
196k
        if(color_stack_ptr == NULL)
3551
0
            return_error(gs_error_unregistered); /* Must not happen. */
3552
196k
        q[0].c = c[0];
3553
196k
        q[1].c = c[1];
3554
196k
        divide_quadrangle_by_v(pfs, &s0, &s1, q, p, c);
3555
196k
        if (LAZY_WEDGES) {
3556
196k
            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
196k
            if (code >= 0)
3558
196k
                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
196k
            if (code >= 0) {
3560
196k
                s0.l1110 = s1.l0001 = &l0;
3561
196k
                s0.l0111 = s1.l0111 = &l1;
3562
196k
                s0.l1000 = s1.l1000 = &l2;
3563
196k
                s0.l0001 = p->l0001;
3564
196k
                s1.l1110 = p->l1110;
3565
196k
            }
3566
196k
        } 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
196k
        if (code >= 0)
3572
196k
            code = fill_quadrangle(pfs, &s0, big1);
3573
196k
        if (code >= 0) {
3574
196k
            if (LAZY_WEDGES) {
3575
196k
                l0.last_side = true;
3576
196k
                move_wedge(&l1, p->l0111, true);
3577
196k
                move_wedge(&l2, p->l1000, false);
3578
196k
            }
3579
196k
            code = fill_quadrangle(pfs, &s1, big1);
3580
196k
        }
3581
196k
        if (LAZY_WEDGES) {
3582
196k
            if (code >= 0)
3583
196k
                code = close_wedge_median(pfs, p->l0111, p->p[0][1]->c, p->p[1][1]->c);
3584
196k
            if (code >= 0)
3585
196k
                code = close_wedge_median(pfs, p->l1000, p->p[1][0]->c, p->p[0][0]->c);
3586
196k
            if (code >= 0)
3587
196k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[1][0]->c, s0.p[1][1]->c);
3588
196k
            release_colors_inline(pfs, color_stack_ptr, 2);
3589
196k
        }
3590
345k
    } else if (divide_u) {
3591
345k
        patch_color_t *c[2];
3592
345k
        byte *color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3593
3594
345k
        if(color_stack_ptr == NULL)
3595
0
            return_error(gs_error_unregistered); /* Must not happen. */
3596
345k
        q[0].c = c[0];
3597
345k
        q[1].c = c[1];
3598
345k
        divide_quadrangle_by_u(pfs, &s0, &s1, q, p, c);
3599
345k
        if (LAZY_WEDGES) {
3600
345k
            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
345k
            if (code >= 0)
3602
345k
                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
345k
            if (code >= 0) {
3604
345k
                s0.l0111 = s1.l1000 = &l0;
3605
345k
                s0.l0001 = s1.l0001 = &l1;
3606
345k
                s0.l1110 = s1.l1110 = &l2;
3607
345k
                s0.l1000 = p->l1000;
3608
345k
                s1.l0111 = p->l0111;
3609
345k
            }
3610
345k
        } 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
345k
        if (code >= 0)
3616
345k
            code = fill_quadrangle(pfs, &s0, big1);
3617
345k
        if (code >= 0) {
3618
345k
            if (LAZY_WEDGES) {
3619
345k
                l0.last_side = true;
3620
345k
                move_wedge(&l1, p->l0001, true);
3621
345k
                move_wedge(&l2, p->l1110, false);
3622
345k
            }
3623
345k
            code = fill_quadrangle(pfs, &s1, big1);
3624
345k
        }
3625
345k
        if (LAZY_WEDGES) {
3626
345k
            if (code >= 0)
3627
345k
                code = close_wedge_median(pfs, p->l0001, p->p[0][0]->c, p->p[0][1]->c);
3628
345k
            if (code >= 0)
3629
345k
                code = close_wedge_median(pfs, p->l1110, p->p[1][1]->c, p->p[1][0]->c);
3630
345k
            if (code >= 0)
3631
345k
                code = terminate_wedge_vertex_list(pfs, &l0, s0.p[0][1]->c, s0.p[1][1]->c);
3632
345k
            release_colors_inline(pfs, color_stack_ptr, 2);
3633
345k
        }
3634
345k
    } else
3635
0
        code = (QUADRANGLES || !pfs->maybe_self_intersecting ?
3636
0
                    constant_color_quadrangle : triangles4)(pfs, p,
3637
0
                        pfs->maybe_self_intersecting);
3638
541k
    pfs->monotonic_color = monotonic_color_save;
3639
541k
    pfs->linear_color = linear_color_save;
3640
541k
    pfs->inside = inside_save;
3641
541k
    return code;
3642
541k
}
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
22.1M
{
3648
22.1M
    s0->c[0][1] = c[0];
3649
22.1M
    s0->c[1][1] = c[1];
3650
22.1M
    split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
3651
22.1M
    split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
3652
22.1M
    split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
3653
22.1M
    split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
3654
22.1M
    s0->c[0][0] = p->c[0][0];
3655
22.1M
    s0->c[1][0] = p->c[1][0];
3656
22.1M
    s1->c[0][0] = s0->c[0][1];
3657
22.1M
    s1->c[1][0] = s0->c[1][1];
3658
22.1M
    patch_interpolate_color(s0->c[0][1], p->c[0][0], p->c[0][1], pfs, 0.5);
3659
22.1M
    patch_interpolate_color(s0->c[1][1], p->c[1][0], p->c[1][1], pfs, 0.5);
3660
22.1M
    s1->c[0][1] = p->c[0][1];
3661
22.1M
    s1->c[1][1] = p->c[1][1];
3662
22.1M
}
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
4.84M
{
3668
4.84M
    s0->c[1][0] = c[0];
3669
4.84M
    s0->c[1][1] = c[1];
3670
4.84M
    split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
3671
4.84M
    split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
3672
4.84M
    split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
3673
4.84M
    split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
3674
4.84M
    s0->c[0][0] = p->c[0][0];
3675
4.84M
    s0->c[0][1] = p->c[0][1];
3676
4.84M
    s1->c[0][0] = s0->c[1][0];
3677
4.84M
    s1->c[0][1] = s0->c[1][1];
3678
4.84M
    patch_interpolate_color(s0->c[1][0], p->c[0][0], p->c[1][0], pfs, 0.5);
3679
4.84M
    patch_interpolate_color(s0->c[1][1], p->c[0][1], p->c[1][1], pfs, 0.5);
3680
4.84M
    s1->c[1][0] = p->c[1][0];
3681
4.84M
    s1->c[1][1] = p->c[1][1];
3682
4.84M
}
3683
3684
static inline void
3685
tensor_patch_bbox(gs_fixed_rect *r, const tensor_patch *p)
3686
37.2M
{
3687
37.2M
    int i, j;
3688
3689
37.2M
    r->p.x = r->q.x = p->pole[0][0].x;
3690
37.2M
    r->p.y = r->q.y = p->pole[0][0].y;
3691
186M
    for (i = 0; i < 4; i++) {
3692
744M
        for (j = 0; j < 4; j++) {
3693
595M
            const gs_fixed_point *q = &p->pole[i][j];
3694
3695
595M
            if (r->p.x > q->x)
3696
118M
                r->p.x = q->x;
3697
595M
            if (r->p.y > q->y)
3698
70.0M
                r->p.y = q->y;
3699
595M
            if (r->q.x < q->x)
3700
79.3M
                r->q.x = q->x;
3701
595M
            if (r->q.y < q->y)
3702
94.0M
                r->q.y = q->y;
3703
595M
        }
3704
148M
    }
3705
37.2M
}
3706
3707
static int
3708
decompose_stripe(patch_fill_state_t *pfs, const tensor_patch *p, int ku)
3709
49.2M
{
3710
49.2M
    if (ku > 1) {
3711
37.7M
        tensor_patch s0, s1;
3712
37.7M
        patch_color_t *c[2];
3713
37.7M
        int code;
3714
37.7M
        byte *color_stack_ptr;
3715
37.7M
        bool save_inside = pfs->inside;
3716
3717
37.7M
        if (!pfs->inside) {
3718
32.0M
            gs_fixed_rect r, r1;
3719
3720
32.0M
            tensor_patch_bbox(&r, p);
3721
32.0M
            r1 = r;
3722
32.0M
            rect_intersect(r, pfs->rect);
3723
32.0M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3724
15.5M
                return 0;
3725
16.5M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3726
4.66M
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3727
1.27M
                pfs->inside = true;
3728
16.5M
        }
3729
22.1M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3730
22.1M
        if(color_stack_ptr == NULL)
3731
0
            return_error(gs_error_unregistered); /* Must not happen. */
3732
22.1M
        split_stripe(pfs, &s0, &s1, p, c);
3733
22.1M
        code = decompose_stripe(pfs, &s0, ku / 2);
3734
22.1M
        if (code >= 0)
3735
22.1M
            code = decompose_stripe(pfs, &s1, ku / 2);
3736
22.1M
        release_colors_inline(pfs, color_stack_ptr, 2);
3737
22.1M
        pfs->inside = save_inside;
3738
22.1M
        return code;
3739
22.1M
    } else {
3740
11.5M
        quadrangle_patch q;
3741
11.5M
        shading_vertex_t qq[2][2];
3742
11.5M
        wedge_vertex_list_t l[4];
3743
11.5M
        int code;
3744
3745
11.5M
        init_wedge_vertex_list(l, count_of(l));
3746
11.5M
        make_quadrangle(p, qq, l, &q);
3747
#       if SKIP_TEST
3748
            dbg_quad_cnt++;
3749
#       endif
3750
11.5M
        code = fill_quadrangle(pfs, &q, true);
3751
11.5M
        if (code < 0)
3752
0
            return code;
3753
11.5M
        if (LAZY_WEDGES) {
3754
11.5M
            code = terminate_wedge_vertex_list(pfs, &l[0], q.p[0][0]->c, q.p[0][1]->c);
3755
11.5M
            if (code < 0)
3756
0
                return code;
3757
11.5M
            code = terminate_wedge_vertex_list(pfs, &l[1], q.p[0][1]->c, q.p[1][1]->c);
3758
11.5M
            if (code < 0)
3759
0
                return code;
3760
11.5M
            code = terminate_wedge_vertex_list(pfs, &l[2], q.p[1][1]->c, q.p[1][0]->c);
3761
11.5M
            if (code < 0)
3762
0
                return code;
3763
11.5M
            code = terminate_wedge_vertex_list(pfs, &l[3], q.p[1][0]->c, q.p[0][1]->c);
3764
11.5M
            if (code < 0)
3765
0
                return code;
3766
11.5M
        }
3767
11.5M
        return code;
3768
11.5M
    }
3769
49.2M
}
3770
3771
static int
3772
fill_stripe(patch_fill_state_t *pfs, const tensor_patch *p)
3773
5.00M
{
3774
    /* The stripe is flattened enough by V, so ignore inner poles. */
3775
5.00M
    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.00M
    ku[0] = curve_samples(pfs, p->pole[0], 1, pfs->fixed_flat);
3784
5.00M
    ku[3] = curve_samples(pfs, p->pole[3], 1, pfs->fixed_flat);
3785
5.00M
    kum = max(ku[0], ku[3]);
3786
5.00M
    code = fill_wedges(pfs, ku[0], kum, p->pole[0], 1, p->c[0][0], p->c[0][1], inpatch_wedge);
3787
5.00M
    if (code < 0)
3788
0
        return code;
3789
5.00M
    if (INTERPATCH_PADDING) {
3790
5.00M
        code = mesh_padding(pfs, &p->pole[0][0], &p->pole[3][0], p->c[0][0], p->c[1][0]);
3791
5.00M
        if (code < 0)
3792
15
            return code;
3793
5.00M
        code = mesh_padding(pfs, &p->pole[0][3], &p->pole[3][3], p->c[0][1], p->c[1][1]);
3794
5.00M
        if (code < 0)
3795
0
            return code;
3796
5.00M
    }
3797
5.00M
    code = decompose_stripe(pfs, p, kum);
3798
5.00M
    if (code < 0)
3799
0
        return code;
3800
5.00M
    return fill_wedges(pfs, ku[3], kum, p->pole[3], 1, p->c[1][0], p->c[1][1], inpatch_wedge);
3801
5.00M
}
3802
3803
static inline bool neqs(int *a, int b)
3804
13.9M
{   /* Unequal signs. Assuming -1, 0, 1 only. */
3805
13.9M
    if (*a * b < 0)
3806
4.80M
        return true;
3807
9.18M
    if (!*a)
3808
2.01M
        *a = b;
3809
9.18M
    return false;
3810
13.9M
}
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
19.2M
{   fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
3815
19.2M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
3816
19.2M
    int64_t vp = (int64_t)dx1 * dy2 - (int64_t)dy1 * dx2;
3817
3818
19.2M
    return (vp > 0 ? 1 : vp < 0 ? -1 : 0);
3819
19.2M
}
3820
3821
static inline bool
3822
is_x_bended(const tensor_patch *p)
3823
5.19M
{
3824
5.19M
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[0][1], &p->pole[1][0]);
3825
3826
5.19M
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][1], &p->pole[0][2], &p->pole[1][1])))
3827
2.54M
        return true;
3828
2.64M
    if (neqs(&sign, vector_pair_orientation(&p->pole[0][2], &p->pole[0][3], &p->pole[1][2])))
3829
1.80M
        return true;
3830
841k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[0][3], &p->pole[0][2], &p->pole[1][3])))
3831
436k
        return true;
3832
3833
404k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3834
6.09k
        return true;
3835
398k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[1][2], &p->pole[2][1])))
3836
0
        return true;
3837
398k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[1][3], &p->pole[2][2])))
3838
3.25k
        return true;
3839
395k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[1][2], &p->pole[2][3])))
3840
1.89k
        return true;
3841
3842
393k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3843
2.00k
        return true;
3844
391k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[2][2], &p->pole[3][1])))
3845
0
        return true;
3846
391k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[2][3], &p->pole[3][2])))
3847
1.25k
        return true;
3848
390k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[2][2], &p->pole[3][3])))
3849
1.22k
        return true;
3850
3851
389k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3852
332
        return true;
3853
388k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[3][2], &p->pole[2][1])))
3854
0
        return true;
3855
388k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[3][3], &p->pole[2][2])))
3856
314
        return true;
3857
388k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[3][2], &p->pole[2][3])))
3858
110
        return true;
3859
388k
    return false;
3860
388k
}
3861
3862
static inline bool
3863
is_y_bended(const tensor_patch *p)
3864
39.7k
{
3865
39.7k
    int sign = vector_pair_orientation(&p->pole[0][0], &p->pole[1][0], &p->pole[0][1]);
3866
3867
39.7k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][0], &p->pole[2][0], &p->pole[1][1])))
3868
316
        return true;
3869
39.4k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][0], &p->pole[3][0], &p->pole[2][1])))
3870
133
        return true;
3871
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][0], &p->pole[2][0], &p->pole[3][1])))
3872
36
        return true;
3873
3874
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3875
0
        return true;
3876
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][1], &p->pole[2][1], &p->pole[1][2])))
3877
0
        return true;
3878
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][1], &p->pole[3][1], &p->pole[2][2])))
3879
0
        return true;
3880
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][1], &p->pole[2][1], &p->pole[3][2])))
3881
2
        return true;
3882
3883
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3884
11
        return true;
3885
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[1][2], &p->pole[2][2], &p->pole[1][3])))
3886
0
        return true;
3887
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[2][2], &p->pole[3][2], &p->pole[2][3])))
3888
0
        return true;
3889
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[3][2], &p->pole[2][2], &p->pole[3][3])))
3890
0
        return true;
3891
3892
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3893
0
        return true;
3894
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[1][3], &p->pole[2][3], &p->pole[1][2])))
3895
0
        return true;
3896
39.2k
    if (neqs(&sign, -vector_pair_orientation(&p->pole[2][3], &p->pole[3][3], &p->pole[2][2])))
3897
0
        return true;
3898
39.2k
    if (neqs(&sign, vector_pair_orientation(&p->pole[3][3], &p->pole[2][3], &p->pole[3][2])))
3899
0
        return true;
3900
39.2k
    return false;
3901
39.2k
}
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
30.1M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3906
30.1M
    fixed xmin0 = min(pole[0 * pole_step].x, pole[1 * pole_step].x);
3907
30.1M
    fixed xmin1 = min(pole[2 * pole_step].x, pole[3 * pole_step].x);
3908
30.1M
    fixed xmin =  min(xmin0, xmin1);
3909
30.1M
    fixed xmax0 = max(pole[0 * pole_step].x, pole[1 * pole_step].x);
3910
30.1M
    fixed xmax1 = max(pole[2 * pole_step].x, pole[3 * pole_step].x);
3911
30.1M
    fixed xmax =  max(xmax0, xmax1);
3912
3913
30.1M
    if(xmax - xmin <= pfs->decomposition_limit)
3914
25.4M
        return true;
3915
4.72M
    return false;
3916
30.1M
}
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
19.5M
{   /* Is curve within a single pixel, or smaller than half pixel ? */
3921
19.5M
    fixed ymin0 = min(pole[0 * pole_step].y, pole[1 * pole_step].y);
3922
19.5M
    fixed ymin1 = min(pole[2 * pole_step].y, pole[3 * pole_step].y);
3923
19.5M
    fixed ymin =  min(ymin0, ymin1);
3924
19.5M
    fixed ymax0 = max(pole[0 * pole_step].y, pole[1 * pole_step].y);
3925
19.5M
    fixed ymax1 = max(pole[2 * pole_step].y, pole[3 * pole_step].y);
3926
19.5M
    fixed ymax =  max(ymax0, ymax1);
3927
3928
19.5M
    if (ymax - ymin <= pfs->decomposition_limit)
3929
19.1M
        return true;
3930
370k
    return false;
3931
19.5M
}
3932
3933
static inline bool
3934
is_patch_narrow(const patch_fill_state_t *pfs, const tensor_patch *p)
3935
9.74M
{
3936
9.74M
    if (!is_curve_x_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3937
1.75M
        return false;
3938
7.99M
    if (!is_curve_x_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3939
1.27M
        return false;
3940
6.71M
    if (!is_curve_x_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3941
971k
        return false;
3942
5.74M
    if (!is_curve_x_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3943
717k
        return false;
3944
5.02M
    if (!is_curve_y_small(pfs, &p->pole[0][0], 4, pfs->fixed_flat))
3945
74.0k
        return false;
3946
4.94M
    if (!is_curve_y_small(pfs, &p->pole[0][1], 4, pfs->fixed_flat))
3947
143k
        return false;
3948
4.80M
    if (!is_curve_y_small(pfs, &p->pole[0][2], 4, pfs->fixed_flat))
3949
67.2k
        return false;
3950
4.73M
    if (!is_curve_y_small(pfs, &p->pole[0][3], 4, pfs->fixed_flat))
3951
85.8k
        return false;
3952
4.65M
    return true;
3953
4.73M
}
3954
3955
static int
3956
fill_patch(patch_fill_state_t *pfs, const tensor_patch *p, int kv, int kv0, int kv1)
3957
10.1M
{
3958
10.1M
    if (kv <= 1) {
3959
9.74M
        if (is_patch_narrow(pfs, p))
3960
4.65M
            return fill_stripe(pfs, p);
3961
5.09M
        if (!is_x_bended(p))
3962
348k
            return fill_stripe(pfs, p);
3963
5.09M
    }
3964
5.17M
    {   tensor_patch s0, s1;
3965
5.17M
        patch_color_t *c[2];
3966
5.17M
        shading_vertex_t q0, q1, q2;
3967
5.17M
        int code = 0;
3968
5.17M
        byte *color_stack_ptr;
3969
5.17M
        bool save_inside = pfs->inside;
3970
3971
5.17M
        if (!pfs->inside) {
3972
5.13M
            gs_fixed_rect r, r1;
3973
3974
5.13M
            tensor_patch_bbox(&r, p);
3975
5.13M
            r.p.x -= INTERPATCH_PADDING;
3976
5.13M
            r.p.y -= INTERPATCH_PADDING;
3977
5.13M
            r.q.x += INTERPATCH_PADDING;
3978
5.13M
            r.q.y += INTERPATCH_PADDING;
3979
5.13M
            r1 = r;
3980
5.13M
            rect_intersect(r, pfs->rect);
3981
5.13M
            if (r.q.x <= r.p.x || r.q.y <= r.p.y)
3982
331k
                return 0;
3983
4.80M
            if (r1.p.x == r.p.x && r1.p.y == r.p.y &&
3984
703k
                r1.q.x == r.q.x && r1.q.y == r.q.y)
3985
10.4k
                pfs->inside = true;
3986
4.80M
        }
3987
4.84M
        color_stack_ptr = reserve_colors_inline(pfs, c, 2);
3988
4.84M
        if(color_stack_ptr == NULL)
3989
0
            return_error(gs_error_unregistered); /* Must not happen. */
3990
4.84M
        split_patch(pfs, &s0, &s1, p, c);
3991
4.84M
        if (kv0 <= 1) {
3992
4.75M
            q0.p = s0.pole[0][0];
3993
4.75M
            q0.c = s0.c[0][0];
3994
4.75M
            q1.p = s1.pole[3][0];
3995
4.75M
            q1.c = s1.c[1][0];
3996
4.75M
            q2.p = s0.pole[3][0];
3997
4.75M
            q2.c = s0.c[1][0];
3998
4.75M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
3999
4.75M
        }
4000
4.84M
        if (kv1 <= 1 && code >= 0) {
4001
4.74M
            q0.p = s0.pole[0][3];
4002
4.74M
            q0.c = s0.c[0][1];
4003
4.74M
            q1.p = s1.pole[3][3];
4004
4.74M
            q1.c = s1.c[1][1];
4005
4.74M
            q2.p = s0.pole[3][3];
4006
4.74M
            q2.c = s0.c[1][1];
4007
4.74M
            code = fill_triangle_wedge(pfs, &q0, &q1, &q2);
4008
4.74M
        }
4009
4.84M
        if (code >= 0)
4010
4.84M
            code = fill_patch(pfs, &s0, kv / 2, kv0 / 2, kv1 / 2);
4011
4.84M
        if (code >= 0)
4012
4.84M
            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
4.84M
        release_colors_inline(pfs, color_stack_ptr, 2);
4033
4.84M
        pfs->inside = save_inside;
4034
4.84M
        return code;
4035
4.84M
    }
4036
4.84M
}
4037
4038
static inline int64_t
4039
lcp1(int64_t p0, int64_t p3)
4040
810k
{   /* Computing the 1st pole of a 3d order besier, which appears a line. */
4041
810k
    return (p0 + p0 + p3);
4042
810k
}
4043
static inline int64_t
4044
lcp2(int64_t p0, int64_t p3)
4045
810k
{   /* Computing the 2nd pole of a 3d order besier, which appears a line. */
4046
810k
    return (p0 + p3 + p3);
4047
810k
}
4048
4049
static void
4050
patch_set_color(const patch_fill_state_t *pfs, patch_color_t *c, const float *cc)
4051
1.94M
{
4052
1.94M
    if (pfs->Function) {
4053
161k
        c->t[0] = cc[0];
4054
161k
        c->t[1] = cc[1];
4055
161k
    } else
4056
1.78M
        memcpy(c->cc.paint.values, cc, sizeof(c->cc.paint.values[0]) * pfs->num_components);
4057
1.94M
}
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
485k
{
4063
485k
    const gs_color_space *pcs = pfs->direct_space;
4064
4065
485k
    p->pole[0][0] = curve[0].vertex.p;
4066
485k
    p->pole[1][0] = curve[0].control[0];
4067
485k
    p->pole[2][0] = curve[0].control[1];
4068
485k
    p->pole[3][0] = curve[1].vertex.p;
4069
485k
    p->pole[3][1] = curve[1].control[0];
4070
485k
    p->pole[3][2] = curve[1].control[1];
4071
485k
    p->pole[3][3] = curve[2].vertex.p;
4072
485k
    p->pole[2][3] = curve[2].control[0];
4073
485k
    p->pole[1][3] = curve[2].control[1];
4074
485k
    p->pole[0][3] = curve[3].vertex.p;
4075
485k
    p->pole[0][2] = curve[3].control[0];
4076
485k
    p->pole[0][1] = curve[3].control[1];
4077
485k
    if (interior != NULL) {
4078
445k
        p->pole[1][1] = interior[0];
4079
445k
        p->pole[1][2] = interior[1];
4080
445k
        p->pole[2][2] = interior[2];
4081
445k
        p->pole[2][1] = interior[3];
4082
445k
    } else {
4083
40.5k
        p->pole[1][1].x = (fixed)((3*(lcp1(p->pole[0][1].x, p->pole[3][1].x) +
4084
40.5k
                                      lcp1(p->pole[1][0].x, p->pole[1][3].x)) -
4085
40.5k
                                   lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4086
40.5k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4087
40.5k
        p->pole[1][2].x = (fixed)((3*(lcp1(p->pole[0][2].x, p->pole[3][2].x) +
4088
40.5k
                                      lcp2(p->pole[1][0].x, p->pole[1][3].x)) -
4089
40.5k
                                   lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4090
40.5k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4091
40.5k
        p->pole[2][1].x = (fixed)((3*(lcp2(p->pole[0][1].x, p->pole[3][1].x) +
4092
40.5k
                                      lcp1(p->pole[2][0].x, p->pole[2][3].x)) -
4093
40.5k
                                   lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
4094
40.5k
                                        lcp1(p->pole[3][0].x, p->pole[3][3].x)))/9);
4095
40.5k
        p->pole[2][2].x = (fixed)((3*(lcp2(p->pole[0][2].x, p->pole[3][2].x) +
4096
40.5k
                                      lcp2(p->pole[2][0].x, p->pole[2][3].x)) -
4097
40.5k
                                   lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
4098
40.5k
                                        lcp2(p->pole[3][0].x, p->pole[3][3].x)))/9);
4099
4100
40.5k
        p->pole[1][1].y = (fixed)((3*(lcp1(p->pole[0][1].y, p->pole[3][1].y) +
4101
40.5k
                                      lcp1(p->pole[1][0].y, p->pole[1][3].y)) -
4102
40.5k
                                   lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4103
40.5k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4104
40.5k
        p->pole[1][2].y = (fixed)((3*(lcp1(p->pole[0][2].y, p->pole[3][2].y) +
4105
40.5k
                                      lcp2(p->pole[1][0].y, p->pole[1][3].y)) -
4106
40.5k
                                   lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4107
40.5k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4108
40.5k
        p->pole[2][1].y = (fixed)((3*(lcp2(p->pole[0][1].y, p->pole[3][1].y) +
4109
40.5k
                                      lcp1(p->pole[2][0].y, p->pole[2][3].y)) -
4110
40.5k
                                   lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
4111
40.5k
                                        lcp1(p->pole[3][0].y, p->pole[3][3].y)))/9);
4112
40.5k
        p->pole[2][2].y = (fixed)((3*(lcp2(p->pole[0][2].y, p->pole[3][2].y) +
4113
40.5k
                                      lcp2(p->pole[2][0].y, p->pole[2][3].y)) -
4114
40.5k
                                   lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
4115
40.5k
                                        lcp2(p->pole[3][0].y, p->pole[3][3].y)))/9);
4116
40.5k
    }
4117
485k
    patch_set_color(pfs, p->c[0][0], curve[0].vertex.cc);
4118
485k
    patch_set_color(pfs, p->c[1][0], curve[1].vertex.cc);
4119
485k
    patch_set_color(pfs, p->c[1][1], curve[2].vertex.cc);
4120
485k
    patch_set_color(pfs, p->c[0][1], curve[3].vertex.cc);
4121
485k
    patch_resolve_color_inline(p->c[0][0], pfs);
4122
485k
    patch_resolve_color_inline(p->c[0][1], pfs);
4123
485k
    patch_resolve_color_inline(p->c[1][0], pfs);
4124
485k
    patch_resolve_color_inline(p->c[1][1], pfs);
4125
485k
    if (!pfs->Function) {
4126
445k
        pcs->type->restrict_color(&p->c[0][0]->cc, pcs);
4127
445k
        pcs->type->restrict_color(&p->c[0][1]->cc, pcs);
4128
445k
        pcs->type->restrict_color(&p->c[1][0]->cc, pcs);
4129
445k
        pcs->type->restrict_color(&p->c[1][1]->cc, pcs);
4130
445k
    }
4131
485k
}
4132
4133
int
4134
gx_shade_background(gx_device *pdev, const gs_fixed_rect *rect,
4135
        const gx_device_color *pdevc, gs_logical_operation_t log_op)
4136
9.90k
{
4137
9.90k
    gs_fixed_edge le, re;
4138
4139
9.90k
    le.start.x = rect->p.x - INTERPATCH_PADDING;
4140
9.90k
    le.start.y = rect->p.y - INTERPATCH_PADDING;
4141
9.90k
    le.end.x = rect->p.x - INTERPATCH_PADDING;
4142
9.90k
    le.end.y = rect->q.y + INTERPATCH_PADDING;
4143
9.90k
    re.start.x = rect->q.x + INTERPATCH_PADDING;
4144
9.90k
    re.start.y = rect->p.y - INTERPATCH_PADDING;
4145
9.90k
    re.end.x = rect->q.x + INTERPATCH_PADDING;
4146
9.90k
    re.end.y = rect->q.y + INTERPATCH_PADDING;
4147
9.90k
    return dev_proc(pdev, fill_trapezoid)(pdev,
4148
9.90k
            &le, &re, le.start.y, le.end.y, false, pdevc, log_op);
4149
9.90k
}
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
485k
{
4157
485k
    tensor_patch p;
4158
485k
    patch_color_t *c[4];
4159
485k
    int kv[4], kvm, ku[4], kum;
4160
485k
    int code = 0;
4161
485k
    byte *color_stack_ptr = reserve_colors_inline(pfs, c, 4); /* Can't fail */
4162
4163
485k
    p.c[0][0] = c[0];
4164
485k
    p.c[0][1] = c[1];
4165
485k
    p.c[1][0] = c[2];
4166
485k
    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
485k
    make_tensor_patch(pfs, &p, curve, interior);
4175
485k
    pfs->unlinear = !is_linear_color_applicable(pfs);
4176
485k
    pfs->linear_color = false;
4177
485k
    if ((*dev_proc(pfs->dev, dev_spec_op))(pfs->dev,
4178
485k
            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
102k
        gx_device *pdev = pfs->dev;
4183
102k
        gx_path path;
4184
102k
        fixed d01x = (curve[1].vertex.p.x - curve[0].vertex.p.x) >> 1;
4185
102k
        fixed d01y = (curve[1].vertex.p.y - curve[0].vertex.p.y) >> 1;
4186
102k
        fixed d12x = (curve[2].vertex.p.x - curve[1].vertex.p.x) >> 1;
4187
102k
        fixed d12y = (curve[2].vertex.p.y - curve[1].vertex.p.y) >> 1;
4188
102k
        fixed d23x = (curve[3].vertex.p.x - curve[2].vertex.p.x) >> 1;
4189
102k
        fixed d23y = (curve[3].vertex.p.y - curve[2].vertex.p.y) >> 1;
4190
102k
        fixed d30x = (curve[0].vertex.p.x - curve[3].vertex.p.x) >> 1;
4191
102k
        fixed d30y = (curve[0].vertex.p.y - curve[3].vertex.p.y) >> 1;
4192
102k
        int64_t s1 = (int64_t)d01x * d12y - (int64_t)d01y * d12x;
4193
102k
        int64_t s2 = (int64_t)d23x * d30y - (int64_t)d23y * d30x;
4194
102k
        int s = (s1 + s2 > 0 ? 1 : 3), i, j, k, jj, l = (s == 1 ? 0 : 1);
4195
4196
102k
        gx_path_init_local(&path, pdev->memory);
4197
102k
        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.1k
        } else {
4203
39.2k
            code = gx_path_add_point(&path, curve[0].vertex.p.x, curve[0].vertex.p.y);
4204
196k
            for (i = k = 0; k < 4 && code >= 0; i = j, k++) {
4205
156k
                j = (i + s) % 4, jj = (s == 1 ? i : j);
4206
156k
                if (curve[jj].straight)
4207
12.6k
                    code = gx_path_add_line(&path, curve[j].vertex.p.x,
4208
156k
                                                curve[j].vertex.p.y);
4209
144k
                else
4210
144k
                    code = gx_path_add_curve(&path, curve[jj].control[l].x, curve[jj].control[l].y,
4211
156k
                                                    curve[jj].control[(l + 1) & 1].x, curve[jj].control[(l + 1) & 1].y,
4212
156k
                                                    curve[j].vertex.p.x,
4213
156k
                                                    curve[j].vertex.p.y);
4214
156k
            }
4215
39.2k
            if (code >= 0)
4216
39.2k
                code = gx_path_close_subpath(&path);
4217
39.2k
        }
4218
102k
        if (code >= 0)
4219
102k
            code = (*dev_proc(pfs->dev, fill_path))(pdev, NULL, &path, NULL, NULL, NULL);
4220
102k
        gx_path_free(&path, "patch_fill");
4221
102k
        if (code < 0)
4222
0
            goto out;
4223
102k
    }
4224
    /* How many subdivisions of the patch in the u and v direction? */
4225
485k
    kv[0] = curve_samples(pfs, &p.pole[0][0], 4, pfs->fixed_flat);
4226
485k
    kv[1] = curve_samples(pfs, &p.pole[0][1], 4, pfs->fixed_flat);
4227
485k
    kv[2] = curve_samples(pfs, &p.pole[0][2], 4, pfs->fixed_flat);
4228
485k
    kv[3] = curve_samples(pfs, &p.pole[0][3], 4, pfs->fixed_flat);
4229
485k
    kvm = max(max(kv[0], kv[1]), max(kv[2], kv[3]));
4230
485k
    ku[0] = curve_samples(pfs, p.pole[0], 1, pfs->fixed_flat);
4231
485k
    ku[1] = curve_samples(pfs, p.pole[1], 1, pfs->fixed_flat);
4232
485k
    ku[2] = curve_samples(pfs, p.pole[2], 1, pfs->fixed_flat);
4233
485k
    ku[3] = curve_samples(pfs, p.pole[3], 1, pfs->fixed_flat);
4234
485k
    kum = max(max(ku[0], ku[1]), max(ku[2], ku[3]));
4235
#   if NOFILL_TEST
4236
    dbg_nofill = false;
4237
#   endif
4238
485k
    code = fill_wedges(pfs, ku[0], kum, p.pole[0], 1, p.c[0][0], p.c[0][1],
4239
485k
        interpatch_padding | inpatch_wedge);
4240
485k
    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
485k
            code = fill_patch(pfs, &p, kvm, kv[0], kv[3]);
4253
485k
    }
4254
485k
    if (code >= 0)
4255
485k
        code = fill_wedges(pfs, ku[3], kum, p.pole[3], 1, p.c[1][0], p.c[1][1],
4256
485k
                interpatch_padding | inpatch_wedge);
4257
485k
out:
4258
485k
    release_colors_inline(pfs, color_stack_ptr, 4);
4259
485k
    return code;
4260
485k
}