~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to mi/miwideline.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: miwideline.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1988, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall
 
24
not be used in advertising or otherwise to promote the sale, use or
 
25
other dealings in this Software without prior written authorization
 
26
from The Open Group.
 
27
 
 
28
*/
 
29
/* $XFree86: xc/programs/Xserver/mi/miwideline.c,v 1.12 2001/12/14 20:00:28 dawes Exp $ */
 
30
 
 
31
/* Author:  Keith Packard, MIT X Consortium */
 
32
 
 
33
/*
 
34
 * Mostly integer wideline code.  Uses a technique similar to
 
35
 * bresenham zero-width lines, except walks an X edge
 
36
 */
 
37
 
 
38
#ifdef HAVE_DIX_CONFIG_H
 
39
#include <dix-config.h>
 
40
#endif
 
41
 
 
42
#include <stdio.h>
 
43
#ifdef _XOPEN_SOURCE
 
44
#include <math.h>
 
45
#else
 
46
#define _XOPEN_SOURCE   /* to get prototype for hypot on some systems */
 
47
#include <math.h>
 
48
#undef _XOPEN_SOURCE
 
49
#endif
 
50
#include <X11/X.h>
 
51
#include "windowstr.h"
 
52
#include "gcstruct.h"
 
53
#include "regionstr.h"
 
54
#include "miwideline.h"
 
55
#include "mi.h"
 
56
 
 
57
#ifdef ICEILTEMPDECL
 
58
ICEILTEMPDECL
 
59
#endif
 
60
 
 
61
static void miLineArc(DrawablePtr pDraw, register GCPtr pGC,
 
62
                      unsigned long pixel, SpanDataPtr spanData,
 
63
                      register LineFacePtr leftFace,
 
64
                      register LineFacePtr rightFace,
 
65
                      double xorg, double yorg, Bool isInt);
 
66
 
 
67
 
 
68
/*
 
69
 * spans-based polygon filler
 
70
 */
 
71
 
 
72
void
 
73
miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, overall_height,
 
74
                  left, right, left_count, right_count)
 
75
    DrawablePtr pDrawable;
 
76
    GCPtr       pGC;
 
77
    unsigned long   pixel;
 
78
    SpanDataPtr spanData;
 
79
    int         y;                      /* start y coordinate */
 
80
    int         overall_height;         /* height of entire segment */
 
81
    PolyEdgePtr left, right;
 
82
    int         left_count, right_count;
 
83
{
 
84
    register int left_x = 0, left_e = 0;
 
85
    int left_stepx = 0;
 
86
    int left_signdx = 0;
 
87
    int left_dy = 0, left_dx = 0;
 
88
 
 
89
    register int right_x = 0, right_e = 0;
 
90
    int right_stepx = 0;
 
91
    int right_signdx = 0;
 
92
    int right_dy = 0, right_dx = 0;
 
93
 
 
94
    int height = 0;
 
95
    int left_height = 0, right_height = 0;
 
96
 
 
97
    register DDXPointPtr ppt;
 
98
    DDXPointPtr pptInit = NULL;
 
99
    register int *pwidth;
 
100
    int *pwidthInit = NULL;
 
101
    XID         oldPixel;
 
102
    int         xorg;
 
103
    Spans       spanRec;
 
104
 
 
105
    left_height = 0;
 
106
    right_height = 0;
 
107
    
 
108
    if (!spanData)
 
109
    {
 
110
        pptInit = (DDXPointPtr) ALLOCATE_LOCAL (overall_height * sizeof(*ppt));
 
111
        if (!pptInit)
 
112
            return;
 
113
        pwidthInit = (int *) ALLOCATE_LOCAL (overall_height * sizeof(*pwidth));
 
114
        if (!pwidthInit)
 
115
        {
 
116
            DEALLOCATE_LOCAL (pptInit);
 
117
            return;
 
118
        }
 
119
        ppt = pptInit;
 
120
        pwidth = pwidthInit;
 
121
        oldPixel = pGC->fgPixel;
 
122
        if (pixel != oldPixel)
 
123
        {
 
124
            DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
 
125
            ValidateGC (pDrawable, pGC);
 
126
        }
 
127
    }
 
128
    else
 
129
    {
 
130
        spanRec.points = (DDXPointPtr) xalloc (overall_height * sizeof (*ppt));
 
131
        if (!spanRec.points)
 
132
            return;
 
133
        spanRec.widths = (int *) xalloc (overall_height * sizeof (int));
 
134
        if (!spanRec.widths)
 
135
        {
 
136
            xfree (spanRec.points);
 
137
            return;
 
138
        }
 
139
        ppt = spanRec.points;
 
140
        pwidth = spanRec.widths;
 
141
    }
 
142
 
 
143
    xorg = 0;
 
144
    if (pGC->miTranslate)
 
145
    {
 
146
        y += pDrawable->y;
 
147
        xorg = pDrawable->x;
 
148
    }
 
149
    while ((left_count || left_height) &&
 
150
           (right_count || right_height))
 
151
    {
 
152
        MIPOLYRELOADLEFT
 
153
        MIPOLYRELOADRIGHT
 
154
 
 
155
        height = left_height;
 
156
        if (height > right_height)
 
157
            height = right_height;
 
158
 
 
159
        left_height -= height;
 
160
        right_height -= height;
 
161
 
 
162
        while (--height >= 0)
 
163
        {
 
164
            if (right_x >= left_x)
 
165
            {
 
166
                ppt->y = y;
 
167
                ppt->x = left_x + xorg;
 
168
                ppt++;
 
169
                *pwidth++ = right_x - left_x + 1;
 
170
            }
 
171
            y++;
 
172
        
 
173
            MIPOLYSTEPLEFT
 
174
 
 
175
            MIPOLYSTEPRIGHT
 
176
        }
 
177
    }
 
178
    if (!spanData)
 
179
    {
 
180
        (*pGC->ops->FillSpans) (pDrawable, pGC, ppt - pptInit, pptInit, pwidthInit, TRUE);
 
181
        DEALLOCATE_LOCAL (pwidthInit);
 
182
        DEALLOCATE_LOCAL (pptInit);
 
183
        if (pixel != oldPixel)
 
184
        {
 
185
            DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
 
186
            ValidateGC (pDrawable, pGC);
 
187
        }
 
188
    }
 
189
    else
 
190
    {
 
191
        spanRec.count = ppt - spanRec.points;
 
192
        AppendSpanGroup (pGC, pixel, &spanRec, spanData)
 
193
    }
 
194
}
 
195
 
 
196
static void
 
197
miFillRectPolyHelper (
 
198
    DrawablePtr pDrawable,
 
199
    GCPtr       pGC,
 
200
    unsigned long   pixel,
 
201
    SpanDataPtr spanData,
 
202
    int         x,
 
203
    int         y,
 
204
    int         w,
 
205
    int         h)
 
206
{
 
207
    register DDXPointPtr ppt;
 
208
    register int *pwidth;
 
209
    XID         oldPixel;
 
210
    Spans       spanRec;
 
211
    xRectangle  rect;
 
212
 
 
213
    if (!spanData)
 
214
    {
 
215
        rect.x = x;
 
216
        rect.y = y;
 
217
        rect.width = w;
 
218
        rect.height = h;
 
219
        oldPixel = pGC->fgPixel;
 
220
        if (pixel != oldPixel)
 
221
        {
 
222
            DoChangeGC (pGC, GCForeground, (XID *)&pixel, FALSE);
 
223
            ValidateGC (pDrawable, pGC);
 
224
        }
 
225
        (*pGC->ops->PolyFillRect) (pDrawable, pGC, 1, &rect);
 
226
        if (pixel != oldPixel)
 
227
        {
 
228
            DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
 
229
            ValidateGC (pDrawable, pGC);
 
230
        }
 
231
    }
 
232
    else
 
233
    {
 
234
        spanRec.points = (DDXPointPtr) xalloc (h * sizeof (*ppt));
 
235
        if (!spanRec.points)
 
236
            return;
 
237
        spanRec.widths = (int *) xalloc (h * sizeof (int));
 
238
        if (!spanRec.widths)
 
239
        {
 
240
            xfree (spanRec.points);
 
241
            return;
 
242
        }
 
243
        ppt = spanRec.points;
 
244
        pwidth = spanRec.widths;
 
245
 
 
246
        if (pGC->miTranslate)
 
247
        {
 
248
            y += pDrawable->y;
 
249
            x += pDrawable->x;
 
250
        }
 
251
        while (h--)
 
252
        {
 
253
            ppt->x = x;
 
254
            ppt->y = y;
 
255
            ppt++;
 
256
            *pwidth++ = w;
 
257
            y++;
 
258
        }
 
259
        spanRec.count = ppt - spanRec.points;
 
260
        AppendSpanGroup (pGC, pixel, &spanRec, spanData)
 
261
    }
 
262
}
 
263
 
 
264
/* static */ int
 
265
miPolyBuildEdge (x0, y0, k, dx, dy, xi, yi, left, edge)
 
266
    double      x0, y0;
 
267
    double      k;  /* x0 * dy - y0 * dx */
 
268
    register int dx, dy;
 
269
    int         xi, yi;
 
270
    int         left;
 
271
    register PolyEdgePtr edge;
 
272
{
 
273
    int     x, y, e;
 
274
    int     xady;
 
275
 
 
276
    if (dy < 0)
 
277
    {
 
278
        dy = -dy;
 
279
        dx = -dx;
 
280
        k = -k;
 
281
    }
 
282
 
 
283
#ifdef NOTDEF
 
284
    {
 
285
        double  realk, kerror;
 
286
        realk = x0 * dy - y0 * dx;
 
287
        kerror = Fabs (realk - k);
 
288
        if (kerror > .1)
 
289
            printf ("realk: %g k: %g\n", realk, k);
 
290
    }
 
291
#endif
 
292
    y = ICEIL (y0);
 
293
    xady = ICEIL (k) + y * dx;
 
294
 
 
295
    if (xady <= 0)
 
296
        x = - (-xady / dy) - 1;
 
297
    else
 
298
        x = (xady - 1) / dy;
 
299
 
 
300
    e = xady - x * dy;
 
301
 
 
302
    if (dx >= 0)
 
303
    {
 
304
        edge->signdx = 1;
 
305
        edge->stepx = dx / dy;
 
306
        edge->dx = dx % dy;
 
307
    }
 
308
    else
 
309
    {
 
310
        edge->signdx = -1;
 
311
        edge->stepx = - (-dx / dy);
 
312
        edge->dx = -dx % dy;
 
313
        e = dy - e + 1;
 
314
    }
 
315
    edge->dy = dy;
 
316
    edge->x = x + left + xi;
 
317
    edge->e = e - dy;   /* bias to compare against 0 instead of dy */
 
318
    return y + yi;
 
319
}
 
320
 
 
321
#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr)))
 
322
 
 
323
/* static */ int
 
324
miPolyBuildPoly (vertices, slopes, count, xi, yi, left, right, pnleft, pnright, h)
 
325
    register PolyVertexPtr vertices;
 
326
    register PolySlopePtr  slopes;
 
327
    int             count;
 
328
    int             xi, yi;
 
329
    PolyEdgePtr     left, right;
 
330
    int             *pnleft, *pnright;
 
331
    int             *h;
 
332
{
 
333
    int     top, bottom;
 
334
    double  miny, maxy;
 
335
    register int i;
 
336
    int     j;
 
337
    int     clockwise;
 
338
    int     slopeoff;
 
339
    register int s;
 
340
    register int nright, nleft;
 
341
    int     y, lasty = 0, bottomy, topy = 0;
 
342
 
 
343
    /* find the top of the polygon */
 
344
    maxy = miny = vertices[0].y;
 
345
    bottom = top = 0;
 
346
    for (i = 1; i < count; i++)
 
347
    {
 
348
        if (vertices[i].y < miny)
 
349
        {
 
350
            top = i;
 
351
            miny = vertices[i].y;
 
352
        }
 
353
        if (vertices[i].y >= maxy)
 
354
        {
 
355
            bottom = i;
 
356
            maxy = vertices[i].y;
 
357
        }
 
358
    }
 
359
    clockwise = 1;
 
360
    slopeoff = 0;
 
361
 
 
362
    i = top;
 
363
    j = StepAround (top, -1, count);
 
364
 
 
365
    if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx)
 
366
    {
 
367
        clockwise = -1;
 
368
        slopeoff = -1;
 
369
    }
 
370
 
 
371
    bottomy = ICEIL (maxy) + yi;
 
372
 
 
373
    nright = 0;
 
374
 
 
375
    s = StepAround (top, slopeoff, count);
 
376
    i = top;
 
377
    while (i != bottom)
 
378
    {
 
379
        if (slopes[s].dy != 0)
 
380
        {
 
381
            y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
 
382
                        slopes[s].k,
 
383
                        slopes[s].dx, slopes[s].dy,
 
384
                        xi, yi, 0,
 
385
                        &right[nright]);
 
386
            if (nright != 0)
 
387
                right[nright-1].height = y - lasty;
 
388
            else
 
389
                topy = y;
 
390
            nright++;
 
391
            lasty = y;
 
392
        }
 
393
 
 
394
        i = StepAround (i, clockwise, count);
 
395
        s = StepAround (s, clockwise, count);
 
396
    }
 
397
    if (nright != 0)
 
398
        right[nright-1].height = bottomy - lasty;
 
399
 
 
400
    if (slopeoff == 0)
 
401
        slopeoff = -1;
 
402
    else
 
403
        slopeoff = 0;
 
404
 
 
405
    nleft = 0;
 
406
    s = StepAround (top, slopeoff, count);
 
407
    i = top;
 
408
    while (i != bottom)
 
409
    {
 
410
        if (slopes[s].dy != 0)
 
411
        {
 
412
            y = miPolyBuildEdge (vertices[i].x, vertices[i].y,
 
413
                           slopes[s].k,
 
414
                           slopes[s].dx,  slopes[s].dy, xi, yi, 1,
 
415
                           &left[nleft]);
 
416
    
 
417
            if (nleft != 0)
 
418
                left[nleft-1].height = y - lasty;
 
419
            nleft++;
 
420
            lasty = y;
 
421
        }
 
422
        i = StepAround (i, -clockwise, count);
 
423
        s = StepAround (s, -clockwise, count);
 
424
    }
 
425
    if (nleft != 0)
 
426
        left[nleft-1].height = bottomy - lasty;
 
427
    *pnleft = nleft;
 
428
    *pnright = nright;
 
429
    *h = bottomy - topy;
 
430
    return topy;
 
431
}
 
432
 
 
433
static void
 
434
miLineOnePoint (
 
435
    DrawablePtr     pDrawable,
 
436
    GCPtr           pGC,
 
437
    unsigned long   pixel,
 
438
    SpanDataPtr     spanData,
 
439
    int             x,
 
440
    int             y)
 
441
{
 
442
    DDXPointRec pt;
 
443
    int     wid;
 
444
    unsigned long       oldPixel;
 
445
 
 
446
    MILINESETPIXEL (pDrawable, pGC, pixel, oldPixel);
 
447
    if (pGC->fillStyle == FillSolid)
 
448
    {
 
449
        pt.x = x;
 
450
        pt.y = y;
 
451
        (*pGC->ops->PolyPoint) (pDrawable, pGC, CoordModeOrigin, 1, &pt);
 
452
    }
 
453
    else
 
454
    {
 
455
        wid = 1;
 
456
        if (pGC->miTranslate) 
 
457
        {
 
458
            x += pDrawable->x;
 
459
            y += pDrawable->y;
 
460
        }
 
461
        pt.x = x;
 
462
        pt.y = y;
 
463
        (*pGC->ops->FillSpans) (pDrawable, pGC, 1, &pt, &wid, TRUE);
 
464
    }
 
465
    MILINERESETPIXEL (pDrawable, pGC, pixel, oldPixel);
 
466
}
 
467
 
 
468
static void
 
469
miLineJoin (
 
470
    DrawablePtr     pDrawable,
 
471
    GCPtr           pGC,
 
472
    unsigned long   pixel,
 
473
    SpanDataPtr     spanData,
 
474
    register LineFacePtr pLeft,
 
475
    register LineFacePtr pRight)
 
476
{
 
477
    double          mx = 0, my = 0;
 
478
    double          denom = 0.0;
 
479
    PolyVertexRec   vertices[4];
 
480
    PolySlopeRec    slopes[4];
 
481
    int             edgecount;
 
482
    PolyEdgeRec     left[4], right[4];
 
483
    int             nleft, nright;
 
484
    int             y, height;
 
485
    int             swapslopes;
 
486
    int             joinStyle = pGC->joinStyle;
 
487
    int             lw = pGC->lineWidth;
 
488
 
 
489
    if (lw == 1 && !spanData) {
 
490
        /* See if one of the lines will draw the joining pixel */
 
491
        if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0))
 
492
            return;
 
493
        if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0))
 
494
            return;
 
495
        if (joinStyle != JoinRound) {
 
496
            denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
 
497
            if (denom == 0)
 
498
                return; /* no join to draw */
 
499
        }
 
500
        if (joinStyle != JoinMiter) {
 
501
            miLineOnePoint (pDrawable, pGC, pixel, spanData, pLeft->x, pLeft->y);
 
502
            return;
 
503
        }
 
504
    } else {
 
505
        if (joinStyle == JoinRound)
 
506
        {
 
507
            miLineArc(pDrawable, pGC, pixel, spanData,
 
508
                      pLeft, pRight,
 
509
                      (double)0.0, (double)0.0, TRUE);
 
510
            return;
 
511
        }
 
512
        denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
 
513
        if (denom == 0.0)
 
514
            return;     /* no join to draw */
 
515
    }
 
516
 
 
517
    swapslopes = 0;
 
518
    if (denom > 0)
 
519
    {
 
520
        pLeft->xa = -pLeft->xa;
 
521
        pLeft->ya = -pLeft->ya;
 
522
        pLeft->dx = -pLeft->dx;
 
523
        pLeft->dy = -pLeft->dy;
 
524
    }
 
525
    else
 
526
    {
 
527
        swapslopes = 1;
 
528
        pRight->xa = -pRight->xa;
 
529
        pRight->ya = -pRight->ya;
 
530
        pRight->dx = -pRight->dx;
 
531
        pRight->dy = -pRight->dy;
 
532
    }
 
533
 
 
534
    vertices[0].x = pRight->xa;
 
535
    vertices[0].y = pRight->ya;
 
536
    slopes[0].dx = -pRight->dy;
 
537
    slopes[0].dy =  pRight->dx;
 
538
    slopes[0].k = 0;
 
539
 
 
540
    vertices[1].x = 0;
 
541
    vertices[1].y = 0;
 
542
    slopes[1].dx =  pLeft->dy;
 
543
    slopes[1].dy = -pLeft->dx;
 
544
    slopes[1].k = 0;
 
545
 
 
546
    vertices[2].x = pLeft->xa;
 
547
    vertices[2].y = pLeft->ya;
 
548
 
 
549
    if (joinStyle == JoinMiter)
 
550
    {
 
551
        my = (pLeft->dy  * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) -
 
552
              pRight->dy * (pLeft->xa  * pLeft->dy  - pLeft->ya  * pLeft->dx )) /
 
553
              denom;
 
554
        if (pLeft->dy != 0)
 
555
        {
 
556
            mx = pLeft->xa + (my - pLeft->ya) *
 
557
                            (double) pLeft->dx / (double) pLeft->dy;
 
558
        }
 
559
        else
 
560
        {
 
561
            mx = pRight->xa + (my - pRight->ya) *
 
562
                            (double) pRight->dx / (double) pRight->dy;
 
563
        }
 
564
        /* check miter limit */
 
565
        if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw)
 
566
            joinStyle = JoinBevel;
 
567
    }
 
568
 
 
569
    if (joinStyle == JoinMiter)
 
570
    {
 
571
        slopes[2].dx = pLeft->dx;
 
572
        slopes[2].dy = pLeft->dy;
 
573
        slopes[2].k =  pLeft->k;
 
574
        if (swapslopes)
 
575
        {
 
576
            slopes[2].dx = -slopes[2].dx;
 
577
            slopes[2].dy = -slopes[2].dy;
 
578
            slopes[2].k  = -slopes[2].k;
 
579
        }
 
580
        vertices[3].x = mx;
 
581
        vertices[3].y = my;
 
582
        slopes[3].dx = pRight->dx;
 
583
        slopes[3].dy = pRight->dy;
 
584
        slopes[3].k  = pRight->k;
 
585
        if (swapslopes)
 
586
        {
 
587
            slopes[3].dx = -slopes[3].dx;
 
588
            slopes[3].dy = -slopes[3].dy;
 
589
            slopes[3].k  = -slopes[3].k;
 
590
        }
 
591
        edgecount = 4;
 
592
    }
 
593
    else
 
594
    {
 
595
        double  scale, dx, dy, adx, ady;
 
596
 
 
597
        adx = dx = pRight->xa - pLeft->xa;
 
598
        ady = dy = pRight->ya - pLeft->ya;
 
599
        if (adx < 0)
 
600
            adx = -adx;
 
601
        if (ady < 0)
 
602
            ady = -ady;
 
603
        scale = ady;
 
604
        if (adx > ady)
 
605
            scale = adx;
 
606
        slopes[2].dx = (dx * 65536) / scale;
 
607
        slopes[2].dy = (dy * 65536) / scale;
 
608
        slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy -
 
609
                       (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0;
 
610
        edgecount = 3;
 
611
    }
 
612
 
 
613
    y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y,
 
614
                   left, right, &nleft, &nright, &height);
 
615
    miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, height, left, right, nleft, nright);
 
616
}
 
617
 
 
618
static int
 
619
miLineArcI (
 
620
    DrawablePtr     pDraw,
 
621
    GCPtr           pGC,
 
622
    int             xorg,
 
623
    int             yorg,
 
624
    DDXPointPtr     points,
 
625
    int             *widths)
 
626
{
 
627
    register DDXPointPtr tpts, bpts;
 
628
    register int *twids, *bwids;
 
629
    register int x, y, e, ex, slw;
 
630
 
 
631
    tpts = points;
 
632
    twids = widths;
 
633
    if (pGC->miTranslate)
 
634
    {
 
635
        xorg += pDraw->x;
 
636
        yorg += pDraw->y;
 
637
    }
 
638
    slw = pGC->lineWidth;
 
639
    if (slw == 1)
 
640
    {
 
641
        tpts->x = xorg;
 
642
        tpts->y = yorg;
 
643
        *twids = 1;
 
644
        return 1;
 
645
    }
 
646
    bpts = tpts + slw;
 
647
    bwids = twids + slw;
 
648
    y = (slw >> 1) + 1;
 
649
    if (slw & 1)
 
650
        e = - ((y << 2) + 3);
 
651
    else
 
652
        e = - (y << 3);
 
653
    ex = -4;
 
654
    x = 0;
 
655
    while (y)
 
656
    {
 
657
        e += (y << 3) - 4;
 
658
        while (e >= 0)
 
659
        {
 
660
            x++;
 
661
            e += (ex = -((x << 3) + 4));
 
662
        }
 
663
        y--;
 
664
        slw = (x << 1) + 1;
 
665
        if ((e == ex) && (slw > 1))
 
666
            slw--;
 
667
        tpts->x = xorg - x;
 
668
        tpts->y = yorg - y;
 
669
        tpts++;
 
670
        *twids++ = slw;
 
671
        if ((y != 0) && ((slw > 1) || (e != ex)))
 
672
        {
 
673
            bpts--;
 
674
            bpts->x = xorg - x;
 
675
            bpts->y = yorg + y;
 
676
            *--bwids = slw;
 
677
        }
 
678
    }
 
679
    return (pGC->lineWidth);
 
680
}
 
681
 
 
682
#define CLIPSTEPEDGE(edgey,edge,edgeleft) \
 
683
    if (ybase == edgey) \
 
684
    { \
 
685
        if (edgeleft) \
 
686
        { \
 
687
            if (edge->x > xcl) \
 
688
                xcl = edge->x; \
 
689
        } \
 
690
        else \
 
691
        { \
 
692
            if (edge->x < xcr) \
 
693
                xcr = edge->x; \
 
694
        } \
 
695
        edgey++; \
 
696
        edge->x += edge->stepx; \
 
697
        edge->e += edge->dx; \
 
698
        if (edge->e > 0) \
 
699
        { \
 
700
            edge->x += edge->signdx; \
 
701
            edge->e -= edge->dy; \
 
702
        } \
 
703
    }
 
704
 
 
705
static int
 
706
miLineArcD (
 
707
    DrawablePtr     pDraw,
 
708
    GCPtr           pGC,
 
709
    double          xorg,
 
710
    double          yorg,
 
711
    DDXPointPtr     points,
 
712
    int             *widths,
 
713
    PolyEdgePtr     edge1,
 
714
    int             edgey1,
 
715
    Bool            edgeleft1,
 
716
    PolyEdgePtr     edge2,
 
717
    int             edgey2,
 
718
    Bool            edgeleft2)
 
719
{
 
720
    register DDXPointPtr pts;
 
721
    register int *wids;
 
722
    double radius, x0, y0, el, er, yk, xlk, xrk, k;
 
723
    int xbase, ybase, y, boty, xl, xr, xcl, xcr;
 
724
    int ymin, ymax;
 
725
    Bool edge1IsMin, edge2IsMin;
 
726
    int ymin1, ymin2;
 
727
 
 
728
    pts = points;
 
729
    wids = widths;
 
730
    xbase = floor(xorg);
 
731
    x0 = xorg - xbase;
 
732
    ybase = ICEIL (yorg);
 
733
    y0 = yorg - ybase;
 
734
    if (pGC->miTranslate)
 
735
    {
 
736
        xbase += pDraw->x;
 
737
        ybase += pDraw->y;
 
738
        edge1->x += pDraw->x;
 
739
        edge2->x += pDraw->x;
 
740
        edgey1 += pDraw->y;
 
741
        edgey2 += pDraw->y;
 
742
    }
 
743
    xlk = x0 + x0 + 1.0;
 
744
    xrk = x0 + x0 - 1.0;
 
745
    yk = y0 + y0 - 1.0;
 
746
    radius = ((double)pGC->lineWidth) / 2.0;
 
747
    y = floor(radius - y0 + 1.0);
 
748
    ybase -= y;
 
749
    ymin = ybase;
 
750
    ymax = 65536;
 
751
    edge1IsMin = FALSE;
 
752
    ymin1 = edgey1;
 
753
    if (edge1->dy >= 0)
 
754
    {
 
755
        if (!edge1->dy)
 
756
        {
 
757
            if (edgeleft1)
 
758
                edge1IsMin = TRUE;
 
759
            else
 
760
                ymax = edgey1;
 
761
            edgey1 = 65536;
 
762
        }
 
763
        else
 
764
        {
 
765
            if ((edge1->signdx < 0) == edgeleft1)
 
766
                edge1IsMin = TRUE;
 
767
        }
 
768
    }
 
769
    edge2IsMin = FALSE;
 
770
    ymin2 = edgey2;
 
771
    if (edge2->dy >= 0)
 
772
    {
 
773
        if (!edge2->dy)
 
774
        {
 
775
            if (edgeleft2)
 
776
                edge2IsMin = TRUE;
 
777
            else
 
778
                ymax = edgey2;
 
779
            edgey2 = 65536;
 
780
        }
 
781
        else
 
782
        {
 
783
            if ((edge2->signdx < 0) == edgeleft2)
 
784
                edge2IsMin = TRUE;
 
785
        }
 
786
    }
 
787
    if (edge1IsMin)
 
788
    {
 
789
        ymin = ymin1;
 
790
        if (edge2IsMin && ymin1 > ymin2)
 
791
            ymin = ymin2;
 
792
    } else if (edge2IsMin)
 
793
        ymin = ymin2;
 
794
    el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0);
 
795
    er = el + xrk;
 
796
    xl = 1;
 
797
    xr = 0;
 
798
    if (x0 < 0.5)
 
799
    {
 
800
        xl = 0;
 
801
        el -= xlk;
 
802
    }
 
803
    boty = (y0 < -0.5) ? 1 : 0;
 
804
    if (ybase + y - boty > ymax)
 
805
        boty = ymax - ybase - y;
 
806
    while (y > boty)
 
807
    {
 
808
        k = (y << 1) + yk;
 
809
        er += k;
 
810
        while (er > 0.0)
 
811
        {
 
812
            xr++;
 
813
            er += xrk - (xr << 1);
 
814
        }
 
815
        el += k;
 
816
        while (el >= 0.0)
 
817
        {
 
818
            xl--;
 
819
            el += (xl << 1) - xlk;
 
820
        }
 
821
        y--;
 
822
        ybase++;
 
823
        if (ybase < ymin)
 
824
            continue;
 
825
        xcl = xl + xbase;
 
826
        xcr = xr + xbase;
 
827
        CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
 
828
        CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
 
829
        if (xcr >= xcl)
 
830
        {
 
831
            pts->x = xcl;
 
832
            pts->y = ybase;
 
833
            pts++;
 
834
            *wids++ = xcr - xcl + 1;
 
835
        }
 
836
    }
 
837
    er = xrk - (xr << 1) - er;
 
838
    el = (xl << 1) - xlk - el;
 
839
    boty = floor(-y0 - radius + 1.0);
 
840
    if (ybase + y - boty > ymax)
 
841
        boty = ymax - ybase - y;
 
842
    while (y > boty)
 
843
    {
 
844
        k = (y << 1) + yk;
 
845
        er -= k;
 
846
        while ((er >= 0.0) && (xr >= 0))
 
847
        {
 
848
            xr--;
 
849
            er += xrk - (xr << 1);
 
850
        }
 
851
        el -= k;
 
852
        while ((el > 0.0) && (xl <= 0))
 
853
        {
 
854
            xl++;
 
855
            el += (xl << 1) - xlk;
 
856
        }
 
857
        y--;
 
858
        ybase++;
 
859
        if (ybase < ymin)
 
860
            continue;
 
861
        xcl = xl + xbase;
 
862
        xcr = xr + xbase;
 
863
        CLIPSTEPEDGE(edgey1, edge1, edgeleft1);
 
864
        CLIPSTEPEDGE(edgey2, edge2, edgeleft2);
 
865
        if (xcr >= xcl)
 
866
        {
 
867
            pts->x = xcl;
 
868
            pts->y = ybase;
 
869
            pts++;
 
870
            *wids++ = xcr - xcl + 1;
 
871
        }
 
872
    }
 
873
    return (pts - points);
 
874
}
 
875
 
 
876
int
 
877
miRoundJoinFace (face, edge, leftEdge)
 
878
    register LineFacePtr face;
 
879
    register PolyEdgePtr edge;
 
880
    Bool        *leftEdge;
 
881
{
 
882
    int     y;
 
883
    int     dx, dy;
 
884
    double  xa, ya;
 
885
    Bool        left;
 
886
 
 
887
    dx = -face->dy;
 
888
    dy = face->dx;
 
889
    xa = face->xa;
 
890
    ya = face->ya;
 
891
    left = 1;
 
892
    if (ya > 0)
 
893
    {
 
894
        ya = 0.0;
 
895
        xa = 0.0;
 
896
    }
 
897
    if (dy < 0 || (dy == 0 && dx > 0))
 
898
    {
 
899
        dx = -dx;
 
900
        dy = -dy;
 
901
        left = !left;
 
902
    }
 
903
    if (dx == 0 && dy == 0)
 
904
        dy = 1;
 
905
    if (dy == 0)
 
906
    {
 
907
        y = ICEIL (face->ya) + face->y;
 
908
        edge->x = -32767;
 
909
        edge->stepx = 0;
 
910
        edge->signdx = 0;
 
911
        edge->e = -1;
 
912
        edge->dy = 0;
 
913
        edge->dx = 0;
 
914
        edge->height = 0;
 
915
    }
 
916
    else
 
917
    {
 
918
        y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge);
 
919
        edge->height = 32767;
 
920
    }
 
921
    *leftEdge = !left;
 
922
    return y;
 
923
}
 
924
 
 
925
void
 
926
miRoundJoinClip (pLeft, pRight, edge1, edge2, y1, y2, left1, left2)
 
927
    register LineFacePtr pLeft, pRight;
 
928
    PolyEdgePtr edge1, edge2;
 
929
    int         *y1, *y2;
 
930
    Bool        *left1, *left2;
 
931
{
 
932
    double      denom;
 
933
 
 
934
    denom = - pLeft->dx * (double)pRight->dy + pRight->dx * (double)pLeft->dy;
 
935
 
 
936
    if (denom >= 0)
 
937
    {
 
938
        pLeft->xa = -pLeft->xa;
 
939
        pLeft->ya = -pLeft->ya;
 
940
    }
 
941
    else
 
942
    {
 
943
        pRight->xa = -pRight->xa;
 
944
        pRight->ya = -pRight->ya;
 
945
    }
 
946
    *y1 = miRoundJoinFace (pLeft, edge1, left1);
 
947
    *y2 = miRoundJoinFace (pRight, edge2, left2);
 
948
}
 
949
 
 
950
int
 
951
miRoundCapClip (face, isInt, edge, leftEdge)
 
952
    register LineFacePtr face;
 
953
    Bool        isInt;
 
954
    register PolyEdgePtr edge;
 
955
    Bool        *leftEdge;
 
956
{
 
957
    int     y;
 
958
    register int dx, dy;
 
959
    double  xa, ya, k;
 
960
    Bool        left;
 
961
 
 
962
    dx = -face->dy;
 
963
    dy = face->dx;
 
964
    xa = face->xa;
 
965
    ya = face->ya;
 
966
    k = 0.0;
 
967
    if (!isInt)
 
968
        k = face->k;
 
969
    left = 1;
 
970
    if (dy < 0 || (dy == 0 && dx > 0))
 
971
    {
 
972
        dx = -dx;
 
973
        dy = -dy;
 
974
        xa = -xa;
 
975
        ya = -ya;
 
976
        left = !left;
 
977
    }
 
978
    if (dx == 0 && dy == 0)
 
979
        dy = 1;
 
980
    if (dy == 0)
 
981
    {
 
982
        y = ICEIL (face->ya) + face->y;
 
983
        edge->x = -32767;
 
984
        edge->stepx = 0;
 
985
        edge->signdx = 0;
 
986
        edge->e = -1;
 
987
        edge->dy = 0;
 
988
        edge->dx = 0;
 
989
        edge->height = 0;
 
990
    }
 
991
    else
 
992
    {
 
993
        y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge);
 
994
        edge->height = 32767;
 
995
    }
 
996
    *leftEdge = !left;
 
997
    return y;
 
998
}
 
999
 
 
1000
static void
 
1001
miLineArc (
 
1002
    DrawablePtr     pDraw,
 
1003
    register GCPtr  pGC,
 
1004
    unsigned long   pixel,
 
1005
    SpanDataPtr     spanData,
 
1006
    register LineFacePtr leftFace,
 
1007
    register LineFacePtr rightFace,
 
1008
    double          xorg,
 
1009
    double          yorg,
 
1010
    Bool            isInt)
 
1011
{
 
1012
    DDXPointPtr points;
 
1013
    int *widths;
 
1014
    int xorgi = 0, yorgi = 0;
 
1015
    XID         oldPixel;
 
1016
    Spans spanRec;
 
1017
    int n;
 
1018
    PolyEdgeRec edge1, edge2;
 
1019
    int         edgey1, edgey2;
 
1020
    Bool        edgeleft1, edgeleft2;
 
1021
 
 
1022
    if (isInt)
 
1023
    {
 
1024
        xorgi = leftFace ? leftFace->x : rightFace->x;
 
1025
        yorgi = leftFace ? leftFace->y : rightFace->y;
 
1026
    }
 
1027
    edgey1 = 65536;
 
1028
    edgey2 = 65536;
 
1029
    edge1.x = 0; /* not used, keep memory checkers happy */
 
1030
    edge1.dy = -1;
 
1031
    edge2.x = 0; /* not used, keep memory checkers happy */
 
1032
    edge2.dy = -1;
 
1033
    edgeleft1 = FALSE;
 
1034
    edgeleft2 = FALSE;
 
1035
    if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) &&
 
1036
        ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) ||
 
1037
         (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt)))
 
1038
    {
 
1039
        if (isInt)
 
1040
        {
 
1041
            xorg = (double) xorgi;
 
1042
            yorg = (double) yorgi;
 
1043
        }
 
1044
        if (leftFace && rightFace)
 
1045
        {
 
1046
            miRoundJoinClip (leftFace, rightFace, &edge1, &edge2,
 
1047
                             &edgey1, &edgey2, &edgeleft1, &edgeleft2);
 
1048
        }
 
1049
        else if (leftFace)
 
1050
        {
 
1051
            edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1);
 
1052
        }
 
1053
        else if (rightFace)
 
1054
        {
 
1055
            edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2);
 
1056
        }
 
1057
        isInt = FALSE;
 
1058
    }
 
1059
    if (!spanData)
 
1060
    {
 
1061
        points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * pGC->lineWidth);
 
1062
        if (!points)
 
1063
            return;
 
1064
        widths = (int *)ALLOCATE_LOCAL(sizeof(int) * pGC->lineWidth);
 
1065
        if (!widths)
 
1066
        {
 
1067
            DEALLOCATE_LOCAL(points);
 
1068
            return;
 
1069
        }
 
1070
        oldPixel = pGC->fgPixel;
 
1071
        if (pixel != oldPixel)
 
1072
        {
 
1073
            DoChangeGC(pGC, GCForeground, (XID *)&pixel, FALSE);
 
1074
            ValidateGC (pDraw, pGC);
 
1075
        }
 
1076
    }
 
1077
    else
 
1078
    {
 
1079
        points = (DDXPointPtr) xalloc (pGC->lineWidth * sizeof (DDXPointRec));
 
1080
        if (!points)
 
1081
            return;
 
1082
        widths = (int *) xalloc (pGC->lineWidth * sizeof (int));
 
1083
        if (!widths)
 
1084
        {
 
1085
            xfree (points);
 
1086
            return;
 
1087
        }
 
1088
        spanRec.points = points;
 
1089
        spanRec.widths = widths;
 
1090
    }
 
1091
    if (isInt)
 
1092
        n = miLineArcI(pDraw, pGC, xorgi, yorgi, points, widths);
 
1093
    else
 
1094
        n = miLineArcD(pDraw, pGC, xorg, yorg, points, widths,
 
1095
                       &edge1, edgey1, edgeleft1,
 
1096
                       &edge2, edgey2, edgeleft2);
 
1097
 
 
1098
    if (!spanData)
 
1099
    {
 
1100
        (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, TRUE);
 
1101
        DEALLOCATE_LOCAL(widths);
 
1102
        DEALLOCATE_LOCAL(points);
 
1103
        if (pixel != oldPixel)
 
1104
        {
 
1105
            DoChangeGC(pGC, GCForeground, &oldPixel, FALSE);
 
1106
            ValidateGC (pDraw, pGC);
 
1107
        }
 
1108
    }
 
1109
    else
 
1110
    {
 
1111
        spanRec.count = n;
 
1112
        AppendSpanGroup (pGC, pixel, &spanRec, spanData)
 
1113
    }
 
1114
}
 
1115
 
 
1116
void
 
1117
miLineProjectingCap (pDrawable, pGC, pixel, spanData, face, isLeft, xorg, yorg, isInt)
 
1118
    DrawablePtr     pDrawable;
 
1119
    register GCPtr  pGC;
 
1120
    unsigned long   pixel;
 
1121
    SpanDataPtr     spanData;
 
1122
    register LineFacePtr face;
 
1123
    Bool            isLeft;
 
1124
    double          xorg, yorg;
 
1125
    Bool            isInt;
 
1126
{
 
1127
    int xorgi = 0, yorgi = 0;
 
1128
    int lw;
 
1129
    PolyEdgeRec lefts[2], rights[2];
 
1130
    int         lefty, righty, topy, bottomy;
 
1131
    PolyEdgePtr left, right;
 
1132
    PolyEdgePtr top, bottom;
 
1133
    double      xa,ya;
 
1134
    double      k;
 
1135
    double      xap, yap;
 
1136
    int         dx, dy;
 
1137
    double      projectXoff, projectYoff;
 
1138
    double      maxy;
 
1139
    int         finaly;
 
1140
    
 
1141
    if (isInt)
 
1142
    {
 
1143
        xorgi = face->x;
 
1144
        yorgi = face->y;
 
1145
    }
 
1146
    lw = pGC->lineWidth;
 
1147
    dx = face->dx;
 
1148
    dy = face->dy;
 
1149
    k = face->k;
 
1150
    if (dy == 0)
 
1151
    {
 
1152
        lefts[0].height = lw;
 
1153
        lefts[0].x = xorgi;
 
1154
        if (isLeft)
 
1155
            lefts[0].x -= (lw >> 1);
 
1156
        lefts[0].stepx = 0;
 
1157
        lefts[0].signdx = 1;
 
1158
        lefts[0].e = -lw;
 
1159
        lefts[0].dx = 0;
 
1160
        lefts[0].dy = lw;
 
1161
        rights[0].height = lw;
 
1162
        rights[0].x = xorgi;
 
1163
        if (!isLeft)
 
1164
            rights[0].x += ((lw + 1) >> 1);
 
1165
        rights[0].stepx = 0;
 
1166
        rights[0].signdx = 1;
 
1167
        rights[0].e = -lw;
 
1168
        rights[0].dx = 0;
 
1169
        rights[0].dy = lw;
 
1170
        miFillPolyHelper (pDrawable, pGC, pixel, spanData, yorgi - (lw >> 1), lw,
 
1171
                     lefts, rights, 1, 1);
 
1172
    }
 
1173
    else if (dx == 0)
 
1174
    {
 
1175
        if (dy < 0) {
 
1176
            dy = -dy;
 
1177
            isLeft = !isLeft;
 
1178
        }
 
1179
        topy = yorgi;
 
1180
        bottomy = yorgi + dy;
 
1181
        if (isLeft)
 
1182
            topy -= (lw >> 1);
 
1183
        else
 
1184
            bottomy += (lw >> 1);
 
1185
        lefts[0].height = bottomy - topy;
 
1186
        lefts[0].x = xorgi - (lw >> 1);
 
1187
        lefts[0].stepx = 0;
 
1188
        lefts[0].signdx = 1;
 
1189
        lefts[0].e = -dy;
 
1190
        lefts[0].dx = dx;
 
1191
        lefts[0].dy = dy;
 
1192
 
 
1193
        rights[0].height = bottomy - topy;
 
1194
        rights[0].x = lefts[0].x + (lw-1);
 
1195
        rights[0].stepx = 0;
 
1196
        rights[0].signdx = 1;
 
1197
        rights[0].e = -dy;
 
1198
        rights[0].dx = dx;
 
1199
        rights[0].dy = dy;
 
1200
        miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy, bottomy - topy, lefts, rights, 1, 1);
 
1201
    }
 
1202
    else
 
1203
    {
 
1204
        xa = face->xa;
 
1205
        ya = face->ya;
 
1206
        projectXoff = -ya;
 
1207
        projectYoff = xa;
 
1208
        if (dx < 0)
 
1209
        {
 
1210
            right = &rights[1];
 
1211
            left = &lefts[0];
 
1212
            top = &rights[0];
 
1213
            bottom = &lefts[1];
 
1214
        }
 
1215
        else
 
1216
        {
 
1217
            right = &rights[0];
 
1218
            left = &lefts[1];
 
1219
            top = &lefts[0];
 
1220
            bottom = &rights[1];
 
1221
        }
 
1222
        if (isLeft)
 
1223
        {
 
1224
            righty = miPolyBuildEdge (xa, ya,
 
1225
                     k, dx, dy, xorgi, yorgi, 0, right);
 
1226
            
 
1227
            xa = -xa;
 
1228
            ya = -ya;
 
1229
            k = -k;
 
1230
            lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
 
1231
                                     k, dx, dy, xorgi, yorgi, 1, left);
 
1232
            if (dx > 0)
 
1233
            {
 
1234
                ya = -ya;
 
1235
                xa = -xa;
 
1236
            }
 
1237
            xap = xa - projectXoff;
 
1238
            yap = ya - projectYoff;
 
1239
            topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
 
1240
                                    -dy, dx, xorgi, yorgi, dx > 0, top);
 
1241
            bottomy = miPolyBuildEdge (xa, ya,
 
1242
                                       0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom);
 
1243
            maxy = -ya;
 
1244
        }
 
1245
        else
 
1246
        {
 
1247
            righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
 
1248
                     k, dx, dy, xorgi, yorgi, 0, right);
 
1249
            
 
1250
            xa = -xa;
 
1251
            ya = -ya;
 
1252
            k = -k;
 
1253
            lefty = miPolyBuildEdge (xa, ya,
 
1254
                    k, dx, dy, xorgi, yorgi, 1, left);
 
1255
            if (dx > 0)
 
1256
            {
 
1257
                ya = -ya;
 
1258
                xa = -xa;
 
1259
            }
 
1260
            xap = xa - projectXoff;
 
1261
            yap = ya - projectYoff;
 
1262
            topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top);
 
1263
            bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
 
1264
                                       -dy, dx, xorgi, xorgi, dx < 0, bottom);
 
1265
            maxy = -ya + projectYoff;
 
1266
        }
 
1267
        finaly = ICEIL(maxy) + yorgi;
 
1268
        if (dx < 0)
 
1269
        {
 
1270
            left->height = bottomy - lefty;
 
1271
            right->height = finaly - righty;
 
1272
            top->height = righty - topy;
 
1273
        }
 
1274
        else
 
1275
        {
 
1276
            right->height =  bottomy - righty;
 
1277
            left->height = finaly - lefty;
 
1278
            top->height = lefty - topy;
 
1279
        }
 
1280
        bottom->height = finaly - bottomy;
 
1281
        miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
 
1282
                     bottom->height + bottomy - topy, lefts, rights, 2, 2);
 
1283
    }
 
1284
}
 
1285
 
 
1286
static void
 
1287
miWideSegment (
 
1288
    DrawablePtr     pDrawable,
 
1289
    GCPtr           pGC,
 
1290
    unsigned long   pixel,
 
1291
    SpanDataPtr     spanData,
 
1292
    register int    x1,
 
1293
    register int    y1,
 
1294
    register int    x2,
 
1295
    register int    y2,
 
1296
    Bool            projectLeft,
 
1297
    Bool            projectRight,
 
1298
    register LineFacePtr leftFace,
 
1299
    register LineFacePtr rightFace)
 
1300
{
 
1301
    double      l, L, r;
 
1302
    double      xa, ya;
 
1303
    double      projectXoff = 0.0, projectYoff = 0.0;
 
1304
    double      k;
 
1305
    double      maxy;
 
1306
    int         x, y;
 
1307
    int         dx, dy;
 
1308
    int         finaly;
 
1309
    PolyEdgePtr left, right;
 
1310
    PolyEdgePtr top, bottom;
 
1311
    int         lefty, righty, topy, bottomy;
 
1312
    int         signdx;
 
1313
    PolyEdgeRec lefts[2], rights[2];
 
1314
    LineFacePtr tface;
 
1315
    int         lw = pGC->lineWidth;
 
1316
 
 
1317
    /* draw top-to-bottom always */
 
1318
    if (y2 < y1 || (y2 == y1 && x2 < x1))
 
1319
    {
 
1320
        x = x1;
 
1321
        x1 = x2;
 
1322
        x2 = x;
 
1323
 
 
1324
        y = y1;
 
1325
        y1 = y2;
 
1326
        y2 = y;
 
1327
 
 
1328
        x = projectLeft;
 
1329
        projectLeft = projectRight;
 
1330
        projectRight = x;
 
1331
 
 
1332
        tface = leftFace;
 
1333
        leftFace = rightFace;
 
1334
        rightFace = tface;
 
1335
    }
 
1336
 
 
1337
    dy = y2 - y1;
 
1338
    signdx = 1;
 
1339
    dx = x2 - x1;
 
1340
    if (dx < 0)
 
1341
        signdx = -1;
 
1342
 
 
1343
    leftFace->x = x1;
 
1344
    leftFace->y = y1;
 
1345
    leftFace->dx = dx;
 
1346
    leftFace->dy = dy;
 
1347
 
 
1348
    rightFace->x = x2;
 
1349
    rightFace->y = y2;
 
1350
    rightFace->dx = -dx;
 
1351
    rightFace->dy = -dy;
 
1352
 
 
1353
    if (dy == 0)
 
1354
    {
 
1355
        rightFace->xa = 0;
 
1356
        rightFace->ya = (double) lw / 2.0;
 
1357
        rightFace->k = -(double) (lw * dx) / 2.0;
 
1358
        leftFace->xa = 0;
 
1359
        leftFace->ya = -rightFace->ya;
 
1360
        leftFace->k = rightFace->k;
 
1361
        x = x1;
 
1362
        if (projectLeft)
 
1363
            x -= (lw >> 1);
 
1364
        y = y1 - (lw >> 1);
 
1365
        dx = x2 - x;
 
1366
        if (projectRight)
 
1367
            dx += ((lw + 1) >> 1);
 
1368
        dy = lw;
 
1369
        miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
 
1370
                              x, y, dx, dy);
 
1371
    }
 
1372
    else if (dx == 0)
 
1373
    {
 
1374
        leftFace->xa =  (double) lw / 2.0;
 
1375
        leftFace->ya = 0;
 
1376
        leftFace->k = (double) (lw * dy) / 2.0;
 
1377
        rightFace->xa = -leftFace->xa;
 
1378
        rightFace->ya = 0;
 
1379
        rightFace->k = leftFace->k;
 
1380
        y = y1;
 
1381
        if (projectLeft)
 
1382
            y -= lw >> 1;
 
1383
        x = x1 - (lw >> 1);
 
1384
        dy = y2 - y;
 
1385
        if (projectRight)
 
1386
            dy += ((lw + 1) >> 1);
 
1387
        dx = lw;
 
1388
        miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
 
1389
                              x, y, dx, dy);
 
1390
    }
 
1391
    else
 
1392
    {
 
1393
        l = ((double) lw) / 2.0;
 
1394
        L = hypot ((double) dx, (double) dy);
 
1395
 
 
1396
        if (dx < 0)
 
1397
        {
 
1398
            right = &rights[1];
 
1399
            left = &lefts[0];
 
1400
            top = &rights[0];
 
1401
            bottom = &lefts[1];
 
1402
        }
 
1403
        else
 
1404
        {
 
1405
            right = &rights[0];
 
1406
            left = &lefts[1];
 
1407
            top = &lefts[0];
 
1408
            bottom = &rights[1];
 
1409
        }
 
1410
        r = l / L;
 
1411
 
 
1412
        /* coord of upper bound at integral y */
 
1413
        ya = -r * dx;
 
1414
        xa = r * dy;
 
1415
 
 
1416
        if (projectLeft | projectRight)
 
1417
        {
 
1418
            projectXoff = -ya;
 
1419
            projectYoff = xa;
 
1420
        }
 
1421
 
 
1422
        /* xa * dy - ya * dx */
 
1423
        k = l * L;
 
1424
 
 
1425
        leftFace->xa = xa;
 
1426
        leftFace->ya = ya;
 
1427
        leftFace->k = k;
 
1428
        rightFace->xa = -xa;
 
1429
        rightFace->ya = -ya;
 
1430
        rightFace->k = k;
 
1431
 
 
1432
        if (projectLeft)
 
1433
            righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
 
1434
                                      k, dx, dy, x1, y1, 0, right);
 
1435
        else
 
1436
            righty = miPolyBuildEdge (xa, ya,
 
1437
                                      k, dx, dy, x1, y1, 0, right);
 
1438
 
 
1439
        /* coord of lower bound at integral y */
 
1440
        ya = -ya;
 
1441
        xa = -xa;
 
1442
 
 
1443
        /* xa * dy - ya * dx */
 
1444
        k = - k;
 
1445
 
 
1446
        if (projectLeft)
 
1447
            lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff,
 
1448
                                     k, dx, dy, x1, y1, 1, left);
 
1449
        else
 
1450
            lefty = miPolyBuildEdge (xa, ya,
 
1451
                                     k, dx, dy, x1, y1, 1, left);
 
1452
 
 
1453
        /* coord of top face at integral y */
 
1454
 
 
1455
        if (signdx > 0)
 
1456
        {
 
1457
            ya = -ya;
 
1458
            xa = -xa;
 
1459
        }
 
1460
 
 
1461
        if (projectLeft)
 
1462
        {
 
1463
            double xap = xa - projectXoff;
 
1464
            double yap = ya - projectYoff;
 
1465
            topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
 
1466
                                    -dy, dx, x1, y1, dx > 0, top);
 
1467
        }
 
1468
        else
 
1469
            topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top);
 
1470
 
 
1471
        /* coord of bottom face at integral y */
 
1472
 
 
1473
        if (projectRight)
 
1474
        {
 
1475
            double xap = xa + projectXoff;
 
1476
            double yap = ya + projectYoff;
 
1477
            bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy,
 
1478
                                       -dy, dx, x2, y2, dx < 0, bottom);
 
1479
            maxy = -ya + projectYoff;
 
1480
        }
 
1481
        else
 
1482
        {
 
1483
            bottomy = miPolyBuildEdge (xa, ya,
 
1484
                                       0.0, -dy, dx, x2, y2, dx < 0, bottom);
 
1485
            maxy = -ya;
 
1486
        }
 
1487
 
 
1488
        finaly = ICEIL (maxy) + y2;
 
1489
 
 
1490
        if (dx < 0)
 
1491
        {
 
1492
            left->height = bottomy - lefty;
 
1493
            right->height = finaly - righty;
 
1494
            top->height = righty - topy;
 
1495
        }
 
1496
        else
 
1497
        {
 
1498
            right->height =  bottomy - righty;
 
1499
            left->height = finaly - lefty;
 
1500
            top->height = lefty - topy;
 
1501
        }
 
1502
        bottom->height = finaly - bottomy;
 
1503
        miFillPolyHelper (pDrawable, pGC, pixel, spanData, topy,
 
1504
                     bottom->height + bottomy - topy, lefts, rights, 2, 2);
 
1505
    }
 
1506
}
 
1507
 
 
1508
SpanDataPtr
 
1509
miSetupSpanData (pGC, spanData, npt)
 
1510
    register GCPtr pGC;
 
1511
    SpanDataPtr spanData;
 
1512
    int         npt;
 
1513
{
 
1514
    if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop(pGC->alu))
 
1515
        return (SpanDataPtr) NULL;
 
1516
    if (pGC->lineStyle == LineDoubleDash)
 
1517
        miInitSpanGroup (&spanData->bgGroup);
 
1518
    miInitSpanGroup (&spanData->fgGroup);
 
1519
    return spanData;
 
1520
}
 
1521
 
 
1522
void
 
1523
miCleanupSpanData (pDrawable, pGC, spanData)
 
1524
    DrawablePtr pDrawable;
 
1525
    GCPtr       pGC;
 
1526
    SpanDataPtr spanData;
 
1527
{
 
1528
    if (pGC->lineStyle == LineDoubleDash)
 
1529
    {
 
1530
        XID oldPixel, pixel;
 
1531
        
 
1532
        pixel = pGC->bgPixel;
 
1533
        oldPixel = pGC->fgPixel;
 
1534
        if (pixel != oldPixel)
 
1535
        {
 
1536
            DoChangeGC (pGC, GCForeground, &pixel, FALSE);
 
1537
            ValidateGC (pDrawable, pGC);
 
1538
        }
 
1539
        miFillUniqueSpanGroup (pDrawable, pGC, &spanData->bgGroup);
 
1540
        miFreeSpanGroup (&spanData->bgGroup);
 
1541
        if (pixel != oldPixel)
 
1542
        {
 
1543
            DoChangeGC (pGC, GCForeground, &oldPixel, FALSE);
 
1544
            ValidateGC (pDrawable, pGC);
 
1545
        }
 
1546
    }
 
1547
    miFillUniqueSpanGroup (pDrawable, pGC, &spanData->fgGroup);
 
1548
    miFreeSpanGroup (&spanData->fgGroup);
 
1549
}
 
1550
 
 
1551
void
 
1552
miWideLine (pDrawable, pGC, mode, npt, pPts)
 
1553
    DrawablePtr pDrawable;
 
1554
    register GCPtr pGC;
 
1555
    int         mode;
 
1556
    register int npt;
 
1557
    register DDXPointPtr pPts;
 
1558
{
 
1559
    int             x1, y1, x2, y2;
 
1560
    SpanDataRec     spanDataRec;
 
1561
    SpanDataPtr     spanData;
 
1562
    unsigned long   pixel;
 
1563
    Bool            projectLeft, projectRight;
 
1564
    LineFaceRec     leftFace, rightFace, prevRightFace;
 
1565
    LineFaceRec     firstFace;
 
1566
    register int    first;
 
1567
    Bool            somethingDrawn = FALSE;
 
1568
    Bool            selfJoin;
 
1569
 
 
1570
    spanData = miSetupSpanData (pGC, &spanDataRec, npt);
 
1571
    pixel = pGC->fgPixel;
 
1572
    x2 = pPts->x;
 
1573
    y2 = pPts->y;
 
1574
    first = TRUE;
 
1575
    selfJoin = FALSE;
 
1576
    if (npt > 1)
 
1577
    {
 
1578
        if (mode == CoordModePrevious)
 
1579
        {
 
1580
            int nptTmp;
 
1581
            DDXPointPtr pPtsTmp;
 
1582
    
 
1583
            x1 = x2;
 
1584
            y1 = y2;
 
1585
            nptTmp = npt;
 
1586
            pPtsTmp = pPts + 1;
 
1587
            while (--nptTmp)
 
1588
            {
 
1589
                x1 += pPtsTmp->x;
 
1590
                y1 += pPtsTmp->y;
 
1591
                ++pPtsTmp;
 
1592
            }
 
1593
            if (x2 == x1 && y2 == y1)
 
1594
                selfJoin = TRUE;
 
1595
        }
 
1596
        else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
 
1597
        {
 
1598
            selfJoin = TRUE;
 
1599
        }
 
1600
    }
 
1601
    projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
 
1602
    projectRight = FALSE;
 
1603
    while (--npt)
 
1604
    {
 
1605
        x1 = x2;
 
1606
        y1 = y2;
 
1607
        ++pPts;
 
1608
        x2 = pPts->x;
 
1609
        y2 = pPts->y;
 
1610
        if (mode == CoordModePrevious)
 
1611
        {
 
1612
            x2 += x1;
 
1613
            y2 += y1;
 
1614
        }
 
1615
        if (x1 != x2 || y1 != y2)
 
1616
        {
 
1617
            somethingDrawn = TRUE;
 
1618
            if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin)
 
1619
                projectRight = TRUE;
 
1620
            miWideSegment (pDrawable, pGC, pixel, spanData, x1, y1, x2, y2,
 
1621
                           projectLeft, projectRight, &leftFace, &rightFace);
 
1622
            if (first)
 
1623
            {
 
1624
                if (selfJoin)
 
1625
                    firstFace = leftFace;
 
1626
                else if (pGC->capStyle == CapRound)
 
1627
                {
 
1628
                    if (pGC->lineWidth == 1 && !spanData)
 
1629
                        miLineOnePoint (pDrawable, pGC, pixel, spanData, x1, y1);
 
1630
                    else
 
1631
                        miLineArc (pDrawable, pGC, pixel, spanData,
 
1632
                                   &leftFace, (LineFacePtr) NULL,
 
1633
                                   (double)0.0, (double)0.0,
 
1634
                                   TRUE);
 
1635
                }
 
1636
            }
 
1637
            else
 
1638
            {
 
1639
                miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
 
1640
                            &prevRightFace);
 
1641
            }
 
1642
            prevRightFace = rightFace;
 
1643
            first = FALSE;
 
1644
            projectLeft = FALSE;
 
1645
        }
 
1646
        if (npt == 1 && somethingDrawn)
 
1647
        {
 
1648
            if (selfJoin)
 
1649
                miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
 
1650
                            &rightFace);
 
1651
            else if (pGC->capStyle == CapRound)
 
1652
            {
 
1653
                if (pGC->lineWidth == 1 && !spanData)
 
1654
                    miLineOnePoint (pDrawable, pGC, pixel, spanData, x2, y2);
 
1655
                else
 
1656
                    miLineArc (pDrawable, pGC, pixel, spanData,
 
1657
                               (LineFacePtr) NULL, &rightFace,
 
1658
                               (double)0.0, (double)0.0,
 
1659
                               TRUE);
 
1660
            }
 
1661
        }
 
1662
    }
 
1663
    /* handle crock where all points are coincedent */
 
1664
    if (!somethingDrawn)
 
1665
    {
 
1666
        projectLeft = pGC->capStyle == CapProjecting;
 
1667
        miWideSegment (pDrawable, pGC, pixel, spanData,
 
1668
                       x2, y2, x2, y2, projectLeft, projectLeft,
 
1669
                       &leftFace, &rightFace);
 
1670
        if (pGC->capStyle == CapRound)
 
1671
        {
 
1672
            miLineArc (pDrawable, pGC, pixel, spanData,
 
1673
                       &leftFace, (LineFacePtr) NULL,
 
1674
                       (double)0.0, (double)0.0,
 
1675
                       TRUE);
 
1676
            rightFace.dx = -1;  /* sleezy hack to make it work */
 
1677
            miLineArc (pDrawable, pGC, pixel, spanData,
 
1678
                       (LineFacePtr) NULL, &rightFace,
 
1679
                       (double)0.0, (double)0.0,
 
1680
                       TRUE);
 
1681
        }
 
1682
    }
 
1683
    if (spanData)
 
1684
        miCleanupSpanData (pDrawable, pGC, spanData);
 
1685
}
 
1686
 
 
1687
#define V_TOP       0
 
1688
#define V_RIGHT     1
 
1689
#define V_BOTTOM    2
 
1690
#define V_LEFT      3
 
1691
 
 
1692
static void
 
1693
miWideDashSegment (
 
1694
    DrawablePtr     pDrawable,
 
1695
    register GCPtr  pGC,
 
1696
    SpanDataPtr     spanData,
 
1697
    int             *pDashOffset,
 
1698
    int             *pDashIndex,
 
1699
    int             x1,
 
1700
    int             y1,
 
1701
    int             x2,
 
1702
    int             y2,
 
1703
    Bool            projectLeft,
 
1704
    Bool            projectRight,
 
1705
    LineFacePtr     leftFace,
 
1706
    LineFacePtr     rightFace)
 
1707
{
 
1708
    int             dashIndex, dashRemain;
 
1709
    unsigned char   *pDash;
 
1710
    double          L, l;
 
1711
    double          k;
 
1712
    PolyVertexRec   vertices[4];
 
1713
    PolyVertexRec   saveRight, saveBottom;
 
1714
    PolySlopeRec    slopes[4];
 
1715
    PolyEdgeRec     left[2], right[2];
 
1716
    LineFaceRec     lcapFace, rcapFace;
 
1717
    int             nleft, nright;
 
1718
    int             h;
 
1719
    int             y;
 
1720
    int             dy, dx;
 
1721
    unsigned long   pixel;
 
1722
    double          LRemain;
 
1723
    double          r;
 
1724
    double          rdx, rdy;
 
1725
    double          dashDx, dashDy;
 
1726
    double          saveK = 0.0;
 
1727
    Bool            first = TRUE;
 
1728
    double          lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0;
 
1729
    unsigned long   fgPixel, bgPixel;
 
1730
    
 
1731
    dx = x2 - x1;
 
1732
    dy = y2 - y1;
 
1733
    dashIndex = *pDashIndex;
 
1734
    pDash = pGC->dash;
 
1735
    dashRemain = pDash[dashIndex] - *pDashOffset;
 
1736
    fgPixel = pGC->fgPixel;
 
1737
    bgPixel = pGC->bgPixel;
 
1738
    if (pGC->fillStyle == FillOpaqueStippled ||
 
1739
        pGC->fillStyle == FillTiled)
 
1740
    {
 
1741
        bgPixel = fgPixel;
 
1742
    }
 
1743
 
 
1744
    l = ((double) pGC->lineWidth) / 2.0;
 
1745
    if (dx == 0)
 
1746
    {
 
1747
        L = dy;
 
1748
        rdx = 0;
 
1749
        rdy = l;
 
1750
        if (dy < 0)
 
1751
        {
 
1752
            L = -dy;
 
1753
            rdy = -l;
 
1754
        }
 
1755
    }
 
1756
    else if (dy == 0)
 
1757
    {
 
1758
        L = dx;
 
1759
        rdx = l;
 
1760
        rdy = 0;
 
1761
        if (dx < 0)
 
1762
        {
 
1763
            L = -dx;
 
1764
            rdx = -l;
 
1765
        }
 
1766
    }
 
1767
    else
 
1768
    {
 
1769
        L = hypot ((double) dx, (double) dy);
 
1770
        r = l / L;
 
1771
 
 
1772
        rdx = r * dx;
 
1773
        rdy = r * dy;
 
1774
    }
 
1775
    k = l * L;
 
1776
    LRemain = L;
 
1777
    /* All position comments are relative to a line with dx and dy > 0,
 
1778
     * but the code does not depend on this */
 
1779
    /* top */
 
1780
    slopes[V_TOP].dx = dx;
 
1781
    slopes[V_TOP].dy = dy;
 
1782
    slopes[V_TOP].k = k;
 
1783
    /* right */
 
1784
    slopes[V_RIGHT].dx = -dy;
 
1785
    slopes[V_RIGHT].dy = dx;
 
1786
    slopes[V_RIGHT].k = 0;
 
1787
    /* bottom */
 
1788
    slopes[V_BOTTOM].dx = -dx;
 
1789
    slopes[V_BOTTOM].dy = -dy;
 
1790
    slopes[V_BOTTOM].k = k;
 
1791
    /* left */
 
1792
    slopes[V_LEFT].dx = dy;
 
1793
    slopes[V_LEFT].dy = -dx;
 
1794
    slopes[V_LEFT].k = 0;
 
1795
 
 
1796
    /* preload the start coordinates */
 
1797
    vertices[V_RIGHT].x = vertices[V_TOP].x = rdy;
 
1798
    vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx;
 
1799
 
 
1800
    vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy;
 
1801
    vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx;
 
1802
 
 
1803
    if (projectLeft)
 
1804
    {
 
1805
        vertices[V_TOP].x -= rdx;
 
1806
        vertices[V_TOP].y -= rdy;
 
1807
 
 
1808
        vertices[V_LEFT].x -= rdx;
 
1809
        vertices[V_LEFT].y -= rdy;
 
1810
 
 
1811
        slopes[V_LEFT].k = rdx * dx + rdy * dy;
 
1812
    }
 
1813
 
 
1814
    lcenterx = x1;
 
1815
    lcentery = y1;
 
1816
 
 
1817
    if (pGC->capStyle == CapRound)
 
1818
    {
 
1819
        lcapFace.dx = dx;
 
1820
        lcapFace.dy = dy;
 
1821
        lcapFace.x = x1;
 
1822
        lcapFace.y = y1;
 
1823
 
 
1824
        rcapFace.dx = -dx;
 
1825
        rcapFace.dy = -dy;
 
1826
        rcapFace.x = x1;
 
1827
        rcapFace.y = y1;
 
1828
    }
 
1829
    while (LRemain > dashRemain)
 
1830
    {
 
1831
        dashDx = (dashRemain * dx) / L;
 
1832
        dashDy = (dashRemain * dy) / L;
 
1833
 
 
1834
        rcenterx = lcenterx + dashDx;
 
1835
        rcentery = lcentery + dashDy;
 
1836
 
 
1837
        vertices[V_RIGHT].x += dashDx;
 
1838
        vertices[V_RIGHT].y += dashDy;
 
1839
 
 
1840
        vertices[V_BOTTOM].x += dashDx;
 
1841
        vertices[V_BOTTOM].y += dashDy;
 
1842
 
 
1843
        slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy;
 
1844
 
 
1845
        if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
 
1846
        {
 
1847
            if (pGC->lineStyle == LineOnOffDash &&
 
1848
                pGC->capStyle == CapProjecting)
 
1849
            {
 
1850
                saveRight = vertices[V_RIGHT];
 
1851
                saveBottom = vertices[V_BOTTOM];
 
1852
                saveK = slopes[V_RIGHT].k;
 
1853
                
 
1854
                if (!first)
 
1855
                {
 
1856
                    vertices[V_TOP].x -= rdx;
 
1857
                    vertices[V_TOP].y -= rdy;
 
1858
    
 
1859
                    vertices[V_LEFT].x -= rdx;
 
1860
                    vertices[V_LEFT].y -= rdy;
 
1861
 
 
1862
                    slopes[V_LEFT].k = vertices[V_LEFT].x *
 
1863
                                       slopes[V_LEFT].dy -
 
1864
                                       vertices[V_LEFT].y *
 
1865
                                       slopes[V_LEFT].dx;
 
1866
                }
 
1867
                
 
1868
                vertices[V_RIGHT].x += rdx;
 
1869
                vertices[V_RIGHT].y += rdy;
 
1870
 
 
1871
                vertices[V_BOTTOM].x += rdx;
 
1872
                vertices[V_BOTTOM].y += rdy;
 
1873
 
 
1874
                slopes[V_RIGHT].k = vertices[V_RIGHT].x *
 
1875
                                   slopes[V_RIGHT].dy -
 
1876
                                   vertices[V_RIGHT].y *
 
1877
                                   slopes[V_RIGHT].dx;
 
1878
            }
 
1879
            y = miPolyBuildPoly (vertices, slopes, 4, x1, y1,
 
1880
                                 left, right, &nleft, &nright, &h);
 
1881
            pixel = (dashIndex & 1) ? bgPixel : fgPixel;
 
1882
            miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
 
1883
 
 
1884
            if (pGC->lineStyle == LineOnOffDash)
 
1885
            {
 
1886
                switch (pGC->capStyle)
 
1887
                {
 
1888
                case CapProjecting:
 
1889
                    vertices[V_BOTTOM] = saveBottom;
 
1890
                    vertices[V_RIGHT] = saveRight;
 
1891
                    slopes[V_RIGHT].k = saveK;
 
1892
                    break;
 
1893
                case CapRound:
 
1894
                    if (!first)
 
1895
                    {
 
1896
                        if (dx < 0)
 
1897
                        {
 
1898
                            lcapFace.xa = -vertices[V_LEFT].x;
 
1899
                            lcapFace.ya = -vertices[V_LEFT].y;
 
1900
                            lcapFace.k = slopes[V_LEFT].k;
 
1901
                        }
 
1902
                        else
 
1903
                        {
 
1904
                            lcapFace.xa = vertices[V_TOP].x;
 
1905
                            lcapFace.ya = vertices[V_TOP].y;
 
1906
                            lcapFace.k = -slopes[V_LEFT].k;
 
1907
                        }
 
1908
                        miLineArc (pDrawable, pGC, pixel, spanData,
 
1909
                                   &lcapFace, (LineFacePtr) NULL,
 
1910
                                   lcenterx, lcentery, FALSE);
 
1911
                    }
 
1912
                    if (dx < 0)
 
1913
                    {
 
1914
                        rcapFace.xa = vertices[V_BOTTOM].x;
 
1915
                        rcapFace.ya = vertices[V_BOTTOM].y;
 
1916
                        rcapFace.k = slopes[V_RIGHT].k;
 
1917
                    }
 
1918
                    else
 
1919
                    {
 
1920
                        rcapFace.xa = -vertices[V_RIGHT].x;
 
1921
                        rcapFace.ya = -vertices[V_RIGHT].y;
 
1922
                        rcapFace.k = -slopes[V_RIGHT].k;
 
1923
                    }
 
1924
                    miLineArc (pDrawable, pGC, pixel, spanData,
 
1925
                               (LineFacePtr) NULL, &rcapFace,
 
1926
                               rcenterx, rcentery, FALSE);
 
1927
                    break;
 
1928
                }
 
1929
            }
 
1930
        }
 
1931
        LRemain -= dashRemain;
 
1932
        ++dashIndex;
 
1933
        if (dashIndex == pGC->numInDashList)
 
1934
            dashIndex = 0;
 
1935
        dashRemain = pDash[dashIndex];
 
1936
 
 
1937
        lcenterx = rcenterx;
 
1938
        lcentery = rcentery;
 
1939
 
 
1940
        vertices[V_TOP] = vertices[V_RIGHT];
 
1941
        vertices[V_LEFT] = vertices[V_BOTTOM];
 
1942
        slopes[V_LEFT].k = -slopes[V_RIGHT].k;
 
1943
        first = FALSE;
 
1944
    }
 
1945
 
 
1946
    if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))
 
1947
    {
 
1948
        vertices[V_TOP].x -= dx;
 
1949
        vertices[V_TOP].y -= dy;
 
1950
 
 
1951
        vertices[V_LEFT].x -= dx;
 
1952
        vertices[V_LEFT].y -= dy;
 
1953
 
 
1954
        vertices[V_RIGHT].x = rdy;
 
1955
        vertices[V_RIGHT].y = -rdx;
 
1956
 
 
1957
        vertices[V_BOTTOM].x = -rdy;
 
1958
        vertices[V_BOTTOM].y = rdx;
 
1959
 
 
1960
        
 
1961
        if (projectRight)
 
1962
        {
 
1963
            vertices[V_RIGHT].x += rdx;
 
1964
            vertices[V_RIGHT].y += rdy;
 
1965
    
 
1966
            vertices[V_BOTTOM].x += rdx;
 
1967
            vertices[V_BOTTOM].y += rdy;
 
1968
            slopes[V_RIGHT].k = vertices[V_RIGHT].x *
 
1969
                                slopes[V_RIGHT].dy -
 
1970
                                vertices[V_RIGHT].y *
 
1971
                                slopes[V_RIGHT].dx;
 
1972
        }
 
1973
        else
 
1974
            slopes[V_RIGHT].k = 0;
 
1975
 
 
1976
        if (!first && pGC->lineStyle == LineOnOffDash &&
 
1977
            pGC->capStyle == CapProjecting)
 
1978
        {
 
1979
            vertices[V_TOP].x -= rdx;
 
1980
            vertices[V_TOP].y -= rdy;
 
1981
 
 
1982
            vertices[V_LEFT].x -= rdx;
 
1983
            vertices[V_LEFT].y -= rdy;
 
1984
            slopes[V_LEFT].k = vertices[V_LEFT].x *
 
1985
                               slopes[V_LEFT].dy -
 
1986
                               vertices[V_LEFT].y *
 
1987
                               slopes[V_LEFT].dx;
 
1988
        }
 
1989
        else
 
1990
            slopes[V_LEFT].k += dx * dx + dy * dy;
 
1991
 
 
1992
 
 
1993
        y = miPolyBuildPoly (vertices, slopes, 4, x2, y2,
 
1994
                             left, right, &nleft, &nright, &h);
 
1995
 
 
1996
        pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
 
1997
        miFillPolyHelper (pDrawable, pGC, pixel, spanData, y, h, left, right, nleft, nright);
 
1998
        if (!first && pGC->lineStyle == LineOnOffDash &&
 
1999
            pGC->capStyle == CapRound)
 
2000
        {
 
2001
            lcapFace.x = x2;
 
2002
            lcapFace.y = y2;
 
2003
            if (dx < 0)
 
2004
            {
 
2005
                lcapFace.xa = -vertices[V_LEFT].x;
 
2006
                lcapFace.ya = -vertices[V_LEFT].y;
 
2007
                lcapFace.k = slopes[V_LEFT].k;
 
2008
            }
 
2009
            else
 
2010
            {
 
2011
                lcapFace.xa = vertices[V_TOP].x;
 
2012
                lcapFace.ya = vertices[V_TOP].y;
 
2013
                lcapFace.k = -slopes[V_LEFT].k;
 
2014
            }
 
2015
            miLineArc (pDrawable, pGC, pixel, spanData,
 
2016
                       &lcapFace, (LineFacePtr) NULL,
 
2017
                       rcenterx, rcentery, FALSE);
 
2018
        }
 
2019
    }
 
2020
    dashRemain = ((double) dashRemain) - LRemain;
 
2021
    if (dashRemain == 0)
 
2022
    {
 
2023
        dashIndex++;
 
2024
        if (dashIndex == pGC->numInDashList)
 
2025
            dashIndex = 0;
 
2026
        dashRemain = pDash[dashIndex];
 
2027
    }
 
2028
 
 
2029
    leftFace->x = x1;
 
2030
    leftFace->y = y1;
 
2031
    leftFace->dx = dx;
 
2032
    leftFace->dy = dy;
 
2033
    leftFace->xa = rdy;
 
2034
    leftFace->ya = -rdx;
 
2035
    leftFace->k = k;
 
2036
 
 
2037
    rightFace->x = x2;
 
2038
    rightFace->y = y2;
 
2039
    rightFace->dx = -dx;
 
2040
    rightFace->dy = -dy;
 
2041
    rightFace->xa = -rdy;
 
2042
    rightFace->ya = rdx;
 
2043
    rightFace->k = k;
 
2044
 
 
2045
    *pDashIndex = dashIndex;
 
2046
    *pDashOffset = pDash[dashIndex] - dashRemain;
 
2047
}
 
2048
 
 
2049
void
 
2050
miWideDash (pDrawable, pGC, mode, npt, pPts)
 
2051
    DrawablePtr pDrawable;
 
2052
    register GCPtr pGC;
 
2053
    int         mode;
 
2054
    register int npt;
 
2055
    register DDXPointPtr pPts;
 
2056
{
 
2057
    int             x1, y1, x2, y2;
 
2058
    unsigned long   pixel;
 
2059
    Bool            projectLeft, projectRight;
 
2060
    LineFaceRec     leftFace, rightFace, prevRightFace;
 
2061
    LineFaceRec     firstFace;
 
2062
    int             first;
 
2063
    int             dashIndex, dashOffset;
 
2064
    register int    prevDashIndex;
 
2065
    SpanDataRec     spanDataRec;
 
2066
    SpanDataPtr     spanData;
 
2067
    Bool            somethingDrawn = FALSE;
 
2068
    Bool            selfJoin;
 
2069
    Bool            endIsFg = FALSE, startIsFg = FALSE;
 
2070
    Bool            firstIsFg = FALSE, prevIsFg = FALSE;
 
2071
 
 
2072
#ifndef XFree86Server
 
2073
    /* XXX backward compatibility */
 
2074
    if (pGC->lineWidth == 0)
 
2075
    {
 
2076
        miZeroDashLine (pDrawable, pGC, mode, npt, pPts);
 
2077
        return;
 
2078
    }
 
2079
#endif
 
2080
    if (pGC->lineStyle == LineDoubleDash && 
 
2081
        (pGC->fillStyle == FillOpaqueStippled || pGC->fillStyle == FillTiled))
 
2082
    {
 
2083
        miWideLine (pDrawable, pGC, mode, npt, pPts);
 
2084
        return;
 
2085
    }
 
2086
    if (npt == 0)
 
2087
        return;
 
2088
    spanData = miSetupSpanData (pGC, &spanDataRec, npt);
 
2089
    x2 = pPts->x;
 
2090
    y2 = pPts->y;
 
2091
    first = TRUE;
 
2092
    selfJoin = FALSE;
 
2093
    if (mode == CoordModePrevious)
 
2094
    {
 
2095
        int nptTmp;
 
2096
        DDXPointPtr pPtsTmp;
 
2097
 
 
2098
        x1 = x2;
 
2099
        y1 = y2;
 
2100
        nptTmp = npt;
 
2101
        pPtsTmp = pPts + 1;
 
2102
        while (--nptTmp)
 
2103
        {
 
2104
            x1 += pPtsTmp->x;
 
2105
            y1 += pPtsTmp->y;
 
2106
            ++pPtsTmp;
 
2107
        }
 
2108
        if (x2 == x1 && y2 == y1)
 
2109
            selfJoin = TRUE;
 
2110
    }
 
2111
    else if (x2 == pPts[npt-1].x && y2 == pPts[npt-1].y)
 
2112
    {
 
2113
        selfJoin = TRUE;
 
2114
    }
 
2115
    projectLeft = pGC->capStyle == CapProjecting && !selfJoin;
 
2116
    projectRight = FALSE;
 
2117
    dashIndex = 0;
 
2118
    dashOffset = 0;
 
2119
    miStepDash ((int)pGC->dashOffset, &dashIndex,
 
2120
                pGC->dash, (int)pGC->numInDashList, &dashOffset);
 
2121
    while (--npt)
 
2122
    {
 
2123
        x1 = x2;
 
2124
        y1 = y2;
 
2125
        ++pPts;
 
2126
        x2 = pPts->x;
 
2127
        y2 = pPts->y;
 
2128
        if (mode == CoordModePrevious)
 
2129
        {
 
2130
            x2 += x1;
 
2131
            y2 += y1;
 
2132
        }
 
2133
        if (x1 != x2 || y1 != y2)
 
2134
        {
 
2135
            somethingDrawn = TRUE;
 
2136
            if (npt == 1 && pGC->capStyle == CapProjecting && 
 
2137
                (!selfJoin || !firstIsFg))
 
2138
                projectRight = TRUE;
 
2139
            prevDashIndex = dashIndex;
 
2140
            miWideDashSegment (pDrawable, pGC, spanData, &dashOffset, &dashIndex,
 
2141
                                x1, y1, x2, y2,
 
2142
                                projectLeft, projectRight, &leftFace, &rightFace);
 
2143
            startIsFg = !(prevDashIndex & 1);
 
2144
            endIsFg = (dashIndex & 1) ^ (dashOffset != 0);
 
2145
            if (pGC->lineStyle == LineDoubleDash || startIsFg)
 
2146
            {
 
2147
                pixel = startIsFg ? pGC->fgPixel : pGC->bgPixel;
 
2148
                if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg))
 
2149
                {
 
2150
                    if (first && selfJoin)
 
2151
                    {
 
2152
                        firstFace = leftFace;
 
2153
                        firstIsFg = startIsFg;
 
2154
                    }
 
2155
                    else if (pGC->capStyle == CapRound)
 
2156
                        miLineArc (pDrawable, pGC, pixel, spanData,
 
2157
                                   &leftFace, (LineFacePtr) NULL,
 
2158
                                   (double)0.0, (double)0.0, TRUE);
 
2159
                }
 
2160
                else
 
2161
                {
 
2162
                    miLineJoin (pDrawable, pGC, pixel, spanData, &leftFace,
 
2163
                                &prevRightFace);
 
2164
                }
 
2165
            }
 
2166
            prevRightFace = rightFace;
 
2167
            prevIsFg = endIsFg;
 
2168
            first = FALSE;
 
2169
            projectLeft = FALSE;
 
2170
        }
 
2171
        if (npt == 1 && somethingDrawn)
 
2172
        {
 
2173
            if (pGC->lineStyle == LineDoubleDash || endIsFg)
 
2174
            {
 
2175
                pixel = endIsFg ? pGC->fgPixel : pGC->bgPixel;
 
2176
                if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg))
 
2177
                {
 
2178
                    miLineJoin (pDrawable, pGC, pixel, spanData, &firstFace,
 
2179
                                &rightFace);
 
2180
                }
 
2181
                else 
 
2182
                {
 
2183
                    if (pGC->capStyle == CapRound)
 
2184
                        miLineArc (pDrawable, pGC, pixel, spanData,
 
2185
                                    (LineFacePtr) NULL, &rightFace,
 
2186
                                    (double)0.0, (double)0.0, TRUE);
 
2187
                }
 
2188
            }
 
2189
            else
 
2190
            {
 
2191
                /* glue a cap to the start of the line if
 
2192
                 * we're OnOffDash and ended on odd dash
 
2193
                 */
 
2194
                if (selfJoin && firstIsFg)
 
2195
                {
 
2196
                    pixel = pGC->fgPixel;
 
2197
                    if (pGC->capStyle == CapProjecting)
 
2198
                        miLineProjectingCap (pDrawable, pGC, pixel, spanData,
 
2199
                                    &firstFace, TRUE,
 
2200
                                    (double)0.0, (double)0.0, TRUE);
 
2201
                    else if (pGC->capStyle == CapRound)
 
2202
                        miLineArc (pDrawable, pGC, pixel, spanData,
 
2203
                                    &firstFace, (LineFacePtr) NULL,
 
2204
                                    (double)0.0, (double)0.0, TRUE);
 
2205
                }
 
2206
            }
 
2207
        }
 
2208
    }
 
2209
    /* handle crock where all points are coincident */
 
2210
    if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)))
 
2211
    {
 
2212
        /* not the same as endIsFg computation above */
 
2213
        pixel = (dashIndex & 1) ? pGC->bgPixel : pGC->fgPixel;
 
2214
        switch (pGC->capStyle) {
 
2215
        case CapRound:
 
2216
            miLineArc (pDrawable, pGC, pixel, spanData,
 
2217
                       (LineFacePtr) NULL, (LineFacePtr) NULL,
 
2218
                       (double)x2, (double)y2,
 
2219
                       FALSE);
 
2220
            break;
 
2221
        case CapProjecting:
 
2222
            x1 = pGC->lineWidth;
 
2223
            miFillRectPolyHelper (pDrawable, pGC, pixel, spanData,
 
2224
                                  x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1);
 
2225
            break;
 
2226
        }
 
2227
    }
 
2228
    if (spanData)
 
2229
        miCleanupSpanData (pDrawable, pGC, spanData);
 
2230
}
 
2231
 
 
2232
/* these are stubs to allow old ddx ValidateGCs to work without change */
 
2233
 
 
2234
void
 
2235
miMiter()
 
2236
{
 
2237
}
 
2238
 
 
2239
void
 
2240
miNotMiter()
 
2241
{
 
2242
}