1
/* $XFree86: xc/programs/Xserver/mi/mifillarc.c,v 3.7 2001/12/14 20:00:22 dawes Exp $ */
2
/************************************************************
4
Copyright 1989, 1998 The Open Group
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
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
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.
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.
26
Author: Bob Scheifler, MIT X Consortium
28
********************************************************/
30
/* $Xorg: mifillarc.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $ */
32
#ifdef HAVE_DIX_CONFIG_H
33
#include <dix-config.h>
38
#include <X11/Xprotostr.h>
39
#include "regionstr.h"
41
#include "pixmapstr.h"
44
#include "mifillarc.h"
46
#define QUADRANT (90 * 64)
47
#define HALFCIRCLE (180 * 64)
48
#define QUADRANT3 (270 * 64)
51
#define M_PI 3.14159265358979323846
54
#define Dsin(d) sin((double)d*(M_PI/11520.0))
55
#define Dcos(d) cos((double)d*(M_PI/11520.0))
58
miFillArcSetup(arc, info)
60
register miFillArcRec *info;
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)
70
/* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
71
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
74
info->yk = info->y << 3;
85
info->e = - (info->y << 3);
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;
96
info->yk -= info->ym >> 1;
100
info->e = - (info->xm >> 3);
105
info->yk += info->ym;
106
info->xk = -(info->xm >> 1);
107
info->e = info->xk - info->yk;
113
miFillArcDSetup(arc, info)
115
register miFillArcDRec *info;
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;
129
info->yk -= info->ym / 2.0;
133
info->e = - (info->xm / 8.0);
138
info->yk += info->ym;
139
info->xk = -info->xm / 2.0;
140
info->e = info->xk - info->yk;
147
register miSliceEdgePtr edge,
152
register int xady, y;
154
y = arc->height >> 1;
155
if (!(arc->width & 1))
163
xady = k + y * edge->dx;
165
edge->x = - ((-xady) / edge->dy + 1);
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;
173
edge->x += arc->x + (arc->width >> 1);
177
edge->stepx = edge->dx / edge->dy;
178
edge->dx = edge->dx % edge->dy;
183
edge->stepx = - ((-edge->dx) / edge->dy);
184
edge->dx = (-edge->dx) % edge->dy;
188
edge->deltax = -edge->deltax;
189
edge->stepx = -edge->stepx;
194
miEllipseAngleToSlope (angle, width, height, dxp, dyp, d_dxp, d_dyp)
204
double d_dx, d_dy, scale;
205
Bool negative_dx, negative_dy;
212
*d_dxp = width / 2.0;
221
*d_dyp = - height / 2.0;
228
*d_dxp = - width / 2.0;
237
*d_dyp = height / 2.0;
241
d_dx = Dcos(angle) * width;
242
d_dy = Dsin(angle) * height;
245
*d_dyp = - d_dy / 2.0;
262
dx = floor ((d_dx * 32768) / scale + 0.5);
266
dy = floor ((d_dy * 32768) / scale + 0.5);
278
register miSliceEdgePtr edge,
285
miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
289
edge->x = left ? -65536 : 65536;
297
edge->x = arc->x + (arc->width >> 1);
298
if (left && (arc->width & 1))
300
else if (!left && !(arc->width & 1))
311
k = (arc->height & 1) ? dx : 0;
316
miGetArcEdge(arc, edge, k, top, left);
320
miFillArcSliceSetup(arc, slice, pGC)
322
register miArcSliceRec *slice;
325
register int angle1, angle2;
327
angle1 = arc->angle1;
331
angle1 += arc->angle2;
334
angle2 = angle1 + arc->angle2;
336
angle1 += FULLCIRCLE;
337
while (angle1 >= FULLCIRCLE)
338
angle1 -= FULLCIRCLE;
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)
351
slice->edge1_top = (angle1 < HALFCIRCLE);
352
slice->edge2_top = (angle2 <= HALFCIRCLE);
353
if ((angle2 == 0) || (angle1 == HALFCIRCLE))
355
if (angle2 ? slice->edge2_top : slice->edge1_top)
356
slice->min_top_y = slice->min_bot_y;
358
slice->min_top_y = arc->height;
359
slice->min_bot_y = 0;
361
else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
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;
367
slice->min_bot_y = 0;
369
else if (slice->edge1_top == slice->edge2_top)
373
slice->flip_top = slice->edge1_top;
374
slice->flip_bot = !slice->edge1_top;
376
else if (slice->edge1_top)
378
slice->min_top_y = 1;
379
slice->min_bot_y = arc->height;
383
slice->min_bot_y = 0;
384
slice->min_top_y = arc->height;
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);
394
double w2, h2, x1, y1, x2, y2, dx, dy, scale;
395
int signdx, signdy, y, k;
396
Bool isInt1 = TRUE, isInt2 = TRUE;
398
w2 = (double)arc->width / 2.0;
399
h2 = (double)arc->height / 2.0;
400
if ((angle1 == 0) || (angle1 == HALFCIRCLE))
402
x1 = angle1 ? -w2 : w2;
405
else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
408
y1 = (angle1 == QUADRANT) ? h2 : -h2;
413
x1 = Dcos(angle1) * w2;
414
y1 = Dsin(angle1) * h2;
416
if ((angle2 == 0) || (angle2 == HALFCIRCLE))
418
x2 = angle2 ? -w2 : w2;
421
else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
424
y2 = (angle2 == QUADRANT) ? h2 : -h2;
429
x2 = Dcos(angle2) * w2;
430
y2 = Dsin(angle2) * h2;
458
if (isInt1 && isInt2)
460
slice->edge1.dx = dx * 2;
461
slice->edge1.dy = dy * 2;
465
scale = (dx > dy) ? dx : dy;
466
slice->edge1.dx = floor((dx * 32768) / scale + .5);
467
slice->edge1.dy = floor((dy * 32768) / scale + .5);
469
if (!slice->edge1.dy)
476
slice->min_top_y = y;
477
slice->min_bot_y = arc->height;
481
slice->max_bot_y = -y - (arc->height & 1);
488
slice->max_top_y = y;
491
slice->min_top_y = arc->height;
492
slice->min_bot_y = -y - (arc->height & 1);
495
slice->edge1_top = TRUE;
496
slice->edge1.x = 65536;
497
slice->edge1.stepx = 0;
499
slice->edge1.dx = -1;
500
slice->edge2 = slice->edge1;
501
slice->edge2_top = FALSE;
503
else if (!slice->edge1.dx)
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;
512
slice->edge1.dx = -1;
513
slice->edge2_top = !slice->edge1_top;
514
slice->edge2 = slice->edge1;
519
slice->edge1.dx = -slice->edge1.dx;
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);
541
if (miFillArcLower(slw)) \
544
pts->y = yorg + y + dy; \
555
register int x, y, e;
556
int yk, xk, ym, xm, dx, dy, xorg, yorg;
560
register DDXPointPtr pts;
564
points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height);
567
widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height);
570
DEALLOCATE_LOCAL(points);
573
miFillArcSetup(arc, &info);
575
if (pGC->miTranslate)
587
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
588
DEALLOCATE_LOCAL(widths);
589
DEALLOCATE_LOCAL(points);
599
int xorg, yorg, dx, dy, slw;
600
double e, yk, xk, ym, xm;
603
register DDXPointPtr pts;
607
points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * arc->height);
610
widths = (int *)ALLOCATE_LOCAL(sizeof(int) * arc->height);
613
DEALLOCATE_LOCAL(points);
616
miFillArcDSetup(arc, &info);
618
if (pGC->miTranslate)
630
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
631
DEALLOCATE_LOCAL(widths);
632
DEALLOCATE_LOCAL(points);
635
#define ADDSPAN(l,r) \
641
*wids++ = r - l + 1; \
644
#define ADDSLICESPANS(flip) \
663
int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
664
register int x, y, e;
669
register DDXPointPtr pts;
673
miFillArcSetup(arc, &info);
674
miFillArcSliceSetup(arc, &slice, pGC);
677
if (slice.flip_top || slice.flip_bot)
678
slw += (arc->height >> 1) + 1;
679
points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw);
682
widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw);
685
DEALLOCATE_LOCAL(points);
688
if (pGC->miTranslate)
692
slice.edge1.x += pDraw->x;
693
slice.edge2.x += pDraw->x;
700
MIARCSLICESTEP(slice.edge1);
701
MIARCSLICESTEP(slice.edge2);
702
if (miFillSliceUpper(slice))
705
MIARCSLICEUPPER(xl, xr, slice, slw);
706
ADDSLICESPANS(slice.flip_top);
708
if (miFillSliceLower(slice))
711
MIARCSLICELOWER(xl, xr, slice, slw);
712
ADDSLICESPANS(slice.flip_bot);
715
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
716
DEALLOCATE_LOCAL(widths);
717
DEALLOCATE_LOCAL(points);
727
int dx, dy, xorg, yorg, slw;
728
double e, yk, xk, ym, xm;
733
register DDXPointPtr pts;
737
miFillArcDSetup(arc, &info);
738
miFillArcSliceSetup(arc, &slice, pGC);
741
if (slice.flip_top || slice.flip_bot)
742
slw += (arc->height >> 1) + 1;
743
points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * slw);
746
widths = (int *)ALLOCATE_LOCAL(sizeof(int) * slw);
749
DEALLOCATE_LOCAL(points);
752
if (pGC->miTranslate)
756
slice.edge1.x += pDraw->x;
757
slice.edge2.x += pDraw->x;
764
MIARCSLICESTEP(slice.edge1);
765
MIARCSLICESTEP(slice.edge2);
766
if (miFillSliceUpper(slice))
769
MIARCSLICEUPPER(xl, xr, slice, slw);
770
ADDSLICESPANS(slice.flip_top);
772
if (miFillSliceLower(slice))
775
MIARCSLICELOWER(xl, xr, slice, slw);
776
ADDSLICESPANS(slice.flip_bot);
779
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
780
DEALLOCATE_LOCAL(widths);
781
DEALLOCATE_LOCAL(points);
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.
789
miPolyFillArc(pDraw, pGC, narcs, parcs)
798
for(i = narcs, arc = parcs; --i >= 0; arc++)
800
if (miFillArcEmpty(arc))
802
if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
804
if (miCanFillArc(arc))
805
miFillEllipseI(pDraw, pGC, arc);
807
miFillEllipseD(pDraw, pGC, arc);
811
if (miCanFillArc(arc))
812
miFillArcSliceI(pDraw, pGC, arc);
814
miFillArcSliceD(pDraw, pGC, arc);