Coverage Report

Created: 2025-11-16 07:40

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