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