~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gdk/linux-fb/miwideline.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

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