/***************************************************************************** * "Irit" - the 3d polygonal solid modeller. * * * * Written by: Gershon Elber Unix - X11 Ver 0.1, Mar. 1990 * ****************************************************************************** * General routines to handle the graphic calls. * * currently supported devices: * * Input: Keyboard, mouse. * * Output: X11 device. * *****************************************************************************/ #ifdef __hpux typedef char *caddr_t; /* Awful kluge. Let me know of a better way. */ #endif /* __hpux */ #include #include #include #include #include #include #include #include #include "graphgen.h" #define POINT_SIZE 0.05 /* Size of + marker drawn. */ #define POINT_TITLE 0.02 /* Distance between point title and + marker. */ #define FONT_NAME "8x13" #define PROGRAM_NAME "irit" #define DEFAULT_TRANS_WIDTH 200 #define DEFAULT_TRANS_HEIGHT 500 #define DEFAULT_VIEW_WIDTH 400 #define DEFAULT_VIEW_HEIGHT 400 /* X global specific staff goes here: */ static Display *XDisplay; static int XScreen; static Window XRoot; static Colormap XColorMap; static GC XTransGraphContext; static GC XViewGraphContext; static Visual *XVisual; static XImage *XImageBuffer; static Pixmap XIcon; static Cursor XCursor; static XColor BlackColor; static XFontStruct *XLoadedFont; static XColor *TransCursorColor = NULL, *ViewCursorColor = NULL; static unsigned long TransBackGroundPixel, TransBorderPixel, TransTextPixel, TransSubWinBackPixel, TransSubWinBorderPixel, ViewBackGroundPixel, ViewBorderPixel, ViewTextPixel; static int XFontYOffsetToCenter = 0, AbortKeyPressed = FALSE, TransHasSize = FALSE, TransHasPos = FALSE, TransPosX = 0, TransPosY = 0, ViewHasSize = FALSE, ViewHasPos = FALSE, ViewPosX = 0, ViewPosY = 0, CurrentXPosition = 0, CurrentYPosition = 0, PopTransWndwAlways = TRUE, LclFullTransMode = TRUE, InGraphicMode = FALSE; static unsigned int TransBorderWidth = 1, TransSubWinBorderWidth = 1, TransWidth = DEFAULT_TRANS_WIDTH, TransHeight = DEFAULT_TRANS_HEIGHT, ViewBorderWidth = 1, ViewWidth = DEFAULT_VIEW_WIDTH, ViewHeight = DEFAULT_VIEW_HEIGHT; /* X Colors to be used for viewed object (see also xgraphic.h): */ int XViewColorDefs[MAX_COLOR + 1][3] = { { 0, 0, 0 }, /* 0. BLACK */ { 0, 0, 43350 }, /* 1. BLUE */ { 0, 43350, 0 }, /* 2. GREEN */ { 0, 43350, 43350 }, /* 3. CYAN */ { 43350, 0, 0 }, /* 4. RED */ { 43350, 0, 43350 }, /* 5. MAGENTA */ { 43350, 43350, 0 }, /* 6. BROWN */ { 43350, 43350, 43350 }, /* 7. LIGHTGREY */ { 21675, 21675, 21675 }, /* 8. DARKGRAY */ { 21675, 21675, 65535 }, /* 9. LIGHTBLUE */ { 21675, 65535, 21675 }, /* 10. LIGHTGREEN */ { 21675, 65535, 65535 }, /* 11. LIGHTCYAN */ { 65535, 21675, 21675 }, /* 12. LIGHTRED */ { 65535, 21675, 65535 }, /* 13. LIGHTMAGENTA */ { 65535, 65535, 21675 }, /* 14. YELLOW */ { 65535, 65535, 65535 } /* 15. WHITE */ }; XColor XViewColors[MAX_COLOR + 1]; /* X Viewing window staff goes here: */ static Window ViewWndw; /* X transformation window staff goes here: */ static Window TransformWndw; static Window ObjScrTglWndw; static Window PersOrthoTglWndw, PersOrthoZWndw; static Window RotateXWndw, RotateYWndw, RotateZWndw; static Window TranslateXWndw, TranslateYWndw, TranslateZWndw; static Window ScaleWndw; static Window DepthCueWndw; static Window SaveGIFWndw; static Window SavePSWndw; static Window SaveMatrixWndw; static Window ResetMatrixWndw; static Window QuitWndw; /* Viewing state variables: */ static int ObjectSpaceState = FALSE, PerspectiveState = FALSE, DepthCueState = FALSE, SubWindowWidthState2 = 1, SubWindowHeightState2 = 1; static int GGMapX(RealType x); static int GGMapY(RealType y); static void ReadXDefaults(void); static char *ReadOneXDefault(char *Entry); static void SetTransformWindow(int argc, char **argv); static void RedrawTransformWindow(void); static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY, unsigned int SubTransWidth, unsigned int SubTransHeight); static void RedrawTransformSubWindow(Window Win, int SubTransPosX, int SubTransPosY, unsigned int SubTransWidth, unsigned int SubTransHeight, int DrawMiddleVertLine, char *DrawString); static void SetViewWindow(int argc, char **argv); static void DrawText(Window Win, char *Str, int PosX, int PosY, unsigned long Color); /**************************************************************************** * Routine to map real -1..1 normalized coordinates to screen X size. * ****************************************************************************/ static int GGMapX(RealType x) { return ((int) ((x + 1.0) * ViewWidth)) / 2; } /**************************************************************************** * Routine to map real -1..1 normalized coordinates to screen Y size. * ****************************************************************************/ static int GGMapY(RealType y) { return ((int) ((1.0 - y) * ViewHeight)) / 2; } /**************************************************************************** * Routine to move to a normalized point between -1..1 on both axes : * ****************************************************************************/ void GGMyMove(RealType x, RealType y) { CurrentXPosition = GGMapX(x); CurrentYPosition = GGMapY(y); } /**************************************************************************** * Routine to draw to a normalized point between -1..1 on both axes : * ****************************************************************************/ void GGMyDraw(RealType x, RealType y) { int NewX, NewY; XDrawLine(XDisplay, ViewWndw, XViewGraphContext, CurrentXPosition, CurrentYPosition, NewX = GGMapX(x), NewY = GGMapY(y)); CurrentXPosition = NewX; CurrentYPosition = NewY; } /**************************************************************************** * Routine to set line style. * ****************************************************************************/ void GGMySetLineStyle(int Style) { switch (Style) { case SOLID_LINE: XSetLineAttributes(XDisplay, XViewGraphContext, 0, LineSolid, CapRound, JoinRound); break; case DOTTED_LINE: XSetLineAttributes(XDisplay, XViewGraphContext, 0, LineOnOffDash, CapRound, JoinRound); break; } } /**************************************************************************** * Routine to draw to a normelized point between -1..1 on both axes : * ****************************************************************************/ void GGMySetColor(int color) { XGCValues values; if (color > MAX_COLOR) color = WHITE; values.foreground = XViewColors[color].pixel; XChangeGC(XDisplay, XViewGraphContext, GCForeground, &values); } /**************************************************************************** * Routine to reset all the system to starting condition : * ****************************************************************************/ void GGInitGraph(int argc, char **argv, int FullTransMode, int TransAlways) { int i; XGCValues values; LclFullTransMode = FullTransMode; PopTransWndwAlways = TransAlways; /* Lets see if we can get access to the X server before we even start: */ if ((XDisplay = (Display *) XOpenDisplay(NULL)) == NULL) { fprintf(stderr, "Failed to access X server, abored.\n"); MyExit(-1); } if ((XLoadedFont = XLoadQueryFont(XDisplay, FONT_NAME)) == NULL) { fprintf(stderr, "Failed to load required X font \"%s\", aborted.\n", FONT_NAME); MyExit(-1); } XFontYOffsetToCenter = (XLoadedFont -> ascent - XLoadedFont -> descent + 1) / 2; XScreen = DefaultScreen(XDisplay); XRoot = RootWindow(XDisplay, XScreen); XColorMap = DefaultColormap(XDisplay, XScreen); XVisual = DefaultVisual(XDisplay, XScreen); values.foreground = WhitePixel(XDisplay, XScreen); values.background = BlackPixel(XDisplay, XScreen); values.font = XLoadedFont -> fid; XTransGraphContext = XCreateGC(XDisplay, XRoot, GCForeground | GCBackground | GCFont, &values); XViewGraphContext = XCreateGC(XDisplay, XRoot, GCForeground | GCBackground, &values); if (XDisplay->db == NULL) XGetDefault(XDisplay, "", ""); ReadXDefaults(); for (i = 0; i <= MAX_COLOR; i++) { XViewColors[i].red = XViewColorDefs[i][0]; XViewColors[i].green = XViewColorDefs[i][1]; XViewColors[i].blue = XViewColorDefs[i][2]; /* If fails to allocate the color - take WHITE instead. */ if (!XAllocColor(XDisplay, XColorMap, &XViewColors[i])) XViewColors[i].pixel = WhitePixel(XDisplay, XScreen); } SetTransformWindow(argc, argv); SetViewWindow(argc, argv); GGGraphicFlush(); InGraphicMode = TRUE; } /**************************************************************************** * Routine to close and shutdown graphic mode : * ****************************************************************************/ void GGCloseGraph(void) { if (!InGraphicMode) return; XFreeGC(XDisplay, XViewGraphContext); XFreeGC(XDisplay, XTransGraphContext); XUnloadFont(XDisplay, XLoadedFont -> fid); XCloseDisplay(XDisplay); InGraphicMode = FALSE; } /***************************************************************************** * Routine to print an message on the given location: * *****************************************************************************/ void GGPutMsgXY(char *s, RealType x, RealType y) { int Len = strlen(s), Width = XTextWidth(XLoadedFont, s, Len), PosX = GGMapX(x), PosY = GGMapY(y); XGCValues values; XDrawString(XDisplay, ViewWndw, XViewGraphContext, PosX - Width / 2, PosY + XFontYOffsetToCenter, s, Len); } /***************************************************************************** * Routine to clear the vewing area. * *****************************************************************************/ void GGClearViewArea(void) { XClearWindow(XDisplay, ViewWndw); } /***************************************************************************** * Routine to make some sound with given Frequency, Time milliseconds: * *****************************************************************************/ void GGTone(int Frequency, int Duration) { if (GlblDoGraphics) XBell(XDisplay, 0); } /***************************************************************************** * Read one default from X resource data base. * *****************************************************************************/ static char *ReadOneXDefault(char *Entry) { XrmString Type; XrmValue Result; char Line[LINE_LEN_LONG]; sprintf(Line, "%s.%s", PROGRAM_NAME, Entry); if ( XrmGetResource(XDisplay->db, Line, "Program.Name", &Type, &Result ) ) return Result.addr; else return NULL; } /***************************************************************************** * Read Defaults from X data base. * *****************************************************************************/ static void ReadXDefaults(void) { int i; XColor Color; char *TransBackGroundColor = ReadOneXDefault("Trans.BackGround"), *TransBorderColor = ReadOneXDefault("Trans*BorderColor"), *TransBorderWidthStr = ReadOneXDefault("Trans*BorderWidth"), *TransTextColor = ReadOneXDefault("Trans.TextColor"), *TransSubWinBackColor = ReadOneXDefault("Trans.SubWin.BackGround"), *TransSubWinBorderColor = ReadOneXDefault("Trans.SubWin.BorderColor"), *TransSubWinBorderWidthStr = ReadOneXDefault("Trans.SubWin.BorderWidth"), *TransGeometry = ReadOneXDefault("Trans.Geometry"), *TransCursorColorStr = ReadOneXDefault("Trans.CursorColor"), *ViewBackGroundColor = ReadOneXDefault("View.BackGround"), *ViewTextColor = ReadOneXDefault("View.TextColor"), *ViewBorderColor = ReadOneXDefault("View.BorderColor"), *ViewBorderWidthStr = ReadOneXDefault("View.BorderWidth"), *ViewGeometry = ReadOneXDefault("View.Geometry"), *ViewCursorColorStr = ReadOneXDefault("View.CursorColor"); if (XParseColor(XDisplay, XColorMap, "Black", &BlackColor)) XAllocColor(XDisplay, XColorMap, &BlackColor); if (TransBackGroundColor != NULL && XParseColor(XDisplay, XColorMap, TransBackGroundColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) TransBackGroundPixel = Color.pixel; else TransBackGroundPixel = BlackPixel(XDisplay, XScreen); if (TransBorderColor != NULL && XParseColor(XDisplay, XColorMap, TransBorderColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) TransBorderPixel = Color.pixel; else TransBorderPixel = WhitePixel(XDisplay, XScreen); if (TransBorderWidthStr) TransBorderWidth = atoi(TransBorderWidthStr); else TransBorderWidth = 1; if (TransTextColor != NULL && XParseColor(XDisplay, XColorMap, TransTextColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) TransTextPixel = Color.pixel; else TransTextPixel = WhitePixel(XDisplay, XScreen); if (TransSubWinBackColor != NULL && XParseColor(XDisplay, XColorMap, TransSubWinBackColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) TransSubWinBackPixel = Color.pixel; else TransSubWinBackPixel = BlackPixel(XDisplay, XScreen); if (TransSubWinBorderColor != NULL && XParseColor(XDisplay, XColorMap, TransSubWinBorderColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) TransSubWinBorderPixel = Color.pixel; else TransSubWinBorderPixel = WhitePixel(XDisplay, XScreen); if (TransSubWinBorderWidthStr) TransSubWinBorderWidth = atoi(TransSubWinBorderWidthStr); else TransSubWinBorderWidth = 1; if (TransGeometry) { i = XParseGeometry(TransGeometry, &TransPosX, &TransPosY, &TransWidth, &TransHeight); TransHasPos = i & XValue && i & YValue; TransHasSize = i & WidthValue && i & HeightValue; } else TransHasSize = TransHasPos = FALSE; if (TransCursorColorStr != NULL && XParseColor(XDisplay, XColorMap, TransCursorColorStr, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) { TransCursorColor = (XColor *) malloc(sizeof(XColor)); *TransCursorColor = Color; } else TransCursorColor = NULL; if (ViewBackGroundColor && XParseColor(XDisplay, XColorMap, ViewBackGroundColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) ViewBackGroundPixel = Color.pixel; else ViewBackGroundPixel = BlackPixel(XDisplay, XScreen); if (ViewBorderColor && XParseColor(XDisplay, XColorMap, ViewBorderColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) ViewBorderPixel = Color.pixel; else ViewBorderPixel = WhitePixel(XDisplay, XScreen); if (ViewTextColor != NULL && XParseColor(XDisplay, XColorMap, ViewTextColor, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) ViewTextPixel = Color.pixel; else ViewTextPixel = WhitePixel(XDisplay, XScreen); if (ViewBorderWidthStr) ViewBorderWidth = atoi(ViewBorderWidthStr); else ViewBorderWidth = 1; if (ViewGeometry) { i = XParseGeometry(ViewGeometry, &ViewPosX, &ViewPosY, &ViewWidth, &ViewHeight); ViewHasPos = i & XValue && i & YValue; ViewHasSize = i & WidthValue && i & HeightValue; } else ViewHasSize = ViewHasPos = FALSE; if (ViewCursorColorStr != NULL && XParseColor(XDisplay, XColorMap, ViewCursorColorStr, &Color) && XAllocColor(XDisplay, XColorMap, &Color)) { ViewCursorColor = (XColor *) malloc(sizeof(XColor)); *ViewCursorColor = Color; } else ViewCursorColor = NULL; } /***************************************************************************** * Set up and draw a transformation window. * *****************************************************************************/ static void SetTransformWindow(int argc, char **argv) { int SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight; long ValueMask; XSizeHints Hints; XSetWindowAttributes SetWinAttr; SetWinAttr.background_pixel = TransBackGroundPixel; SetWinAttr.border_pixel = TransBorderPixel; ValueMask = CWBackPixel | CWBorderPixel; Hints.flags = PMinSize | PMaxSize; Hints.x = Hints.y = 1; Hints.min_width = 100; Hints.max_width = 1000; Hints.min_height = 200; Hints.max_height = 1000; if (TransHasSize) { Hints.flags |= PSize; if (TransWidth < Hints.min_width) TransWidth = Hints.min_width; if (TransWidth > Hints.max_width) TransWidth = Hints.max_width; if (TransHeight < Hints.min_height) TransHeight = Hints.min_height; if (TransHeight > Hints.max_height) TransHeight = Hints.max_height; Hints.width = TransWidth; Hints.height = TransHeight; } else { Hints.flags |= PSize; Hints.width = TransWidth = DEFAULT_TRANS_WIDTH; Hints.height = TransHeight = DEFAULT_TRANS_HEIGHT; } if (TransHasPos) { Hints.flags |= USPosition; Hints.x = TransPosX; Hints.y = TransPosY; } TransformWndw = XCreateWindow(XDisplay, XRoot, TransPosX, TransPosY, TransWidth, TransHeight, 1, 0, CopyFromParent, CopyFromParent, ValueMask, &SetWinAttr); XSetStandardProperties(XDisplay, TransformWndw, PROGRAM_NAME, PROGRAM_NAME, None, argv, argc, &Hints); /* Set our own cursor: */ XCursor = XCreateFontCursor(XDisplay, XC_hand1); XDefineCursor(XDisplay, TransformWndw, XCursor); if (TransCursorColor != NULL) XRecolorCursor(XDisplay, XCursor, TransCursorColor, &BlackColor); /* Now lets create the sub windows inside. Note we do not place them yet. */ SubTransPosX = 0; SubTransPosY = TransHeight; SubTransWidth = TransWidth - SubTransPosX * 2; SubTransHeight = TransHeight / 25; /* OBJECT/SCREEN space toggle: */ ObjScrTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* PERSPECTIVE/ORTHOGRPHIC toggle: */ PersOrthoTglWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); PersOrthoZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* ROTATE: */ RotateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); RotateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); RotateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* TRANSLATE: */ TranslateXWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); TranslateYWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); TranslateZWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* SCALE: */ ScaleWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* DEPTH CUE: */ DepthCueWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); if (LclFullTransMode) { /* SAVE GIF: */ SaveGIFWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* SAVE PS: */ SavePSWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* SAVE MATRIX: */ SaveMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); } /* RESET MATRIX: */ ResetMatrixWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); /* QUIT: */ QuitWndw = SetTransformSubWindow(SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); XSelectInput(XDisplay, TransformWndw, ExposureMask); ObjectSpaceState = GlblTransformMode == TRANS_OBJECT; PerspectiveState = GlblViewMode == VIEW_PERSPECTIVE; DepthCueState = GlblDepthCue; } /***************************************************************************** * Redraw a transformation window (after exposure or resize events). * *****************************************************************************/ static void RedrawTransformWindow(void) { int SubTransPosX, SubTransPosY, SizeChanged = FALSE; unsigned long SubTransWidth, SubTransHeight; long ValueMask; XSizeHints Hints; XWindowAttributes TransWindowAttr; XSetWindowAttributes SetWinAttr; XClearWindow(XDisplay, TransformWndw); /* Get the window attributes, and see if it is the same size or not. */ XGetWindowAttributes(XDisplay, TransformWndw, &TransWindowAttr); if (TransWindowAttr.width != TransWidth || TransWindowAttr.height != TransHeight) { SizeChanged = TRUE; TransWidth = TransWindowAttr.width; TransHeight = TransWindowAttr.height; } /* Now lets update the sub windows inside: */ SubTransPosX = MIN(TransWidth / 10, 20); SubTransPosY = TransHeight / (LclFullTransMode ? 30 : 25); SubTransWidth = TransWidth - SubTransPosX * 2; SubTransHeight = TransHeight / (LclFullTransMode ? 30 : 25); /* OBJECT/SCREEN space toggle: */ RedrawTransformSubWindow(ObjScrTglWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, GlblTransformMode == TRANS_OBJECT ? "Object" : "Screen"); SubTransPosY += SubTransHeight * 2; /* PERSPECTIVE/ORTHOGRAPHIC toggle: */ RedrawTransformSubWindow(PersOrthoTglWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, GlblViewMode == VIEW_ORTHOGRAPHIC ? "Orthographic" : "Perspective"); SubTransPosY += SubTransHeight; RedrawTransformSubWindow(PersOrthoZWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Z", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); SubTransPosY += SubTransHeight; /* ROTATE: */ DrawText(TransformWndw, "Rotate", TransWidth / 2, SubTransPosY, TransTextPixel); SubTransPosY += SubTransHeight / 2; RedrawTransformSubWindow(RotateXWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "X", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); RedrawTransformSubWindow(RotateYWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Y", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); RedrawTransformSubWindow(RotateZWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Z", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); /* TRANSLATE: */ SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Translate", TransWidth / 2, SubTransPosY, TransTextPixel); SubTransPosY += SubTransHeight / 2; RedrawTransformSubWindow(TranslateXWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "X", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); RedrawTransformSubWindow(TranslateYWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Y", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); RedrawTransformSubWindow(TranslateZWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Z", SubTransPosX / 2, SubTransPosY - SubTransHeight / 4, TransTextPixel); /* SCALE: */ SubTransPosY += SubTransHeight; DrawText(TransformWndw, "Scale", TransWidth / 2, SubTransPosY, TransTextPixel); SubTransPosY += SubTransHeight / 2; RedrawTransformSubWindow(ScaleWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, TRUE, NULL); /* DEPTH CUE: */ SubTransPosY += SubTransHeight * 2; RedrawTransformSubWindow(DepthCueWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, GlblDepthCue ? "Depth Cue" : "No Depth Cue"); if (LclFullTransMode) { /* SAVE GIF: */ SubTransPosY += SubTransHeight * 2; RedrawTransformSubWindow(SaveGIFWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, "Save GIF"); /* SAVE PS: */ SubTransPosY += SubTransHeight * 2; RedrawTransformSubWindow(SavePSWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, "Save PS"); /* SAVE MATRIX: */ SubTransPosY += SubTransHeight * 2; RedrawTransformSubWindow(SaveMatrixWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, "Save Matrix"); } /* RESET MATRIX: */ SubTransPosY += SubTransHeight * 2; RedrawTransformSubWindow(ResetMatrixWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, "Reset Matrix"); /* QUIT: */ SubTransPosY += SubTransHeight * 3; RedrawTransformSubWindow(QuitWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, FALSE, "Quit" ); /* Save half of the window width so we can refer to the zero point on X */ /* axes, which is the vertical line in the middle of the window: */ SubWindowWidthState2 = SubTransWidth / 2; SubWindowHeightState2 = SubTransHeight / 2; GGGraphicFlush(); } /***************************************************************************** * Set up a transformation sub window. * *****************************************************************************/ static Window SetTransformSubWindow(int SubTransPosX, int SubTransPosY, unsigned int SubTransWidth, unsigned int SubTransHeight) { long ValueMask; XSetWindowAttributes SetWinAttr; Window Win; SetWinAttr.background_pixel = TransSubWinBackPixel; SetWinAttr.border_pixel = TransSubWinBorderPixel; SetWinAttr.bit_gravity = SetWinAttr.win_gravity = CenterGravity; ValueMask = CWBackPixel | CWBorderPixel | CWBitGravity | CWWinGravity; Win = XCreateWindow(XDisplay, TransformWndw, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight, 1, 0, CopyFromParent, CopyFromParent, ValueMask, &SetWinAttr); XSelectInput(XDisplay, Win, ButtonPressMask | Button1MotionMask); XMapWindow(XDisplay, Win); return Win; } /***************************************************************************** * Redraw a transformation sub window. * *****************************************************************************/ static void RedrawTransformSubWindow(Window Win, int SubTransPosX, int SubTransPosY, unsigned int SubTransWidth, unsigned int SubTransHeight, int DrawMiddleVertLine, char *DrawString) { XGCValues values; XMoveResizeWindow(XDisplay, Win, SubTransPosX, SubTransPosY, SubTransWidth, SubTransHeight); if (DrawMiddleVertLine) { values.foreground = TransSubWinBorderPixel; XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values); XDrawLine(XDisplay, Win, XTransGraphContext, SubTransWidth / 2, 0, SubTransWidth / 2, SubTransHeight); } if (DrawString != NULL) { DrawText(Win, DrawString, SubTransWidth / 2, SubTransHeight / 2, TransTextPixel); } } /***************************************************************************** * Set up a view window. * *****************************************************************************/ static void SetViewWindow(int argc, char **argv) { long ValueMask; XSizeHints Hints; XSetWindowAttributes SetWinAttr; SetWinAttr.background_pixel = ViewBackGroundPixel; SetWinAttr.border_pixel = ViewBorderPixel; ValueMask = CWBackPixel | CWBorderPixel; Hints.flags = PMinSize | PMaxSize; Hints.x = Hints.y = 1; Hints.min_width = 50; Hints.max_width = 1000; Hints.min_height = 50; Hints.max_height = 1000; if (ViewHasSize) { Hints.flags |= PSize; if (ViewWidth < Hints.min_width) ViewWidth = Hints.min_width; if (ViewWidth > Hints.max_width) ViewWidth = Hints.max_width; if (ViewHeight < Hints.min_height) ViewHeight = Hints.min_height; if (ViewHeight > Hints.max_height) ViewHeight = Hints.max_height; Hints.width = ViewWidth; Hints.height = ViewHeight; } else { Hints.flags |= PSize; Hints.width = ViewWidth = DEFAULT_VIEW_WIDTH; Hints.height = ViewHeight = DEFAULT_VIEW_HEIGHT; } if (ViewHasPos) { Hints.flags |= USPosition; Hints.x = ViewPosX; Hints.y = ViewPosY; } ViewWndw = XCreateWindow(XDisplay, XRoot, ViewPosX, ViewPosY, ViewWidth, ViewHeight, 1, 0, CopyFromParent, CopyFromParent, ValueMask, &SetWinAttr); XSetStandardProperties(XDisplay, ViewWndw, PROGRAM_NAME, PROGRAM_NAME, None, argv, argc, &Hints); /* Set our own cursor: */ XCursor = XCreateFontCursor(XDisplay, XC_iron_cross); XDefineCursor(XDisplay, ViewWndw, XCursor); if (ViewCursorColor != NULL) XRecolorCursor(XDisplay, XCursor, ViewCursorColor, &BlackColor); XSelectInput(XDisplay, ViewWndw, ExposureMask | ButtonPressMask); XMapWindow(XDisplay, ViewWndw); } /***************************************************************************** * Return View window ID and the address of the display it is in. * *****************************************************************************/ long GGGetViewWindowID(long *XDisplayAddr, long *XColorMapID) { *XDisplayAddr = (long) XDisplay; *XColorMapID = (long) XColorMap; return (long) ViewWndw; } /****************************************************************************** * Returns status of abort key if pressed, and reset it. * ******************************************************************************/ int GGIsAbortKeyPressed(void) { int RetVal = AbortKeyPressed; AbortKeyPressed = FALSE; return RetVal; } /****************************************************************************** * Flush output of graphic command. * ******************************************************************************/ void GGGraphicFlush(void) { XFlush(XDisplay); } /****************************************************************************** * Handle X events * ******************************************************************************/ GraphicEventType GGGetGraphicEvent(RealType *ChangeFactor) { static int LastX; int Dx; XEvent Event; XWindowAttributes WinAttr; XMapWindow(XDisplay, TransformWndw); while (TRUE) { XNextEvent(XDisplay, &Event); switch (Event.type) { case Expose: /* Get rid of all Expose events in the queue. */ while (XCheckWindowEvent(XDisplay, Event.xbutton.window, ExposureMask, &Event)); if (Event.xbutton.window == TransformWndw) RedrawTransformWindow(); else if (Event.xbutton.window == ViewWndw) { XGetWindowAttributes(XDisplay, ViewWndw, &WinAttr); ViewWidth = WinAttr.width; ViewHeight = WinAttr.height; UpdateInteractHandleInput(); } break; case ButtonPress: LastX = Event.xbutton.x; *ChangeFactor = ((RealType) (LastX - SubWindowWidthState2)) / SubWindowWidthState2; if (Event.xbutton.button == 3) { AbortKeyPressed = TRUE; break; } if (Event.xbutton.window == ObjScrTglWndw) { XClearWindow(XDisplay, ObjScrTglWndw); GlblTransformMode = GlblTransformMode == TRANS_OBJECT ? TRANS_SCREEN : TRANS_OBJECT; DrawText(ObjScrTglWndw, GlblTransformMode == TRANS_OBJECT ? "Object" : "Screen", SubWindowWidthState2, SubWindowHeightState2, TransTextPixel); return EVENT_SCR_OBJ_TGL; } else if (Event.xbutton.window == PersOrthoTglWndw) { XClearWindow(XDisplay, PersOrthoTglWndw); GlblViewMode = GlblViewMode == VIEW_PERSPECTIVE ? VIEW_ORTHOGRAPHIC : VIEW_PERSPECTIVE; DrawText(PersOrthoTglWndw, GlblViewMode == VIEW_PERSPECTIVE ? "Perspective" : "Orthographic", SubWindowWidthState2, SubWindowHeightState2, TransTextPixel); return EVENT_PERS_ORTHO_TGL; } else if (Event.xbutton.window == PersOrthoZWndw) { return EVENT_PERS_ORTHO_Z; } else if (Event.xbutton.window == RotateXWndw) { return EVENT_ROTATE_X; } else if (Event.xbutton.window == RotateYWndw) { return EVENT_ROTATE_Y; } else if (Event.xbutton.window == RotateZWndw) { return EVENT_ROTATE_Z; } else if (Event.xbutton.window == TranslateXWndw) { return EVENT_TRANSLATE_X; } else if (Event.xbutton.window == TranslateYWndw) { return EVENT_TRANSLATE_Y; } else if (Event.xbutton.window == TranslateZWndw) { return EVENT_TRANSLATE_Z; } else if (Event.xbutton.window == ScaleWndw) { return EVENT_SCALE; } else if (Event.xbutton.window == DepthCueWndw) { XClearWindow(XDisplay, DepthCueWndw); GlblDepthCue = !GlblDepthCue; DrawText(DepthCueWndw, GlblDepthCue ? "Depth Cue" : "No Depth Cue", SubWindowWidthState2, SubWindowHeightState2, TransTextPixel); return EVENT_DEPTH_CUE; } else if (LclFullTransMode && Event.xbutton.window == SaveMatrixWndw) { return EVENT_SAVE_MATRIX; } else if (LclFullTransMode && Event.xbutton.window == SaveGIFWndw) { return EVENT_SAVE_GIF; } else if (LclFullTransMode && Event.xbutton.window == SavePSWndw) { return EVENT_SAVE_PS; } else if (Event.xbutton.window == ResetMatrixWndw) { return EVENT_RESET_MATRIX; } else if (Event.xbutton.window == QuitWndw) { if (!PopTransWndwAlways) XUnmapWindow(XDisplay, TransformWndw); GGGraphicFlush(); return EVENT_QUIT; } break; case MotionNotify: /* We may get events of movement in Y which are ignored. */ if (Event.xbutton.x - LastX == 0) break; *ChangeFactor = ((RealType) (Event.xbutton.x - LastX)) / SubWindowWidthState2; LastX = Event.xbutton.x; if (Event.xbutton.window == PersOrthoZWndw) { return EVENT_PERS_ORTHO_Z; } else if (Event.xbutton.window == RotateXWndw) { return EVENT_ROTATE_X; } else if (Event.xbutton.window == RotateYWndw) { return EVENT_ROTATE_Y; } else if (Event.xbutton.window == RotateZWndw) { return EVENT_ROTATE_Z; } else if (Event.xbutton.window == TranslateXWndw) { return EVENT_TRANSLATE_X; } else if (Event.xbutton.window == TranslateYWndw) { return EVENT_TRANSLATE_Y; } else if (Event.xbutton.window == TranslateZWndw) { return EVENT_TRANSLATE_Z; } else if (Event.xbutton.window == ScaleWndw) { return EVENT_SCALE; } break; default: fprintf(stderr, "undefined event type %d.\n", Event.type); } } } /****************************************************************************** * Draw text centered at the given position. * ******************************************************************************/ static void DrawText(Window Win, char *Str, int PosX, int PosY, unsigned long Color) { int Len = strlen(Str), Width = XTextWidth(XLoadedFont, Str, Len); XGCValues values; values.foreground = Color; XChangeGC(XDisplay, XTransGraphContext, GCForeground, &values); XDrawString(XDisplay, Win, XTransGraphContext, PosX - Width / 2, PosY + XFontYOffsetToCenter, Str, Len); }