Coverage Report

Created: 2025-12-31 07:31

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