Coverage Report

Created: 2026-08-08 08:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gxscanc.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* Path stroking procedures for Ghostscript library */
17
#include "math_.h"
18
#include "memory_.h"
19
#include "string_.h"
20
#include "gx.h"
21
#include "gpcheck.h"
22
#include "gserrors.h"
23
#include "gsdcolor.h"
24
#include "gsptype1.h"
25
#include "gxfixed.h"
26
#include "gxfarith.h"
27
#include "gxmatrix.h"
28
#include "gscoord.h"
29
#include "gsdevice.h"
30
#include "gxdevice.h"
31
#include "gxhttile.h"
32
#include "gxgstate.h"
33
#include "gzline.h"
34
#include "gzpath.h"
35
#include "gzcpath.h"
36
#include "gxpaint.h"
37
#include "gxscanc.h"
38
#include "gxfill.h"
39
#include "gxdcolor.h"
40
#include "assert_.h"
41
#include <stdlib.h>             /* for qsort */
42
#include <limits.h>             /* For INT_MAX */
43
44
/* Overview of the scan conversion algorithm.
45
 *
46
 * The normal scan conversion algorithm runs through a path, converting
47
 * it into a sequence of edges. It then runs through those edges from
48
 * top to bottom keeping a list of which ones are "active", and ordering
49
 * them so that it can read out a list of intersection points from left
50
 * to right across any given scanline (or scan "band" when working with
51
 * trapezoids).
52
 *
53
 * This scan conversion algorithm avoids the need to maintain an active
54
 * line list, and to repeatedly re-sort lines. It is thus faster, at
55
 * the cost of using more memory, and not being able to cope with
56
 * trapezoids.
57
 *
58
 * Conceptually, the idea is to make an (initially empty) table. Each
59
 * row of the table holds the set of intersection data for a given
60
 * scanline. We therefore just need to run through the path once,
61
 * decomposing it to a sequence of edges. We then step along each edge
62
 * adding intersection information into each row of the table as we go.
63
 * Each piece of intersection information includes the point at which
64
 * the edge crosses the scanline, and the direction in which it does so
65
 * (up or down).
66
 *
67
 * At the end of this process, we can then sort each rows data, and
68
 * simply 'fill in' the scanline according to the winding rule.
69
 *
70
 * This copes well with 'centre of a pixel' fill modes, but 'any part
71
 * of a pixel' requires some extra work. Let's describe 'centre of a
72
 * pixel' first.
73
 *
74
 * Assume we have a path with n segments in, and a bbox that crosses
75
 * a region x wide, y high.
76
 *
77
 * 1) Create a table, A, 1 int entry per scan line. Run through the path,
78
 * segment by segment counting how many intersections occur on each
79
 * scanline. (O(y * n))
80
 *
81
 * 2) Create a table, B, with as many entries per scanline as determined in
82
 * the table A. (O(y * n))
83
 *
84
 * [Each entry is a (xcoord,direction) tuple. xcoord = the xcoord where
85
 * an edge crosses the horizontal line through the middle of the pixel.
86
 * direction = 0 if the edge is rising, 1 if falling.]
87
 *
88
 * 3) Run through the path segment by segment, inserting entries for each
89
 * scanline intersection in table B. (O(y * n))
90
 *
91
 * 4) Sort the scanline intersections of table B (on left,right,direction).
92
 * (O(y * n log n) for current code)
93
 *
94
 * 5) Filter the scanline intersections according to the winding rule.
95
 * (O(y * n))
96
 *
97
 * 6) Fill rectangles according to each set of scanline intersections.
98
 * (O(y * n))
99
 *
100
 * So worst case complexity (when every segment crosses every scanline) is
101
 * O(y * n log n).
102
 *
103
 * NOTE: If we use a binary comparison based sort, then the best we can manage
104
 * is n log n for step 4. If we use a radix based sort, we can get O(n).
105
 * Consider this if we ever need it.
106
 *
107
 * In order to cope with 'any part of a pixel' it no longer suffices
108
 * to keep a single intersection point for each scanline intersection.
109
 * Instead we keep the interval of a scanline that the edge intersects.
110
 * Thus each entry is a (left,right,direction) tuple. left = the
111
 * leftmost point at which this edge intersects this scanline. right =
112
 * the rightmost point at which this edge intersects this scanline.
113
 * direction = 0 for rising edges, 1 for falling edges.
114
 *
115
 * The rest of the algorithm is unchanged, apart from additional care
116
 * being required when filling the scanlines to allow for the fact
117
 * that edges are no longer point intersections.
118
 *
119
 * The first set of routines (gx_scan_convert and gx_fill_edgebuffer)
120
 * implement the "pixel centre" covered routines by drawing rectangle
121
 * high scanlines at a time. The second set of routines
122
 * (gx_scan_convert_app and gx_fill_edgebuffer_app) is the equivalent,
123
 * for "Any Part of Pixel" covered.
124
 *
125
 * The third and fourth are the same things, but using trapezoids
126
 * that can be multiple scanlines high rather than scanlines.
127
 *
128
 * In order to do trapezoid extraction, we extend the edge intersection
129
 * information to be (left,right,id,direction) (for the "centre pixel"
130
 * variants) and (left,left_id,right,right_id,direction) (for the "any
131
 * part of a pixel" variants). The 'id' is a int that is guaranteed
132
 * unique for each flattened line in path.
133
 *
134
 * If we spot that each scanlines data has the same set of ids in the
135
 * same order, then we can 'collate' them into a trapezoid.
136
 */
137
138
/* NOTE: code in this file assumes that fixed and int can be used
139
 * interchangably. */
140
141
#undef DEBUG_SCAN_CONVERTER
142
#undef DEBUG_OUTPUT_SC_AS_PS
143
144
typedef int64_t fixed64;
145
146
enum
147
{
148
    DIRN_UNSET = -1,
149
    DIRN_UP = 0,
150
    DIRN_DOWN = 1
151
};
152
153
/* Centre of a pixel routines */
154
155
static int intcmp(const void *a, const void *b)
156
1.72M
{
157
1.72M
    return *((int*)a) - *((int *)b);
158
1.72M
}
159
160
#if defined(DEBUG_SCAN_CONVERTER)
161
int debugging_scan_converter = 1;
162
163
static void
164
gx_edgebuffer_print(gx_edgebuffer * edgebuffer)
165
{
166
    int i;
167
168
    dlprintf1("Edgebuffer %x\n", edgebuffer);
169
    dlprintf4("xmin=%x xmax=%x base=%x height=%x\n",
170
              edgebuffer->xmin, edgebuffer->xmax, edgebuffer->base, edgebuffer->height);
171
    for (i=0; i < edgebuffer->height; i++) {
172
        int  offset = edgebuffer->index[i];
173
        int *row    = &edgebuffer->table[offset];
174
        int count   = *row++;
175
        dlprintf3("%d @ %d: %d =", i, offset, count);
176
        while (count-- > 0) {
177
            int v = *row++;
178
            dlprintf2(" %x:%d", v&~1, v&1);
179
        }
180
        dlprintf("\n");
181
    }
182
}
183
#endif
184
185
#ifdef DEBUG_OUTPUT_SC_AS_PS
186
static void coord(const char *str, fixed x, fixed y)
187
{
188
    if (x > 0)
189
        dlprintf1(" 16#%x ", x);
190
    else
191
        dlprintf1("0 16#%x sub ", -x);
192
    if (y > 0)
193
        dlprintf1(" 16#%x ", y);
194
    else
195
        dlprintf1("0 16#%x sub ", -y);
196
    dlprintf1("%s %%PS\n", str);
197
}
198
#endif
199
200
typedef void (zero_filler_fn)(int *, const fixed *);
201
202
static void mark_line_zero(fixed sx, fixed ex, fixed *zf)
203
29.2k
{
204
29.2k
    if (sx < zf[0])
205
0
        zf[0] = sx;
206
29.2k
    if (ex < zf[0])
207
3.15k
        zf[0] = ex;
208
29.2k
    if (sx > zf[1])
209
0
        zf[1] = sx;
210
29.2k
    if (ex > zf[1])
211
5.20k
        zf[1] = ex;
212
29.2k
}
213
214
static void mark_curve_zero(fixed sx, fixed c1x, fixed c2x, fixed ex, int depth, fixed *zf)
215
0
{
216
0
    fixed ax = (sx + c1x)>>1;
217
0
    fixed bx = (c1x + c2x)>>1;
218
0
    fixed cx = (c2x + ex)>>1;
219
0
    fixed dx = (ax + bx)>>1;
220
0
    fixed fx = (bx + cx)>>1;
221
0
    fixed gx = (dx + fx)>>1;
222
223
0
    assert(depth >= 0);
224
0
    if (depth == 0)
225
0
        mark_line_zero(sx, ex, zf);
226
0
    else {
227
0
        depth--;
228
0
        mark_curve_zero(sx, ax, dx, gx, depth, zf);
229
0
        mark_curve_zero(gx, fx, cx, ex, depth, zf);
230
0
    }
231
0
}
232
233
static void mark_curve_big_zero(fixed64 sx, fixed64 c1x, fixed64 c2x, fixed64 ex, int depth, fixed *zf)
234
0
{
235
0
    fixed64 ax = (sx + c1x)>>1;
236
0
    fixed64 bx = (c1x + c2x)>>1;
237
0
    fixed64 cx = (c2x + ex)>>1;
238
0
    fixed64 dx = (ax + bx)>>1;
239
0
    fixed64 fx = (bx + cx)>>1;
240
0
    fixed64 gx = (dx + fx)>>1;
241
242
0
    assert(depth >= 0);
243
0
    if (depth == 0)
244
0
        mark_line_zero((fixed)sx, (fixed)ex, zf);
245
0
    else {
246
0
        depth--;
247
0
        mark_curve_big_zero(sx, ax, dx, gx, depth, zf);
248
0
        mark_curve_big_zero(gx, fx, cx, ex, depth, zf);
249
0
    }
250
0
}
251
252
static void mark_curve_top_zero(fixed sx, fixed c1x, fixed c2x, fixed ex, int depth, fixed *zf)
253
0
{
254
0
    fixed test = (sx^(sx<<1))|(c1x^(c1x<<1))|(c2x^(c2x<<1))|(ex^(ex<<1));
255
256
0
    if (test < 0)
257
0
        mark_curve_big_zero(sx, c1x, c2x, ex, depth, zf);
258
0
    else
259
0
        mark_curve_zero(sx, c1x, c2x, ex, depth, zf);
260
0
}
261
262
static int
263
zero_case(gx_device      * gs_restrict pdev,
264
          gx_path        * gs_restrict path,
265
          gs_fixed_rect  * gs_restrict ibox,
266
          int            * gs_restrict index,
267
          int            * gs_restrict table,
268
          fixed                        fixed_flat,
269
          zero_filler_fn *             fill)
270
6.06k
{
271
6.06k
    const subpath *psub;
272
6.06k
    fixed zf[2];
273
274
    /* Step 2 continued: Now we run through the path, filling in the real
275
     * values. */
276
12.5k
    for (psub = path->first_subpath; psub != 0;) {
277
6.51k
        const segment *pseg = (const segment *)psub;
278
6.51k
        fixed ex = pseg->pt.x;
279
6.51k
        fixed sy = pseg->pt.y;
280
6.51k
        fixed ix = ex;
281
6.51k
        int iy = fixed2int(pseg->pt.y);
282
283
6.51k
        zf[0] = ex;
284
6.51k
        zf[1] = ex;
285
286
29.2k
        while ((pseg = pseg->next) != 0 &&
287
23.1k
               pseg->type != s_start
288
22.7k
            ) {
289
22.7k
            fixed sx = ex;
290
22.7k
            ex = pseg->pt.x;
291
292
22.7k
            switch (pseg->type) {
293
0
                default:
294
0
                case s_start: /* Should never happen */
295
0
                case s_dash:  /* We should never be seeing a dash here */
296
0
                    assert("This should never happen" == NULL);
297
0
                    break;
298
0
                case s_curve: {
299
0
                    const curve_segment *const pcur = (const curve_segment *)pseg;
300
0
                    int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat);
301
302
0
                    mark_curve_top_zero(sx, pcur->p1.x, pcur->p2.x, ex, k, zf);
303
0
                    break;
304
0
                }
305
0
                case s_gap:
306
17.3k
                case s_line:
307
22.7k
                case s_line_close:
308
22.7k
                    mark_line_zero(sx, ex, zf);
309
22.7k
                    break;
310
22.7k
            }
311
22.7k
        }
312
        /* And close any open segments */
313
6.51k
        mark_line_zero(ex, ix, zf);
314
6.51k
        fill(&table[index[iy-ibox->p.y]], zf);
315
6.51k
        psub = (const subpath *)pseg;
316
6.51k
    }
317
318
6.06k
    return 0;
319
6.06k
}
320
321
static void mark_line(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index)
322
172M
{
323
172M
    int64_t delta;
324
172M
    int iy, ih;
325
172M
    fixed clip_sy, clip_ey;
326
172M
    int dirn = DIRN_UP;
327
172M
    int *row;
328
329
#ifdef DEBUG_SCAN_CONVERTER
330
    if (debugging_scan_converter)
331
        dlprintf6("Marking line from %x,%x to %x,%x (%x,%x)\n", sx, sy, ex, ey, fixed2int(sy + fixed_half-1) - base_y, fixed2int(ey + fixed_half-1) - base_y);
332
#endif
333
#ifdef DEBUG_OUTPUT_SC_AS_PS
334
    dlprintf("0.001 setlinewidth 0 0 0 setrgbcolor %%PS\n");
335
    coord("moveto", sx, sy);
336
    coord("lineto", ex, ey);
337
    dlprintf("stroke %%PS\n");
338
#endif
339
340
172M
    if (fixed2int(sy + fixed_half-1) == fixed2int(ey + fixed_half-1))
341
152M
        return;
342
20.0M
    if (sy > ey) {
343
11.0M
        int t;
344
11.0M
        t = sy; sy = ey; ey = t;
345
11.0M
        t = sx; sx = ex; ex = t;
346
11.0M
        dirn = DIRN_DOWN;
347
11.0M
    }
348
    /* Lines go from sy to ey, closed at the start, open at the end. */
349
    /* We clip them to a region to make them closed at both ends. */
350
    /* Thus the first scanline marked (>= sy) is: */
351
20.0M
    clip_sy = ((sy + fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
352
    /* The last scanline marked (< ey) is: */
353
20.0M
    clip_ey = ((ey - fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
354
    /* Now allow for banding */
355
20.0M
    if (clip_sy < int2fixed(base_y) + fixed_half)
356
9.10M
        clip_sy = int2fixed(base_y) + fixed_half;
357
20.0M
    if (ey <= clip_sy)
358
8.74M
        return;
359
11.2M
    if (clip_ey > int2fixed(base_y + height - 1) + fixed_half)
360
3.76M
        clip_ey = int2fixed(base_y + height - 1) + fixed_half;
361
11.2M
    if (sy > clip_ey)
362
3.38M
        return;
363
7.88M
    delta = (int64_t)clip_sy - (int64_t)sy;
364
7.88M
    if (delta > 0)
365
7.17M
    {
366
7.17M
        int64_t dx = (int64_t)ex - (int64_t)sx;
367
7.17M
        int64_t dy = (int64_t)ey - (int64_t)sy;
368
7.17M
        int advance = (int)((dx * delta + (dy>>1)) / dy);
369
7.17M
        sx += advance;
370
7.17M
        sy += delta;
371
7.17M
    }
372
7.88M
    delta = (int64_t)ey - (int64_t)clip_ey;
373
7.88M
    if (delta > 0)
374
7.88M
    {
375
7.88M
        int64_t dx = (int64_t)ex - (int64_t)sx;
376
7.88M
        int64_t dy = (int64_t)ey - (int64_t)sy;
377
7.88M
        int advance = (int)((dx * delta + (dy>>1)) / dy);
378
7.88M
        ex -= advance;
379
7.88M
        ey -= delta;
380
7.88M
    }
381
7.88M
    ex -= sx;
382
7.88M
    ey -= sy;
383
7.88M
    ih = fixed2int(ey);
384
7.88M
    assert(ih >= 0);
385
7.88M
    iy = fixed2int(sy) - base_y;
386
#ifdef DEBUG_SCAN_CONVERTER
387
    if (debugging_scan_converter)
388
        dlprintf2("    iy=%x ih=%x\n", iy, ih);
389
#endif
390
7.88M
    assert(iy >= 0 && iy < height);
391
    /* We always cross at least one scanline */
392
7.88M
    row = &table[index[iy]];
393
7.88M
    *row = (*row)+1; /* Increment the count */
394
7.88M
    row[*row] = (sx&~1) | dirn;
395
7.88M
    if (ih == 0)
396
6.28M
        return;
397
1.60M
    if (ex >= 0) {
398
964k
        int x_inc, n_inc, f;
399
400
        /* We want to change sx by ex in ih steps. So each step, we add
401
         * ex/ih to sx. That's x_inc + n_inc/ih.
402
         */
403
964k
        x_inc = ex/ih;
404
964k
        n_inc = ex-(x_inc*ih);
405
964k
        f     = ih>>1;
406
964k
        delta = ih;
407
6.58M
        do {
408
6.58M
            int count;
409
6.58M
            iy++;
410
6.58M
            sx += x_inc;
411
6.58M
            f  -= n_inc;
412
6.58M
            if (f < 0) {
413
1.13M
                f += ih;
414
1.13M
                sx++;
415
1.13M
            }
416
6.58M
            assert(iy >= 0 && iy < height);
417
6.58M
            row = &table[index[iy]];
418
6.58M
            count = *row = (*row)+1; /* Increment the count */
419
6.58M
            row[count] = (sx&~1) | dirn;
420
6.58M
        } while (--delta);
421
964k
    } else {
422
635k
        int x_dec, n_dec, f;
423
424
635k
        ex = -ex;
425
        /* We want to change sx by ex in ih steps. So each step, we subtract
426
         * ex/ih from sx. That's x_dec + n_dec/ih.
427
         */
428
635k
        x_dec = ex/ih;
429
635k
        n_dec = ex-(x_dec*ih);
430
635k
        f     = ih>>1;
431
635k
        delta = ih;
432
5.77M
        do {
433
5.77M
            int count;
434
5.77M
            iy++;
435
5.77M
            sx -= x_dec;
436
5.77M
            f  -= n_dec;
437
5.77M
            if (f < 0) {
438
2.96M
                f += ih;
439
2.96M
                sx--;
440
2.96M
            }
441
5.77M
            assert(iy >= 0 && iy < height);
442
5.77M
            row = &table[index[iy]];
443
5.77M
            count = *row = (*row)+1; /* Increment the count */
444
5.77M
            row[count] = (sx&~1) | dirn;
445
5.77M
        } while (--delta);
446
635k
    }
447
1.60M
}
448
449
static void mark_curve(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int depth)
450
0
{
451
0
    fixed ax = (sx + c1x)>>1;
452
0
    fixed ay = (sy + c1y)>>1;
453
0
    fixed bx = (c1x + c2x)>>1;
454
0
    fixed by = (c1y + c2y)>>1;
455
0
    fixed cx = (c2x + ex)>>1;
456
0
    fixed cy = (c2y + ey)>>1;
457
0
    fixed dx = (ax + bx)>>1;
458
0
    fixed dy = (ay + by)>>1;
459
0
    fixed fx = (bx + cx)>>1;
460
0
    fixed fy = (by + cy)>>1;
461
0
    fixed gx = (dx + fx)>>1;
462
0
    fixed gy = (dy + fy)>>1;
463
464
0
    assert(depth >= 0);
465
0
    if (depth == 0)
466
0
        mark_line(sx, sy, ex, ey, base_y, height, table, index);
467
0
    else {
468
0
        depth--;
469
0
        mark_curve(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, depth);
470
0
        mark_curve(gx, gy, fx, fy, cx, cy, ex, ey, base_y, height, table, index, depth);
471
0
    }
472
0
}
473
474
static void mark_curve_big(fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, fixed base_y, fixed height, int *table, int *index, int depth)
475
0
{
476
0
    fixed64 ax = (sx + c1x)>>1;
477
0
    fixed64 ay = (sy + c1y)>>1;
478
0
    fixed64 bx = (c1x + c2x)>>1;
479
0
    fixed64 by = (c1y + c2y)>>1;
480
0
    fixed64 cx = (c2x + ex)>>1;
481
0
    fixed64 cy = (c2y + ey)>>1;
482
0
    fixed64 dx = (ax + bx)>>1;
483
0
    fixed64 dy = (ay + by)>>1;
484
0
    fixed64 fx = (bx + cx)>>1;
485
0
    fixed64 fy = (by + cy)>>1;
486
0
    fixed64 gx = (dx + fx)>>1;
487
0
    fixed64 gy = (dy + fy)>>1;
488
489
0
    assert(depth >= 0);
490
0
    if (depth == 0)
491
0
        mark_line((fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, base_y, height, table, index);
492
0
    else {
493
0
        depth--;
494
0
        mark_curve_big(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, depth);
495
0
        mark_curve_big(gx, gy, fx, fy, cx, cy, ex, ey, base_y, height, table, index, depth);
496
0
    }
497
0
}
498
499
static void mark_curve_top(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int depth)
500
0
{
501
0
    fixed test = (sx^(sx<<1))|(sy^(sy<<1))|(c1x^(c1x<<1))|(c1y^(c1y<<1))|(c2x^(c2x<<1))|(c2y^(c2y<<1))|(ex^(ex<<1))|(ey^(ey<<1));
502
503
0
    if (test < 0)
504
0
        mark_curve_big(sx, sy, c1x, c1y, c2x, c2y, ex, ey, base_y, height, table, index, depth);
505
0
    else
506
0
        mark_curve(sx, sy, c1x, c1y, c2x, c2y, ex, ey, base_y, height, table, index, depth);
507
0
}
508
509
static int make_bbox(gx_path       * path,
510
               const gs_fixed_rect * clip,
511
                     gs_fixed_rect * bbox,
512
                     gs_fixed_rect * ibox,
513
                     fixed           adjust)
514
15.3M
{
515
15.3M
    int           code;
516
15.3M
    int           ret = 0;
517
518
    /* Find the bbox - fixed */
519
15.3M
    code = gx_path_bbox(path, bbox);
520
15.3M
    if (code < 0)
521
0
        return code;
522
523
15.3M
    if (bbox->p.y == bbox->q.y) {
524
        /* Zero height path */
525
6.43k
        if (!clip ||
526
6.43k
            (bbox->p.y >= clip->p.y && bbox->q.y <= clip->q.y)) {
527
            /* Either we're not clipping, or we are vertically inside the clip */
528
6.29k
            if (clip) {
529
6.29k
                if (bbox->p.x < clip->p.x)
530
464
                    bbox->p.x = clip->p.x;
531
6.29k
                if (bbox->q.x > clip->q.x)
532
403
                    bbox->q.x = clip->q.x;
533
6.29k
            }
534
6.29k
            if (bbox->p.x <= bbox->q.x) {
535
                /* Zero height rectangle, not clipped completely away */
536
6.06k
                ret = 1;
537
6.06k
            }
538
6.29k
        }
539
6.43k
    }
540
541
15.3M
    if (clip) {
542
15.3M
        if (bbox->p.y < clip->p.y)
543
4.58M
            bbox->p.y = clip->p.y;
544
15.3M
        if (bbox->q.y > clip->q.y)
545
4.55M
            bbox->q.y = clip->q.y;
546
15.3M
    }
547
548
    /* Convert to bbox - int */
549
15.3M
    ibox->p.x = fixed2int(bbox->p.x+adjust-(adjust?1:0));
550
15.3M
    ibox->p.y = fixed2int(bbox->p.y+adjust-(adjust?1:0));
551
15.3M
    ibox->q.x = fixed2int(bbox->q.x-adjust+fixed_1);
552
15.3M
    ibox->q.y = fixed2int(bbox->q.y-adjust+fixed_1);
553
554
15.3M
    return ret;
555
15.3M
}
556
557
static inline int
558
make_table_template(gx_device     * pdev,
559
                    gx_path       * path,
560
                    gs_fixed_rect * ibox,
561
                    int             intersection_size,
562
                    int             adjust,
563
                    int           * scanlinesp,
564
                    int          ** indexp,
565
                    int          ** tablep)
566
15.2M
{
567
15.2M
    int             scanlines;
568
15.2M
    const subpath * gs_restrict psub;
569
15.2M
    int           * gs_restrict index;
570
15.2M
    int           * gs_restrict table;
571
15.2M
    int             i;
572
15.2M
    int64_t         offset;
573
15.2M
    int             delta;
574
15.2M
    fixed           base_y;
575
576
15.2M
    *scanlinesp = 0;
577
15.2M
    *indexp     = NULL;
578
15.2M
    *tablep     = NULL;
579
580
15.2M
    if (pdev->max_fill_band != 0)
581
0
        ibox->p.y &= ~(pdev->max_fill_band-1);
582
15.2M
    base_y = ibox->p.y;
583
584
    /* Previously we took adjust as a fixed distance to add to miny/maxy
585
     * to allow for the expansion due to 'any part of a pixel'. This causes
586
     * problems with over/underflow near INT_MAX/INT_MIN, so instead we
587
     * take adjust as boolean telling us whether to expand y by 1 or not, and
588
     * then adjust the assignments into the index as appropriate. This
589
     * solves Bug 697970. */
590
591
    /* Step 1: Make us a table */
592
15.2M
    scanlines = ibox->q.y-base_y;
593
    /* +1+adjust simplifies the loop below */
594
15.2M
    index = (int *)gs_alloc_bytes(pdev->memory,
595
15.2M
                                  (size_t)(scanlines+1+adjust) * sizeof(*index),
596
15.2M
                                  "scanc index buffer");
597
15.2M
    if (index == NULL)
598
0
        return_error(gs_error_VMerror);
599
600
    /* Step 1 continued: Blank the index */
601
15.2M
    memset(index, 0, (scanlines+1)*sizeof(int));
602
603
    /* Step 1 continued: Run through the path, filling in the index */
604
37.7M
    for (psub = path->first_subpath; psub != 0;) {
605
22.5M
        const segment * gs_restrict pseg = (const segment *)psub;
606
22.5M
        fixed          ey = pseg->pt.y;
607
22.5M
        fixed          iy = ey;
608
22.5M
        int            iey = fixed2int(iy) - base_y;
609
610
22.5M
        assert(pseg->type == s_start);
611
612
        /* Allow for 2 extra intersections on the start scanline.
613
         * This copes with the 'zero height rectangle' case. */
614
22.5M
        if (iey >= 0 && iey < scanlines)
615
11.8M
        {
616
11.8M
            index[iey] += 2;
617
11.8M
            if (iey+1 < scanlines)
618
8.10M
                index[iey+1] -= 2;
619
11.8M
        }
620
621
1.16G
        while ((pseg = pseg->next) != 0 &&
622
1.14G
               pseg->type != s_start
623
1.14G
            ) {
624
1.14G
            fixed sy = ey;
625
1.14G
            ey = pseg->pt.y;
626
627
1.14G
            switch (pseg->type) {
628
0
                default:
629
0
                case s_start: /* Should never happen */
630
0
                case s_dash:  /* We should never be seeing a dash here */
631
0
                    assert("This should never happen" == NULL);
632
0
                    break;
633
24.7k
                case s_curve: {
634
24.7k
                    const curve_segment *const gs_restrict pcur = (const curve_segment *)pseg;
635
24.7k
                    fixed c1y = pcur->p1.y;
636
24.7k
                    fixed c2y = pcur->p2.y;
637
24.7k
                    fixed maxy = sy, miny = sy;
638
24.7k
                    int imaxy, iminy;
639
24.7k
                    if (miny > c1y)
640
10.2k
                        miny = c1y;
641
24.7k
                    if (miny > c2y)
642
12.1k
                        miny = c2y;
643
24.7k
                    if (miny > ey)
644
9.87k
                        miny = ey;
645
24.7k
                    if (maxy < c1y)
646
10.8k
                        maxy = c1y;
647
24.7k
                    if (maxy < c2y)
648
12.1k
                        maxy = c2y;
649
24.7k
                    if (maxy < ey)
650
10.5k
                        maxy = ey;
651
#ifdef DEBUG_SCAN_CONVERTER
652
                    if (debugging_scan_converter)
653
                        dlprintf2("Curve (%x->%x) ", miny, maxy);
654
#endif
655
24.7k
                    iminy = fixed2int(miny) - base_y;
656
24.7k
                    if (iminy <= 0)
657
7.94k
                        iminy = 0;
658
16.7k
                    else
659
16.7k
                        iminy -= adjust;
660
24.7k
                    if (iminy < scanlines) {
661
19.1k
                        imaxy = fixed2int(maxy) - base_y;
662
19.1k
                        if (imaxy >= 0) {
663
#ifdef DEBUG_SCAN_CONVERTER
664
                            if (debugging_scan_converter)
665
                                dlprintf1("+%x ", iminy);
666
#endif
667
12.8k
                            index[iminy]+=3;
668
12.8k
                            if (imaxy < scanlines) {
669
#ifdef DEBUG_SCAN_CONVERTER
670
                                if (debugging_scan_converter)
671
                                    dlprintf1("-%x ", imaxy+1);
672
#endif
673
12.1k
                                index[imaxy+1+adjust]-=3;
674
12.1k
                            }
675
12.8k
                        }
676
19.1k
                    }
677
#ifdef DEBUG_SCAN_CONVERTER
678
                    if (debugging_scan_converter)
679
                        dlprintf("\n");
680
#endif
681
24.7k
                    break;
682
0
                }
683
0
                case s_gap:
684
1.12G
                case s_line:
685
1.14G
                case s_line_close: {
686
1.14G
                    fixed miny, maxy;
687
1.14G
                    int imaxy, iminy;
688
1.14G
                    if (sy == ey) {
689
#ifdef DEBUG_SCAN_CONVERTER
690
                        if (debugging_scan_converter)
691
                            dlprintf("Line (Horiz)\n");
692
#endif
693
99.8M
                        break;
694
99.8M
                    }
695
1.04G
                    if (sy < ey)
696
519M
                        miny = sy, maxy = ey;
697
521M
                    else
698
521M
                        miny = ey, maxy = sy;
699
#ifdef DEBUG_SCAN_CONVERTER
700
                    if (debugging_scan_converter)
701
                        dlprintf2("Line (%x->%x) ", miny, maxy);
702
#endif
703
1.04G
                    iminy = fixed2int(miny) - base_y;
704
1.04G
                    if (iminy <= 0)
705
495M
                        iminy = 0;
706
545M
                    else
707
545M
                        iminy -= adjust;
708
1.04G
                    if (iminy < scanlines) {
709
740M
                        imaxy = fixed2int(maxy) - base_y;
710
740M
                        if (imaxy >= 0) {
711
#ifdef DEBUG_SCAN_CONVERTER
712
                            if (debugging_scan_converter)
713
                                dlprintf1("+%x ", iminy);
714
#endif
715
299M
                            index[iminy]++;
716
299M
                            if (imaxy < scanlines) {
717
#ifdef DEBUG_SCAN_CONVERTER
718
                                if (debugging_scan_converter)
719
                                    dlprintf1("-%x ", imaxy+1);
720
#endif
721
284M
                                index[imaxy+1+adjust]--;
722
284M
                            }
723
299M
                        }
724
740M
                    }
725
#ifdef DEBUG_SCAN_CONVERTER
726
                    if (debugging_scan_converter)
727
                        dlprintf("\n");
728
#endif
729
1.04G
                    break;
730
1.14G
                }
731
1.14G
            }
732
1.14G
        }
733
734
        /* And close any segments that need it */
735
22.5M
        if (ey != iy) {
736
670k
            fixed miny, maxy;
737
670k
            int imaxy, iminy;
738
670k
            if (iy < ey)
739
302k
                miny = iy, maxy = ey;
740
367k
            else
741
367k
                miny = ey, maxy = iy;
742
#ifdef DEBUG_SCAN_CONVERTER
743
            if (debugging_scan_converter)
744
                dlprintf2("Close (%x->%x) ", miny, maxy);
745
#endif
746
670k
            iminy = fixed2int(miny) - base_y;
747
670k
            if (iminy <= 0)
748
495k
                iminy = 0;
749
174k
            else
750
174k
                iminy -= adjust;
751
670k
            if (iminy < scanlines) {
752
506k
                imaxy = fixed2int(maxy) - base_y;
753
506k
                if (imaxy >= 0) {
754
#ifdef DEBUG_SCAN_CONVERTER
755
                    if (debugging_scan_converter)
756
                        dlprintf1("+%x ", iminy);
757
#endif
758
269k
                    index[iminy]++;
759
269k
                    if (imaxy < scanlines) {
760
#ifdef DEBUG_SCAN_CONVERTER
761
                        if (debugging_scan_converter)
762
                            dlprintf1("-%x ", imaxy+1);
763
#endif
764
149k
                        index[imaxy+1+adjust]--;
765
149k
                    }
766
269k
                }
767
506k
            }
768
#ifdef DEBUG_SCAN_CONVERTER
769
            if (debugging_scan_converter)
770
                dlprintf("\n");
771
#endif
772
670k
        }
773
#ifdef DEBUG_SCAN_CONVERTER
774
        if (debugging_scan_converter)
775
            dlprintf("\n");
776
#endif
777
22.5M
        psub = (const subpath *)pseg;
778
22.5M
    }
779
780
    /* Step 1 continued: index now contains a list of deltas (how the
781
     * number of intersects on line x differs from the number on line x-1).
782
     * First convert them to be the real number of intersects on that line.
783
     * Sum these values to get us the total number of intersects. Then
784
     * convert the table to be a list of offsets into the real intersect
785
     * buffer. */
786
15.2M
    offset = 0;
787
15.2M
    delta  = 0;
788
403M
    for (i=0; i < scanlines+adjust; i++) {
789
388M
        delta    += intersection_size*index[i];  /* delta = Num ints on this scanline. */
790
388M
        index[i]  = offset;                      /* Offset into table for this lines data. */
791
388M
        offset   += delta+1;                     /* Adjust offset for next line. */
792
388M
    }
793
    /* Ensure we always have enough room for our zero height rectangle hack. */
794
15.2M
    if (offset < 2*intersection_size)
795
85
        offset += 2*intersection_size;
796
15.2M
    offset *= sizeof(*table);
797
798
    /* Try to keep the size to 1Meg. This is enough for the vast majority
799
     * of files. Allow us to grow above this if it would mean dropping
800
     * the height below a suitably small number (set to be larger than
801
     * any max_fill_band we might meet). */
802
15.2M
    if (scanlines > 16 && offset > 1024*1024) { /* Arbitrary */
803
183
        gs_free_object(pdev->memory, index, "scanc index buffer");
804
183
        return offset/(1024*1024) + 1;
805
183
    }
806
807
    /* In the case where we have let offset be large, at least make sure
808
     * it's not TOO large for us to malloc. */
809
15.2M
    if (offset != (int64_t)(uint)offset)
810
0
    {
811
0
        gs_free_object(pdev->memory, index, "scanc index buffer");
812
0
        return_error(gs_error_VMerror);
813
0
    }
814
815
    /* End of step 1: index[i] = offset into table 2 for scanline i's
816
     * intersection data. offset = Total number of int entries required for
817
     * table. */
818
819
    /* Step 2: Collect the real intersections */
820
15.2M
    table = (int *)gs_alloc_bytes(pdev->memory, offset,
821
15.2M
                                  "scanc intersects buffer");
822
15.2M
    if (table == NULL) {
823
0
        gs_free_object(pdev->memory, index, "scanc index buffer");
824
0
        return_error(gs_error_VMerror);
825
0
    }
826
827
    /* Step 2 continued: initialise table's data; each scanlines data starts
828
     * with a count of the number of intersects so far, followed by a record
829
     * of the intersect points on this scanline. */
830
393M
    for (i=0; i < scanlines; i++) {
831
378M
        table[index[i]] = 0;
832
378M
    }
833
834
15.2M
    *scanlinesp = scanlines;
835
15.2M
    *tablep     = table;
836
15.2M
    *indexp     = index;
837
838
15.2M
    return 0;
839
15.2M
}
840
841
static int make_table(gx_device     * pdev,
842
                      gx_path       * path,
843
                      gs_fixed_rect * ibox,
844
                      int           * scanlines,
845
                      int          ** index,
846
                      int          ** table)
847
422k
{
848
422k
    return make_table_template(pdev, path, ibox, 1, 1, scanlines, index, table);
849
422k
}
850
851
static void
852
fill_zero(int *row, const fixed *x)
853
0
{
854
0
    int n = *row = (*row)+2; /* Increment the count */
855
0
    row[n-1] = (x[0]&~1);
856
0
    row[n  ] = (x[1]|1);
857
0
}
858
859
int gx_scan_convert(gx_device     * gs_restrict pdev,
860
                    gx_path       * gs_restrict path,
861
              const gs_fixed_rect * gs_restrict clip,
862
                    gx_edgebuffer * gs_restrict edgebuffer,
863
                    fixed                       fixed_flat)
864
434k
{
865
434k
    gs_fixed_rect  ibox;
866
434k
    gs_fixed_rect  bbox;
867
434k
    int            scanlines;
868
434k
    const subpath *psub;
869
434k
    int           *index;
870
434k
    int           *table;
871
434k
    int            i;
872
434k
    int            code;
873
434k
    int            zero;
874
875
434k
    edgebuffer->index = NULL;
876
434k
    edgebuffer->table = NULL;
877
878
    /* Bale out if no actual path. We see this with the clist */
879
434k
    if (path->first_subpath == NULL)
880
1.96k
        return 0;
881
882
432k
    zero = make_bbox(path, clip, &bbox, &ibox, fixed_half);
883
432k
    if (zero < 0)
884
0
        return zero;
885
886
432k
    if (ibox.q.y <= ibox.p.y)
887
9.81k
        return 0;
888
889
422k
    code = make_table(pdev, path, &ibox, &scanlines, &index, &table);
890
422k
    if (code != 0) /* >0 means "retry with smaller height" */
891
0
        return code;
892
893
422k
    if (scanlines == 0)
894
0
        return 0;
895
896
422k
    if (zero) {
897
0
        code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero);
898
422k
    } else {
899
900
    /* Step 2 continued: Now we run through the path, filling in the real
901
     * values. */
902
1.10M
    for (psub = path->first_subpath; psub != 0;) {
903
682k
        const segment *pseg = (const segment *)psub;
904
682k
        fixed ex = pseg->pt.x;
905
682k
        fixed ey = pseg->pt.y;
906
682k
        fixed ix = ex;
907
682k
        fixed iy = ey;
908
909
203M
        while ((pseg = pseg->next) != 0 &&
910
203M
               pseg->type != s_start
911
203M
            ) {
912
203M
            fixed sx = ex;
913
203M
            fixed sy = ey;
914
203M
            ex = pseg->pt.x;
915
203M
            ey = pseg->pt.y;
916
917
203M
            switch (pseg->type) {
918
0
                default:
919
0
                case s_start: /* Should never happen */
920
0
                case s_dash:  /* We should never be seeing a dash here */
921
0
                    assert("This should never happen" == NULL);
922
0
                    break;
923
0
                case s_curve: {
924
0
                    const curve_segment *const pcur = (const curve_segment *)pseg;
925
0
                    int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat);
926
927
0
                    mark_curve_top(sx, sy, pcur->p1.x, pcur->p1.y, pcur->p2.x, pcur->p2.y, ex, ey, ibox.p.y, scanlines, table, index, k);
928
0
                    break;
929
0
                }
930
0
                case s_gap:
931
202M
                case s_line:
932
203M
                case s_line_close:
933
203M
                    if (sy != ey)
934
172M
                        mark_line(sx, sy, ex, ey, ibox.p.y, scanlines, table, index);
935
203M
                    break;
936
203M
            }
937
203M
        }
938
        /* And close any open segments */
939
682k
        if (iy != ey)
940
171k
            mark_line(ex, ey, ix, iy, ibox.p.y, scanlines, table, index);
941
682k
        psub = (const subpath *)pseg;
942
682k
    }
943
422k
    }
944
945
    /* Step 2 complete: We now have a complete list of intersection data in
946
     * table, indexed by index. */
947
948
422k
    edgebuffer->base   = ibox.p.y;
949
422k
    edgebuffer->height = scanlines;
950
422k
    edgebuffer->xmin   = ibox.p.x;
951
422k
    edgebuffer->xmax   = ibox.q.x;
952
422k
    edgebuffer->index  = index;
953
422k
    edgebuffer->table  = table;
954
955
#ifdef DEBUG_SCAN_CONVERTER
956
    if (debugging_scan_converter) {
957
        dlprintf("Before sorting:\n");
958
        gx_edgebuffer_print(edgebuffer);
959
    }
960
#endif
961
962
    /* Step 3: Sort the intersects on x */
963
6.49M
    for (i=0; i < scanlines; i++) {
964
6.07M
        int *row = &table[index[i]];
965
6.07M
        int  rowlen = *row++;
966
967
        /* Bubblesort short runs, qsort longer ones. */
968
        /* FIXME: Check "6" below */
969
6.07M
        if (rowlen <= 6) {
970
5.97M
            int j, k;
971
19.3M
            for (j = 0; j < rowlen-1; j++) {
972
13.4M
                int t = row[j];
973
39.3M
                for (k = j+1; k < rowlen; k++) {
974
25.9M
                    int s = row[k];
975
25.9M
                    if (t > s)
976
12.4M
                         row[k] = t, t = row[j] = s;
977
25.9M
                }
978
13.4M
            }
979
5.97M
        } else
980
97.1k
            qsort(row, rowlen, sizeof(int), intcmp);
981
6.07M
    }
982
983
422k
    return 0;
984
422k
}
985
986
/* Step 5: Filter the intersections according to the rules */
987
int
988
gx_filter_edgebuffer(gx_device       * gs_restrict pdev,
989
                     gx_edgebuffer   * gs_restrict edgebuffer,
990
                     int                        rule)
991
434k
{
992
434k
    int i;
993
994
#ifdef DEBUG_SCAN_CONVERTER
995
    if (debugging_scan_converter) {
996
        dlprintf("Before filtering:\n");
997
        gx_edgebuffer_print(edgebuffer);
998
    }
999
#endif
1000
1001
6.50M
    for (i=0; i < edgebuffer->height; i++) {
1002
6.07M
        int *row      = &edgebuffer->table[edgebuffer->index[i]];
1003
6.07M
        int *rowstart = row;
1004
6.07M
        int  rowlen   = *row++;
1005
6.07M
        int *rowout   = row;
1006
1007
15.9M
        while (rowlen > 0)
1008
9.84M
        {
1009
9.84M
            int left, right;
1010
1011
9.84M
            if (rule == gx_rule_even_odd) {
1012
                /* Even Odd */
1013
0
                left  = (*row++)&~1;
1014
0
                right = (*row++)&~1;
1015
0
                rowlen -= 2;
1016
9.84M
            } else {
1017
                /* Non-Zero */
1018
9.84M
                int w;
1019
1020
9.84M
                left = *row++;
1021
9.84M
                w = ((left&1)-1) | (left&1);
1022
9.84M
                rowlen--;
1023
10.3M
                do {
1024
10.3M
                    right  = *row++;
1025
10.3M
                    rowlen--;
1026
10.3M
                    w += ((right&1)-1) | (right&1);
1027
10.3M
                } while (w != 0);
1028
9.84M
                left &= ~1;
1029
9.84M
                right &= ~1;
1030
9.84M
            }
1031
1032
9.84M
            if (right > left) {
1033
9.77M
                *rowout++ = left;
1034
9.77M
                *rowout++ = right;
1035
9.77M
            }
1036
9.84M
        }
1037
6.07M
        *rowstart = (rowout-rowstart)-1;
1038
6.07M
    }
1039
434k
    return 0;
1040
434k
}
1041
1042
/* Step 6: Fill the edgebuffer */
1043
int
1044
gx_fill_edgebuffer(gx_device       * gs_restrict pdev,
1045
             const gx_device_color * gs_restrict pdevc,
1046
                   gx_edgebuffer   * gs_restrict edgebuffer,
1047
                   int                        log_op)
1048
434k
{
1049
434k
    int i, code;
1050
1051
6.50M
    for (i=0; i < edgebuffer->height; i++) {
1052
6.07M
        int *row    = &edgebuffer->table[edgebuffer->index[i]];
1053
6.07M
        int  rowlen = *row++;
1054
1055
15.8M
        while (rowlen > 0) {
1056
9.77M
            int left, right;
1057
1058
9.77M
            left  = *row++;
1059
9.77M
            right = *row++;
1060
9.77M
            rowlen -= 2;
1061
9.77M
            left  = fixed2int(left + fixed_half);
1062
9.77M
            right = fixed2int(right + fixed_half);
1063
9.77M
            right -= left;
1064
9.77M
            if (right > 0) {
1065
#ifdef DEBUG_OUTPUT_SC_AS_PS
1066
                dlprintf("0.001 setlinewidth 1 0.5 0 setrgbcolor %% orange %%PS\n");
1067
                coord("moveto", int2fixed(left), int2fixed(edgebuffer->base+i));
1068
                coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i));
1069
                coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i+1));
1070
                coord("lineto", int2fixed(left), int2fixed(edgebuffer->base+i+1));
1071
                dlprintf("closepath stroke %%PS\n");
1072
#endif
1073
9.48M
                if (log_op < 0)
1074
5.13M
                    code = dev_proc(pdev, fill_rectangle)(pdev, left, edgebuffer->base+i, right, 1, pdevc->colors.pure);
1075
4.34M
                else
1076
4.34M
                    code = gx_fill_rectangle_device_rop(left, edgebuffer->base+i, right, 1, pdevc, pdev, (gs_logical_operation_t)log_op);
1077
9.48M
                if (code < 0)
1078
0
                    return code;
1079
9.48M
            }
1080
9.77M
        }
1081
6.07M
    }
1082
434k
    return 0;
1083
434k
}
1084
1085
/* Any part of a pixel routines */
1086
1087
static int edgecmp(const void *a, const void *b)
1088
808k
{
1089
808k
    int left  = ((int*)a)[0];
1090
808k
    int right = ((int*)b)[0];
1091
808k
    left -= right;
1092
808k
    if (left)
1093
801k
        return left;
1094
7.68k
    return ((int*)a)[1] - ((int*)b)[1];
1095
808k
}
1096
1097
#ifdef DEBUG_SCAN_CONVERTER
1098
static void
1099
gx_edgebuffer_print_app(gx_edgebuffer * edgebuffer)
1100
{
1101
    int i;
1102
    int borked = 0;
1103
1104
    if (!debugging_scan_converter)
1105
        return;
1106
1107
    dlprintf1("Edgebuffer %x\n", edgebuffer);
1108
    dlprintf4("xmin=%x xmax=%x base=%x height=%x\n",
1109
              edgebuffer->xmin, edgebuffer->xmax, edgebuffer->base, edgebuffer->height);
1110
    for (i=0; i < edgebuffer->height; i++) {
1111
        int  offset = edgebuffer->index[i];
1112
        int *row    = &edgebuffer->table[offset];
1113
        int count   = *row++;
1114
        int c       = count;
1115
        int wind    = 0;
1116
        dlprintf3("%x @ %d: %d =", i, offset, count);
1117
        while (count-- > 0) {
1118
            int left  = *row++;
1119
            int right = *row++;
1120
            int w     = -(left&1) | 1;
1121
            wind += w;
1122
            dlprintf3(" (%x,%x)%c", left&~1, right, left&1 ? 'v' : '^');
1123
        }
1124
        if (wind != 0 || c & 1) {
1125
            dlprintf(" <- BROKEN");
1126
            borked = 1;
1127
        }
1128
        dlprintf("\n");
1129
    }
1130
    if (borked) {
1131
        borked = borked; /* Breakpoint here */
1132
    }
1133
}
1134
#endif
1135
1136
typedef struct
1137
{
1138
    fixed  left;
1139
    fixed  right;
1140
    fixed  y;
1141
    signed char d; /* 0 up (or horiz), 1 down, -1 uninited */
1142
    unsigned char first;
1143
    unsigned char saved;
1144
1145
    fixed  save_left;
1146
    fixed  save_right;
1147
    int    save_iy;
1148
    int    save_d;
1149
1150
    int    scanlines;
1151
    int   *table;
1152
    int   *index;
1153
    int    base;
1154
} cursor;
1155
1156
static inline void
1157
cursor_output(cursor * gs_restrict cr, int iy)
1158
2.78M
{
1159
2.78M
    int *row;
1160
2.78M
    int count;
1161
1162
2.78M
    if (iy >= 0 && iy < cr->scanlines) {
1163
2.49M
        if (cr->first) {
1164
            /* Save it for later in case we join up */
1165
198k
            cr->save_left  = cr->left;
1166
198k
            cr->save_right = cr->right;
1167
198k
            cr->save_iy    = iy;
1168
198k
            cr->save_d     = cr->d;
1169
198k
            cr->saved      = 1;
1170
2.29M
        } else if (cr->d != DIRN_UNSET) {
1171
            /* Enter it into the table */
1172
2.29M
            row = &cr->table[cr->index[iy]];
1173
2.29M
            *row = count = (*row)+1; /* Increment the count */
1174
2.29M
            row[2 * count - 1] = (cr->left&~1) | cr->d;
1175
2.29M
            row[2 * count    ] = cr->right;
1176
2.29M
        } else {
1177
891
            assert(cr->left == max_fixed && cr->right == min_fixed);
1178
891
        }
1179
2.49M
    }
1180
2.78M
    cr->first = 0;
1181
2.78M
}
1182
1183
static inline void
1184
cursor_output_inrange(cursor * gs_restrict cr, int iy)
1185
2.21M
{
1186
2.21M
    int *row;
1187
2.21M
    int count;
1188
1189
2.21M
    assert(iy >= 0 && iy < cr->scanlines);
1190
2.21M
    if (cr->first) {
1191
        /* Save it for later in case we join up */
1192
7.12k
        cr->save_left  = cr->left;
1193
7.12k
        cr->save_right = cr->right;
1194
7.12k
        cr->save_iy    = iy;
1195
7.12k
        cr->save_d     = cr->d;
1196
7.12k
        cr->saved      = 1;
1197
2.20M
    } else {
1198
        /* Enter it into the table */
1199
2.20M
        assert(cr->d != DIRN_UNSET);
1200
1201
2.20M
        row = &cr->table[cr->index[iy]];
1202
2.20M
        *row = count = (*row)+1; /* Increment the count */
1203
2.20M
        row[2 * count - 1] = (cr->left&~1) | cr->d;
1204
2.20M
        row[2 * count    ] = cr->right;
1205
2.20M
    }
1206
2.21M
    cr->first = 0;
1207
2.21M
}
1208
1209
/* Step the cursor in y, allowing for maybe crossing a scanline */
1210
static inline void
1211
cursor_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip)
1212
814k
{
1213
814k
    int new_iy;
1214
814k
    int iy = fixed2int(cr->y) - cr->base;
1215
1216
814k
    cr->y += dy;
1217
814k
    new_iy = fixed2int(cr->y) - cr->base;
1218
814k
    if (new_iy != iy) {
1219
814k
        if (!skip)
1220
798k
            cursor_output(cr, iy);
1221
814k
        cr->left = x;
1222
814k
        cr->right = x;
1223
814k
    } else {
1224
0
        if (x < cr->left)
1225
0
            cr->left = x;
1226
0
        if (x > cr->right)
1227
0
            cr->right = x;
1228
0
    }
1229
814k
}
1230
1231
/* Step the cursor in y, never by enough to cross a scanline. */
1232
static inline void
1233
cursor_never_step_vertical(cursor * gs_restrict cr, fixed dy, fixed x)
1234
18.8k
{
1235
18.8k
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
1236
1237
18.8k
    cr->y += dy;
1238
18.8k
}
1239
1240
/* Step the cursor in y, never by enough to cross a scanline,
1241
 * knowing that we are moving left, and that the right edge
1242
 * has already been accounted for. */
1243
static inline void
1244
cursor_never_step_left(cursor * gs_restrict cr, fixed dy, fixed x)
1245
187k
{
1246
187k
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
1247
1248
187k
    if (x < cr->left)
1249
134k
        cr->left = x;
1250
187k
    cr->y += dy;
1251
187k
}
1252
1253
/* Step the cursor in y, never by enough to cross a scanline,
1254
 * knowing that we are moving right, and that the left edge
1255
 * has already been accounted for. */
1256
static inline void
1257
cursor_never_step_right(cursor * gs_restrict cr, fixed dy, fixed x)
1258
187k
{
1259
187k
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
1260
1261
187k
    if (x > cr->right)
1262
182k
        cr->right = x;
1263
187k
    cr->y += dy;
1264
187k
}
1265
1266
/* Step the cursor in y, always by enough to cross a scanline. */
1267
static inline void
1268
cursor_always_step(cursor * gs_restrict cr, fixed dy, fixed x, int skip)
1269
644k
{
1270
644k
    int iy = fixed2int(cr->y) - cr->base;
1271
1272
644k
    if (!skip)
1273
524k
        cursor_output(cr, iy);
1274
644k
    cr->y += dy;
1275
644k
    cr->left = x;
1276
644k
    cr->right = x;
1277
644k
}
1278
1279
/* Step the cursor in y, always by enough to cross a scanline, as
1280
 * part of a vertical line, knowing that we are moving from a
1281
 * position guaranteed to be in the valid y range. */
1282
static inline void
1283
cursor_always_step_inrange_vertical(cursor * gs_restrict cr, fixed dy, fixed x)
1284
589k
{
1285
589k
    int iy = fixed2int(cr->y) - cr->base;
1286
1287
589k
    cursor_output(cr, iy);
1288
589k
    cr->y += dy;
1289
589k
}
1290
1291
/* Step the cursor in y, always by enough to cross a scanline, as
1292
 * part of a left moving line, knowing that we are moving from a
1293
 * position guaranteed to be in the valid y range. */
1294
static inline void
1295
cursor_always_inrange_step_left(cursor * gs_restrict cr, fixed dy, fixed x)
1296
1.18M
{
1297
1.18M
    int iy = fixed2int(cr->y) - cr->base;
1298
1299
1.18M
    cr->y += dy;
1300
1.18M
    cursor_output_inrange(cr, iy);
1301
1.18M
    cr->right = x;
1302
1.18M
}
1303
1304
/* Step the cursor in y, always by enough to cross a scanline, as
1305
 * part of a right moving line, knowing that we are moving from a
1306
 * position guaranteed to be in the valid y range. */
1307
static inline void
1308
cursor_always_inrange_step_right(cursor * gs_restrict cr, fixed dy, fixed x)
1309
1.03M
{
1310
1.03M
    int iy = fixed2int(cr->y) - cr->base;
1311
1312
1.03M
    cr->y += dy;
1313
1.03M
    cursor_output_inrange(cr, iy);
1314
1.03M
    cr->left = x;
1315
1.03M
}
1316
1317
static inline void cursor_left_merge(cursor * gs_restrict cr, fixed x)
1318
2.66M
{
1319
2.66M
    if (x < cr->left)
1320
955k
        cr->left = x;
1321
2.66M
}
1322
1323
static inline void cursor_left(cursor * gs_restrict cr, fixed x)
1324
1.71M
{
1325
1.71M
    cr->left = x;
1326
1.71M
}
1327
1328
static inline void cursor_right_merge(cursor * gs_restrict cr, fixed x)
1329
2.70M
{
1330
2.70M
    if (x > cr->right)
1331
894k
        cr->right = x;
1332
2.70M
}
1333
1334
static inline void cursor_right(cursor * gs_restrict cr, fixed x)
1335
1.56M
{
1336
1.56M
    cr->right = x;
1337
1.56M
}
1338
1339
static inline int cursor_down(cursor * gs_restrict cr, fixed x)
1340
906k
{
1341
906k
    int skip = 0;
1342
906k
    if ((cr->y & 0xff) == 0)
1343
136k
        skip = 1;
1344
906k
    if (cr->d == DIRN_UP)
1345
135k
    {
1346
135k
        if (!skip)
1347
135k
            cursor_output(cr, fixed2int(cr->y) - cr->base);
1348
135k
        cr->left = x;
1349
135k
        cr->right = x;
1350
135k
    }
1351
906k
    cr->d = DIRN_DOWN;
1352
906k
    return skip;
1353
906k
}
1354
1355
static inline void cursor_up(cursor * gs_restrict cr, fixed x)
1356
899k
{
1357
899k
    if (cr->d == DIRN_DOWN)
1358
131k
    {
1359
131k
        cursor_output(cr, fixed2int(cr->y) - cr->base);
1360
131k
        cr->left = x;
1361
131k
        cr->right = x;
1362
131k
    }
1363
899k
    cr->d = DIRN_UP;
1364
899k
}
1365
1366
static inline void
1367
cursor_flush(cursor * gs_restrict cr, fixed x)
1368
466k
{
1369
466k
    int iy;
1370
1371
    /* This should only happen if we were entirely out of bounds,
1372
     * or if everything was within a zero height horizontal
1373
     * rectangle from the start point. */
1374
466k
    if (cr->first) {
1375
249
        int iy = fixed2int(cr->y) - cr->base;
1376
        /* Any zero height rectangle counts as filled, except
1377
         * those on the baseline of a pixel. */
1378
249
        if (cr->d == DIRN_UNSET && (cr->y & 0xff) == 0)
1379
6
            return;
1380
249
        assert(cr->left != max_fixed && cr->right != min_fixed);
1381
243
        if (iy >= 0 && iy < cr->scanlines) {
1382
7
            int *row = &cr->table[cr->index[iy]];
1383
7
            int count = *row = (*row)+2; /* Increment the count */
1384
7
            row[2 * count - 3] = (cr->left & ~1) | DIRN_UP;
1385
7
            row[2 * count - 2] = (cr->right & ~1);
1386
7
            row[2 * count - 1] = (cr->right & ~1) | DIRN_DOWN;
1387
7
            row[2 * count    ] = cr->right;
1388
7
        }
1389
243
        return;
1390
249
    }
1391
1392
    /* Merge save into current if we can */
1393
466k
    iy = fixed2int(cr->y) - cr->base;
1394
466k
    if (cr->saved && iy == cr->save_iy &&
1395
170k
        (cr->d == cr->save_d || cr->save_d == DIRN_UNSET)) {
1396
82.7k
        if (cr->left > cr->save_left)
1397
23.2k
            cr->left = cr->save_left;
1398
82.7k
        if (cr->right < cr->save_right)
1399
24.1k
            cr->right = cr->save_right;
1400
82.7k
        cursor_output(cr, iy);
1401
82.7k
        return;
1402
82.7k
    }
1403
1404
    /* Merge not possible */
1405
383k
    cursor_output(cr, iy);
1406
383k
    if (cr->saved) {
1407
123k
        cr->left  = cr->save_left;
1408
123k
        cr->right = cr->save_right;
1409
123k
        assert(cr->save_d != DIRN_UNSET);
1410
123k
        if (cr->save_d != DIRN_UNSET)
1411
123k
            cr->d = cr->save_d;
1412
123k
        cursor_output(cr, cr->save_iy);
1413
123k
    }
1414
383k
}
1415
1416
static inline void
1417
cursor_null(cursor *cr)
1418
571k
{
1419
571k
    cr->right = min_fixed;
1420
571k
    cr->left  = max_fixed;
1421
571k
    cr->d     = DIRN_UNSET;
1422
571k
}
1423
1424
static void mark_line_app(cursor * gs_restrict cr, fixed sx, fixed sy, fixed ex, fixed ey)
1425
11.3M
{
1426
11.3M
    int isy, iey;
1427
11.3M
    fixed saved_sy = sy;
1428
11.3M
    fixed saved_ex = ex;
1429
11.3M
    fixed saved_ey = ey;
1430
11.3M
    int truncated;
1431
1432
11.3M
    if (sx == ex && sy == ey)
1433
467k
        return;
1434
1435
10.9M
    isy = fixed2int(sy) - cr->base;
1436
10.9M
    iey = fixed2int(ey) - cr->base;
1437
#ifdef DEBUG_SCAN_CONVERTER
1438
    if (debugging_scan_converter)
1439
        dlprintf6("Marking line (app) from %x,%x to %x,%x (%x,%x)\n", sx, sy, ex, ey, isy, iey);
1440
#endif
1441
#ifdef DEBUG_OUTPUT_SC_AS_PS
1442
    dlprintf("0.001 setlinewidth 0 0 0 setrgbcolor %%PS\n");
1443
    coord("moveto", sx, sy);
1444
    coord("lineto", ex, ey);
1445
    dlprintf("stroke %%PS\n");
1446
#endif
1447
1448
    /* Horizontal motion at the bottom of a pixel is ignored */
1449
10.9M
    if (sy == ey && (sy & 0xff) == 0)
1450
5.54k
        return;
1451
1452
10.9M
    assert(cr->y == sy &&
1453
10.9M
           ((cr->left <= sx && cr->right >= sx) || ((sy & 0xff) == 0)) &&
1454
10.9M
           cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN);
1455
1456
10.9M
    if (isy < iey) {
1457
        /* Rising line */
1458
4.45M
        if (iey < 0 || isy >= cr->scanlines) {
1459
            /* All line is outside. */
1460
3.92M
            if ((ey & 0xff) == 0)
1461
26.2k
                cursor_null(cr);
1462
3.89M
            else {
1463
3.89M
                cr->left = ex;
1464
3.89M
                cr->right = ex;
1465
3.89M
            }
1466
3.92M
            cr->y = ey;
1467
3.92M
            cr->first = 0;
1468
3.92M
            return;
1469
3.92M
        }
1470
536k
        if (isy < 0) {
1471
            /* Move sy up */
1472
130k
            int64_t y = (int64_t)ey - (int64_t)sy;
1473
130k
            fixed new_sy = int2fixed(cr->base);
1474
130k
            int64_t dy = (int64_t)new_sy - (int64_t)sy;
1475
130k
            sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y);
1476
130k
            sy = new_sy;
1477
130k
            cursor_null(cr);
1478
130k
            cr->y = sy;
1479
130k
            isy = 0;
1480
130k
        }
1481
536k
        truncated = iey > cr->scanlines;
1482
536k
        if (truncated) {
1483
            /* Move ey down */
1484
117k
            int64_t y = ey - sy;
1485
117k
            fixed new_ey = int2fixed(cr->base + cr->scanlines);
1486
117k
            int64_t dy = (int64_t)ey - (int64_t)new_ey;
1487
117k
            saved_ex = ex;
1488
117k
            saved_ey = ey;
1489
117k
            ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y);
1490
117k
            ey = new_ey;
1491
117k
            iey = cr->scanlines;
1492
117k
        }
1493
6.44M
    } else {
1494
        /* Falling line */
1495
6.44M
        if (isy < 0 || iey >= cr->scanlines) {
1496
            /* All line is outside. */
1497
5.06M
            if ((ey & 0xff) == 0)
1498
23.7k
                cursor_null(cr);
1499
5.04M
            else {
1500
5.04M
                cr->left = ex;
1501
5.04M
                cr->right = ex;
1502
5.04M
            }
1503
5.06M
            cr->y = ey;
1504
5.06M
            cr->first = 0;
1505
5.06M
            return;
1506
5.06M
        }
1507
1.38M
        truncated = iey < 0;
1508
1.38M
        if (truncated) {
1509
            /* Move ey up */
1510
130k
            int64_t y = (int64_t)ey - (int64_t)sy;
1511
130k
            fixed new_ey = int2fixed(cr->base);
1512
130k
            int64_t dy = (int64_t)ey - (int64_t)new_ey;
1513
130k
            ex -= (int)((((int64_t)(ex-sx))*dy + y/2)/y);
1514
130k
            ey = new_ey;
1515
130k
            iey = 0;
1516
130k
        }
1517
1.38M
        if (isy >= cr->scanlines) {
1518
            /* Move sy down */
1519
131k
            int64_t y = (int64_t)ey - (int64_t)sy;
1520
131k
            fixed new_sy = int2fixed(cr->base + cr->scanlines);
1521
131k
            int64_t dy = (int64_t)new_sy - (int64_t)sy;
1522
131k
            sx += (int)((((int64_t)(ex-sx))*dy + y/2)/y);
1523
131k
            sy = new_sy;
1524
131k
            cursor_null(cr);
1525
131k
            cr->y = sy;
1526
131k
            isy = cr->scanlines;
1527
131k
        }
1528
1.38M
    }
1529
1530
1.91M
    cursor_left_merge(cr, sx);
1531
1.91M
    cursor_right_merge(cr, sx);
1532
1533
1.91M
    assert(cr->left <= sx);
1534
1.91M
    assert(cr->right >= sx);
1535
1.91M
    assert(cr->y == sy);
1536
1537
    /* A note: The code below used to be of the form:
1538
     *   if (isy == iey)   ... deal with horizontal lines
1539
     *   else if (ey > sy) {
1540
     *     fixed y_steps = ey - sy;
1541
     *      ... deal with rising lines ...
1542
     *   } else {
1543
     *     fixed y_steps = ey - sy;
1544
     *     ... deal with falling lines
1545
     *   }
1546
     * but that lead to problems, for instance, an example seen
1547
     * has sx=2aa8e, sy=8aee7, ex=7ffc1686, ey=8003e97a.
1548
     * Thus isy=84f, iey=ff80038a. We can see that ey < sy, but
1549
     * sy - ey < 0!
1550
     * We therefore rejig our code so that the choice between
1551
     * cases is done based on the sign of y_steps rather than
1552
     * the relative size of ey and sy.
1553
     */
1554
1555
    /* First, deal with lines that don't change scanline.
1556
     * This accommodates horizontal lines. */
1557
1.91M
    if (isy == iey) {
1558
862k
        if (saved_sy == saved_ey) {
1559
            /* Horizontal line. Don't change cr->d, don't flush. */
1560
112k
            if ((ey & 0xff) == 0)
1561
0
                goto no_merge;
1562
750k
        } else if (saved_sy > saved_ey) {
1563
            /* Falling line, flush if previous was rising */
1564
376k
            int skip = cursor_down(cr, sx);
1565
376k
            if ((ey & 0xff) == 0) {
1566
                /* We are falling to the baseline of a subpixel, so output
1567
                 * for the current pixel, and leave the cursor nulled. */
1568
15.6k
                if (sx <= ex) {
1569
9.86k
                    cursor_right_merge(cr, ex);
1570
9.86k
                } else {
1571
5.77k
                    cursor_left_merge(cr, ex);
1572
5.77k
                }
1573
15.6k
                if (!skip)
1574
15.4k
                    cursor_output(cr, fixed2int(cr->y) - cr->base);
1575
15.6k
                cursor_null(cr);
1576
15.6k
                goto no_merge;
1577
15.6k
            }
1578
376k
        } else {
1579
            /* Rising line, flush if previous was falling */
1580
374k
            cursor_up(cr, sx);
1581
374k
            if ((ey & 0xff) == 0) {
1582
212
                cursor_null(cr);
1583
212
                goto no_merge;
1584
212
            }
1585
374k
        }
1586
847k
        if (sx <= ex) {
1587
447k
            cursor_right_merge(cr, ex);
1588
447k
        } else {
1589
399k
            cursor_left_merge(cr, ex);
1590
399k
        }
1591
862k
no_merge:
1592
862k
        cr->y = ey;
1593
862k
        if (sy > saved_ey)
1594
376k
            goto endFalling;
1595
1.05M
    } else if (iey > isy) {
1596
        /* We want to change from sy to ey, which are guaranteed to be on
1597
         * different scanlines. We do this in 3 phases.
1598
         * Phase 1 gets us from sy to the next scanline boundary.
1599
         * Phase 2 gets us all the way to the last scanline boundary.
1600
         * Phase 3 gets us from the last scanline boundary to ey.
1601
         */
1602
        /* We want to change from sy to ey, which are guaranteed to be on
1603
         * different scanlines. We do this in 3 phases.
1604
         * Phase 1 gets us from sy to the next scanline boundary. (We may exit after phase 1).
1605
         * Phase 2 gets us all the way to the last scanline boundary. (This may be a null operation)
1606
         * Phase 3 gets us from the last scanline boundary to ey. (We are guaranteed to have output the cursor at least once before phase 3).
1607
         */
1608
524k
        int phase1_y_steps = (-sy) & (fixed_1 - 1);
1609
524k
        int phase3_y_steps = ey & (fixed_1 - 1);
1610
524k
        ufixed y_steps = (ufixed)ey - (ufixed)sy;
1611
1612
524k
        cursor_up(cr, sx);
1613
1614
524k
        if (sx == ex) {
1615
            /* Vertical line. (Rising) */
1616
1617
            /* Phase 1: */
1618
42.1k
            if (phase1_y_steps) {
1619
                /* If phase 1 will move us into a new scanline, then we must
1620
                 * flush it before we move. */
1621
21.8k
                cursor_step(cr, phase1_y_steps, sx, 0);
1622
21.8k
                sy += phase1_y_steps;
1623
21.8k
                y_steps -= phase1_y_steps;
1624
21.8k
                if (y_steps == 0) {
1625
2.39k
                    cursor_null(cr);
1626
2.39k
                    goto end;
1627
2.39k
                }
1628
21.8k
            }
1629
1630
            /* Phase 3: precalculation */
1631
39.7k
            y_steps -= phase3_y_steps;
1632
1633
            /* Phase 2: */
1634
39.7k
            y_steps = fixed2int(y_steps);
1635
39.7k
            assert(y_steps >= 0);
1636
39.7k
            if (y_steps > 0) {
1637
33.1k
                cursor_always_step(cr, fixed_1, sx, 0);
1638
33.1k
                y_steps--;
1639
267k
                while (y_steps) {
1640
234k
                    cursor_always_step_inrange_vertical(cr, fixed_1, sx);
1641
234k
                    y_steps--;
1642
234k
                }
1643
33.1k
            }
1644
1645
            /* Phase 3 */
1646
39.7k
            assert(cr->left == sx && cr->right == sx);
1647
39.7k
            if (phase3_y_steps == 0)
1648
19.3k
                cursor_null(cr);
1649
20.4k
            else
1650
20.4k
                cr->y += phase3_y_steps;
1651
482k
        } else if (sx < ex) {
1652
            /* Lines increasing in x. (Rightwards, rising) */
1653
237k
            int phase1_x_steps, phase3_x_steps;
1654
237k
            fixed x_steps = ex - sx;
1655
1656
            /* Phase 1: */
1657
237k
            if (phase1_y_steps) {
1658
191k
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
1659
191k
                sx += phase1_x_steps;
1660
191k
                cursor_right_merge(cr, sx);
1661
191k
                x_steps -= phase1_x_steps;
1662
191k
                cursor_step(cr, phase1_y_steps, sx, 0);
1663
191k
                sy += phase1_y_steps;
1664
191k
                y_steps -= phase1_y_steps;
1665
191k
                if (y_steps == 0) {
1666
4.31k
                    cursor_null(cr);
1667
4.31k
                    goto end;
1668
4.31k
                }
1669
191k
            }
1670
1671
            /* Phase 3: precalculation */
1672
233k
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
1673
233k
            x_steps -= phase3_x_steps;
1674
233k
            y_steps -= phase3_y_steps;
1675
233k
            assert((y_steps & (fixed_1 - 1)) == 0);
1676
1677
            /* Phase 2: */
1678
233k
            y_steps = fixed2int(y_steps);
1679
233k
            assert(y_steps >= 0);
1680
233k
            if (y_steps) {
1681
                /* We want to change sx by x_steps in y_steps steps.
1682
                 * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/y_steps. */
1683
140k
                int x_inc = x_steps/y_steps;
1684
140k
                int n_inc = x_steps - (x_inc * y_steps);
1685
140k
                int f = y_steps/2;
1686
140k
                int d = y_steps;
1687
1688
                /* Special casing the first iteration, allows us to simplify
1689
                 * the following loop. */
1690
140k
                sx += x_inc;
1691
140k
                f -= n_inc;
1692
140k
                if (f < 0)
1693
29.5k
                    f += d, sx++;
1694
140k
                cursor_right_merge(cr, sx);
1695
140k
                cursor_always_step(cr, fixed_1, sx, 0);
1696
140k
                y_steps--;
1697
1698
644k
                while (y_steps) {
1699
503k
                    sx += x_inc;
1700
503k
                    f -= n_inc;
1701
503k
                    if (f < 0)
1702
234k
                        f += d, sx++;
1703
503k
                    cursor_right(cr, sx);
1704
503k
                    cursor_always_inrange_step_right(cr, fixed_1, sx);
1705
503k
                    y_steps--;
1706
503k
                };
1707
140k
            }
1708
1709
            /* Phase 3 */
1710
233k
            assert(cr->left <= ex && cr->right >= sx);
1711
233k
            if (phase3_y_steps == 0)
1712
41.5k
                cursor_null(cr);
1713
191k
            else {
1714
191k
                cursor_right(cr, ex);
1715
191k
                cr->y += phase3_y_steps;
1716
191k
            }
1717
245k
        } else {
1718
            /* Lines decreasing in x. (Leftwards, rising) */
1719
245k
            int phase1_x_steps, phase3_x_steps;
1720
245k
            fixed x_steps = sx - ex;
1721
1722
            /* Phase 1: */
1723
245k
            if (phase1_y_steps) {
1724
190k
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
1725
190k
                x_steps -= phase1_x_steps;
1726
190k
                sx -= phase1_x_steps;
1727
190k
                cursor_left_merge(cr, sx);
1728
190k
                cursor_step(cr, phase1_y_steps, sx, 0);
1729
190k
                sy += phase1_y_steps;
1730
190k
                y_steps -= phase1_y_steps;
1731
190k
                if (y_steps == 0) {
1732
4.44k
                    cursor_null(cr);
1733
4.44k
                    goto end;
1734
4.44k
                }
1735
190k
            }
1736
1737
            /* Phase 3: precalculation */
1738
240k
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
1739
240k
            x_steps -= phase3_x_steps;
1740
240k
            y_steps -= phase3_y_steps;
1741
240k
            assert((y_steps & (fixed_1 - 1)) == 0);
1742
1743
            /* Phase 2: */
1744
240k
            y_steps = fixed2int(y_steps);
1745
240k
            assert(y_steps >= 0);
1746
240k
            if (y_steps) {
1747
                /* We want to change sx by x_steps in y_steps steps.
1748
                 * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
1749
148k
                int x_inc = x_steps/y_steps;
1750
148k
                int n_inc = x_steps - (x_inc * y_steps);
1751
148k
                int f = y_steps/2;
1752
148k
                int d = y_steps;
1753
1754
                /* Special casing the first iteration, allows us to simplify
1755
                 * the following loop. */
1756
148k
                sx -= x_inc;
1757
148k
                f -= n_inc;
1758
148k
                if (f < 0)
1759
26.6k
                    f += d, sx--;
1760
148k
                cursor_left_merge(cr, sx);
1761
148k
                cursor_always_step(cr, fixed_1, sx, 0);
1762
148k
                y_steps--;
1763
1764
755k
                while (y_steps) {
1765
607k
                    sx -= x_inc;
1766
607k
                    f -= n_inc;
1767
607k
                    if (f < 0)
1768
239k
                        f += d, sx--;
1769
607k
                    cursor_left(cr, sx);
1770
607k
                    cursor_always_inrange_step_left(cr, fixed_1, sx);
1771
607k
                    y_steps--;
1772
607k
                }
1773
148k
            }
1774
1775
            /* Phase 3 */
1776
240k
            assert(cr->right >= ex && cr->left <= sx);
1777
240k
            if (phase3_y_steps == 0)
1778
51.4k
                cursor_null(cr);
1779
189k
            else {
1780
189k
                cursor_left(cr, ex);
1781
189k
                cr->y += phase3_y_steps;
1782
189k
            }
1783
240k
        }
1784
529k
    } else {
1785
        /* So lines decreasing in y. */
1786
        /* We want to change from sy to ey, which are guaranteed to be on
1787
         * different scanlines. We do this in 3 phases.
1788
         * Phase 1 gets us from sy to the next scanline boundary. This never causes an output.
1789
         * Phase 2 gets us all the way to the last scanline boundary. This is guaranteed to cause an output.
1790
         * Phase 3 gets us from the last scanline boundary to ey. We are guaranteed to have outputted by now.
1791
         */
1792
529k
        int phase1_y_steps = sy & (fixed_1 - 1);
1793
529k
        int phase3_y_steps = (-ey) & (fixed_1 - 1);
1794
529k
        ufixed y_steps = (ufixed)sy - (ufixed)ey;
1795
1796
529k
        int skip = cursor_down(cr, sx);
1797
1798
529k
        if (sx == ex) {
1799
            /* Vertical line. (Falling) */
1800
1801
            /* Phase 1: */
1802
42.4k
            if (phase1_y_steps) {
1803
                /* Phase 1 in a falling line never moves us into a new scanline. */
1804
18.8k
                cursor_never_step_vertical(cr, -phase1_y_steps, sx);
1805
18.8k
                sy -= phase1_y_steps;
1806
18.8k
                y_steps -= phase1_y_steps;
1807
18.8k
                if (y_steps == 0)
1808
0
                    goto endFallingLeftOnEdgeOfPixel;
1809
18.8k
            }
1810
1811
            /* Phase 3: precalculation */
1812
42.4k
            y_steps -= phase3_y_steps;
1813
42.4k
            assert((y_steps & (fixed_1 - 1)) == 0);
1814
1815
            /* Phase 2: */
1816
42.4k
            y_steps = fixed2int(y_steps);
1817
42.4k
            assert(y_steps >= 0);
1818
42.4k
            if (y_steps) {
1819
33.7k
                cursor_always_step(cr, -fixed_1, sx, skip);
1820
33.7k
                skip = 0;
1821
33.7k
                y_steps--;
1822
268k
                while (y_steps) {
1823
234k
                    cursor_always_step_inrange_vertical(cr, -fixed_1, sx);
1824
234k
                    y_steps--;
1825
234k
                }
1826
33.7k
            }
1827
1828
            /* Phase 3 */
1829
42.4k
            if (phase3_y_steps == 0) {
1830
20.6k
endFallingLeftOnEdgeOfPixel:
1831
20.6k
                cursor_always_step_inrange_vertical(cr, 0, sx);
1832
20.6k
                cursor_null(cr);
1833
21.7k
            } else {
1834
21.7k
                cursor_step(cr, -phase3_y_steps, sx, skip);
1835
21.7k
                assert(cr->left == sx && cr->right == sx);
1836
21.7k
            }
1837
487k
        } else if (sx < ex) {
1838
            /* Lines increasing in x. (Rightwards, falling) */
1839
241k
            int phase1_x_steps, phase3_x_steps;
1840
241k
            fixed x_steps = ex - sx;
1841
1842
            /* Phase 1: */
1843
241k
            if (phase1_y_steps) {
1844
187k
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
1845
187k
                x_steps -= phase1_x_steps;
1846
187k
                sx += phase1_x_steps;
1847
                /* Phase 1 in a falling line never moves us into a new scanline. */
1848
187k
                cursor_never_step_right(cr, -phase1_y_steps, sx);
1849
187k
                sy -= phase1_y_steps;
1850
187k
                y_steps -= phase1_y_steps;
1851
187k
                if (y_steps == 0)
1852
0
                    goto endFallingRightOnEdgeOfPixel;
1853
187k
            }
1854
1855
            /* Phase 3: precalculation */
1856
241k
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
1857
241k
            x_steps -= phase3_x_steps;
1858
241k
            y_steps -= phase3_y_steps;
1859
241k
            assert((y_steps & (fixed_1 - 1)) == 0);
1860
1861
            /* Phase 2: */
1862
241k
            y_steps = fixed2int(y_steps);
1863
241k
            assert(y_steps >= 0);
1864
241k
            if (y_steps) {
1865
                /* We want to change sx by x_steps in y_steps steps.
1866
                 * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/ey. */
1867
143k
                int x_inc = x_steps/y_steps;
1868
143k
                int n_inc = x_steps - (x_inc * y_steps);
1869
143k
                int f = y_steps/2;
1870
143k
                int d = y_steps;
1871
1872
143k
                cursor_always_step(cr, -fixed_1, sx, skip);
1873
143k
                skip = 0;
1874
143k
                sx += x_inc;
1875
143k
                f -= n_inc;
1876
143k
                if (f < 0)
1877
30.9k
                    f += d, sx++;
1878
143k
                cursor_right(cr, sx);
1879
143k
                y_steps--;
1880
1881
674k
                while (y_steps) {
1882
531k
                    cursor_always_inrange_step_right(cr, -fixed_1, sx);
1883
531k
                    sx += x_inc;
1884
531k
                    f -= n_inc;
1885
531k
                    if (f < 0)
1886
243k
                        f += d, sx++;
1887
531k
                    cursor_right(cr, sx);
1888
531k
                    y_steps--;
1889
531k
                }
1890
143k
            }
1891
1892
            /* Phase 3 */
1893
241k
            if (phase3_y_steps == 0) {
1894
47.8k
endFallingRightOnEdgeOfPixel:
1895
47.8k
                cursor_always_step_inrange_vertical(cr, 0, sx);
1896
47.8k
                cursor_null(cr);
1897
193k
            } else {
1898
193k
                cursor_step(cr, -phase3_y_steps, sx, skip);
1899
193k
                cursor_right(cr, ex);
1900
193k
                assert(cr->left == sx && cr->right == ex);
1901
193k
            }
1902
246k
        } else {
1903
            /* Lines decreasing in x. (Falling) */
1904
246k
            int phase1_x_steps, phase3_x_steps;
1905
246k
            fixed x_steps = sx - ex;
1906
1907
            /* Phase 1: */
1908
246k
            if (phase1_y_steps) {
1909
187k
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
1910
187k
                x_steps -= phase1_x_steps;
1911
187k
                sx -= phase1_x_steps;
1912
                /* Phase 1 in a falling line never moves us into a new scanline. */
1913
187k
                cursor_never_step_left(cr, -phase1_y_steps, sx);
1914
187k
                sy -= phase1_y_steps;
1915
187k
                y_steps -= phase1_y_steps;
1916
187k
                if (y_steps == 0)
1917
0
                    goto endFallingVerticalOnEdgeOfPixel;
1918
187k
            }
1919
1920
            /* Phase 3: precalculation */
1921
246k
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
1922
246k
            x_steps -= phase3_x_steps;
1923
246k
            y_steps -= phase3_y_steps;
1924
246k
            assert((y_steps & (fixed_1 - 1)) == 0);
1925
1926
            /* Phase 2: */
1927
246k
            y_steps = fixed2int(y_steps);
1928
246k
            assert(y_steps >= 0);
1929
246k
            if (y_steps) {
1930
                /* We want to change sx by x_steps in y_steps steps.
1931
                 * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
1932
145k
                int x_inc = x_steps/y_steps;
1933
145k
                int n_inc = x_steps - (x_inc * y_steps);
1934
145k
                int f = y_steps/2;
1935
145k
                int d = y_steps;
1936
1937
145k
                cursor_always_step(cr, -fixed_1, sx, skip);
1938
145k
                skip = 0;
1939
145k
                sx -= x_inc;
1940
145k
                f -= n_inc;
1941
145k
                if (f < 0)
1942
29.0k
                    f += d, sx--;
1943
145k
                cursor_left(cr, sx);
1944
145k
                y_steps--;
1945
1946
718k
                while (y_steps) {
1947
573k
                    cursor_always_inrange_step_left(cr, -fixed_1, sx);
1948
573k
                    sx -= x_inc;
1949
573k
                    f -= n_inc;
1950
573k
                    if (f < 0)
1951
256k
                        f += d, sx--;
1952
573k
                    cursor_left(cr, sx);
1953
573k
                    y_steps--;
1954
573k
                }
1955
145k
            }
1956
1957
            /* Phase 3 */
1958
246k
            if (phase3_y_steps == 0) {
1959
51.7k
endFallingVerticalOnEdgeOfPixel:
1960
51.7k
                cursor_always_step_inrange_vertical(cr, 0, sx);
1961
51.7k
                cursor_null(cr);
1962
194k
            } else {
1963
194k
                cursor_step(cr, -phase3_y_steps, sx, skip);
1964
194k
                cursor_left(cr, ex);
1965
194k
                assert(cr->left == ex && cr->right == sx);
1966
194k
            }
1967
246k
        }
1968
906k
endFalling: {}
1969
906k
    }
1970
1971
1.91M
end:
1972
1.91M
    if (truncated) {
1973
248k
        cr->left = saved_ex;
1974
248k
        cr->right = saved_ex;
1975
248k
        cr->y = saved_ey;
1976
248k
    }
1977
1.91M
}
1978
1979
static void mark_curve_app(cursor *cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth)
1980
15.8k
{
1981
15.8k
        int ax = (sx + c1x)>>1;
1982
15.8k
        int ay = (sy + c1y)>>1;
1983
15.8k
        int bx = (c1x + c2x)>>1;
1984
15.8k
        int by = (c1y + c2y)>>1;
1985
15.8k
        int cx = (c2x + ex)>>1;
1986
15.8k
        int cy = (c2y + ey)>>1;
1987
15.8k
        int dx = (ax + bx)>>1;
1988
15.8k
        int dy = (ay + by)>>1;
1989
15.8k
        int fx = (bx + cx)>>1;
1990
15.8k
        int fy = (by + cy)>>1;
1991
15.8k
        int gx = (dx + fx)>>1;
1992
15.8k
        int gy = (dy + fy)>>1;
1993
1994
15.8k
        assert(depth >= 0);
1995
15.8k
        if (depth == 0)
1996
15.2k
            mark_line_app(cr, sx, sy, ex, ey);
1997
598
        else {
1998
598
            depth--;
1999
598
            mark_curve_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth);
2000
598
            mark_curve_app(cr, gx, gy, fx, fy, cx, cy, ex, ey, depth);
2001
598
        }
2002
15.8k
}
2003
2004
static void mark_curve_big_app(cursor *cr, fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, int depth)
2005
0
{
2006
0
    fixed64 ax = (sx + c1x)>>1;
2007
0
    fixed64 ay = (sy + c1y)>>1;
2008
0
    fixed64 bx = (c1x + c2x)>>1;
2009
0
    fixed64 by = (c1y + c2y)>>1;
2010
0
    fixed64 cx = (c2x + ex)>>1;
2011
0
    fixed64 cy = (c2y + ey)>>1;
2012
0
    fixed64 dx = (ax + bx)>>1;
2013
0
    fixed64 dy = (ay + by)>>1;
2014
0
    fixed64 fx = (bx + cx)>>1;
2015
0
    fixed64 fy = (by + cy)>>1;
2016
0
    fixed64 gx = (dx + fx)>>1;
2017
0
    fixed64 gy = (dy + fy)>>1;
2018
2019
0
    assert(depth >= 0);
2020
0
    if (depth == 0)
2021
0
        mark_line_app(cr, (fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey);
2022
0
    else {
2023
0
        depth--;
2024
0
        mark_curve_big_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth);
2025
0
        mark_curve_big_app(cr, gx, gy, fx, fy, cx, cy, ex, ey, depth);
2026
0
    }
2027
0
}
2028
2029
static void mark_curve_top_app(cursor *cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth)
2030
14.6k
{
2031
14.6k
    fixed test = (sx^(sx<<1))|(sy^(sy<<1))|(c1x^(c1x<<1))|(c1y^(c1y<<1))|(c2x^(c2x<<1))|(c2y^(c2y<<1))|(ex^(ex<<1))|(ey^(ey<<1));
2032
2033
14.6k
    if (test < 0)
2034
0
        mark_curve_big_app(cr, sx, sy, c1x, c1y, c2x, c2y, ex, ey, depth);
2035
14.6k
    else
2036
14.6k
        mark_curve_app(cr, sx, sy, c1x, c1y, c2x, c2y, ex, ey, depth);
2037
14.6k
}
2038
2039
static int make_table_app(gx_device     * pdev,
2040
                          gx_path       * path,
2041
                          gs_fixed_rect * ibox,
2042
                          int           * scanlines,
2043
                          int          ** index,
2044
                          int          ** table)
2045
251k
{
2046
251k
    return make_table_template(pdev, path, ibox, 2, 0, scanlines, index, table);
2047
251k
}
2048
2049
static void
2050
fill_zero_app(int *row, const fixed *x)
2051
34
{
2052
34
    int n = *row = (*row)+2; /* Increment the count */
2053
34
    row[2*n-3] = (x[0]&~1);
2054
34
    row[2*n-2] = (x[1]&~1);
2055
34
    row[2*n-1] = (x[1]&~1)|1;
2056
34
    row[2*n  ] = x[1];
2057
34
}
2058
2059
int gx_scan_convert_app(gx_device     * gs_restrict pdev,
2060
                        gx_path       * gs_restrict path,
2061
                  const gs_fixed_rect * gs_restrict clip,
2062
                        gx_edgebuffer * gs_restrict edgebuffer,
2063
                        fixed                    fixed_flat)
2064
253k
{
2065
253k
    gs_fixed_rect  ibox;
2066
253k
    gs_fixed_rect  bbox;
2067
253k
    int            scanlines;
2068
253k
    const subpath *psub;
2069
253k
    int           *index;
2070
253k
    int           *table;
2071
253k
    int            i;
2072
253k
    cursor         cr;
2073
253k
    int            code;
2074
253k
    int            zero;
2075
2076
253k
    edgebuffer->index = NULL;
2077
253k
    edgebuffer->table = NULL;
2078
2079
    /* Bale out if no actual path. We see this with the clist */
2080
253k
    if (path->first_subpath == NULL)
2081
476
        return 0;
2082
2083
252k
    zero = make_bbox(path, clip, &bbox, &ibox, 0);
2084
252k
    if (zero < 0)
2085
0
        return zero;
2086
2087
252k
    if (ibox.q.y <= ibox.p.y)
2088
1.47k
        return 0;
2089
2090
251k
    code = make_table_app(pdev, path, &ibox, &scanlines, &index, &table);
2091
251k
    if (code != 0) /* > 0 means "retry with smaller height" */
2092
0
        return code;
2093
2094
251k
    if (scanlines == 0)
2095
0
        return 0;
2096
2097
251k
    if (zero) {
2098
34
        code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_app);
2099
251k
    } else {
2100
2101
    /* Step 2 continued: Now we run through the path, filling in the real
2102
     * values. */
2103
251k
    cr.scanlines = scanlines;
2104
251k
    cr.index     = index;
2105
251k
    cr.table     = table;
2106
251k
    cr.base      = ibox.p.y;
2107
717k
    for (psub = path->first_subpath; psub != 0;) {
2108
466k
        const segment *pseg = (const segment *)psub;
2109
466k
        fixed ex = pseg->pt.x;
2110
466k
        fixed ey = pseg->pt.y;
2111
466k
        fixed ix = ex;
2112
466k
        fixed iy = ey;
2113
466k
        fixed sx, sy;
2114
2115
466k
        if ((ey & 0xff) == 0) {
2116
4.34k
            cr.left  = max_fixed;
2117
4.34k
            cr.right = min_fixed;
2118
462k
        } else {
2119
462k
            cr.left = cr.right = ex;
2120
462k
        }
2121
466k
        cr.y = ey;
2122
466k
        cr.d = DIRN_UNSET;
2123
466k
        cr.first = 1;
2124
466k
        cr.saved = 0;
2125
2126
11.3M
        while ((pseg = pseg->next) != 0 &&
2127
11.1M
               pseg->type != s_start
2128
10.9M
            ) {
2129
10.9M
            sx = ex;
2130
10.9M
            sy = ey;
2131
10.9M
            ex = pseg->pt.x;
2132
10.9M
            ey = pseg->pt.y;
2133
2134
10.9M
            switch (pseg->type) {
2135
0
                default:
2136
0
                case s_start: /* Should never happen */
2137
0
                case s_dash:  /* We should never be seeing a dash here */
2138
0
                    assert("This should never happen" == NULL);
2139
0
                    break;
2140
14.6k
                case s_curve: {
2141
14.6k
                    const curve_segment *const pcur = (const curve_segment *)pseg;
2142
14.6k
                    int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat);
2143
2144
14.6k
                    mark_curve_top_app(&cr, sx, sy, pcur->p1.x, pcur->p1.y, pcur->p2.x, pcur->p2.y, ex, ey, k);
2145
14.6k
                    break;
2146
0
                }
2147
0
                case s_gap:
2148
10.5M
                case s_line:
2149
10.8M
                case s_line_close:
2150
10.8M
                    mark_line_app(&cr, sx, sy, ex, ey);
2151
10.8M
                    break;
2152
10.9M
            }
2153
10.9M
        }
2154
        /* And close any open segments */
2155
466k
        mark_line_app(&cr, ex, ey, ix, iy);
2156
466k
        cursor_flush(&cr, ex);
2157
466k
        psub = (const subpath *)pseg;
2158
466k
    }
2159
251k
    }
2160
2161
    /* Step 2 complete: We now have a complete list of intersection data in
2162
     * table, indexed by index. */
2163
2164
251k
    edgebuffer->base   = ibox.p.y;
2165
251k
    edgebuffer->height = scanlines;
2166
251k
    edgebuffer->xmin   = ibox.p.x;
2167
251k
    edgebuffer->xmax   = ibox.q.x;
2168
251k
    edgebuffer->index  = index;
2169
251k
    edgebuffer->table  = table;
2170
2171
#ifdef DEBUG_SCAN_CONVERTER
2172
    if (debugging_scan_converter) {
2173
        dlprintf("Before sorting:\n");
2174
        gx_edgebuffer_print_app(edgebuffer);
2175
    }
2176
#endif
2177
2178
    /* Step 3: Sort the intersects on x */
2179
2.14M
    for (i=0; i < scanlines; i++) {
2180
1.89M
        int *row = &table[index[i]];
2181
1.89M
        int  rowlen = *row++;
2182
2183
        /* Bubblesort short runs, qsort longer ones. */
2184
        /* FIXME: Verify the figure 6 below */
2185
1.89M
        if (rowlen <= 6) {
2186
1.87M
            int j, k;
2187
4.22M
            for (j = 0; j < rowlen-1; j++) {
2188
2.35M
                int * gs_restrict t = &row[j<<1];
2189
5.46M
                for (k = j+1; k < rowlen; k++) {
2190
3.11M
                    int * gs_restrict s = &row[k<<1];
2191
3.11M
                    int tmp;
2192
3.11M
                    if (t[0] < s[0])
2193
1.16M
                        continue;
2194
1.94M
                    if (t[0] > s[0])
2195
1.94M
                        goto swap01;
2196
1.38k
                    if (t[1] <= s[1])
2197
1.15k
                        continue;
2198
230
                    if (0) {
2199
1.94M
swap01:
2200
1.94M
                        tmp = t[0], t[0] = s[0], s[0] = tmp;
2201
1.94M
                    }
2202
1.94M
                    tmp = t[1], t[1] = s[1], s[1] = tmp;
2203
1.94M
                }
2204
2.35M
            }
2205
1.87M
        } else
2206
18.3k
            qsort(row, rowlen, 2*sizeof(int), edgecmp);
2207
1.89M
    }
2208
2209
251k
    return 0;
2210
251k
}
2211
2212
/* Step 5: Filter the intersections according to the rules */
2213
int
2214
gx_filter_edgebuffer_app(gx_device       * gs_restrict pdev,
2215
                         gx_edgebuffer   * gs_restrict edgebuffer,
2216
                         int                        rule)
2217
253k
{
2218
253k
    int i;
2219
2220
#ifdef DEBUG_SCAN_CONVERTER
2221
    if (debugging_scan_converter) {
2222
        dlprintf("Before filtering:\n");
2223
        gx_edgebuffer_print_app(edgebuffer);
2224
    }
2225
#endif
2226
2227
2.14M
    for (i=0; i < edgebuffer->height; i++) {
2228
1.89M
        int *row      = &edgebuffer->table[edgebuffer->index[i]];
2229
1.89M
        int  rowlen   = *row++;
2230
1.89M
        int *rowstart = row;
2231
1.89M
        int *rowout   = row;
2232
1.89M
        int  ll, lr, rl, rr, wind, marked_to;
2233
2234
        /* Avoid double setting pixels, by keeping where we have marked to. */
2235
1.89M
        marked_to = INT_MIN;
2236
4.02M
        while (rowlen > 0) {
2237
2.13M
            if (rule == gx_rule_even_odd) {
2238
                /* Even Odd */
2239
61.0k
                ll = (*row++)&~1;
2240
61.0k
                lr = *row;
2241
61.0k
                row += 2;
2242
61.0k
                rowlen-=2;
2243
2244
                /* We will fill solidly from ll to at least lr, possibly further */
2245
61.0k
                assert(rowlen >= 0);
2246
61.0k
                rr = (*row++);
2247
61.0k
                if (rr > lr)
2248
58.3k
                    lr = rr;
2249
2.07M
            } else {
2250
                /* Non-Zero */
2251
2.07M
                int w;
2252
2253
2.07M
                ll = *row++;
2254
2.07M
                lr = *row++;
2255
2.07M
                wind = -(ll&1) | 1;
2256
2.07M
                ll &= ~1;
2257
2.07M
                rowlen--;
2258
2259
2.07M
                assert(rowlen > 0);
2260
2.30M
                do {
2261
2.30M
                    rl = *row++;
2262
2.30M
                    rr = *row++;
2263
2.30M
                    w = -(rl&1) | 1;
2264
2.30M
                    rl &= ~1;
2265
2.30M
                    rowlen--;
2266
2.30M
                    if (rr > lr)
2267
2.20M
                        lr = rr;
2268
2.30M
                    wind += w;
2269
2.30M
                    if (wind == 0)
2270
2.07M
                        break;
2271
2.30M
                } while (rowlen > 0);
2272
2.07M
            }
2273
2274
2.13M
            if (marked_to >= lr)
2275
900
                continue;
2276
2277
2.13M
            if (marked_to >= ll) {
2278
18.2k
                if (rowout == rowstart)
2279
0
                    ll = marked_to;
2280
18.2k
                else {
2281
18.2k
                    rowout -= 2;
2282
18.2k
                    ll = *rowout;
2283
18.2k
                }
2284
18.2k
            }
2285
2286
2.13M
            if (lr >= ll) {
2287
2.13M
                *rowout++ = ll;
2288
2.13M
                *rowout++ = lr;
2289
2.13M
                marked_to = lr;
2290
2.13M
            }
2291
2.13M
        }
2292
1.89M
        rowstart[-1] = rowout - rowstart;
2293
1.89M
    }
2294
253k
    return 0;
2295
253k
}
2296
2297
/* Step 6: Fill */
2298
int
2299
gx_fill_edgebuffer_app(gx_device       * gs_restrict pdev,
2300
                 const gx_device_color * gs_restrict pdevc,
2301
                       gx_edgebuffer   * gs_restrict edgebuffer,
2302
                       int                        log_op)
2303
253k
{
2304
253k
    int i, code;
2305
2306
2.14M
    for (i=0; i < edgebuffer->height; i++) {
2307
1.89M
        int *row    = &edgebuffer->table[edgebuffer->index[i]];
2308
1.89M
        int  rowlen = *row++;
2309
1.89M
        int  left, right;
2310
2311
4.00M
        while (rowlen > 0) {
2312
2.11M
            left  = *row++;
2313
2.11M
            right = *row++;
2314
2.11M
            left  = fixed2int(left);
2315
2.11M
            right = fixed2int(right + fixed_1 - 1);
2316
2.11M
            rowlen -= 2;
2317
2318
2.11M
            right -= left;
2319
2.11M
            if (right > 0) {
2320
2.11M
                if (log_op < 0)
2321
1.67M
                    code = dev_proc(pdev, fill_rectangle)(pdev, left, edgebuffer->base+i, right, 1, pdevc->colors.pure);
2322
437k
                else
2323
437k
                    code = gx_fill_rectangle_device_rop(left, edgebuffer->base+i, right, 1, pdevc, pdev, (gs_logical_operation_t)log_op);
2324
2.11M
                if (code < 0)
2325
0
                    return code;
2326
2.11M
            }
2327
2.11M
        }
2328
1.89M
    }
2329
253k
    return 0;
2330
253k
}
2331
2332
/* Centre of a pixel trapezoid routines */
2333
2334
static int intcmp_tr(const void *a, const void *b)
2335
2.83M
{
2336
2.83M
    int left  = ((int*)a)[0];
2337
2.83M
    int right = ((int*)b)[0];
2338
2.83M
    if (left != right)
2339
2.83M
        return left - right;
2340
5.02k
    return ((int*)a)[1] - ((int*)b)[1];
2341
2.83M
}
2342
2343
#ifdef DEBUG_SCAN_CONVERTER
2344
static void
2345
gx_edgebuffer_print_tr(gx_edgebuffer * edgebuffer)
2346
{
2347
    int i;
2348
2349
    if (!debugging_scan_converter)
2350
        return;
2351
2352
    dlprintf1("Edgebuffer %x\n", edgebuffer);
2353
    dlprintf4("xmin=%x xmax=%x base=%x height=%x\n",
2354
              edgebuffer->xmin, edgebuffer->xmax, edgebuffer->base, edgebuffer->height);
2355
    for (i=0; i < edgebuffer->height; i++)
2356
    {
2357
        int  offset = edgebuffer->index[i];
2358
        int *row    = &edgebuffer->table[offset];
2359
        int count   = *row++;
2360
        dlprintf3("%d @ %d: %d =", i, offset, count);
2361
        while (count-- > 0) {
2362
            int e  = *row++;
2363
            int id = *row++;
2364
            dlprintf3(" %x%c%d", e, id&1 ? 'v' : '^', id>>1);
2365
        }
2366
        dlprintf("\n");
2367
    }
2368
}
2369
#endif
2370
2371
static void mark_line_tr(fixed sx, fixed sy, fixed ex, fixed ey, int base_y, int height, int *table, int *index, int id)
2372
27.1M
{
2373
27.1M
    int64_t delta;
2374
27.1M
    int iy, ih;
2375
27.1M
    fixed clip_sy, clip_ey;
2376
27.1M
    int dirn = DIRN_UP;
2377
27.1M
    int *row;
2378
2379
#ifdef DEBUG_SCAN_CONVERTER
2380
    if (debugging_scan_converter)
2381
        dlprintf6("Marking line (tr) from %x,%x to %x,%x (%x,%x)\n", sx, sy, ex, ey, fixed2int(sy + fixed_half-1) - base_y, fixed2int(ey + fixed_half-1) - base_y);
2382
#endif
2383
#ifdef DEBUG_OUTPUT_SC_AS_PS
2384
    dlprintf("0.001 setlinewidth 0 0 0 setrgbcolor %%PS\n");
2385
    coord("moveto", sx, sy);
2386
    coord("lineto", ex, ey);
2387
    dlprintf("stroke %%PS\n");
2388
#endif
2389
2390
27.1M
    if (fixed2int(sy + fixed_half-1) == fixed2int(ey + fixed_half-1))
2391
17.2M
        return;
2392
9.91M
    if (sy > ey) {
2393
4.79M
        int t;
2394
4.79M
        t = sy; sy = ey; ey = t;
2395
4.79M
        t = sx; sx = ex; ex = t;
2396
4.79M
        dirn = DIRN_DOWN;
2397
4.79M
    }
2398
    /* Lines go from sy to ey, closed at the start, open at the end. */
2399
    /* We clip them to a region to make them closed at both ends. */
2400
    /* Thus the first scanline marked (>= sy) is: */
2401
9.91M
    clip_sy = ((sy + fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
2402
    /* The last scanline marked (< ey) is: */
2403
9.91M
    clip_ey = ((ey - fixed_half - 1) & ~(fixed_1-1)) | fixed_half;
2404
    /* Now allow for banding */
2405
9.91M
    if (clip_sy < int2fixed(base_y) + fixed_half)
2406
7.96M
        clip_sy = int2fixed(base_y) + fixed_half;
2407
9.91M
    if (ey <= clip_sy)
2408
7.68M
        return;
2409
2.22M
    if (clip_ey > int2fixed(base_y + height - 1) + fixed_half)
2410
1.09M
        clip_ey = int2fixed(base_y + height - 1) + fixed_half;
2411
2.22M
    if (sy > clip_ey)
2412
855k
        return;
2413
1.37M
    delta = (int64_t)clip_sy - (int64_t)sy;
2414
1.37M
    if (delta > 0)
2415
1.34M
    {
2416
1.34M
        int64_t dx = (int64_t)ex - (int64_t)sx;
2417
1.34M
        int64_t dy = (int64_t)ey - (int64_t)sy;
2418
1.34M
        int advance = (int)((dx * delta + (dy>>1)) / dy);
2419
1.34M
        sx += advance;
2420
1.34M
        sy += delta;
2421
1.34M
    }
2422
1.37M
    delta = (int64_t)ey - (int64_t)clip_ey;
2423
1.37M
    if (delta > 0)
2424
1.37M
    {
2425
1.37M
        int64_t dx = (int64_t)ex - (int64_t)sx;
2426
1.37M
        int64_t dy = (int64_t)ey - (int64_t)sy;
2427
1.37M
        int advance = (int)((dx * delta + (dy>>1)) / dy);
2428
1.37M
        ex -= advance;
2429
1.37M
        ey -= delta;
2430
1.37M
    }
2431
1.37M
    ex -= sx;
2432
1.37M
    ey -= sy;
2433
1.37M
    ih = fixed2int(ey);
2434
1.37M
    assert(ih >= 0);
2435
1.37M
    iy = fixed2int(sy) - base_y;
2436
#ifdef DEBUG_SCAN_CONVERTER
2437
    if (debugging_scan_converter)
2438
        dlprintf2("    iy=%x ih=%x\n", iy, ih);
2439
#endif
2440
1.37M
    assert(iy >= 0 && iy < height);
2441
1.37M
    id = (id<<1) | dirn;
2442
    /* We always cross at least one scanline */
2443
1.37M
    row = &table[index[iy]];
2444
1.37M
    *row = (*row)+1; /* Increment the count */
2445
1.37M
    row[*row * 2 - 1] = sx;
2446
1.37M
    row[*row * 2    ] = id;
2447
1.37M
    if (ih == 0)
2448
734k
        return;
2449
636k
    if (ex >= 0) {
2450
458k
        int x_inc, n_inc, f;
2451
2452
        /* We want to change sx by ex in ih steps. So each step, we add
2453
         * ex/ih to sx. That's x_inc + n_inc/ih.
2454
         */
2455
458k
        x_inc = ex/ih;
2456
458k
        n_inc = ex-(x_inc*ih);
2457
458k
        f     = ih>>1;
2458
458k
        delta = ih;
2459
6.27M
        do {
2460
6.27M
            int count;
2461
6.27M
            iy++;
2462
6.27M
            sx += x_inc;
2463
6.27M
            f  -= n_inc;
2464
6.27M
            if (f < 0) {
2465
938k
                f += ih;
2466
938k
                sx++;
2467
938k
            }
2468
6.27M
            assert(iy >= 0 && iy < height);
2469
6.27M
            row = &table[index[iy]];
2470
6.27M
            count = *row = (*row)+1; /* Increment the count */
2471
6.27M
            row[count * 2 - 1] = sx;
2472
6.27M
            row[count * 2    ] = id;
2473
6.27M
        }
2474
6.27M
        while (--delta);
2475
458k
    } else {
2476
177k
        int x_dec, n_dec, f;
2477
2478
177k
        ex = -ex;
2479
        /* We want to change sx by ex in ih steps. So each step, we subtract
2480
         * ex/ih from sx. That's x_dec + n_dec/ih.
2481
         */
2482
177k
        x_dec = ex/ih;
2483
177k
        n_dec = ex-(x_dec*ih);
2484
177k
        f     = ih>>1;
2485
177k
        delta = ih;
2486
2.44M
        do {
2487
2.44M
            int count;
2488
2.44M
            iy++;
2489
2.44M
            sx -= x_dec;
2490
2.44M
            f  -= n_dec;
2491
2.44M
            if (f < 0) {
2492
1.00M
                f += ih;
2493
1.00M
                sx--;
2494
1.00M
            }
2495
2.44M
            assert(iy >= 0 && iy < height);
2496
2.44M
            row = &table[index[iy]];
2497
2.44M
            count = *row = (*row)+1; /* Increment the count */
2498
2.44M
            row[count * 2 - 1] = sx;
2499
2.44M
            row[count * 2    ] = id;
2500
2.44M
         }
2501
2.44M
         while (--delta);
2502
177k
    }
2503
636k
}
2504
2505
static void mark_curve_tr(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int *id, int depth)
2506
0
{
2507
0
    fixed ax = (sx + c1x)>>1;
2508
0
    fixed ay = (sy + c1y)>>1;
2509
0
    fixed bx = (c1x + c2x)>>1;
2510
0
    fixed by = (c1y + c2y)>>1;
2511
0
    fixed cx = (c2x + ex)>>1;
2512
0
    fixed cy = (c2y + ey)>>1;
2513
0
    fixed dx = (ax + bx)>>1;
2514
0
    fixed dy = (ay + by)>>1;
2515
0
    fixed fx = (bx + cx)>>1;
2516
0
    fixed fy = (by + cy)>>1;
2517
0
    fixed gx = (dx + fx)>>1;
2518
0
    fixed gy = (dy + fy)>>1;
2519
2520
0
    assert(depth >= 0);
2521
0
    if (depth == 0) {
2522
0
        *id += 1;
2523
0
        mark_line_tr(sx, sy, ex, ey, base_y, height, table, index, *id);
2524
0
    } else {
2525
0
        depth--;
2526
0
        mark_curve_tr(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, id, depth);
2527
0
        mark_curve_tr(gx, gy, fx, fy, cx, cy, ex, ey, base_y, height, table, index, id, depth);
2528
0
    }
2529
0
}
2530
2531
static void mark_curve_big_tr(fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, fixed base_y, fixed height, int *table, int *index, int *id, int depth)
2532
0
{
2533
0
    fixed64 ax = (sx + c1x)>>1;
2534
0
    fixed64 ay = (sy + c1y)>>1;
2535
0
    fixed64 bx = (c1x + c2x)>>1;
2536
0
    fixed64 by = (c1y + c2y)>>1;
2537
0
    fixed64 cx = (c2x + ex)>>1;
2538
0
    fixed64 cy = (c2y + ey)>>1;
2539
0
    fixed64 dx = (ax + bx)>>1;
2540
0
    fixed64 dy = (ay + by)>>1;
2541
0
    fixed64 fx = (bx + cx)>>1;
2542
0
    fixed64 fy = (by + cy)>>1;
2543
0
    fixed64 gx = (dx + fx)>>1;
2544
0
    fixed64 gy = (dy + fy)>>1;
2545
2546
0
    assert(depth >= 0);
2547
0
    if (depth == 0) {
2548
0
        *id += 1;
2549
0
        mark_line_tr((fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, base_y, height, table, index, *id);
2550
0
    } else {
2551
0
        depth--;
2552
0
        mark_curve_big_tr(sx, sy, ax, ay, dx, dy, gx, gy, base_y, height, table, index, id, depth);
2553
0
        mark_curve_big_tr(gx, gy, fx, fy, cx, cy, ex, ey, base_y, height, table, index, id, depth);
2554
0
    }
2555
0
}
2556
2557
static void mark_curve_top_tr(fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, fixed base_y, fixed height, int *table, int *index, int *id, int depth)
2558
0
{
2559
0
    fixed test = (sx^(sx<<1))|(sy^(sy<<1))|(c1x^(c1x<<1))|(c1y^(c1y<<1))|(c2x^(c2x<<1))|(c2y^(c2y<<1))|(ex^(ex<<1))|(ey^(ey<<1));
2560
2561
0
    if (test < 0)
2562
0
        mark_curve_big_tr(sx, sy, c1x, c1y, c2x, c2y, ex, ey, base_y, height, table, index, id, depth);
2563
0
    else
2564
0
        mark_curve_tr(sx, sy, c1x, c1y, c2x, c2y, ex, ey, base_y, height, table, index, id, depth);
2565
0
}
2566
2567
static int make_table_tr(gx_device     * pdev,
2568
                         gx_path       * path,
2569
                         gs_fixed_rect * ibox,
2570
                         int           * scanlines,
2571
                         int          ** index,
2572
                         int          ** table)
2573
170k
{
2574
170k
    return make_table_template(pdev, path, ibox, 2, 1, scanlines, index, table);
2575
170k
}
2576
2577
static void
2578
fill_zero_tr(int *row, const fixed *x)
2579
0
{
2580
0
    int n = *row = (*row)+2; /* Increment the count */
2581
0
    row[2*n-3] = x[0];
2582
0
    row[2*n-2] = 0;
2583
0
    row[2*n-1] = x[1];
2584
0
    row[2*n  ] = 1;
2585
0
}
2586
2587
int gx_scan_convert_tr(gx_device     * gs_restrict pdev,
2588
                       gx_path       * gs_restrict path,
2589
                 const gs_fixed_rect * gs_restrict clip,
2590
                       gx_edgebuffer * gs_restrict edgebuffer,
2591
                       fixed                    fixed_flat)
2592
323k
{
2593
323k
    gs_fixed_rect  ibox;
2594
323k
    gs_fixed_rect  bbox;
2595
323k
    int            scanlines;
2596
323k
    const subpath *psub;
2597
323k
    int           *index;
2598
323k
    int           *table;
2599
323k
    int            i;
2600
323k
    int            code;
2601
323k
    int            id = 0;
2602
323k
    int            zero;
2603
2604
323k
    edgebuffer->index = NULL;
2605
323k
    edgebuffer->table = NULL;
2606
2607
    /* Bale out if no actual path. We see this with the clist */
2608
323k
    if (path->first_subpath == NULL)
2609
149k
        return 0;
2610
2611
174k
    zero = make_bbox(path, clip, &bbox, &ibox, fixed_half);
2612
174k
    if (zero < 0)
2613
0
        return zero;
2614
2615
174k
    if (ibox.q.y <= ibox.p.y)
2616
3.99k
        return 0;
2617
2618
170k
    code = make_table_tr(pdev, path, &ibox, &scanlines, &index, &table);
2619
170k
    if (code != 0) /* > 0 means "retry with smaller height" */
2620
3
        return code;
2621
2622
170k
    if (scanlines == 0)
2623
0
        return 0;
2624
2625
170k
    if (zero) {
2626
0
        code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_tr);
2627
170k
    } else {
2628
2629
    /* Step 3: Now we run through the path, filling in the real
2630
     * values. */
2631
376k
    for (psub = path->first_subpath; psub != 0;) {
2632
206k
        const segment *pseg = (const segment *)psub;
2633
206k
        fixed ex = pseg->pt.x;
2634
206k
        fixed ey = pseg->pt.y;
2635
206k
        fixed ix = ex;
2636
206k
        fixed iy = ey;
2637
2638
28.0M
        while ((pseg = pseg->next) != 0 &&
2639
27.9M
               pseg->type != s_start
2640
27.8M
            ) {
2641
27.8M
            fixed sx = ex;
2642
27.8M
            fixed sy = ey;
2643
27.8M
            ex = pseg->pt.x;
2644
27.8M
            ey = pseg->pt.y;
2645
2646
27.8M
            switch (pseg->type) {
2647
0
                default:
2648
0
                case s_start: /* Should never happen */
2649
0
                case s_dash:  /* We should never be seeing a dash here */
2650
0
                    assert("This should never happen" == NULL);
2651
0
                    break;
2652
0
                case s_curve: {
2653
0
                    const curve_segment *const pcur = (const curve_segment *)pseg;
2654
0
                    int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat);
2655
2656
0
                    mark_curve_top_tr(sx, sy, pcur->p1.x, pcur->p1.y, pcur->p2.x, pcur->p2.y, ex, ey, ibox.p.y, scanlines, table, index, &id, k);
2657
0
                    break;
2658
0
                }
2659
0
                case s_gap:
2660
27.7M
                case s_line:
2661
27.8M
                case s_line_close:
2662
27.8M
                    if (sy != ey)
2663
27.1M
                        mark_line_tr(sx, sy, ex, ey, ibox.p.y, scanlines, table, index, ++id);
2664
27.8M
                    break;
2665
27.8M
            }
2666
27.8M
        }
2667
        /* And close any open segments */
2668
206k
        if (iy != ey)
2669
48.1k
            mark_line_tr(ex, ey, ix, iy, ibox.p.y, scanlines, table, index, ++id);
2670
206k
        psub = (const subpath *)pseg;
2671
206k
    }
2672
170k
    }
2673
2674
    /*if (zero) {
2675
        if (table[0] == 0) { */
2676
            /* Zero height rectangle fills a span */
2677
/*          table[0] = 2;
2678
            table[1] = int2fixed(fixed2int(bbox.p.x + fixed_half));
2679
            table[2] = 0;
2680
            table[3] = int2fixed(fixed2int(bbox.q.x + fixed_half));
2681
            table[4] = 1;
2682
        }
2683
    }*/
2684
2685
    /* Step 2 complete: We now have a complete list of intersection data in
2686
     * table, indexed by index. */
2687
2688
170k
    edgebuffer->base   = ibox.p.y;
2689
170k
    edgebuffer->height = scanlines;
2690
170k
    edgebuffer->xmin   = ibox.p.x;
2691
170k
    edgebuffer->xmax   = ibox.q.x;
2692
170k
    edgebuffer->index  = index;
2693
170k
    edgebuffer->table  = table;
2694
2695
#ifdef DEBUG_SCAN_CONVERTER
2696
    if (debugging_scan_converter) {
2697
        dlprintf("Before sorting:\n");
2698
        gx_edgebuffer_print_tr(edgebuffer);
2699
    }
2700
#endif
2701
2702
    /* Step 4: Sort the intersects on x */
2703
3.66M
    for (i=0; i < scanlines; i++) {
2704
3.49M
        int *row = &table[index[i]];
2705
3.49M
        int  rowlen = *row++;
2706
2707
        /* Bubblesort short runs, qsort longer ones. */
2708
        /* FIXME: Verify the figure 6 below */
2709
3.49M
        if (rowlen <= 6) {
2710
3.45M
            int j, k;
2711
9.19M
            for (j = 0; j < rowlen-1; j++) {
2712
5.74M
                int * gs_restrict t = &row[j<<1];
2713
15.6M
                for (k = j+1; k < rowlen; k++) {
2714
9.89M
                    int * gs_restrict s = &row[k<<1];
2715
9.89M
                    int tmp;
2716
9.89M
                    if (t[0] < s[0])
2717
6.26M
                        continue;
2718
3.63M
                    if (t[0] == s[0]) {
2719
117k
                        if (t[1] <= s[1])
2720
117k
                            continue;
2721
117k
                    } else
2722
3.51M
                        tmp = t[0], t[0] = s[0], s[0] = tmp;
2723
3.51M
                    tmp = t[1], t[1] = s[1], s[1] = tmp;
2724
3.51M
                }
2725
5.74M
            }
2726
3.45M
        } else
2727
45.5k
            qsort(row, rowlen, 2*sizeof(int), intcmp_tr);
2728
3.49M
    }
2729
2730
170k
    return 0;
2731
170k
}
2732
2733
/* Step 5: Filter the intersections according to the rules */
2734
int
2735
gx_filter_edgebuffer_tr(gx_device       * gs_restrict pdev,
2736
                        gx_edgebuffer   * gs_restrict edgebuffer,
2737
                        int                           rule)
2738
323k
{
2739
323k
    int i;
2740
2741
#ifdef DEBUG_SCAN_CONVERTER
2742
    if (debugging_scan_converter) {
2743
        dlprintf("Before filtering\n");
2744
        gx_edgebuffer_print_tr(edgebuffer);
2745
    }
2746
#endif
2747
2748
3.82M
    for (i=0; i < edgebuffer->height; i++) {
2749
3.49M
        int *row      = &edgebuffer->table[edgebuffer->index[i]];
2750
3.49M
        int  rowlen   = *row++;
2751
3.49M
        int *rowstart = row;
2752
3.49M
        int *rowout   = row;
2753
2754
8.52M
        while (rowlen > 0) {
2755
5.02M
            int left, lid, right, rid;
2756
2757
5.02M
            if (rule == gx_rule_even_odd) {
2758
                /* Even Odd */
2759
1.59k
                left  = *row++;
2760
1.59k
                lid   = *row++;
2761
1.59k
                right = *row++;
2762
1.59k
                rid   = *row++;
2763
1.59k
                rowlen -= 2;
2764
5.02M
            } else {
2765
                /* Non-Zero */
2766
5.02M
                int w;
2767
2768
5.02M
                left = *row++;
2769
5.02M
                lid  = *row++;
2770
5.02M
                w = ((lid&1)-1) | 1;
2771
5.02M
                rowlen--;
2772
5.05M
                do {
2773
5.05M
                    right = *row++;
2774
5.05M
                    rid   = *row++;
2775
5.05M
                    rowlen--;
2776
5.05M
                    w += ((rid&1)-1) | 1;
2777
5.05M
                } while (w != 0);
2778
5.02M
            }
2779
2780
5.02M
            if (right > left) {
2781
4.91M
                *rowout++ = left;
2782
4.91M
                *rowout++ = lid;
2783
4.91M
                *rowout++ = right;
2784
4.91M
                *rowout++ = rid;
2785
4.91M
            }
2786
5.02M
        }
2787
3.49M
        rowstart[-1] = (rowout-rowstart)>>1;
2788
3.49M
    }
2789
323k
    return 0;
2790
323k
}
2791
2792
/* Step 6: Fill the edgebuffer */
2793
int
2794
gx_fill_edgebuffer_tr(gx_device       * gs_restrict pdev,
2795
                const gx_device_color * gs_restrict pdevc,
2796
                      gx_edgebuffer   * gs_restrict edgebuffer,
2797
                      int                        log_op)
2798
323k
{
2799
323k
    int i, j, code;
2800
323k
    int mfb = pdev->max_fill_band;
2801
2802
#ifdef DEBUG_SCAN_CONVERTER
2803
    if (debugging_scan_converter) {
2804
        dlprintf("Before filling\n");
2805
        gx_edgebuffer_print_tr(edgebuffer);
2806
    }
2807
#endif
2808
2809
896k
    for (i=0; i < edgebuffer->height; ) {
2810
573k
        int *row    = &edgebuffer->table[edgebuffer->index[i]];
2811
573k
        int  rowlen = *row++;
2812
573k
        int *row2;
2813
573k
        int *rowptr;
2814
573k
        int *row2ptr;
2815
573k
        int y_band_max;
2816
2817
573k
        if (mfb) {
2818
0
            y_band_max = (i & ~(mfb-1)) + mfb;
2819
0
            if (y_band_max > edgebuffer->height)
2820
0
                y_band_max = edgebuffer->height;
2821
573k
        } else {
2822
573k
            y_band_max = edgebuffer->height;
2823
573k
        }
2824
2825
        /* See how many scanlines match i */
2826
3.49M
        for (j = i+1; j < y_band_max; j++) {
2827
3.32M
            int row2len;
2828
2829
3.32M
            row2    = &edgebuffer->table[edgebuffer->index[j]];
2830
3.32M
            row2len = *row2++;
2831
3.32M
            row2ptr = row2;
2832
3.32M
            rowptr  = row;
2833
2834
3.32M
            if (rowlen != row2len)
2835
54.2k
                break;
2836
11.2M
            while (row2len > 0) {
2837
8.37M
                if ((rowptr[1]&~1) != (row2ptr[1]&~1))
2838
349k
                    goto rowdifferent;
2839
8.02M
                rowptr  += 2;
2840
8.02M
                row2ptr += 2;
2841
8.02M
                row2len--;
2842
8.02M
            }
2843
3.27M
        }
2844
573k
rowdifferent:{}
2845
2846
        /* So j is the first scanline that doesn't match i */
2847
2848
573k
        if (j == i+1) {
2849
972k
            while (rowlen > 0) {
2850
644k
                int left, right;
2851
2852
644k
                left  = row[0];
2853
644k
                right = row[2];
2854
644k
                row += 4;
2855
644k
                rowlen -= 2;
2856
2857
644k
                left  = fixed2int(left + fixed_half);
2858
644k
                right = fixed2int(right + fixed_half);
2859
644k
                right -= left;
2860
644k
                if (right > 0) {
2861
#ifdef DEBUG_OUTPUT_SC_AS_PS
2862
                    dlprintf("0.001 setlinewidth 1 0 1 setrgbcolor %% purple %%PS\n");
2863
                    coord("moveto", int2fixed(left), int2fixed(edgebuffer->base+i));
2864
                    coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i));
2865
                    coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i+1));
2866
                    coord("lineto", int2fixed(left), int2fixed(edgebuffer->base+i+1));
2867
                    dlprintf("closepath stroke %%PS\n");
2868
#endif
2869
642k
                    if (log_op < 0)
2870
0
                        code = dev_proc(pdev, fill_rectangle)(pdev, left, edgebuffer->base+i, right, 1, pdevc->colors.pure);
2871
642k
                    else
2872
642k
                        code = gx_fill_rectangle_device_rop(left, edgebuffer->base+i, right, 1, pdevc, pdev, (gs_logical_operation_t)log_op);
2873
642k
                    if (code < 0)
2874
0
                        return code;
2875
642k
                }
2876
644k
            }
2877
328k
        } else {
2878
245k
            gs_fixed_edge le;
2879
245k
            gs_fixed_edge re;
2880
2881
#ifdef DEBUG_OUTPUT_SC_AS_PS
2882
#ifdef DEBUG_OUTPUT_SC_AS_PS_TRAPS_AS_RECTS
2883
            int k;
2884
            for (k = i; k < j; k++)
2885
            {
2886
                int row2len;
2887
                int left, right;
2888
                row2    = &edgebuffer->table[edgebuffer->index[k]];
2889
                row2len = *row2++;
2890
                while (row2len > 0) {
2891
                    left = row2[0];
2892
                    right = row2[2];
2893
                    row2 += 4;
2894
                    row2len -= 2;
2895
2896
                    left  = fixed2int(left + fixed_half);
2897
                    right = fixed2int(right + fixed_half);
2898
                    right -= left;
2899
                    if (right > 0) {
2900
                        dlprintf("0.001 setlinewidth 1 0 0.5 setrgbcolor %%PS\n");
2901
                        coord("moveto", int2fixed(left), int2fixed(edgebuffer->base+k));
2902
                        coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+k));
2903
                        coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+k+1));
2904
                        coord("lineto", int2fixed(left), int2fixed(edgebuffer->base+k+1));
2905
                        dlprintf("closepath stroke %%PS\n");
2906
                    }
2907
                }
2908
            }
2909
#endif
2910
#endif
2911
2912
245k
            le.start.y = re.start.y = int2fixed(edgebuffer->base+i) + fixed_half;
2913
245k
            le.end.y   = re.end.y   = int2fixed(edgebuffer->base+j) - (fixed_half-1);
2914
245k
            row2    = &edgebuffer->table[edgebuffer->index[j-1]+1];
2915
568k
            while (rowlen > 0) {
2916
323k
                le.start.x = row[0];
2917
323k
                re.start.x = row[2];
2918
323k
                le.end.x   = row2[0];
2919
323k
                re.end.x   = row2[2];
2920
323k
                row += 4;
2921
323k
                row2 += 4;
2922
323k
                rowlen -= 2;
2923
2924
323k
                assert(re.start.x >= le.start.x);
2925
323k
                assert(re.end.x >= le.end.x);
2926
2927
#ifdef DEBUG_OUTPUT_SC_AS_PS
2928
                dlprintf("0.001 setlinewidth 0 1 1 setrgbcolor %%cyan %%PS\n");
2929
                coord("moveto", le.start.x, le.start.y);
2930
                coord("lineto", le.end.x, le.end.y);
2931
                coord("lineto", re.end.x, re.end.y);
2932
                coord("lineto", re.start.x, re.start.y);
2933
                dlprintf("closepath stroke %%PS\n");
2934
#endif
2935
323k
                code = dev_proc(pdev, fill_trapezoid)(
2936
323k
                                pdev,
2937
323k
                                &le,
2938
323k
                                &re,
2939
323k
                                le.start.y,
2940
323k
                                le.end.y,
2941
323k
                                0, /* bool swap_axes */
2942
323k
                                pdevc, /*const gx_drawing_color *pdcolor */
2943
323k
                                log_op);
2944
323k
                if (code < 0)
2945
0
                    return code;
2946
323k
            }
2947
245k
        }
2948
2949
573k
        i = j;
2950
573k
    }
2951
323k
    return 0;
2952
323k
}
2953
2954
/* Any part of a pixel trapezoid routines */
2955
2956
static int edgecmp_tr(const void *a, const void *b)
2957
475M
{
2958
475M
    int left  = ((int*)a)[0];
2959
475M
    int right = ((int*)b)[0];
2960
475M
    if (left != right)
2961
467M
        return left - right;
2962
8.37M
    left = ((int*)a)[2] - ((int*)b)[2];
2963
8.37M
    if (left != 0)
2964
1.02M
        return left;
2965
7.34M
    left = ((int*)a)[1] - ((int*)b)[1];
2966
7.34M
    if (left != 0)
2967
7.34M
        return left;
2968
2.95k
    return ((int*)a)[3] - ((int*)b)[3];
2969
7.34M
}
2970
2971
#ifdef DEBUG_SCAN_CONVERTER
2972
static void
2973
gx_edgebuffer_print_filtered_tr_app(gx_edgebuffer * edgebuffer)
2974
{
2975
    int i;
2976
2977
    if (!debugging_scan_converter)
2978
        return;
2979
2980
    dlprintf1("Edgebuffer %x\n", edgebuffer);
2981
    dlprintf4("xmin=%x xmax=%x base=%x height=%x\n",
2982
              edgebuffer->xmin, edgebuffer->xmax, edgebuffer->base, edgebuffer->height);
2983
    for (i=0; i < edgebuffer->height; i++)
2984
    {
2985
        int  offset = edgebuffer->index[i];
2986
        int *row    = &edgebuffer->table[offset];
2987
        int count   = *row++;
2988
        dlprintf3("%x @ %d: %d =", i, offset, count);
2989
        while (count-- > 0) {
2990
            int left  = *row++;
2991
            int lid   = *row++;
2992
            int right = *row++;
2993
            int rid   = *row++;
2994
            dlprintf4(" (%x:%d,%x:%d)", left, lid, right, rid);
2995
        }
2996
        dlprintf("\n");
2997
    }
2998
}
2999
3000
static void
3001
gx_edgebuffer_print_tr_app(gx_edgebuffer * edgebuffer)
3002
{
3003
    int i;
3004
    int borked = 0;
3005
3006
    if (!debugging_scan_converter)
3007
        return;
3008
3009
    dlprintf1("Edgebuffer %x\n", edgebuffer);
3010
    dlprintf4("xmin=%x xmax=%x base=%x height=%x\n",
3011
              edgebuffer->xmin, edgebuffer->xmax, edgebuffer->base, edgebuffer->height);
3012
    for (i=0; i < edgebuffer->height; i++)
3013
    {
3014
        int  offset = edgebuffer->index[i];
3015
        int *row    = &edgebuffer->table[offset];
3016
        int count   = *row++;
3017
        int c       = count;
3018
        int wind    = 0;
3019
        dlprintf3("%x @ %d: %d =", i, offset, count);
3020
        while (count-- > 0) {
3021
            int left  = *row++;
3022
            int lid   = *row++;
3023
            int right = *row++;
3024
            int rid   = *row++;
3025
            int ww    = lid & 1;
3026
            int w     = -ww | 1;
3027
            lid >>= 1;
3028
            wind += w;
3029
            dlprintf5(" (%x:%d,%x:%d)%c", left, lid, right, rid, ww ? 'v' : '^');
3030
        }
3031
        if (wind != 0 || c & 1) {
3032
            dlprintf(" <- BROKEN");
3033
            borked = 1;
3034
        }
3035
        dlprintf("\n");
3036
    }
3037
    if (borked) {
3038
        borked = borked; /* Breakpoint here */
3039
    }
3040
}
3041
#endif
3042
3043
typedef struct
3044
{
3045
    fixed  left;
3046
    int    lid;
3047
    fixed  right;
3048
    int    rid;
3049
    fixed  y;
3050
    signed char  d; /* 0 up (or horiz), 1 down, -1 uninited */
3051
    unsigned char first;
3052
    unsigned char saved;
3053
    fixed  save_left;
3054
    int    save_lid;
3055
    fixed  save_right;
3056
    int    save_rid;
3057
    int    save_iy;
3058
    int    save_d;
3059
3060
    int    scanlines;
3061
    int   *table;
3062
    int   *index;
3063
    int    base;
3064
} cursor_tr;
3065
3066
static inline void
3067
cursor_output_tr(cursor_tr * gs_restrict cr, int iy)
3068
604M
{
3069
604M
    int *row;
3070
604M
    int count;
3071
3072
604M
    if (iy >= 0 && iy < cr->scanlines) {
3073
594M
        if (cr->first) {
3074
            /* Save it for later in case we join up */
3075
13.2M
            cr->save_left  = cr->left;
3076
13.2M
            cr->save_lid   = cr->lid;
3077
13.2M
            cr->save_right = cr->right;
3078
13.2M
            cr->save_rid   = cr->rid;
3079
13.2M
            cr->save_iy    = iy;
3080
13.2M
            cr->save_d     = cr->d;
3081
13.2M
            cr->saved      = 1;
3082
581M
        } else if (cr->d != DIRN_UNSET) {
3083
            /* Enter it into the table */
3084
581M
            row = &cr->table[cr->index[iy]];
3085
581M
            *row = count = (*row)+1; /* Increment the count */
3086
581M
            row[4 * count - 3] = cr->left;
3087
581M
            row[4 * count - 2] = cr->d | (cr->lid<<1);
3088
581M
            row[4 * count - 1] = cr->right;
3089
581M
            row[4 * count    ] = cr->rid;
3090
581M
        } else {
3091
121k
            assert(cr->left == max_fixed && cr->right == min_fixed);
3092
121k
        }
3093
594M
    }
3094
604M
    cr->first = 0;
3095
604M
}
3096
3097
static inline void
3098
cursor_output_inrange_tr(cursor_tr * gs_restrict cr, int iy)
3099
281M
{
3100
281M
    int *row;
3101
281M
    int count;
3102
3103
281M
    assert(iy >= 0 && iy < cr->scanlines);
3104
281M
    if (cr->first) {
3105
        /* Save it for later in case we join up */
3106
329k
        cr->save_left  = cr->left;
3107
329k
        cr->save_lid   = cr->lid;
3108
329k
        cr->save_right = cr->right;
3109
329k
        cr->save_rid   = cr->rid;
3110
329k
        cr->save_iy    = iy;
3111
329k
        cr->save_d     = cr->d;
3112
329k
        cr->saved      = 1;
3113
281M
    } else {
3114
        /* Enter it into the table */
3115
281M
        assert(cr->d != DIRN_UNSET);
3116
3117
281M
        row = &cr->table[cr->index[iy]];
3118
281M
        *row = count = (*row)+1; /* Increment the count */
3119
281M
        row[4 * count - 3] = cr->left;
3120
281M
        row[4 * count - 2] = cr->d | (cr->lid<<1);
3121
281M
        row[4 * count - 1] = cr->right;
3122
281M
        row[4 * count    ] = cr->rid;
3123
281M
    }
3124
281M
    cr->first = 0;
3125
281M
}
3126
3127
/* Step the cursor in y, allowing for maybe crossing a scanline */
3128
static inline void
3129
cursor_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip)
3130
69.9M
{
3131
69.9M
    int new_iy;
3132
69.9M
    int iy = fixed2int(cr->y) - cr->base;
3133
3134
69.9M
    cr->y += dy;
3135
69.9M
    new_iy = fixed2int(cr->y) - cr->base;
3136
69.9M
    if (new_iy != iy) {
3137
69.9M
        if (!skip)
3138
69.0M
            cursor_output_tr(cr, iy);
3139
69.9M
        cr->left = x;
3140
69.9M
        cr->lid = id;
3141
69.9M
        cr->right = x;
3142
69.9M
        cr->rid = id;
3143
69.9M
    } else {
3144
0
        if (x < cr->left) {
3145
0
            cr->left = x;
3146
0
            cr->lid = id;
3147
0
        }
3148
0
        if (x > cr->right) {
3149
0
            cr->right = x;
3150
0
            cr->rid = id;
3151
0
        }
3152
0
    }
3153
69.9M
}
3154
3155
/* Step the cursor in y, never by enough to cross a scanline. */
3156
static inline void
3157
cursor_never_step_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3158
4.40M
{
3159
4.40M
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
3160
3161
4.40M
    cr->y += dy;
3162
4.40M
}
3163
3164
/* Step the cursor in y, never by enough to cross a scanline,
3165
 * knowing that we are moving left, and that the right edge
3166
 * has already been accounted for. */
3167
static inline void
3168
cursor_never_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3169
15.8M
{
3170
15.8M
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
3171
3172
15.8M
    if (x < cr->left)
3173
12.6M
    {
3174
12.6M
        cr->left = x;
3175
12.6M
        cr->lid = id;
3176
12.6M
    }
3177
15.8M
    cr->y += dy;
3178
15.8M
}
3179
3180
/* Step the cursor in y, never by enough to cross a scanline,
3181
 * knowing that we are moving right, and that the left edge
3182
 * has already been accounted for. */
3183
static inline void
3184
cursor_never_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3185
14.3M
{
3186
14.3M
    assert(fixed2int(cr->y+dy) == fixed2int(cr->y));
3187
3188
14.3M
    if (x > cr->right)
3189
13.8M
    {
3190
13.8M
        cr->right = x;
3191
13.8M
        cr->rid = id;
3192
13.8M
    }
3193
14.3M
    cr->y += dy;
3194
14.3M
}
3195
3196
/* Step the cursor in y, always by enough to cross a scanline. */
3197
static inline void
3198
cursor_always_step_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id, int skip)
3199
54.2M
{
3200
54.2M
    int iy = fixed2int(cr->y) - cr->base;
3201
3202
54.2M
    if (!skip)
3203
48.5M
        cursor_output_tr(cr, iy);
3204
54.2M
    cr->y += dy;
3205
54.2M
    cr->left = x;
3206
54.2M
    cr->lid = id;
3207
54.2M
    cr->right = x;
3208
54.2M
    cr->rid = id;
3209
54.2M
}
3210
3211
/* Step the cursor in y, always by enough to cross a scanline, as
3212
 * part of a vertical line, knowing that we are moving from a
3213
 * position guaranteed to be in the valid y range. */
3214
static inline void
3215
cursor_always_step_inrange_vertical_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3216
438M
{
3217
438M
    int iy = fixed2int(cr->y) - cr->base;
3218
3219
438M
    cursor_output_tr(cr, iy);
3220
438M
    cr->y += dy;
3221
438M
}
3222
3223
/* Step the cursor in y, always by enough to cross a scanline, as
3224
 * part of a left moving line, knowing that we are moving from a
3225
 * position guaranteed to be in the valid y range. */
3226
static inline void
3227
cursor_always_inrange_step_left_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3228
141M
{
3229
141M
    int iy = fixed2int(cr->y) - cr->base;
3230
3231
141M
    cr->y += dy;
3232
141M
    cursor_output_inrange_tr(cr, iy);
3233
141M
    cr->right = x;
3234
141M
    cr->rid = id;
3235
141M
}
3236
3237
/* Step the cursor in y, always by enough to cross a scanline, as
3238
 * part of a right moving line, knowing that we are moving from a
3239
 * position guaranteed to be in the valid y range. */
3240
static inline void
3241
cursor_always_inrange_step_right_tr(cursor_tr * gs_restrict cr, fixed dy, fixed x, int id)
3242
140M
{
3243
140M
    int iy = fixed2int(cr->y) - cr->base;
3244
3245
140M
    cr->y += dy;
3246
140M
    cursor_output_inrange_tr(cr, iy);
3247
140M
    cr->left = x;
3248
140M
    cr->lid = id;
3249
140M
}
3250
3251
static inline void cursor_left_merge_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3252
190M
{
3253
190M
    if (x < cr->left) {
3254
62.3M
        cr->left = x;
3255
62.3M
        cr->lid  = id;
3256
62.3M
    }
3257
190M
}
3258
3259
static inline void cursor_left_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3260
183M
{
3261
183M
    cr->left = x;
3262
183M
    cr->lid  = id;
3263
183M
}
3264
3265
static inline void cursor_right_merge_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3266
196M
{
3267
196M
    if (x > cr->right) {
3268
63.3M
        cr->right = x;
3269
63.3M
        cr->rid   = id;
3270
63.3M
    }
3271
196M
}
3272
3273
static inline void cursor_right_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3274
180M
{
3275
180M
    cr->right = x;
3276
180M
    cr->rid   = id;
3277
180M
}
3278
3279
static inline int cursor_down_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3280
62.1M
{
3281
62.1M
    int skip = 0;
3282
62.1M
    if ((cr->y & 0xff) == 0)
3283
6.58M
        skip = 1;
3284
62.1M
    if (cr->d == DIRN_UP)
3285
9.25M
    {
3286
9.25M
        if (!skip)
3287
9.25M
            cursor_output_tr(cr, fixed2int(cr->y) - cr->base);
3288
9.25M
        cr->left = x;
3289
9.25M
        cr->lid = id;
3290
9.25M
        cr->right = x;
3291
9.25M
        cr->rid = id;
3292
9.25M
    }
3293
62.1M
    cr->d = DIRN_DOWN;
3294
62.1M
    return skip;
3295
62.1M
}
3296
3297
static inline void cursor_up_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3298
61.3M
{
3299
61.3M
    if (cr->d == DIRN_DOWN)
3300
8.96M
    {
3301
8.96M
        cursor_output_tr(cr, fixed2int(cr->y) - cr->base);
3302
8.96M
        cr->left = x;
3303
8.96M
        cr->lid = id;
3304
8.96M
        cr->right = x;
3305
8.96M
        cr->rid = id;
3306
8.96M
    }
3307
61.3M
    cr->d = DIRN_UP;
3308
61.3M
}
3309
3310
static inline void
3311
cursor_flush_tr(cursor_tr * gs_restrict cr, fixed x, int id)
3312
20.9M
{
3313
20.9M
    int iy;
3314
3315
    /* This should only happen if we were entirely out of bounds,
3316
     * or if everything was within a zero height horizontal
3317
     * rectangle from the start point. */
3318
20.9M
    if (cr->first) {
3319
5.60k
        int iy = fixed2int(cr->y) - cr->base;
3320
        /* Any zero height rectangle counts as filled, except
3321
         * those on the baseline of a pixel. */
3322
5.60k
        if (cr->d == DIRN_UNSET && (cr->y & 0xff) == 0)
3323
354
            return;
3324
5.60k
        assert(cr->left != max_fixed && cr->right != min_fixed);
3325
5.25k
        if (iy >= 0 && iy < cr->scanlines) {
3326
4.15k
            int *row = &cr->table[cr->index[iy]];
3327
4.15k
            int count = *row = (*row)+2; /* Increment the count */
3328
4.15k
            row[4 * count - 7] = cr->left;
3329
4.15k
            row[4 * count - 6] = DIRN_UP | (cr->lid<<1);
3330
4.15k
            row[4 * count - 5] = cr->right;
3331
4.15k
            row[4 * count - 4] = cr->rid;
3332
4.15k
            row[4 * count - 3] = cr->right;
3333
4.15k
            row[4 * count - 2] = DIRN_DOWN | (cr->rid<<1);
3334
4.15k
            row[4 * count - 1] = cr->right;
3335
4.15k
            row[4 * count    ] = cr->rid;
3336
4.15k
        }
3337
5.25k
        return;
3338
5.60k
    }
3339
3340
    /* Merge save into current if we can */
3341
20.9M
    iy = fixed2int(cr->y) - cr->base;
3342
20.9M
    if (cr->saved && iy == cr->save_iy &&
3343
11.1M
        (cr->d == cr->save_d || cr->save_d == DIRN_UNSET)) {
3344
4.85M
        if (cr->left > cr->save_left) {
3345
1.20M
            cr->left = cr->save_left;
3346
1.20M
            cr->lid  = cr->save_lid;
3347
1.20M
        }
3348
4.85M
        if (cr->right < cr->save_right) {
3349
1.08M
            cr->right = cr->save_right;
3350
1.08M
            cr->rid = cr->save_rid;
3351
1.08M
        }
3352
4.85M
        cursor_output_tr(cr, iy);
3353
4.85M
        return;
3354
4.85M
    }
3355
3356
    /* Merge not possible */
3357
16.0M
    cursor_output_tr(cr, iy);
3358
16.0M
    if (cr->saved) {
3359
8.77M
        cr->left  = cr->save_left;
3360
8.77M
        cr->lid   = cr->save_lid;
3361
8.77M
        cr->right = cr->save_right;
3362
8.77M
        cr->rid   = cr->save_rid;
3363
8.77M
        assert(cr->save_d != DIRN_UNSET);
3364
8.77M
        if (cr->save_d != DIRN_UNSET)
3365
8.77M
            cr->d = cr->save_d;
3366
8.77M
        cursor_output_tr(cr, cr->save_iy);
3367
8.77M
    }
3368
16.0M
}
3369
3370
static inline void
3371
cursor_null_tr(cursor_tr *cr)
3372
28.4M
{
3373
28.4M
    cr->right = min_fixed;
3374
28.4M
    cr->left  = max_fixed;
3375
28.4M
    cr->d     = DIRN_UNSET;
3376
28.4M
}
3377
3378
static void mark_line_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed ex, fixed ey, int id)
3379
898M
{
3380
898M
    int isy, iey;
3381
898M
    fixed saved_sy = sy;
3382
898M
    fixed saved_ex = ex;
3383
898M
    fixed saved_ey = ey;
3384
898M
    int truncated;
3385
3386
898M
    if (sy == ey && sx == ex)
3387
29.6M
        return;
3388
3389
868M
    isy = fixed2int(sy) - cr->base;
3390
868M
    iey = fixed2int(ey) - cr->base;
3391
3392
#ifdef DEBUG_SCAN_CONVERTER
3393
    if (debugging_scan_converter)
3394
        dlprintf6("Marking line (tr_app) from %x,%x to %x,%x (%x,%x)\n", sx, sy, ex, ey, isy, iey);
3395
#endif
3396
#ifdef DEBUG_OUTPUT_SC_AS_PS
3397
    dlprintf("0.001 setlinewidth 0 0 0 setrgbcolor %%PS\n");
3398
    coord("moveto", sx, sy);
3399
    coord("lineto", ex, ey);
3400
    dlprintf("stroke %%PS\n");
3401
#endif
3402
3403
    /* Horizontal motion at the bottom of a pixel is ignored */
3404
868M
    if (sy == ey && (sy & 0xff) == 0)
3405
1.39M
        return;
3406
3407
868M
    assert(cr->y == sy &&
3408
867M
           ((cr->left <= sx && cr->right >= sx) || ((sy & 0xff) == 0)) &&
3409
867M
           cr->d >= DIRN_UNSET && cr->d <= DIRN_DOWN);
3410
3411
867M
    if (isy < iey) {
3412
        /* Rising line */
3413
348M
        if (iey < 0 || isy >= cr->scanlines) {
3414
            /* All line is outside. */
3415
307M
            if ((ey & 0xff) == 0) {
3416
2.01M
                cursor_null_tr(cr);
3417
305M
            } else {
3418
305M
                cr->left = ex;
3419
305M
                cr->lid = id;
3420
305M
                cr->right = ex;
3421
305M
                cr->rid = id;
3422
305M
            }
3423
307M
            cr->y = ey;
3424
307M
            cr->first = 0;
3425
307M
            return;
3426
307M
        }
3427
40.8M
        if (isy < 0) {
3428
            /* Move sy up */
3429
6.05M
            int64_t y = (int64_t)ey - (int64_t)sy;
3430
6.05M
            fixed new_sy = int2fixed(cr->base);
3431
6.05M
            int64_t dy = (int64_t)new_sy - (int64_t)sy;
3432
6.05M
            sx += (int)(((((int64_t)ex-sx))*dy + y/2)/y);
3433
6.05M
            sy = new_sy;
3434
6.05M
            cursor_null_tr(cr);
3435
6.05M
            cr->y = sy;
3436
6.05M
            isy = 0;
3437
6.05M
        }
3438
40.8M
        truncated = iey > cr->scanlines;
3439
40.8M
        if (truncated) {
3440
            /* Move ey down */
3441
5.45M
            int64_t y = (int64_t)ey - (int64_t)sy;
3442
5.45M
            fixed new_ey = int2fixed(cr->base + cr->scanlines);
3443
5.45M
            int64_t dy = (int64_t)ey - (int64_t)new_ey;
3444
5.45M
            saved_ex = ex;
3445
5.45M
            saved_ey = ey;
3446
5.45M
            ex -= (int)(((((int64_t)ex-sx))*dy + y/2)/y);
3447
5.45M
            ey = new_ey;
3448
5.45M
            iey = cr->scanlines;
3449
5.45M
        }
3450
518M
    } else {
3451
        /* Falling line */
3452
518M
        if (isy < 0 || iey >= cr->scanlines) {
3453
            /* All line is outside. */
3454
419M
            if ((ey & 0xff) == 0) {
3455
1.70M
                cursor_null_tr(cr);
3456
418M
            } else {
3457
418M
                cr->left = ex;
3458
418M
                cr->lid = id;
3459
418M
                cr->right = ex;
3460
418M
                cr->rid = id;
3461
418M
            }
3462
419M
            cr->y = ey;
3463
419M
            cr->first = 0;
3464
419M
            return;
3465
419M
        }
3466
98.5M
        truncated = iey < 0;
3467
98.5M
        if (truncated) {
3468
            /* Move ey up */
3469
6.05M
            int64_t y = (int64_t)ey - (int64_t)sy;
3470
6.05M
            fixed new_ey = int2fixed(cr->base);
3471
6.05M
            int64_t dy = (int64_t)ey - (int64_t)new_ey;
3472
6.05M
            ex -= (int)(((((int64_t)ex-sx))*dy + y/2)/y);
3473
6.05M
            ey = new_ey;
3474
6.05M
            iey = 0;
3475
6.05M
        }
3476
98.5M
        if (isy >= cr->scanlines) {
3477
            /* Move sy down */
3478
6.01M
            int64_t y = (int64_t)ey - (int64_t)sy;
3479
6.01M
            fixed new_sy = int2fixed(cr->base + cr->scanlines);
3480
6.01M
            int64_t dy = (int64_t)new_sy - (int64_t)sy;
3481
6.01M
            sx += (int)(((((int64_t)ex-sx))*dy + y/2)/y);
3482
6.01M
            sy = new_sy;
3483
6.01M
            cursor_null_tr(cr);
3484
6.01M
            cr->y = sy;
3485
6.01M
            isy = cr->scanlines;
3486
6.01M
        }
3487
98.5M
    }
3488
3489
139M
    cursor_left_merge_tr(cr, sx, id);
3490
139M
    cursor_right_merge_tr(cr, sx, id);
3491
3492
139M
    assert(cr->left <= sx);
3493
139M
    assert(cr->right >= sx);
3494
139M
    assert(cr->y == sy);
3495
3496
    /* A note: The code below used to be of the form:
3497
     *   if (isy == iey)   ... deal with horizontal lines
3498
     *   else if (ey > sy) {
3499
     *     fixed y_steps = ey - sy;
3500
     *      ... deal with rising lines ...
3501
     *   } else {
3502
     *     fixed y_steps = ey - sy;
3503
     *     ... deal with falling lines
3504
     *   }
3505
     * but that lead to problems, for instance, an example seen
3506
     * has sx=2aa8e, sy=8aee7, ex=7ffc1686, ey=8003e97a.
3507
     * Thus isy=84f, iey=ff80038a. We can see that ey < sy, but
3508
     * sy - ey < 0!
3509
     * We therefore rejig our code so that the choice between
3510
     * cases is done based on the sign of y_steps rather than
3511
     * the relative size of ey and sy.
3512
     */
3513
3514
    /* First, deal with lines that don't change scanline.
3515
     * This accommodates horizontal lines. */
3516
139M
    if (isy == iey) {
3517
57.9M
        if (saved_sy == saved_ey) {
3518
            /* Horizontal line. Don't change cr->d, don't flush. */
3519
15.8M
            if ((ey & 0xff) == 0) {
3520
0
                cursor_null_tr(cr);
3521
0
                goto no_merge;
3522
0
            }
3523
42.0M
        } else if (saved_sy > saved_ey) {
3524
            /* Falling line, flush if previous was rising */
3525
20.9M
            int skip = cursor_down_tr(cr, sx, id);
3526
20.9M
            if ((ey & 0xff) == 0) {
3527
                /* We are falling to the baseline of a subpixel, so output
3528
                 * for the current pixel, and leave the cursor nulled. */
3529
912k
                if (sx <= ex) {
3530
625k
                    cursor_right_merge_tr(cr, ex, id);
3531
625k
                } else {
3532
287k
                    cursor_left_merge_tr(cr, ex, id);
3533
287k
                }
3534
912k
                if (!skip)
3535
894k
                    cursor_output_tr(cr, fixed2int(cr->y) - cr->base);
3536
912k
                cursor_null_tr(cr);
3537
912k
                goto no_merge;
3538
912k
            }
3539
21.0M
        } else {
3540
            /* Rising line, flush if previous was falling */
3541
21.0M
            cursor_up_tr(cr, sx, id);
3542
21.0M
            if ((ey & 0xff) == 0) {
3543
20.4k
                cursor_null_tr(cr);
3544
20.4k
                goto no_merge;
3545
20.4k
            }
3546
21.0M
        }
3547
56.9M
        if (sx <= ex) {
3548
30.0M
            cursor_right_merge_tr(cr, ex, id);
3549
30.0M
        } else {
3550
26.9M
            cursor_left_merge_tr(cr, ex, id);
3551
26.9M
        }
3552
57.9M
no_merge:
3553
57.9M
        cr->y = ey;
3554
57.9M
        if (sy > saved_ey)
3555
20.9M
            goto endFalling;
3556
81.4M
    } else if (iey > isy) {
3557
        /* So lines increasing in y. */
3558
        /* We want to change from sy to ey, which are guaranteed to be on
3559
         * different scanlines. We do this in 3 phases.
3560
         * Phase 1 gets us from sy to the next scanline boundary. (We may exit after phase 1).
3561
         * Phase 2 gets us all the way to the last scanline boundary. (This may be a null operation)
3562
         * Phase 3 gets us from the last scanline boundary to ey. (We are guaranteed to have output the cursor at least once before phase 3).
3563
         */
3564
40.2M
        int phase1_y_steps = (-sy) & (fixed_1 - 1);
3565
40.2M
        int phase3_y_steps = ey & (fixed_1 - 1);
3566
40.2M
        ufixed y_steps = (ufixed)ey - (ufixed)sy;
3567
3568
40.2M
        cursor_up_tr(cr, sx, id);
3569
3570
40.2M
        if (sx == ex) {
3571
            /* Vertical line. (Rising) */
3572
3573
            /* Phase 1: */
3574
7.49M
            if (phase1_y_steps) {
3575
                /* If phase 1 will move us into a new scanline, then we must
3576
                 * flush it before we move. */
3577
4.59M
                cursor_step_tr(cr, phase1_y_steps, sx, id, 0);
3578
4.59M
                sy += phase1_y_steps;
3579
4.59M
                y_steps -= phase1_y_steps;
3580
4.59M
                if (y_steps == 0) {
3581
316k
                    cursor_null_tr(cr);
3582
316k
                    goto end;
3583
316k
                }
3584
4.59M
            }
3585
3586
            /* Phase 3: precalculation */
3587
7.17M
            y_steps -= phase3_y_steps;
3588
3589
            /* Phase 2: */
3590
7.17M
            y_steps = fixed2int(y_steps);
3591
7.17M
            assert(y_steps >= 0);
3592
7.17M
            if (y_steps > 0) {
3593
5.97M
                cursor_always_step_tr(cr, fixed_1, sx, id, 0);
3594
5.97M
                y_steps--;
3595
221M
                while (y_steps) {
3596
215M
                    cursor_always_step_inrange_vertical_tr(cr, fixed_1, sx, id);
3597
215M
                    y_steps--;
3598
215M
                }
3599
5.97M
            }
3600
3601
            /* Phase 3 */
3602
7.17M
            assert(cr->left == sx && cr->right == sx && cr->lid == id && cr->rid == id);
3603
7.17M
            if (phase3_y_steps == 0)
3604
2.78M
                cursor_null_tr(cr);
3605
4.39M
            else
3606
4.39M
                cr->y += phase3_y_steps;
3607
32.7M
        } else if (sx < ex) {
3608
            /* Lines increasing in x. (Rightwards, rising) */
3609
16.9M
            int phase1_x_steps, phase3_x_steps;
3610
            /* Use unsigned int here, to allow for extreme cases like
3611
             * ex = 0x7fffffff, sx = 0x80000000 */
3612
16.9M
            unsigned int x_steps = ex - sx;
3613
3614
            /* Phase 1: */
3615
16.9M
            if (phase1_y_steps) {
3616
15.4M
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
3617
15.4M
                sx += phase1_x_steps;
3618
15.4M
                cursor_right_merge_tr(cr, sx, id);
3619
15.4M
                x_steps -= phase1_x_steps;
3620
15.4M
                cursor_step_tr(cr, phase1_y_steps, sx, id, 0);
3621
15.4M
                sy += phase1_y_steps;
3622
15.4M
                y_steps -= phase1_y_steps;
3623
15.4M
                if (y_steps == 0) {
3624
227k
                    cursor_null_tr(cr);
3625
227k
                    goto end;
3626
227k
                }
3627
15.4M
            }
3628
3629
            /* Phase 3: precalculation */
3630
16.6M
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
3631
16.6M
            x_steps -= phase3_x_steps;
3632
16.6M
            y_steps -= phase3_y_steps;
3633
16.6M
            assert((y_steps & (fixed_1 - 1)) == 0);
3634
3635
            /* Phase 2: */
3636
16.6M
            y_steps = fixed2int(y_steps);
3637
16.6M
            assert(y_steps >= 0);
3638
16.6M
            if (y_steps) {
3639
                /* We want to change sx by x_steps in y_steps steps.
3640
                 * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/y_steps. */
3641
11.2M
                int x_inc = x_steps/y_steps;
3642
11.2M
                int n_inc = x_steps - (x_inc * y_steps);
3643
11.2M
                int f = y_steps/2;
3644
11.2M
                int d = y_steps;
3645
3646
                /* Special casing the first iteration, allows us to simplify
3647
                 * the following loop. */
3648
11.2M
                sx += x_inc;
3649
11.2M
                f -= n_inc;
3650
11.2M
                if (f < 0)
3651
2.35M
                    f += d, sx++;
3652
11.2M
                cursor_right_merge_tr(cr, sx, id);
3653
11.2M
                cursor_always_step_tr(cr, fixed_1, sx, id, 0);
3654
11.2M
                y_steps--;
3655
3656
85.6M
                while (y_steps) {
3657
74.4M
                    sx += x_inc;
3658
74.4M
                    f -= n_inc;
3659
74.4M
                    if (f < 0)
3660
32.0M
                        f += d, sx++;
3661
74.4M
                    cursor_right_tr(cr, sx, id);
3662
74.4M
                    cursor_always_inrange_step_right_tr(cr, fixed_1, sx, id);
3663
74.4M
                    y_steps--;
3664
74.4M
                };
3665
11.2M
            }
3666
3667
            /* Phase 3 */
3668
16.6M
            assert(cr->left <= ex && cr->lid == id && cr->right >= sx);
3669
16.6M
            if (phase3_y_steps == 0)
3670
1.25M
                cursor_null_tr(cr);
3671
15.4M
            else {
3672
15.4M
                cursor_right_tr(cr, ex, id);
3673
15.4M
                cr->y += phase3_y_steps;
3674
15.4M
            }
3675
16.6M
        } else {
3676
            /* Lines decreasing in x. (Leftwards, rising) */
3677
15.8M
            int phase1_x_steps, phase3_x_steps;
3678
            /* Use unsigned int here, to allow for extreme cases like
3679
             * sx = 0x7fffffff, ex = 0x80000000 */
3680
15.8M
            unsigned int x_steps = sx - ex;
3681
3682
            /* Phase 1: */
3683
15.8M
            if (phase1_y_steps) {
3684
14.4M
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
3685
14.4M
                x_steps -= phase1_x_steps;
3686
14.4M
                sx -= phase1_x_steps;
3687
14.4M
                cursor_left_merge_tr(cr, sx, id);
3688
14.4M
                cursor_step_tr(cr, phase1_y_steps, sx, id, 0);
3689
14.4M
                sy += phase1_y_steps;
3690
14.4M
                y_steps -= phase1_y_steps;
3691
14.4M
                if (y_steps == 0) {
3692
207k
                    cursor_null_tr(cr);
3693
207k
                    goto end;
3694
207k
                }
3695
14.4M
            }
3696
3697
            /* Phase 3: precalculation */
3698
15.6M
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
3699
15.6M
            x_steps -= phase3_x_steps;
3700
15.6M
            y_steps -= phase3_y_steps;
3701
15.6M
            assert((y_steps & (fixed_1 - 1)) == 0);
3702
3703
            /* Phase 2: */
3704
15.6M
            y_steps = fixed2int((unsigned int)y_steps);
3705
15.6M
            assert(y_steps >= 0);
3706
15.6M
            if (y_steps) {
3707
                /* We want to change sx by x_steps in y_steps steps.
3708
                 * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
3709
9.76M
                int x_inc = x_steps/y_steps;
3710
9.76M
                int n_inc = x_steps - (x_inc * y_steps);
3711
9.76M
                int f = y_steps/2;
3712
9.76M
                int d = y_steps;
3713
3714
                /* Special casing the first iteration, allows us to simplify
3715
                 * the following loop. */
3716
9.76M
                sx -= x_inc;
3717
9.76M
                f -= n_inc;
3718
9.76M
                if (f < 0)
3719
1.84M
                    f += d, sx--;
3720
9.76M
                cursor_left_merge_tr(cr, sx, id);
3721
9.76M
                cursor_always_step_tr(cr, fixed_1, sx, id, 0);
3722
9.76M
                y_steps--;
3723
3724
77.3M
                while (y_steps) {
3725
67.6M
                    sx -= x_inc;
3726
67.6M
                    f -= n_inc;
3727
67.6M
                    if (f < 0)
3728
27.4M
                        f += d, sx--;
3729
67.6M
                    cursor_left_tr(cr, sx, id);
3730
67.6M
                    cursor_always_inrange_step_left_tr(cr, fixed_1, sx, id);
3731
67.6M
                    y_steps--;
3732
67.6M
                }
3733
9.76M
            }
3734
3735
            /* Phase 3 */
3736
15.6M
            assert(cr->right >= ex && cr->rid == id && cr->left <= sx);
3737
15.6M
            if (phase3_y_steps == 0)
3738
1.24M
                cursor_null_tr(cr);
3739
14.4M
            else {
3740
14.4M
                cursor_left_tr(cr, ex, id);
3741
14.4M
                cr->y += phase3_y_steps;
3742
14.4M
            }
3743
15.6M
        }
3744
41.1M
    } else {
3745
        /* So lines decreasing in y. */
3746
        /* We want to change from sy to ey, which are guaranteed to be on
3747
         * different scanlines. We do this in 3 phases.
3748
         * Phase 1 gets us from sy to the next scanline boundary. This never causes an output.
3749
         * Phase 2 gets us all the way to the last scanline boundary. This is guaranteed to cause an output.
3750
         * Phase 3 gets us from the last scanline boundary to ey. We are guaranteed to have outputted by now.
3751
         */
3752
41.1M
        int phase1_y_steps = sy & (fixed_1 - 1);
3753
41.1M
        int phase3_y_steps = (-ey) & (fixed_1 - 1);
3754
41.1M
        ufixed y_steps = (ufixed)sy - (ufixed)ey;
3755
3756
41.1M
        int skip = cursor_down_tr(cr, sx, id);
3757
3758
41.1M
        if (sx == ex) {
3759
            /* Vertical line. (Falling) */
3760
3761
            /* Phase 1: */
3762
7.60M
            if (phase1_y_steps) {
3763
                /* Phase 1 in a falling line never moves us into a new scanline. */
3764
4.40M
                cursor_never_step_vertical_tr(cr, -phase1_y_steps, sx, id);
3765
4.40M
                sy -= phase1_y_steps;
3766
4.40M
                y_steps -= phase1_y_steps;
3767
4.40M
                if (y_steps == 0)
3768
0
                    goto endFallingLeftOnEdgeOfPixel;
3769
4.40M
            }
3770
3771
            /* Phase 3: precalculation */
3772
7.60M
            y_steps -= phase3_y_steps;
3773
7.60M
            assert((y_steps & (fixed_1 - 1)) == 0);
3774
3775
            /* Phase 2: */
3776
7.60M
            y_steps = fixed2int(y_steps);
3777
7.60M
            assert(y_steps >= 0);
3778
7.60M
            if (y_steps) {
3779
6.03M
                cursor_always_step_tr(cr, -fixed_1, sx, id, skip);
3780
6.03M
                skip = 0;
3781
6.03M
                y_steps--;
3782
222M
                while (y_steps) {
3783
216M
                    cursor_always_step_inrange_vertical_tr(cr, -fixed_1, sx, id);
3784
216M
                    y_steps--;
3785
216M
                }
3786
6.03M
            }
3787
3788
            /* Phase 3 */
3789
7.60M
            if (phase3_y_steps == 0) {
3790
2.92M
endFallingLeftOnEdgeOfPixel:
3791
2.92M
                cursor_always_step_inrange_vertical_tr(cr, 0, sx, id);
3792
2.92M
                cursor_null_tr(cr);
3793
4.68M
            } else {
3794
4.68M
                cursor_step_tr(cr, -phase3_y_steps, sx, id, skip);
3795
4.68M
                assert(cr->left == sx && cr->lid == id && cr->right == sx && cr->rid == id);
3796
4.68M
            }
3797
33.5M
        } else if (sx < ex) {
3798
            /* Lines increasing in x. (Rightwards, falling) */
3799
15.9M
            int phase1_x_steps, phase3_x_steps;
3800
            /* Use unsigned int here, to allow for extreme cases like
3801
             * ex = 0x7fffffff, sx = 0x80000000 */
3802
15.9M
            unsigned int x_steps = ex - sx;
3803
3804
            /* Phase 1: */
3805
15.9M
            if (phase1_y_steps) {
3806
14.3M
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
3807
14.3M
                x_steps -= phase1_x_steps;
3808
14.3M
                sx += phase1_x_steps;
3809
                /* Phase 1 in a falling line never moves us into a new scanline. */
3810
14.3M
                cursor_never_step_right_tr(cr, -phase1_y_steps, sx, id);
3811
14.3M
                sy -= phase1_y_steps;
3812
14.3M
                y_steps -= phase1_y_steps;
3813
14.3M
                if (y_steps == 0)
3814
0
                    goto endFallingRightOnEdgeOfPixel;
3815
14.3M
            }
3816
3817
            /* Phase 3: precalculation */
3818
15.9M
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
3819
15.9M
            x_steps -= phase3_x_steps;
3820
15.9M
            y_steps -= phase3_y_steps;
3821
15.9M
            assert((y_steps & (fixed_1 - 1)) == 0);
3822
3823
            /* Phase 2: */
3824
15.9M
            y_steps = fixed2int(y_steps);
3825
15.9M
            assert(y_steps >= 0);
3826
15.9M
            if (y_steps) {
3827
                /* We want to change sx by x_steps in y_steps steps.
3828
                 * So each step, we add x_steps/y_steps to sx. That's x_inc + n_inc/ey. */
3829
9.55M
                int x_inc = x_steps/y_steps;
3830
9.55M
                int n_inc = x_steps - (x_inc * y_steps);
3831
9.55M
                int f = y_steps/2;
3832
9.55M
                int d = y_steps;
3833
3834
9.55M
                cursor_always_step_tr(cr, -fixed_1, sx, id, skip);
3835
9.55M
                skip = 0;
3836
9.55M
                sx += x_inc;
3837
9.55M
                f -= n_inc;
3838
9.55M
                if (f < 0)
3839
1.93M
                    f += d, sx++;
3840
9.55M
                cursor_right_tr(cr, sx, id);
3841
9.55M
                y_steps--;
3842
3843
75.7M
                while (y_steps) {
3844
66.2M
                    cursor_always_inrange_step_right_tr(cr, -fixed_1, sx, id);
3845
66.2M
                    sx += x_inc;
3846
66.2M
                    f -= n_inc;
3847
66.2M
                    if (f < 0)
3848
27.1M
                        f += d, sx++;
3849
66.2M
                    cursor_right_tr(cr, sx, id);
3850
66.2M
                    y_steps--;
3851
66.2M
                }
3852
9.55M
            }
3853
3854
            /* Phase 3 */
3855
15.9M
            if (phase3_y_steps == 0) {
3856
1.31M
endFallingRightOnEdgeOfPixel:
3857
1.31M
                cursor_always_step_inrange_vertical_tr(cr, 0, sx, id);
3858
1.31M
                cursor_null_tr(cr);
3859
14.6M
            } else {
3860
14.6M
                cursor_step_tr(cr, -phase3_y_steps, sx, id, skip);
3861
14.6M
                cursor_right_tr(cr, ex, id);
3862
14.6M
                assert(cr->left == sx && cr->lid == id && cr->right == ex && cr->rid == id);
3863
14.6M
            }
3864
17.6M
        } else {
3865
            /* Lines decreasing in x. (Falling) */
3866
17.6M
            int phase1_x_steps, phase3_x_steps;
3867
            /* Use unsigned int here, to allow for extreme cases like
3868
             * sx = 0x7fffffff, ex = 0x80000000 */
3869
17.6M
            unsigned int x_steps = sx - ex;
3870
3871
            /* Phase 1: */
3872
17.6M
            if (phase1_y_steps) {
3873
15.8M
                phase1_x_steps = (int)(((int64_t)x_steps * phase1_y_steps + y_steps/2) / y_steps);
3874
15.8M
                x_steps -= phase1_x_steps;
3875
15.8M
                sx -= phase1_x_steps;
3876
                /* Phase 1 in a falling line never moves us into a new scanline. */
3877
15.8M
                cursor_never_step_left_tr(cr, -phase1_y_steps, sx, id);
3878
15.8M
                sy -= phase1_y_steps;
3879
15.8M
                y_steps -= phase1_y_steps;
3880
15.8M
                if (y_steps == 0)
3881
0
                    goto endFallingVerticalOnEdgeOfPixel;
3882
15.8M
            }
3883
3884
            /* Phase 3: precalculation */
3885
17.6M
            phase3_x_steps = (int)(((int64_t)x_steps * phase3_y_steps + y_steps/2) / y_steps);
3886
17.6M
            x_steps -= phase3_x_steps;
3887
17.6M
            y_steps -= phase3_y_steps;
3888
17.6M
            assert((y_steps & (fixed_1 - 1)) == 0);
3889
3890
            /* Phase 2: */
3891
17.6M
            y_steps = fixed2int(y_steps);
3892
17.6M
            assert(y_steps >= 0);
3893
17.6M
            if (y_steps) {
3894
                /* We want to change sx by x_steps in y_steps steps.
3895
                 * So each step, we sub x_steps/y_steps from sx. That's x_inc + n_inc/ey. */
3896
11.6M
                int x_inc = x_steps/y_steps;
3897
11.6M
                int n_inc = x_steps - (x_inc * y_steps);
3898
11.6M
                int f = y_steps/2;
3899
11.6M
                int d = y_steps;
3900
3901
11.6M
                cursor_always_step_tr(cr, -fixed_1, sx, id, skip);
3902
11.6M
                skip = 0;
3903
11.6M
                sx -= x_inc;
3904
11.6M
                f -= n_inc;
3905
11.6M
                if (f < 0)
3906
2.42M
                    f += d, sx--;
3907
11.6M
                cursor_left_tr(cr, sx, id);
3908
11.6M
                y_steps--;
3909
3910
85.2M
                while (y_steps) {
3911
73.5M
                    cursor_always_inrange_step_left_tr(cr, -fixed_1, sx, id);
3912
73.5M
                    sx -= x_inc;
3913
73.5M
                    f -= n_inc;
3914
73.5M
                    if (f < 0)
3915
31.9M
                        f += d, sx--;
3916
73.5M
                    cursor_left_tr(cr, sx, id);
3917
73.5M
                    y_steps--;
3918
73.5M
                }
3919
11.6M
            }
3920
3921
            /* Phase 3 */
3922
17.6M
            if (phase3_y_steps == 0) {
3923
1.50M
endFallingVerticalOnEdgeOfPixel:
3924
1.50M
                cursor_always_step_inrange_vertical_tr(cr, 0, sx, id);
3925
1.50M
                cursor_null_tr(cr);
3926
16.1M
            } else {
3927
16.1M
                cursor_step_tr(cr, -phase3_y_steps, sx, id, skip);
3928
16.1M
                cursor_left_tr(cr, ex, id);
3929
16.1M
                assert(cr->left == ex && cr->lid == id && cr->right == sx && cr->rid == id);
3930
16.1M
            }
3931
17.6M
        }
3932
62.1M
endFalling: {}
3933
62.1M
    }
3934
3935
139M
end:
3936
139M
    if (truncated) {
3937
11.5M
        cr->left = saved_ex;
3938
11.5M
        cr->lid = id;
3939
11.5M
        cr->right = saved_ex;
3940
11.5M
        cr->rid = id;
3941
11.5M
        cr->y = saved_ey;
3942
11.5M
    }
3943
139M
}
3944
3945
static void mark_curve_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * gs_restrict id)
3946
43.1k
{
3947
43.1k
        int ax = (sx + c1x)>>1;
3948
43.1k
        int ay = (sy + c1y)>>1;
3949
43.1k
        int bx = (c1x + c2x)>>1;
3950
43.1k
        int by = (c1y + c2y)>>1;
3951
43.1k
        int cx = (c2x + ex)>>1;
3952
43.1k
        int cy = (c2y + ey)>>1;
3953
43.1k
        int dx = (ax + bx)>>1;
3954
43.1k
        int dy = (ay + by)>>1;
3955
43.1k
        int fx = (bx + cx)>>1;
3956
43.1k
        int fy = (by + cy)>>1;
3957
43.1k
        int gx = (dx + fx)>>1;
3958
43.1k
        int gy = (dy + fy)>>1;
3959
3960
43.1k
        assert(depth >= 0);
3961
43.1k
        if (depth == 0) {
3962
26.4k
            *id += 1;
3963
26.4k
            mark_line_tr_app(cr, sx, sy, ex, ey, *id);
3964
26.4k
        } else {
3965
16.6k
            depth--;
3966
16.6k
            mark_curve_tr_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth, id);
3967
16.6k
            mark_curve_tr_app(cr, gx, gy, fx, fy, cx, cy, ex, ey, depth, id);
3968
16.6k
        }
3969
43.1k
}
3970
3971
static void mark_curve_big_tr_app(cursor_tr * gs_restrict cr, fixed64 sx, fixed64 sy, fixed64 c1x, fixed64 c1y, fixed64 c2x, fixed64 c2y, fixed64 ex, fixed64 ey, int depth, int * gs_restrict id)
3972
270k
{
3973
270k
    fixed64 ax = (sx + c1x)>>1;
3974
270k
    fixed64 ay = (sy + c1y)>>1;
3975
270k
    fixed64 bx = (c1x + c2x)>>1;
3976
270k
    fixed64 by = (c1y + c2y)>>1;
3977
270k
    fixed64 cx = (c2x + ex)>>1;
3978
270k
    fixed64 cy = (c2y + ey)>>1;
3979
270k
    fixed64 dx = (ax + bx)>>1;
3980
270k
    fixed64 dy = (ay + by)>>1;
3981
270k
    fixed64 fx = (bx + cx)>>1;
3982
270k
    fixed64 fy = (by + cy)>>1;
3983
270k
    fixed64 gx = (dx + fx)>>1;
3984
270k
    fixed64 gy = (dy + fy)>>1;
3985
3986
270k
    assert(depth >= 0);
3987
270k
    if (depth == 0) {
3988
135k
        *id += 1;
3989
135k
        mark_line_tr_app(cr, (fixed)sx, (fixed)sy, (fixed)ex, (fixed)ey, *id);
3990
135k
    } else {
3991
135k
        depth--;
3992
135k
        mark_curve_big_tr_app(cr, sx, sy, ax, ay, dx, dy, gx, gy, depth, id);
3993
135k
        mark_curve_big_tr_app(cr, gx, gy, fx, fy, cx, cy, ex, ey, depth, id);
3994
135k
    }
3995
270k
}
3996
3997
static void mark_curve_top_tr_app(cursor_tr * gs_restrict cr, fixed sx, fixed sy, fixed c1x, fixed c1y, fixed c2x, fixed c2y, fixed ex, fixed ey, int depth, int * gs_restrict id)
3998
9.85k
{
3999
9.85k
    fixed test = (sx^(sx<<1))|(sy^(sy<<1))|(c1x^(c1x<<1))|(c1y^(c1y<<1))|(c2x^(c2x<<1))|(c2y^(c2y<<1))|(ex^(ex<<1))|(ey^(ey<<1));
4000
4001
9.85k
    if (test < 0)
4002
36
        mark_curve_big_tr_app(cr, sx, sy, c1x, c1y, c2x, c2y, ex, ey, depth, id);
4003
9.82k
    else
4004
9.82k
        mark_curve_tr_app(cr, sx, sy, c1x, c1y, c2x, c2y, ex, ey, depth, id);
4005
9.85k
}
4006
4007
static int make_table_tr_app(gx_device     * pdev,
4008
                             gx_path       * path,
4009
                             gs_fixed_rect * ibox,
4010
                             int           * scanlines,
4011
                             int          ** index,
4012
                             int          ** table)
4013
14.3M
{
4014
14.3M
    return make_table_template(pdev, path, ibox, 4, 0, scanlines, index, table);
4015
14.3M
}
4016
4017
static void
4018
fill_zero_app_tr(int *row, const fixed *x)
4019
6.48k
{
4020
6.48k
    int n = *row = (*row)+2; /* Increment the count */
4021
6.48k
    row[4*n-7] = x[0];
4022
6.48k
    row[4*n-6] = 0;
4023
6.48k
    row[4*n-5] = x[1];
4024
6.48k
    row[4*n-4] = 0;
4025
6.48k
    row[4*n-3] = x[1];
4026
6.48k
    row[4*n-2] = (1<<1)|1;
4027
6.48k
    row[4*n-1] = x[1];
4028
6.48k
    row[4*n  ] = 1;
4029
6.48k
}
4030
4031
int gx_scan_convert_tr_app(gx_device     * gs_restrict pdev,
4032
                           gx_path       * gs_restrict path,
4033
                     const gs_fixed_rect * gs_restrict clip,
4034
                           gx_edgebuffer * gs_restrict edgebuffer,
4035
                           fixed                    fixed_flat)
4036
15.1M
{
4037
15.1M
    gs_fixed_rect  ibox;
4038
15.1M
    gs_fixed_rect  bbox;
4039
15.1M
    int            scanlines;
4040
15.1M
    const subpath *psub;
4041
15.1M
    int           *index;
4042
15.1M
    int           *table;
4043
15.1M
    int            i;
4044
15.1M
    cursor_tr      cr;
4045
15.1M
    int            code;
4046
15.1M
    int            id = 0;
4047
15.1M
    int            zero;
4048
4049
15.1M
    edgebuffer->index = NULL;
4050
15.1M
    edgebuffer->table = NULL;
4051
4052
    /* Bale out if no actual path. We see this with the clist */
4053
15.1M
    if (path->first_subpath == NULL)
4054
692k
        return 0;
4055
4056
14.4M
    zero = make_bbox(path, clip, &bbox, &ibox, 0);
4057
14.4M
    if (zero < 0)
4058
0
        return zero;
4059
4060
14.4M
    if (ibox.q.y <= ibox.p.y)
4061
118k
        return 0;
4062
4063
14.3M
    code = make_table_tr_app(pdev, path, &ibox, &scanlines, &index, &table);
4064
14.3M
    if (code != 0) /* > 0 means "retry with smaller height" */
4065
180
        return code;
4066
4067
14.3M
    if (scanlines == 0)
4068
0
        return 0;
4069
4070
14.3M
    if (zero) {
4071
6.03k
        code = zero_case(pdev, path, &ibox, index, table, fixed_flat, fill_zero_app_tr);
4072
14.3M
    } else {
4073
4074
    /* Step 2 continued: Now we run through the path, filling in the real
4075
     * values. */
4076
14.3M
    cr.scanlines = scanlines;
4077
14.3M
    cr.index     = index;
4078
14.3M
    cr.table     = table;
4079
14.3M
    cr.base      = ibox.p.y;
4080
35.3M
    for (psub = path->first_subpath; psub != 0;) {
4081
20.9M
        const segment *pseg = (const segment *)psub;
4082
20.9M
        fixed ex = pseg->pt.x;
4083
20.9M
        fixed ey = pseg->pt.y;
4084
20.9M
        fixed ix = ex;
4085
20.9M
        fixed iy = ey;
4086
20.9M
        fixed sx, sy;
4087
4088
20.9M
        if ((ey & 0xff) == 0) {
4089
904k
            cr.left  = max_fixed;
4090
904k
            cr.right = min_fixed;
4091
20.0M
        } else {
4092
20.0M
            cr.left = cr.right = ex;
4093
20.0M
        }
4094
20.9M
        cr.lid = cr.rid = id+1;
4095
20.9M
        cr.y = ey;
4096
20.9M
        cr.d = DIRN_UNSET;
4097
20.9M
        cr.first = 1;
4098
20.9M
        cr.saved = 0;
4099
4100
898M
        while ((pseg = pseg->next) != 0 &&
4101
883M
               pseg->type != s_start
4102
877M
            ) {
4103
877M
            sx = ex;
4104
877M
            sy = ey;
4105
877M
            ex = pseg->pt.x;
4106
877M
            ey = pseg->pt.y;
4107
4108
877M
            switch (pseg->type) {
4109
0
                default:
4110
0
                case s_start: /* Should never happen */
4111
0
                case s_dash:  /* We should never be seeing a dash here */
4112
0
                    assert("This should never happen" == NULL);
4113
0
                    break;
4114
9.85k
                case s_curve: {
4115
9.85k
                    const curve_segment *const pcur = (const curve_segment *)pseg;
4116
9.85k
                    int k = gx_curve_log2_samples(sx, sy, pcur, fixed_flat);
4117
4118
9.85k
                    mark_curve_top_tr_app(&cr, sx, sy, pcur->p1.x, pcur->p1.y, pcur->p2.x, pcur->p2.y, ex, ey, k, &id);
4119
9.85k
                    break;
4120
0
                }
4121
0
                case s_gap:
4122
857M
                case s_line:
4123
877M
                case s_line_close:
4124
877M
                    mark_line_tr_app(&cr, sx, sy, ex, ey, ++id);
4125
877M
                    break;
4126
877M
            }
4127
877M
        }
4128
        /* And close any open segments */
4129
20.9M
        mark_line_tr_app(&cr, ex, ey, ix, iy, ++id);
4130
20.9M
        cursor_flush_tr(&cr, ex, id);
4131
20.9M
        psub = (const subpath *)pseg;
4132
20.9M
    }
4133
14.3M
    }
4134
4135
    /* Step 2 complete: We now have a complete list of intersection data in
4136
     * table, indexed by index. */
4137
4138
14.3M
    edgebuffer->base   = ibox.p.y;
4139
14.3M
    edgebuffer->height = scanlines;
4140
14.3M
    edgebuffer->xmin   = ibox.p.x;
4141
14.3M
    edgebuffer->xmax   = ibox.q.x;
4142
14.3M
    edgebuffer->index  = index;
4143
14.3M
    edgebuffer->table  = table;
4144
4145
#ifdef DEBUG_SCAN_CONVERTER
4146
    if (debugging_scan_converter) {
4147
        dlprintf("Before sorting\n");
4148
        gx_edgebuffer_print_tr_app(edgebuffer);
4149
    }
4150
#endif
4151
4152
    /* Step 3: Sort the intersects on x */
4153
381M
    for (i=0; i < scanlines; i++) {
4154
366M
        int *row = &table[index[i]];
4155
366M
        int  rowlen = *row++;
4156
4157
        /* Bubblesort short runs, qsort longer ones. */
4158
        /* Figure of '6' comes from testing */
4159
366M
        if (rowlen <= 6) {
4160
363M
            int j, k;
4161
763M
            for (j = 0; j < rowlen-1; j++) {
4162
400M
                int * gs_restrict t = &row[j<<2];
4163
864M
                for (k = j+1; k < rowlen; k++) {
4164
464M
                    int * gs_restrict s = &row[k<<2];
4165
464M
                    int tmp;
4166
464M
                    if (t[0] < s[0])
4167
209M
                        continue;
4168
255M
                    if (t[0] > s[0])
4169
241M
                        goto swap0213;
4170
13.9M
                    if (t[2] < s[2])
4171
1.52M
                        continue;
4172
12.4M
                    if (t[2] > s[2])
4173
2.75M
                        goto swap213;
4174
9.67M
                    if (t[1] < s[1])
4175
8.61M
                        continue;
4176
1.05M
                    if (t[1] > s[1])
4177
1.05M
                        goto swap13;
4178
45
                    if (t[3] <= s[3])
4179
45
                        continue;
4180
0
                    if (0) {
4181
241M
swap0213:
4182
241M
                        tmp = t[0], t[0] = s[0], s[0] = tmp;
4183
243M
swap213:
4184
243M
                        tmp = t[2], t[2] = s[2], s[2] = tmp;
4185
245M
swap13:
4186
245M
                        tmp = t[1], t[1] = s[1], s[1] = tmp;
4187
245M
                    }
4188
245M
                    tmp = t[3], t[3] = s[3], s[3] = tmp;
4189
245M
                }
4190
400M
            }
4191
363M
        } else
4192
2.77M
            qsort(row, rowlen, 4*sizeof(int), edgecmp_tr);
4193
366M
    }
4194
4195
14.3M
    return 0;
4196
14.3M
}
4197
4198
/* Step 5: Filter the intersections according to the rules */
4199
int
4200
gx_filter_edgebuffer_tr_app(gx_device       * gs_restrict pdev,
4201
                            gx_edgebuffer   * gs_restrict edgebuffer,
4202
                            int                        rule)
4203
15.1M
{
4204
15.1M
    int i;
4205
15.1M
    int marked_id = 0;
4206
4207
#ifdef DEBUG_SCAN_CONVERTER
4208
    if (debugging_scan_converter) {
4209
        dlprintf("Before filtering:\n");
4210
        gx_edgebuffer_print_tr_app(edgebuffer);
4211
    }
4212
#endif
4213
4214
381M
    for (i=0; i < edgebuffer->height; i++) {
4215
366M
        int *row      = &edgebuffer->table[edgebuffer->index[i]];
4216
366M
        int  rowlen   = *row++;
4217
366M
        int *rowstart = row;
4218
366M
        int *rowout   = row;
4219
366M
        int  ll, llid, lr, lrid, rlid, rr, rrid, wind, marked_to;
4220
4221
        /* Avoid double setting pixels, by keeping where we have marked to. */
4222
366M
        marked_to = INT_MIN;
4223
791M
        while (rowlen > 0) {
4224
425M
            if (rule == gx_rule_even_odd) {
4225
                /* Even Odd */
4226
29.0M
                ll   = *row++;
4227
29.0M
                llid = (*row++)>>1;
4228
29.0M
                lr   = *row++;
4229
29.0M
                lrid = *row++;
4230
29.0M
                rowlen--;
4231
4232
                /* We will fill solidly from ll to at least lr, possibly further */
4233
29.0M
                assert(rowlen > 0);
4234
29.0M
                (void)row++; /* rl not needed here */
4235
29.0M
                (void)row++;
4236
29.0M
                rr   = *row++;
4237
29.0M
                rrid = *row++;
4238
29.0M
                rowlen--;
4239
29.0M
                if (rr > lr) {
4240
26.5M
                    lr   = rr;
4241
26.5M
                    lrid = rrid;
4242
26.5M
                }
4243
395M
            } else {
4244
                /* Non-Zero */
4245
395M
                int w;
4246
4247
395M
                ll   = *row++;
4248
395M
                llid = *row++;
4249
395M
                lr   = *row++;
4250
395M
                lrid = *row++;
4251
395M
                wind = -(llid&1) | 1;
4252
395M
                llid >>= 1;
4253
395M
                rowlen--;
4254
4255
395M
                assert(rowlen > 0);
4256
408M
                do {
4257
408M
                    (void)row++; /* rl not needed */
4258
408M
                    rlid = *row++;
4259
408M
                    rr   = *row++;
4260
408M
                    rrid = *row++;
4261
408M
                    w = -(rlid&1) | 1;
4262
408M
                    rlid >>= 1;
4263
408M
                    rowlen--;
4264
408M
                    if (rr > lr) {
4265
396M
                        lr   = rr;
4266
396M
                        lrid = rrid;
4267
396M
                    }
4268
408M
                    wind += w;
4269
408M
                    if (wind == 0)
4270
395M
                        break;
4271
408M
                } while (rowlen > 0);
4272
395M
            }
4273
4274
425M
            if (lr < marked_to)
4275
1.54M
                continue;
4276
4277
423M
            if (marked_to >= ll) {
4278
5.04M
                if (rowout == rowstart) {
4279
1.92k
                    ll   = marked_to;
4280
1.92k
                    llid = --marked_id;
4281
5.04M
                } else {
4282
5.04M
                    rowout -= 4;
4283
5.04M
                    ll   = rowout[0];
4284
5.04M
                    llid = rowout[1];
4285
5.04M
                }
4286
5.04M
            }
4287
4288
423M
            if (lr >= ll) {
4289
423M
                *rowout++ = ll;
4290
423M
                *rowout++ = llid;
4291
423M
                *rowout++ = lr;
4292
423M
                *rowout++ = lrid;
4293
423M
                marked_to = lr;
4294
423M
            }
4295
423M
        }
4296
366M
        rowstart[-1] = (rowout - rowstart)>>2;
4297
366M
    }
4298
15.1M
    return 0;
4299
15.1M
}
4300
4301
/* Step 6: Fill */
4302
int
4303
gx_fill_edgebuffer_tr_app(gx_device       * gs_restrict pdev,
4304
                    const gx_device_color * gs_restrict pdevc,
4305
                          gx_edgebuffer   * gs_restrict edgebuffer,
4306
                          int                        log_op)
4307
15.1M
{
4308
15.1M
    int i, j, code;
4309
15.1M
    int mfb = pdev->max_fill_band;
4310
4311
#ifdef DEBUG_SCAN_CONVERTER
4312
    if (debugging_scan_converter) {
4313
        dlprintf("Filling:\n");
4314
        gx_edgebuffer_print_filtered_tr_app(edgebuffer);
4315
    }
4316
#endif
4317
4318
66.3M
    for (i=0; i < edgebuffer->height; ) {
4319
51.1M
        int *row    = &edgebuffer->table[edgebuffer->index[i]];
4320
51.1M
        int  rowlen = *row++;
4321
51.1M
        int *row2;
4322
51.1M
        int *rowptr;
4323
51.1M
        int *row2ptr;
4324
51.1M
        int y_band_max;
4325
4326
51.1M
        if (mfb) {
4327
0
            y_band_max = (i & ~(mfb-1)) + mfb;
4328
0
            if (y_band_max > edgebuffer->height)
4329
0
                y_band_max = edgebuffer->height;
4330
51.1M
        } else {
4331
51.1M
            y_band_max = edgebuffer->height;
4332
51.1M
        }
4333
4334
        /* See how many scanlines match i */
4335
366M
        for (j = i+1; j < y_band_max; j++) {
4336
352M
            int row2len;
4337
4338
352M
            row2    = &edgebuffer->table[edgebuffer->index[j]];
4339
352M
            row2len = *row2++;
4340
352M
            row2ptr = row2;
4341
352M
            rowptr  = row;
4342
4343
352M
            if (rowlen != row2len)
4344
1.50M
                break;
4345
682M
            while (row2len > 0) {
4346
367M
                if (rowptr[1] != row2ptr[1] || rowptr[3] != row2ptr[3])
4347
35.3M
                    goto rowdifferent;
4348
331M
                rowptr  += 4;
4349
331M
                row2ptr += 4;
4350
331M
                row2len--;
4351
331M
            }
4352
350M
        }
4353
51.1M
rowdifferent:{}
4354
4355
        /* So j is the first scanline that doesn't match i */
4356
4357
        /* The first scanline is always sent as rectangles */
4358
140M
        while (rowlen > 0) {
4359
89.7M
            int left  = row[0];
4360
89.7M
            int right = row[2];
4361
89.7M
            row += 4;
4362
89.7M
            left = fixed2int(left);
4363
89.7M
            right = fixed2int(right + fixed_1 - 1);
4364
89.7M
            rowlen--;
4365
4366
89.7M
            right -= left;
4367
89.7M
            if (right > 0) {
4368
#ifdef DEBUG_OUTPUT_SC_AS_PS
4369
                dlprintf("0.001 setlinewidth 1 0 0 setrgbcolor %%red %%PS\n");
4370
                coord("moveto", int2fixed(left), int2fixed(edgebuffer->base+i));
4371
                coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i));
4372
                coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+i+1));
4373
                coord("lineto", int2fixed(left), int2fixed(edgebuffer->base+i+1));
4374
                dlprintf("closepath stroke %%PS\n");
4375
#endif
4376
89.7M
                if (log_op < 0)
4377
0
                    code = dev_proc(pdev, fill_rectangle)(pdev, left, edgebuffer->base+i, right, 1, pdevc->colors.pure);
4378
89.7M
                else
4379
89.7M
                    code = gx_fill_rectangle_device_rop(left, edgebuffer->base+i, right, 1, pdevc, pdev, (gs_logical_operation_t)log_op);
4380
89.7M
                if (code < 0)
4381
1
                    return code;
4382
89.7M
            }
4383
89.7M
        }
4384
4385
        /* The middle section (all but the first and last
4386
         * scanlines) can be sent as a trapezoid. */
4387
51.1M
        if (i + 2 < j) {
4388
15.4M
            gs_fixed_edge le;
4389
15.4M
            gs_fixed_edge re;
4390
15.4M
            fixed ybot = int2fixed(edgebuffer->base+i+1);
4391
15.4M
            fixed ytop = int2fixed(edgebuffer->base+j-1);
4392
15.4M
            int *row3, *row4;
4393
15.4M
            int offset = 1;
4394
15.4M
            row    = &edgebuffer->table[edgebuffer->index[i]];
4395
15.4M
            row2    = &edgebuffer->table[edgebuffer->index[i+1]];
4396
15.4M
            row3    = &edgebuffer->table[edgebuffer->index[j-2]];
4397
15.4M
            row4    = &edgebuffer->table[edgebuffer->index[j-1]];
4398
15.4M
            rowlen = *row;
4399
31.9M
            while (rowlen > 0) {
4400
                /* The fill rules used by fill_trap state that if a
4401
                 * pixel centre is touched by a boundary, the pixel
4402
                 * will be filled iff the boundary is horizontal and
4403
                 * the filled region is above it, or the boundary is
4404
                 * not horizontal, and the filled region is to the
4405
                 * right of it.
4406
                 *
4407
                 * We need to fill "any part of a pixel", not just
4408
                 * "centre covered", so we need to adjust our edges
4409
                 * by half a pixel in both X and Y.
4410
                 *
4411
                 * X is relatively easy. We move the left edge back by
4412
                 * just less than half, so ...00 goes to ...81 and
4413
                 * therefore does not cause an extra pixel to get filled.
4414
                 *
4415
                 * Similarly, we move the right edge forward by half, so
4416
                 *  ...00 goes to ...80 and therefore does not cause an
4417
                 * extra pixel to get filled.
4418
                 *
4419
                 * For y, we can adjust edges up or down as appropriate.
4420
                 * We move up by half, so ...0 goes to ..80 and therefore
4421
                 * does not cause an extra pixel to get filled. We move
4422
                 * down by just less than a half so that ...0 goes to
4423
                 * ...81 and therefore does not cause an extra pixel to
4424
                 * get filled.
4425
                 *
4426
                 * We use ybot = ...80 and ytop = ...81 in the trap call
4427
                 * so that it just covers the pixel centres.
4428
                 */
4429
16.5M
                if (row[offset] <= row4[offset]) {
4430
11.2M
                    le.start.x = row2[offset] - (fixed_half-1);
4431
11.2M
                    le.end.x   = row4[offset] - (fixed_half-1);
4432
11.2M
                    le.start.y = ybot + fixed_half;
4433
11.2M
                    le.end.y   = ytop + fixed_half;
4434
11.2M
                } else {
4435
5.33M
                    le.start.x = row [offset] - (fixed_half-1);
4436
5.33M
                    le.end.x   = row3[offset] - (fixed_half-1);
4437
5.33M
                    le.start.y = ybot - (fixed_half-1);
4438
5.33M
                    le.end.y   = ytop - (fixed_half-1);
4439
5.33M
                }
4440
16.5M
                if (row[offset+2] <= row4[offset+2]) {
4441
11.2M
                    re.start.x = row [offset+2] + fixed_half;
4442
11.2M
                    re.end.x   = row3[offset+2] + fixed_half;
4443
11.2M
                    re.start.y = ybot - (fixed_half-1);
4444
11.2M
                    re.end.y   = ytop - (fixed_half-1);
4445
11.2M
                } else {
4446
5.28M
                    re.start.x = row2[offset+2] + fixed_half;
4447
5.28M
                    re.end.x   = row4[offset+2] + fixed_half;
4448
5.28M
                    re.start.y = ybot + fixed_half;
4449
5.28M
                    re.end.y   = ytop + fixed_half;
4450
5.28M
                }
4451
16.5M
                offset += 4;
4452
16.5M
                rowlen--;
4453
4454
16.5M
                assert(re.start.x >= le.start.x);
4455
16.5M
                assert(re.end.x >= le.end.x);
4456
16.5M
                assert(le.start.y <= ybot + fixed_half);
4457
16.5M
                assert(re.start.y <= ybot + fixed_half);
4458
16.5M
                assert(le.end.y >= ytop - (fixed_half - 1));
4459
16.5M
                assert(re.end.y >= ytop - (fixed_half - 1));
4460
4461
#ifdef DEBUG_OUTPUT_SC_AS_PS
4462
                dlprintf("0.001 setlinewidth 0 1 0 setrgbcolor %% green %%PS\n");
4463
                coord("moveto", le.start.x, le.start.y);
4464
                coord("lineto", le.end.x, le.end.y);
4465
                coord("lineto", re.end.x, re.end.y);
4466
                coord("lineto", re.start.x, re.start.y);
4467
                dlprintf("closepath stroke %%PS\n");
4468
#endif
4469
16.5M
                code = dev_proc(pdev, fill_trapezoid)(
4470
16.5M
                                pdev,
4471
16.5M
                                &le,
4472
16.5M
                                &re,
4473
16.5M
                                ybot + fixed_half,
4474
16.5M
                                ytop - (fixed_half - 1),
4475
16.5M
                                0, /* bool swap_axes */
4476
16.5M
                                pdevc, /*const gx_drawing_color *pdcolor */
4477
16.5M
                                log_op);
4478
16.5M
                if (code < 0)
4479
0
                    return code;
4480
16.5M
            }
4481
15.4M
        }
4482
4483
51.1M
        if (i + 1 < j)
4484
23.2M
        {
4485
            /* The last scanline is always sent as rectangles */
4486
23.2M
            row    = &edgebuffer->table[edgebuffer->index[j-1]];
4487
23.2M
            rowlen = *row++;
4488
48.7M
            while (rowlen > 0) {
4489
25.4M
                int left  = row[0];
4490
25.4M
                int right = row[2];
4491
25.4M
                row += 4;
4492
25.4M
                left = fixed2int(left);
4493
25.4M
                right = fixed2int(right + fixed_1 - 1);
4494
25.4M
                rowlen--;
4495
4496
25.4M
                right -= left;
4497
25.4M
                if (right > 0) {
4498
#ifdef DEBUG_OUTPUT_SC_AS_PS
4499
                    dlprintf("0.001 setlinewidth 0 0 1 setrgbcolor %% blue %%PS\n");
4500
                    coord("moveto", int2fixed(left), int2fixed(edgebuffer->base+j-1));
4501
                    coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+j-1));
4502
                    coord("lineto", int2fixed(left+right), int2fixed(edgebuffer->base+j));
4503
                    coord("lineto", int2fixed(left), int2fixed(edgebuffer->base+j));
4504
                    dlprintf("closepath stroke %%PS\n");
4505
#endif
4506
25.4M
                    if (log_op < 0)
4507
0
                        code = dev_proc(pdev, fill_rectangle)(pdev, left, edgebuffer->base+j-1, right, 1, pdevc->colors.pure);
4508
25.4M
                    else
4509
25.4M
                        code = gx_fill_rectangle_device_rop(left, edgebuffer->base+j-1, right, 1, pdevc, pdev, (gs_logical_operation_t)log_op);
4510
25.4M
                    if (code < 0)
4511
0
                        return code;
4512
25.4M
                }
4513
25.4M
            }
4514
23.2M
        }
4515
51.1M
        i = j;
4516
51.1M
    }
4517
15.1M
    return 0;
4518
15.1M
}
4519
4520
4521
void
4522
gx_edgebuffer_init(gx_edgebuffer * edgebuffer)
4523
16.1M
{
4524
16.1M
    edgebuffer->base   = 0;
4525
16.1M
    edgebuffer->height = 0;
4526
16.1M
    edgebuffer->index  = NULL;
4527
16.1M
    edgebuffer->table  = NULL;
4528
16.1M
}
4529
4530
void
4531
gx_edgebuffer_fin(gx_device     * pdev,
4532
                  gx_edgebuffer * edgebuffer)
4533
16.1M
{
4534
16.1M
    gs_free_object(pdev->memory, edgebuffer->table, "scanc intersects buffer");
4535
16.1M
    gs_free_object(pdev->memory, edgebuffer->index, "scanc index buffer");
4536
16.1M
    edgebuffer->index = NULL;
4537
16.1M
    edgebuffer->table = NULL;
4538
16.1M
}
4539
4540
gx_scan_converter_t gx_scan_converter =
4541
{
4542
    gx_scan_convert,
4543
    gx_filter_edgebuffer,
4544
    gx_fill_edgebuffer
4545
};
4546
4547
gx_scan_converter_t gx_scan_converter_app =
4548
{
4549
    gx_scan_convert_app,
4550
    gx_filter_edgebuffer_app,
4551
    gx_fill_edgebuffer_app
4552
};
4553
4554
gx_scan_converter_t gx_scan_converter_tr =
4555
{
4556
    gx_scan_convert_tr,
4557
    gx_filter_edgebuffer_tr,
4558
    gx_fill_edgebuffer_tr
4559
};
4560
4561
gx_scan_converter_t gx_scan_converter_tr_app =
4562
{
4563
    gx_scan_convert_tr_app,
4564
    gx_filter_edgebuffer_tr_app,
4565
    gx_fill_edgebuffer_tr_app
4566
};
4567
4568
int
4569
gx_scan_convert_and_fill(const gx_scan_converter_t *sc,
4570
                               gx_device       *dev,
4571
                               gx_path         *ppath,
4572
                         const gs_fixed_rect   *ibox,
4573
                               fixed            flat,
4574
                               int              rule,
4575
                         const gx_device_color *pdevc,
4576
                               int              lop)
4577
16.1M
{
4578
16.1M
    int code;
4579
16.1M
    gx_edgebuffer eb;
4580
16.1M
    gs_fixed_rect ibox2 = *ibox;
4581
16.1M
    int height;
4582
16.1M
    int mfb = dev->max_fill_band;
4583
4584
16.1M
    if (mfb != 0) {
4585
0
        ibox2.p.y &= ~(mfb-1);
4586
0
        ibox2.q.y = (ibox2.q.y+mfb-1) & ~(mfb-1);
4587
0
    }
4588
16.1M
    height = ibox2.q.y - ibox2.p.y;
4589
4590
16.1M
    do {
4591
16.1M
        gx_edgebuffer_init(&eb);
4592
16.1M
        while (1) {
4593
16.1M
            ibox2.q.y = ibox2.p.y + height;
4594
16.1M
            if (ibox2.q.y > ibox->q.y)
4595
80
                ibox2.q.y = ibox->q.y;
4596
16.1M
            code = sc->scan_convert(dev,
4597
16.1M
                                    ppath,
4598
16.1M
                                    &ibox2,
4599
16.1M
                                    &eb,
4600
16.1M
                                    flat);
4601
16.1M
            if (code <= 0)
4602
16.1M
                break;
4603
            /* Let's shrink the ibox and try again */
4604
183
            if (mfb && height == mfb) {
4605
                /* Can't shrink the height any more! */
4606
0
                code = gs_error_rangecheck;
4607
0
                break;
4608
0
            }
4609
183
            height = height/code;
4610
183
            if (mfb)
4611
0
                height = (height + mfb-1) & ~(mfb-1);
4612
183
            if (height < (mfb ? mfb : 1)) {
4613
0
                code = gs_error_VMerror;
4614
0
                break;
4615
0
            }
4616
183
        }
4617
16.1M
        if (code >= 0)
4618
16.1M
            code = sc->filter(dev,
4619
16.1M
                              &eb,
4620
16.1M
                              rule);
4621
16.1M
        if (code >= 0)
4622
16.1M
            code = sc->fill(dev,
4623
16.1M
                            pdevc,
4624
16.1M
                            &eb,
4625
16.1M
                            lop);
4626
16.1M
        gx_edgebuffer_fin(dev,&eb);
4627
16.1M
        ibox2.p.y += height;
4628
16.1M
    }
4629
16.1M
    while (ibox2.p.y < ibox->q.y);
4630
4631
16.1M
    return code;
4632
16.1M
}