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/* Derived from: 3005b261ecSmrg * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" 3105b261ecSmrg * by M. L. V. Pitteway 3205b261ecSmrg * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 3305b261ecSmrg */ 3405b261ecSmrg 3505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3605b261ecSmrg#include <dix-config.h> 3705b261ecSmrg#endif 3805b261ecSmrg 3905b261ecSmrg#include <math.h> 4005b261ecSmrg#include <X11/X.h> 4105b261ecSmrg#include <X11/Xprotostr.h> 4205b261ecSmrg#include "regionstr.h" 4305b261ecSmrg#include "gcstruct.h" 4405b261ecSmrg#include "pixmapstr.h" 4505b261ecSmrg#include "mi.h" 4605b261ecSmrg#include "mizerarc.h" 4705b261ecSmrg 4805b261ecSmrg#define FULLCIRCLE (360 * 64) 4905b261ecSmrg#define OCTANT (45 * 64) 5005b261ecSmrg#define QUADRANT (90 * 64) 5105b261ecSmrg#define HALFCIRCLE (180 * 64) 5205b261ecSmrg#define QUADRANT3 (270 * 64) 5305b261ecSmrg 5405b261ecSmrg#ifndef M_PI 5505b261ecSmrg#define M_PI 3.14159265358979323846 5605b261ecSmrg#endif 5705b261ecSmrg 5805b261ecSmrg#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \ 5905b261ecSmrg ((d) == HALFCIRCLE ? 0.0 : \ 6005b261ecSmrg ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0)))))) 6105b261ecSmrg 6205b261ecSmrg#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \ 6305b261ecSmrg ((d) == HALFCIRCLE ? -1.0 : \ 6405b261ecSmrg ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0)))))) 6505b261ecSmrg 6605b261ecSmrg#define EPSILON45 64 6705b261ecSmrg 6805b261ecSmrgtypedef struct { 6905b261ecSmrg int skipStart; 7005b261ecSmrg int haveStart; 7105b261ecSmrg DDXPointRec startPt; 7205b261ecSmrg int haveLast; 7305b261ecSmrg int skipLast; 7405b261ecSmrg DDXPointRec endPt; 7505b261ecSmrg int dashIndex; 7605b261ecSmrg int dashOffset; 7705b261ecSmrg int dashIndexInit; 7805b261ecSmrg int dashOffsetInit; 7905b261ecSmrg} DashInfo; 8005b261ecSmrg 8135c4bbdfSmrgstatic miZeroArcPtRec oob = { 65536, 65536, 0 }; 8205b261ecSmrg 8305b261ecSmrg/* 8405b261ecSmrg * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1 8505b261ecSmrg * 8605b261ecSmrg * where l is either 0 or .5 8705b261ecSmrg * 8805b261ecSmrg * alpha = 4(W^2) 8905b261ecSmrg * beta = 4(H^2) 9005b261ecSmrg * gamma = 0 9105b261ecSmrg * u = 2(W^2)H 9205b261ecSmrg * v = 4(H^2)l 9305b261ecSmrg * k = -4(H^2)(l^2) 9405b261ecSmrg * 9505b261ecSmrg */ 9605b261ecSmrg 976747b715SmrgBool 9835c4bbdfSmrgmiZeroArcSetup(xArc * arc, miZeroArcRec * info, Bool ok360) 9905b261ecSmrg{ 10005b261ecSmrg int l; 10105b261ecSmrg int angle1, angle2; 10205b261ecSmrg int startseg, endseg; 10305b261ecSmrg int startAngle, endAngle; 10405b261ecSmrg int i, overlap; 10505b261ecSmrg miZeroArcPtRec start, end; 10605b261ecSmrg 10705b261ecSmrg l = arc->width & 1; 10835c4bbdfSmrg if (arc->width == arc->height) { 10935c4bbdfSmrg info->alpha = 4; 11035c4bbdfSmrg info->beta = 4; 11135c4bbdfSmrg info->k1 = -8; 11235c4bbdfSmrg info->k3 = -16; 11335c4bbdfSmrg info->b = 12; 11435c4bbdfSmrg info->a = (arc->width << 2) - 12; 11535c4bbdfSmrg info->d = 17 - (arc->width << 1); 11635c4bbdfSmrg if (l) { 11735c4bbdfSmrg info->b -= 4; 11835c4bbdfSmrg info->a += 4; 11935c4bbdfSmrg info->d -= 7; 12035c4bbdfSmrg } 12135c4bbdfSmrg } 12235c4bbdfSmrg else if (!arc->width || !arc->height) { 12335c4bbdfSmrg info->alpha = 0; 12435c4bbdfSmrg info->beta = 0; 12535c4bbdfSmrg info->k1 = 0; 12635c4bbdfSmrg info->k3 = 0; 12735c4bbdfSmrg info->a = -(int) arc->height; 12835c4bbdfSmrg info->b = 0; 12935c4bbdfSmrg info->d = -1; 13035c4bbdfSmrg } 13135c4bbdfSmrg else { 13235c4bbdfSmrg /* initial conditions */ 13335c4bbdfSmrg info->alpha = (arc->width * arc->width) << 2; 13435c4bbdfSmrg info->beta = (arc->height * arc->height) << 2; 13535c4bbdfSmrg info->k1 = info->beta << 1; 13635c4bbdfSmrg info->k3 = info->k1 + (info->alpha << 1); 13735c4bbdfSmrg info->b = l ? 0 : -info->beta; 13835c4bbdfSmrg info->a = info->alpha * arc->height; 13935c4bbdfSmrg info->d = info->b - (info->a >> 1) - (info->alpha >> 2); 14035c4bbdfSmrg if (l) 14135c4bbdfSmrg info->d -= info->beta >> 2; 14235c4bbdfSmrg info->a -= info->b; 14335c4bbdfSmrg /* take first step, d < 0 always */ 14435c4bbdfSmrg info->b -= info->k1; 14535c4bbdfSmrg info->a += info->k1; 14635c4bbdfSmrg info->d += info->b; 14735c4bbdfSmrg /* octant change, b < 0 always */ 14835c4bbdfSmrg info->k1 = -info->k1; 14935c4bbdfSmrg info->k3 = -info->k3; 15035c4bbdfSmrg info->b = -info->b; 15135c4bbdfSmrg info->d = info->b - info->a - info->d; 15235c4bbdfSmrg info->a = info->a - (info->b << 1); 15305b261ecSmrg } 15405b261ecSmrg info->dx = 1; 15505b261ecSmrg info->dy = 0; 15605b261ecSmrg info->w = (arc->width + 1) >> 1; 15705b261ecSmrg info->h = arc->height >> 1; 15805b261ecSmrg info->xorg = arc->x + (arc->width >> 1); 15905b261ecSmrg info->yorg = arc->y; 16005b261ecSmrg info->xorgo = info->xorg + l; 16105b261ecSmrg info->yorgo = info->yorg + arc->height; 16235c4bbdfSmrg if (!arc->width) { 16335c4bbdfSmrg if (!arc->height) { 16435c4bbdfSmrg info->x = 0; 16535c4bbdfSmrg info->y = 0; 16635c4bbdfSmrg info->initialMask = 0; 16735c4bbdfSmrg info->startAngle = 0; 16835c4bbdfSmrg info->endAngle = 0; 16935c4bbdfSmrg info->start = oob; 17035c4bbdfSmrg info->end = oob; 17135c4bbdfSmrg return FALSE; 17235c4bbdfSmrg } 17335c4bbdfSmrg info->x = 0; 17435c4bbdfSmrg info->y = 1; 17535c4bbdfSmrg } 17635c4bbdfSmrg else { 17735c4bbdfSmrg info->x = 1; 17835c4bbdfSmrg info->y = 0; 17905b261ecSmrg } 18005b261ecSmrg angle1 = arc->angle1; 18105b261ecSmrg angle2 = arc->angle2; 18235c4bbdfSmrg if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) { 18335c4bbdfSmrg startAngle = 0; 18435c4bbdfSmrg endAngle = 0; 18535c4bbdfSmrg } 18635c4bbdfSmrg else { 18735c4bbdfSmrg if (angle2 > FULLCIRCLE) 18835c4bbdfSmrg angle2 = FULLCIRCLE; 18935c4bbdfSmrg else if (angle2 < -FULLCIRCLE) 19035c4bbdfSmrg angle2 = -FULLCIRCLE; 19135c4bbdfSmrg if (angle2 < 0) { 19235c4bbdfSmrg startAngle = angle1 + angle2; 19335c4bbdfSmrg endAngle = angle1; 19435c4bbdfSmrg } 19535c4bbdfSmrg else { 19635c4bbdfSmrg startAngle = angle1; 19735c4bbdfSmrg endAngle = angle1 + angle2; 19835c4bbdfSmrg } 19935c4bbdfSmrg if (startAngle < 0) 20035c4bbdfSmrg startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; 20135c4bbdfSmrg if (startAngle >= FULLCIRCLE) 20235c4bbdfSmrg startAngle = startAngle % FULLCIRCLE; 20335c4bbdfSmrg if (endAngle < 0) 20435c4bbdfSmrg endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; 20535c4bbdfSmrg if (endAngle >= FULLCIRCLE) 20635c4bbdfSmrg endAngle = endAngle % FULLCIRCLE; 20705b261ecSmrg } 20805b261ecSmrg info->startAngle = startAngle; 20905b261ecSmrg info->endAngle = endAngle; 21005b261ecSmrg if (ok360 && (startAngle == endAngle) && arc->angle2 && 21135c4bbdfSmrg arc->width && arc->height) { 21235c4bbdfSmrg info->initialMask = 0xf; 21335c4bbdfSmrg info->start = oob; 21435c4bbdfSmrg info->end = oob; 21535c4bbdfSmrg return TRUE; 21605b261ecSmrg } 21705b261ecSmrg startseg = startAngle / OCTANT; 21835c4bbdfSmrg if (!arc->height || (((startseg + 1) & 2) && arc->width)) { 21935c4bbdfSmrg start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0); 22035c4bbdfSmrg if (start.x < 0) 22135c4bbdfSmrg start.x = -start.x; 22235c4bbdfSmrg start.y = -1; 22335c4bbdfSmrg } 22435c4bbdfSmrg else { 22535c4bbdfSmrg start.y = Dsin(startAngle) * (arc->height / 2.0); 22635c4bbdfSmrg if (start.y < 0) 22735c4bbdfSmrg start.y = -start.y; 22835c4bbdfSmrg start.y = info->h - start.y; 22935c4bbdfSmrg start.x = 65536; 23005b261ecSmrg } 23105b261ecSmrg endseg = endAngle / OCTANT; 23235c4bbdfSmrg if (!arc->height || (((endseg + 1) & 2) && arc->width)) { 23335c4bbdfSmrg end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0); 23435c4bbdfSmrg if (end.x < 0) 23535c4bbdfSmrg end.x = -end.x; 23635c4bbdfSmrg end.y = -1; 23735c4bbdfSmrg } 23835c4bbdfSmrg else { 23935c4bbdfSmrg end.y = Dsin(endAngle) * (arc->height / 2.0); 24035c4bbdfSmrg if (end.y < 0) 24135c4bbdfSmrg end.y = -end.y; 24235c4bbdfSmrg end.y = info->h - end.y; 24335c4bbdfSmrg end.x = 65536; 24405b261ecSmrg } 24505b261ecSmrg info->firstx = start.x; 24605b261ecSmrg info->firsty = start.y; 24705b261ecSmrg info->initialMask = 0; 24805b261ecSmrg overlap = arc->angle2 && (endAngle <= startAngle); 24935c4bbdfSmrg for (i = 0; i < 4; i++) { 25035c4bbdfSmrg if (overlap ? 25135c4bbdfSmrg ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) : 25235c4bbdfSmrg ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle))) 25335c4bbdfSmrg info->initialMask |= (1 << i); 25405b261ecSmrg } 25505b261ecSmrg start.mask = info->initialMask; 25605b261ecSmrg end.mask = info->initialMask; 25705b261ecSmrg startseg >>= 1; 25805b261ecSmrg endseg >>= 1; 25905b261ecSmrg overlap = overlap && (endseg == startseg); 26035c4bbdfSmrg if (start.x != end.x || start.y != end.y || !overlap) { 26135c4bbdfSmrg if (startseg & 1) { 26235c4bbdfSmrg if (!overlap) 26335c4bbdfSmrg info->initialMask &= ~(1 << startseg); 26435c4bbdfSmrg if (start.x > end.x || start.y > end.y) 26535c4bbdfSmrg end.mask &= ~(1 << startseg); 26635c4bbdfSmrg } 26735c4bbdfSmrg else { 26835c4bbdfSmrg start.mask &= ~(1 << startseg); 26935c4bbdfSmrg if (((start.x < end.x || start.y < end.y) || 27035c4bbdfSmrg (start.x == end.x && start.y == end.y && (endseg & 1))) && 27135c4bbdfSmrg !overlap) 27235c4bbdfSmrg end.mask &= ~(1 << startseg); 27335c4bbdfSmrg } 27435c4bbdfSmrg if (endseg & 1) { 27535c4bbdfSmrg end.mask &= ~(1 << endseg); 27635c4bbdfSmrg if (((start.x > end.x || start.y > end.y) || 27735c4bbdfSmrg (start.x == end.x && start.y == end.y && !(startseg & 1))) && 27835c4bbdfSmrg !overlap) 27935c4bbdfSmrg start.mask &= ~(1 << endseg); 28035c4bbdfSmrg } 28135c4bbdfSmrg else { 28235c4bbdfSmrg if (!overlap) 28335c4bbdfSmrg info->initialMask &= ~(1 << endseg); 28435c4bbdfSmrg if (start.x < end.x || start.y < end.y) 28535c4bbdfSmrg start.mask &= ~(1 << endseg); 28635c4bbdfSmrg } 28705b261ecSmrg } 28805b261ecSmrg /* take care of case when start and stop are both near 45 */ 28905b261ecSmrg /* handle here rather than adding extra code to pixelization loops */ 29005b261ecSmrg if (startAngle && 29135c4bbdfSmrg ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) { 29235c4bbdfSmrg i = (startAngle + OCTANT) % OCTANT; 29335c4bbdfSmrg if (i < EPSILON45 || i > OCTANT - EPSILON45) { 29435c4bbdfSmrg i = (endAngle + OCTANT) % OCTANT; 29535c4bbdfSmrg if (i < EPSILON45 || i > OCTANT - EPSILON45) { 29635c4bbdfSmrg if (start.y < 0) { 29735c4bbdfSmrg i = Dsin(startAngle) * (arc->height / 2.0); 29835c4bbdfSmrg if (i < 0) 29935c4bbdfSmrg i = -i; 30035c4bbdfSmrg if (info->h - i == end.y) 30135c4bbdfSmrg start.mask = end.mask; 30235c4bbdfSmrg } 30335c4bbdfSmrg else { 30435c4bbdfSmrg i = Dsin(endAngle) * (arc->height / 2.0); 30535c4bbdfSmrg if (i < 0) 30635c4bbdfSmrg i = -i; 30735c4bbdfSmrg if (info->h - i == start.y) 30835c4bbdfSmrg end.mask = start.mask; 30935c4bbdfSmrg } 31035c4bbdfSmrg } 31135c4bbdfSmrg } 31235c4bbdfSmrg } 31335c4bbdfSmrg if (startseg & 1) { 31435c4bbdfSmrg info->start = start; 31535c4bbdfSmrg info->end = oob; 31635c4bbdfSmrg } 31735c4bbdfSmrg else { 31835c4bbdfSmrg info->end = start; 31935c4bbdfSmrg info->start = oob; 32035c4bbdfSmrg } 32135c4bbdfSmrg if (endseg & 1) { 32235c4bbdfSmrg info->altend = end; 32335c4bbdfSmrg if (info->altend.x < info->end.x || info->altend.y < info->end.y) { 32435c4bbdfSmrg miZeroArcPtRec tmp; 32535c4bbdfSmrg 32635c4bbdfSmrg tmp = info->altend; 32735c4bbdfSmrg info->altend = info->end; 32835c4bbdfSmrg info->end = tmp; 32935c4bbdfSmrg } 33035c4bbdfSmrg info->altstart = oob; 33135c4bbdfSmrg } 33235c4bbdfSmrg else { 33335c4bbdfSmrg info->altstart = end; 33435c4bbdfSmrg if (info->altstart.x < info->start.x || 33535c4bbdfSmrg info->altstart.y < info->start.y) { 33635c4bbdfSmrg miZeroArcPtRec tmp; 33735c4bbdfSmrg 33835c4bbdfSmrg tmp = info->altstart; 33935c4bbdfSmrg info->altstart = info->start; 34035c4bbdfSmrg info->start = tmp; 34135c4bbdfSmrg } 34235c4bbdfSmrg info->altend = oob; 34335c4bbdfSmrg } 34435c4bbdfSmrg if (!info->start.x || !info->start.y) { 34535c4bbdfSmrg info->initialMask = info->start.mask; 34635c4bbdfSmrg info->start = info->altstart; 34735c4bbdfSmrg } 34835c4bbdfSmrg if (!arc->width && (arc->height == 1)) { 34935c4bbdfSmrg /* kludge! */ 35035c4bbdfSmrg info->initialMask |= info->end.mask; 35135c4bbdfSmrg info->initialMask |= info->initialMask << 1; 35235c4bbdfSmrg info->end.x = 0; 35335c4bbdfSmrg info->end.mask = 0; 35405b261ecSmrg } 35505b261ecSmrg return FALSE; 35605b261ecSmrg} 35705b261ecSmrg 35805b261ecSmrg#define Pixelate(xval,yval) \ 35905b261ecSmrg { \ 36005b261ecSmrg pts->x = xval; \ 36105b261ecSmrg pts->y = yval; \ 36205b261ecSmrg pts++; \ 36305b261ecSmrg } 36405b261ecSmrg 36505b261ecSmrg#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval); 36605b261ecSmrg 36705b261ecSmrgstatic DDXPointPtr 36835c4bbdfSmrgmiZeroArcPts(xArc * arc, DDXPointPtr pts) 36905b261ecSmrg{ 37005b261ecSmrg miZeroArcRec info; 37105b261ecSmrg int x, y, a, b, d, mask; 37205b261ecSmrg int k1, k3, dx, dy; 37305b261ecSmrg Bool do360; 37405b261ecSmrg 37505b261ecSmrg do360 = miZeroArcSetup(arc, &info, TRUE); 37605b261ecSmrg MIARCSETUP(); 37705b261ecSmrg mask = info.initialMask; 37835c4bbdfSmrg if (!(arc->width & 1)) { 37935c4bbdfSmrg DoPix(1, info.xorgo, info.yorg); 38035c4bbdfSmrg DoPix(3, info.xorgo, info.yorgo); 38135c4bbdfSmrg } 38235c4bbdfSmrg if (!info.end.x || !info.end.y) { 38335c4bbdfSmrg mask = info.end.mask; 38435c4bbdfSmrg info.end = info.altend; 38535c4bbdfSmrg } 38635c4bbdfSmrg if (do360 && (arc->width == arc->height) && !(arc->width & 1)) { 38735c4bbdfSmrg int yorgh = info.yorg + info.h; 38835c4bbdfSmrg int xorghp = info.xorg + info.h; 38935c4bbdfSmrg int xorghn = info.xorg - info.h; 39035c4bbdfSmrg 39135c4bbdfSmrg while (1) { 39235c4bbdfSmrg Pixelate(info.xorg + x, info.yorg + y); 39335c4bbdfSmrg Pixelate(info.xorg - x, info.yorg + y); 39435c4bbdfSmrg Pixelate(info.xorg - x, info.yorgo - y); 39535c4bbdfSmrg Pixelate(info.xorg + x, info.yorgo - y); 39635c4bbdfSmrg if (a < 0) 39735c4bbdfSmrg break; 39835c4bbdfSmrg Pixelate(xorghp - y, yorgh - x); 39935c4bbdfSmrg Pixelate(xorghn + y, yorgh - x); 40035c4bbdfSmrg Pixelate(xorghn + y, yorgh + x); 40135c4bbdfSmrg Pixelate(xorghp - y, yorgh + x); 40235c4bbdfSmrg MIARCCIRCLESTEP(; 40335c4bbdfSmrg ); 40435c4bbdfSmrg } 40535c4bbdfSmrg if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y) 40635c4bbdfSmrg pts -= 4; 40735c4bbdfSmrg x = info.w; 40835c4bbdfSmrg y = info.h; 40935c4bbdfSmrg } 41035c4bbdfSmrg else if (do360) { 41135c4bbdfSmrg while (y < info.h || x < info.w) { 41235c4bbdfSmrg MIARCOCTANTSHIFT(; 41335c4bbdfSmrg ); 41435c4bbdfSmrg Pixelate(info.xorg + x, info.yorg + y); 41535c4bbdfSmrg Pixelate(info.xorgo - x, info.yorg + y); 41635c4bbdfSmrg Pixelate(info.xorgo - x, info.yorgo - y); 41735c4bbdfSmrg Pixelate(info.xorg + x, info.yorgo - y); 41835c4bbdfSmrg MIARCSTEP(; 41935c4bbdfSmrg ,; 42035c4bbdfSmrg ); 42135c4bbdfSmrg } 42235c4bbdfSmrg } 42335c4bbdfSmrg else { 42435c4bbdfSmrg while (y < info.h || x < info.w) { 42535c4bbdfSmrg MIARCOCTANTSHIFT(; 42635c4bbdfSmrg ); 42735c4bbdfSmrg if ((x == info.start.x) || (y == info.start.y)) { 42835c4bbdfSmrg mask = info.start.mask; 42935c4bbdfSmrg info.start = info.altstart; 43035c4bbdfSmrg } 43135c4bbdfSmrg DoPix(0, info.xorg + x, info.yorg + y); 43235c4bbdfSmrg DoPix(1, info.xorgo - x, info.yorg + y); 43335c4bbdfSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 43435c4bbdfSmrg DoPix(3, info.xorg + x, info.yorgo - y); 43535c4bbdfSmrg if ((x == info.end.x) || (y == info.end.y)) { 43635c4bbdfSmrg mask = info.end.mask; 43735c4bbdfSmrg info.end = info.altend; 43835c4bbdfSmrg } 43935c4bbdfSmrg MIARCSTEP(; 44035c4bbdfSmrg ,; 44135c4bbdfSmrg ); 44235c4bbdfSmrg } 44305b261ecSmrg } 44405b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 44535c4bbdfSmrg mask = info.start.mask; 44605b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 44705b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 44835c4bbdfSmrg if (arc->height & 1) { 44935c4bbdfSmrg DoPix(1, info.xorgo - x, info.yorg + y); 45035c4bbdfSmrg DoPix(3, info.xorg + x, info.yorgo - y); 45105b261ecSmrg } 45205b261ecSmrg return pts; 45305b261ecSmrg} 45405b261ecSmrg 45505b261ecSmrg#undef DoPix 45605b261ecSmrg#define DoPix(idx,xval,yval) \ 45705b261ecSmrg if (mask & (1 << idx)) \ 45805b261ecSmrg { \ 45905b261ecSmrg arcPts[idx]->x = xval; \ 46005b261ecSmrg arcPts[idx]->y = yval; \ 46105b261ecSmrg arcPts[idx]++; \ 46205b261ecSmrg } 46305b261ecSmrg 46405b261ecSmrgstatic void 46535c4bbdfSmrgmiZeroArcDashPts(GCPtr pGC, 46635c4bbdfSmrg xArc * arc, 46735c4bbdfSmrg DashInfo * dinfo, 46835c4bbdfSmrg DDXPointPtr points, 46935c4bbdfSmrg int maxPts, DDXPointPtr * evenPts, DDXPointPtr * oddPts) 47005b261ecSmrg{ 47105b261ecSmrg miZeroArcRec info; 47205b261ecSmrg int x, y, a, b, d, mask; 47305b261ecSmrg int k1, k3, dx, dy; 47405b261ecSmrg int dashRemaining; 47505b261ecSmrg DDXPointPtr arcPts[4]; 47605b261ecSmrg DDXPointPtr startPts[5], endPts[5]; 47705b261ecSmrg int deltas[5]; 47805b261ecSmrg DDXPointPtr startPt, pt, lastPt, pts; 47905b261ecSmrg int i, j, delta, ptsdelta, seg, startseg; 48005b261ecSmrg 48105b261ecSmrg for (i = 0; i < 4; i++) 48235c4bbdfSmrg arcPts[i] = points + (i * maxPts); 48335c4bbdfSmrg (void) miZeroArcSetup(arc, &info, FALSE); 48405b261ecSmrg MIARCSETUP(); 48505b261ecSmrg mask = info.initialMask; 48605b261ecSmrg startseg = info.startAngle / QUADRANT; 48705b261ecSmrg startPt = arcPts[startseg]; 48835c4bbdfSmrg if (!(arc->width & 1)) { 48935c4bbdfSmrg DoPix(1, info.xorgo, info.yorg); 49035c4bbdfSmrg DoPix(3, info.xorgo, info.yorgo); 49135c4bbdfSmrg } 49235c4bbdfSmrg if (!info.end.x || !info.end.y) { 49335c4bbdfSmrg mask = info.end.mask; 49435c4bbdfSmrg info.end = info.altend; 49535c4bbdfSmrg } 49635c4bbdfSmrg while (y < info.h || x < info.w) { 49735c4bbdfSmrg MIARCOCTANTSHIFT(; 49835c4bbdfSmrg ); 49935c4bbdfSmrg if ((x == info.firstx) || (y == info.firsty)) 50035c4bbdfSmrg startPt = arcPts[startseg]; 50135c4bbdfSmrg if ((x == info.start.x) || (y == info.start.y)) { 50235c4bbdfSmrg mask = info.start.mask; 50335c4bbdfSmrg info.start = info.altstart; 50435c4bbdfSmrg } 50535c4bbdfSmrg DoPix(0, info.xorg + x, info.yorg + y); 50635c4bbdfSmrg DoPix(1, info.xorgo - x, info.yorg + y); 50735c4bbdfSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 50835c4bbdfSmrg DoPix(3, info.xorg + x, info.yorgo - y); 50935c4bbdfSmrg if ((x == info.end.x) || (y == info.end.y)) { 51035c4bbdfSmrg mask = info.end.mask; 51135c4bbdfSmrg info.end = info.altend; 51235c4bbdfSmrg } 51335c4bbdfSmrg MIARCSTEP(; 51435c4bbdfSmrg ,; 51535c4bbdfSmrg ); 51605b261ecSmrg } 51705b261ecSmrg if ((x == info.firstx) || (y == info.firsty)) 51835c4bbdfSmrg startPt = arcPts[startseg]; 51905b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 52035c4bbdfSmrg mask = info.start.mask; 52105b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 52205b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 52335c4bbdfSmrg if (arc->height & 1) { 52435c4bbdfSmrg DoPix(1, info.xorgo - x, info.yorg + y); 52535c4bbdfSmrg DoPix(3, info.xorg + x, info.yorgo - y); 52635c4bbdfSmrg } 52735c4bbdfSmrg for (i = 0; i < 4; i++) { 52835c4bbdfSmrg seg = (startseg + i) & 3; 52935c4bbdfSmrg pt = points + (seg * maxPts); 53035c4bbdfSmrg if (seg & 1) { 53135c4bbdfSmrg startPts[i] = pt; 53235c4bbdfSmrg endPts[i] = arcPts[seg]; 53335c4bbdfSmrg deltas[i] = 1; 53435c4bbdfSmrg } 53535c4bbdfSmrg else { 53635c4bbdfSmrg startPts[i] = arcPts[seg] - 1; 53735c4bbdfSmrg endPts[i] = pt - 1; 53835c4bbdfSmrg deltas[i] = -1; 53935c4bbdfSmrg } 54005b261ecSmrg } 54105b261ecSmrg startPts[4] = startPts[0]; 54205b261ecSmrg endPts[4] = startPt; 54305b261ecSmrg startPts[0] = startPt; 54435c4bbdfSmrg if (startseg & 1) { 54535c4bbdfSmrg if (startPts[4] != endPts[4]) 54635c4bbdfSmrg endPts[4]--; 54735c4bbdfSmrg deltas[4] = 1; 54835c4bbdfSmrg } 54935c4bbdfSmrg else { 55035c4bbdfSmrg if (startPts[0] > startPts[4]) 55135c4bbdfSmrg startPts[0]--; 55235c4bbdfSmrg if (startPts[4] < endPts[4]) 55335c4bbdfSmrg endPts[4]--; 55435c4bbdfSmrg deltas[4] = -1; 55535c4bbdfSmrg } 55635c4bbdfSmrg if (arc->angle2 < 0) { 55735c4bbdfSmrg DDXPointPtr tmps, tmpe; 55835c4bbdfSmrg int tmpd; 55935c4bbdfSmrg 56035c4bbdfSmrg tmpd = deltas[0]; 56135c4bbdfSmrg tmps = startPts[0] - tmpd; 56235c4bbdfSmrg tmpe = endPts[0] - tmpd; 56335c4bbdfSmrg startPts[0] = endPts[4] - deltas[4]; 56435c4bbdfSmrg endPts[0] = startPts[4] - deltas[4]; 56535c4bbdfSmrg deltas[0] = -deltas[4]; 56635c4bbdfSmrg startPts[4] = tmpe; 56735c4bbdfSmrg endPts[4] = tmps; 56835c4bbdfSmrg deltas[4] = -tmpd; 56935c4bbdfSmrg tmpd = deltas[1]; 57035c4bbdfSmrg tmps = startPts[1] - tmpd; 57135c4bbdfSmrg tmpe = endPts[1] - tmpd; 57235c4bbdfSmrg startPts[1] = endPts[3] - deltas[3]; 57335c4bbdfSmrg endPts[1] = startPts[3] - deltas[3]; 57435c4bbdfSmrg deltas[1] = -deltas[3]; 57535c4bbdfSmrg startPts[3] = tmpe; 57635c4bbdfSmrg endPts[3] = tmps; 57735c4bbdfSmrg deltas[3] = -tmpd; 57835c4bbdfSmrg tmps = startPts[2] - deltas[2]; 57935c4bbdfSmrg startPts[2] = endPts[2] - deltas[2]; 58035c4bbdfSmrg endPts[2] = tmps; 58135c4bbdfSmrg deltas[2] = -deltas[2]; 58235c4bbdfSmrg } 58335c4bbdfSmrg for (i = 0; i < 5 && startPts[i] == endPts[i]; i++); 58405b261ecSmrg if (i == 5) 58535c4bbdfSmrg return; 58605b261ecSmrg pt = startPts[i]; 58735c4bbdfSmrg for (j = 4; startPts[j] == endPts[j]; j--); 58805b261ecSmrg lastPt = endPts[j] - deltas[j]; 58905b261ecSmrg if (dinfo->haveLast && 59035c4bbdfSmrg (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) { 59135c4bbdfSmrg startPts[i] += deltas[i]; 59205b261ecSmrg } 59335c4bbdfSmrg else { 59435c4bbdfSmrg dinfo->dashIndex = dinfo->dashIndexInit; 59535c4bbdfSmrg dinfo->dashOffset = dinfo->dashOffsetInit; 59605b261ecSmrg } 59735c4bbdfSmrg if (!dinfo->skipStart && (info.startAngle != info.endAngle)) { 59835c4bbdfSmrg dinfo->startPt = *pt; 59935c4bbdfSmrg dinfo->haveStart = TRUE; 60005b261ecSmrg } 60105b261ecSmrg else if (!dinfo->skipLast && dinfo->haveStart && 60235c4bbdfSmrg (lastPt->x == dinfo->startPt.x) && 60335c4bbdfSmrg (lastPt->y == dinfo->startPt.y) && (lastPt != startPts[i])) 60435c4bbdfSmrg endPts[j] = lastPt; 60535c4bbdfSmrg if (info.startAngle != info.endAngle) { 60635c4bbdfSmrg dinfo->haveLast = TRUE; 60735c4bbdfSmrg dinfo->endPt = *lastPt; 60805b261ecSmrg } 60905b261ecSmrg dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset; 61035c4bbdfSmrg for (i = 0; i < 5; i++) { 61135c4bbdfSmrg pt = startPts[i]; 61235c4bbdfSmrg lastPt = endPts[i]; 61335c4bbdfSmrg delta = deltas[i]; 61435c4bbdfSmrg while (pt != lastPt) { 61535c4bbdfSmrg if (dinfo->dashIndex & 1) { 61635c4bbdfSmrg pts = *oddPts; 61735c4bbdfSmrg ptsdelta = -1; 61835c4bbdfSmrg } 61935c4bbdfSmrg else { 62035c4bbdfSmrg pts = *evenPts; 62135c4bbdfSmrg ptsdelta = 1; 62235c4bbdfSmrg } 62335c4bbdfSmrg while ((pt != lastPt) && --dashRemaining >= 0) { 62435c4bbdfSmrg *pts = *pt; 62535c4bbdfSmrg pts += ptsdelta; 62635c4bbdfSmrg pt += delta; 62735c4bbdfSmrg } 62835c4bbdfSmrg if (dinfo->dashIndex & 1) 62935c4bbdfSmrg *oddPts = pts; 63035c4bbdfSmrg else 63135c4bbdfSmrg *evenPts = pts; 63235c4bbdfSmrg if (dashRemaining <= 0) { 63335c4bbdfSmrg if (++(dinfo->dashIndex) == pGC->numInDashList) 63435c4bbdfSmrg dinfo->dashIndex = 0; 63535c4bbdfSmrg dashRemaining = pGC->dash[dinfo->dashIndex]; 63635c4bbdfSmrg } 63735c4bbdfSmrg } 63805b261ecSmrg } 63905b261ecSmrg dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining; 64005b261ecSmrg} 64105b261ecSmrg 6426747b715Smrgvoid 64335c4bbdfSmrgmiZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs) 64405b261ecSmrg{ 64505b261ecSmrg int maxPts = 0; 64605b261ecSmrg int n, maxw = 0; 64705b261ecSmrg xArc *arc; 64805b261ecSmrg int i; 6496747b715Smrg DDXPointPtr points, pts, oddPts = NULL; 65005b261ecSmrg DDXPointPtr pt; 65105b261ecSmrg int numPts; 65205b261ecSmrg Bool dospans; 65305b261ecSmrg int *widths = NULL; 65405b261ecSmrg XID fgPixel = pGC->fgPixel; 65505b261ecSmrg DashInfo dinfo; 65605b261ecSmrg 65735c4bbdfSmrg for (arc = parcs, i = narcs; --i >= 0; arc++) { 65835c4bbdfSmrg if (!miCanZeroArc(arc)) 65935c4bbdfSmrg miWideArc(pDraw, pGC, 1, arc); 66035c4bbdfSmrg else { 66135c4bbdfSmrg if (arc->width > arc->height) 66235c4bbdfSmrg n = arc->width + (arc->height >> 1); 66335c4bbdfSmrg else 66435c4bbdfSmrg n = arc->height + (arc->width >> 1); 66535c4bbdfSmrg if (n > maxPts) 66635c4bbdfSmrg maxPts = n; 66735c4bbdfSmrg } 66805b261ecSmrg } 66905b261ecSmrg if (!maxPts) 67035c4bbdfSmrg return; 67105b261ecSmrg numPts = maxPts << 2; 67205b261ecSmrg dospans = (pGC->fillStyle != FillSolid); 67335c4bbdfSmrg if (dospans) { 67435c4bbdfSmrg widths = xallocarray(numPts, sizeof(int)); 67535c4bbdfSmrg if (!widths) 67635c4bbdfSmrg return; 67735c4bbdfSmrg maxw = 0; 67835c4bbdfSmrg } 67935c4bbdfSmrg if (pGC->lineStyle != LineSolid) { 68035c4bbdfSmrg numPts <<= 1; 68135c4bbdfSmrg dinfo.haveStart = FALSE; 68235c4bbdfSmrg dinfo.skipStart = FALSE; 68335c4bbdfSmrg dinfo.haveLast = FALSE; 68435c4bbdfSmrg dinfo.dashIndexInit = 0; 68535c4bbdfSmrg dinfo.dashOffsetInit = 0; 68635c4bbdfSmrg miStepDash((int) pGC->dashOffset, &dinfo.dashIndexInit, 68735c4bbdfSmrg (unsigned char *) pGC->dash, (int) pGC->numInDashList, 68835c4bbdfSmrg &dinfo.dashOffsetInit); 68935c4bbdfSmrg } 69035c4bbdfSmrg points = xallocarray(numPts, sizeof(DDXPointRec)); 69135c4bbdfSmrg if (!points) { 69235c4bbdfSmrg if (dospans) { 69335c4bbdfSmrg free(widths); 69435c4bbdfSmrg } 69535c4bbdfSmrg return; 69635c4bbdfSmrg } 69735c4bbdfSmrg for (arc = parcs, i = narcs; --i >= 0; arc++) { 69835c4bbdfSmrg if (miCanZeroArc(arc)) { 69935c4bbdfSmrg if (pGC->lineStyle == LineSolid) 70035c4bbdfSmrg pts = miZeroArcPts(arc, points); 70135c4bbdfSmrg else { 70235c4bbdfSmrg pts = points; 70335c4bbdfSmrg oddPts = &points[(numPts >> 1) - 1]; 70435c4bbdfSmrg dinfo.skipLast = i; 70535c4bbdfSmrg miZeroArcDashPts(pGC, arc, &dinfo, 70635c4bbdfSmrg oddPts + 1, maxPts, &pts, &oddPts); 70735c4bbdfSmrg dinfo.skipStart = TRUE; 70835c4bbdfSmrg } 70935c4bbdfSmrg n = pts - points; 71035c4bbdfSmrg if (!dospans) 71135c4bbdfSmrg (*pGC->ops->PolyPoint) (pDraw, pGC, CoordModeOrigin, n, points); 71235c4bbdfSmrg else { 71335c4bbdfSmrg if (n > maxw) { 71435c4bbdfSmrg while (maxw < n) 71535c4bbdfSmrg widths[maxw++] = 1; 71635c4bbdfSmrg } 71735c4bbdfSmrg if (pGC->miTranslate) { 71835c4bbdfSmrg for (pt = points; pt != pts; pt++) { 71935c4bbdfSmrg pt->x += pDraw->x; 72035c4bbdfSmrg pt->y += pDraw->y; 72135c4bbdfSmrg } 72235c4bbdfSmrg } 72335c4bbdfSmrg (*pGC->ops->FillSpans) (pDraw, pGC, n, points, widths, FALSE); 72435c4bbdfSmrg } 72535c4bbdfSmrg if (pGC->lineStyle != LineDoubleDash) 72635c4bbdfSmrg continue; 72735c4bbdfSmrg if ((pGC->fillStyle == FillSolid) || 72835c4bbdfSmrg (pGC->fillStyle == FillStippled)) { 72935c4bbdfSmrg ChangeGCVal gcval; 73035c4bbdfSmrg 73135c4bbdfSmrg gcval.val = pGC->bgPixel; 73235c4bbdfSmrg ChangeGC(NullClient, pGC, GCForeground, &gcval); 73335c4bbdfSmrg ValidateGC(pDraw, pGC); 73435c4bbdfSmrg } 73535c4bbdfSmrg pts = &points[numPts >> 1]; 73635c4bbdfSmrg oddPts++; 73735c4bbdfSmrg n = pts - oddPts; 73835c4bbdfSmrg if (!dospans) 73935c4bbdfSmrg (*pGC->ops->PolyPoint) (pDraw, pGC, CoordModeOrigin, n, oddPts); 74035c4bbdfSmrg else { 74135c4bbdfSmrg if (n > maxw) { 74235c4bbdfSmrg while (maxw < n) 74335c4bbdfSmrg widths[maxw++] = 1; 74435c4bbdfSmrg } 74535c4bbdfSmrg if (pGC->miTranslate) { 74635c4bbdfSmrg for (pt = oddPts; pt != pts; pt++) { 74735c4bbdfSmrg pt->x += pDraw->x; 74835c4bbdfSmrg pt->y += pDraw->y; 74935c4bbdfSmrg } 75035c4bbdfSmrg } 75135c4bbdfSmrg (*pGC->ops->FillSpans) (pDraw, pGC, n, oddPts, widths, FALSE); 75235c4bbdfSmrg } 75335c4bbdfSmrg if ((pGC->fillStyle == FillSolid) || 75435c4bbdfSmrg (pGC->fillStyle == FillStippled)) { 75535c4bbdfSmrg ChangeGCVal gcval; 75635c4bbdfSmrg 75735c4bbdfSmrg gcval.val = fgPixel; 75835c4bbdfSmrg ChangeGC(NullClient, pGC, GCForeground, &gcval); 75935c4bbdfSmrg ValidateGC(pDraw, pGC); 76035c4bbdfSmrg } 76135c4bbdfSmrg } 76205b261ecSmrg } 7636747b715Smrg free(points); 76435c4bbdfSmrg if (dospans) { 76535c4bbdfSmrg free(widths); 76605b261ecSmrg } 76705b261ecSmrg} 768