Coverage Report

Created: 2022-10-31 07:00

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