768 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			768 lines
		
	
	
		
			23 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
 | 
						|
 */
 | 
						|
 | 
						|
#include <dix-config.h>
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xprotostr.h>
 | 
						|
 | 
						|
#include "mi/mi_priv.h"
 | 
						|
 | 
						|
#include "regionstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "pixmapstr.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))
 | 
						|
            miWideArc(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 = xallocarray(numPts, sizeof(int));
 | 
						|
        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 = xallocarray(numPts, sizeof(DDXPointRec));
 | 
						|
    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);
 | 
						|
    }
 | 
						|
}
 |