mizerarc.c revision 6747b715
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 3005b261ecSmrg/* Derived from: 3105b261ecSmrg * "Algorithm for drawing ellipses or hyperbolae with a digital plotter" 3205b261ecSmrg * by M. L. V. Pitteway 3305b261ecSmrg * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289 3405b261ecSmrg */ 3505b261ecSmrg 3605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3705b261ecSmrg#include <dix-config.h> 3805b261ecSmrg#endif 3905b261ecSmrg 4005b261ecSmrg#include <math.h> 4105b261ecSmrg#include <X11/X.h> 4205b261ecSmrg#include <X11/Xprotostr.h> 4305b261ecSmrg#include "regionstr.h" 4405b261ecSmrg#include "gcstruct.h" 4505b261ecSmrg#include "pixmapstr.h" 4605b261ecSmrg#include "mi.h" 4705b261ecSmrg#include "mizerarc.h" 4805b261ecSmrg 4905b261ecSmrg#define FULLCIRCLE (360 * 64) 5005b261ecSmrg#define OCTANT (45 * 64) 5105b261ecSmrg#define QUADRANT (90 * 64) 5205b261ecSmrg#define HALFCIRCLE (180 * 64) 5305b261ecSmrg#define QUADRANT3 (270 * 64) 5405b261ecSmrg 5505b261ecSmrg#ifndef M_PI 5605b261ecSmrg#define M_PI 3.14159265358979323846 5705b261ecSmrg#endif 5805b261ecSmrg 5905b261ecSmrg#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \ 6005b261ecSmrg ((d) == HALFCIRCLE ? 0.0 : \ 6105b261ecSmrg ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0)))))) 6205b261ecSmrg 6305b261ecSmrg#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \ 6405b261ecSmrg ((d) == HALFCIRCLE ? -1.0 : \ 6505b261ecSmrg ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0)))))) 6605b261ecSmrg 6705b261ecSmrg#define EPSILON45 64 6805b261ecSmrg 6905b261ecSmrgtypedef struct { 7005b261ecSmrg int skipStart; 7105b261ecSmrg int haveStart; 7205b261ecSmrg DDXPointRec startPt; 7305b261ecSmrg int haveLast; 7405b261ecSmrg int skipLast; 7505b261ecSmrg DDXPointRec endPt; 7605b261ecSmrg int dashIndex; 7705b261ecSmrg int dashOffset; 7805b261ecSmrg int dashIndexInit; 7905b261ecSmrg int dashOffsetInit; 8005b261ecSmrg} DashInfo; 8105b261ecSmrg 8205b261ecSmrgstatic miZeroArcPtRec oob = {65536, 65536, 0}; 8305b261ecSmrg 8405b261ecSmrg/* 8505b261ecSmrg * (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1 8605b261ecSmrg * 8705b261ecSmrg * where l is either 0 or .5 8805b261ecSmrg * 8905b261ecSmrg * alpha = 4(W^2) 9005b261ecSmrg * beta = 4(H^2) 9105b261ecSmrg * gamma = 0 9205b261ecSmrg * u = 2(W^2)H 9305b261ecSmrg * v = 4(H^2)l 9405b261ecSmrg * k = -4(H^2)(l^2) 9505b261ecSmrg * 9605b261ecSmrg */ 9705b261ecSmrg 986747b715SmrgBool 994642e01fSmrgmiZeroArcSetup(xArc *arc, miZeroArcRec *info, Bool ok360) 10005b261ecSmrg{ 10105b261ecSmrg int l; 10205b261ecSmrg int angle1, angle2; 10305b261ecSmrg int startseg, endseg; 10405b261ecSmrg int startAngle, endAngle; 10505b261ecSmrg int i, overlap; 10605b261ecSmrg miZeroArcPtRec start, end; 10705b261ecSmrg 10805b261ecSmrg l = arc->width & 1; 10905b261ecSmrg if (arc->width == arc->height) 11005b261ecSmrg { 11105b261ecSmrg info->alpha = 4; 11205b261ecSmrg info->beta = 4; 11305b261ecSmrg info->k1 = -8; 11405b261ecSmrg info->k3 = -16; 11505b261ecSmrg info->b = 12; 11605b261ecSmrg info->a = (arc->width << 2) - 12; 11705b261ecSmrg info->d = 17 - (arc->width << 1); 11805b261ecSmrg if (l) 11905b261ecSmrg { 12005b261ecSmrg info->b -= 4; 12105b261ecSmrg info->a += 4; 12205b261ecSmrg info->d -= 7; 12305b261ecSmrg } 12405b261ecSmrg } 12505b261ecSmrg else if (!arc->width || !arc->height) 12605b261ecSmrg { 12705b261ecSmrg info->alpha = 0; 12805b261ecSmrg info->beta = 0; 12905b261ecSmrg info->k1 = 0; 13005b261ecSmrg info->k3 = 0; 13105b261ecSmrg info->a = -(int)arc->height; 13205b261ecSmrg info->b = 0; 13305b261ecSmrg info->d = -1; 13405b261ecSmrg } 13505b261ecSmrg else 13605b261ecSmrg { 13705b261ecSmrg /* initial conditions */ 13805b261ecSmrg info->alpha = (arc->width * arc->width) << 2; 13905b261ecSmrg info->beta = (arc->height * arc->height) << 2; 14005b261ecSmrg info->k1 = info->beta << 1; 14105b261ecSmrg info->k3 = info->k1 + (info->alpha << 1); 14205b261ecSmrg info->b = l ? 0 : -info->beta; 14305b261ecSmrg info->a = info->alpha * arc->height; 14405b261ecSmrg info->d = info->b - (info->a >> 1) - (info->alpha >> 2); 14505b261ecSmrg if (l) 14605b261ecSmrg info->d -= info->beta >> 2; 14705b261ecSmrg info->a -= info->b; 14805b261ecSmrg /* take first step, d < 0 always */ 14905b261ecSmrg info->b -= info->k1; 15005b261ecSmrg info->a += info->k1; 15105b261ecSmrg info->d += info->b; 15205b261ecSmrg /* octant change, b < 0 always */ 15305b261ecSmrg info->k1 = -info->k1; 15405b261ecSmrg info->k3 = -info->k3; 15505b261ecSmrg info->b = -info->b; 15605b261ecSmrg info->d = info->b - info->a - info->d; 15705b261ecSmrg info->a = info->a - (info->b << 1); 15805b261ecSmrg } 15905b261ecSmrg info->dx = 1; 16005b261ecSmrg info->dy = 0; 16105b261ecSmrg info->w = (arc->width + 1) >> 1; 16205b261ecSmrg info->h = arc->height >> 1; 16305b261ecSmrg info->xorg = arc->x + (arc->width >> 1); 16405b261ecSmrg info->yorg = arc->y; 16505b261ecSmrg info->xorgo = info->xorg + l; 16605b261ecSmrg info->yorgo = info->yorg + arc->height; 16705b261ecSmrg if (!arc->width) 16805b261ecSmrg { 16905b261ecSmrg if (!arc->height) 17005b261ecSmrg { 17105b261ecSmrg info->x = 0; 17205b261ecSmrg info->y = 0; 17305b261ecSmrg info->initialMask = 0; 17405b261ecSmrg info->startAngle = 0; 17505b261ecSmrg info->endAngle = 0; 17605b261ecSmrg info->start = oob; 17705b261ecSmrg info->end = oob; 17805b261ecSmrg return FALSE; 17905b261ecSmrg } 18005b261ecSmrg info->x = 0; 18105b261ecSmrg info->y = 1; 18205b261ecSmrg } 18305b261ecSmrg else 18405b261ecSmrg { 18505b261ecSmrg info->x = 1; 18605b261ecSmrg info->y = 0; 18705b261ecSmrg } 18805b261ecSmrg angle1 = arc->angle1; 18905b261ecSmrg angle2 = arc->angle2; 19005b261ecSmrg if ((angle1 == 0) && (angle2 >= FULLCIRCLE)) 19105b261ecSmrg { 19205b261ecSmrg startAngle = 0; 19305b261ecSmrg endAngle = 0; 19405b261ecSmrg } 19505b261ecSmrg else 19605b261ecSmrg { 19705b261ecSmrg if (angle2 > FULLCIRCLE) 19805b261ecSmrg angle2 = FULLCIRCLE; 19905b261ecSmrg else if (angle2 < -FULLCIRCLE) 20005b261ecSmrg angle2 = -FULLCIRCLE; 20105b261ecSmrg if (angle2 < 0) 20205b261ecSmrg { 20305b261ecSmrg startAngle = angle1 + angle2; 20405b261ecSmrg endAngle = angle1; 20505b261ecSmrg } 20605b261ecSmrg else 20705b261ecSmrg { 20805b261ecSmrg startAngle = angle1; 20905b261ecSmrg endAngle = angle1 + angle2; 21005b261ecSmrg } 21105b261ecSmrg if (startAngle < 0) 21205b261ecSmrg startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE; 21305b261ecSmrg if (startAngle >= FULLCIRCLE) 21405b261ecSmrg startAngle = startAngle % FULLCIRCLE; 21505b261ecSmrg if (endAngle < 0) 21605b261ecSmrg endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE; 21705b261ecSmrg if (endAngle >= FULLCIRCLE) 21805b261ecSmrg endAngle = endAngle % FULLCIRCLE; 21905b261ecSmrg } 22005b261ecSmrg info->startAngle = startAngle; 22105b261ecSmrg info->endAngle = endAngle; 22205b261ecSmrg if (ok360 && (startAngle == endAngle) && arc->angle2 && 22305b261ecSmrg arc->width && arc->height) 22405b261ecSmrg { 22505b261ecSmrg info->initialMask = 0xf; 22605b261ecSmrg info->start = oob; 22705b261ecSmrg info->end = oob; 22805b261ecSmrg return TRUE; 22905b261ecSmrg } 23005b261ecSmrg startseg = startAngle / OCTANT; 23105b261ecSmrg if (!arc->height || (((startseg + 1) & 2) && arc->width)) 23205b261ecSmrg { 23305b261ecSmrg start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0); 23405b261ecSmrg if (start.x < 0) 23505b261ecSmrg start.x = -start.x; 23605b261ecSmrg start.y = -1; 23705b261ecSmrg } 23805b261ecSmrg else 23905b261ecSmrg { 24005b261ecSmrg start.y = Dsin(startAngle) * (arc->height / 2.0); 24105b261ecSmrg if (start.y < 0) 24205b261ecSmrg start.y = -start.y; 24305b261ecSmrg start.y = info->h - start.y; 24405b261ecSmrg start.x = 65536; 24505b261ecSmrg } 24605b261ecSmrg endseg = endAngle / OCTANT; 24705b261ecSmrg if (!arc->height || (((endseg + 1) & 2) && arc->width)) 24805b261ecSmrg { 24905b261ecSmrg end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0); 25005b261ecSmrg if (end.x < 0) 25105b261ecSmrg end.x = -end.x; 25205b261ecSmrg end.y = -1; 25305b261ecSmrg } 25405b261ecSmrg else 25505b261ecSmrg { 25605b261ecSmrg end.y = Dsin(endAngle) * (arc->height / 2.0); 25705b261ecSmrg if (end.y < 0) 25805b261ecSmrg end.y = -end.y; 25905b261ecSmrg end.y = info->h - end.y; 26005b261ecSmrg end.x = 65536; 26105b261ecSmrg } 26205b261ecSmrg info->firstx = start.x; 26305b261ecSmrg info->firsty = start.y; 26405b261ecSmrg info->initialMask = 0; 26505b261ecSmrg overlap = arc->angle2 && (endAngle <= startAngle); 26605b261ecSmrg for (i = 0; i < 4; i++) 26705b261ecSmrg { 26805b261ecSmrg if (overlap ? 26905b261ecSmrg ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) : 27005b261ecSmrg ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle))) 27105b261ecSmrg info->initialMask |= (1 << i); 27205b261ecSmrg } 27305b261ecSmrg start.mask = info->initialMask; 27405b261ecSmrg end.mask = info->initialMask; 27505b261ecSmrg startseg >>= 1; 27605b261ecSmrg endseg >>= 1; 27705b261ecSmrg overlap = overlap && (endseg == startseg); 27805b261ecSmrg if (start.x != end.x || start.y != end.y || !overlap) 27905b261ecSmrg { 28005b261ecSmrg if (startseg & 1) 28105b261ecSmrg { 28205b261ecSmrg if (!overlap) 28305b261ecSmrg info->initialMask &= ~(1 << startseg); 28405b261ecSmrg if (start.x > end.x || start.y > end.y) 28505b261ecSmrg end.mask &= ~(1 << startseg); 28605b261ecSmrg } 28705b261ecSmrg else 28805b261ecSmrg { 28905b261ecSmrg start.mask &= ~(1 << startseg); 29005b261ecSmrg if (((start.x < end.x || start.y < end.y) || 29105b261ecSmrg (start.x == end.x && start.y == end.y && (endseg & 1))) && 29205b261ecSmrg !overlap) 29305b261ecSmrg end.mask &= ~(1 << startseg); 29405b261ecSmrg } 29505b261ecSmrg if (endseg & 1) 29605b261ecSmrg { 29705b261ecSmrg end.mask &= ~(1 << endseg); 29805b261ecSmrg if (((start.x > end.x || start.y > end.y) || 29905b261ecSmrg (start.x == end.x && start.y == end.y && !(startseg & 1))) && 30005b261ecSmrg !overlap) 30105b261ecSmrg start.mask &= ~(1 << endseg); 30205b261ecSmrg } 30305b261ecSmrg else 30405b261ecSmrg { 30505b261ecSmrg if (!overlap) 30605b261ecSmrg info->initialMask &= ~(1 << endseg); 30705b261ecSmrg if (start.x < end.x || start.y < end.y) 30805b261ecSmrg start.mask &= ~(1 << endseg); 30905b261ecSmrg } 31005b261ecSmrg } 31105b261ecSmrg /* take care of case when start and stop are both near 45 */ 31205b261ecSmrg /* handle here rather than adding extra code to pixelization loops */ 31305b261ecSmrg if (startAngle && 31405b261ecSmrg ((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0))) 31505b261ecSmrg { 31605b261ecSmrg i = (startAngle + OCTANT) % OCTANT; 31705b261ecSmrg if (i < EPSILON45 || i > OCTANT - EPSILON45) 31805b261ecSmrg { 31905b261ecSmrg i = (endAngle + OCTANT) % OCTANT; 32005b261ecSmrg if (i < EPSILON45 || i > OCTANT - EPSILON45) 32105b261ecSmrg { 32205b261ecSmrg if (start.y < 0) 32305b261ecSmrg { 32405b261ecSmrg i = Dsin(startAngle) * (arc->height / 2.0); 32505b261ecSmrg if (i < 0) 32605b261ecSmrg i = -i; 32705b261ecSmrg if (info->h - i == end.y) 32805b261ecSmrg start.mask = end.mask; 32905b261ecSmrg } 33005b261ecSmrg else 33105b261ecSmrg { 33205b261ecSmrg i = Dsin(endAngle) * (arc->height / 2.0); 33305b261ecSmrg if (i < 0) 33405b261ecSmrg i = -i; 33505b261ecSmrg if (info->h - i == start.y) 33605b261ecSmrg end.mask = start.mask; 33705b261ecSmrg } 33805b261ecSmrg } 33905b261ecSmrg } 34005b261ecSmrg } 34105b261ecSmrg if (startseg & 1) 34205b261ecSmrg { 34305b261ecSmrg info->start = start; 34405b261ecSmrg info->end = oob; 34505b261ecSmrg } 34605b261ecSmrg else 34705b261ecSmrg { 34805b261ecSmrg info->end = start; 34905b261ecSmrg info->start = oob; 35005b261ecSmrg } 35105b261ecSmrg if (endseg & 1) 35205b261ecSmrg { 35305b261ecSmrg info->altend = end; 35405b261ecSmrg if (info->altend.x < info->end.x || info->altend.y < info->end.y) 35505b261ecSmrg { 35605b261ecSmrg miZeroArcPtRec tmp; 35705b261ecSmrg tmp = info->altend; 35805b261ecSmrg info->altend = info->end; 35905b261ecSmrg info->end = tmp; 36005b261ecSmrg } 36105b261ecSmrg info->altstart = oob; 36205b261ecSmrg } 36305b261ecSmrg else 36405b261ecSmrg { 36505b261ecSmrg info->altstart = end; 36605b261ecSmrg if (info->altstart.x < info->start.x || 36705b261ecSmrg info->altstart.y < info->start.y) 36805b261ecSmrg { 36905b261ecSmrg miZeroArcPtRec tmp; 37005b261ecSmrg tmp = info->altstart; 37105b261ecSmrg info->altstart = info->start; 37205b261ecSmrg info->start = tmp; 37305b261ecSmrg } 37405b261ecSmrg info->altend = oob; 37505b261ecSmrg } 37605b261ecSmrg if (!info->start.x || !info->start.y) 37705b261ecSmrg { 37805b261ecSmrg info->initialMask = info->start.mask; 37905b261ecSmrg info->start = info->altstart; 38005b261ecSmrg } 38105b261ecSmrg if (!arc->width && (arc->height == 1)) 38205b261ecSmrg { 38305b261ecSmrg /* kludge! */ 38405b261ecSmrg info->initialMask |= info->end.mask; 38505b261ecSmrg info->initialMask |= info->initialMask << 1; 38605b261ecSmrg info->end.x = 0; 38705b261ecSmrg info->end.mask = 0; 38805b261ecSmrg } 38905b261ecSmrg return FALSE; 39005b261ecSmrg} 39105b261ecSmrg 39205b261ecSmrg#define Pixelate(xval,yval) \ 39305b261ecSmrg { \ 39405b261ecSmrg pts->x = xval; \ 39505b261ecSmrg pts->y = yval; \ 39605b261ecSmrg pts++; \ 39705b261ecSmrg } 39805b261ecSmrg 39905b261ecSmrg#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval); 40005b261ecSmrg 40105b261ecSmrgstatic DDXPointPtr 40205b261ecSmrgmiZeroArcPts(xArc *arc, DDXPointPtr pts) 40305b261ecSmrg{ 40405b261ecSmrg miZeroArcRec info; 40505b261ecSmrg int x, y, a, b, d, mask; 40605b261ecSmrg int k1, k3, dx, dy; 40705b261ecSmrg Bool do360; 40805b261ecSmrg 40905b261ecSmrg do360 = miZeroArcSetup(arc, &info, TRUE); 41005b261ecSmrg MIARCSETUP(); 41105b261ecSmrg mask = info.initialMask; 41205b261ecSmrg if (!(arc->width & 1)) 41305b261ecSmrg { 41405b261ecSmrg DoPix(1, info.xorgo, info.yorg); 41505b261ecSmrg DoPix(3, info.xorgo, info.yorgo); 41605b261ecSmrg } 41705b261ecSmrg if (!info.end.x || !info.end.y) 41805b261ecSmrg { 41905b261ecSmrg mask = info.end.mask; 42005b261ecSmrg info.end = info.altend; 42105b261ecSmrg } 42205b261ecSmrg if (do360 && (arc->width == arc->height) && !(arc->width & 1)) 42305b261ecSmrg { 42405b261ecSmrg int yorgh = info.yorg + info.h; 42505b261ecSmrg int xorghp = info.xorg + info.h; 42605b261ecSmrg int xorghn = info.xorg - info.h; 42705b261ecSmrg 42805b261ecSmrg while (1) 42905b261ecSmrg { 43005b261ecSmrg Pixelate(info.xorg + x, info.yorg + y); 43105b261ecSmrg Pixelate(info.xorg - x, info.yorg + y); 43205b261ecSmrg Pixelate(info.xorg - x, info.yorgo - y); 43305b261ecSmrg Pixelate(info.xorg + x, info.yorgo - y); 43405b261ecSmrg if (a < 0) 43505b261ecSmrg break; 43605b261ecSmrg Pixelate(xorghp - y, yorgh - x); 43705b261ecSmrg Pixelate(xorghn + y, yorgh - x); 43805b261ecSmrg Pixelate(xorghn + y, yorgh + x); 43905b261ecSmrg Pixelate(xorghp - y, yorgh + x); 44005b261ecSmrg MIARCCIRCLESTEP(;); 44105b261ecSmrg } 44205b261ecSmrg if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y) 44305b261ecSmrg pts -= 4; 44405b261ecSmrg x = info.w; 44505b261ecSmrg y = info.h; 44605b261ecSmrg } 44705b261ecSmrg else if (do360) 44805b261ecSmrg { 44905b261ecSmrg while (y < info.h || x < info.w) 45005b261ecSmrg { 45105b261ecSmrg MIARCOCTANTSHIFT(;); 45205b261ecSmrg Pixelate(info.xorg + x, info.yorg + y); 45305b261ecSmrg Pixelate(info.xorgo - x, info.yorg + y); 45405b261ecSmrg Pixelate(info.xorgo - x, info.yorgo - y); 45505b261ecSmrg Pixelate(info.xorg + x, info.yorgo - y); 45605b261ecSmrg MIARCSTEP(;,;); 45705b261ecSmrg } 45805b261ecSmrg } 45905b261ecSmrg else 46005b261ecSmrg { 46105b261ecSmrg while (y < info.h || x < info.w) 46205b261ecSmrg { 46305b261ecSmrg MIARCOCTANTSHIFT(;); 46405b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 46505b261ecSmrg { 46605b261ecSmrg mask = info.start.mask; 46705b261ecSmrg info.start = info.altstart; 46805b261ecSmrg } 46905b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 47005b261ecSmrg DoPix(1, info.xorgo - x, info.yorg + y); 47105b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 47205b261ecSmrg DoPix(3, info.xorg + x, info.yorgo - y); 47305b261ecSmrg if ((x == info.end.x) || (y == info.end.y)) 47405b261ecSmrg { 47505b261ecSmrg mask = info.end.mask; 47605b261ecSmrg info.end = info.altend; 47705b261ecSmrg } 47805b261ecSmrg MIARCSTEP(;,;); 47905b261ecSmrg } 48005b261ecSmrg } 48105b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 48205b261ecSmrg mask = info.start.mask; 48305b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 48405b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 48505b261ecSmrg if (arc->height & 1) 48605b261ecSmrg { 48705b261ecSmrg DoPix(1, info.xorgo - x, info.yorg + y); 48805b261ecSmrg DoPix(3, info.xorg + x, info.yorgo - y); 48905b261ecSmrg } 49005b261ecSmrg return pts; 49105b261ecSmrg} 49205b261ecSmrg 49305b261ecSmrg#undef DoPix 49405b261ecSmrg#define DoPix(idx,xval,yval) \ 49505b261ecSmrg if (mask & (1 << idx)) \ 49605b261ecSmrg { \ 49705b261ecSmrg arcPts[idx]->x = xval; \ 49805b261ecSmrg arcPts[idx]->y = yval; \ 49905b261ecSmrg arcPts[idx]++; \ 50005b261ecSmrg } 50105b261ecSmrg 50205b261ecSmrgstatic void 50305b261ecSmrgmiZeroArcDashPts( 50405b261ecSmrg GCPtr pGC, 50505b261ecSmrg xArc *arc, 50605b261ecSmrg DashInfo *dinfo, 50705b261ecSmrg DDXPointPtr points, 50805b261ecSmrg int maxPts, 50905b261ecSmrg DDXPointPtr *evenPts, 51005b261ecSmrg DDXPointPtr *oddPts ) 51105b261ecSmrg{ 51205b261ecSmrg miZeroArcRec info; 51305b261ecSmrg int x, y, a, b, d, mask; 51405b261ecSmrg int k1, k3, dx, dy; 51505b261ecSmrg int dashRemaining; 51605b261ecSmrg DDXPointPtr arcPts[4]; 51705b261ecSmrg DDXPointPtr startPts[5], endPts[5]; 51805b261ecSmrg int deltas[5]; 51905b261ecSmrg DDXPointPtr startPt, pt, lastPt, pts; 52005b261ecSmrg int i, j, delta, ptsdelta, seg, startseg; 52105b261ecSmrg 52205b261ecSmrg for (i = 0; i < 4; i++) 52305b261ecSmrg arcPts[i] = points + (i * maxPts); 52405b261ecSmrg (void)miZeroArcSetup(arc, &info, FALSE); 52505b261ecSmrg MIARCSETUP(); 52605b261ecSmrg mask = info.initialMask; 52705b261ecSmrg startseg = info.startAngle / QUADRANT; 52805b261ecSmrg startPt = arcPts[startseg]; 52905b261ecSmrg if (!(arc->width & 1)) 53005b261ecSmrg { 53105b261ecSmrg DoPix(1, info.xorgo, info.yorg); 53205b261ecSmrg DoPix(3, info.xorgo, info.yorgo); 53305b261ecSmrg } 53405b261ecSmrg if (!info.end.x || !info.end.y) 53505b261ecSmrg { 53605b261ecSmrg mask = info.end.mask; 53705b261ecSmrg info.end = info.altend; 53805b261ecSmrg } 53905b261ecSmrg while (y < info.h || x < info.w) 54005b261ecSmrg { 54105b261ecSmrg MIARCOCTANTSHIFT(;); 54205b261ecSmrg if ((x == info.firstx) || (y == info.firsty)) 54305b261ecSmrg startPt = arcPts[startseg]; 54405b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 54505b261ecSmrg { 54605b261ecSmrg mask = info.start.mask; 54705b261ecSmrg info.start = info.altstart; 54805b261ecSmrg } 54905b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 55005b261ecSmrg DoPix(1, info.xorgo - x, info.yorg + y); 55105b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 55205b261ecSmrg DoPix(3, info.xorg + x, info.yorgo - y); 55305b261ecSmrg if ((x == info.end.x) || (y == info.end.y)) 55405b261ecSmrg { 55505b261ecSmrg mask = info.end.mask; 55605b261ecSmrg info.end = info.altend; 55705b261ecSmrg } 55805b261ecSmrg MIARCSTEP(;,;); 55905b261ecSmrg } 56005b261ecSmrg if ((x == info.firstx) || (y == info.firsty)) 56105b261ecSmrg startPt = arcPts[startseg]; 56205b261ecSmrg if ((x == info.start.x) || (y == info.start.y)) 56305b261ecSmrg mask = info.start.mask; 56405b261ecSmrg DoPix(0, info.xorg + x, info.yorg + y); 56505b261ecSmrg DoPix(2, info.xorgo - x, info.yorgo - y); 56605b261ecSmrg if (arc->height & 1) 56705b261ecSmrg { 56805b261ecSmrg DoPix(1, info.xorgo - x, info.yorg + y); 56905b261ecSmrg DoPix(3, info.xorg + x, info.yorgo - y); 57005b261ecSmrg } 57105b261ecSmrg for (i = 0; i < 4; i++) 57205b261ecSmrg { 57305b261ecSmrg seg = (startseg + i) & 3; 57405b261ecSmrg pt = points + (seg * maxPts); 57505b261ecSmrg if (seg & 1) 57605b261ecSmrg { 57705b261ecSmrg startPts[i] = pt; 57805b261ecSmrg endPts[i] = arcPts[seg]; 57905b261ecSmrg deltas[i] = 1; 58005b261ecSmrg } 58105b261ecSmrg else 58205b261ecSmrg { 58305b261ecSmrg startPts[i] = arcPts[seg] - 1; 58405b261ecSmrg endPts[i] = pt - 1; 58505b261ecSmrg deltas[i] = -1; 58605b261ecSmrg } 58705b261ecSmrg } 58805b261ecSmrg startPts[4] = startPts[0]; 58905b261ecSmrg endPts[4] = startPt; 59005b261ecSmrg startPts[0] = startPt; 59105b261ecSmrg if (startseg & 1) 59205b261ecSmrg { 59305b261ecSmrg if (startPts[4] != endPts[4]) 59405b261ecSmrg endPts[4]--; 59505b261ecSmrg deltas[4] = 1; 59605b261ecSmrg } 59705b261ecSmrg else 59805b261ecSmrg { 59905b261ecSmrg if (startPts[0] > startPts[4]) 60005b261ecSmrg startPts[0]--; 60105b261ecSmrg if (startPts[4] < endPts[4]) 60205b261ecSmrg endPts[4]--; 60305b261ecSmrg deltas[4] = -1; 60405b261ecSmrg } 60505b261ecSmrg if (arc->angle2 < 0) 60605b261ecSmrg { 60705b261ecSmrg DDXPointPtr tmps, tmpe; 60805b261ecSmrg int tmpd; 60905b261ecSmrg 61005b261ecSmrg tmpd = deltas[0]; 61105b261ecSmrg tmps = startPts[0] - tmpd; 61205b261ecSmrg tmpe = endPts[0] - tmpd; 61305b261ecSmrg startPts[0] = endPts[4] - deltas[4]; 61405b261ecSmrg endPts[0] = startPts[4] - deltas[4]; 61505b261ecSmrg deltas[0] = -deltas[4]; 61605b261ecSmrg startPts[4] = tmpe; 61705b261ecSmrg endPts[4] = tmps; 61805b261ecSmrg deltas[4] = -tmpd; 61905b261ecSmrg tmpd = deltas[1]; 62005b261ecSmrg tmps = startPts[1] - tmpd; 62105b261ecSmrg tmpe = endPts[1] - tmpd; 62205b261ecSmrg startPts[1] = endPts[3] - deltas[3]; 62305b261ecSmrg endPts[1] = startPts[3] - deltas[3]; 62405b261ecSmrg deltas[1] = -deltas[3]; 62505b261ecSmrg startPts[3] = tmpe; 62605b261ecSmrg endPts[3] = tmps; 62705b261ecSmrg deltas[3] = -tmpd; 62805b261ecSmrg tmps = startPts[2] - deltas[2]; 62905b261ecSmrg startPts[2] = endPts[2] - deltas[2]; 63005b261ecSmrg endPts[2] = tmps; 63105b261ecSmrg deltas[2] = -deltas[2]; 63205b261ecSmrg } 63305b261ecSmrg for (i = 0; i < 5 && startPts[i] == endPts[i]; i++) 63405b261ecSmrg ; 63505b261ecSmrg if (i == 5) 63605b261ecSmrg return; 63705b261ecSmrg pt = startPts[i]; 63805b261ecSmrg for (j = 4; startPts[j] == endPts[j]; j--) 63905b261ecSmrg ; 64005b261ecSmrg lastPt = endPts[j] - deltas[j]; 64105b261ecSmrg if (dinfo->haveLast && 64205b261ecSmrg (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) 64305b261ecSmrg { 64405b261ecSmrg startPts[i] += deltas[i]; 64505b261ecSmrg } 64605b261ecSmrg else 64705b261ecSmrg { 64805b261ecSmrg dinfo->dashIndex = dinfo->dashIndexInit; 64905b261ecSmrg dinfo->dashOffset = dinfo->dashOffsetInit; 65005b261ecSmrg } 65105b261ecSmrg if (!dinfo->skipStart && (info.startAngle != info.endAngle)) 65205b261ecSmrg { 65305b261ecSmrg dinfo->startPt = *pt; 65405b261ecSmrg dinfo->haveStart = TRUE; 65505b261ecSmrg } 65605b261ecSmrg else if (!dinfo->skipLast && dinfo->haveStart && 65705b261ecSmrg (lastPt->x == dinfo->startPt.x) && 65805b261ecSmrg (lastPt->y == dinfo->startPt.y) && 65905b261ecSmrg (lastPt != startPts[i])) 66005b261ecSmrg endPts[j] = lastPt; 66105b261ecSmrg if (info.startAngle != info.endAngle) 66205b261ecSmrg { 66305b261ecSmrg dinfo->haveLast = TRUE; 66405b261ecSmrg dinfo->endPt = *lastPt; 66505b261ecSmrg } 66605b261ecSmrg dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset; 66705b261ecSmrg for (i = 0; i < 5; i++) 66805b261ecSmrg { 66905b261ecSmrg pt = startPts[i]; 67005b261ecSmrg lastPt = endPts[i]; 67105b261ecSmrg delta = deltas[i]; 67205b261ecSmrg while (pt != lastPt) 67305b261ecSmrg { 67405b261ecSmrg if (dinfo->dashIndex & 1) 67505b261ecSmrg { 67605b261ecSmrg pts = *oddPts; 67705b261ecSmrg ptsdelta = -1; 67805b261ecSmrg } 67905b261ecSmrg else 68005b261ecSmrg { 68105b261ecSmrg pts = *evenPts; 68205b261ecSmrg ptsdelta = 1; 68305b261ecSmrg } 68405b261ecSmrg while ((pt != lastPt) && --dashRemaining >= 0) 68505b261ecSmrg { 68605b261ecSmrg *pts = *pt; 68705b261ecSmrg pts += ptsdelta; 68805b261ecSmrg pt += delta; 68905b261ecSmrg } 69005b261ecSmrg if (dinfo->dashIndex & 1) 69105b261ecSmrg *oddPts = pts; 69205b261ecSmrg else 69305b261ecSmrg *evenPts = pts; 69405b261ecSmrg if (dashRemaining <= 0) 69505b261ecSmrg { 69605b261ecSmrg if (++(dinfo->dashIndex) == pGC->numInDashList) 69705b261ecSmrg dinfo->dashIndex = 0; 69805b261ecSmrg dashRemaining = pGC->dash[dinfo->dashIndex]; 69905b261ecSmrg } 70005b261ecSmrg } 70105b261ecSmrg } 70205b261ecSmrg dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining; 70305b261ecSmrg} 70405b261ecSmrg 7056747b715Smrgvoid 7064642e01fSmrgmiZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) 70705b261ecSmrg{ 70805b261ecSmrg int maxPts = 0; 70905b261ecSmrg int n, maxw = 0; 71005b261ecSmrg xArc *arc; 71105b261ecSmrg int i; 7126747b715Smrg DDXPointPtr points, pts, oddPts = NULL; 71305b261ecSmrg DDXPointPtr pt; 71405b261ecSmrg int numPts; 71505b261ecSmrg Bool dospans; 71605b261ecSmrg int *widths = NULL; 71705b261ecSmrg XID fgPixel = pGC->fgPixel; 71805b261ecSmrg DashInfo dinfo; 71905b261ecSmrg 72005b261ecSmrg for (arc = parcs, i = narcs; --i >= 0; arc++) 72105b261ecSmrg { 72205b261ecSmrg if (!miCanZeroArc(arc)) 72305b261ecSmrg miPolyArc(pDraw, pGC, 1, arc); 72405b261ecSmrg else 72505b261ecSmrg { 72605b261ecSmrg if (arc->width > arc->height) 72705b261ecSmrg n = arc->width + (arc->height >> 1); 72805b261ecSmrg else 72905b261ecSmrg n = arc->height + (arc->width >> 1); 73005b261ecSmrg if (n > maxPts) 73105b261ecSmrg maxPts = n; 73205b261ecSmrg } 73305b261ecSmrg } 73405b261ecSmrg if (!maxPts) 73505b261ecSmrg return; 73605b261ecSmrg numPts = maxPts << 2; 73705b261ecSmrg dospans = (pGC->fillStyle != FillSolid); 73805b261ecSmrg if (dospans) 73905b261ecSmrg { 7406747b715Smrg widths = malloc(sizeof(int) * numPts); 74105b261ecSmrg if (!widths) 74205b261ecSmrg return; 74305b261ecSmrg maxw = 0; 74405b261ecSmrg } 74505b261ecSmrg if (pGC->lineStyle != LineSolid) 74605b261ecSmrg { 74705b261ecSmrg numPts <<= 1; 74805b261ecSmrg dinfo.haveStart = FALSE; 74905b261ecSmrg dinfo.skipStart = FALSE; 75005b261ecSmrg dinfo.haveLast = FALSE; 75105b261ecSmrg dinfo.dashIndexInit = 0; 75205b261ecSmrg dinfo.dashOffsetInit = 0; 75305b261ecSmrg miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit, 75405b261ecSmrg (unsigned char *) pGC->dash, (int)pGC->numInDashList, 75505b261ecSmrg &dinfo.dashOffsetInit); 75605b261ecSmrg } 7576747b715Smrg points = malloc(sizeof(DDXPointRec) * numPts); 75805b261ecSmrg if (!points) 75905b261ecSmrg { 76005b261ecSmrg if (dospans) 76105b261ecSmrg { 7626747b715Smrg free(widths); 76305b261ecSmrg } 76405b261ecSmrg return; 76505b261ecSmrg } 76605b261ecSmrg for (arc = parcs, i = narcs; --i >= 0; arc++) 76705b261ecSmrg { 76805b261ecSmrg if (miCanZeroArc(arc)) 76905b261ecSmrg { 77005b261ecSmrg if (pGC->lineStyle == LineSolid) 77105b261ecSmrg pts = miZeroArcPts(arc, points); 77205b261ecSmrg else 77305b261ecSmrg { 77405b261ecSmrg pts = points; 77505b261ecSmrg oddPts = &points[(numPts >> 1) - 1]; 77605b261ecSmrg dinfo.skipLast = i; 77705b261ecSmrg miZeroArcDashPts(pGC, arc, &dinfo, 77805b261ecSmrg oddPts + 1, maxPts, &pts, &oddPts); 77905b261ecSmrg dinfo.skipStart = TRUE; 78005b261ecSmrg } 78105b261ecSmrg n = pts - points; 78205b261ecSmrg if (!dospans) 78305b261ecSmrg (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points); 78405b261ecSmrg else 78505b261ecSmrg { 78605b261ecSmrg if (n > maxw) 78705b261ecSmrg { 78805b261ecSmrg while (maxw < n) 78905b261ecSmrg widths[maxw++] = 1; 79005b261ecSmrg } 79105b261ecSmrg if (pGC->miTranslate) 79205b261ecSmrg { 79305b261ecSmrg for (pt = points; pt != pts; pt++) 79405b261ecSmrg { 79505b261ecSmrg pt->x += pDraw->x; 79605b261ecSmrg pt->y += pDraw->y; 79705b261ecSmrg } 79805b261ecSmrg } 79905b261ecSmrg (*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE); 80005b261ecSmrg } 80105b261ecSmrg if (pGC->lineStyle != LineDoubleDash) 80205b261ecSmrg continue; 80305b261ecSmrg if ((pGC->fillStyle == FillSolid) || 80405b261ecSmrg (pGC->fillStyle == FillStippled)) 80505b261ecSmrg { 8066747b715Smrg ChangeGCVal gcval; 8076747b715Smrg gcval.val = pGC->bgPixel; 8086747b715Smrg ChangeGC(NullClient, pGC, GCForeground, &gcval); 80905b261ecSmrg ValidateGC(pDraw, pGC); 81005b261ecSmrg } 81105b261ecSmrg pts = &points[numPts >> 1]; 81205b261ecSmrg oddPts++; 81305b261ecSmrg n = pts - oddPts; 81405b261ecSmrg if (!dospans) 81505b261ecSmrg (*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts); 81605b261ecSmrg else 81705b261ecSmrg { 81805b261ecSmrg if (n > maxw) 81905b261ecSmrg { 82005b261ecSmrg while (maxw < n) 82105b261ecSmrg widths[maxw++] = 1; 82205b261ecSmrg } 82305b261ecSmrg if (pGC->miTranslate) 82405b261ecSmrg { 82505b261ecSmrg for (pt = oddPts; pt != pts; pt++) 82605b261ecSmrg { 82705b261ecSmrg pt->x += pDraw->x; 82805b261ecSmrg pt->y += pDraw->y; 82905b261ecSmrg } 83005b261ecSmrg } 83105b261ecSmrg (*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE); 83205b261ecSmrg } 83305b261ecSmrg if ((pGC->fillStyle == FillSolid) || 83405b261ecSmrg (pGC->fillStyle == FillStippled)) 83505b261ecSmrg { 8366747b715Smrg ChangeGCVal gcval; 8376747b715Smrg gcval.val = fgPixel; 8386747b715Smrg ChangeGC(NullClient, pGC, GCForeground, &gcval); 83905b261ecSmrg ValidateGC(pDraw, pGC); 84005b261ecSmrg } 84105b261ecSmrg } 84205b261ecSmrg } 8436747b715Smrg free(points); 84405b261ecSmrg if (dospans) 84505b261ecSmrg { 8466747b715Smrg free(widths); 84705b261ecSmrg } 84805b261ecSmrg} 849