105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgAuthor: Bob Scheifler, MIT X Consortium 2605b261ecSmrg 2705b261ecSmrg********************************************************/ 2805b261ecSmrg 2905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3005b261ecSmrg#include <dix-config.h> 3105b261ecSmrg#endif 3205b261ecSmrg 3305b261ecSmrg#include <math.h> 3405b261ecSmrg#include <X11/X.h> 3505b261ecSmrg#include <X11/Xprotostr.h> 3605b261ecSmrg#include "regionstr.h" 3705b261ecSmrg#include "gcstruct.h" 3805b261ecSmrg#include "pixmapstr.h" 3905b261ecSmrg#include "mi.h" 4005b261ecSmrg#include "mifillarc.h" 4105b261ecSmrg 4205b261ecSmrg#define QUADRANT (90 * 64) 4305b261ecSmrg#define HALFCIRCLE (180 * 64) 4405b261ecSmrg#define QUADRANT3 (270 * 64) 4505b261ecSmrg 4605b261ecSmrg#ifndef M_PI 4705b261ecSmrg#define M_PI 3.14159265358979323846 4805b261ecSmrg#endif 4905b261ecSmrg 5005b261ecSmrg#define Dsin(d) sin((double)d*(M_PI/11520.0)) 5105b261ecSmrg#define Dcos(d) cos((double)d*(M_PI/11520.0)) 5205b261ecSmrg 5335c4bbdfSmrgstatic void 5435c4bbdfSmrgmiFillArcSetup(xArc * arc, miFillArcRec * info) 5505b261ecSmrg{ 5605b261ecSmrg info->y = arc->height >> 1; 5705b261ecSmrg info->dy = arc->height & 1; 5805b261ecSmrg info->yorg = arc->y + info->y; 5905b261ecSmrg info->dx = arc->width & 1; 6005b261ecSmrg info->xorg = arc->x + (arc->width >> 1) + info->dx; 6105b261ecSmrg info->dx = 1 - info->dx; 6235c4bbdfSmrg if (arc->width == arc->height) { 6335c4bbdfSmrg /* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */ 6435c4bbdfSmrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 6535c4bbdfSmrg info->ym = 8; 6635c4bbdfSmrg info->xm = 8; 6735c4bbdfSmrg info->yk = info->y << 3; 6835c4bbdfSmrg if (!info->dx) { 6935c4bbdfSmrg info->xk = 0; 7035c4bbdfSmrg info->e = -1; 7135c4bbdfSmrg } 7235c4bbdfSmrg else { 7335c4bbdfSmrg info->y++; 7435c4bbdfSmrg info->yk += 4; 7535c4bbdfSmrg info->xk = -4; 7635c4bbdfSmrg info->e = -(info->y << 3); 7735c4bbdfSmrg } 7805b261ecSmrg } 7935c4bbdfSmrg else { 8035c4bbdfSmrg /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ 8135c4bbdfSmrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 8235c4bbdfSmrg info->ym = (arc->width * arc->width) << 3; 8335c4bbdfSmrg info->xm = (arc->height * arc->height) << 3; 8435c4bbdfSmrg info->yk = info->y * info->ym; 8535c4bbdfSmrg if (!info->dy) 8635c4bbdfSmrg info->yk -= info->ym >> 1; 8735c4bbdfSmrg if (!info->dx) { 8835c4bbdfSmrg info->xk = 0; 8935c4bbdfSmrg info->e = -(info->xm >> 3); 9035c4bbdfSmrg } 9135c4bbdfSmrg else { 9235c4bbdfSmrg info->y++; 9335c4bbdfSmrg info->yk += info->ym; 9435c4bbdfSmrg info->xk = -(info->xm >> 1); 9535c4bbdfSmrg info->e = info->xk - info->yk; 9635c4bbdfSmrg } 9705b261ecSmrg } 9805b261ecSmrg} 9905b261ecSmrg 10005b261ecSmrgstatic void 10135c4bbdfSmrgmiFillArcDSetup(xArc * arc, miFillArcDRec * info) 10205b261ecSmrg{ 10305b261ecSmrg /* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */ 10405b261ecSmrg /* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */ 10505b261ecSmrg info->y = arc->height >> 1; 10605b261ecSmrg info->dy = arc->height & 1; 10705b261ecSmrg info->yorg = arc->y + info->y; 10805b261ecSmrg info->dx = arc->width & 1; 10905b261ecSmrg info->xorg = arc->x + (arc->width >> 1) + info->dx; 11005b261ecSmrg info->dx = 1 - info->dx; 11135c4bbdfSmrg info->ym = ((double) arc->width) * (arc->width * 8); 11235c4bbdfSmrg info->xm = ((double) arc->height) * (arc->height * 8); 11305b261ecSmrg info->yk = info->y * info->ym; 11405b261ecSmrg if (!info->dy) 11535c4bbdfSmrg info->yk -= info->ym / 2.0; 11635c4bbdfSmrg if (!info->dx) { 11735c4bbdfSmrg info->xk = 0; 11835c4bbdfSmrg info->e = -(info->xm / 8.0); 11905b261ecSmrg } 12035c4bbdfSmrg else { 12135c4bbdfSmrg info->y++; 12235c4bbdfSmrg info->yk += info->ym; 12335c4bbdfSmrg info->xk = -info->xm / 2.0; 12435c4bbdfSmrg info->e = info->xk - info->yk; 12505b261ecSmrg } 12605b261ecSmrg} 12705b261ecSmrg 12805b261ecSmrgstatic void 12935c4bbdfSmrgmiGetArcEdge(xArc * arc, miSliceEdgePtr edge, int k, Bool top, Bool left) 13005b261ecSmrg{ 13105b261ecSmrg int xady, y; 13205b261ecSmrg 13305b261ecSmrg y = arc->height >> 1; 13405b261ecSmrg if (!(arc->width & 1)) 13535c4bbdfSmrg y++; 13635c4bbdfSmrg if (!top) { 13735c4bbdfSmrg y = -y; 13835c4bbdfSmrg if (arc->height & 1) 13935c4bbdfSmrg y--; 14005b261ecSmrg } 14105b261ecSmrg xady = k + y * edge->dx; 14205b261ecSmrg if (xady <= 0) 14335c4bbdfSmrg edge->x = -((-xady) / edge->dy + 1); 14405b261ecSmrg else 14535c4bbdfSmrg edge->x = (xady - 1) / edge->dy; 14605b261ecSmrg edge->e = xady - edge->x * edge->dy; 14705b261ecSmrg if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0))) 14835c4bbdfSmrg edge->e = edge->dy - edge->e + 1; 14905b261ecSmrg if (left) 15035c4bbdfSmrg edge->x++; 15105b261ecSmrg edge->x += arc->x + (arc->width >> 1); 15235c4bbdfSmrg if (edge->dx > 0) { 15335c4bbdfSmrg edge->deltax = 1; 15435c4bbdfSmrg edge->stepx = edge->dx / edge->dy; 15535c4bbdfSmrg edge->dx = edge->dx % edge->dy; 15605b261ecSmrg } 15735c4bbdfSmrg else { 15835c4bbdfSmrg edge->deltax = -1; 15935c4bbdfSmrg edge->stepx = -((-edge->dx) / edge->dy); 16035c4bbdfSmrg edge->dx = (-edge->dx) % edge->dy; 16105b261ecSmrg } 16235c4bbdfSmrg if (!top) { 16335c4bbdfSmrg edge->deltax = -edge->deltax; 16435c4bbdfSmrg edge->stepx = -edge->stepx; 16505b261ecSmrg } 16605b261ecSmrg} 16705b261ecSmrg 16805b261ecSmrgstatic void 16935c4bbdfSmrgmiEllipseAngleToSlope(int angle, int width, int height, int *dxp, int *dyp, 17035c4bbdfSmrg double *d_dxp, double *d_dyp) 17105b261ecSmrg{ 17235c4bbdfSmrg int dx, dy; 17335c4bbdfSmrg double d_dx, d_dy, scale; 17435c4bbdfSmrg Bool negative_dx, negative_dy; 17505b261ecSmrg 17605b261ecSmrg switch (angle) { 17705b261ecSmrg case 0: 17835c4bbdfSmrg *dxp = -1; 17935c4bbdfSmrg *dyp = 0; 18035c4bbdfSmrg if (d_dxp) { 18135c4bbdfSmrg *d_dxp = width / 2.0; 18235c4bbdfSmrg *d_dyp = 0; 18335c4bbdfSmrg } 18435c4bbdfSmrg break; 18505b261ecSmrg case QUADRANT: 18635c4bbdfSmrg *dxp = 0; 18735c4bbdfSmrg *dyp = 1; 18835c4bbdfSmrg if (d_dxp) { 18935c4bbdfSmrg *d_dxp = 0; 19035c4bbdfSmrg *d_dyp = -height / 2.0; 19135c4bbdfSmrg } 19235c4bbdfSmrg break; 19305b261ecSmrg case HALFCIRCLE: 19435c4bbdfSmrg *dxp = 1; 19535c4bbdfSmrg *dyp = 0; 19635c4bbdfSmrg if (d_dxp) { 19735c4bbdfSmrg *d_dxp = -width / 2.0; 19835c4bbdfSmrg *d_dyp = 0; 19935c4bbdfSmrg } 20035c4bbdfSmrg break; 20105b261ecSmrg case QUADRANT3: 20235c4bbdfSmrg *dxp = 0; 20335c4bbdfSmrg *dyp = -1; 20435c4bbdfSmrg if (d_dxp) { 20535c4bbdfSmrg *d_dxp = 0; 20635c4bbdfSmrg *d_dyp = height / 2.0; 20735c4bbdfSmrg } 20835c4bbdfSmrg break; 20905b261ecSmrg default: 21035c4bbdfSmrg d_dx = Dcos(angle) * width; 21135c4bbdfSmrg d_dy = Dsin(angle) * height; 21235c4bbdfSmrg if (d_dxp) { 21335c4bbdfSmrg *d_dxp = d_dx / 2.0; 21435c4bbdfSmrg *d_dyp = -d_dy / 2.0; 21535c4bbdfSmrg } 21635c4bbdfSmrg negative_dx = FALSE; 21735c4bbdfSmrg if (d_dx < 0.0) { 21835c4bbdfSmrg d_dx = -d_dx; 21935c4bbdfSmrg negative_dx = TRUE; 22035c4bbdfSmrg } 22135c4bbdfSmrg negative_dy = FALSE; 22235c4bbdfSmrg if (d_dy < 0.0) { 22335c4bbdfSmrg d_dy = -d_dy; 22435c4bbdfSmrg negative_dy = TRUE; 22535c4bbdfSmrg } 22635c4bbdfSmrg scale = d_dx; 22735c4bbdfSmrg if (d_dy > d_dx) 22835c4bbdfSmrg scale = d_dy; 22935c4bbdfSmrg dx = floor((d_dx * 32768) / scale + 0.5); 23035c4bbdfSmrg if (negative_dx) 23135c4bbdfSmrg dx = -dx; 23235c4bbdfSmrg *dxp = dx; 23335c4bbdfSmrg dy = floor((d_dy * 32768) / scale + 0.5); 23435c4bbdfSmrg if (negative_dy) 23535c4bbdfSmrg dy = -dy; 23635c4bbdfSmrg *dyp = dy; 23735c4bbdfSmrg break; 23805b261ecSmrg } 23905b261ecSmrg} 24005b261ecSmrg 24105b261ecSmrgstatic void 24235c4bbdfSmrgmiGetPieEdge(xArc * arc, int angle, miSliceEdgePtr edge, Bool top, Bool left) 24305b261ecSmrg{ 24405b261ecSmrg int k; 24535c4bbdfSmrg int dx, dy; 24605b261ecSmrg 24735c4bbdfSmrg miEllipseAngleToSlope(angle, arc->width, arc->height, &dx, &dy, 0, 0); 24805b261ecSmrg 24935c4bbdfSmrg if (dy == 0) { 25035c4bbdfSmrg edge->x = left ? -65536 : 65536; 25135c4bbdfSmrg edge->stepx = 0; 25235c4bbdfSmrg edge->e = 0; 25335c4bbdfSmrg edge->dx = -1; 25435c4bbdfSmrg return; 25505b261ecSmrg } 25635c4bbdfSmrg if (dx == 0) { 25735c4bbdfSmrg edge->x = arc->x + (arc->width >> 1); 25835c4bbdfSmrg if (left && (arc->width & 1)) 25935c4bbdfSmrg edge->x++; 26035c4bbdfSmrg else if (!left && !(arc->width & 1)) 26135c4bbdfSmrg edge->x--; 26235c4bbdfSmrg edge->stepx = 0; 26335c4bbdfSmrg edge->e = 0; 26435c4bbdfSmrg edge->dx = -1; 26535c4bbdfSmrg return; 26605b261ecSmrg } 26705b261ecSmrg if (dy < 0) { 26835c4bbdfSmrg dx = -dx; 26935c4bbdfSmrg dy = -dy; 27005b261ecSmrg } 27105b261ecSmrg k = (arc->height & 1) ? dx : 0; 27205b261ecSmrg if (arc->width & 1) 27335c4bbdfSmrg k += dy; 27405b261ecSmrg edge->dx = dx << 1; 27505b261ecSmrg edge->dy = dy << 1; 27605b261ecSmrg miGetArcEdge(arc, edge, k, top, left); 27705b261ecSmrg} 27805b261ecSmrg 27935c4bbdfSmrgstatic void 28035c4bbdfSmrgmiFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC) 28105b261ecSmrg{ 28205b261ecSmrg int angle1, angle2; 28305b261ecSmrg 28405b261ecSmrg angle1 = arc->angle1; 28535c4bbdfSmrg if (arc->angle2 < 0) { 28635c4bbdfSmrg angle2 = angle1; 28735c4bbdfSmrg angle1 += arc->angle2; 28805b261ecSmrg } 28905b261ecSmrg else 29035c4bbdfSmrg angle2 = angle1 + arc->angle2; 29105b261ecSmrg while (angle1 < 0) 29235c4bbdfSmrg angle1 += FULLCIRCLE; 29305b261ecSmrg while (angle1 >= FULLCIRCLE) 29435c4bbdfSmrg angle1 -= FULLCIRCLE; 29505b261ecSmrg while (angle2 < 0) 29635c4bbdfSmrg angle2 += FULLCIRCLE; 29705b261ecSmrg while (angle2 >= FULLCIRCLE) 29835c4bbdfSmrg angle2 -= FULLCIRCLE; 29905b261ecSmrg slice->min_top_y = 0; 30005b261ecSmrg slice->max_top_y = arc->height >> 1; 30105b261ecSmrg slice->min_bot_y = 1 - (arc->height & 1); 30205b261ecSmrg slice->max_bot_y = slice->max_top_y - 1; 30305b261ecSmrg slice->flip_top = FALSE; 30405b261ecSmrg slice->flip_bot = FALSE; 30535c4bbdfSmrg if (pGC->arcMode == ArcPieSlice) { 30635c4bbdfSmrg slice->edge1_top = (angle1 < HALFCIRCLE); 30735c4bbdfSmrg slice->edge2_top = (angle2 <= HALFCIRCLE); 30835c4bbdfSmrg if ((angle2 == 0) || (angle1 == HALFCIRCLE)) { 30935c4bbdfSmrg if (angle2 ? slice->edge2_top : slice->edge1_top) 31035c4bbdfSmrg slice->min_top_y = slice->min_bot_y; 31135c4bbdfSmrg else 31235c4bbdfSmrg slice->min_top_y = arc->height; 31335c4bbdfSmrg slice->min_bot_y = 0; 31435c4bbdfSmrg } 31535c4bbdfSmrg else if ((angle1 == 0) || (angle2 == HALFCIRCLE)) { 31635c4bbdfSmrg slice->min_top_y = slice->min_bot_y; 31735c4bbdfSmrg if (angle1 ? slice->edge1_top : slice->edge2_top) 31835c4bbdfSmrg slice->min_bot_y = arc->height; 31935c4bbdfSmrg else 32035c4bbdfSmrg slice->min_bot_y = 0; 32135c4bbdfSmrg } 32235c4bbdfSmrg else if (slice->edge1_top == slice->edge2_top) { 32335c4bbdfSmrg if (angle2 < angle1) { 32435c4bbdfSmrg slice->flip_top = slice->edge1_top; 32535c4bbdfSmrg slice->flip_bot = !slice->edge1_top; 32635c4bbdfSmrg } 32735c4bbdfSmrg else if (slice->edge1_top) { 32835c4bbdfSmrg slice->min_top_y = 1; 32935c4bbdfSmrg slice->min_bot_y = arc->height; 33035c4bbdfSmrg } 33135c4bbdfSmrg else { 33235c4bbdfSmrg slice->min_bot_y = 0; 33335c4bbdfSmrg slice->min_top_y = arc->height; 33435c4bbdfSmrg } 33535c4bbdfSmrg } 33635c4bbdfSmrg miGetPieEdge(arc, angle1, &slice->edge1, 33735c4bbdfSmrg slice->edge1_top, !slice->edge1_top); 33835c4bbdfSmrg miGetPieEdge(arc, angle2, &slice->edge2, 33935c4bbdfSmrg slice->edge2_top, slice->edge2_top); 34005b261ecSmrg } 34135c4bbdfSmrg else { 34235c4bbdfSmrg double w2, h2, x1, y1, x2, y2, dx, dy, scale; 34335c4bbdfSmrg int signdx, signdy, y, k; 34435c4bbdfSmrg Bool isInt1 = TRUE, isInt2 = TRUE; 34535c4bbdfSmrg 34635c4bbdfSmrg w2 = (double) arc->width / 2.0; 34735c4bbdfSmrg h2 = (double) arc->height / 2.0; 34835c4bbdfSmrg if ((angle1 == 0) || (angle1 == HALFCIRCLE)) { 34935c4bbdfSmrg x1 = angle1 ? -w2 : w2; 35035c4bbdfSmrg y1 = 0.0; 35135c4bbdfSmrg } 35235c4bbdfSmrg else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3)) { 35335c4bbdfSmrg x1 = 0.0; 35435c4bbdfSmrg y1 = (angle1 == QUADRANT) ? h2 : -h2; 35535c4bbdfSmrg } 35635c4bbdfSmrg else { 35735c4bbdfSmrg isInt1 = FALSE; 35835c4bbdfSmrg x1 = Dcos(angle1) * w2; 35935c4bbdfSmrg y1 = Dsin(angle1) * h2; 36035c4bbdfSmrg } 36135c4bbdfSmrg if ((angle2 == 0) || (angle2 == HALFCIRCLE)) { 36235c4bbdfSmrg x2 = angle2 ? -w2 : w2; 36335c4bbdfSmrg y2 = 0.0; 36435c4bbdfSmrg } 36535c4bbdfSmrg else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3)) { 36635c4bbdfSmrg x2 = 0.0; 36735c4bbdfSmrg y2 = (angle2 == QUADRANT) ? h2 : -h2; 36835c4bbdfSmrg } 36935c4bbdfSmrg else { 37035c4bbdfSmrg isInt2 = FALSE; 37135c4bbdfSmrg x2 = Dcos(angle2) * w2; 37235c4bbdfSmrg y2 = Dsin(angle2) * h2; 37335c4bbdfSmrg } 37435c4bbdfSmrg dx = x2 - x1; 37535c4bbdfSmrg dy = y2 - y1; 37635c4bbdfSmrg if (arc->height & 1) { 37735c4bbdfSmrg y1 -= 0.5; 37835c4bbdfSmrg y2 -= 0.5; 37935c4bbdfSmrg } 38035c4bbdfSmrg if (arc->width & 1) { 38135c4bbdfSmrg x1 += 0.5; 38235c4bbdfSmrg x2 += 0.5; 38335c4bbdfSmrg } 38435c4bbdfSmrg if (dy < 0.0) { 38535c4bbdfSmrg dy = -dy; 38635c4bbdfSmrg signdy = -1; 38735c4bbdfSmrg } 38835c4bbdfSmrg else 38935c4bbdfSmrg signdy = 1; 39035c4bbdfSmrg if (dx < 0.0) { 39135c4bbdfSmrg dx = -dx; 39235c4bbdfSmrg signdx = -1; 39335c4bbdfSmrg } 39435c4bbdfSmrg else 39535c4bbdfSmrg signdx = 1; 39635c4bbdfSmrg if (isInt1 && isInt2) { 39735c4bbdfSmrg slice->edge1.dx = dx * 2; 39835c4bbdfSmrg slice->edge1.dy = dy * 2; 39935c4bbdfSmrg } 40035c4bbdfSmrg else { 40135c4bbdfSmrg scale = (dx > dy) ? dx : dy; 40235c4bbdfSmrg slice->edge1.dx = floor((dx * 32768) / scale + .5); 40335c4bbdfSmrg slice->edge1.dy = floor((dy * 32768) / scale + .5); 40435c4bbdfSmrg } 40535c4bbdfSmrg if (!slice->edge1.dy) { 40635c4bbdfSmrg if (signdx < 0) { 40735c4bbdfSmrg y = floor(y1 + 1.0); 40835c4bbdfSmrg if (y >= 0) { 40935c4bbdfSmrg slice->min_top_y = y; 41035c4bbdfSmrg slice->min_bot_y = arc->height; 41135c4bbdfSmrg } 41235c4bbdfSmrg else { 41335c4bbdfSmrg slice->max_bot_y = -y - (arc->height & 1); 41435c4bbdfSmrg } 41535c4bbdfSmrg } 41635c4bbdfSmrg else { 41735c4bbdfSmrg y = floor(y1); 41835c4bbdfSmrg if (y >= 0) 41935c4bbdfSmrg slice->max_top_y = y; 42035c4bbdfSmrg else { 42135c4bbdfSmrg slice->min_top_y = arc->height; 42235c4bbdfSmrg slice->min_bot_y = -y - (arc->height & 1); 42335c4bbdfSmrg } 42435c4bbdfSmrg } 42535c4bbdfSmrg slice->edge1_top = TRUE; 42635c4bbdfSmrg slice->edge1.x = 65536; 42735c4bbdfSmrg slice->edge1.stepx = 0; 42835c4bbdfSmrg slice->edge1.e = 0; 42935c4bbdfSmrg slice->edge1.dx = -1; 43035c4bbdfSmrg slice->edge2 = slice->edge1; 43135c4bbdfSmrg slice->edge2_top = FALSE; 43235c4bbdfSmrg } 43335c4bbdfSmrg else if (!slice->edge1.dx) { 43435c4bbdfSmrg if (signdy < 0) 43535c4bbdfSmrg x1 -= 1.0; 43635c4bbdfSmrg slice->edge1.x = ceil(x1); 43735c4bbdfSmrg slice->edge1_top = signdy < 0; 43835c4bbdfSmrg slice->edge1.x += arc->x + (arc->width >> 1); 43935c4bbdfSmrg slice->edge1.stepx = 0; 44035c4bbdfSmrg slice->edge1.e = 0; 44135c4bbdfSmrg slice->edge1.dx = -1; 44235c4bbdfSmrg slice->edge2_top = !slice->edge1_top; 44335c4bbdfSmrg slice->edge2 = slice->edge1; 44435c4bbdfSmrg } 44535c4bbdfSmrg else { 44635c4bbdfSmrg if (signdx < 0) 44735c4bbdfSmrg slice->edge1.dx = -slice->edge1.dx; 44835c4bbdfSmrg if (signdy < 0) 44935c4bbdfSmrg slice->edge1.dx = -slice->edge1.dx; 45035c4bbdfSmrg k = ceil(((x1 + x2) * slice->edge1.dy - 45135c4bbdfSmrg (y1 + y2) * slice->edge1.dx) / 2.0); 45235c4bbdfSmrg slice->edge2.dx = slice->edge1.dx; 45335c4bbdfSmrg slice->edge2.dy = slice->edge1.dy; 45435c4bbdfSmrg slice->edge1_top = signdy < 0; 45535c4bbdfSmrg slice->edge2_top = !slice->edge1_top; 45635c4bbdfSmrg miGetArcEdge(arc, &slice->edge1, k, 45735c4bbdfSmrg slice->edge1_top, !slice->edge1_top); 45835c4bbdfSmrg miGetArcEdge(arc, &slice->edge2, k, 45935c4bbdfSmrg slice->edge2_top, slice->edge2_top); 46035c4bbdfSmrg } 46105b261ecSmrg } 46205b261ecSmrg} 46305b261ecSmrg 46405b261ecSmrg#define ADDSPANS() \ 46505b261ecSmrg pts->x = xorg - x; \ 46605b261ecSmrg pts->y = yorg - y; \ 46705b261ecSmrg *wids = slw; \ 46805b261ecSmrg pts++; \ 46905b261ecSmrg wids++; \ 47005b261ecSmrg if (miFillArcLower(slw)) \ 47105b261ecSmrg { \ 47205b261ecSmrg pts->x = xorg - x; \ 47305b261ecSmrg pts->y = yorg + y + dy; \ 47405b261ecSmrg pts++; \ 47505b261ecSmrg *wids++ = slw; \ 47605b261ecSmrg } 47705b261ecSmrg 47835c4bbdfSmrgstatic int 47935c4bbdfSmrgmiFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths) 48005b261ecSmrg{ 48105b261ecSmrg int x, y, e; 48205b261ecSmrg int yk, xk, ym, xm, dx, dy, xorg, yorg; 48305b261ecSmrg int slw; 48405b261ecSmrg miFillArcRec info; 48505b261ecSmrg DDXPointPtr pts; 48605b261ecSmrg int *wids; 48705b261ecSmrg 48805b261ecSmrg miFillArcSetup(arc, &info); 48905b261ecSmrg MIFILLARCSETUP(); 49035c4bbdfSmrg if (pGC->miTranslate) { 49135c4bbdfSmrg xorg += pDraw->x; 49235c4bbdfSmrg yorg += pDraw->y; 49305b261ecSmrg } 49405b261ecSmrg pts = points; 49505b261ecSmrg wids = widths; 49635c4bbdfSmrg while (y > 0) { 49735c4bbdfSmrg MIFILLARCSTEP(slw); 49835c4bbdfSmrg ADDSPANS(); 49905b261ecSmrg } 50035c4bbdfSmrg return pts - points; 50105b261ecSmrg} 50205b261ecSmrg 50335c4bbdfSmrgstatic int 50435c4bbdfSmrgmiFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths) 50505b261ecSmrg{ 50605b261ecSmrg int x, y; 50705b261ecSmrg int xorg, yorg, dx, dy, slw; 50805b261ecSmrg double e, yk, xk, ym, xm; 50905b261ecSmrg miFillArcDRec info; 51005b261ecSmrg DDXPointPtr pts; 51105b261ecSmrg int *wids; 51205b261ecSmrg 51305b261ecSmrg miFillArcDSetup(arc, &info); 51405b261ecSmrg MIFILLARCSETUP(); 51535c4bbdfSmrg if (pGC->miTranslate) { 51635c4bbdfSmrg xorg += pDraw->x; 51735c4bbdfSmrg yorg += pDraw->y; 51805b261ecSmrg } 51905b261ecSmrg pts = points; 52005b261ecSmrg wids = widths; 52135c4bbdfSmrg while (y > 0) { 52235c4bbdfSmrg MIFILLARCSTEP(slw); 52335c4bbdfSmrg ADDSPANS(); 52405b261ecSmrg } 52535c4bbdfSmrg return pts - points; 52605b261ecSmrg} 52705b261ecSmrg 52805b261ecSmrg#define ADDSPAN(l,r) \ 52905b261ecSmrg if (r >= l) \ 53005b261ecSmrg { \ 53105b261ecSmrg pts->x = l; \ 53205b261ecSmrg pts->y = ya; \ 53305b261ecSmrg pts++; \ 53405b261ecSmrg *wids++ = r - l + 1; \ 53505b261ecSmrg } 53605b261ecSmrg 53705b261ecSmrg#define ADDSLICESPANS(flip) \ 53805b261ecSmrg if (!flip) \ 53905b261ecSmrg { \ 54005b261ecSmrg ADDSPAN(xl, xr); \ 54105b261ecSmrg } \ 54205b261ecSmrg else \ 54305b261ecSmrg { \ 54405b261ecSmrg xc = xorg - x; \ 54505b261ecSmrg ADDSPAN(xc, xr); \ 54605b261ecSmrg xc += slw - 1; \ 54705b261ecSmrg ADDSPAN(xl, xc); \ 54805b261ecSmrg } 54905b261ecSmrg 55035c4bbdfSmrgstatic int 55135c4bbdfSmrgmiFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths) 55205b261ecSmrg{ 55305b261ecSmrg int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; 55405b261ecSmrg int x, y, e; 55505b261ecSmrg miFillArcRec info; 55605b261ecSmrg miArcSliceRec slice; 55705b261ecSmrg int ya, xl, xr, xc; 55805b261ecSmrg DDXPointPtr pts; 55905b261ecSmrg int *wids; 56005b261ecSmrg 56105b261ecSmrg miFillArcSetup(arc, &info); 56205b261ecSmrg miFillArcSliceSetup(arc, &slice, pGC); 56305b261ecSmrg MIFILLARCSETUP(); 56405b261ecSmrg slw = arc->height; 56505b261ecSmrg if (slice.flip_top || slice.flip_bot) 56635c4bbdfSmrg slw += (arc->height >> 1) + 1; 56735c4bbdfSmrg if (pGC->miTranslate) { 56835c4bbdfSmrg xorg += pDraw->x; 56935c4bbdfSmrg yorg += pDraw->y; 57035c4bbdfSmrg slice.edge1.x += pDraw->x; 57135c4bbdfSmrg slice.edge2.x += pDraw->x; 57205b261ecSmrg } 57305b261ecSmrg pts = points; 57405b261ecSmrg wids = widths; 57535c4bbdfSmrg while (y > 0) { 57635c4bbdfSmrg MIFILLARCSTEP(slw); 57735c4bbdfSmrg MIARCSLICESTEP(slice.edge1); 57835c4bbdfSmrg MIARCSLICESTEP(slice.edge2); 57935c4bbdfSmrg if (miFillSliceUpper(slice)) { 58035c4bbdfSmrg ya = yorg - y; 58135c4bbdfSmrg MIARCSLICEUPPER(xl, xr, slice, slw); 58235c4bbdfSmrg ADDSLICESPANS(slice.flip_top); 58335c4bbdfSmrg } 58435c4bbdfSmrg if (miFillSliceLower(slice)) { 58535c4bbdfSmrg ya = yorg + y + dy; 58635c4bbdfSmrg MIARCSLICELOWER(xl, xr, slice, slw); 58735c4bbdfSmrg ADDSLICESPANS(slice.flip_bot); 58835c4bbdfSmrg } 58905b261ecSmrg } 59035c4bbdfSmrg return pts - points; 59105b261ecSmrg} 59205b261ecSmrg 59335c4bbdfSmrgstatic int 59435c4bbdfSmrgmiFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths) 59505b261ecSmrg{ 59605b261ecSmrg int x, y; 59705b261ecSmrg int dx, dy, xorg, yorg, slw; 59805b261ecSmrg double e, yk, xk, ym, xm; 59905b261ecSmrg miFillArcDRec info; 60005b261ecSmrg miArcSliceRec slice; 60105b261ecSmrg int ya, xl, xr, xc; 60205b261ecSmrg DDXPointPtr pts; 60305b261ecSmrg int *wids; 60405b261ecSmrg 60505b261ecSmrg miFillArcDSetup(arc, &info); 60605b261ecSmrg miFillArcSliceSetup(arc, &slice, pGC); 60705b261ecSmrg MIFILLARCSETUP(); 60805b261ecSmrg slw = arc->height; 60905b261ecSmrg if (slice.flip_top || slice.flip_bot) 61035c4bbdfSmrg slw += (arc->height >> 1) + 1; 61135c4bbdfSmrg if (pGC->miTranslate) { 61235c4bbdfSmrg xorg += pDraw->x; 61335c4bbdfSmrg yorg += pDraw->y; 61435c4bbdfSmrg slice.edge1.x += pDraw->x; 61535c4bbdfSmrg slice.edge2.x += pDraw->x; 61605b261ecSmrg } 61705b261ecSmrg pts = points; 61805b261ecSmrg wids = widths; 61935c4bbdfSmrg while (y > 0) { 62035c4bbdfSmrg MIFILLARCSTEP(slw); 62135c4bbdfSmrg MIARCSLICESTEP(slice.edge1); 62235c4bbdfSmrg MIARCSLICESTEP(slice.edge2); 62335c4bbdfSmrg if (miFillSliceUpper(slice)) { 62435c4bbdfSmrg ya = yorg - y; 62535c4bbdfSmrg MIARCSLICEUPPER(xl, xr, slice, slw); 62635c4bbdfSmrg ADDSLICESPANS(slice.flip_top); 62735c4bbdfSmrg } 62835c4bbdfSmrg if (miFillSliceLower(slice)) { 62935c4bbdfSmrg ya = yorg + y + dy; 63035c4bbdfSmrg MIARCSLICELOWER(xl, xr, slice, slw); 63135c4bbdfSmrg ADDSLICESPANS(slice.flip_bot); 63235c4bbdfSmrg } 63305b261ecSmrg } 63435c4bbdfSmrg return pts - points; 63505b261ecSmrg} 63605b261ecSmrg 63705b261ecSmrg/* MIPOLYFILLARC -- The public entry for the PolyFillArc request. 63805b261ecSmrg * Since we don't have to worry about overlapping segments, we can just 63905b261ecSmrg * fill each arc as it comes. 64005b261ecSmrg */ 64135c4bbdfSmrg 64235c4bbdfSmrg/* Limit the number of spans in a single draw request to avoid integer 64335c4bbdfSmrg * overflow in the computation of the span buffer size. 64435c4bbdfSmrg */ 64535c4bbdfSmrg#define MAX_SPANS_PER_LOOP (4 * 1024 * 1024) 64635c4bbdfSmrg 6476747b715Smrgvoid 64835c4bbdfSmrgmiPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs_all, xArc * parcs) 64905b261ecSmrg{ 65035c4bbdfSmrg while (narcs_all > 0) { 65135c4bbdfSmrg int narcs; 65235c4bbdfSmrg int i; 65335c4bbdfSmrg xArc *arc; 65435c4bbdfSmrg int nspans = 0; 65535c4bbdfSmrg DDXPointPtr pts, points; 65635c4bbdfSmrg int *wids, *widths; 65735c4bbdfSmrg int n; 65835c4bbdfSmrg 65935c4bbdfSmrg for (narcs = 0, arc = parcs; narcs < narcs_all; narcs++, arc++) { 66035c4bbdfSmrg if (narcs && nspans + arc->height > MAX_SPANS_PER_LOOP) 66135c4bbdfSmrg break; 66235c4bbdfSmrg nspans += arc->height; 66335c4bbdfSmrg 66435c4bbdfSmrg /* A pie-slice arc may add another pile of spans */ 66535c4bbdfSmrg if (pGC->arcMode == ArcPieSlice && 66635c4bbdfSmrg (-FULLCIRCLE < arc->angle2 && arc->angle2 < FULLCIRCLE)) 66735c4bbdfSmrg nspans += (arc->height + 1) >> 1; 66835c4bbdfSmrg } 66935c4bbdfSmrg 67035c4bbdfSmrg pts = points = malloc (sizeof (DDXPointRec) * nspans + 67135c4bbdfSmrg sizeof(int) * nspans); 67235c4bbdfSmrg if (points) { 67335c4bbdfSmrg wids = widths = (int *) (points + nspans); 67435c4bbdfSmrg 67535c4bbdfSmrg for (i = 0, arc = parcs; i < narcs; arc++, i++) { 67635c4bbdfSmrg if (miFillArcEmpty(arc)) 67735c4bbdfSmrg continue; 67835c4bbdfSmrg if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) 67935c4bbdfSmrg { 68035c4bbdfSmrg if (miCanFillArc(arc)) 68135c4bbdfSmrg n = miFillEllipseI(pDraw, pGC, arc, pts, wids); 68235c4bbdfSmrg else 68335c4bbdfSmrg n = miFillEllipseD(pDraw, pGC, arc, pts, wids); 68435c4bbdfSmrg } 68535c4bbdfSmrg else 68635c4bbdfSmrg { 68735c4bbdfSmrg if (miCanFillArc(arc)) 68835c4bbdfSmrg n = miFillArcSliceI(pDraw, pGC, arc, pts, wids); 68935c4bbdfSmrg else 69035c4bbdfSmrg n = miFillArcSliceD(pDraw, pGC, arc, pts, wids); 69135c4bbdfSmrg } 69235c4bbdfSmrg pts += n; 69335c4bbdfSmrg wids += n; 69435c4bbdfSmrg } 69535c4bbdfSmrg nspans = pts - points; 69635c4bbdfSmrg if (nspans) 69735c4bbdfSmrg (*pGC->ops->FillSpans) (pDraw, pGC, nspans, points, 69835c4bbdfSmrg widths, FALSE); 69935c4bbdfSmrg free (points); 70035c4bbdfSmrg } 70135c4bbdfSmrg parcs += narcs; 70235c4bbdfSmrg narcs_all -= narcs; 70305b261ecSmrg } 70405b261ecSmrg} 705