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; }