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

« back to all changes in this revision

Viewing changes to mi/mifillarc.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
/* $XFree86: xc/programs/Xserver/mi/mifillarc.c,v 3.7 2001/12/14 20:00:22 dawes Exp $ */
 
2
/************************************************************
 
3
 
 
4
Copyright 1989, 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 in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of The Open Group shall not be
 
23
used in advertising or otherwise to promote the sale, use or other dealings
 
24
in this Software without prior written authorization from The Open Group.
 
25
 
 
26
Author:  Bob Scheifler, MIT X Consortium
 
27
 
 
28
********************************************************/
 
29
 
 
30
/* $Xorg: mifillarc.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */
 
31
 
 
32
#ifdef HAVE_DIX_CONFIG_H
 
33
#include <dix-config.h>
 
34
#endif
 
35
 
 
36
#include <math.h>
 
37
#include <X11/X.h>
 
38
#include <X11/Xprotostr.h>
 
39
#include "regionstr.h"
 
40
#include "gcstruct.h"
 
41
#include "pixmapstr.h"
 
42
#include "mifpoly.h"
 
43
#include "mi.h"
 
44
#include "mifillarc.h"
 
45
 
 
46
#define QUADRANT (90 * 64)
 
47
#define HALFCIRCLE (180 * 64)
 
48
#define QUADRANT3 (270 * 64)
 
49
 
 
50
#ifndef M_PI
 
51
#define M_PI    3.14159265358979323846
 
52
#endif
 
53
 
 
54
#define Dsin(d) sin((double)d*(M_PI/11520.0))
 
55
#define Dcos(d) cos((double)d*(M_PI/11520.0))
 
56
 
 
57
void
 
58
miFillArcSetup(arc, info)
 
59
    register xArc *arc;
 
60
    register miFillArcRec *info;
 
61
{
 
62
    info->y = arc->height >> 1;
 
63
    info->dy = arc->height & 1;
 
64
    info->yorg = arc->y + info->y;
 
65
    info->dx = arc->width & 1;
 
66
    info->xorg = arc->x + (arc->width >> 1) + info->dx;
 
67
    info->dx = 1 - info->dx;
 
68
    if (arc->width == arc->height)
 
69
    {
 
70
        /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
 
71
        /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 
72
        info->ym = 8;
 
73
        info->xm = 8;
 
74
        info->yk = info->y << 3;
 
75
        if (!info->dx)
 
76
        {
 
77
            info->xk = 0;
 
78
            info->e = -1;
 
79
        }
 
80
        else
 
81
        {
 
82
            info->y++;
 
83
            info->yk += 4;
 
84
            info->xk = -4;
 
85
            info->e = - (info->y << 3);
 
86
        }
 
87
    }
 
88
    else
 
89
    {
 
90
        /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
 
91
        /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 
92
        info->ym = (arc->width * arc->width) << 3;
 
93
        info->xm = (arc->height * arc->height) << 3;
 
94
        info->yk = info->y * info->ym;
 
95
        if (!info->dy)
 
96
            info->yk -= info->ym >> 1;
 
97
        if (!info->dx)
 
98
        {
 
99
            info->xk = 0;
 
100
            info->e = - (info->xm >> 3);
 
101
        }
 
102
        else
 
103
        {
 
104
            info->y++;
 
105
            info->yk += info->ym;
 
106
            info->xk = -(info->xm >> 1);
 
107
            info->e = info->xk - info->yk;
 
108
        }
 
109
    }
 
110
}
 
111
 
 
112
void
 
113
miFillArcDSetup(arc, info)
 
114
    register xArc *arc;
 
115
    register miFillArcDRec *info;
 
116
{
 
117
    /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
 
118
    /* even: xorg = yorg = 0   odd:  xorg = .5, yorg = -.5 */
 
119
    info->y = arc->height >> 1;
 
120
    info->dy = arc->height & 1;
 
121
    info->yorg = arc->y + info->y;
 
122
    info->dx = arc->width & 1;
 
123
    info->xorg = arc->x + (arc->width >> 1) + info->dx;
 
124
    info->dx = 1 - info->dx;
 
125
    info->ym = ((double)arc->width) * (arc->width * 8);
 
126
    info->xm = ((double)arc->height) * (arc->height * 8);
 
127
    info->yk = info->y * info->ym;
 
128
    if (!info->dy)
 
129
        info->yk -= info->ym / 2.0;
 
130
    if (!info->dx)
 
131
    {
 
132
        info->xk = 0;
 
133
        info->e = - (info->xm / 8.0);
 
134
    }
 
135
    else
 
136
    {
 
137
        info->y++;
 
138
        info->yk += info->ym;
 
139
        info->xk = -info->xm / 2.0;
 
140
        info->e = info->xk - info->yk;
 
141
    }
 
142
}
 
143
 
 
144
static void
 
145
miGetArcEdge(
 
146
             register xArc *arc,
 
147
             register miSliceEdgePtr edge,
 
148
             int k,
 
149
             Bool top, 
 
150
             Bool left )
 
151
{
 
152
    register int xady, y;
 
153
 
 
154
    y = arc->height >> 1;
 
155
    if (!(arc->width & 1))
 
156
        y++;
 
157
    if (!top)
 
158
    {
 
159
        y = -y;
 
160
        if (arc->height & 1)
 
161
            y--;
 
162
    }
 
163
    xady = k + y * edge->dx;
 
164
    if (xady <= 0)
 
165
        edge->x = - ((-xady) / edge->dy + 1);
 
166
    else
 
167
        edge->x = (xady - 1) / edge->dy;
 
168
    edge->e = xady - edge->x * edge->dy;
 
169
    if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
 
170
        edge->e = edge->dy - edge->e + 1;
 
171
    if (left)
 
172
        edge->x++;
 
173
    edge->x += arc->x + (arc->width >> 1);
 
174
    if (edge->dx > 0)
 
175
    {
 
176
        edge->deltax = 1;
 
177
        edge->stepx = edge->dx / edge->dy;
 
178
        edge->dx = edge->dx % edge->dy;
 
179
    }
 
180
    else
 
181
    {
 
182
        edge->deltax = -1;
 
183
        edge->stepx = - ((-edge->dx) / edge->dy);
 
184
        edge->dx = (-edge->dx) % edge->dy;
 
185
    }
 
186
    if (!top)
 
187
    {
 
188
        edge->deltax = -edge->deltax;
 
189
        edge->stepx = -edge->stepx;
 
190
    }
 
191
}
 
192
 
 
193
void
 
194
miEllipseAngleToSlope (angle, width, height, dxp, dyp, d_dxp, d_dyp)
 
195
    int     angle;
 
196
    int     width;
 
197
    int     height;
 
198
    int     *dxp;
 
199
    int     *dyp;
 
200
    double  *d_dxp;
 
201
    double  *d_dyp;
 
202
{
 
203
    int     dx, dy;
 
204
    double  d_dx, d_dy, scale;
 
205
    Bool    negative_dx, negative_dy;
 
206
 
 
207
    switch (angle) {
 
208
    case 0:
 
209
        *dxp = -1;
 
210
        *dyp = 0;
 
211
        if (d_dxp) {
 
212
            *d_dxp = width / 2.0;
 
213
            *d_dyp = 0;
 
214
        }
 
215
        break;
 
216
    case QUADRANT:
 
217
        *dxp = 0;
 
218
        *dyp = 1;
 
219
        if (d_dxp) {
 
220
            *d_dxp = 0;
 
221
            *d_dyp = - height / 2.0;
 
222
        }
 
223
        break;
 
224
    case HALFCIRCLE:
 
225
        *dxp = 1;
 
226
        *dyp = 0;
 
227
        if (d_dxp) {
 
228
            *d_dxp = - width / 2.0;
 
229
            *d_dyp = 0;
 
230
        }
 
231
        break;
 
232
    case QUADRANT3:
 
233
        *dxp = 0;
 
234
        *dyp = -1;
 
235
        if (d_dxp) {
 
236
            *d_dxp = 0;
 
237
            *d_dyp = height / 2.0;
 
238
        }
 
239
        break;
 
240
    default:
 
241
        d_dx = Dcos(angle) * width;
 
242
        d_dy = Dsin(angle) * height;
 
243
        if (d_dxp) {
 
244
            *d_dxp = d_dx / 2.0;
 
245
            *d_dyp = - d_dy / 2.0;
 
246
        }
 
247
        negative_dx = FALSE;
 
248
        if (d_dx < 0.0)
 
249
        {
 
250
            d_dx = -d_dx;
 
251
            negative_dx = TRUE;
 
252
        }
 
253
        negative_dy = FALSE;
 
254
        if (d_dy < 0.0)
 
255
        {
 
256
            d_dy = -d_dy;
 
257
            negative_dy = TRUE;
 
258
        }
 
259
        scale = d_dx;
 
260
        if (d_dy > d_dx)
 
261
            scale = d_dy;
 
262
        dx = floor ((d_dx * 32768) / scale + 0.5);
 
263
        if (negative_dx)
 
264
            dx = -dx;
 
265
        *dxp = dx;
 
266
        dy = floor ((d_dy * 32768) / scale + 0.5);
 
267
        if (negative_dy)
 
268
            dy = -dy;
 
269
        *dyp = dy;
 
270
        break;
 
271
    }
 
272
}
 
273
 
 
274
static void
 
275
miGetPieEdge(
 
276
             register xArc *arc,
 
277
             register int angle,
 
278
             register miSliceEdgePtr edge,
 
279
             Bool top, 
 
280
             Bool left )
 
281
{
 
282
    register int k;
 
283
    int dx, dy;
 
284
 
 
285
    miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
 
286
 
 
287
    if (dy == 0)
 
288
    {
 
289
        edge->x = left ? -65536 : 65536;
 
290
        edge->stepx = 0;
 
291
        edge->e = 0;
 
292
        edge->dx = -1;
 
293
        return;
 
294
    }
 
295
    if (dx == 0)
 
296
    {
 
297
        edge->x = arc->x + (arc->width >> 1);
 
298
        if (left && (arc->width & 1))
 
299
            edge->x++;
 
300
        else if (!left && !(arc->width & 1))
 
301
            edge->x--;
 
302
        edge->stepx = 0;
 
303
        edge->e = 0;
 
304
        edge->dx = -1;
 
305
        return;
 
306
    }
 
307
    if (dy < 0) {
 
308
        dx = -dx;
 
309
        dy = -dy;
 
310
    }
 
311
    k = (arc->height & 1) ? dx : 0;
 
312
    if (arc->width & 1)
 
313
        k += dy;
 
314
    edge->dx = dx << 1;
 
315
    edge->dy = dy << 1;
 
316
    miGetArcEdge(arc, edge, k, top, left);
 
317
}
 
318
 
 
319
void
 
320
miFillArcSliceSetup(arc, slice, pGC)
 
321
    register xArc *arc;
 
322
    register miArcSliceRec *slice;
 
323
    GCPtr pGC;
 
324
{
 
325
    register int angle1, angle2;
 
326
 
 
327
    angle1 = arc->angle1;
 
328
    if (arc->angle2 < 0)
 
329
    {
 
330
        angle2 = angle1;
 
331
        angle1 += arc->angle2;
 
332
    }
 
333
    else
 
334
        angle2 = angle1 + arc->angle2;
 
335
    while (angle1 < 0)
 
336
        angle1 += FULLCIRCLE;
 
337
    while (angle1 >= FULLCIRCLE)
 
338
        angle1 -= FULLCIRCLE;
 
339
    while (angle2 < 0)
 
340
        angle2 += FULLCIRCLE;
 
341
    while (angle2 >= FULLCIRCLE)
 
342
        angle2 -= FULLCIRCLE;
 
343
    slice->min_top_y = 0;
 
344
    slice->max_top_y = arc->height >> 1;
 
345
    slice->min_bot_y = 1 - (arc->height & 1);
 
346
    slice->max_bot_y = slice->max_top_y - 1;
 
347
    slice->flip_top = FALSE;
 
348
    slice->flip_bot = FALSE;
 
349
    if (pGC->arcMode == ArcPieSlice)
 
350
    {
 
351
        slice->edge1_top = (angle1 < HALFCIRCLE);
 
352
        slice->edge2_top = (angle2 <= HALFCIRCLE);
 
353
        if ((angle2 == 0) || (angle1 == HALFCIRCLE))
 
354
        {
 
355
            if (angle2 ? slice->edge2_top : slice->edge1_top)
 
356
                slice->min_top_y = slice->min_bot_y;
 
357
            else
 
358
                slice->min_top_y = arc->height;
 
359
            slice->min_bot_y = 0;
 
360
        }
 
361
        else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
 
362
        {
 
363
            slice->min_top_y = slice->min_bot_y;
 
364
            if (angle1 ? slice->edge1_top : slice->edge2_top)
 
365
                slice->min_bot_y = arc->height;
 
366
            else
 
367
                slice->min_bot_y = 0;
 
368
        }
 
369
        else if (slice->edge1_top == slice->edge2_top)
 
370
        {
 
371
            if (angle2 < angle1)
 
372
            {
 
373
                slice->flip_top = slice->edge1_top;
 
374
                slice->flip_bot = !slice->edge1_top;
 
375
            }
 
376
            else if (slice->edge1_top)
 
377
            {
 
378
                slice->min_top_y = 1;
 
379
                slice->min_bot_y = arc->height;
 
380
            }
 
381
            else
 
382
            {
 
383
                slice->min_bot_y = 0;
 
384
                slice->min_top_y = arc->height;
 
385
            }
 
386
        }
 
387
        miGetPieEdge(arc, angle1, &slice->edge1,
 
388
                     slice->edge1_top, !slice->edge1_top);
 
389
        miGetPieEdge(arc, angle2, &slice->edge2,
 
390
                     slice->edge2_top, slice->edge2_top);
 
391
    }
 
392
    else
 
393
    {
 
394
        double w2, h2, x1, y1, x2, y2, dx, dy, scale;
 
395
        int signdx, signdy, y, k;
 
396
        Bool isInt1 = TRUE, isInt2 = TRUE;
 
397
 
 
398
        w2 = (double)arc->width / 2.0;
 
399
        h2 = (double)arc->height / 2.0;
 
400
        if ((angle1 == 0) || (angle1 == HALFCIRCLE))
 
401
        {
 
402
            x1 = angle1 ? -w2 : w2;
 
403
            y1 = 0.0;
 
404
        }
 
405
        else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
 
406
        {
 
407
            x1 = 0.0;
 
408
            y1 = (angle1 == QUADRANT) ? h2 : -h2;
 
409
        }
 
410
        else
 
411
        {
 
412
            isInt1 = FALSE;
 
413
            x1 = Dcos(angle1) * w2;
 
414
            y1 = Dsin(angle1) * h2;
 
415
        }
 
416
        if ((angle2 == 0) || (angle2 == HALFCIRCLE))
 
417
        {
 
418
            x2 = angle2 ? -w2 : w2;
 
419
            y2 = 0.0;
 
420
        }
 
421
        else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
 
422
        {
 
423
            x2 = 0.0;
 
424
            y2 = (angle2 == QUADRANT) ? h2 : -h2;
 
425
        }
 
426
        else
 
427
        {
 
428
            isInt2 = FALSE;
 
429
            x2 = Dcos(angle2) * w2;
 
430
            y2 = Dsin(angle2) * h2;
 
431
        }
 
432
        dx = x2 - x1;
 
433
        dy = y2 - y1;
 
434
        if (arc->height & 1)
 
435
        {
 
436
            y1 -= 0.5;
 
437
            y2 -= 0.5;
 
438
        }
 
439
        if (arc->width & 1)
 
440
        {
 
441
            x1 += 0.5;
 
442
            x2 += 0.5;
 
443
        }
 
444
        if (dy < 0.0)
 
445
        {
 
446
            dy = -dy;
 
447
            signdy = -1;
 
448
        }
 
449
        else
 
450
            signdy = 1;
 
451
        if (dx < 0.0)
 
452
        {
 
453
            dx = -dx;
 
454
            signdx = -1;
 
455
        }
 
456
        else
 
457
            signdx = 1;
 
458
        if (isInt1 && isInt2)
 
459
        {
 
460
            slice->edge1.dx = dx * 2;
 
461
            slice->edge1.dy = dy * 2;
 
462
        }
 
463
        else
 
464
        {
 
465
            scale = (dx > dy) ? dx : dy;
 
466
            slice->edge1.dx = floor((dx * 32768) / scale + .5);
 
467
            slice->edge1.dy = floor((dy * 32768) / scale + .5);
 
468
        }
 
469
        if (!slice->edge1.dy)
 
470
        {
 
471
            if (signdx < 0)
 
472
            {
 
473
                y = floor(y1 + 1.0);
 
474
                if (y >= 0)
 
475
                {
 
476
                    slice->min_top_y = y;
 
477
                    slice->min_bot_y = arc->height;
 
478
                }
 
479
                else
 
480
                {
 
481
                    slice->max_bot_y = -y - (arc->height & 1);
 
482
                }
 
483
            }
 
484
            else
 
485
            {
 
486
                y = floor(y1);
 
487
                if (y >= 0)
 
488
                    slice->max_top_y = y;
 
489
                else
 
490
                {
 
491
                    slice->min_top_y = arc->height;
 
492
                    slice->min_bot_y = -y - (arc->height & 1);
 
493
                }
 
494
            }
 
495
            slice->edge1_top = TRUE;
 
496
            slice->edge1.x = 65536;
 
497
            slice->edge1.stepx = 0;
 
498
            slice->edge1.e = 0;
 
499
            slice->edge1.dx = -1;
 
500
            slice->edge2 = slice->edge1;
 
501
            slice->edge2_top = FALSE;
 
502
        }
 
503
        else if (!slice->edge1.dx)
 
504
        {
 
505
            if (signdy < 0)
 
506
                x1 -= 1.0;
 
507
            slice->edge1.x = ceil(x1);
 
508
            slice->edge1_top = signdy < 0;
 
509
            slice->edge1.x += arc->x + (arc->width >> 1);
 
510
            slice->edge1.stepx = 0;
 
511
            slice->edge1.e = 0;
 
512
            slice->edge1.dx = -1;
 
513
            slice->edge2_top = !slice->edge1_top;
 
514
            slice->edge2 = slice->edge1;
 
515
        }
 
516
        else
 
517
        {
 
518
            if (signdx < 0)
 
519
                slice->edge1.dx = -slice->edge1.dx;
 
520
            if (signdy < 0)
 
521
                slice->edge1.dx = -slice->edge1.dx;
 
522
            k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
 
523
            slice->edge2.dx = slice->edge1.dx;
 
524
            slice->edge2.dy = slice->edge1.dy;
 
525
            slice->edge1_top = signdy < 0;
 
526
            slice->edge2_top = !slice->edge1_top;
 
527
            miGetArcEdge(arc, &slice->edge1, k,
 
528
                         slice->edge1_top, !slice->edge1_top);
 
529
            miGetArcEdge(arc, &slice->edge2, k,
 
530
                         slice->edge2_top, slice->edge2_top);
 
531
        }
 
532
    }
 
533
}
 
534
 
 
535
#define ADDSPANS() \
 
536
    pts->x = xorg - x; \
 
537
    pts->y = yorg - y; \
 
538
    *wids = slw; \
 
539
    pts++; \
 
540
    wids++; \
 
541
    if (miFillArcLower(slw)) \
 
542
    { \
 
543
        pts->x = xorg - x; \
 
544
        pts->y = yorg + y + dy; \
 
545
        pts++; \
 
546
        *wids++ = slw; \
 
547
    }
 
548
 
 
549
static void
 
550
miFillEllipseI(
 
551
               DrawablePtr pDraw,
 
552
               GCPtr pGC,
 
553
               xArc *arc )
 
554
{
 
555
    register int x, y, e;
 
556
    int yk, xk, ym, xm, dx, dy, xorg, yorg;
 
557
    int slw;
 
558
    miFillArcRec info;
 
559
    DDXPointPtr points;
 
560
    register DDXPointPtr pts;
 
561
    int *widths;
 
562
    register int *wids;
 
563
 
 
564
    points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height);
 
565
    if (!points)
 
566
        return;
 
567
    widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height);
 
568
    if (!widths)
 
569
    {
 
570
        DEALLOCATE_LOCAL(points);
 
571
        return;
 
572
    }
 
573
    miFillArcSetup(arc, &info);
 
574
    MIFILLARCSETUP();
 
575
    if (pGC->miTranslate)
 
576
    {
 
577
        xorg += pDraw->x;
 
578
        yorg += pDraw->y;
 
579
    }
 
580
    pts = points;
 
581
    wids = widths;
 
582
    while (y > 0)
 
583
    {
 
584
        MIFILLARCSTEP(slw);
 
585
        ADDSPANS();
 
586
    }
 
587
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 
588
    DEALLOCATE_LOCAL(widths);
 
589
    DEALLOCATE_LOCAL(points);
 
590
}
 
591
 
 
592
static void
 
593
miFillEllipseD(
 
594
               DrawablePtr pDraw,
 
595
               GCPtr pGC,
 
596
               xArc *arc )
 
597
{
 
598
    register int x, y;
 
599
    int xorg, yorg, dx, dy, slw;
 
600
    double e, yk, xk, ym, xm;
 
601
    miFillArcDRec info;
 
602
    DDXPointPtr points;
 
603
    register DDXPointPtr pts;
 
604
    int *widths;
 
605
    register int *wids;
 
606
 
 
607
    points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height);
 
608
    if (!points)
 
609
        return;
 
610
    widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height);
 
611
    if (!widths)
 
612
    {
 
613
        DEALLOCATE_LOCAL(points);
 
614
        return;
 
615
    }
 
616
    miFillArcDSetup(arc, &info);
 
617
    MIFILLARCSETUP();
 
618
    if (pGC->miTranslate)
 
619
    {
 
620
        xorg += pDraw->x;
 
621
        yorg += pDraw->y;
 
622
    }
 
623
    pts = points;
 
624
    wids = widths;
 
625
    while (y > 0)
 
626
    {
 
627
        MIFILLARCSTEP(slw);
 
628
        ADDSPANS();
 
629
    }
 
630
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 
631
    DEALLOCATE_LOCAL(widths);
 
632
    DEALLOCATE_LOCAL(points);
 
633
}
 
634
 
 
635
#define ADDSPAN(l,r) \
 
636
    if (r >= l) \
 
637
    { \
 
638
        pts->x = l; \
 
639
        pts->y = ya; \
 
640
        pts++; \
 
641
        *wids++ = r - l + 1; \
 
642
    }
 
643
 
 
644
#define ADDSLICESPANS(flip) \
 
645
    if (!flip) \
 
646
    { \
 
647
        ADDSPAN(xl, xr); \
 
648
    } \
 
649
    else \
 
650
    { \
 
651
        xc = xorg - x; \
 
652
        ADDSPAN(xc, xr); \
 
653
        xc += slw - 1; \
 
654
        ADDSPAN(xl, xc); \
 
655
    }
 
656
 
 
657
static void
 
658
miFillArcSliceI(
 
659
                DrawablePtr pDraw,
 
660
                GCPtr pGC,
 
661
                xArc *arc )
 
662
{
 
663
    int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
 
664
    register int x, y, e;
 
665
    miFillArcRec info;
 
666
    miArcSliceRec slice;
 
667
    int ya, xl, xr, xc;
 
668
    DDXPointPtr points;
 
669
    register DDXPointPtr pts;
 
670
    int *widths;
 
671
    register int *wids;
 
672
 
 
673
    miFillArcSetup(arc, &info);
 
674
    miFillArcSliceSetup(arc, &slice, pGC);
 
675
    MIFILLARCSETUP();
 
676
    slw = arc->height;
 
677
    if (slice.flip_top || slice.flip_bot)
 
678
        slw += (arc->height >> 1) + 1;
 
679
    points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw);
 
680
    if (!points)
 
681
        return;
 
682
    widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw);
 
683
    if (!widths)
 
684
    {
 
685
        DEALLOCATE_LOCAL(points);
 
686
        return;
 
687
    }
 
688
    if (pGC->miTranslate)
 
689
    {
 
690
        xorg += pDraw->x;
 
691
        yorg += pDraw->y;
 
692
        slice.edge1.x += pDraw->x;
 
693
        slice.edge2.x += pDraw->x;
 
694
    }
 
695
    pts = points;
 
696
    wids = widths;
 
697
    while (y > 0)
 
698
    {
 
699
        MIFILLARCSTEP(slw);
 
700
        MIARCSLICESTEP(slice.edge1);
 
701
        MIARCSLICESTEP(slice.edge2);
 
702
        if (miFillSliceUpper(slice))
 
703
        {
 
704
            ya = yorg - y;
 
705
            MIARCSLICEUPPER(xl, xr, slice, slw);
 
706
            ADDSLICESPANS(slice.flip_top);
 
707
        }
 
708
        if (miFillSliceLower(slice))
 
709
        {
 
710
            ya = yorg + y + dy;
 
711
            MIARCSLICELOWER(xl, xr, slice, slw);
 
712
            ADDSLICESPANS(slice.flip_bot);
 
713
        }
 
714
    }
 
715
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 
716
    DEALLOCATE_LOCAL(widths);
 
717
    DEALLOCATE_LOCAL(points);
 
718
}
 
719
 
 
720
static void
 
721
miFillArcSliceD(
 
722
                DrawablePtr pDraw,
 
723
                GCPtr pGC,
 
724
                xArc *arc )
 
725
{
 
726
    register int x, y;
 
727
    int dx, dy, xorg, yorg, slw;
 
728
    double e, yk, xk, ym, xm;
 
729
    miFillArcDRec info;
 
730
    miArcSliceRec slice;
 
731
    int ya, xl, xr, xc;
 
732
    DDXPointPtr points;
 
733
    register DDXPointPtr pts;
 
734
    int *widths;
 
735
    register int *wids;
 
736
 
 
737
    miFillArcDSetup(arc, &info);
 
738
    miFillArcSliceSetup(arc, &slice, pGC);
 
739
    MIFILLARCSETUP();
 
740
    slw = arc->height;
 
741
    if (slice.flip_top || slice.flip_bot)
 
742
        slw += (arc->height >> 1) + 1;
 
743
    points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw);
 
744
    if (!points)
 
745
        return;
 
746
    widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw);
 
747
    if (!widths)
 
748
    {
 
749
        DEALLOCATE_LOCAL(points);
 
750
        return;
 
751
    }
 
752
    if (pGC->miTranslate)
 
753
    {
 
754
        xorg += pDraw->x;
 
755
        yorg += pDraw->y;
 
756
        slice.edge1.x += pDraw->x;
 
757
        slice.edge2.x += pDraw->x;
 
758
    }
 
759
    pts = points;
 
760
    wids = widths;
 
761
    while (y > 0)
 
762
    {
 
763
        MIFILLARCSTEP(slw);
 
764
        MIARCSLICESTEP(slice.edge1);
 
765
        MIARCSLICESTEP(slice.edge2);
 
766
        if (miFillSliceUpper(slice))
 
767
        {
 
768
            ya = yorg - y;
 
769
            MIARCSLICEUPPER(xl, xr, slice, slw);
 
770
            ADDSLICESPANS(slice.flip_top);
 
771
        }
 
772
        if (miFillSliceLower(slice))
 
773
        {
 
774
            ya = yorg + y + dy;
 
775
            MIARCSLICELOWER(xl, xr, slice, slw);
 
776
            ADDSLICESPANS(slice.flip_bot);
 
777
        }
 
778
    }
 
779
    (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
 
780
    DEALLOCATE_LOCAL(widths);
 
781
    DEALLOCATE_LOCAL(points);
 
782
}
 
783
 
 
784
/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
 
785
 * Since we don't have to worry about overlapping segments, we can just
 
786
 * fill each arc as it comes.
 
787
 */
 
788
void
 
789
miPolyFillArc(pDraw, pGC, narcs, parcs)
 
790
    DrawablePtr pDraw;
 
791
    GCPtr       pGC;
 
792
    int         narcs;
 
793
    xArc        *parcs;
 
794
{
 
795
    register int i;
 
796
    register xArc *arc;
 
797
 
 
798
    for(i = narcs, arc = parcs; --i >= 0; arc++)
 
799
    {
 
800
        if (miFillArcEmpty(arc))
 
801
            continue;;
 
802
        if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
 
803
        {
 
804
            if (miCanFillArc(arc))
 
805
                miFillEllipseI(pDraw, pGC, arc);
 
806
            else
 
807
                miFillEllipseD(pDraw, pGC, arc);
 
808
        }
 
809
        else
 
810
        {
 
811
            if (miCanFillArc(arc))
 
812
                miFillArcSliceI(pDraw, pGC, arc);
 
813
            else
 
814
                miFillArcSliceD(pDraw, pGC, arc);
 
815
        }
 
816
    }
 
817
}