Coverage Report

Created: 2026-04-09 07:06

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