Coverage Report

Created: 2025-06-24 07:01

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