1706f2543Smrg/************************************************************ 2706f2543Smrg 3706f2543SmrgCopyright 1989, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg 25706f2543SmrgAuthor: Bob Scheifler, MIT X Consortium 26706f2543Smrg 27706f2543Smrg********************************************************/ 28706f2543Smrg 29706f2543Smrg 30706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 31706f2543Smrg#include <dix-config.h> 32706f2543Smrg#endif 33706f2543Smrg 34706f2543Smrg#include <math.h> 35706f2543Smrg#include <X11/X.h> 36706f2543Smrg#include <X11/Xprotostr.h> 37706f2543Smrg#include "regionstr.h" 38706f2543Smrg#include "gcstruct.h" 39706f2543Smrg#include "pixmapstr.h" 40706f2543Smrg#include "mifpoly.h" 41706f2543Smrg#include "mi.h" 42706f2543Smrg#include "mifillarc.h" 43706f2543Smrg 44706f2543Smrg#define QUADRANT (90 * 64) 45706f2543Smrg#define HALFCIRCLE (180 * 64) 46706f2543Smrg#define QUADRANT3 (270 * 64) 47706f2543Smrg 48706f2543Smrg#ifndef M_PI 49706f2543Smrg#define M_PI 3.14159265358979323846 50706f2543Smrg#endif 51706f2543Smrg 52706f2543Smrg#define Dsin(d) sin((double)d*(M_PI/11520.0)) 53706f2543Smrg#define Dcos(d) cos((double)d*(M_PI/11520.0)) 54706f2543Smrg 55706f2543Smrgvoid 56706f2543SmrgmiFillArcSetup(xArc *arc, miFillArcRec *info) 57706f2543Smrg{ 58706f2543Smrg info->y = arc->height >> 1; 59706f2543Smrg info->dy = arc->height & 1; 60706f2543Smrg info->yorg = arc->y + info->y; 61706f2543Smrg info->dx = arc->width & 1; 62706f2543Smrg info->xorg = arc->x + (arc->width >> 1) + info->dx; 63706f2543Smrg info->dx = 1 - info->dx; 64706f2543Smrg if (arc->width == arc->height) 65706f2543Smrg { 66706f2543Smrg /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */ 67706f2543Smrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 68706f2543Smrg info->ym = 8; 69706f2543Smrg info->xm = 8; 70706f2543Smrg info->yk = info->y << 3; 71706f2543Smrg if (!info->dx) 72706f2543Smrg { 73706f2543Smrg info->xk = 0; 74706f2543Smrg info->e = -1; 75706f2543Smrg } 76706f2543Smrg else 77706f2543Smrg { 78706f2543Smrg info->y++; 79706f2543Smrg info->yk += 4; 80706f2543Smrg info->xk = -4; 81706f2543Smrg info->e = - (info->y << 3); 82706f2543Smrg } 83706f2543Smrg } 84706f2543Smrg else 85706f2543Smrg { 86706f2543Smrg /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ 87706f2543Smrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 88706f2543Smrg info->ym = (arc->width * arc->width) << 3; 89706f2543Smrg info->xm = (arc->height * arc->height) << 3; 90706f2543Smrg info->yk = info->y * info->ym; 91706f2543Smrg if (!info->dy) 92706f2543Smrg info->yk -= info->ym >> 1; 93706f2543Smrg if (!info->dx) 94706f2543Smrg { 95706f2543Smrg info->xk = 0; 96706f2543Smrg info->e = - (info->xm >> 3); 97706f2543Smrg } 98706f2543Smrg else 99706f2543Smrg { 100706f2543Smrg info->y++; 101706f2543Smrg info->yk += info->ym; 102706f2543Smrg info->xk = -(info->xm >> 1); 103706f2543Smrg info->e = info->xk - info->yk; 104706f2543Smrg } 105706f2543Smrg } 106706f2543Smrg} 107706f2543Smrg 108706f2543Smrgstatic void 109706f2543SmrgmiFillArcDSetup(xArc *arc, miFillArcDRec *info) 110706f2543Smrg{ 111706f2543Smrg /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ 112706f2543Smrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 113706f2543Smrg info->y = arc->height >> 1; 114706f2543Smrg info->dy = arc->height & 1; 115706f2543Smrg info->yorg = arc->y + info->y; 116706f2543Smrg info->dx = arc->width & 1; 117706f2543Smrg info->xorg = arc->x + (arc->width >> 1) + info->dx; 118706f2543Smrg info->dx = 1 - info->dx; 119706f2543Smrg info->ym = ((double)arc->width) * (arc->width * 8); 120706f2543Smrg info->xm = ((double)arc->height) * (arc->height * 8); 121706f2543Smrg info->yk = info->y * info->ym; 122706f2543Smrg if (!info->dy) 123706f2543Smrg info->yk -= info->ym / 2.0; 124706f2543Smrg if (!info->dx) 125706f2543Smrg { 126706f2543Smrg info->xk = 0; 127706f2543Smrg info->e = - (info->xm / 8.0); 128706f2543Smrg } 129706f2543Smrg else 130706f2543Smrg { 131706f2543Smrg info->y++; 132706f2543Smrg info->yk += info->ym; 133706f2543Smrg info->xk = -info->xm / 2.0; 134706f2543Smrg info->e = info->xk - info->yk; 135706f2543Smrg } 136706f2543Smrg} 137706f2543Smrg 138706f2543Smrgstatic void 139706f2543SmrgmiGetArcEdge( 140706f2543Smrg xArc *arc, 141706f2543Smrg miSliceEdgePtr edge, 142706f2543Smrg int k, 143706f2543Smrg Bool top, 144706f2543Smrg Bool left ) 145706f2543Smrg{ 146706f2543Smrg int xady, y; 147706f2543Smrg 148706f2543Smrg y = arc->height >> 1; 149706f2543Smrg if (!(arc->width & 1)) 150706f2543Smrg y++; 151706f2543Smrg if (!top) 152706f2543Smrg { 153706f2543Smrg y = -y; 154706f2543Smrg if (arc->height & 1) 155706f2543Smrg y--; 156706f2543Smrg } 157706f2543Smrg xady = k + y * edge->dx; 158706f2543Smrg if (xady <= 0) 159706f2543Smrg edge->x = - ((-xady) / edge->dy + 1); 160706f2543Smrg else 161706f2543Smrg edge->x = (xady - 1) / edge->dy; 162706f2543Smrg edge->e = xady - edge->x * edge->dy; 163706f2543Smrg if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0))) 164706f2543Smrg edge->e = edge->dy - edge->e + 1; 165706f2543Smrg if (left) 166706f2543Smrg edge->x++; 167706f2543Smrg edge->x += arc->x + (arc->width >> 1); 168706f2543Smrg if (edge->dx > 0) 169706f2543Smrg { 170706f2543Smrg edge->deltax = 1; 171706f2543Smrg edge->stepx = edge->dx / edge->dy; 172706f2543Smrg edge->dx = edge->dx % edge->dy; 173706f2543Smrg } 174706f2543Smrg else 175706f2543Smrg { 176706f2543Smrg edge->deltax = -1; 177706f2543Smrg edge->stepx = - ((-edge->dx) / edge->dy); 178706f2543Smrg edge->dx = (-edge->dx) % edge->dy; 179706f2543Smrg } 180706f2543Smrg if (!top) 181706f2543Smrg { 182706f2543Smrg edge->deltax = -edge->deltax; 183706f2543Smrg edge->stepx = -edge->stepx; 184706f2543Smrg } 185706f2543Smrg} 186706f2543Smrg 187706f2543Smrgstatic void 188706f2543SmrgmiEllipseAngleToSlope (int angle, int width, int height, int *dxp, int *dyp, 189706f2543Smrg double *d_dxp, double *d_dyp) 190706f2543Smrg{ 191706f2543Smrg int dx, dy; 192706f2543Smrg double d_dx, d_dy, scale; 193706f2543Smrg Bool negative_dx, negative_dy; 194706f2543Smrg 195706f2543Smrg switch (angle) { 196706f2543Smrg case 0: 197706f2543Smrg *dxp = -1; 198706f2543Smrg *dyp = 0; 199706f2543Smrg if (d_dxp) { 200706f2543Smrg *d_dxp = width / 2.0; 201706f2543Smrg *d_dyp = 0; 202706f2543Smrg } 203706f2543Smrg break; 204706f2543Smrg case QUADRANT: 205706f2543Smrg *dxp = 0; 206706f2543Smrg *dyp = 1; 207706f2543Smrg if (d_dxp) { 208706f2543Smrg *d_dxp = 0; 209706f2543Smrg *d_dyp = - height / 2.0; 210706f2543Smrg } 211706f2543Smrg break; 212706f2543Smrg case HALFCIRCLE: 213706f2543Smrg *dxp = 1; 214706f2543Smrg *dyp = 0; 215706f2543Smrg if (d_dxp) { 216706f2543Smrg *d_dxp = - width / 2.0; 217706f2543Smrg *d_dyp = 0; 218706f2543Smrg } 219706f2543Smrg break; 220706f2543Smrg case QUADRANT3: 221706f2543Smrg *dxp = 0; 222706f2543Smrg *dyp = -1; 223706f2543Smrg if (d_dxp) { 224706f2543Smrg *d_dxp = 0; 225706f2543Smrg *d_dyp = height / 2.0; 226706f2543Smrg } 227706f2543Smrg break; 228706f2543Smrg default: 229706f2543Smrg d_dx = Dcos(angle) * width; 230706f2543Smrg d_dy = Dsin(angle) * height; 231706f2543Smrg if (d_dxp) { 232706f2543Smrg *d_dxp = d_dx / 2.0; 233706f2543Smrg *d_dyp = - d_dy / 2.0; 234706f2543Smrg } 235706f2543Smrg negative_dx = FALSE; 236706f2543Smrg if (d_dx < 0.0) 237706f2543Smrg { 238706f2543Smrg d_dx = -d_dx; 239706f2543Smrg negative_dx = TRUE; 240706f2543Smrg } 241706f2543Smrg negative_dy = FALSE; 242706f2543Smrg if (d_dy < 0.0) 243706f2543Smrg { 244706f2543Smrg d_dy = -d_dy; 245706f2543Smrg negative_dy = TRUE; 246706f2543Smrg } 247706f2543Smrg scale = d_dx; 248706f2543Smrg if (d_dy > d_dx) 249706f2543Smrg scale = d_dy; 250706f2543Smrg dx = floor ((d_dx * 32768) / scale + 0.5); 251706f2543Smrg if (negative_dx) 252706f2543Smrg dx = -dx; 253706f2543Smrg *dxp = dx; 254706f2543Smrg dy = floor ((d_dy * 32768) / scale + 0.5); 255706f2543Smrg if (negative_dy) 256706f2543Smrg dy = -dy; 257706f2543Smrg *dyp = dy; 258706f2543Smrg break; 259706f2543Smrg } 260706f2543Smrg} 261706f2543Smrg 262706f2543Smrgstatic void 263706f2543SmrgmiGetPieEdge( 264706f2543Smrg xArc *arc, 265706f2543Smrg int angle, 266706f2543Smrg miSliceEdgePtr edge, 267706f2543Smrg Bool top, 268706f2543Smrg Bool left ) 269706f2543Smrg{ 270706f2543Smrg int k; 271706f2543Smrg int dx, dy; 272706f2543Smrg 273706f2543Smrg miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0); 274706f2543Smrg 275706f2543Smrg if (dy == 0) 276706f2543Smrg { 277706f2543Smrg edge->x = left ? -65536 : 65536; 278706f2543Smrg edge->stepx = 0; 279706f2543Smrg edge->e = 0; 280706f2543Smrg edge->dx = -1; 281706f2543Smrg return; 282706f2543Smrg } 283706f2543Smrg if (dx == 0) 284706f2543Smrg { 285706f2543Smrg edge->x = arc->x + (arc->width >> 1); 286706f2543Smrg if (left && (arc->width & 1)) 287706f2543Smrg edge->x++; 288706f2543Smrg else if (!left && !(arc->width & 1)) 289706f2543Smrg edge->x--; 290706f2543Smrg edge->stepx = 0; 291706f2543Smrg edge->e = 0; 292706f2543Smrg edge->dx = -1; 293706f2543Smrg return; 294706f2543Smrg } 295706f2543Smrg if (dy < 0) { 296706f2543Smrg dx = -dx; 297706f2543Smrg dy = -dy; 298706f2543Smrg } 299706f2543Smrg k = (arc->height & 1) ? dx : 0; 300706f2543Smrg if (arc->width & 1) 301706f2543Smrg k += dy; 302706f2543Smrg edge->dx = dx << 1; 303706f2543Smrg edge->dy = dy << 1; 304706f2543Smrg miGetArcEdge(arc, edge, k, top, left); 305706f2543Smrg} 306706f2543Smrg 307706f2543Smrgvoid 308706f2543SmrgmiFillArcSliceSetup(xArc *arc, miArcSliceRec *slice, GCPtr pGC) 309706f2543Smrg{ 310706f2543Smrg int angle1, angle2; 311706f2543Smrg 312706f2543Smrg angle1 = arc->angle1; 313706f2543Smrg if (arc->angle2 < 0) 314706f2543Smrg { 315706f2543Smrg angle2 = angle1; 316706f2543Smrg angle1 += arc->angle2; 317706f2543Smrg } 318706f2543Smrg else 319706f2543Smrg angle2 = angle1 + arc->angle2; 320706f2543Smrg while (angle1 < 0) 321706f2543Smrg angle1 += FULLCIRCLE; 322706f2543Smrg while (angle1 >= FULLCIRCLE) 323706f2543Smrg angle1 -= FULLCIRCLE; 324706f2543Smrg while (angle2 < 0) 325706f2543Smrg angle2 += FULLCIRCLE; 326706f2543Smrg while (angle2 >= FULLCIRCLE) 327706f2543Smrg angle2 -= FULLCIRCLE; 328706f2543Smrg slice->min_top_y = 0; 329706f2543Smrg slice->max_top_y = arc->height >> 1; 330706f2543Smrg slice->min_bot_y = 1 - (arc->height & 1); 331706f2543Smrg slice->max_bot_y = slice->max_top_y - 1; 332706f2543Smrg slice->flip_top = FALSE; 333706f2543Smrg slice->flip_bot = FALSE; 334706f2543Smrg if (pGC->arcMode == ArcPieSlice) 335706f2543Smrg { 336706f2543Smrg slice->edge1_top = (angle1 < HALFCIRCLE); 337706f2543Smrg slice->edge2_top = (angle2 <= HALFCIRCLE); 338706f2543Smrg if ((angle2 == 0) || (angle1 == HALFCIRCLE)) 339706f2543Smrg { 340706f2543Smrg if (angle2 ? slice->edge2_top : slice->edge1_top) 341706f2543Smrg slice->min_top_y = slice->min_bot_y; 342706f2543Smrg else 343706f2543Smrg slice->min_top_y = arc->height; 344706f2543Smrg slice->min_bot_y = 0; 345706f2543Smrg } 346706f2543Smrg else if ((angle1 == 0) || (angle2 == HALFCIRCLE)) 347706f2543Smrg { 348706f2543Smrg slice->min_top_y = slice->min_bot_y; 349706f2543Smrg if (angle1 ? slice->edge1_top : slice->edge2_top) 350706f2543Smrg slice->min_bot_y = arc->height; 351706f2543Smrg else 352706f2543Smrg slice->min_bot_y = 0; 353706f2543Smrg } 354706f2543Smrg else if (slice->edge1_top == slice->edge2_top) 355706f2543Smrg { 356706f2543Smrg if (angle2 < angle1) 357706f2543Smrg { 358706f2543Smrg slice->flip_top = slice->edge1_top; 359706f2543Smrg slice->flip_bot = !slice->edge1_top; 360706f2543Smrg } 361706f2543Smrg else if (slice->edge1_top) 362706f2543Smrg { 363706f2543Smrg slice->min_top_y = 1; 364706f2543Smrg slice->min_bot_y = arc->height; 365706f2543Smrg } 366706f2543Smrg else 367706f2543Smrg { 368706f2543Smrg slice->min_bot_y = 0; 369706f2543Smrg slice->min_top_y = arc->height; 370706f2543Smrg } 371706f2543Smrg } 372706f2543Smrg miGetPieEdge(arc, angle1, &slice->edge1, 373706f2543Smrg slice->edge1_top, !slice->edge1_top); 374706f2543Smrg miGetPieEdge(arc, angle2, &slice->edge2, 375706f2543Smrg slice->edge2_top, slice->edge2_top); 376706f2543Smrg } 377706f2543Smrg else 378706f2543Smrg { 379706f2543Smrg double w2, h2, x1, y1, x2, y2, dx, dy, scale; 380706f2543Smrg int signdx, signdy, y, k; 381706f2543Smrg Bool isInt1 = TRUE, isInt2 = TRUE; 382706f2543Smrg 383706f2543Smrg w2 = (double)arc->width / 2.0; 384706f2543Smrg h2 = (double)arc->height / 2.0; 385706f2543Smrg if ((angle1 == 0) || (angle1 == HALFCIRCLE)) 386706f2543Smrg { 387706f2543Smrg x1 = angle1 ? -w2 : w2; 388706f2543Smrg y1 = 0.0; 389706f2543Smrg } 390706f2543Smrg else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3)) 391706f2543Smrg { 392706f2543Smrg x1 = 0.0; 393706f2543Smrg y1 = (angle1 == QUADRANT) ? h2 : -h2; 394706f2543Smrg } 395706f2543Smrg else 396706f2543Smrg { 397706f2543Smrg isInt1 = FALSE; 398706f2543Smrg x1 = Dcos(angle1) * w2; 399706f2543Smrg y1 = Dsin(angle1) * h2; 400706f2543Smrg } 401706f2543Smrg if ((angle2 == 0) || (angle2 == HALFCIRCLE)) 402706f2543Smrg { 403706f2543Smrg x2 = angle2 ? -w2 : w2; 404706f2543Smrg y2 = 0.0; 405706f2543Smrg } 406706f2543Smrg else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3)) 407706f2543Smrg { 408706f2543Smrg x2 = 0.0; 409706f2543Smrg y2 = (angle2 == QUADRANT) ? h2 : -h2; 410706f2543Smrg } 411706f2543Smrg else 412706f2543Smrg { 413706f2543Smrg isInt2 = FALSE; 414706f2543Smrg x2 = Dcos(angle2) * w2; 415706f2543Smrg y2 = Dsin(angle2) * h2; 416706f2543Smrg } 417706f2543Smrg dx = x2 - x1; 418706f2543Smrg dy = y2 - y1; 419706f2543Smrg if (arc->height & 1) 420706f2543Smrg { 421706f2543Smrg y1 -= 0.5; 422706f2543Smrg y2 -= 0.5; 423706f2543Smrg } 424706f2543Smrg if (arc->width & 1) 425706f2543Smrg { 426706f2543Smrg x1 += 0.5; 427706f2543Smrg x2 += 0.5; 428706f2543Smrg } 429706f2543Smrg if (dy < 0.0) 430706f2543Smrg { 431706f2543Smrg dy = -dy; 432706f2543Smrg signdy = -1; 433706f2543Smrg } 434706f2543Smrg else 435706f2543Smrg signdy = 1; 436706f2543Smrg if (dx < 0.0) 437706f2543Smrg { 438706f2543Smrg dx = -dx; 439706f2543Smrg signdx = -1; 440706f2543Smrg } 441706f2543Smrg else 442706f2543Smrg signdx = 1; 443706f2543Smrg if (isInt1 && isInt2) 444706f2543Smrg { 445706f2543Smrg slice->edge1.dx = dx * 2; 446706f2543Smrg slice->edge1.dy = dy * 2; 447706f2543Smrg } 448706f2543Smrg else 449706f2543Smrg { 450706f2543Smrg scale = (dx > dy) ? dx : dy; 451706f2543Smrg slice->edge1.dx = floor((dx * 32768) / scale + .5); 452706f2543Smrg slice->edge1.dy = floor((dy * 32768) / scale + .5); 453706f2543Smrg } 454706f2543Smrg if (!slice->edge1.dy) 455706f2543Smrg { 456706f2543Smrg if (signdx < 0) 457706f2543Smrg { 458706f2543Smrg y = floor(y1 + 1.0); 459706f2543Smrg if (y >= 0) 460706f2543Smrg { 461706f2543Smrg slice->min_top_y = y; 462706f2543Smrg slice->min_bot_y = arc->height; 463706f2543Smrg } 464706f2543Smrg else 465706f2543Smrg { 466706f2543Smrg slice->max_bot_y = -y - (arc->height & 1); 467706f2543Smrg } 468706f2543Smrg } 469706f2543Smrg else 470706f2543Smrg { 471706f2543Smrg y = floor(y1); 472706f2543Smrg if (y >= 0) 473706f2543Smrg slice->max_top_y = y; 474706f2543Smrg else 475706f2543Smrg { 476706f2543Smrg slice->min_top_y = arc->height; 477706f2543Smrg slice->min_bot_y = -y - (arc->height & 1); 478706f2543Smrg } 479706f2543Smrg } 480706f2543Smrg slice->edge1_top = TRUE; 481706f2543Smrg slice->edge1.x = 65536; 482706f2543Smrg slice->edge1.stepx = 0; 483706f2543Smrg slice->edge1.e = 0; 484706f2543Smrg slice->edge1.dx = -1; 485706f2543Smrg slice->edge2 = slice->edge1; 486706f2543Smrg slice->edge2_top = FALSE; 487706f2543Smrg } 488706f2543Smrg else if (!slice->edge1.dx) 489706f2543Smrg { 490706f2543Smrg if (signdy < 0) 491706f2543Smrg x1 -= 1.0; 492706f2543Smrg slice->edge1.x = ceil(x1); 493706f2543Smrg slice->edge1_top = signdy < 0; 494706f2543Smrg slice->edge1.x += arc->x + (arc->width >> 1); 495706f2543Smrg slice->edge1.stepx = 0; 496706f2543Smrg slice->edge1.e = 0; 497706f2543Smrg slice->edge1.dx = -1; 498706f2543Smrg slice->edge2_top = !slice->edge1_top; 499706f2543Smrg slice->edge2 = slice->edge1; 500706f2543Smrg } 501706f2543Smrg else 502706f2543Smrg { 503706f2543Smrg if (signdx < 0) 504706f2543Smrg slice->edge1.dx = -slice->edge1.dx; 505706f2543Smrg if (signdy < 0) 506706f2543Smrg slice->edge1.dx = -slice->edge1.dx; 507706f2543Smrg k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0); 508706f2543Smrg slice->edge2.dx = slice->edge1.dx; 509706f2543Smrg slice->edge2.dy = slice->edge1.dy; 510706f2543Smrg slice->edge1_top = signdy < 0; 511706f2543Smrg slice->edge2_top = !slice->edge1_top; 512706f2543Smrg miGetArcEdge(arc, &slice->edge1, k, 513706f2543Smrg slice->edge1_top, !slice->edge1_top); 514706f2543Smrg miGetArcEdge(arc, &slice->edge2, k, 515706f2543Smrg slice->edge2_top, slice->edge2_top); 516706f2543Smrg } 517706f2543Smrg } 518706f2543Smrg} 519706f2543Smrg 520706f2543Smrg#define ADDSPANS() \ 521706f2543Smrg pts->x = xorg - x; \ 522706f2543Smrg pts->y = yorg - y; \ 523706f2543Smrg *wids = slw; \ 524706f2543Smrg pts++; \ 525706f2543Smrg wids++; \ 526706f2543Smrg if (miFillArcLower(slw)) \ 527706f2543Smrg { \ 528706f2543Smrg pts->x = xorg - x; \ 529706f2543Smrg pts->y = yorg + y + dy; \ 530706f2543Smrg pts++; \ 531706f2543Smrg *wids++ = slw; \ 532706f2543Smrg } 533706f2543Smrg 534706f2543Smrgstatic void 535706f2543SmrgmiFillEllipseI( 536706f2543Smrg DrawablePtr pDraw, 537706f2543Smrg GCPtr pGC, 538706f2543Smrg xArc *arc ) 539706f2543Smrg{ 540706f2543Smrg int x, y, e; 541706f2543Smrg int yk, xk, ym, xm, dx, dy, xorg, yorg; 542706f2543Smrg int slw; 543706f2543Smrg miFillArcRec info; 544706f2543Smrg DDXPointPtr points; 545706f2543Smrg DDXPointPtr pts; 546706f2543Smrg int *widths; 547706f2543Smrg int *wids; 548706f2543Smrg 549706f2543Smrg points = malloc(sizeof(DDXPointRec) * arc->height); 550706f2543Smrg if (!points) 551706f2543Smrg return; 552706f2543Smrg widths = malloc(sizeof(int) * arc->height); 553706f2543Smrg if (!widths) 554706f2543Smrg { 555706f2543Smrg free(points); 556706f2543Smrg return; 557706f2543Smrg } 558706f2543Smrg miFillArcSetup(arc, &info); 559706f2543Smrg MIFILLARCSETUP(); 560706f2543Smrg if (pGC->miTranslate) 561706f2543Smrg { 562706f2543Smrg xorg += pDraw->x; 563706f2543Smrg yorg += pDraw->y; 564706f2543Smrg } 565706f2543Smrg pts = points; 566706f2543Smrg wids = widths; 567706f2543Smrg while (y > 0) 568706f2543Smrg { 569706f2543Smrg MIFILLARCSTEP(slw); 570706f2543Smrg ADDSPANS(); 571706f2543Smrg } 572706f2543Smrg (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); 573706f2543Smrg free(widths); 574706f2543Smrg free(points); 575706f2543Smrg} 576706f2543Smrg 577706f2543Smrgstatic void 578706f2543SmrgmiFillEllipseD( 579706f2543Smrg DrawablePtr pDraw, 580706f2543Smrg GCPtr pGC, 581706f2543Smrg xArc *arc ) 582706f2543Smrg{ 583706f2543Smrg int x, y; 584706f2543Smrg int xorg, yorg, dx, dy, slw; 585706f2543Smrg double e, yk, xk, ym, xm; 586706f2543Smrg miFillArcDRec info; 587706f2543Smrg DDXPointPtr points; 588706f2543Smrg DDXPointPtr pts; 589706f2543Smrg int *widths; 590706f2543Smrg int *wids; 591706f2543Smrg 592706f2543Smrg points = malloc(sizeof(DDXPointRec) * arc->height); 593706f2543Smrg if (!points) 594706f2543Smrg return; 595706f2543Smrg widths = malloc(sizeof(int) * arc->height); 596706f2543Smrg if (!widths) 597706f2543Smrg { 598706f2543Smrg free(points); 599706f2543Smrg return; 600706f2543Smrg } 601706f2543Smrg miFillArcDSetup(arc, &info); 602706f2543Smrg MIFILLARCSETUP(); 603706f2543Smrg if (pGC->miTranslate) 604706f2543Smrg { 605706f2543Smrg xorg += pDraw->x; 606706f2543Smrg yorg += pDraw->y; 607706f2543Smrg } 608706f2543Smrg pts = points; 609706f2543Smrg wids = widths; 610706f2543Smrg while (y > 0) 611706f2543Smrg { 612706f2543Smrg MIFILLARCSTEP(slw); 613706f2543Smrg ADDSPANS(); 614706f2543Smrg } 615706f2543Smrg (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); 616706f2543Smrg free(widths); 617706f2543Smrg free(points); 618706f2543Smrg} 619706f2543Smrg 620706f2543Smrg#define ADDSPAN(l,r) \ 621706f2543Smrg if (r >= l) \ 622706f2543Smrg { \ 623706f2543Smrg pts->x = l; \ 624706f2543Smrg pts->y = ya; \ 625706f2543Smrg pts++; \ 626706f2543Smrg *wids++ = r - l + 1; \ 627706f2543Smrg } 628706f2543Smrg 629706f2543Smrg#define ADDSLICESPANS(flip) \ 630706f2543Smrg if (!flip) \ 631706f2543Smrg { \ 632706f2543Smrg ADDSPAN(xl, xr); \ 633706f2543Smrg } \ 634706f2543Smrg else \ 635706f2543Smrg { \ 636706f2543Smrg xc = xorg - x; \ 637706f2543Smrg ADDSPAN(xc, xr); \ 638706f2543Smrg xc += slw - 1; \ 639706f2543Smrg ADDSPAN(xl, xc); \ 640706f2543Smrg } 641706f2543Smrg 642706f2543Smrgstatic void 643706f2543SmrgmiFillArcSliceI( 644706f2543Smrg DrawablePtr pDraw, 645706f2543Smrg GCPtr pGC, 646706f2543Smrg xArc *arc ) 647706f2543Smrg{ 648706f2543Smrg int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; 649706f2543Smrg int x, y, e; 650706f2543Smrg miFillArcRec info; 651706f2543Smrg miArcSliceRec slice; 652706f2543Smrg int ya, xl, xr, xc; 653706f2543Smrg DDXPointPtr points; 654706f2543Smrg DDXPointPtr pts; 655706f2543Smrg int *widths; 656706f2543Smrg int *wids; 657706f2543Smrg 658706f2543Smrg miFillArcSetup(arc, &info); 659706f2543Smrg miFillArcSliceSetup(arc, &slice, pGC); 660706f2543Smrg MIFILLARCSETUP(); 661706f2543Smrg slw = arc->height; 662706f2543Smrg if (slice.flip_top || slice.flip_bot) 663706f2543Smrg slw += (arc->height >> 1) + 1; 664706f2543Smrg points = malloc(sizeof(DDXPointRec) * slw); 665706f2543Smrg if (!points) 666706f2543Smrg return; 667706f2543Smrg widths = malloc(sizeof(int) * slw); 668706f2543Smrg if (!widths) 669706f2543Smrg { 670706f2543Smrg free(points); 671706f2543Smrg return; 672706f2543Smrg } 673706f2543Smrg if (pGC->miTranslate) 674706f2543Smrg { 675706f2543Smrg xorg += pDraw->x; 676706f2543Smrg yorg += pDraw->y; 677706f2543Smrg slice.edge1.x += pDraw->x; 678706f2543Smrg slice.edge2.x += pDraw->x; 679706f2543Smrg } 680706f2543Smrg pts = points; 681706f2543Smrg wids = widths; 682706f2543Smrg while (y > 0) 683706f2543Smrg { 684706f2543Smrg MIFILLARCSTEP(slw); 685706f2543Smrg MIARCSLICESTEP(slice.edge1); 686706f2543Smrg MIARCSLICESTEP(slice.edge2); 687706f2543Smrg if (miFillSliceUpper(slice)) 688706f2543Smrg { 689706f2543Smrg ya = yorg - y; 690706f2543Smrg MIARCSLICEUPPER(xl, xr, slice, slw); 691706f2543Smrg ADDSLICESPANS(slice.flip_top); 692706f2543Smrg } 693706f2543Smrg if (miFillSliceLower(slice)) 694706f2543Smrg { 695706f2543Smrg ya = yorg + y + dy; 696706f2543Smrg MIARCSLICELOWER(xl, xr, slice, slw); 697706f2543Smrg ADDSLICESPANS(slice.flip_bot); 698706f2543Smrg } 699706f2543Smrg } 700706f2543Smrg (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); 701706f2543Smrg free(widths); 702706f2543Smrg free(points); 703706f2543Smrg} 704706f2543Smrg 705706f2543Smrgstatic void 706706f2543SmrgmiFillArcSliceD( 707706f2543Smrg DrawablePtr pDraw, 708706f2543Smrg GCPtr pGC, 709706f2543Smrg xArc *arc ) 710706f2543Smrg{ 711706f2543Smrg int x, y; 712706f2543Smrg int dx, dy, xorg, yorg, slw; 713706f2543Smrg double e, yk, xk, ym, xm; 714706f2543Smrg miFillArcDRec info; 715706f2543Smrg miArcSliceRec slice; 716706f2543Smrg int ya, xl, xr, xc; 717706f2543Smrg DDXPointPtr points; 718706f2543Smrg DDXPointPtr pts; 719706f2543Smrg int *widths; 720706f2543Smrg int *wids; 721706f2543Smrg 722706f2543Smrg miFillArcDSetup(arc, &info); 723706f2543Smrg miFillArcSliceSetup(arc, &slice, pGC); 724706f2543Smrg MIFILLARCSETUP(); 725706f2543Smrg slw = arc->height; 726706f2543Smrg if (slice.flip_top || slice.flip_bot) 727706f2543Smrg slw += (arc->height >> 1) + 1; 728706f2543Smrg points = malloc(sizeof(DDXPointRec) * slw); 729706f2543Smrg if (!points) 730706f2543Smrg return; 731706f2543Smrg widths = malloc(sizeof(int) * slw); 732706f2543Smrg if (!widths) 733706f2543Smrg { 734706f2543Smrg free(points); 735706f2543Smrg return; 736706f2543Smrg } 737706f2543Smrg if (pGC->miTranslate) 738706f2543Smrg { 739706f2543Smrg xorg += pDraw->x; 740706f2543Smrg yorg += pDraw->y; 741706f2543Smrg slice.edge1.x += pDraw->x; 742706f2543Smrg slice.edge2.x += pDraw->x; 743706f2543Smrg } 744706f2543Smrg pts = points; 745706f2543Smrg wids = widths; 746706f2543Smrg while (y > 0) 747706f2543Smrg { 748706f2543Smrg MIFILLARCSTEP(slw); 749706f2543Smrg MIARCSLICESTEP(slice.edge1); 750706f2543Smrg MIARCSLICESTEP(slice.edge2); 751706f2543Smrg if (miFillSliceUpper(slice)) 752706f2543Smrg { 753706f2543Smrg ya = yorg - y; 754706f2543Smrg MIARCSLICEUPPER(xl, xr, slice, slw); 755706f2543Smrg ADDSLICESPANS(slice.flip_top); 756706f2543Smrg } 757706f2543Smrg if (miFillSliceLower(slice)) 758706f2543Smrg { 759706f2543Smrg ya = yorg + y + dy; 760706f2543Smrg MIARCSLICELOWER(xl, xr, slice, slw); 761706f2543Smrg ADDSLICESPANS(slice.flip_bot); 762706f2543Smrg } 763706f2543Smrg } 764706f2543Smrg (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE); 765706f2543Smrg free(widths); 766706f2543Smrg free(points); 767706f2543Smrg} 768706f2543Smrg 769706f2543Smrg/* MIPOLYFILLARC -- The public entry for the PolyFillArc request. 770706f2543Smrg * Since we don't have to worry about overlapping segments, we can just 771706f2543Smrg * fill each arc as it comes. 772706f2543Smrg */ 773706f2543Smrgvoid 774706f2543SmrgmiPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) 775706f2543Smrg{ 776706f2543Smrg int i; 777706f2543Smrg xArc *arc; 778706f2543Smrg 779706f2543Smrg for(i = narcs, arc = parcs; --i >= 0; arc++) 780706f2543Smrg { 781706f2543Smrg if (miFillArcEmpty(arc)) 782706f2543Smrg continue; 783706f2543Smrg if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) 784706f2543Smrg { 785706f2543Smrg if (miCanFillArc(arc)) 786706f2543Smrg miFillEllipseI(pDraw, pGC, arc); 787706f2543Smrg else 788706f2543Smrg miFillEllipseD(pDraw, pGC, arc); 789706f2543Smrg } 790706f2543Smrg else 791706f2543Smrg { 792706f2543Smrg if (miCanFillArc(arc)) 793706f2543Smrg miFillArcSliceI(pDraw, pGC, arc); 794706f2543Smrg else 795706f2543Smrg miFillArcSliceD(pDraw, pGC, arc); 796706f2543Smrg } 797706f2543Smrg } 798706f2543Smrg} 799