[gnu.gcc.bug] cc1 craps out in sparc version

cmc3@BELLCORE.BELLCORE.COM (c.m.chase) (01/06/89)

Here is the CPP output from miarc.c on the X server. 

$ gcc -O bug.c 

will result in cc1 dying with "fatal signal 6"

vital stats
hardware: Sun4/110 (sparc)
OS: Sun OS 4.0
Gcc version: 1.32

If there's any other information I can provide that would be useful,
please let me know.

Craig Chase
cmc3@nvuxr.bellcore.bcr.com

P.S. please respond to let me know that this message arrived intact.  It
is somewhat longish (~75Kbytes)

---------------------------------------------------------------------------
# 1 "miarc.c"


























# 1 "/usr/local/pkg/X11/src/X11/X.h"





































typedef unsigned long XID;

typedef XID Window;
typedef XID Drawable;
typedef XID Font;
typedef XID Pixmap;
typedef XID Cursor;
typedef XID Colormap;
typedef XID GContext;
typedef XID KeySym;

typedef unsigned long Mask;

typedef unsigned long Atom;

typedef unsigned long VisualID;

typedef unsigned long Time;

typedef unsigned char KeyCode;

































































































































































		       



















































































# 311 "/usr/local/pkg/X11/src/X11/X.h"





























































































































































































































































































































































# 27 "miarc.c"

# 1 "/usr/local/pkg/X11/src/X11/Xprotostr.h"



























# 1 "/usr/local/pkg/X11/src/X11/Xmd.h"

























































































typedef long           INT32;
typedef short          INT16;
typedef char           INT8;

typedef unsigned long CARD32;
typedef unsigned short CARD16;
typedef unsigned char  CARD8;

typedef unsigned long		BITS32;
typedef unsigned short		BITS16;
typedef unsigned char		BYTE;

typedef unsigned char            BOOL;
































  




# 28 "/usr/local/pkg/X11/src/X11/Xprotostr.h"




typedef struct _xSegment {
    INT16 x1 , y1 , x2 , y2 ;
} xSegment;



typedef struct _xPoint {
	INT16		x , y ;
} xPoint;

typedef struct _xRectangle {
    INT16 x , y ;
    CARD16  width , height ;
} xRectangle;



typedef struct _xArc {
    INT16 x , y ;
    CARD16   width , height ;
    INT16   angle1 , angle2 ;
} xArc;


# 28 "miarc.c"

# 1 "../../include/misc.h"
































extern unsigned long globalSerialNumber;














typedef unsigned char *pointer;
typedef int Bool;
typedef unsigned long PIXEL;
typedef unsigned long ATOM;






# 1 "../../include/os.h"




























# 1 "../../include/misc.h"
























# 117 "../../include/misc.h"

# 29 "../../include/os.h"



# 1 "/usr/include/alloca.h"




# 32 "../../include/os.h"











typedef pointer	FID;
typedef struct _FontPathRec *FontPathPtr;
typedef struct _NewClientRec *NewClientPtr;










# 69 "../../include/os.h"









char *__builtin_alloca();





# 92 "../../include/os.h"














char		*ReadRequestFromClient();
char		*strcat();
char		*strncat();
char		*strcpy();
char		*strncpy();
Bool		CloseDownConnection();
FontPathPtr	GetFontPath();
FontPathPtr	ExpandFontNamePattern();
FID		FiOpenForRead();
void		CreateWellKnownSockets();
void		SetDefaultFontPath();
void		FreeFontRecord();
void		SetFontPath();
void		ErrorF();
void		Error();
void		FatalError();
void		ProcessCommandLine();
void		Xfree();
void		FlushAllOutput();
void		FlushIfCriticalOutputPending();
unsigned long	*Xalloc();
unsigned long	*Xrealloc();
long		GetTimeInMillis();


# 58 "../../include/misc.h"






    

















































typedef struct _DDXPoint *DDXPointPtr;
typedef struct _Box *BoxPtr;


# 29 "miarc.c"

# 1 "../../include/gcstruct.h"




























# 1 "../../include/gc.h"






















































typedef struct _GCInterest *GCInterestPtr;
typedef struct _GC    *GCPtr;
extern void  ValidateGC();
extern int ChangeGC();
extern GCPtr CreateGC();
extern int CopyGC();
extern int FreeGC();
extern void SetGCMask();
extern GCPtr GetScratchGC();
extern void  FreeScratchGC();

# 29 "../../include/gcstruct.h"


# 1 "../../include/miscstruct.h"



























# 1 "../../include/misc.h"
























# 117 "../../include/misc.h"

# 28 "../../include/miscstruct.h"


extern unsigned long globalSerialNumber;
typedef struct _DDXPoint {
    short x, y;
} DDXPointRec;

typedef struct _Box {
    short x1, y1, x2, y2;
} BoxRec;

# 31 "../../include/gcstruct.h"

# 1 "../../include/region.h"




































typedef struct _Region *RegionPtr;

extern int SingleRectRegionEqual();






# 32 "../../include/gcstruct.h"

# 1 "../../include/pixmap.h"










































typedef struct _DrawInfo *DrawablePtr;	
typedef struct _Pixmap *PixmapPtr;

# 33 "../../include/gcstruct.h"

# 1 "../../include/screenint.h"



























typedef struct _PixmapFormat *PixmapFormatPtr;
typedef struct _Visual *VisualPtr;
typedef struct _Depth  *DepthPtr;
typedef struct _Screen *ScreenPtr;


# 34 "../../include/gcstruct.h"

# 1 "../../include/dixfont.h"





























typedef struct _DIXFontProp *DIXFontPropPtr;
typedef struct _Font *FontPtr;




typedef enum {Linear8Bit, TwoD8Bit, Linear16Bit, TwoD16Bit} FontEncoding;
typedef struct _FontData *FontDataPtr;

extern FontPtr OpenFont();

# 35 "../../include/gcstruct.h"


typedef struct _GCInterest {
    struct _GCInterest	*pNextGCInterest;
    struct _GCInterest	*pLastGCInterest;
    int			length;		
    ATOM		owner;		
    unsigned long	ValInterestMask;
    void		(* ValidateGC) ();
    unsigned long	ChangeInterestMask;
    int			(* ChangeGC) ();
    void		(* CopyGCSource) ();
    void		(* CopyGCDest) ();
    void		(* DestroyGC) ();
    pointer		extPriv;	
} GCInterestRec;

typedef struct _GC{
    ScreenPtr	pScreen;		
    pointer	devPriv;		
    pointer	devBackingStore;	
    int         depth;    
    unsigned long        serialNumber;
    GCInterestPtr	pNextGCInterest;
    GCInterestPtr	pLastGCInterest;
    int		alu;
    unsigned long	planemask;
    unsigned long	fgPixel, bgPixel;
    int		lineWidth;          
    int		lineStyle;
    int		capStyle;
    int		joinStyle;
    int		fillStyle;
    int		fillRule;
    int		arcMode;
    PixmapPtr	tile;
    PixmapPtr	stipple;
    DDXPointRec	patOrg;			
    FontPtr	font;
    int		subWindowMode;
    Bool	graphicsExposures;
    DDXPointRec	clipOrg;
    pointer	clientClip;
    int		clientClipType;		
    int		dashOffset;
    int		numInDashList;		
    unsigned char *dash;		

    unsigned long	stateChanges;	
    DDXPointRec	lastWinOrg;		
    int		miTranslate:1;		

    void (* FillSpans)();
    void (* SetSpans)();

    void (* PutImage)();
    RegionPtr (* CopyArea)();
    RegionPtr (* CopyPlane)();
    void (* PolyPoint)();
    void (* Polylines)();
    void (* PolySegment)();
    void (* PolyRectangle)();
    void (* PolyArc)();
    void (* FillPolygon)();
    void (* PolyFillRect)();
    void (* PolyFillArc)();
    int (* PolyText8)();
    int (* PolyText16)();
    void (* ImageText8)();
    void (* ImageText16)();
    void (* ImageGlyphBlt)();
    void (* PolyGlyphBlt)();
    void (* PushPixels)();
    void (* LineHelper)();
    void (* ChangeClip) ();
    void (* DestroyClip) ();
    void (* CopyClip)();
} GC;


# 30 "miarc.c"

# 1 "../../include/scrnintstr.h"



























# 1 "../../include/screenint.h"
























# 33 "../../include/screenint.h"

# 28 "../../include/scrnintstr.h"

# 1 "../../include/misc.h"
























# 117 "../../include/misc.h"

# 29 "../../include/scrnintstr.h"

# 1 "../../include/region.h"
























# 41 "../../include/region.h"





# 30 "../../include/scrnintstr.h"

# 1 "../../include/pixmap.h"
























# 45 "../../include/pixmap.h"

# 31 "../../include/scrnintstr.h"

# 1 "../../include/gc.h"


























# 65 "../../include/gc.h"

# 32 "../../include/scrnintstr.h"

# 1 "../../include/colormap.h"






































# 55 "../../include/colormap.h"









typedef unsigned long	Pixel;
typedef struct _CMEntry *EntryPtr;
typedef struct _ColormapRec *ColormapPtr;

extern int CreateColormap();
extern Pixel FindColor();
extern int FreeColormap();
extern int TellNoMap();
extern int TellLostMap();
extern int TellGainedMap();
extern int IsMapInstalled();
extern void UninstallColormap();


# 33 "../../include/scrnintstr.h"



typedef struct _PixmapFormat {
    unsigned char	depth;
    unsigned char	bitsPerPixel;
    unsigned char	scanlinePad;
    } PixmapFormatRec;
    
typedef struct _Visual {
    unsigned long	vid;
    short	screen;    
    short       class;
    unsigned long	redMask, greenMask, blueMask;
    int		offsetRed, offsetGreen, offsetBlue;
    short       bitsPerRGBValue;
    short	ColormapEntries;
    short	nplanes;	


  } VisualRec;

typedef struct _Depth {
    int		depth;
    int		numVids;
    unsigned long	*vids;    
  } DepthRec;

typedef struct _Screen {
    int			myNum;	
    ATOM id;
    short		width, height;
    short		mmWidth, mmHeight;
    short		numDepths;
    DepthPtr       	allowedDepths;
    short       	rootDepth;
    unsigned long      	rootVisual;
    unsigned long	defColormap;
    short		minInstalledCmaps, maxInstalledCmaps;
    char                backingStoreSupport, saveUnderSupport;
    unsigned long	whitePixel, blackPixel;
    unsigned long	rgf;	
    GCPtr		GCperDepth[8+1];
			






    PixmapPtr		PixmapPerDepth[1];
    pointer		devPrivate;
    short       	numVisuals;
    VisualPtr		visuals;

    

    Bool (* CloseScreen)();		
    void (* QueryBestSize)();		
    Bool (* SaveScreen)();		
    void (* GetImage)();		

    unsigned int  *(* GetSpans)();	

    void (* PointerNonInterestBox)();	

    

    Bool (* CreateWindow)();		
    Bool (* DestroyWindow)();		
    Bool (* PositionWindow)();		
    Bool (* ChangeWindowAttributes)();	
    Bool (* RealizeWindow)();		
    Bool (* UnrealizeWindow)();		
    int  (* ValidateTree)();		
    void (* WindowExposures)();       

    

    PixmapPtr (* CreatePixmap)(); 	
    Bool (* DestroyPixmap)();		

    

    Bool (* RealizeFont)();		
    Bool (* UnrealizeFont)();		

    
    void (* ConstrainCursor)();   	
    void (* CursorLimits)();		
    Bool (* DisplayCursor)();		
    Bool (* RealizeCursor)();		
    Bool (* UnrealizeCursor)();		
    void (* RecolorCursor)();		
    Bool (* SetCursorPosition)();	

    

    Bool (* CreateGC)();		

    

    void (* CreateColormap)();		
    void (* DestroyColormap)();		
    void (* InstallColormap)();		
    void (* UninstallColormap)();	
    int (* ListInstalledColormaps) (); 	
    void (* StoreColors)();		
    void (* ResolveColor)();		

    

    RegionPtr (* RegionCreate)(); 	
    void (* RegionCopy)();		
    void (* RegionDestroy)();		
    int (* Intersect)();		
    int (* Union)();			
    int (* Subtract)();			
    int (* Inverse)();			
    void (* RegionReset)();		
    void (* TranslateRegion)();		
    int (* RectIn)();			
    Bool (* PointInRegion)();		
    Bool (* RegionNotEmpty)();      	
    void (* RegionEmpty)();        	
    BoxPtr (*RegionExtents)(); 		
    void (* SendGraphicsExpose)();	

    
    void (* BlockHandler)();		
    void (* WakeupHandler)();		
    pointer blockData;
    pointer wakeupData;
} ScreenRec;

typedef struct _ScreenInfo {
    int		imageByteOrder;
    int		bitmapScanlineUnit;
    int		bitmapScanlinePad;
    int		bitmapBitOrder;
    int		numPixmapFormats;
    PixmapFormatRec
		formats[8];
    int		arraySize;
    int		numScreens;
    ScreenPtr	screen;
} ScreenInfo;

extern ScreenInfo screenInfo;

# 31 "miarc.c"

# 1 "../../include/pixmapstr.h"



























# 1 "../../include/pixmap.h"
























# 45 "../../include/pixmap.h"

# 28 "../../include/pixmapstr.h"

# 1 "../../include/screenint.h"
























# 33 "../../include/screenint.h"

# 29 "../../include/pixmapstr.h"

# 1 "../../include/misc.h"
























# 117 "../../include/misc.h"

# 30 "../../include/pixmapstr.h"



typedef struct _DrawInfo {
    short	type;
    ScreenPtr	pScreen;     
    int         depth;          
    unsigned long        serialNumber;
} DrawableRec;




typedef struct _Pixmap {
    DrawableRec drawable;
    int width, height;
    int refcnt;
    int devKind;		
    pointer devPrivate;		
    } PixmapRec;

# 32 "miarc.c"

# 1 "../../include/windowstr.h"




























# 1 "../../include/window.h"

















































typedef struct _BackingStore *BackingStorePtr;
typedef struct _Window *WindowPtr;


# 29 "../../include/windowstr.h"

# 1 "../../include/pixmapstr.h"

























# 50 "../../include/pixmapstr.h"

# 30 "../../include/windowstr.h"

# 1 "../../include/region.h"
























# 41 "../../include/region.h"





# 31 "../../include/windowstr.h"

# 1 "../../include/cursor.h"




























typedef struct _Cursor *CursorPtr;
typedef struct _CursorMetric *CursorMetricPtr;

extern CursorPtr rootCursor;

# 32 "../../include/windowstr.h"

# 1 "../../include/property.h"


























typedef struct _Property *PropertyPtr;

# 33 "../../include/windowstr.h"

# 1 "../../include/resource.h"


























# 1 "../../include/misc.h"
























# 117 "../../include/misc.h"

# 27 "../../include/resource.h"







































unsigned short CreateNewResourceType();
short CreateNewResourceClass();
unsigned long FakeClientID();
void AddResource();
void FreeResource();
void FreeClientResources();
pointer LookupID();


# 34 "../../include/windowstr.h"

# 1 "../../include/dix.h"




























# 1 "../../include/gc.h"


























# 65 "../../include/gc.h"

# 29 "../../include/dix.h"

# 1 "../../include/window.h"

























# 53 "../../include/window.h"

# 30 "../../include/dix.h"






























typedef struct _TimeStamp *TimeStampPtr;
typedef struct _Client *ClientPtr;
extern ClientPtr requestingClient;
extern ClientPtr *clients;
extern ClientPtr serverClient;
extern int currentMaxClients;

extern int ProcAllowEvents();
extern int ProcBell();
extern int ProcChangeActivePointerGrab();
extern int ProcChangeKeyboardControl();
extern int ProcChangePointerControl();
extern int ProcGetKeyboardMapping();
extern int ProcGetPointerMapping();
extern int ProcGetInputFocus();
extern int ProcGetKeyboardControl();
extern int ProcGetMotionEvents();
extern int ProcGetPointerControl();
extern int ProcGrabButton();
extern int ProcGrabKey();
extern int ProcGrabKeyboard();
extern int ProcGrabPointer();
extern int ProcQueryKeymap();
extern int ProcQueryPointer();
extern int ProcSetInputFocus();
extern int ProcSetKeyboardMapping();
extern int ProcSetPointerMapping();
extern int ProcSendEvent();
extern int ProcUngrabButton();
extern int ProcUngrabKey();
extern int ProcUngrabKeyboard();
extern int ProcUngrabPointer();
extern int ProcWarpPointer();
extern int ProcRecolorCursor();

extern WindowPtr LookupWindow();
extern pointer LookupDrawable();

extern void NoopDDA();


# 35 "../../include/windowstr.h"

# 1 "../../include/miscstruct.h"
























# 38 "../../include/miscstruct.h"

# 36 "../../include/windowstr.h"

# 1 "/usr/local/pkg/X11/src/X11/Xprotostr.h"

# 55 "/usr/local/pkg/X11/src/X11/Xprotostr.h"

# 37 "../../include/windowstr.h"





typedef struct _BackingStore {
    RegionPtr obscured;
    DDXPointRec oldAbsCorner;	    
    void (* SaveDoomedAreas)();
    RegionPtr  (* RestoreAreas)();
    void (* ExposeCopy)();  	    
    void (* TranslateBackingStore)(); 

    void (* ClearToBackground)();
    void (* DrawGuarantee)();
} BackingStoreRec;






typedef struct _Window {

	DrawableRec drawable;		

	VisualID visual;

	struct _Window *parent;	        
	struct _Window *nextSib;	        
	struct _Window *prevSib;	        
	struct _Window *firstChild;	
	struct _Window *lastChild;	

	CursorPtr cursor;                 

	ClientPtr client;		
	Window wid;                        

	RegionPtr clipList;               
	RegionPtr winSize;                

	RegionPtr borderClip;             
	RegionPtr borderSize;             
        RegionPtr exposed;                



	
	RegionPtr borderExposed;
	xRectangle clientWinSize;       

	DDXPointRec  absCorner;
	DDXPointRec  oldAbsCorner;      
	int class;                    
	Mask eventMask;
	Mask dontPropagateMask;
	Mask allEventMasks;
	Mask deliverableEvents;
	pointer otherClients;		
	pointer passiveGrabs;		

	PropertyPtr userProps;            

	XID nolongerused; 
	PixmapPtr backgroundTile;
	unsigned long backgroundPixel;
	PixmapPtr borderTile;
	unsigned long borderPixel;
	int borderWidth;
        void (* PaintWindowBackground)();
        void (* PaintWindowBorder)();
	void (* CopyWindow)();
	void (* ClearToBackground)();

	unsigned long backingBitPlanes;
	unsigned long backingPixel;
	int  backingStore;           
	BackingStorePtr backStorage;

	char  bitGravity;
        char  winGravity;
	Colormap colormap;
		
                        
                     
	Bool	saveUnder:1;
        unsigned  visibility:2;		      
	unsigned mapped:1;
	unsigned realized:1;            
	unsigned viewable:1;            
	unsigned overrideRedirect:1;
	unsigned marked:1;

	pointer devBackingStore;		
	pointer devPrivate;			
} WindowRec;

extern int DeleteWindow();
extern int ChangeWindowAttributes();
extern int WalkTree();
extern CreateRootWindow();
extern WindowPtr CreateWindow();
extern int DeleteWindow();
extern int DestroySubwindows();
extern int ChangeWindowAttributes();
extern int GetWindowAttributes();
extern int ConfigureWindow();
extern int ReparentWindow();
extern int MapWindow();
extern int MapSubwindow();
extern int UnmapWindow();
extern int UnmapSubwindow();
extern RegionPtr NotClippedByChildren();



# 33 "miarc.c"

# 1 "mifpoly.h"














































typedef struct _SppPoint {
	double	x, y;
} SppPointRec, *SppPointPtr;

typedef struct _SppArc {
	double	x, y, width, height;
	double	angle1, angle2;
} SppArcRec, *SppArcPtr;

extern SppPointRec miExtendSegment();
# 34 "miarc.c"

# 1 "../../include/mi.h"


























# 1 "../../include/region.h"
























# 41 "../../include/region.h"





# 27 "../../include/mi.h"


typedef struct _miDash *miDashPtr;



extern void  miPutImage();
extern void  miGetImage();
extern RegionPtr  miCopyArea();
extern RegionPtr  miCopyPlane();
extern void  miClearToBackground();
extern int   miValidateTree();
extern void  miPolySegment();
extern void  miPolyRectangle();
extern void  miFillPolygon();
extern int   miPolyText8();
extern int   miPolyText16();
extern void  miImageText8();
extern void  miImageText16();
extern int   miFillConvexPoly();
extern int   miFillGeneralPoly();
extern void miNotMiter();
extern void miMiter();
extern void miWideLine();
extern void miWideDash();
extern void  miPolyArc();
extern void miPolyFillRect();
extern void miPolyFillArc();
extern void  miPolyGlyphBlt();
extern void  miImageGlyphBlt();
extern void  miZeroLine();
extern void  miPaintWindow();
extern miDashPtr   miDashLine();
extern void  miPushPixels();
extern void  miGetPts(), miRoundCap(), miOneSegWide();
extern int   miPtToAngle();
extern    RegionPtr miRegionCreate();
extern    void miRegionCopy();
extern    void miRegionDestroy();
extern    int miIntersect();
extern    int miInverse();
extern    int miUnion();
extern    int miSubtract();
extern    void miRegionReset();
extern    void miTranslateRegion();
extern    int miRectIn();
extern	RegionPtr miRectsToRegion();
extern    Bool miPointInRegion();
extern    Bool miRegionNotEmpty();
extern    void miRegionEmpty();
extern    int miNumberRectsInRegion();
extern    void miWindowExposures();    
extern    BoxPtr miRegionExtents();
extern    void miSendGraphicsExpose();
extern    RegionPtr miHandleExposures();


# 35 "miarc.c"


























extern double sqrt(), cos(), sin(), atan();




















typedef struct _miArcJoin {
	int	arcIndex0, arcIndex1;
	int	phase0, phase1;
	int	end0, end1;
} miArcJoinRec, *miArcJoinPtr;

typedef struct _miArcCap {
	int		arcIndex;
	int		end;		
} miArcCapRec, *miArcCapPtr;

typedef struct _miArcFace {
	SppPointRec	clock;
	SppPointRec	center;
	SppPointRec	counterClock;
} miArcFaceRec, *miArcFacePtr;

typedef struct _miArcData {
	xArc		arc;
	int		render;		
	int		join;		
	int		cap;		
	int		selfJoin;	
	miArcFaceRec	bounds[2];
	double		x0, y0, x1, y1;
} miArcDataRec, *miArcDataPtr;






typedef struct _miPolyArc {
	int		narcs;
	miArcDataPtr	arcs;
	int		ncaps;
	miArcCapPtr	caps;
	int		njoins;
	miArcJoinPtr	joins;
} miPolyArcRec, *miPolyArcPtr;

static miPolyArcPtr miComputeArcs ();









static CARD32 gcvals[6];





static void
miArcSegment(pDraw, pGC, tarc, right, left)
    DrawablePtr   pDraw;
    GCPtr         pGC;
    xArc          tarc;
    miArcFacePtr	right, left;
{
    int l = pGC->lineWidth;
    int	w, h;
    int a0, a1, startAngle, endAngle;
    int st, ct;
    miArcFacePtr	temp;

    if (tarc.width == 0 || tarc.height == 0) {
    	drawZeroArc (pDraw, pGC, tarc, left, right);
	return;
    }

    if (pGC->miTranslate && (pDraw->type == 0)) {
	tarc.x += ((WindowPtr) pDraw)->absCorner.x;
	tarc.y += ((WindowPtr) pDraw)->absCorner.y;
    }

    if (l < 1)
	l = 1;		

    a0 = tarc.angle1;
    a1 = tarc.angle2;
    if (a1 > (64 * 360))
	a1 = (64 * 360);
    else if (a1 < -(64 * 360))
	a1 = -(64 * 360);
    if (a1 < 0) {
    	startAngle = a0 + a1;
	endAngle = a0;
	temp = right;
	right = left;
	left = temp;
    } else {
	startAngle = a0;
	endAngle = a0 + a1;
    }
    


    if (startAngle < 0)
	startAngle = (64 * 360) - (-startAngle) % (64 * 360);
    if (startAngle >= (64 * 360))
	startAngle = startAngle % (64 * 360);
    if (endAngle < 0)
	endAngle = (64 * 360) - (-endAngle) % (64 * 360);
    if (endAngle > (64 * 360))
	endAngle = (endAngle-1) % (64 * 360) + 1;
    if (startAngle == endAngle) {
	startAngle = 0;
	endAngle = (64 * 360);
    }

    drawArc ((int) tarc.x, (int) tarc.y,
             (int) tarc.width, (int) tarc.height, l, startAngle, endAngle,
	     right, left);
}













void
miPolyArc(pDraw, pGC, narcs, parcs)
    DrawablePtr	pDraw;
    GCPtr	pGC;
    int		narcs;
    xArc	*parcs;
{
    register int		i;
    int				xMin, xMax, yMin, yMax;
    int				dx, dy;
    int				xOrg, yOrg;
    double			helperDx, helperDy;
    int				ifirst, count, width;
    Bool			fTricky;
    DrawablePtr			pDrawTo;
    unsigned long		fg, bg;
    GCPtr			pGCTo;
    miPolyArcPtr		polyArcs;
    int				cap[2], join[2];
    int				iphase;

    width = pGC->lineWidth;
    if(width == 0 && pGC->lineStyle == 	0)
    {
	for(i = 0; i < narcs; i++)
	    miArcSegment( pDraw, pGC, parcs[i],
 	    (miArcFacePtr) 0, (miArcFacePtr) 0 );
	fillSpans (pDraw, pGC);
    }
    else 
    {
	
	switch(pGC->alu)
	{
	  case 		0x0		:		
	  case 		0x3		:		
	  case 	0xc		:	
	  case 		0xf		:		
	    fTricky = 0;
	    pDrawTo = pDraw;
	    pGCTo = pGC;
	    break;
	  default:
	    fTricky = 1;

	    xMin = yMin = 32767;
	    xMax = yMax = -32767 ;

	    for(i = 0; i < narcs; i++)
	    {
		xMin = (((xMin) < ( parcs[i].x)) ? (xMin) : ( parcs[i].x));
		yMin = (((yMin) < ( parcs[i].y)) ? (yMin) : ( parcs[i].y));
		xMax = (((xMax) > ( (parcs[i].x + (int) parcs[i].width))) ? (xMax) : ( (parcs[i].x + (int) parcs[i].width)));
		yMax = (((yMax) > ( (parcs[i].y + (int) parcs[i].height))) ? (yMax) : ( (parcs[i].y + (int) parcs[i].height)));
	    }

	    pGCTo = GetScratchGC(1, pDraw->pScreen);
	    gcvals[	0] = 		0x3		;
	    gcvals[	1] = 1;
	    gcvals[	2] = 0;
	    gcvals[	3] = pGC->lineWidth;
	    gcvals[		4] = pGC->capStyle;
	    gcvals[	5] = pGC->joinStyle;
	    DoChangeGC(pGCTo, 	(             (1L<<0) |            (1L<<2) |            (1L<<3) |             (1L<<4) |              (1L<<6) | 	(1L<<7)), gcvals, 0);
    
    	    xOrg = xMin - (width + 1)/2;
	    yOrg = yMin - (width + 1)/2;
	    dx = (xMax - xMin) + width + 1;
	    dy = (yMax - yMin) + width + 1;
	    for(i = 0; i < narcs; i++)
	    {
		parcs[i].x -= xOrg;
		parcs[i].y -= yOrg;
	    }
	    if (pGC->miTranslate && (pDraw->type == 0))
	    {
		xOrg += (double) ((WindowPtr)pDraw)->absCorner.x;
		yOrg += (double) ((WindowPtr)pDraw)->absCorner.y;
	    }

	    

	    pDrawTo = (DrawablePtr)(*pDraw->pScreen->CreatePixmap)
					(pDraw->pScreen, dx, dy, 1, 	0	);
	    ValidateGC(pDrawTo, pGCTo);
	    miClearDrawable(pDrawTo, pGCTo);
	}

	fg = pGCTo->fgPixel;
	bg = pGCTo->bgPixel;
	polyArcs = miComputeArcs (parcs, narcs,
 	    		!(pGC->lineStyle == 	0),
 			pGC->lineStyle == 	2,
			pGC->dash, pGC->numInDashList, pGC->dashOffset);

	if (!polyArcs)
	{
	    if (fTricky) {
		(*pDraw->pScreen->DestroyPixmap) (pDrawTo);
		FreeScratchGC (pGCTo);
	    }
	    return;
	}

	cap[0] = cap[1] = 0;
	join[0] = join[1] = 0;
	for (iphase = ((pGC->lineStyle == 	2) ? 1 : 0);
 	     iphase >= 0;
	     iphase--)
	{
	    if (iphase == 1) {
		gcvals[0] = bg;
		gcvals[1] = fg;
		DoChangeGC (pGC,            (1L<<2)|           (1L<<3), gcvals, 0);
		ValidateGC (pDraw, pGC);
	    } else if (pGC->lineStyle == 	2) {
		gcvals[0] = fg;
		gcvals[1] = bg;
		DoChangeGC (pGC,            (1L<<2)|           (1L<<3), gcvals, 0);
		ValidateGC (pDraw, pGC);
	    }
	    for (i = 0; i < polyArcs[iphase].narcs; i++) {
		miArcDataPtr	arcData;
		int		j;

		arcData = &polyArcs[iphase].arcs[i];
		miArcSegment(pDrawTo, pGCTo, arcData->arc,
			     &arcData->bounds[0],
			     &arcData->bounds[1]);
		if (polyArcs[iphase].arcs[i].render) {
		    fillSpans (pDrawTo, pGCTo);
		    


		    if (polyArcs[iphase].arcs[i].selfJoin &&
		        cap[iphase] < polyArcs[iphase].arcs[i].cap)
		    	cap[iphase]++;
		    while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
			int	arcIndex, end;
			miArcDataPtr	arcData0;

			arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;
			end = polyArcs[iphase].caps[cap[iphase]].end;
			arcData0 = &polyArcs[iphase].arcs[arcIndex];
			miArcCap (pDrawTo, pGCTo,
 				  &arcData0->bounds[end], end,
				  arcData0->arc.x, arcData0->arc.y,
				  (double) arcData0->arc.width / 2.0,
 				  (double) arcData0->arc.height / 2.0);
			++cap[iphase];
		    }
		    while (join[iphase] < polyArcs[iphase].arcs[i].join) {
			int	arcIndex0, arcIndex1, end0, end1;
			int	phase0, phase1;
			miArcDataPtr	arcData0, arcData1;
			miArcJoinPtr	joinp;

			joinp = &polyArcs[iphase].joins[join[iphase]];
			arcIndex0 = joinp->arcIndex0;
			end0 = joinp->end0;
			arcIndex1 = joinp->arcIndex1;
			end1 = joinp->end1;
			phase0 = joinp->phase0;
			phase1 = joinp->phase1;
			arcData0 = &polyArcs[phase0].arcs[arcIndex0];
			arcData1 = &polyArcs[phase1].arcs[arcIndex1];
			miArcJoin (pDrawTo, pGCTo,
				  &arcData0->bounds[end0],
 				  &arcData1->bounds[end1],
				  arcData0->arc.x, arcData0->arc.y,
				  (double) arcData0->arc.width / 2.0,
 				  (double) arcData0->arc.height / 2.0,
				  arcData1->arc.x, arcData1->arc.y,
				  (double) arcData1->arc.width / 2.0,
 				  (double) arcData1->arc.height / 2.0);
			++join[iphase];
		    }
		    if (fTricky) {
		    	(*pGC->PushPixels) (pGC, pDrawTo, pDraw, dx,
					    dy, xOrg, yOrg);
			miClearDrawable ((DrawablePtr) pDrawTo, pGCTo);
		    }
		}
	    }
	}
	for (iphase = ((pGC->lineStyle == 	2) ? 1 : 0);
 	     iphase >= 0;
	     iphase--)
	{
	    if (polyArcs[iphase].narcs > 0)
		Xfree((pointer) polyArcs[iphase].arcs);
	    if (polyArcs[iphase].njoins > 0)
		Xfree ((pointer) polyArcs[iphase].joins);
	    if (polyArcs[iphase].ncaps > 0)
		Xfree ((pointer) polyArcs[iphase].caps);
	}
	Xfree((pointer) polyArcs);

	if(fTricky)
	{
	    (*pGCTo->pScreen->DestroyPixmap)((PixmapPtr)pDrawTo);
	    FreeScratchGC(pGCTo);
	}
    }
}

static double
angleBetween (center, point1, point2)
	SppPointRec	center, point1, point2;
{
	double	atan2 (), a1, a2, a;
	
	



	a1 = atan2 (- (point1.y - center.y), point1.x - center.x);
	a2 = atan2 (- (point2.y - center.y), point2.x - center.x);
	a = a2 - a1;
	if (a < -3.14159265358979323846)
		a += 2 * 3.14159265358979323846;
	else if (a > 3.14159265358979323846)
		a -= 2 * 3.14159265358979323846;
	return a;
}

static
translateBounds (b, x, y, fx, fy)
miArcFacePtr	b;
int		x, y;
double		fx, fy;
{
	b->clock.x -= x + fx;
	b->clock.y -= y + fy;
	b->center.x -= x + fx;
	b->center.y -= y + fy;
	b->counterClock.x -= x + fx;
	b->counterClock.y -= y + fy;
}

miArcJoin (pDraw, pGC, pLeft, pRight,
	   xOrgLeft, yOrgLeft, xFtransLeft, yFtransLeft,
	   xOrgRight, yOrgRight, xFtransRight, yFtransRight)
	DrawablePtr	*pDraw;
	GCPtr		pGC;
	miArcFacePtr	pRight, pLeft;
	int		xOrgRight, yOrgRight;
	double		xFtransRight, yFtransRight;
	int		xOrgLeft, yOrgLeft;
	double		xFtransLeft, yFtransLeft;
{
	SppPointRec	center, corner, otherCorner, end;
	SppPointRec	poly[5], e;
	SppPointPtr	pArcPts;
	int		cpt;
	SppArcRec	arc;
	miArcFaceRec	Right, Left;
	int		polyLen;
	int		xOrg, yOrg;
	double		xFtrans, yFtrans;
	double		angle[4];
	double		a;
	double		ae, ac2, ec2, bc2, de;
	double		width;
	
	xOrg = (xOrgRight + xOrgLeft) / 2;
	yOrg = (yOrgRight + yOrgLeft) / 2;
	xFtrans = (xFtransLeft + xFtransRight) / 2;
	yFtrans = (yFtransLeft + yFtransRight) / 2;
	Right = *pRight;
	translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight,
				 xFtrans - xFtransRight, yFtrans - yFtransRight);
	Left = *pLeft;
	translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft,
				 xFtrans - xFtransLeft, yFtrans - yFtransLeft);
	pRight = &Right;
	pLeft = &Left;

	if (pRight->clock.x == pLeft->counterClock.x &&
	    pRight->clock.y == pLeft->counterClock.y)
		return;
	center = pRight->center;
	if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock))
 	    && a <= 3.14159265358979323846)
 	{
		corner = pRight->clock;
		otherCorner = pLeft->counterClock;
	} else {
		a = angleBetween (center, pLeft->clock, pRight->counterClock);
		corner = pLeft->clock;
		otherCorner = pRight->counterClock;
	}
	switch (pGC->joinStyle) {
	case 	1:
		width = (pGC->lineWidth ? pGC->lineWidth : 1);

		arc.x = center.x - width/2;
		arc.y = center.y - width/2;
		arc.width = width;
		arc.height = width;
		arc.angle1 = -atan2 (corner.y - center.y, corner.x - center.x);
		arc.angle2 = a;
		pArcPts = (SppPointPtr) Xalloc (sizeof (SppPointRec));
		pArcPts->x = center.x;
		pArcPts->y = center.y;
		if( cpt = miGetArcPts(&arc, 1, &pArcPts))
		{
			


			miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans);
			Xfree((pointer)pArcPts);
		}
		return;
	case 	0:
		


		if (a < 169 * 3.14159265358979323846 / 180.0) {
			poly[0] = corner;
			poly[1] = center;
			poly[2] = otherCorner;
			bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) +
			      (corner.y - otherCorner.y) * (corner.y - otherCorner.y);
			ec2 = bc2 / 4;
			ac2 = (corner.x - center.x) * (corner.x - center.x) +
			      (corner.y - center.y) * (corner.y - center.y);
			ae = sqrt (ac2 - ec2);
			de = ec2 / ae;
			e.x = (corner.x + otherCorner.x) / 2;
			e.y = (corner.y + otherCorner.y) / 2;
			poly[3].x = e.x + de * (e.x - center.x) / ae;
			poly[3].y = e.y + de * (e.y - center.y) / ae;
			poly[4] = corner;
			polyLen = 5;
			break;
		}
	case 	2:
		poly[0] = corner;
		poly[1] = center;
		poly[2] = otherCorner;
		poly[3] = corner;
		polyLen = 4;
		break;
	}
	miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans);
}

miArcCap (pDraw, pGC, pFace, end, xOrg, yOrg, xFtrans, yFtrans)
	DrawablePtr	*pDraw;
	GCPtr		pGC;
	miArcFacePtr	pFace;
	int		end;
	int		xOrg, yOrg;
	double		xFtrans, yFtrans;
{
	SppPointRec	corner, otherCorner, center, endPoint, poly[5];

	corner = pFace->clock;
	otherCorner = pFace->counterClock;
	center = pFace->center;
	switch (pGC->capStyle) {
	case 	3:
		poly[0].x = otherCorner.x;
		poly[0].y = otherCorner.y;
		poly[1].x = corner.x;
		poly[1].y = corner.y;
		poly[2].x = corner.x -
 				(center.y - corner.y);
		poly[2].y = corner.y +
 				(center.x - corner.x);
		poly[3].x = otherCorner.x -
 				(otherCorner.y - center.y);
		poly[3].y = otherCorner.y +
 				(otherCorner.x - center.x);
		poly[4].x = otherCorner.x;
		poly[4].y = otherCorner.y;
		miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans);
		break;
	case 	2:
		


		endPoint = center;
		endPoint.x = endPoint.x + 100;
		miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0,
			    -xOrg, -yOrg, xFtrans, yFtrans);
		break;
	}
}







void
miPolyFillArc(pDraw, pGC, narcs, parcs)
    DrawablePtr	pDraw;
    GCPtr	pGC;
    int		narcs;
    xArc	*parcs;
{
    int	i, cpt;
    SppPointPtr pPts;
    SppArcRec	sppArc;
    int		angle1, angle2;

    for(i = 0; i < narcs; i++)
    {
	angle1 = parcs[i].angle1;
	if (angle1 >= (64 * 360))
		angle1 = angle1 % (64 * 360);
	else if (angle1 <= -(64 * 360))
		angle1 = - (-angle1 % (64 * 360));
	angle2 = parcs[i].angle2;
	if (angle2 > (64 * 360))
		angle2 = (64 * 360);
	else if (angle2 < -(64 * 360))
		angle2 = -(64 * 360);
	sppArc.x = parcs[i].x;
	sppArc.y = parcs[i].y;
	sppArc.width = parcs[i].width;
	sppArc.height = parcs[i].height;
	sppArc.angle1 = (((double) (angle1)) / 64.0 * 3.14159265358979323846/180.0);
	sppArc.angle2 = (((double) (angle2)) / 64.0 * 3.14159265358979323846/180.0);
	


        if(pGC->arcMode == 	1	 && parcs[i].angle2 < (64 * 360))
	{
	    if (!(pPts = (SppPointPtr)Xalloc(sizeof(SppPointRec))))
		return;
	    if(cpt = miGetArcPts(&sppArc, 1, &pPts))
	    {
		pPts[0].x = sppArc.x + sppArc.width/2;
		pPts[0].y = sppArc.y + sppArc.height /2;
		miFillSppPoly(pDraw, pGC, cpt + 1, pPts, 0, 0, 0.0, 0.0);
		Xfree((pointer) pPts);
	    }
	}
        else 
	{
	    pPts = (SppPointPtr)           0;
	    if(cpt = miGetArcPts(&sppArc, 0, &pPts))
	    {
		miFillSppPoly(pDraw, pGC, cpt, pPts, 0, 0, 0.0, 0.0);
		Xfree((pointer) pPts);
	    }
	}
    }
}














int
miGetArcPts(parc, cpt, ppPts)
    SppArcPtr	parc;	
    int		cpt;	
    SppPointPtr	*ppPts; 
{
    double 	st,	
                et,	
		dt,	
		cdt,	
    		x0, y0,	
		x1, y1,
		x2, y2, 
		xc, yc, 
                xt, yt;	
    int		count, i, axis, npts = 2; 
    double      asin(), fmax (), sin(), cos ();
    SppPointPtr	poly;
    DDXPointRec last;		

    



    
    st = - parc->angle1;

    et = - parc->angle2;

    



    cdt = fmax(parc->width, parc->height)/2.0;
    if(cdt < 1.0)
	return 0;
    dt = asin( 1.0 / cdt ); 
    count = et/dt;
    count = ((count) > 0 ? (count) : -(count)) + 1;
    dt = et/count;	
    count++;

    cdt = 2 * cos(dt);






    if (!(poly = (SppPointPtr) Xrealloc((pointer)*ppPts,
					(cpt + 2) * sizeof(SppPointRec))))
	return(0);


    xc = parc->width/2.0;		
    yc = parc->height/2.0;
    axis = (xc >= yc) ? 0 : 1;
    
    x0 = xc * cos(st);
    y0 = yc * sin(st);
    x1 = xc * cos(st + dt);
    y1 = yc * sin(st + dt);
    xc += parc->x;		
    yc += parc->y;		

    poly[cpt].x = (xc + x0);
    poly[cpt].y = (yc + y0);
    last.x =   ((int) ((( poly[cpt + 1].x = (xc + x1) ) > 0.0) ? (( poly[cpt + 1].x = (xc + x1) ) + 0.5) : (( poly[cpt + 1].x = (xc + x1) ) - 0.5)));
    last.y =   ((int) ((( poly[cpt + 1].y = (yc + y1) ) > 0.0) ? (( poly[cpt + 1].y = (yc + y1) ) + 0.5) : (( poly[cpt + 1].y = (yc + y1) ) - 0.5)));

    for(i = 2; i < count; i++)
    {
	x2 = cdt * x1 - x0;
	y2 = cdt * y1 - y0;





	xt = xc + x2;
	yt = yc + y2;
 	if (((axis == 0) ?
	     (  ((int) (((yt) > 0.0) ? ((yt) + 0.5) : ((yt) - 0.5))) != last.y) :
	     (  ((int) (((xt) > 0.0) ? ((xt) + 0.5) : ((xt) - 0.5))) != last.x)) ||
	    i > count - 3)	
 	{
	    
	    
 	    if ((npts - 2) % 10		 == 0)
	    {
 		if (!(poly = (SppPointPtr)
		      Xrealloc((pointer) poly,
			       ((npts + 10		 + cpt) *
				sizeof(SppPointRec)))))
		    return(0);
	    }
	    
	    if (((poly[cpt + npts - 2].y - poly[cpt + npts - 1].y > 0.0) ?
		 (yt - poly[cpt + npts - 1].y > 0.0) :
		 (poly[cpt + npts - 1].y - yt > 0.0)) ||
		((poly[cpt + npts - 2].x - poly[cpt + npts - 1].x > 0.0) ?
		 (xt - poly[cpt + npts - 1].x > 0.0) :
		 (poly[cpt + npts - 1].x - xt > 0.0)))
	    {
		


		poly[cpt + npts].x = xc + x1;
		poly[cpt + npts].y = yc + y1;
		npts++;
		if ((npts - 2) % 10		 == 0)
		{
		    if (!(poly = (SppPointPtr)
			  Xrealloc((pointer) poly,
				   ((npts + 10		 + cpt) *
				    sizeof(SppPointRec)))))
			return(0);
		}
	    }
 	    last.x =   ((int) ((( poly[cpt + npts].x = xt ) > 0.0) ? (( poly[cpt + npts].x = xt ) + 0.5) : (( poly[cpt + npts].x = xt ) - 0.5)));
 	    last.y =   ((int) ((( poly[cpt + npts].y = yt ) > 0.0) ? (( poly[cpt + npts].y = yt ) + 0.5) : (( poly[cpt + npts].y = yt ) - 0.5)));
 	    npts++;
 	}


	x0 = x1; y0 = y1;
	x1 = x2; y1 = y2;
    }

    count = i = npts;

    
    if (((parc->angle2) > 0 ? (parc->angle2) : -(parc->angle2)) >= (64 * 360))
	poly[cpt +i -1] = poly[0];
    else {
	poly[cpt +i -1].x = (cos(st + et) * parc->width/2.0 + xc);
	poly[cpt +i -1].y = (sin(st + et) * parc->height/2.0 + yc);
    }


    *ppPts = poly;		

    return(count);
}

struct arcData {
	double	x0, y0, x1, y1;
	int	selfJoin;
};



addCap (capsp, ncapsp, sizep, end, arcIndex)
	miArcCapPtr	*capsp;
	int		*ncapsp, *sizep;
	int		end, arcIndex;
{
	miArcCapPtr	cap;

	if (*ncapsp == *sizep)
		*capsp = (miArcCapPtr) Xrealloc (*capsp,
 				(*sizep += 20) * sizeof (**capsp));
	cap = &(*capsp)[*ncapsp];
	cap->end = end;
	cap->arcIndex = arcIndex;
	++*ncapsp;
}

addJoin (joinsp, njoinsp, sizep, end0, index0, phase0, end1, index1, phase1)
	miArcJoinPtr	*joinsp;
	int		*njoinsp, *sizep;
	int		end0, index0, end1, index1;
{
	miArcJoinPtr	join;

	if (*njoinsp == *sizep)
		*joinsp = (miArcJoinPtr) Xrealloc (*joinsp,
 				(*sizep += 20) * sizeof (**joinsp));
	join = &(*joinsp)[*njoinsp];
	join->end0 = end0;
	join->arcIndex0 = index0;
	join->phase0 = phase0;
	join->end1 = end1;
	join->arcIndex1 = index1;
	join->phase1 = phase1;
	++*njoinsp;
}

miArcDataPtr
addArc (arcsp, narcsp, sizep, xarc)
	miArcDataPtr	*arcsp;
	int		*narcsp, *sizep;
	xArc		xarc;
{
	miArcDataPtr	arc;

	if (*narcsp == *sizep)
		*arcsp = (miArcDataPtr) Xrealloc (*arcsp,
 				(*sizep += 20) * sizeof (**arcsp));
	arc = &(*arcsp)[*narcsp];
	arc->arc = xarc;
	++*narcsp;
	return arc;
}





static miPolyArcPtr
miComputeArcs (parcs, narcs, isDashed, isDoubleDash, pDash, nDashes, dashOffset)
	xArc	*parcs;
	int	narcs;
	int	isDashed, isDoubleDash;
	unsigned char	*pDash;
	int	nDashes, dashOffset;
{
	miPolyArcPtr	arcs;
	int		start, i, j, k, nexti, nextk;
	int		joinSize[2];
	int		capSize[2];
	int		arcSize[2];
	int		angle2;
	double		x0, y0, x1, y1, a0, a1, xc, yc;
	struct arcData	*data;
	miArcDataPtr	arc;
	xArc		xarc;
	int		iphase, prevphase, joinphase;
	int		arcsJoin;
	int		selfJoin;

	int		iDash, dashRemaining;
	int		iDashStart, dashRemainingStart, iphaseStart;
	int		startAngle, spanAngle, endAngle, backwards;
	int		prevDashAngle, dashAngle;
	static int	computeAngleFromPath ();

	arcs = (miPolyArcPtr) Xalloc (sizeof (*arcs) * (isDoubleDash ? 2 : 1));
	data = (struct arcData *) __builtin_alloca((int)(narcs * sizeof (struct arcData)));

	for (i = 0; i < narcs; i++) {
		a0 = (((double) (parcs[i].angle1)) / 64.0 * 3.14159265358979323846/180.0);
		angle2 = parcs[i].angle2;
		if (angle2 > (64 * 360))
			angle2 = (64 * 360);
		else if (angle2 < -(64 * 360))
			angle2 = -(64 * 360);
		data[i].selfJoin = angle2 == (64 * 360) || angle2 == -(64 * 360);
		a1 = (((double) (parcs[i].angle1 + angle2)) / 64.0 * 3.14159265358979323846/180.0);
		data[i].x0 = parcs[i].x + (double) parcs[i].width / 2 * (1 + cos (a0));
		data[i].y0 = parcs[i].y + (double) parcs[i].height / 2 * (1 - sin (a0));
		data[i].x1 = parcs[i].x + (double) parcs[i].width / 2 * (1 + cos (a1));
		data[i].y1 = parcs[i].y + (double) parcs[i].height / 2 * (1 - sin (a1));
	}

	for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) {
		arcs[iphase].njoins = 0;
		arcs[iphase].joins = 0;
		joinSize[iphase] = 0;
		
		arcs[iphase].ncaps = 0;
		arcs[iphase].caps = 0;
		capSize[iphase] = 0;
		
		arcs[iphase].narcs = 0;
		arcs[iphase].arcs = 0;
		arcSize[iphase] = 0;
	}

	iphase = 0;
	if (isDashed) {
		iDash = 0;
		dashRemaining = pDash[0];
	 	while (dashOffset > 0) {
			if (dashOffset >= dashRemaining) {
				dashOffset -= dashRemaining;
				iphase = iphase ? 0 : 1;
				iDash++;
				dashRemaining = pDash[iDash];
			} else {
				dashRemaining -= dashOffset;
				dashOffset = 0;
			}
		}
		iDashStart = iDash;
		dashRemainingStart = dashRemaining;
	}
	iphaseStart = iphase;

	for (i = narcs - 1; i >= 0; i--) {
		j = i + 1;
		if (j == narcs)
			j = 0;
		if (data[i].selfJoin || 
		     (((((data[i].x1) - ( data[j].x0)) > 0.0 ? ((data[i].x1) - ( data[j].x0)) : -((data[i].x1) - ( data[j].x0)))	 > 0.000001) ||
		      ((((data[i].y1) - ( data[j].y0)) > 0.0 ? ((data[i].y1) - ( data[j].y0)) : -((data[i].y1) - ( data[j].y0)))	 > 0.000001)))
 		{
			if (iphase == 0 || isDoubleDash)
				addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
	 				&capSize[iphase], 0, 0);
			break;
		}
	}
	start = i + 1;
	if (start == narcs)
		start = 0;
	i = start;
	for (;;) {
		j = i + 1;
		if (j == narcs)
			j = 0;
		nexti = i+1;
		if (nexti == narcs)
			nexti = 0;
		if (isDashed) {
			



			startAngle = parcs[i].angle1;
			spanAngle = parcs[i].angle2;
			if (spanAngle > (64 * 360))
				spanAngle = (64 * 360);
			else if (spanAngle < -(64 * 360))
				spanAngle = -(64 * 360);
			if (startAngle < 0)
				startAngle = (64 * 360) - (-startAngle) % (64 * 360);
			if (startAngle >= (64 * 360))
				startAngle = startAngle % (64 * 360);
			endAngle = startAngle + spanAngle;
			backwards = spanAngle < 0;
			prevDashAngle = startAngle;
			selfJoin = data[i].selfJoin &&
 				    (iphase == 0 || isDoubleDash);
			while (prevDashAngle != endAngle) {
				dashAngle = computeAngleFromPath
 						(prevDashAngle, endAngle,
		 				  parcs[i].width, parcs[i].height,
						  &dashRemaining, backwards);
				if (iphase == 0 || isDoubleDash) {
					xarc = parcs[i];
					xarc.angle1 = prevDashAngle;
					if (backwards) {
						spanAngle = dashAngle - prevDashAngle;
						if (dashAngle > prevDashAngle)
							spanAngle = - 360 * 64 + spanAngle;
					} else {
						spanAngle = dashAngle - prevDashAngle;
						if (dashAngle < prevDashAngle)
							spanAngle = 360 * 64 + spanAngle;
					}
					xarc.angle2 = spanAngle;
					arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
 							&arcSize[iphase], xarc);
					


					if (!isDoubleDash) {
						if (prevDashAngle != startAngle) {
							addCap (&arcs[iphase].caps,
 								&arcs[iphase].ncaps,
 								&capSize[iphase], 0,
 								arc - arcs[iphase].arcs);
							
						}
						if (dashAngle != endAngle) {
							addCap (&arcs[iphase].caps,
 								&arcs[iphase].ncaps,
 								&capSize[iphase], 1,
 								arc - arcs[iphase].arcs);
						}
					}
					arc->cap = arcs[iphase].ncaps;
					arc->join = arcs[iphase].njoins;
					arc->render = 0;
					arc->selfJoin = 0;
					if (dashAngle == endAngle)
						arc->selfJoin = selfJoin;
				}
				prevphase = iphase;
				if (dashRemaining <= 0) {
					++iDash;
					if (iDash == nDashes)
						iDash = 0;
					iphase = iphase ? 0:1;
					dashRemaining = pDash[iDash];
				}
				prevDashAngle = dashAngle;
			}
		} else {
			arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
 				      &arcSize[iphase], parcs[i]);
			arc->join = arcs[iphase].njoins;
			arc->cap = arcs[iphase].ncaps;
			arc->selfJoin = data[i].selfJoin;
			prevphase = iphase;
		}
		if (prevphase == 0 || isDoubleDash)
			k = arcs[prevphase].narcs - 1;
		if (iphase == 0 || isDoubleDash)
			nextk = arcs[iphase].narcs;
		if (nexti == start) {
			nextk = 0;
			if (isDashed) {
				iDash = iDashStart;
				iphase = iphaseStart;
				dashRemaining = dashRemainingStart;
			}
		}
		arcsJoin = narcs > 1 && 
	 		    ((((data[i].x1) - ( data[j].x0)) > 0.0 ? ((data[i].x1) - ( data[j].x0)) : -((data[i].x1) - ( data[j].x0)))	 <= 0.000001) &&
			    ((((data[i].y1) - ( data[j].y0)) > 0.0 ? ((data[i].y1) - ( data[j].y0)) : -((data[i].y1) - ( data[j].y0)))	 <= 0.000001) &&
			    !data[i].selfJoin && !data[j].selfJoin;
		if (arcsJoin)
			arc->render = 0;
		else
			arc->render = 1;
		if (arcsJoin &&
		    (prevphase == 0 || isDoubleDash) &&
		    (iphase == 0 || isDoubleDash))
 		{
			joinphase = iphase;
			if (isDoubleDash) {
				if (nexti == start)
					joinphase = iphaseStart;
				






				if (joinphase != prevphase)
					joinphase = 0;
			}
			if (joinphase == 0 || isDoubleDash) {
				addJoin (&arcs[joinphase].joins,
 					 &arcs[joinphase].njoins,
 					 &joinSize[joinphase],
	 				 1, k, prevphase,
	 				 0, nextk, iphase);
				arc->join = arcs[prevphase].njoins;
			}
		} else {
			



			if ((prevphase == 0 || isDoubleDash) &&
			    !arc->selfJoin)
			{
				addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps,
 					&capSize[prevphase], 1, k);
				arc->cap = arcs[prevphase].ncaps;
			}
			if (isDashed && !arcsJoin) {
				iDash = iDashStart;
				iphase = iphaseStart;
				dashRemaining = dashRemainingStart;
			}
			nextk = arcs[iphase].narcs;
			if (nexti == start) {
				nextk = 0;
				iDash = iDashStart;
				iphase = iphaseStart;
				dashRemaining = dashRemainingStart;
			}
			








			if ((iphase == 0 || isDoubleDash) &&
			    (nexti != start || arcsJoin && isDashed))
				addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
 					&capSize[iphase], 0, nextk);
		}
		i = nexti;
		if (i == start)
			break;
	}
	


	for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++)
		if (arcs[iphase].narcs > 0) {
			arcs[iphase].arcs[arcs[iphase].narcs-1].render = 1;
			arcs[iphase].arcs[arcs[iphase].narcs-1].join =
			         arcs[iphase].njoins;
			arcs[iphase].arcs[arcs[iphase].narcs-1].cap =
			         arcs[iphase].ncaps;
		}
	return arcs;
}

















static int
computeAngleFromPath (startAngle, endAngle, w, h, lenp, backwards)
	int	startAngle, endAngle;	

	int	*lenp;
	int	backwards;
{
	double	len;
	double	t0, t1, t, l, x0, y0, x1, y1, sidelen;
	int	a, startq, endq, q;
	int	a0, a1;
	double	atan2 (), floor (), acos (), asin ();

	a0 = startAngle;
	a1 = endAngle;
	len = *lenp;
	if (backwards) {
		a0 = (64 * 360) - a0;
		a1 = (64 * 360) - a1;
	}
	if (a1 < a0)
		a1 += (64 * 360);
	startq = floor ((double) a0 / (90.0 * 64.0));
	endq = floor ((double) a1 / (90.0 * 64.0));
	a = a0;
	a0 = a0 - startq * 90 *64;
	a1 = a1 - endq * 90 * 64;
	for (q = startq; q <= endq && len > 0; ++q) {
		



		if (q == startq && a0 != 0) {
			t0 = (((double) (a0 + startq * 90 * 64)) / 64.0 * 3.14159265358979323846/180.0);
			x0 = (double) w / 2 * cos (t0);
			y0 = (double) h / 2* sin (t0);
		} else {
			x0 = 0;
			y0 = 0;
			switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
			case 0: x0 = (double) w/2;	break;
			case 2:	x0 = - (double) w/2;	break;
			case 1:	y0 = (double) h/2;	break;
			case 3:	y0 = -(double) h/2;	break;
			}
		}
		if (q == endq) {
 			if (a1 == 0) {
				x1 = 0;
				y1 = 0;
				switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
				case 0: x1 = (double) w/2;	break;
				case 2:	x1 = - (double) w/2;	break;
				case 1:	y1 = (double) h/2;	break;
				case 3:	y1 = -(double) h/2;	break;
				}
			} else {
				t1 = (((double) (a1 + endq * 90 * 64)) / 64.0 * 3.14159265358979323846/180.0);
				x1 = (double) w / 2 * cos(t1);
				y1 = (double) h / 2 * sin(t1);
			}
		} else {
			x1 = 0;
			y1 = 0;
			switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
			case 0:	y1 = (double) h/2;	break;
			case 2:	y1 = - (double) h/2;	break;
			case 1:	x1 = -(double) w/2;	break;
			case 3:	x1 = (double) w/2;	break;
			}
		}
		




		sidelen = sqrt ((x1-x0)*(x1-x0) + (y1-y0) * (y1-y0));
		if (sidelen >= len) {
			


			x1 = 0;
			y1 = 0;
			switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
			case 0:	y1 = (double) h/2;	break;
			case 2:	y1 = -(double) h/2;	break;
			case 1:	x1 = -(double) w/2;	break;
			case 3:	x1 = (double) w/2;	break;
			}
			sidelen = sqrt ((x1-x0) * (x1-x0) + (y1-y0) * (y1-y0));
			


			y1 = y0 + (y1 - y0) * len / sidelen;
			x1 = x0 + (x1 - x0) * len / sidelen;
			




			if (x1 == (double) w/2 && y1 == 0)
				a1 = 0;
			else if (x1 == -(double) w/2 && y1 == 0)
				a1 = 180 * 64;
			else if (y1 == (double) h/2 && x1 == 0)
				a1 = 90 * 64;
			else if (y1 == -(double) h/2 && x1 == 0)
				a1 = 270 * 64;
			else {
				if (w == 0) {
					t1 = asin (y1 / ((double) h/2));
					switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
					case 1:
					case 2:
						t1 = 3.14159265358979323846 - t1;
					}
				} else if (h == 0) {
					t1 = acos (x1 / ((double) w/2));
					switch (((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4))) {
					case 2:
					case 3:
						t1 = 2 * 3.14159265358979323846 - t1;
					}
 				} else {
					



					t1 = atan2 (y1 * w, x1 * h);
				}
				a1 = (t1 * 180/3.14159265358979323846) * 64.0;
				if (a1 < 0)
					a1 += (64 * 360);
			}
 			a1 -= ((q) >= 0 ? (q) % ( 4) : ( 4) - (-q) % ( 4)) * 90 * 64;
			len = 0;
		} else
			len -= sidelen;
	}
	*lenp = len;
	a1 = a1 + (q-1) * (90*64);
	if (backwards)
		a1 = (64 * 360) - a1;
	return a1;
}



















double
FullDcos (a)
double	a;
{
	double	cos ();
	int	i;

	if (floor (a/90) == a/90) {
		i = (int) (a/90.0);
		switch (((i) >= 0 ? (i) % ( 4) : ( 4) - (-i) % ( 4))) {
		case 0: return 1;
		case 1: return 0;
		case 2: return -1;
		case 3: return 0;
		}
	}
	return cos (a * 3.14159265358979323846 / 180.0);
}

double
FullDsin (a)
double	a;
{
	double	sin ();
	int	i;

	if (floor (a/90) == a/90) {
		i = (int) (a/90.0);
		switch (((i) >= 0 ? (i) % ( 4) : ( 4) - (-i) % ( 4))) {
		case 0: return 0;
		case 1: return 1;
		case 2: return 0;
		case 3: return -1;
		}
	}
	return sin (a * 3.14159265358979323846 / 180.0);
}









extern double	ceil (), floor (), fabs (), sin (), cos (), sqrt (), pow ();





drawZeroArc (pDraw, pGC, tarc, left, right)
    DrawablePtr   pDraw;
    GCPtr         pGC;
    xArc          tarc;
    miArcFacePtr	right, left;
{
	double	x0, y0, x1, y1, w, h;
	int	a0, a1;
	double	startAngle, endAngle;
	double	l;

	l = pGC->lineWidth;
	if (l == 0)
		l = 1;
	l /= 2;
	a0 = tarc.angle1;
	a1 = tarc.angle2;
	if (a1 > (64 * 360))
		a1 = (64 * 360);
	else if (a1 < -(64 * 360))
		a1 = -(64 * 360);
	w = tarc.width / 2.0;
	h = tarc.height / 2.0;
	


	startAngle = - ((double) a0 / 64.0);
	endAngle = - ((double) (a0 + a1) / 64.0);
	
	x0 = w * FullDcos(startAngle);
	y0 = h * FullDsin(startAngle);
	x1 = w * FullDcos(endAngle);
	y1 = h * FullDsin(endAngle);

	if (y0 != y1) {
		if (y0 < y1) {
			x0 = -l;
			x1 = l;
		} else {
			x0 = l;
			x1 = -l;
		}
	} else {
		if (x0 < x1) {
			y0 = -l;
			y1 = l;
		} else {
			y0 = l;
			y1 = -l;
		}
	}
	if (x1 != x0 && y1 != y0) {
		int	minx, maxx, miny, maxy, y, t;
		xRectangle  rect;

		minx = ceil (x0 + w) + tarc.x;
		maxx = ceil (x1 + w) + tarc.x;
		if (minx > maxx) {
			t = minx;
			minx = maxx;
			maxx = t;
		}
		miny = ceil (y0 + h) + tarc.y;
		maxy = ceil (y1 + h) + tarc.y;
		if (miny > maxy) {
			t = miny;
			miny = maxy;
			maxy = t;
		}
		rect.x = minx;
		rect.y = miny;
		rect.width = maxx - minx;
		rect.height = maxy - miny;
		(*pGC->PolyFillRect) (pDraw, pGC, 1, &rect);




	}
	if (right) {
		if (h != 0) {
			right->clock.x = x1;
			right->clock.y = y0;
			right->center.x = 0;
			right->center.y = y0;
			right->counterClock.x = x0;
			right->counterClock.y = y0;
		} else {
			right->clock.x = x0;
			right->clock.y = y0;
			right->center.x = x0;
			right->center.y = 0;
			right->counterClock.x = x0;
			right->counterClock.y = y1;
		}
	}
	if (left) {
		if (h != 0) {
			left->clock.x = x0;
			left->clock.y = y1;
			left->center.x = 0;
			left->center.y = y1;
			left->counterClock.x = x1;
			left->counterClock.y = y1;
		} else {
			left->clock.x = x1;
			left->clock.y = y1;
			left->center.x = x1;
			left->center.y = 0;
			left->counterClock.x = x1;
			left->counterClock.y = y0;
		}
	}
}




struct bound {
	double	min, max;
};

struct line {
	double	m, b;
	int	valid;
};





struct arc_bound {
	struct bound	elipse;
	struct bound	inner;
	struct bound	outer;
	struct bound	right;
	struct bound	left;
};

struct accelerators {
	double		tail_y;
	double		h2;
	double		w2;
	double		h4;
	double		w4;
	double		h2mw2;
	double		wh2mw2;
	double		wh4;
	struct line	left, right;
};

struct arc_def {
	double	w, h, l;
	double	a0, a1;
};

double
Sqrt (x)
double	x;
{
	if (x < 0) {
		if (x > -(0.0000001))
			return 0;
		else
			abort ();
	}
	return sqrt (x);
}

double
fmax (a, b)
double	a,b;
{
	return a > b? a : b;
}

double
fmin (a, b)
double	a, b;
{
	return a < b ? a : b;
}















double
tailElipseY (w, h, l)
	double	w, h, l;
{
	extern double	Sqrt (), pow ();
	double		t;

	if (w != h) {
		t = (pow (h * l * w, 2.0/3.0) - 1.5874010519681993173435330390930175781250 * h*h) /
		    (w*w - h*h);
		if (t < 0)
			return 0;	
		return h / 1.2599210498948732038115849718451499938964 * Sqrt (t);
	} else
		return 0;
}






double
outerXfromXY (x, y, def, acc)
	double			x, y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	return x + (x * acc->h2 * def->l) /
		   (2 * Sqrt (x*x *acc->h4 + y*y * acc->w4));
}

double
outerXfromY (y, def, acc)
	double			y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	double	x;

	x = def->w * Sqrt ((acc->h2 - (y*y)) / acc->h2);

	return x + (x * acc->h2 * def->l) /
		   (2 * Sqrt (x*x *acc->h4 + y*y * acc->w4));
}

double
outerYfromXY (x, y, def, acc)
	double		x, y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	return y + (y * acc->w2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

double
outerYfromY (y, def, acc)
	double	y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	double	x;

	x = def->w * Sqrt ((acc->h2 - (y*y)) / acc->h2);

	return y + (y * acc->w2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

double
innerXfromXY (x, y, def, acc)
	double			x, y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	return x - (x * acc->h2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

double
innerXfromY (y, def, acc)
	double			y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	double	x;

	x = def->w * Sqrt ((acc->h2 - (y*y)) / acc->h2);
	
	return x - (x * acc->h2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

double
innerYfromXY (x, y, def, acc)
	double			x, y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	return y - (y * acc->w2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

double
innerYfromY (y, def, acc)
	double	y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	double	x;

	x = def->w * Sqrt ((acc->h2 - (y*y)) / acc->h2);

	return y - (y * acc->w2 * def->l) /
		   (2 * Sqrt (x*x * acc->h4 + y*y * acc->w4));
}

computeLine (x1, y1, x2, y2, line)
	double		x1, y1, x2, y2;
	struct line	*line;
{
	if (y1 == y2)
		line->valid = 0;
	else {
		line->m = (x1 - x2) / (y1 - y2);
		line->b = x1  - y1 * line->m;
		line->valid = 1;
	}
}

double
intersectLine (y, line)
	double		y;
	struct line	*line;
{
	return line->m * y + line->b;
}



















computeAcc (def, acc)
	struct arc_def		*def;
	struct accelerators	*acc;
{
	acc->h2 = def->h * def->h;
	acc->w2 = def->w * def->w;
	acc->h4 = acc->h2 * acc->h2;
	acc->w4 = acc->w2 * acc->w2;
	acc->h2mw2 = acc->h2 - acc->w2;
	acc->wh2mw2 = def->w * acc->h2mw2;
	acc->wh4 = def->w * acc->h4;
	acc->tail_y = tailElipseY (def->w, def->h, def->l);
}
		





computeBound (def, bound, acc, right, left)
	struct arc_def		*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
	miArcFacePtr		right, left;
{
	double		t, elipseX ();
	double		innerTaily;
	double		tail_y;
	struct bound	innerx, outerx;
	struct bound	elipsex;

	bound->elipse.min = ((def->a0) == 0.0 ? 0.0 : ((def->a0) == 90.0 ? 1.0 : sin(def->a0*3.14159265358979323846/180.0))) * def->h;
	bound->elipse.max = ((def->a1) == 0.0 ? 0.0 : ((def->a1) == 90.0 ? 1.0 : sin(def->a1*3.14159265358979323846/180.0))) * def->h;
	if (def->a0 == 45 && def->w == def->h)
		elipsex.min = bound->elipse.min;
	else
		elipsex.min = ((def->a0) == 0.0 ? 1.0 : ((def->a0) == 90.0 ? 0.0 : cos(def->a0*3.14159265358979323846/180.0))) * def->w;
	if (def->a1 == 45 && def->w == def->h)
		elipsex.max = bound->elipse.max;
	else
		elipsex.max = ((def->a1) == 0.0 ? 1.0 : ((def->a1) == 90.0 ? 0.0 : cos(def->a1*3.14159265358979323846/180.0))) * def->w;
	bound->outer.min = outerYfromXY (elipsex.min, bound->elipse.min, def, acc);
	bound->outer.max = outerYfromXY (elipsex.max, bound->elipse.max, def, acc);
	bound->inner.min = innerYfromXY (elipsex.min, bound->elipse.min, def, acc);
	bound->inner.max = innerYfromXY (elipsex.max, bound->elipse.max, def, acc);

	outerx.min = outerXfromXY (elipsex.min, bound->elipse.min, def, acc);
	outerx.max = outerXfromXY (elipsex.max, bound->elipse.max, def, acc);
	innerx.min = innerXfromXY (elipsex.min, bound->elipse.min, def, acc);
	innerx.max = innerXfromXY (elipsex.max, bound->elipse.max, def, acc);
	
	







	if (right) {
		right->counterClock.y = bound->outer.min;
		right->counterClock.x = outerx.min;
		right->center.y = bound->elipse.min;
		right->center.x = elipsex.min;
		right->clock.y = bound->inner.min;
		right->clock.x = innerx.min;
	}

	if (left) {
		left->clock.y = bound->outer.max;
		left->clock.x = outerx.max;
		left->center.y = bound->elipse.max;
		left->center.x = elipsex.max;
		left->counterClock.y = bound->inner.max;
		left->counterClock.x = innerx.max;
	}

	bound->left.min = bound->inner.max;
	bound->left.max = bound->outer.max;
	bound->right.min = bound->inner.min;
	bound->right.max = bound->outer.min;

	computeLine (innerx.min, bound->inner.min, outerx.min, bound->outer.min,
		      &acc->right);
	computeLine (innerx.max, bound->inner.max, outerx.max, bound->outer.max,
		     &acc->left);

	if (bound->inner.min > bound->inner.max) {
		t = bound->inner.min;
		bound->inner.min = bound->inner.max;
		bound->inner.max = t;
	}
	tail_y = acc->tail_y;
	if (tail_y > bound->elipse.max)
		tail_y = bound->elipse.max;
	else if (tail_y < bound->elipse.min)
		tail_y = bound->elipse.min;
	innerTaily = innerYfromY (tail_y, def, acc);
	if (bound->inner.min > innerTaily)
		bound->inner.min = innerTaily;
	if (bound->inner.max < innerTaily)
		bound->inner.max = innerTaily;
}



































double
elipseY (edge_y, def, bound, acc, outer, y0, y1)
	double			edge_y;
	struct arc_def		*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
	register double		y0, y1;
{
	register double	w, h, l, h2, h4, w2, w4, x, y2;
	double		newtony, binaryy;
	double		value0, value1, valuealt;
	double		newtonvalue, binaryvalue;
	double		minY, maxY;
	double		binarylimit;
	double		(*f)();
	
	


	w = def->w;
	h = def->h;
	f = outer ? outerYfromY : innerYfromY;
	l = outer ? def->l : -def->l;
	h2 = acc->h2;
	h4 = acc->h4;
	w2 = acc->w2;
	w4 = acc->w4;

	value0 = f (y0, def, acc) - edge_y;
	if (value0 == 0)
		return y0;
	value1 = f (y1, def, acc) - edge_y;
	maxY = y1;
	minY = y0;
	if (y0 > y1) {
		maxY = y0;
		minY = y1;
	}
	if (value1 == 0)
		return y1;
	if (value1 > 0 == value0 > 0)
		return -1.0;	
	binarylimit = fabs ((value1 - value0) / 25.0);
	if (binarylimit < (0.1))
		binarylimit = (0.1);
	


	do {
		if (y0 == y1 || value0 == value1)
			return maxY+1;
		binaryy = (y0 + y1) / 2;

		



		y2 = binaryy*binaryy;
		x = w * Sqrt ((h2 - (y2)) / h2);

		binaryvalue = ( binaryy + (binaryy * w2 * l) /
			      (2 * Sqrt (x*x * h4 + y2 * w4))) - edge_y;

		if (binaryvalue > 0 == value0 > 0) {
			y0 = binaryy;
			value0 = binaryvalue;
		} else {
			y1 = binaryy;
			value1 = binaryvalue;
		}
	} while (fabs (value1) > binarylimit);
	if (binaryvalue == 0)
		return binaryy;

	



	while (fabs (value1) > (0.0000001)) {
		newtony = y1 - value1 * (y1 - y0) / (value1 - value0);
		if (newtony > maxY)
			newtony = maxY;
		if (newtony < minY)
			newtony = minY;
		



		y2 = newtony*newtony;
		x = w * Sqrt ((h2 - (y2)) / h2);

		newtonvalue = ( newtony + (newtony * w2 * l) /
			      (2 * Sqrt (x*x * h4 + y2 * w4))) - edge_y;

		if (newtonvalue == 0)
			return newtony;
		if (fabs (value0) > fabs (value1)) {
			y0 = newtony;
			value0 = newtonvalue;
		} else {
			y1 = newtony;
			value1 = newtonvalue;
		}
	}
	return y1;
}

double
elipseX (elipse_y, def, acc)
	double			elipse_y;
	struct arc_def		*def;
	struct accelerators	*acc;
{
	return def->w / def->h * Sqrt (acc->h2 - elipse_y * elipse_y);
}

double
outerX (outer_y, def, bound, acc)
	register double		outer_y;
	register struct arc_def	*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
{
	double	y;

	


	if (def->w == def->h) {
		register double	x;

		x = def->w + def->l/2.0;
		x = Sqrt (x * x - outer_y * outer_y);
		return x;
	}
	if (outer_y == bound->outer.min)
		y = bound->elipse.min;
	if (outer_y == bound->outer.max)
		y = bound->elipse.max;
	else
		y = elipseY (outer_y, def, bound, acc, 1,
 			     bound->elipse.min, bound->elipse.max);
	return outerXfromY (y, def, acc);
}





innerXs (inner_y, def, bound, acc, innerX1p, innerX2p)
	register double		inner_y;
	struct arc_def		*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
	double			*innerX1p, *innerX2p;
{
	register double	x1, x2;
	double		xalt, y0, y1, altY, elipse_y1, elipse_y2;

	


	if (def->w == def->h) {
		x1 = def->w - def->l/2.0;
		x2 = Sqrt (x1 * x1 - inner_y * inner_y);
		if (x1 < 0)
			x2 = -x2;
		*innerX1p = *innerX2p = x2;
		return;
	}
	if ((( bound->elipse).min <= (acc->tail_y) && (acc->tail_y) <= ( bound->elipse).max)) {
		if (def->h > def->w) {
			y0 = bound->elipse.min;
			y1 = acc->tail_y;
			altY = bound->elipse.max;
		} else {
			y0 = bound->elipse.max;
			y1 = acc->tail_y;
			altY = bound->elipse.min;
		}
		elipse_y1 = elipseY (inner_y, def, bound, acc, 0, y0, y1);
		elipse_y2 = elipseY (inner_y, def, bound, acc, 0, y1, altY);
		if (elipse_y1 == -1.0)
			elipse_y1 = elipse_y2;
		if (elipse_y2 == -1.0)
			elipse_y2 = elipse_y1;
	} else {
		elipse_y1 = elipseY (inner_y, def, bound, acc, 0,
				     bound->elipse.min, bound->elipse.max);
		elipse_y2 = elipse_y1;
	}
	x2 = x1 = innerXfromY (elipse_y1, def, acc);
	if (elipse_y1 != elipse_y2)
		x2 = innerXfromY (elipse_y2, def, acc);
	if (acc->left.valid && (( bound->left).min <= (inner_y) && (inner_y) <= ( bound->left).max)) {
		xalt = intersectLine (inner_y, &acc->left);
		if (xalt < x2 && xalt < x1)
			x2 = xalt;
		if (xalt < x1)
			x1 = xalt;
	}
	if (acc->right.valid && (( bound->right).min <= (inner_y) && (inner_y) <= ( bound->right).max)) {
		xalt = intersectLine (inner_y, &acc->right);
		if (xalt < x2 && xalt < x1)
			x2 = xalt;
		if (xalt < x1)
			x1 = xalt;
	}
	*innerX1p = x1;
	*innerX2p = x2;
}



















































double
hookElipseY (scan_y, def, bound, acc, left)
	double			scan_y;
	struct arc_def		*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
{
	double	ret;

	if (acc->h2mw2 == 0) {
		if (scan_y > 0 && !left || scan_y < 0 && left)
			return bound->elipse.min;
		return bound->elipse.max;
	}
	ret = (acc->h4 * scan_y) / (acc->h2mw2);
	if (ret >= 0)
		return pow (ret, 1.0/3.0);
	else
		return -pow (-ret, 1.0/3.0);
}






double
hookX (scan_y, def, bound, acc, left)
	double			scan_y;
	struct arc_def		*def;
	struct arc_bound	*bound;
	struct accelerators	*acc;
	int			left;
{
	double	elipse_y, elipse_x, x, xalt;
	double	maxMin;

	if (def->w != def->h) {
		elipse_y = hookElipseY (scan_y, def, bound, acc, left);
		if ((( bound->elipse).min <= (elipse_y) && (elipse_y) <= ( bound->elipse).max)) {
			



			maxMin = elipse_y*elipse_y*elipse_y * acc->h2mw2 -
		 	 acc->h2 * scan_y * (3 * elipse_y*elipse_y - 2*acc->h2);
			if ((left && maxMin > 0) || (!left && maxMin < 0)) {
				if (elipse_y == 0)
					return def->w + left ? -def->l/2 : def->l/2;
				x = (acc->h2 * scan_y - elipse_y * acc->h2mw2) *
					Sqrt (acc->h2 - elipse_y * elipse_y) /
			 		(def->h * def->w * elipse_y);
				return x;
			}
		}
	}
	if (left) {
		if (acc->left.valid && (( bound->left).min <= (scan_y) && (scan_y) <= ( bound->left).max)) {
			x = intersectLine (scan_y, &acc->left);
		} else {
			if (acc->right.valid)
				x = intersectLine (scan_y, &acc->right);
			else
				x = def->w - def->l/2;
		}
	} else {
		if (acc->right.valid && (( bound->right).min <= (scan_y) && (scan_y) <= ( bound->right).max)) {
			x = intersectLine (scan_y, &acc->right);
		} else {
			if (acc->left.valid)
				x = intersectLine (scan_y, &acc->left);
			else
				x = def->w - def->l/2;
		}
	}
	return x;
}
















arcSpan (y, def, bounds, acc)
	double			y;
	struct arc_def		*def;
	struct arc_bound	*bounds;
	struct accelerators	*acc;
{
	double	innerx1, innerx2, outerx1, outerx2;

	if ((( bounds->inner).min <= (y) && (y) <= ( bounds->inner).max)) {
		


		innerXs (y, def, bounds, acc, &innerx1, &innerx2);
	} else {
		


		innerx2 = innerx1 = hookX (y, def, bounds, acc, 1);
		if (acc->right.valid && (( bounds->right).min <= (y) && (y) <= ( bounds->right).max))
		{
			innerx2 = intersectLine (y, &acc->right);
			if (innerx2 < innerx1)
				innerx1 = innerx2;
		}
	}
	if ((( bounds->outer).min <= (y) && (y) <= ( bounds->outer).max)) {
		


		outerx1 = outerx2 = outerX (y, def, bounds, acc);
	} else {
		


		outerx2 = outerx1 = hookX (y, def, bounds, acc, 0);
		if (acc->left.valid && (( bounds->left).min <= (y) && (y) <= ( bounds->left).max))
 		{
			outerx2 = intersectLine (y, &acc->left);
			if (outerx2 < outerx1)
				outerx2 = outerx1;
		}
	}
	



	if (innerx1 < outerx1 && outerx1 < innerx2 && innerx2 < outerx2) {
		span (innerx1, outerx1);
		span (innerx2, outerx2);
	} else
		span (innerx1, outerx2);
}






static double	arcXcenter, arcYcenter;
static int	arcXoffset, arcYoffset;

static struct finalSpan	**finalSpans;
static int		finalMiny, finalMaxy;
static int		finalSize;

static int		nspans;		

struct finalSpan {
	struct finalSpan	*next;
	int			min, max;	
};

static struct finalSpan    *freeFinalSpans, *tmpFinalSpan;










struct finalSpanChunk {
	struct finalSpan	data[   128];
	struct finalSpanChunk	*next;
};

static struct finalSpanChunk	*chunks;

struct finalSpan *
realAllocSpan ()
{
	register struct finalSpanChunk	*newChunk;
	register struct finalSpan	*span;
	register int			i;

	newChunk = (struct finalSpanChunk *) Xalloc (sizeof (struct finalSpanChunk));
	if (!newChunk)
		return (struct finalSpan *) Xalloc (sizeof (struct finalSpan));
	newChunk->next = chunks;
	chunks = newChunk;
	freeFinalSpans = span = newChunk->data + 1;
	for (i = 1; i <    128-1; i++) {
		span->next = span+1;
		span++;
	}
	span->next = 0;
	span = newChunk->data;
	span->next = 0;
	return span;
}

disposeFinalSpans ()
{
	struct finalSpanChunk	*chunk, *next;

	for (chunk = chunks; chunk; chunk = next) {
		next = chunk->next;
		Xfree (chunk);
	}
	chunks = 0;
	freeFinalSpans = 0;
}

fillSpans (pDrawable, pGC)
    DrawablePtr	pDrawable;
    GCPtr	pGC;
{
	register struct finalSpan	*span;
	register DDXPointPtr		xSpan;
	register int			*xWidth;
	register int			i;
	register struct finalSpan	**f;
	register int			spany;
	DDXPointPtr			xSpans;
	int				*xWidths;

	if (nspans == 0)
		return;
	xSpan = xSpans = (DDXPointPtr) Xalloc (nspans * sizeof (DDXPointRec));
	xWidth = xWidths = (int *) Xalloc (nspans * sizeof (int));
	i = 0;
	f = finalSpans;
	for (spany = finalMiny; spany < finalMaxy; spany++, f++) {
		for (span = *f; span; span=span->next) {
			if (span->max <= span->min) {
				printf ("span width: %d\n", span->max-span->min);
				continue;
			}
			xSpan->x = span->min;
			xSpan->y = spany;
			++xSpan;
			*xWidth++ = span->max - span->min;
			++i;
		}
	}
	disposeFinalSpans ();
	Xfree (finalSpans);
	(*pGC->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, 1);
	Xfree (xSpans);
	Xfree (xWidths);
	finalSpans = 0;
	finalMiny = 0;
	finalMaxy = 0;
	finalSize = 0;
	nspans = 0;
}







struct finalSpan **
realFindSpan (y)
{
	struct finalSpan	**newSpans;
	int			newSize, newMiny, newMaxy;
	int			change;
	int			i;

	if (y < finalMiny || y >= finalMaxy) {
		if (y < finalMiny)
			change = finalMiny - y;
		else
			change = y - finalMaxy;
		if (change > 1024)
			change += 1024;
		else
			change = 1024;
		newSize = finalSize + change;
		newSpans = (struct finalSpan **) Xalloc
 					(newSize * sizeof (struct finalSpan *));
		newMiny = finalMiny;
		newMaxy = finalMaxy;
		if (y < finalMiny)
			newMiny = finalMiny - change;
		else
			newMaxy = finalMaxy + change;
		if (finalSpans) {
			bcopy ((char *) finalSpans,
	 		       ((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *),
			       finalSize * sizeof (struct finalSpan *));
			Xfree (finalSpans);
		}
		if ((i = finalMiny - newMiny) > 0)
			bzero (newSpans, i * sizeof (struct finalSpan *));
		if ((i = newMaxy - finalMaxy) > 0)
			bzero (newSpans + finalMaxy - newMiny,
			       i * sizeof (struct finalSpan *));
		finalSpans = newSpans;
		finalMaxy = newMaxy;
		finalMiny = newMiny;
		finalSize = newSize;
	}
	return &finalSpans[y - finalMiny];
}

newFinalSpan (y, xmin, xmax)
int		y;
register int	xmin, xmax;
{
	register struct finalSpan	*x;
	register struct finalSpan	**f;
	struct finalSpan		*oldx;
	struct finalSpan		*prev;

	f = ((finalMiny <= (y) && (y) < finalMaxy) ? &finalSpans[(y) - finalMiny] : realFindSpan (y));
	oldx = 0;
	for (;;) {
		prev = 0;
		for (x = *f; x; x=x->next) {
			if (x == oldx) {
				prev = x;
				continue;
			}
			if (x->min <= xmax && xmin <= x->max) {
				if (oldx) {
					oldx->min = min (x->min, xmin);
					oldx->max = max (x->max, xmax);
					if (prev)
						prev->next = x->next;
					else
						*f = x->next;
					--nspans;
				} else {
					x->min = min (x->min, xmin);
					x->max = max (x->max, xmax);
					oldx = x;
				}
				xmin = oldx->min;
				xmax = oldx->max;
				break;
			}
			prev = x;
		}
		if (!x)
			break;
	}
	if (!oldx) {
		x =   (freeFinalSpans ?	((tmpFinalSpan = freeFinalSpans), (freeFinalSpans = freeFinalSpans->next), (tmpFinalSpan->next = 0), tmpFinalSpan) : realAllocSpan ());
		x->min = xmin;
		x->max = xmax;
		x->next = *f;
		*f = x;
		++nspans;
	}
}

mirrorSppPoint (quadrant, sppPoint)
	int		quadrant;
	SppPointPtr	sppPoint;
{
	switch (quadrant) {
	case 0:
		break;
	case 1:
		sppPoint->x = -sppPoint->x;
		break;
	case 2:
		sppPoint->x = -sppPoint->x;
		sppPoint->y = -sppPoint->y;
		break;
	case 3:
		sppPoint->y = -sppPoint->y;
		break;
	}
	


	sppPoint->y = -sppPoint->y;
}

static double	spanY;

static int	quadrantMask;

span (left, right)
	double	left, right;
{
	register int	mask = quadrantMask, bit;
	register double	min, max, y;
	int	xmin, xmax, spany;

	while (mask) {
		bit = ((mask) & (~(mask) + 1));
		mask &= ~bit;
		switch (bit) {
		case 1:
			min = left;
			max = right;
			y = spanY;
			break;
		case 2:
			min = -right;
			max = -left;
			y = spanY;
			break;
		case 4:
			min = -right;
			max = -left;
			y = -spanY;
			break;
		case 8:
			min = left;
			max = right;
			y = -spanY;
			break;
		default:
			abort ();
		}
		xmin = (int) ceil (min + arcXcenter) + arcXoffset;
		xmax = (int) ceil (max + arcXcenter) + arcXoffset;
		spany = (int) (ceil (arcYcenter - y)) + arcYoffset;

		if (xmax > xmin)
			newFinalSpan (spany, xmin, xmax);
	}
}









drawArc (x0, y0, w, h, l, a0, a1, right, left)
	int	x0, y0, w, h, l, a0, a1;
	miArcFacePtr	right, left;	
{
	struct arc_def		def;
	struct accelerators	acc;
	struct span		*result;
	int			startq, endq, curq;
	int			rightq, leftq, righta, lefta;
	miArcFacePtr		passRight, passLeft;
	int			q0, q1, mask;
	struct band {
		int	a0, a1;
		int	mask;
	}	band[5], sweep[20];
	int			bandno, sweepno;
	int			i, j, k;
	int			flipRight = 0, flipLeft = 0;			

	def.w = ((double) w) / 2;
	def.h = ((double) h) / 2;
	arcXoffset = x0;
	arcYoffset = y0;
	arcXcenter = def.w;
	arcYcenter = def.h;
	def.l = (double) l;
	if (a1 < a0)
		a1 += 360 * 64;
	startq = a0 / (90 * 64);
	endq = (a1-1) / (90 * 64);
	bandno = 0;
	curq = startq;
	for (;;) {
		switch (curq) {
		case 0:
			if (a0 > 90 * 64)
				q0 = 0;
			else
				q0 = a0;
			if (a1 < 360 * 64)
				q1 = min (a1, 90 * 64);
			else
				q1 = 90 * 64;
			if (curq == startq && a0 == q0) {
				righta = q0;
				rightq = curq;
			}
			if (curq == endq && a1 == q1) {
				lefta = q1;
				leftq = curq;
			}
			break;
		case 1:
			if (a1 < 90 * 64)
				q0 = 0;
			else
				q0 = 180 * 64 - min (a1, 180 * 64);
			if (a0 > 180 * 64)
				q1 = 90 * 64;
			else
				q1 = 180 * 64 - max (a0, 90 * 64);
			if (curq == startq && 180 * 64 - a0 == q1) {
				righta = q1;
				rightq = curq;
			}
			if (curq == endq && 180 * 64 - a1 == q0) {
				lefta = q0;
				leftq = curq;
			}
			break;
		case 2:
			if (a0 > 270 * 64)
				q0 = 0;
			else
				q0 = max (a0, 180 * 64) - 180 * 64;
			if (a1 < 180 * 64)
				q1 = 90 * 64;
			else
				q1 = min (a1, 270 * 64) - 180 * 64;
			if (curq == startq && a0 - 180*64 == q0) {
				righta = q0;
				rightq = curq;
			}
			if (curq == endq && a1 - 180 * 64 == q1) {
				lefta = q1;
				leftq = curq;
			}
			break;
		case 3:
			if (a1 < 270 * 64)
				q0 = 0;
			else
				q0 = 360 * 64 - min (a1, 360 * 64);
			q1 = 360 * 64 - max (a0, 270 * 64);
			if (curq == startq && 360 * 64 - a0 == q1) {
				righta = q1;
				rightq = curq;
			}
			if (curq == endq && 360 * 64 - a1 == q0) {
				lefta = q0;
				leftq = curq;
			}
			break;
		}
		band[bandno].a0 = q0;
		band[bandno].a1 = q1;
		band[bandno].mask = 1 << curq;
		bandno++;
		if (curq == endq)
			break;
		curq++;
		if (curq == 4) {
			a0 = 0;
			a1 -= 360 * 64;
			curq = 0;
			endq -= 4;
		}
	}
	sweepno = 0;
	for (;;) {
		q0 = 90 * 64;
		mask = 0;
		


		for (i = 0; i < bandno; i++)
			if (band[i].a0 < q0) {
				q0 = band[i].a0;
				q1 = band[i].a1;
				mask = band[i].mask;
			}
		if (!mask)
			break;
		


		for (i = 0; i < bandno; i++)
			if (!(mask & band[i].mask)) {
				if (band[i].a0 == q0) {
					if (band[i].a1 < q1)
						q1 = band[i].a1;
					mask |= band[i].mask;
 				} else if (band[i].a0 < q1)
					q1 = band[i].a0;
			}
		


		sweep[sweepno].a0 = q0;
		sweep[sweepno].a1 = q1;
		sweep[sweepno].mask = mask;
		sweepno++;
		


		for (i = 0; i < bandno; i++)
			if (band[i].a0 == q0) {
				band[i].a0 = q1;
				


				if (band[i].a0 == band[i].a1)
					band[i].a1 = band[i].a0 = 90 * 64;
			}
	}
	computeAcc (&def, &acc);
	for (j = 0; j < sweepno; j++) {
		mask = sweep[j].mask;
		passRight = passLeft = 0;
 		if (mask & (1 << rightq)) {
			if (sweep[j].a0 == righta)
				passRight = right;
			if (sweep[j].a1 == righta) {
				passLeft = right;
				flipRight = 1;
			}
		}
		if (mask & (1 << leftq)) {
			if (sweep[j].a0 == lefta) {
				passRight = left;
				flipLeft = 1;
			}
			if (sweep[j].a1 == lefta)
				passLeft = left;
		}
		drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask, 
 			      passRight, passLeft);
	}
	



	if (right) {
		mirrorSppPoint (rightq, &right->clock);
		mirrorSppPoint (rightq, &right->center);
		mirrorSppPoint (rightq, &right->counterClock);
		if (flipRight) {
			SppPointRec	temp;

			temp = right->clock;
			right->clock = right->counterClock;
			right->counterClock = temp;
		}
	}
	if (left) {
		mirrorSppPoint (leftq,  &left->counterClock);
		mirrorSppPoint (leftq,  &left->center);
		mirrorSppPoint (leftq,  &left->clock);
		if (flipLeft) {
			SppPointRec	temp;

			temp = left->clock;
			left->clock = left->counterClock;
			left->counterClock = temp;
		}
	}
}

drawQuadrant (def, acc, a0, a1, mask, right, left)
	struct arc_def		*def;
	struct accelerators	*acc;
	int			a0, a1;
	int			mask;
	miArcFacePtr		right, left;
{
	struct arc_bound	bound;
	double			miny, maxy, y;
	int			minIsInteger;

	def->a0 = ((double) a0) / 64.0;
	def->a1 = ((double) a1) / 64.0;
	computeBound (def, &bound, acc, right, left);
	y = fmin (bound.inner.min, bound.outer.min);
	miny = ceil(y) +  def->w - floor (def->w);
	minIsInteger = y == miny;
	y = fmax (bound.inner.max, bound.outer.max);
	maxy = floor (y) +  def->w - floor (def->w);
	for (y = miny; y <= maxy; y = y + 1.0) {
		if (y == miny && minIsInteger)
			quadrantMask = mask & 0xc;
		else
			quadrantMask = mask;
		spanY = y;
		arcSpan (y, def, &bound, acc);
	}
	


	if (a1 == 90 * 64 && (mask & 1) && ((int) (def->w * 2 + def->l)) & 1) {
		quadrantMask = 1;
		spanY = def->h + def->l/2;
		span (0.0, 1.0);
	}
}

max (x, y)
{
	return x>y? x:y;
}

min (x, y)
{
	return x<y? x:y;
}