849 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			849 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
 | 
						|
Copyright 1989, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 | 
						|
Author:  Bob Scheifler, MIT X Consortium
 | 
						|
 | 
						|
********************************************************/
 | 
						|
 | 
						|
 | 
						|
/* Derived from:
 | 
						|
 * "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
 | 
						|
 * by M. L. V. Pitteway
 | 
						|
 * The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xprotostr.h>
 | 
						|
#include "regionstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "mi.h"
 | 
						|
#include "mizerarc.h"
 | 
						|
 | 
						|
#define FULLCIRCLE (360 * 64)
 | 
						|
#define OCTANT (45 * 64)
 | 
						|
#define QUADRANT (90 * 64)
 | 
						|
#define HALFCIRCLE (180 * 64)
 | 
						|
#define QUADRANT3 (270 * 64)
 | 
						|
 | 
						|
#ifndef M_PI
 | 
						|
#define M_PI	3.14159265358979323846
 | 
						|
#endif
 | 
						|
 | 
						|
#define Dsin(d)	((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
 | 
						|
		 ((d) == HALFCIRCLE ? 0.0 : \
 | 
						|
		 ((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
 | 
						|
 | 
						|
#define Dcos(d)	((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
 | 
						|
		 ((d) == HALFCIRCLE ? -1.0 : \
 | 
						|
		 ((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
 | 
						|
 | 
						|
#define EPSILON45 64
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    int skipStart;
 | 
						|
    int haveStart;
 | 
						|
    DDXPointRec startPt;
 | 
						|
    int haveLast;
 | 
						|
    int skipLast;
 | 
						|
    DDXPointRec endPt;
 | 
						|
    int dashIndex;
 | 
						|
    int dashOffset;
 | 
						|
    int dashIndexInit;
 | 
						|
    int dashOffsetInit;
 | 
						|
} DashInfo;
 | 
						|
 | 
						|
static miZeroArcPtRec oob = {65536, 65536, 0};
 | 
						|
 | 
						|
/*
 | 
						|
 * (x - l)^2 / (W/2)^2  + (y + H/2)^2 / (H/2)^2 = 1
 | 
						|
 *
 | 
						|
 * where l is either 0 or .5
 | 
						|
 *
 | 
						|
 * alpha = 4(W^2)
 | 
						|
 * beta = 4(H^2)
 | 
						|
 * gamma = 0
 | 
						|
 * u = 2(W^2)H
 | 
						|
 * v = 4(H^2)l
 | 
						|
 * k = -4(H^2)(l^2)
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
miZeroArcSetup(xArc *arc, miZeroArcRec *info, Bool ok360)
 | 
						|
{
 | 
						|
    int l;
 | 
						|
    int angle1, angle2;
 | 
						|
    int startseg, endseg;
 | 
						|
    int startAngle, endAngle;
 | 
						|
    int i, overlap;
 | 
						|
    miZeroArcPtRec start, end;
 | 
						|
 | 
						|
    l = arc->width & 1;
 | 
						|
    if (arc->width == arc->height)
 | 
						|
    {
 | 
						|
	info->alpha = 4;
 | 
						|
	info->beta = 4;
 | 
						|
	info->k1 = -8;
 | 
						|
	info->k3 = -16;
 | 
						|
	info->b = 12;
 | 
						|
	info->a = (arc->width << 2) - 12;
 | 
						|
	info->d = 17 - (arc->width << 1);
 | 
						|
	if (l)
 | 
						|
	{
 | 
						|
	    info->b -= 4;
 | 
						|
	    info->a += 4;
 | 
						|
	    info->d -= 7;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else if (!arc->width || !arc->height)
 | 
						|
    {
 | 
						|
	info->alpha = 0;
 | 
						|
	info->beta = 0;
 | 
						|
	info->k1 = 0;
 | 
						|
	info->k3 = 0;
 | 
						|
	info->a = -(int)arc->height;
 | 
						|
	info->b = 0;
 | 
						|
	info->d = -1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	/* initial conditions */
 | 
						|
	info->alpha = (arc->width * arc->width) << 2;
 | 
						|
	info->beta = (arc->height * arc->height) << 2;
 | 
						|
	info->k1 = info->beta << 1;
 | 
						|
	info->k3 = info->k1 + (info->alpha << 1);
 | 
						|
	info->b = l ? 0 : -info->beta;
 | 
						|
	info->a = info->alpha * arc->height;
 | 
						|
	info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
 | 
						|
	if (l)
 | 
						|
	    info->d -= info->beta >> 2;
 | 
						|
	info->a -= info->b;
 | 
						|
	/* take first step, d < 0 always */
 | 
						|
	info->b -= info->k1;
 | 
						|
	info->a += info->k1;
 | 
						|
	info->d += info->b;
 | 
						|
	/* octant change, b < 0 always */
 | 
						|
	info->k1 = -info->k1;
 | 
						|
	info->k3 = -info->k3;
 | 
						|
	info->b = -info->b;
 | 
						|
	info->d = info->b - info->a - info->d;
 | 
						|
	info->a = info->a - (info->b << 1);
 | 
						|
    }
 | 
						|
    info->dx = 1;
 | 
						|
    info->dy = 0;
 | 
						|
    info->w = (arc->width + 1) >> 1;
 | 
						|
    info->h = arc->height >> 1;
 | 
						|
    info->xorg = arc->x + (arc->width >> 1);
 | 
						|
    info->yorg = arc->y;
 | 
						|
    info->xorgo = info->xorg + l;
 | 
						|
    info->yorgo = info->yorg + arc->height;
 | 
						|
    if (!arc->width)
 | 
						|
    {
 | 
						|
	if (!arc->height)
 | 
						|
	{
 | 
						|
	    info->x = 0;
 | 
						|
	    info->y = 0;
 | 
						|
	    info->initialMask = 0;
 | 
						|
	    info->startAngle = 0;
 | 
						|
	    info->endAngle = 0;
 | 
						|
	    info->start = oob;
 | 
						|
	    info->end = oob;
 | 
						|
	    return FALSE;
 | 
						|
	}
 | 
						|
	info->x = 0;
 | 
						|
	info->y = 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	info->x = 1;
 | 
						|
	info->y = 0;
 | 
						|
    }
 | 
						|
    angle1 = arc->angle1;
 | 
						|
    angle2 = arc->angle2;
 | 
						|
    if ((angle1 == 0) && (angle2 >= FULLCIRCLE))
 | 
						|
    {
 | 
						|
	startAngle = 0;
 | 
						|
	endAngle = 0;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	if (angle2 > FULLCIRCLE)
 | 
						|
	    angle2 = FULLCIRCLE;
 | 
						|
	else if (angle2 < -FULLCIRCLE)
 | 
						|
	    angle2 = -FULLCIRCLE;
 | 
						|
	if (angle2 < 0)
 | 
						|
	{
 | 
						|
	    startAngle = angle1 + angle2;
 | 
						|
	    endAngle = angle1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    startAngle = angle1;
 | 
						|
	    endAngle = angle1 + angle2;
 | 
						|
	}
 | 
						|
	if (startAngle < 0)
 | 
						|
	    startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
 | 
						|
	if (startAngle >= FULLCIRCLE)
 | 
						|
	    startAngle = startAngle % FULLCIRCLE;
 | 
						|
	if (endAngle < 0)
 | 
						|
	    endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
 | 
						|
	if (endAngle >= FULLCIRCLE)
 | 
						|
	    endAngle = endAngle % FULLCIRCLE;
 | 
						|
    }
 | 
						|
    info->startAngle = startAngle;
 | 
						|
    info->endAngle = endAngle;
 | 
						|
    if (ok360 && (startAngle == endAngle) && arc->angle2 &&
 | 
						|
	arc->width && arc->height)
 | 
						|
    {
 | 
						|
	info->initialMask = 0xf;
 | 
						|
	info->start = oob;
 | 
						|
	info->end = oob;
 | 
						|
	return TRUE;
 | 
						|
    }
 | 
						|
    startseg = startAngle / OCTANT;
 | 
						|
    if (!arc->height || (((startseg + 1) & 2) && arc->width))
 | 
						|
    {
 | 
						|
	start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
 | 
						|
	if (start.x < 0)
 | 
						|
	    start.x = -start.x;
 | 
						|
	start.y = -1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	start.y = Dsin(startAngle) * (arc->height / 2.0);
 | 
						|
	if (start.y < 0)
 | 
						|
	    start.y = -start.y;
 | 
						|
	start.y = info->h - start.y;
 | 
						|
	start.x = 65536;
 | 
						|
    }
 | 
						|
    endseg = endAngle / OCTANT;
 | 
						|
    if (!arc->height || (((endseg + 1) & 2) && arc->width))
 | 
						|
    {
 | 
						|
	end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
 | 
						|
	if (end.x < 0)
 | 
						|
	    end.x = -end.x;
 | 
						|
	end.y = -1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	end.y = Dsin(endAngle) * (arc->height / 2.0);
 | 
						|
	if (end.y < 0)
 | 
						|
	    end.y = -end.y;
 | 
						|
	end.y = info->h - end.y;
 | 
						|
	end.x = 65536;
 | 
						|
    }
 | 
						|
    info->firstx = start.x;
 | 
						|
    info->firsty = start.y;
 | 
						|
    info->initialMask = 0;
 | 
						|
    overlap = arc->angle2 && (endAngle <= startAngle);
 | 
						|
    for (i = 0; i < 4; i++)
 | 
						|
    {
 | 
						|
	if (overlap ?
 | 
						|
	    ((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
 | 
						|
	    ((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
 | 
						|
	    info->initialMask |= (1 << i);
 | 
						|
    }
 | 
						|
    start.mask = info->initialMask;
 | 
						|
    end.mask = info->initialMask;
 | 
						|
    startseg >>= 1;
 | 
						|
    endseg >>= 1;
 | 
						|
    overlap = overlap && (endseg == startseg);
 | 
						|
    if (start.x != end.x || start.y != end.y || !overlap)
 | 
						|
    {
 | 
						|
	if (startseg & 1)
 | 
						|
	{
 | 
						|
	    if (!overlap)
 | 
						|
		info->initialMask &= ~(1 << startseg);
 | 
						|
	    if (start.x > end.x || start.y > end.y)
 | 
						|
		end.mask &= ~(1 << startseg);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    start.mask &= ~(1 << startseg);
 | 
						|
	    if (((start.x < end.x || start.y < end.y) ||
 | 
						|
		 (start.x == end.x && start.y == end.y && (endseg & 1))) &&
 | 
						|
		!overlap)
 | 
						|
		end.mask &= ~(1 << startseg);
 | 
						|
	}
 | 
						|
	if (endseg & 1)
 | 
						|
	{
 | 
						|
	    end.mask &= ~(1 << endseg);
 | 
						|
	    if (((start.x > end.x || start.y > end.y) ||
 | 
						|
		 (start.x == end.x && start.y == end.y && !(startseg & 1))) &&
 | 
						|
		!overlap)
 | 
						|
		start.mask &= ~(1 << endseg);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (!overlap)
 | 
						|
		info->initialMask &= ~(1 << endseg);
 | 
						|
	    if (start.x < end.x || start.y < end.y)
 | 
						|
		start.mask &= ~(1 << endseg);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /* take care of case when start and stop are both near 45 */
 | 
						|
    /* handle here rather than adding extra code to pixelization loops */
 | 
						|
    if (startAngle &&
 | 
						|
	((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0)))
 | 
						|
    {
 | 
						|
	i = (startAngle + OCTANT) % OCTANT;
 | 
						|
	if (i < EPSILON45 || i > OCTANT - EPSILON45)
 | 
						|
	{
 | 
						|
	    i = (endAngle + OCTANT) % OCTANT;
 | 
						|
	    if (i < EPSILON45 || i > OCTANT - EPSILON45)
 | 
						|
	    {
 | 
						|
		if (start.y < 0)
 | 
						|
		{
 | 
						|
		    i = Dsin(startAngle) * (arc->height / 2.0);
 | 
						|
		    if (i < 0)
 | 
						|
			i = -i;
 | 
						|
		    if (info->h - i == end.y)
 | 
						|
			start.mask = end.mask;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
		    i = Dsin(endAngle) * (arc->height / 2.0);
 | 
						|
		    if (i < 0)
 | 
						|
			i = -i;
 | 
						|
		    if (info->h - i == start.y)
 | 
						|
			end.mask = start.mask;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (startseg & 1)
 | 
						|
    {
 | 
						|
	info->start = start;
 | 
						|
	info->end = oob;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	info->end = start;
 | 
						|
	info->start = oob;
 | 
						|
    }
 | 
						|
    if (endseg & 1)
 | 
						|
    {
 | 
						|
	info->altend = end;
 | 
						|
	if (info->altend.x < info->end.x || info->altend.y < info->end.y)
 | 
						|
	{
 | 
						|
	    miZeroArcPtRec tmp;
 | 
						|
	    tmp = info->altend;
 | 
						|
	    info->altend = info->end;
 | 
						|
	    info->end = tmp;
 | 
						|
	}
 | 
						|
	info->altstart = oob;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	info->altstart = end;
 | 
						|
	if (info->altstart.x < info->start.x ||
 | 
						|
	    info->altstart.y < info->start.y)
 | 
						|
	{
 | 
						|
	    miZeroArcPtRec tmp;
 | 
						|
	    tmp = info->altstart;
 | 
						|
	    info->altstart = info->start;
 | 
						|
	    info->start = tmp;
 | 
						|
	}
 | 
						|
	info->altend = oob;
 | 
						|
    }
 | 
						|
    if (!info->start.x || !info->start.y)
 | 
						|
    {
 | 
						|
	info->initialMask = info->start.mask;
 | 
						|
	info->start = info->altstart;
 | 
						|
    }
 | 
						|
    if (!arc->width && (arc->height == 1))
 | 
						|
    {
 | 
						|
	/* kludge! */
 | 
						|
	info->initialMask |= info->end.mask;
 | 
						|
	info->initialMask |= info->initialMask << 1;
 | 
						|
	info->end.x = 0;
 | 
						|
	info->end.mask = 0;
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
#define Pixelate(xval,yval) \
 | 
						|
    { \
 | 
						|
	pts->x = xval; \
 | 
						|
	pts->y = yval; \
 | 
						|
	pts++; \
 | 
						|
    }
 | 
						|
 | 
						|
#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
 | 
						|
 | 
						|
static DDXPointPtr
 | 
						|
miZeroArcPts(xArc *arc, DDXPointPtr pts)
 | 
						|
{
 | 
						|
    miZeroArcRec info;
 | 
						|
    int x, y, a, b, d, mask;
 | 
						|
    int k1, k3, dx, dy;
 | 
						|
    Bool do360;
 | 
						|
 | 
						|
    do360 = miZeroArcSetup(arc, &info, TRUE);
 | 
						|
    MIARCSETUP();
 | 
						|
    mask = info.initialMask;
 | 
						|
    if (!(arc->width & 1))
 | 
						|
    {
 | 
						|
	DoPix(1, info.xorgo, info.yorg);
 | 
						|
	DoPix(3, info.xorgo, info.yorgo);
 | 
						|
    }
 | 
						|
    if (!info.end.x || !info.end.y)
 | 
						|
    {
 | 
						|
	mask = info.end.mask;
 | 
						|
	info.end = info.altend;
 | 
						|
    }
 | 
						|
    if (do360 && (arc->width == arc->height) && !(arc->width & 1))
 | 
						|
    {
 | 
						|
	int yorgh = info.yorg + info.h;
 | 
						|
	int xorghp = info.xorg + info.h;
 | 
						|
	int xorghn = info.xorg - info.h;
 | 
						|
 | 
						|
	while (1)
 | 
						|
	{
 | 
						|
	    Pixelate(info.xorg + x, info.yorg + y);
 | 
						|
	    Pixelate(info.xorg - x, info.yorg + y);
 | 
						|
	    Pixelate(info.xorg - x, info.yorgo - y);
 | 
						|
	    Pixelate(info.xorg + x, info.yorgo - y);
 | 
						|
	    if (a < 0)
 | 
						|
		break;
 | 
						|
	    Pixelate(xorghp - y, yorgh - x);
 | 
						|
	    Pixelate(xorghn + y, yorgh - x);
 | 
						|
	    Pixelate(xorghn + y, yorgh + x);
 | 
						|
	    Pixelate(xorghp - y, yorgh + x);
 | 
						|
	    MIARCCIRCLESTEP(;);
 | 
						|
	}
 | 
						|
	if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
 | 
						|
	    pts -= 4;
 | 
						|
	x = info.w;
 | 
						|
	y = info.h;
 | 
						|
    }
 | 
						|
    else if (do360)
 | 
						|
    {
 | 
						|
	while (y < info.h || x < info.w)
 | 
						|
	{
 | 
						|
	    MIARCOCTANTSHIFT(;);
 | 
						|
	    Pixelate(info.xorg + x, info.yorg + y);
 | 
						|
	    Pixelate(info.xorgo - x, info.yorg + y);
 | 
						|
	    Pixelate(info.xorgo - x, info.yorgo - y);
 | 
						|
	    Pixelate(info.xorg + x, info.yorgo - y);
 | 
						|
	    MIARCSTEP(;,;);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	while (y < info.h || x < info.w)
 | 
						|
	{
 | 
						|
	    MIARCOCTANTSHIFT(;);
 | 
						|
	    if ((x == info.start.x) || (y == info.start.y))
 | 
						|
	    {
 | 
						|
		mask = info.start.mask;
 | 
						|
		info.start = info.altstart;
 | 
						|
	    }
 | 
						|
	    DoPix(0, info.xorg + x, info.yorg + y);
 | 
						|
	    DoPix(1, info.xorgo - x, info.yorg + y);
 | 
						|
	    DoPix(2, info.xorgo - x, info.yorgo - y);
 | 
						|
	    DoPix(3, info.xorg + x, info.yorgo - y);
 | 
						|
	    if ((x == info.end.x) || (y == info.end.y))
 | 
						|
	    {
 | 
						|
		mask = info.end.mask;
 | 
						|
		info.end = info.altend;
 | 
						|
	    }
 | 
						|
	    MIARCSTEP(;,;);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if ((x == info.start.x) || (y == info.start.y))
 | 
						|
	mask = info.start.mask;
 | 
						|
    DoPix(0, info.xorg + x, info.yorg + y);
 | 
						|
    DoPix(2, info.xorgo - x, info.yorgo - y);
 | 
						|
    if (arc->height & 1)
 | 
						|
    {
 | 
						|
	DoPix(1, info.xorgo - x, info.yorg + y);
 | 
						|
	DoPix(3, info.xorg + x, info.yorgo - y);
 | 
						|
    }
 | 
						|
    return pts;
 | 
						|
}
 | 
						|
 | 
						|
#undef DoPix
 | 
						|
#define DoPix(idx,xval,yval) \
 | 
						|
    if (mask & (1 << idx)) \
 | 
						|
    { \
 | 
						|
	arcPts[idx]->x = xval; \
 | 
						|
	arcPts[idx]->y = yval; \
 | 
						|
	arcPts[idx]++; \
 | 
						|
    }
 | 
						|
 | 
						|
static void
 | 
						|
miZeroArcDashPts(
 | 
						|
    GCPtr pGC,
 | 
						|
    xArc *arc,
 | 
						|
    DashInfo *dinfo,
 | 
						|
    DDXPointPtr points,
 | 
						|
    int maxPts,
 | 
						|
    DDXPointPtr *evenPts, 
 | 
						|
    DDXPointPtr *oddPts )
 | 
						|
{
 | 
						|
    miZeroArcRec info;
 | 
						|
    int x, y, a, b, d, mask;
 | 
						|
    int k1, k3, dx, dy;
 | 
						|
    int dashRemaining;
 | 
						|
    DDXPointPtr arcPts[4];
 | 
						|
    DDXPointPtr startPts[5], endPts[5];
 | 
						|
    int deltas[5];
 | 
						|
    DDXPointPtr startPt, pt, lastPt, pts;
 | 
						|
    int i, j, delta, ptsdelta, seg, startseg;
 | 
						|
 | 
						|
    for (i = 0; i < 4; i++)
 | 
						|
	arcPts[i] = points + (i * maxPts);
 | 
						|
    (void)miZeroArcSetup(arc, &info, FALSE);
 | 
						|
    MIARCSETUP();
 | 
						|
    mask = info.initialMask;
 | 
						|
    startseg = info.startAngle / QUADRANT;
 | 
						|
    startPt = arcPts[startseg];
 | 
						|
    if (!(arc->width & 1))
 | 
						|
    {
 | 
						|
	DoPix(1, info.xorgo, info.yorg);
 | 
						|
	DoPix(3, info.xorgo, info.yorgo);
 | 
						|
    }
 | 
						|
    if (!info.end.x || !info.end.y)
 | 
						|
    {
 | 
						|
	mask = info.end.mask;
 | 
						|
	info.end = info.altend;
 | 
						|
    }
 | 
						|
    while (y < info.h || x < info.w)
 | 
						|
    {
 | 
						|
	MIARCOCTANTSHIFT(;);
 | 
						|
	if ((x == info.firstx) || (y == info.firsty))
 | 
						|
	    startPt = arcPts[startseg];
 | 
						|
	if ((x == info.start.x) || (y == info.start.y))
 | 
						|
	{
 | 
						|
	    mask = info.start.mask;
 | 
						|
	    info.start = info.altstart;
 | 
						|
	}
 | 
						|
	DoPix(0, info.xorg + x, info.yorg + y);
 | 
						|
	DoPix(1, info.xorgo - x, info.yorg + y);
 | 
						|
	DoPix(2, info.xorgo - x, info.yorgo - y);
 | 
						|
	DoPix(3, info.xorg + x, info.yorgo - y);
 | 
						|
	if ((x == info.end.x) || (y == info.end.y))
 | 
						|
	{
 | 
						|
	    mask = info.end.mask;
 | 
						|
	    info.end = info.altend;
 | 
						|
	}
 | 
						|
	MIARCSTEP(;,;);
 | 
						|
    }
 | 
						|
    if ((x == info.firstx) || (y == info.firsty))
 | 
						|
	startPt = arcPts[startseg];
 | 
						|
    if ((x == info.start.x) || (y == info.start.y))
 | 
						|
	mask = info.start.mask;
 | 
						|
    DoPix(0, info.xorg + x, info.yorg + y);
 | 
						|
    DoPix(2, info.xorgo - x, info.yorgo - y);
 | 
						|
    if (arc->height & 1)
 | 
						|
    {
 | 
						|
	DoPix(1, info.xorgo - x, info.yorg + y);
 | 
						|
	DoPix(3, info.xorg + x, info.yorgo - y);
 | 
						|
    }
 | 
						|
    for (i = 0; i < 4; i++)
 | 
						|
    {
 | 
						|
	seg = (startseg + i) & 3;
 | 
						|
	pt = points + (seg * maxPts);
 | 
						|
	if (seg & 1)
 | 
						|
	{
 | 
						|
	    startPts[i] = pt;
 | 
						|
	    endPts[i] = arcPts[seg];
 | 
						|
	    deltas[i] = 1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    startPts[i] = arcPts[seg] - 1;
 | 
						|
	    endPts[i] = pt - 1;
 | 
						|
	    deltas[i] = -1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    startPts[4] = startPts[0];
 | 
						|
    endPts[4] = startPt;
 | 
						|
    startPts[0] = startPt;
 | 
						|
    if (startseg & 1)
 | 
						|
    {
 | 
						|
	if (startPts[4] != endPts[4])
 | 
						|
	    endPts[4]--;
 | 
						|
	deltas[4] = 1;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	if (startPts[0] > startPts[4])
 | 
						|
	    startPts[0]--;
 | 
						|
	if (startPts[4] < endPts[4])
 | 
						|
	    endPts[4]--;
 | 
						|
	deltas[4] = -1;
 | 
						|
    }
 | 
						|
    if (arc->angle2 < 0)
 | 
						|
    {
 | 
						|
	DDXPointPtr tmps, tmpe;
 | 
						|
	int tmpd;
 | 
						|
 | 
						|
	tmpd = deltas[0];
 | 
						|
	tmps = startPts[0] - tmpd;
 | 
						|
	tmpe = endPts[0] - tmpd;
 | 
						|
	startPts[0] = endPts[4] - deltas[4];
 | 
						|
	endPts[0] = startPts[4] - deltas[4];
 | 
						|
	deltas[0] = -deltas[4];
 | 
						|
	startPts[4] = tmpe;
 | 
						|
	endPts[4] = tmps;
 | 
						|
	deltas[4] = -tmpd;
 | 
						|
	tmpd = deltas[1];
 | 
						|
	tmps = startPts[1] - tmpd;
 | 
						|
	tmpe = endPts[1] - tmpd;
 | 
						|
	startPts[1] = endPts[3] - deltas[3];
 | 
						|
	endPts[1] = startPts[3] - deltas[3];
 | 
						|
	deltas[1] = -deltas[3];
 | 
						|
	startPts[3] = tmpe;
 | 
						|
	endPts[3] = tmps;
 | 
						|
	deltas[3] = -tmpd;
 | 
						|
	tmps = startPts[2] - deltas[2];
 | 
						|
	startPts[2] = endPts[2] - deltas[2];
 | 
						|
	endPts[2] = tmps;
 | 
						|
	deltas[2] = -deltas[2];
 | 
						|
    }
 | 
						|
    for (i = 0; i < 5 && startPts[i] == endPts[i]; i++)
 | 
						|
	;
 | 
						|
    if (i == 5)
 | 
						|
	return;
 | 
						|
    pt = startPts[i];
 | 
						|
    for (j = 4; startPts[j] == endPts[j]; j--)
 | 
						|
	;
 | 
						|
    lastPt = endPts[j] - deltas[j];
 | 
						|
    if (dinfo->haveLast &&
 | 
						|
	(pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
 | 
						|
    {
 | 
						|
	startPts[i] += deltas[i];
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	dinfo->dashIndex = dinfo->dashIndexInit;
 | 
						|
	dinfo->dashOffset = dinfo->dashOffsetInit;
 | 
						|
    }
 | 
						|
    if (!dinfo->skipStart && (info.startAngle != info.endAngle))
 | 
						|
    {
 | 
						|
	dinfo->startPt = *pt;
 | 
						|
	dinfo->haveStart = TRUE;
 | 
						|
    }
 | 
						|
    else if (!dinfo->skipLast && dinfo->haveStart &&
 | 
						|
	     (lastPt->x == dinfo->startPt.x) &&
 | 
						|
	     (lastPt->y == dinfo->startPt.y) &&
 | 
						|
	     (lastPt != startPts[i]))
 | 
						|
	endPts[j] = lastPt;
 | 
						|
    if (info.startAngle != info.endAngle)
 | 
						|
    {
 | 
						|
	dinfo->haveLast = TRUE;
 | 
						|
	dinfo->endPt = *lastPt;
 | 
						|
    }
 | 
						|
    dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
 | 
						|
    for (i = 0; i < 5; i++)
 | 
						|
    {
 | 
						|
	pt = startPts[i];
 | 
						|
	lastPt = endPts[i];
 | 
						|
	delta = deltas[i];
 | 
						|
	while (pt != lastPt)
 | 
						|
	{
 | 
						|
	    if (dinfo->dashIndex & 1)
 | 
						|
	    {
 | 
						|
		pts = *oddPts;
 | 
						|
		ptsdelta = -1;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pts = *evenPts;
 | 
						|
		ptsdelta = 1;
 | 
						|
	    }
 | 
						|
	    while ((pt != lastPt) && --dashRemaining >= 0)
 | 
						|
	    {
 | 
						|
		*pts = *pt;
 | 
						|
		pts += ptsdelta;
 | 
						|
		pt += delta;
 | 
						|
	    }
 | 
						|
	    if (dinfo->dashIndex & 1)
 | 
						|
		*oddPts = pts;
 | 
						|
	    else
 | 
						|
		*evenPts = pts;
 | 
						|
	    if (dashRemaining <= 0)
 | 
						|
	    {
 | 
						|
		if (++(dinfo->dashIndex) == pGC->numInDashList)
 | 
						|
		    dinfo->dashIndex = 0;
 | 
						|
		dashRemaining = pGC->dash[dinfo->dashIndex];
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miZeroPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
 | 
						|
{
 | 
						|
    int maxPts = 0;
 | 
						|
    int n, maxw = 0;
 | 
						|
    xArc *arc;
 | 
						|
    int i;
 | 
						|
    DDXPointPtr points, pts, oddPts = NULL;
 | 
						|
    DDXPointPtr pt;
 | 
						|
    int numPts;
 | 
						|
    Bool dospans;
 | 
						|
    int *widths = NULL;
 | 
						|
    XID fgPixel = pGC->fgPixel;
 | 
						|
    DashInfo dinfo;
 | 
						|
 | 
						|
    for (arc = parcs, i = narcs; --i >= 0; arc++)
 | 
						|
    {
 | 
						|
	if (!miCanZeroArc(arc))
 | 
						|
	    miPolyArc(pDraw, pGC, 1, arc);
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (arc->width > arc->height)
 | 
						|
		n = arc->width + (arc->height >> 1);
 | 
						|
	    else
 | 
						|
		n = arc->height + (arc->width >> 1);
 | 
						|
	    if (n > maxPts)
 | 
						|
		maxPts = n;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (!maxPts)
 | 
						|
	return;
 | 
						|
    numPts = maxPts << 2;
 | 
						|
    dospans = (pGC->fillStyle != FillSolid);
 | 
						|
    if (dospans)
 | 
						|
    {
 | 
						|
	widths = malloc(sizeof(int) * numPts);
 | 
						|
	if (!widths)
 | 
						|
	    return;
 | 
						|
	maxw = 0;
 | 
						|
    }
 | 
						|
    if (pGC->lineStyle != LineSolid)
 | 
						|
    {
 | 
						|
	numPts <<= 1;
 | 
						|
	dinfo.haveStart = FALSE;
 | 
						|
	dinfo.skipStart = FALSE;
 | 
						|
	dinfo.haveLast = FALSE;
 | 
						|
	dinfo.dashIndexInit = 0;
 | 
						|
	dinfo.dashOffsetInit = 0;
 | 
						|
	miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
 | 
						|
		   (unsigned char *) pGC->dash, (int)pGC->numInDashList,
 | 
						|
		   &dinfo.dashOffsetInit);
 | 
						|
    }
 | 
						|
    points = malloc(sizeof(DDXPointRec) * numPts);
 | 
						|
    if (!points)
 | 
						|
    {
 | 
						|
	if (dospans)
 | 
						|
	{
 | 
						|
	    free(widths);
 | 
						|
	}
 | 
						|
	return;
 | 
						|
    }
 | 
						|
    for (arc = parcs, i = narcs; --i >= 0; arc++)
 | 
						|
    {
 | 
						|
	if (miCanZeroArc(arc))
 | 
						|
	{
 | 
						|
	    if (pGC->lineStyle == LineSolid)
 | 
						|
		pts = miZeroArcPts(arc, points);
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pts = points;
 | 
						|
		oddPts = &points[(numPts >> 1) - 1];
 | 
						|
		dinfo.skipLast = i;
 | 
						|
		miZeroArcDashPts(pGC, arc, &dinfo,
 | 
						|
				 oddPts + 1, maxPts, &pts, &oddPts);
 | 
						|
		dinfo.skipStart = TRUE;
 | 
						|
	    }
 | 
						|
	    n = pts - points;
 | 
						|
	    if (!dospans)
 | 
						|
		(*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		if (n > maxw)
 | 
						|
		{
 | 
						|
		    while (maxw < n)
 | 
						|
			widths[maxw++] = 1;
 | 
						|
		}
 | 
						|
		if (pGC->miTranslate)
 | 
						|
		{
 | 
						|
		    for (pt = points; pt != pts; pt++)
 | 
						|
		    {
 | 
						|
			pt->x += pDraw->x;
 | 
						|
			pt->y += pDraw->y;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		(*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
 | 
						|
	    }
 | 
						|
	    if (pGC->lineStyle != LineDoubleDash)
 | 
						|
		continue;
 | 
						|
	    if ((pGC->fillStyle == FillSolid) ||
 | 
						|
		(pGC->fillStyle == FillStippled))
 | 
						|
	    {
 | 
						|
		ChangeGCVal gcval;
 | 
						|
		gcval.val = pGC->bgPixel;
 | 
						|
		ChangeGC(NullClient, pGC, GCForeground, &gcval);
 | 
						|
		ValidateGC(pDraw, pGC);
 | 
						|
	    }
 | 
						|
	    pts = &points[numPts >> 1];
 | 
						|
	    oddPts++;
 | 
						|
	    n = pts - oddPts;
 | 
						|
	    if (!dospans)
 | 
						|
		(*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		if (n > maxw)
 | 
						|
		{
 | 
						|
		    while (maxw < n)
 | 
						|
			widths[maxw++] = 1;
 | 
						|
		}
 | 
						|
		if (pGC->miTranslate)
 | 
						|
		{
 | 
						|
		    for (pt = oddPts; pt != pts; pt++)
 | 
						|
		    {
 | 
						|
			pt->x += pDraw->x;
 | 
						|
			pt->y += pDraw->y;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		(*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
 | 
						|
	    }
 | 
						|
	    if ((pGC->fillStyle == FillSolid) ||
 | 
						|
		(pGC->fillStyle == FillStippled))
 | 
						|
	    {
 | 
						|
		ChangeGCVal gcval;
 | 
						|
		gcval.val = fgPixel;
 | 
						|
		ChangeGC(NullClient, pGC, GCForeground, &gcval);
 | 
						|
		ValidateGC(pDraw, pGC);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    free(points);
 | 
						|
    if (dospans)
 | 
						|
    {
 | 
						|
	free(widths);
 | 
						|
    }
 | 
						|
}
 |