Coverage Report

Created: 2025-08-28 07:06

/src/ghostpdl/base/gdevddrw.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
/* Default polygon and image drawing device procedures */
17
#include "math_.h"
18
#include "memory_.h"
19
#include "stdint_.h"
20
#include "gx.h"
21
#include "gpcheck.h"
22
#include "gserrors.h"
23
#include "gsrect.h"
24
#include "gxfixed.h"
25
#include "gxmatrix.h"
26
#include "gxdcolor.h"
27
#include "gxdevice.h"
28
#include "gxiparam.h"
29
#include "gxgstate.h"
30
#include "gxhldevc.h"
31
#include "gdevddrw.h"
32
/*
33
#include "gxdtfill.h" - Do not remove this comment.
34
                        "gxdtfill.h" is included below.
35
*/
36
37
#define SWAP(a, b, t)\
38
117M
  (t = a, a = b, b = t)
39
40
/* ---------------- Polygon and line drawing ---------------- */
41
42
/* Define the 'remainder' analogue of fixed_mult_quo. */
43
static fixed
44
fixed_mult_rem(fixed a, fixed b, fixed c)
45
36.4M
{
46
    /* All kinds of truncation may happen here, but it's OK. */
47
36.4M
    return a * b - fixed_mult_quo(a, b, c) * c;
48
36.4M
}
49
50
/*
51
 * The trapezoid fill algorithm uses trap_line structures to keep track of
52
 * the left and right edges during the Bresenham loop.
53
 */
54
typedef struct trap_line_s {
55
        /*
56
         * h is the y extent of the line (edge.end.y - edge.start.y).
57
         * We know h > 0.
58
         */
59
    fixed h;
60
        /*
61
         * The dx/dy ratio for the line is di + df/h.
62
         * (The quotient refers to the l.s.b. of di, not fixed_1.)
63
         * We know 0 <= df < h.
64
         */
65
    int di;
66
    fixed df;
67
        /*
68
         * The intersection of the line with a scan line is x + xf/h + 1.
69
         * (The 1 refers to the least significant bit of x, not fixed_1;
70
         * similarly, the quotient refers to the l.s.b. of x.)
71
         * We know -h <= xf < 0.
72
         *
73
         * This rational value preciselly represents the mathematical line
74
         * (with no machine arithmetic error).
75
         *
76
         * Note that the fractional part is negative to simplify
77
         * some conditions in the Bresenham algorithm.
78
         * Due to that some expressions are inobvious.
79
         * We believe that it's a kind of archaic
80
         * for the modern hyperthreading architecture,
81
         * we still keep it because the code passed a huge testing
82
         * on various platforms.
83
         */
84
    fixed x, xf;
85
        /*
86
         * We increment (x,xf) by (ldi,ldf) after each scan line.
87
         * (ldi,ldf) is just (di,df) converted to fixed point.
88
         * We know 0 <= ldf < h.
89
         */
90
    fixed ldi, ldf;
91
} trap_line;
92
93
/*
94
 * The linear color trapezoid fill algorithm uses trap_color structures to keep track of
95
 * the color change during the Bresenham loop.
96
 */
97
typedef struct trap_gradient_s {
98
        frac31 *c; /* integer part of the color in frac32 units. */
99
        int32_t *f; /* the fraction part numerator */
100
        int32_t *num; /* the gradient numerator */
101
        int32_t den; /* color gradient denominator */
102
} trap_gradient;
103
104
/*
105
 * Compute the di and df members of a trap_line structure.  The x extent
106
 * (edge.end.x - edge.start.x) is a parameter; the y extent (h member)
107
 * has already been set.  Also adjust x for the initial y.
108
 */
109
static inline void
110
compute_dx(trap_line *tl, fixed xd, fixed ys)
111
209M
{
112
209M
    fixed h = tl->h;
113
209M
    int di;
114
115
209M
    if (xd >= 0) {
116
87.6M
        if (xd < h)
117
38.3M
            tl->di = 0, tl->df = xd;
118
49.3M
        else {
119
49.3M
            tl->di = di = (int)(xd / h);
120
49.3M
            tl->df = xd - di * h;
121
49.3M
            tl->x += ys * di;
122
49.3M
        }
123
122M
    } else {
124
122M
        if ((tl->df = xd + h) >= 0 /* xd >= -h */)
125
76.8M
            tl->di = -1, tl->x -= ys;
126
45.3M
        else {
127
45.3M
            tl->di = di = (int)((xd + 1) / h - 1);
128
45.3M
            tl->df = xd - di * h;
129
45.3M
            tl->x += ys * di;
130
45.3M
        }
131
122M
    }
132
209M
}
133
134
638M
#define YMULT_LIMIT (max_fixed / fixed_1)
135
136
/* Compute ldi, ldf, and xf similarly. */
137
static inline void
138
compute_ldx(trap_line *tl, fixed ys)
139
263M
{
140
263M
    int di = tl->di;
141
263M
    fixed df = tl->df;
142
263M
    fixed h = tl->h;
143
144
263M
    if ( df < YMULT_LIMIT ) {
145
263M
         if ( df == 0 )    /* vertical edge, worth checking for */
146
62.7M
             tl->ldi = int2fixed(di), tl->ldf = 0, tl->xf = -h;
147
200M
         else {
148
200M
             tl->ldi = int2fixed(di) + int2fixed(df) / h;
149
200M
             tl->ldf = int2fixed(df) % h;
150
200M
             tl->xf =
151
200M
                 (ys < fixed_1 ? ys * df % h : fixed_mult_rem(ys, df, h)) - h;
152
200M
         }
153
263M
    }
154
154k
    else {
155
154k
        tl->ldi = int2fixed(di) + fixed_mult_quo(fixed_1, df, h);
156
154k
        tl->ldf = fixed_mult_rem(fixed_1, df, h);
157
154k
        tl->xf = fixed_mult_rem(ys, df, h) - h;
158
154k
    }
159
263M
}
160
161
static inline int
162
init_gradient(trap_gradient *g, const gs_fill_attributes *fa,
163
                const gs_linear_color_edge *e, const gs_linear_color_edge *e1,
164
                const trap_line *l, fixed ybot, int num_components)
165
84.5M
{
166
84.5M
    int i;
167
84.5M
    int64_t c;
168
84.5M
    int32_t d;
169
170
84.5M
    if (e->c1 == NULL || e->c0 == NULL)
171
7.44M
        g->den = 0; /* A wedge - the color is axial along another edge. */
172
77.1M
    else {
173
77.1M
        bool ends_from_fa = (e1->c1 == NULL || e1->c0 == NULL);
174
175
77.1M
        if (ends_from_fa)
176
7.44M
            g->den = fa->yend - fa->ystart;
177
69.7M
        else {
178
69.7M
            g->den = e->end.y - e->start.y;
179
69.7M
            if (g->den != l->h)
180
0
                return_error(gs_error_unregistered); /* Must not happen. */
181
69.7M
        }
182
299M
        for (i = 0; i < num_components; i++) {
183
222M
            g->num[i] = e->c1[i] - e->c0[i];
184
222M
            c = (int64_t)g->num[i] * (uint32_t)(ybot -
185
222M
                    (ends_from_fa ? fa->ystart : e->start.y));
186
222M
            d = (int32_t)(c / g->den);
187
222M
            g->c[i] = e->c0[i] + d;
188
222M
            c -= (int64_t)d * g->den;
189
222M
            if (c < 0) {
190
61.6M
                g->c[i]--;
191
61.6M
                c += g->den;
192
61.6M
            }
193
222M
            g->f[i] = (int32_t)c;
194
222M
        }
195
77.1M
    }
196
84.5M
    return 0;
197
84.5M
}
198
199
static inline void
200
step_gradient(trap_gradient *g, int num_components)
201
894M
{
202
894M
    int i;
203
204
894M
    if (g->den == 0)
205
132M
        return;
206
2.73G
    for (i = 0; i < num_components; i++) {
207
1.97G
        int64_t fc = g->f[i] + (int64_t)g->num[i] * fixed_1;
208
1.97G
        int32_t fc32;
209
210
1.97G
        g->c[i] += (int32_t)(fc / g->den);
211
1.97G
        fc32 = (int32_t)(fc -  fc / g->den * g->den);
212
1.97G
        if (fc32 < 0) {
213
581M
            fc32 += g->den;
214
581M
            g->c[i]--;
215
581M
        }
216
1.97G
        g->f[i] = fc32;
217
1.97G
    }
218
761M
}
219
220
static inline bool
221
check_gradient_overflow(const gs_linear_color_edge *le, const gs_linear_color_edge *re)
222
68.4M
{
223
68.4M
    if (le->c1 == NULL || re->c1 == NULL) {
224
        /* A wedge doesn't use a gradient by X. */
225
8.46M
        return false;
226
60.0M
    } else {
227
        /* Check whether set_x_gradient, fill_linear_color_scanline can overflow.
228
229
           dev_proc(dev, fill_linear_color_scanline) can perform its computation in 32-bit fractions,
230
           so we assume it never overflows. Devices which implement it with no this
231
           assumption must implement the check in gx_default_fill_linear_color_trapezoid,
232
           gx_default_fill_linear_color_triangle with a function other than this one.
233
234
           Since set_x_gradient perform computations in int64_t, which provides 63 bits
235
           while multiplying a 32-bits color value to a coordinate,
236
           we must restrict the X span with 63 - 32 = 31 bits.
237
         */
238
60.0M
        int32_t xl = min(le->start.x, le->end.x);
239
60.0M
        int32_t xr = min(re->start.x, re->end.x);
240
        /* The pixel span boundaries : */
241
60.0M
        return arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE;
242
60.0M
    }
243
68.4M
}
244
245
static inline int
246
set_x_gradient_nowedge(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg,
247
             const trap_line *l, const trap_line *r, int il, int ir, int num_components)
248
61.5M
{
249
    /* Ignoring the ending coordinats fractions,
250
       so the gridient is slightly shifted to the left (in <1 'fixed' unit). */
251
61.5M
    int32_t xl = l->x - (l->xf == -l->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
252
61.5M
    int32_t xr = r->x - (r->xf == -r->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */
253
    /* The pixel span boundaries : */
254
61.5M
    int32_t x0 = int2fixed(il) + fixed_half; /* Shift to the pixel center. */
255
61.5M
    int32_t x1 = int2fixed(ir) - fixed_half; /* The center of the last pixel to paint. */
256
61.5M
    int i;
257
258
#   ifdef DEBUG
259
        if (arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE) /* Can overflow ? */
260
            return_error(gs_error_unregistered); /* Must not happen. */
261
#   endif
262
    /* We cannot compute the color of the 'ir' pixel
263
       because it can overflow 'c1' due to the pixel ir center
264
       may be greater that r->x .
265
       Therefore we base the proportion on the pixel index ir-1 (see comment to 'x1').
266
       Debugged with CET 12-14O.PS SpecialTestJ02Test12.
267
     */
268
61.5M
    xg->den = fixed2int(x1 - x0);
269
61.5M
    if (xg->den <= 0) {
270
        /* The span contains a single pixel, will construct a degenerate gradient. */
271
28.8M
        xg->den = 1; /* Safety (against zerodivide). */
272
28.8M
    }
273
230M
    for (i = 0; i < num_components; i++) {
274
        /* Ignoring the ending colors fractions,
275
           so the color gets a slightly smaller value
276
           (in <1 'frac31' unit), but it's not important due to
277
           the further conversion to [0, 1 << cinfo->comp_bits[j]],
278
           which drops the fraction anyway. */
279
168M
        int32_t cl = lg->c[i];
280
168M
        int32_t cr = rg->c[i];
281
168M
        int32_t c0 = (int32_t)(cl + ((int64_t)cr - cl) * (x0 - xl) / (xr - xl));
282
168M
        int32_t c1 = (int32_t)(cl + ((int64_t)cr - cl) * (x1 - xl) / (xr - xl));
283
284
168M
        xg->c[i] = c0;
285
168M
        xg->f[i] = 0; /* Insufficient bits to compute it better.
286
                         The color so the color gets a slightly smaller value
287
                         (in <1 'frac31' unit), but it's not important due to
288
                         the further conversion to [0, 1 << cinfo->comp_bits[j]],
289
                         which drops the fraction anyway.
290
                         So setting 0 appears pretty good and fast. */
291
168M
        xg->num[i] = c1 - c0;
292
168M
    }
293
61.5M
    return 0;
294
61.5M
}
295
296
static inline int
297
set_x_gradient(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg,
298
             const trap_line *l, const trap_line *r, int il, int ir, int num_components)
299
138M
{
300
138M
    if (lg->den == 0 || rg->den == 0) {
301
        /* A wedge doesn't use a gradient by X. */
302
76.7M
        int i;
303
304
76.7M
        xg->den = 1;
305
290M
        for (i = 0; i < num_components; i++) {
306
213M
            xg->c[i] = (lg->den == 0 ? rg->c[i] : lg->c[i]);
307
213M
            xg->f[i] = 0; /* Compatible to set_x_gradient_nowedge. */
308
213M
            xg->num[i] = 0;
309
213M
        }
310
76.7M
        return 0;
311
76.7M
    } else
312
61.5M
        return set_x_gradient_nowedge(xg, lg, rg, l, r, il, ir, num_components);
313
138M
}
314
315
/*
316
 * Fill a trapezoid.
317
 * Since we need several statically defined variants of this algorithm,
318
 * we stored it in gxdtfill.h and include it configuring with
319
 * macros defined here.
320
 */
321
4.85G
#define LINEAR_COLOR 0 /* Common for shading variants. */
322
#define EDGE_TYPE gs_fixed_edge  /* Common for non-shading variants. */
323
#define FILL_ATTRS gs_logical_operation_t  /* Common for non-shading variants. */
324
325
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_as_fd
326
#define CONTIGUOUS_FILL 0
327
50.4M
#define SWAP_AXES 1
328
50.4M
#define FILL_DIRECT 1
329
#include "gxdtfill.h"
330
#undef GX_FILL_TRAPEZOID
331
#undef CONTIGUOUS_FILL
332
#undef SWAP_AXES
333
#undef FILL_DIRECT
334
335
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_as_nd
336
#define CONTIGUOUS_FILL 0
337
385M
#define SWAP_AXES 1
338
385M
#define FILL_DIRECT 0
339
#include "gxdtfill.h"
340
#undef GX_FILL_TRAPEZOID
341
#undef CONTIGUOUS_FILL
342
#undef SWAP_AXES
343
#undef FILL_DIRECT
344
345
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_ns_fd
346
#define CONTIGUOUS_FILL 0
347
446M
#define SWAP_AXES 0
348
446M
#define FILL_DIRECT 1
349
#include "gxdtfill.h"
350
#undef GX_FILL_TRAPEZOID
351
#undef CONTIGUOUS_FILL
352
#undef SWAP_AXES
353
#undef FILL_DIRECT
354
355
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_ns_nd
356
#define CONTIGUOUS_FILL 0
357
1.47G
#define SWAP_AXES 0
358
1.47G
#define FILL_DIRECT 0
359
#include "gxdtfill.h"
360
#undef GX_FILL_TRAPEZOID
361
#undef CONTIGUOUS_FILL
362
#undef SWAP_AXES
363
#undef FILL_DIRECT
364
365
#define GX_FILL_TRAPEZOID int gx_fill_trapezoid_cf_fd
366
#define CONTIGUOUS_FILL 1
367
0
#define SWAP_AXES 0
368
0
#define FILL_DIRECT 1
369
#include "gxdtfill.h"
370
#undef GX_FILL_TRAPEZOID
371
#undef CONTIGUOUS_FILL
372
#undef SWAP_AXES
373
#undef FILL_DIRECT
374
375
#define GX_FILL_TRAPEZOID int gx_fill_trapezoid_cf_nd
376
#define CONTIGUOUS_FILL 1
377
0
#define SWAP_AXES 0
378
0
#define FILL_DIRECT 0
379
#include "gxdtfill.h"
380
#undef GX_FILL_TRAPEZOID
381
#undef CONTIGUOUS_FILL
382
#undef SWAP_AXES
383
#undef FILL_DIRECT
384
385
#undef EDGE_TYPE
386
#undef LINEAR_COLOR
387
#undef FILL_ATTRS
388
389
489M
#define LINEAR_COLOR 1 /* Common for shading variants. */
390
#define EDGE_TYPE gs_linear_color_edge /* Common for shading variants. */
391
#define FILL_ATTRS const gs_fill_attributes *  /* Common for non-shading variants. */
392
393
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_ns_lc
394
#define CONTIGUOUS_FILL 0
395
#define SWAP_AXES 0
396
13
#define FILL_DIRECT 1
397
#include "gxdtfill.h"
398
#undef GX_FILL_TRAPEZOID
399
#undef CONTIGUOUS_FILL
400
#undef SWAP_AXES
401
#undef FILL_DIRECT
402
403
#define GX_FILL_TRAPEZOID static int gx_fill_trapezoid_as_lc
404
#define CONTIGUOUS_FILL 0
405
#define SWAP_AXES 1
406
4
#define FILL_DIRECT 1
407
#include "gxdtfill.h"
408
#undef GX_FILL_TRAPEZOID
409
#undef CONTIGUOUS_FILL
410
#undef SWAP_AXES
411
#undef FILL_DIRECT
412
413
#undef EDGE_TYPE
414
#undef LINEAR_COLOR
415
#undef FILL_ATTRS
416
417
int
418
gx_default_fill_trapezoid(gx_device * dev, const gs_fixed_edge * left,
419
    const gs_fixed_edge * right, fixed ybot, fixed ytop, bool swap_axes,
420
    const gx_device_color * pdevc, gs_logical_operation_t lop)
421
228M
{
422
228M
    bool fill_direct = color_writes_pure(pdevc, lop);
423
424
228M
    if (swap_axes) {
425
25.3M
        if (dev->width != 0 && dev->non_strict_bounds == 0)
426
25.2M
        {
427
            /* Some devices init max->width to be int_max, which overflows when converted to fixed. */
428
25.2M
            int dw = dev->width > max_int_in_fixed ? max_int_in_fixed : dev->width;
429
25.2M
            if (ytop < 0)
430
3.45M
                return 0;
431
21.7M
            if (ybot < 0)
432
2.86k
                ybot = 0;
433
21.7M
            dw = int2fixed(dw);
434
21.7M
            if (ybot > dw)
435
14.4M
                return 0;
436
7.34M
            if (ytop > dw)
437
53.1k
                ytop = dw;
438
7.34M
        }
439
440
7.43M
        if (fill_direct)
441
3.14M
            return gx_fill_trapezoid_as_fd(dev, left, right, ybot, ytop, 0, pdevc, lop);
442
4.29M
        else
443
4.29M
            return gx_fill_trapezoid_as_nd(dev, left, right, ybot, ytop, 0, pdevc, lop);
444
203M
    } else {
445
203M
        if (dev->height != 0 && dev->non_strict_bounds == 0)
446
197M
        {
447
            /* Some devices init max->height to be int_max, which overflows when converted to fixed. */
448
197M
            int dh = dev->height > max_int_in_fixed ? max_int_in_fixed : dev->height;
449
197M
            if (ytop < 0)
450
31.8M
                return 0;
451
166M
            if (ybot < 0)
452
350k
                ybot = 0;
453
166M
            dh = int2fixed(dh);
454
166M
            if (ybot > dh)
455
40.2M
                return 0;
456
125M
            if (ytop > dh)
457
480k
                ytop = dh;
458
125M
        }
459
460
131M
        if (fill_direct)
461
42.7M
            return gx_fill_trapezoid_ns_fd(dev, left, right, ybot, ytop, 0, pdevc, lop);
462
88.3M
        else
463
88.3M
            return gx_fill_trapezoid_ns_nd(dev, left, right, ybot, ytop, 0, pdevc, lop);
464
131M
    }
465
228M
}
466
467
static inline int
468
fill_linear_color_trapezoid_nocheck(gx_device *dev, const gs_fill_attributes *fa,
469
        const gs_linear_color_edge *le, const gs_linear_color_edge *re)
470
68.4M
{
471
68.4M
    fixed y02 = max(le->start.y, re->start.y), ymin = max(y02, fa->clip->p.y);
472
68.4M
    fixed y13 = min(le->end.y, re->end.y), ymax = min(y13, fa->clip->q.y);
473
68.4M
    int code;
474
475
68.4M
    code = (fa->swap_axes ? gx_fill_trapezoid_as_lc : gx_fill_trapezoid_ns_lc)(dev,
476
68.4M
            le, re, ymin, ymax, 0, NULL, fa);
477
68.4M
    if (code < 0)
478
17
        return code;
479
68.4M
    return !code;
480
68.4M
}
481
482
/*  Fill a trapezoid with a linear color.
483
    [p0 : p1] - left edge, from bottom to top.
484
    [p2 : p3] - right edge, from bottom to top.
485
    The filled area is within Y-spans of both edges.
486
487
    This implemetation actually handles a bilinear color,
488
    in which the generatrix keeps a parallelizm to the X axis.
489
    In general a bilinear function doesn't keep the generatrix parallelizm,
490
    so the caller must decompose/approximate such functions.
491
492
    Return values :
493
    1 - success;
494
    0 - Too big. The area isn't filled. The client must decompose the area.
495
    <0 - error.
496
 */
497
int
498
gx_default_fill_linear_color_trapezoid(gx_device *dev, const gs_fill_attributes *fa,
499
        const gs_fixed_point *p0, const gs_fixed_point *p1,
500
        const gs_fixed_point *p2, const gs_fixed_point *p3,
501
        const frac31 *c0, const frac31 *c1,
502
        const frac31 *c2, const frac31 *c3)
503
11.3M
{
504
11.3M
    gs_linear_color_edge le, re;
505
506
11.3M
    le.start = *p0;
507
11.3M
    le.end = *p1;
508
11.3M
    le.c0 = c0;
509
11.3M
    le.c1 = c1;
510
11.3M
    le.clip_x = fa->clip->p.x;
511
11.3M
    re.start = *p2;
512
11.3M
    re.end = *p3;
513
11.3M
    re.c0 = c2;
514
11.3M
    re.c1 = c3;
515
11.3M
    re.clip_x = fa->clip->q.x;
516
11.3M
    if (check_gradient_overflow(&le, &re))
517
0
        return 0;
518
11.3M
    return fill_linear_color_trapezoid_nocheck(dev, fa, &le, &re);
519
11.3M
}
520
521
static inline int
522
fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
523
        const gs_fixed_point *p0, const gs_fixed_point *p1,
524
        const gs_fixed_point *p2,
525
        const frac31 *c0, const frac31 *c1, const frac31 *c2)
526
31.4M
{   /* p0 must be the lowest vertex. */
527
31.4M
    int code;
528
31.4M
    gs_linear_color_edge e0, e1, e2;
529
530
31.4M
    if (p0->y == p1->y)
531
1.20M
        return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p2, p1, p2, c0, c2, c1, c2);
532
30.2M
    if (p1->y == p2->y)
533
1.64M
        return gx_default_fill_linear_color_trapezoid(dev, fa, p0, p2, p0, p1, c0, c2, c0, c1);
534
28.5M
    e0.start = *p0;
535
28.5M
    e0.end = *p2;
536
28.5M
    e0.c0 = c0;
537
28.5M
    e0.c1 = c2;
538
28.5M
    e0.clip_x = fa->clip->p.x;
539
28.5M
    e1.start = *p0;
540
28.5M
    e1.end = *p1;
541
28.5M
    e1.c0 = c0;
542
28.5M
    e1.c1 = c1;
543
28.5M
    e1.clip_x = fa->clip->q.x;
544
28.5M
    if (p0->y < p1->y && p1->y < p2->y) {
545
13.8M
        e2.start = *p1;
546
13.8M
        e2.end = *p2;
547
13.8M
        e2.c0 = c1;
548
13.8M
        e2.c1 = c2;
549
13.8M
        e2.clip_x = fa->clip->q.x;
550
13.8M
        if (check_gradient_overflow(&e0, &e1))
551
0
            return 0;
552
13.8M
        if (check_gradient_overflow(&e0, &e2))
553
0
            return 0;
554
13.8M
        code = fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e1);
555
13.8M
        if (code <= 0) /* Sic! */
556
0
            return code;
557
13.8M
        return fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e2);
558
14.7M
    } else { /* p0->y < p2->y && p2->y < p1->y */
559
14.7M
        e2.start = *p2;
560
14.7M
        e2.end = *p1;
561
14.7M
        e2.c0 = c2;
562
14.7M
        e2.c1 = c1;
563
14.7M
        e2.clip_x = fa->clip->q.x;
564
14.7M
        if (check_gradient_overflow(&e0, &e1))
565
0
            return 0;
566
14.7M
        if (check_gradient_overflow(&e2, &e1))
567
0
            return 0;
568
14.7M
        code = fill_linear_color_trapezoid_nocheck(dev, fa, &e0, &e1);
569
14.7M
        if (code <= 0) /* Sic! */
570
0
            return code;
571
14.7M
        return fill_linear_color_trapezoid_nocheck(dev, fa, &e2, &e1);
572
14.7M
    }
573
28.5M
}
574
575
/*  Fill a triangle with a linear color. */
576
int
577
gx_default_fill_linear_color_triangle(gx_device *dev, const gs_fill_attributes *fa,
578
        const gs_fixed_point *p0, const gs_fixed_point *p1,
579
        const gs_fixed_point *p2,
580
        const frac31 *c0, const frac31 *c1, const frac31 *c2)
581
31.4M
{
582
31.4M
    fixed dx1 = p1->x - p0->x, dy1 = p1->y - p0->y;
583
31.4M
    fixed dx2 = p2->x - p0->x, dy2 = p2->y - p0->y;
584
585
31.4M
    if ((int64_t)dx1 * dy2 < (int64_t)dx2 * dy1) {
586
15.0M
        const gs_fixed_point *p = p1;
587
15.0M
        const frac31 *c = c1;
588
589
15.0M
        p1 = p2;
590
15.0M
        p2 = p;
591
15.0M
        c1 = c2;
592
15.0M
        c2 = c;
593
15.0M
    }
594
31.4M
    if (p0->y <= p1->y && p0->y <= p2->y)
595
14.5M
        return fill_linear_color_triangle(dev, fa, p0, p1, p2, c0, c1, c2);
596
16.8M
    if (p1->y <= p0->y && p1->y <= p2->y)
597
8.68M
        return fill_linear_color_triangle(dev, fa, p1, p2, p0, c1, c2, c0);
598
8.16M
    else
599
8.16M
        return fill_linear_color_triangle(dev, fa, p2, p0, p1, c2, c0, c1);
600
16.8M
}
601
602
/* Fill a parallelogram whose points are p, p+a, p+b, and p+a+b. */
603
/* We should swap axes to get best accuracy, but we don't. */
604
/* We must be very careful to follow the center-of-pixel rule in all cases. */
605
int
606
gx_default_fill_parallelogram(gx_device * dev,
607
                 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
608
                  const gx_device_color * pdevc, gs_logical_operation_t lop)
609
79.2M
{
610
79.2M
    fixed t;
611
79.2M
    fixed qx, qy, ym;
612
79.2M
    dev_proc_fill_trapezoid((*fill_trapezoid));
613
79.2M
    gs_fixed_edge left, right;
614
79.2M
    int code;
615
616
    /* Make a special fast check for rectangles. */
617
79.2M
    if (PARALLELOGRAM_IS_RECT(ax, ay, bx, by)) {
618
7.95M
        gs_int_rect r;
619
620
7.95M
        INT_RECT_FROM_PARALLELOGRAM(&r, px, py, ax, ay, bx, by);
621
7.95M
        return gx_fill_rectangle_device_rop(r.p.x, r.p.y, r.q.x - r.p.x,
622
7.95M
                                            r.q.y - r.p.y, pdevc, dev, lop);
623
7.95M
    }
624
    /*
625
     * Not a rectangle.  Ensure that the 'a' line is to the left of
626
     * the 'b' line.  Testing ax <= bx is neither sufficient nor
627
     * necessary: in general, we need to compare the slopes.
628
     */
629
    /* Ensure ay >= 0, by >= 0. */
630
71.2M
    if (ay < 0)
631
40.4M
        px += ax, py += ay, ax = -ax, ay = -ay;
632
71.2M
    if (by < 0)
633
16.5M
        px += bx, py += by, bx = -bx, by = -by;
634
71.2M
    qx = px + ax + bx;
635
71.2M
    if ((ax ^ bx) < 0) { /* In this case, the test ax <= bx is sufficient. */
636
42.8M
        if (ax > bx)
637
9.75M
            SWAP(ax, bx, t), SWAP(ay, by, t);
638
42.8M
    } else {     /*
639
                                 * Compare the slopes.  We know that ay >= 0, by >= 0,
640
                                 * and ax and bx have the same sign; the lines are in the
641
                                 * correct order iff
642
                                 *          ay/ax >= by/bx, or
643
                                 *          ay*bx >= by*ax
644
                                 * Eventually we can probably find a better way to test this,
645
                                 * without using floating point.
646
                                 */
647
28.4M
        if ((double)ay * bx < (double)by * ax)
648
14.7M
            SWAP(ax, bx, t), SWAP(ay, by, t);
649
28.4M
    }
650
71.2M
    fill_trapezoid = dev_proc(dev, fill_trapezoid);
651
71.2M
    qy = py + ay + by;
652
71.2M
    left.start.x = right.start.x = px;
653
71.2M
    left.start.y = right.start.y = py;
654
71.2M
    left.end.x = px + ax;
655
71.2M
    left.end.y = py + ay;
656
71.2M
    right.end.x = px + bx;
657
71.2M
    right.end.y = py + by;
658
71.2M
#define ROUNDED_SAME(p1, p2)\
659
213M
  (fixed_pixround(p1) == fixed_pixround(p2))
660
71.2M
    if (ay < by) {
661
32.5M
        if (!ROUNDED_SAME(py, left.end.y)) {
662
4.66M
            code = (*fill_trapezoid) (dev, &left, &right, py, left.end.y,
663
4.66M
                                      false, pdevc, lop);
664
4.66M
            if (code < 0)
665
0
                return code;
666
4.66M
        }
667
32.5M
        left.start = left.end;
668
32.5M
        left.end.x = qx, left.end.y = qy;
669
32.5M
        ym = right.end.y;
670
32.5M
        if (!ROUNDED_SAME(left.start.y, ym)) {
671
17.2M
            code = (*fill_trapezoid) (dev, &left, &right, left.start.y, ym,
672
17.2M
                                      false, pdevc, lop);
673
17.2M
            if (code < 0)
674
0
                return code;
675
17.2M
        }
676
32.5M
        right.start = right.end;
677
32.5M
        right.end.x = qx, right.end.y = qy;
678
38.7M
    } else {
679
38.7M
        if (!ROUNDED_SAME(py, right.end.y)) {
680
6.57M
            code = (*fill_trapezoid) (dev, &left, &right, py, right.end.y,
681
6.57M
                                      false, pdevc, lop);
682
6.57M
            if (code < 0)
683
0
                return code;
684
6.57M
        }
685
38.7M
        right.start = right.end;
686
38.7M
        right.end.x = qx, right.end.y = qy;
687
38.7M
        ym = left.end.y;
688
38.7M
        if (!ROUNDED_SAME(right.start.y, ym)) {
689
19.6M
            code = (*fill_trapezoid) (dev, &left, &right, right.start.y, ym,
690
19.6M
                                      false, pdevc, lop);
691
19.6M
            if (code < 0)
692
0
                return code;
693
19.6M
        }
694
38.7M
        left.start = left.end;
695
38.7M
        left.end.x = qx, left.end.y = qy;
696
38.7M
    }
697
71.2M
    if (!ROUNDED_SAME(ym, qy))
698
11.2M
        return (*fill_trapezoid) (dev, &left, &right, ym, qy,
699
11.2M
                                  false, pdevc, lop);
700
60.0M
    else
701
60.0M
        return 0;
702
71.2M
#undef ROUNDED_SAME
703
71.2M
}
704
705
/* Fill a triangle whose points are p, p+a, and p+b. */
706
/* We should swap axes to get best accuracy, but we don't. */
707
int
708
gx_default_fill_triangle(gx_device * dev,
709
                 fixed px, fixed py, fixed ax, fixed ay, fixed bx, fixed by,
710
                  const gx_device_color * pdevc, gs_logical_operation_t lop)
711
3.38M
{
712
3.38M
    fixed t;
713
3.38M
    fixed ym;
714
715
3.38M
    dev_proc_fill_trapezoid((*fill_trapezoid)) =
716
3.38M
        dev_proc(dev, fill_trapezoid);
717
3.38M
    gs_fixed_edge left, right;
718
3.38M
    int code;
719
720
    /* Ensure ay >= 0, by >= 0. */
721
3.38M
    if (ay < 0)
722
11.0k
        px += ax, py += ay, bx -= ax, by -= ay, ax = -ax, ay = -ay;
723
3.38M
    if (by < 0)
724
7.13k
        px += bx, py += by, ax -= bx, ay -= by, bx = -bx, by = -by;
725
    /* Ensure ay <= by. */
726
3.38M
    if (ay > by)
727
8.71k
        SWAP(ax, bx, t), SWAP(ay, by, t);
728
    /*
729
     * Make a special check for a flat bottom or top,
730
     * which we can handle with a single call on fill_trapezoid.
731
     */
732
3.38M
    left.start.x = right.start.x = px;
733
3.38M
    left.start.y = right.start.y = py;
734
3.38M
    if (ay == 0) {
735
        /* Flat top */
736
1.48M
        if (ax < 0)
737
1.30k
            left.start.x = px + ax;
738
1.48M
        else
739
1.48M
            right.start.x = px + ax;
740
1.48M
        left.end.x = right.end.x = px + bx;
741
1.48M
        left.end.y = right.end.y = py + by;
742
1.48M
        ym = py;
743
1.90M
    } else if (ay == by) {
744
        /* Flat bottom */
745
1.44M
        if (ax < bx)
746
1.43M
            left.end.x = px + ax, right.end.x = px + bx;
747
12.7k
        else
748
12.7k
            left.end.x = px + bx, right.end.x = px + ax;
749
1.44M
        left.end.y = right.end.y = py + by;
750
1.44M
        ym = py;
751
1.44M
    } else {
752
452k
        ym = py + ay;
753
452k
        if (fixed_mult_quo(bx, ay, by) < ax) {
754
            /* The 'b' line is to the left of the 'a' line. */
755
65.0k
            left.end.x = px + bx, left.end.y = py + by;
756
65.0k
            right.end.x = px + ax, right.end.y = py + ay;
757
65.0k
            code = (*fill_trapezoid) (dev, &left, &right, py, ym,
758
65.0k
                                      false, pdevc, lop);
759
65.0k
            right.start = right.end;
760
65.0k
            right.end = left.end;
761
387k
        } else {
762
            /* The 'a' line is to the left of the 'b' line. */
763
387k
            left.end.x = px + ax, left.end.y = py + ay;
764
387k
            right.end.x = px + bx, right.end.y = py + by;
765
387k
            code = (*fill_trapezoid) (dev, &left, &right, py, ym,
766
387k
                                      false, pdevc, lop);
767
387k
            left.start = left.end;
768
387k
            left.end = right.end;
769
387k
        }
770
452k
        if (code < 0)
771
0
            return code;
772
452k
    }
773
3.38M
    return (*fill_trapezoid) (dev, &left, &right, ym, right.end.y,
774
3.38M
                              false, pdevc, lop);
775
3.38M
}
776
777
/* Draw a one-pixel-wide line. */
778
int
779
gx_default_draw_thin_line(gx_device * dev,
780
                          fixed fx0, fixed fy0, fixed fx1, fixed fy1,
781
                    const gx_device_color * pdevc, gs_logical_operation_t lop,
782
                          fixed adjustx, fixed adjusty)
783
71.9M
{
784
71.9M
    int ix, iy, itox, itoy;
785
71.9M
    int epsilon;
786
787
71.9M
    return_if_interrupt(dev->memory);
788
789
    /* This function was updated in revision 10391 to fix problems with
790
     * mispositioned thin lines. This introduced a regression (see bug
791
     * 691030). The code was then reworked to behave in what we believe is
792
     * the correct manner, but this causes unacceptable problems with PCL
793
     * output. While the current PCL work is underway, we have therefore
794
     * amended this code to take note of the fill adjust values; if non-
795
     * zero (i.e. postscript) we do "the correct thing". If zero, we do
796
     * what we used to.
797
     *
798
     * The one case where this doesn't work is in the case where our PCL
799
     * implementation thickens lines slightly to try and approximate HP
800
     * printer behaviour. Here we do use a non-zero fill_adjust and hence
801
     * have differences; tests show that these are acceptable though.
802
     *
803
     * It is hoped that this difference in behaviour will be short lived.
804
     */
805
806
71.9M
    epsilon = ((adjustx | adjusty) == 0 ? fixed_epsilon : 0);
807
808
71.9M
    {
809
71.9M
        fixed h = fy1 - fy0;
810
71.9M
        fixed w = fx1 - fx0;
811
71.9M
        fixed tf;
812
71.9M
        bool swap_axes;
813
71.9M
        gs_fixed_edge left, right;
814
815
71.9M
        if ((w < 0 ? -w : w) <= (h < 0 ? -h : h)) {
816
            /* A "mostly-vertical" line */
817
39.3M
            if (h < 0)
818
18.5M
                SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
819
18.5M
                    h = -h;
820
            /* So we are plotting a trapezoid with horizontal thin edges.
821
             * If we are drawing a non-axis aligned trap, then we check
822
             * for whether a triangular extension area on the end covers an
823
             * additional pixel centre; if so, we fill an extra pixel.
824
             * If we are drawing an axis aligned trap and fill adjust is 0,
825
             * then we shouldn't need to do this.
826
             * If we are drawing an axis aligned trap, and fill adjust is non
827
             * zero, then perform the check, but with a "butt cap" rather than
828
             * a "triangle cap" region.
829
             * See bug 687721 and bug 693212 for this history of this.
830
             */
831
39.3M
            if (w == 0 && adjusty) {
832
7.35M
                int deltay;
833
7.35M
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;
834
835
7.35M
                if ((deltay > 0) && (deltay <= fixed_half))
836
3.67M
                {
837
3.67M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
838
3.67M
                                                         fixed2int_var(fy1),
839
3.67M
                                                         1,1,pdevc,dev,lop);
840
3.67M
                    if (c < 0) return c;
841
3.67M
                }
842
7.35M
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;
843
844
7.35M
                if ((deltay < 0) && (deltay >= -fixed_half))
845
3.64M
                {
846
3.64M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
847
3.64M
                                                         fixed2int_var(fy0),
848
3.64M
                                                         1,1,pdevc,dev,lop);
849
3.64M
                    if (c < 0) return c;
850
3.64M
                }
851
31.9M
            } else if (w != 0) {
852
31.9M
                int deltax, deltay;
853
31.9M
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;
854
31.9M
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;
855
856
31.9M
                if (deltax < 0) deltax=-deltax;
857
31.9M
                if ((deltay > 0) && (deltay <= fixed_half) &&
858
31.9M
                    (deltay+deltax <= fixed_half))
859
8.05M
                {
860
8.05M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
861
8.05M
                                                         fixed2int_var(fy1),
862
8.05M
                                                         1,1,pdevc,dev,lop);
863
8.05M
                    if (c < 0) return c;
864
8.05M
                }
865
31.9M
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;
866
31.9M
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;
867
868
31.9M
                if (deltax < 0) deltax=-deltax;
869
31.9M
                if ((deltay < 0) && (deltay >= -fixed_half) &&
870
31.9M
                    (-deltay+deltax <= fixed_half))
871
7.90M
                {
872
7.90M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
873
7.90M
                                                         fixed2int_var(fy0),
874
7.90M
                                                         1,1,pdevc,dev,lop);
875
7.90M
                    if (c < 0) return c;
876
7.90M
                }
877
31.9M
            }
878
            /* Can we treat it as a vertical rectangle? */
879
39.3M
            ix   = fixed2int_var(fx0-epsilon);
880
39.3M
            itox = fixed2int_var(fx1-epsilon);
881
39.3M
            if (itox == ix) {
882
                /* Figure out the start/height, allowing for our "covers
883
                 * centre of pixel" rule. */
884
15.7M
                iy   = fixed2int_var(fy0+fixed_half-fixed_epsilon);
885
15.7M
                itoy = fixed2int_var(fy1+fixed_half-fixed_epsilon);
886
15.7M
                itoy = itoy - iy;
887
15.7M
                if (itoy <= 0) {
888
                    /* Zero height; drawing this as a trapezoid wouldn't
889
                     * fill any pixels, so just exit. */
890
1.60M
                    return 0;
891
1.60M
                }
892
14.1M
                return gx_fill_rectangle_device_rop(ix, iy, 1, itoy,
893
15.7M
                                                    pdevc, dev, lop);
894
15.7M
            }
895
23.6M
            left.start.x = fx0 - fixed_half + fixed_epsilon - epsilon;
896
23.6M
            right.start.x = left.start.x + fixed_1;
897
23.6M
            left.end.x = fx1 - fixed_half + fixed_epsilon - epsilon;
898
23.6M
            right.end.x = left.end.x + fixed_1;
899
23.6M
            left.start.y = right.start.y = fy0;
900
23.6M
            left.end.y = right.end.y = fy1;
901
23.6M
            swap_axes = false;
902
32.6M
        } else {
903
            /* A "mostly-horizontal" line */
904
32.6M
            if (w < 0)
905
15.8M
                SWAP(fx0, fx1, tf), SWAP(fy0, fy1, tf),
906
15.8M
                    w = -w;
907
            /* So we are plotting a trapezoid with vertical thin edges
908
             * Check for whether a triangular extension area on the end
909
             * covers an additional pixel centre. */
910
32.6M
            if (h == 0 && adjustx) {
911
12.4M
                int deltax;
912
12.4M
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;
913
914
12.4M
                if ((deltax > 0) && (deltax <= fixed_half))
915
5.82M
                {
916
5.82M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
917
5.82M
                                                         fixed2int_var(fy1),
918
5.82M
                                                         1,1,pdevc,dev,lop);
919
5.82M
                    if (c < 0) return c;
920
5.82M
                }
921
12.4M
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;
922
923
12.4M
                if ((deltax < 0) && (deltax >= -fixed_half))
924
5.77M
                {
925
5.77M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
926
5.77M
                                                         fixed2int_var(fy0),
927
5.77M
                                                         1,1,pdevc,dev,lop);
928
5.77M
                    if (c < 0) return c;
929
5.77M
                }
930
20.1M
            } else if (h != 0) {
931
20.1M
                int deltax, deltay;
932
20.1M
                deltax = int2fixed(fixed2int_var(fx1)) + fixed_half -fx1;
933
20.1M
                deltay = int2fixed(fixed2int_var(fy1)) + fixed_half -fy1;
934
935
20.1M
                if (deltay < 0) deltay=-deltay;
936
20.1M
                if ((deltax > 0) && (deltax <= fixed_half) &&
937
20.1M
                    (deltax+deltay <= fixed_half))
938
5.01M
                {
939
5.01M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx1),
940
5.01M
                                                         fixed2int_var(fy1),
941
5.01M
                                                         1,1,pdevc,dev,lop);
942
5.01M
                    if (c < 0) return c;
943
5.01M
                }
944
20.1M
                deltax = int2fixed(fixed2int_var(fx0)) + fixed_half -fx0;
945
20.1M
                deltay = int2fixed(fixed2int_var(fy0)) + fixed_half -fy0;
946
947
20.1M
                if (deltay < 0) deltay=-deltay;
948
20.1M
                if ((deltax < 0) && (deltax >= -fixed_half) &&
949
20.1M
                    (-deltax+deltay <= fixed_half))
950
5.00M
                {
951
5.00M
                    int c = gx_fill_rectangle_device_rop(fixed2int_var(fx0),
952
5.00M
                                                         fixed2int_var(fy0),
953
5.00M
                                                         1,1,pdevc,dev,lop);
954
5.00M
                    if (c < 0) return c;
955
5.00M
                }
956
20.1M
            }
957
            /* Can we treat this as a horizontal rectangle? */
958
32.6M
            iy   = fixed2int_var(fy0 - epsilon);
959
32.6M
            itoy = fixed2int_var(fy1 - epsilon);
960
32.6M
            if (itoy == iy) {
961
                /* Figure out the start/width, allowing for our "covers
962
                * centre of pixel" rule. */
963
16.8M
                ix   = fixed2int_var(fx0+fixed_half-fixed_epsilon);
964
16.8M
                itox = fixed2int_var(fx1+fixed_half-fixed_epsilon);
965
16.8M
                itox = itox - ix;
966
16.8M
                if (itox <= 0) {
967
                    /* Zero width; drawing this as a trapezoid wouldn't
968
                     * fill any pixels, so just exit. */
969
1.74M
                    return 0;
970
1.74M
                }
971
15.1M
                return gx_fill_rectangle_device_rop(ix, iy, itox, 1,
972
16.8M
                                                    pdevc, dev, lop);
973
16.8M
            }
974
15.7M
            left.start.x = fy0 - fixed_half + fixed_epsilon - epsilon;
975
15.7M
            right.start.x = left.start.x + fixed_1;
976
15.7M
            left.end.x = fy1 - fixed_half + fixed_epsilon - epsilon;
977
15.7M
            right.end.x = left.end.x + fixed_1;
978
15.7M
            left.start.y = right.start.y = fx0;
979
15.7M
            left.end.y = right.end.y = fx1;
980
15.7M
            swap_axes = true;
981
15.7M
        }
982
39.3M
        return (*dev_proc(dev, fill_trapezoid)) (dev, &left, &right,
983
39.3M
                                                 left.start.y, left.end.y,
984
39.3M
                                                 swap_axes, pdevc, lop);
985
71.9M
    }
986
71.9M
}
987
988
/* ---------------- Image drawing ---------------- */
989
990
/* GC structures for image enumerator */
991
public_st_gx_image_enum_common();
992
993
static
994
39
ENUM_PTRS_WITH(image_enum_common_enum_ptrs, gx_image_enum_common_t *eptr)
995
13
    return 0;
996
13
case 0: return ENUM_OBJ(gx_device_enum_ptr(eptr->dev));
997
39
ENUM_PTR(1,gx_image_enum_common_t,pgs);
998
39
ENUM_PTRS_END
999
1000
13
static RELOC_PTRS_WITH(image_enum_common_reloc_ptrs, gx_image_enum_common_t *eptr)
1001
13
{
1002
13
    eptr->dev = gx_device_reloc_ptr(eptr->dev, gcst);
1003
13
    RELOC_PTR(gx_image_enum_common_t,pgs);
1004
13
}
1005
13
RELOC_PTRS_END
1006
1007
int
1008
gx_default_begin_typed_image(gx_device * dev,
1009
                        const gs_gstate * pgs, const gs_matrix * pmat,
1010
                   const gs_image_common_t * pic, const gs_int_rect * prect,
1011
              const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
1012
                      gs_memory_t * memory, gx_image_enum_common_t ** pinfo)
1013
2.35M
{
1014
2.35M
    return (*pic->type->begin_typed_image)
1015
2.35M
        (dev, pgs, pmat, pic, prect, pdcolor, pcpath, memory, pinfo);
1016
2.35M
}
1017
1018
int
1019
gx_default_fillpage(gx_device *dev, gs_gstate * pgs, gx_device_color *pdevc)
1020
3.07M
{
1021
3.07M
    bool hl_color_available = gx_hld_is_hl_color_available(pgs, pdevc);
1022
3.07M
    int code = 0;
1023
1024
    /* Fill the page directly, ignoring clipping. */
1025
    /* Use the default RasterOp. */
1026
3.07M
    if (hl_color_available) {
1027
13.6k
        gs_fixed_rect rect;
1028
1029
13.6k
        rect.p.x = rect.p.y = 0;
1030
13.6k
        rect.q.x = int2fixed(dev->width);
1031
13.6k
        rect.q.y = int2fixed(dev->height);
1032
13.6k
        code = dev_proc(dev, fill_rectangle_hl_color)(dev,
1033
13.6k
                &rect, (const gs_gstate *)pgs, pdevc, NULL);
1034
13.6k
    }
1035
3.07M
    if (!hl_color_available || code == gs_error_rangecheck)
1036
3.05M
        code = gx_fill_rectangle_device_rop(0, 0, dev->width, dev->height, pdevc, dev, lop_default);
1037
3.07M
    return code;
1038
3.07M
}