📄 xdisplay.c
字号:
ok &= FindString("-i-", fontName, 0) != -1; } else { ok &= FindString("-r-", fontName, 0) != -1; } if (ok) { thisSize = SizeFromFontName(fontName); if (bestIndex == -1 || abs(size - thisSize) < abs(size - bestSize)) { bestSize = thisSize; bestIndex = i; } } } if (bestIndex != -1) { if (fontInfo != NULL) XFreeFont(disp, fontInfo); fontInfo = XLoadQueryFont(disp, fontList[bestIndex]); if (fontInfo == NULL) { Error("Internal error: Can't find font"); } XSetFont(disp, drawGC, fontInfo->fid); XSetFont(disp, eraseGC, fontInfo->fid); XFreeFontNames(fontList); currentFont = CopyString(font); currentSize = bestSize; currentStyle = style; } } sprintf(fontbuf, "%d %d %s", currentSize, currentStyle, currentFont); return (CopyString(fontbuf));}/* * Function: DisplayFontMetrics * ---------------------------- * This function returns the necessary font metric information through * its argument pointers. */void DisplayFontMetrics(double *pAscent, double *pDescent, double *pHeight){ *pAscent = InchesY(fontInfo->max_bounds.ascent); *pDescent = InchesY(fontInfo->max_bounds.descent); *pHeight = InchesY(fontInfo->ascent + fontInfo->descent);}/* * Function: XDSetTitle * -------------------- * This function copies the user-supplied string into the window and * icon name. */void XDSetTitle(string title){ XTextProperty tp; XStringListToTextProperty(&title, 1, &tp); XSetWMIconName(disp, mainWindow, &tp); XSetWMName(disp, mainWindow, &tp);}/* * Function: XDSetEraseMode * ------------------------ * This function sets the internal state of the display logic so * that it maintains the correct state of the eraseMode flag. In * the rest of the code, the eraseMode flag is used to control * which colors are used. */void XDSetEraseMode(bool flag){ eraseMode = flag;}/* * Function: XDStartRegion * ----------------------- * This function changes the state of the package so that subsequent * calls to XDDrawLine and XDDrawArc are used to add segments to a * polygonal region instead of having them appear on the display. * See the code for StartPolygon, AddSegment, and DisplayPolygon for * details. */void XDStartRegion(double grayScale){ regionStarted = TRUE; regionGrayScale = grayScale; StartPolygon();}/* * Function: XDEndRegion * --------------------- * This function closes the region opened by XDStartRegion * and displays the assembled polygon. */void XDEndRegion(void){ DisplayPolygon(); regionStarted = FALSE;}/* * Function: XDGetMouse * -------------------- * This function returns the current mouse state through the * argument pointers. */void XDGetMouse(bool *buttonStateP, double *xp, double *yp){ Window root, child; int rootX, rootY, winX, winY; unsigned int buttons; (void) XQueryPointer(disp, mainWindow, &root, &child, &rootX, &rootY, &winX, &winY, &buttons); *buttonStateP = (buttons != 0); *xp = InchesX(winX); *yp = windowHeight - InchesY(winY);}/* * Function: XDWaitForMouse * ------------------------ * This function waits for the mouse to enter the state given * by down. */void XDWaitForMouse(bool buttonState){ bool currentState; double x, y; XDGetMouse(¤tState, &x, &y); if (buttonState == currentState) { XMReleaseClient(); } else { waitState = (buttonState) ? WaitingForMouseDown : WaitingForMouseUp; }}/* * Function: XDSetColor * -------------------- * This function sets the pen color as specified by the arguments. */void XDSetColor(double red, double green, double blue){ XColor color; color.red = red * 65535; color.green = green * 65535; color.blue = blue * 65535; if (XAllocColor(disp, colormap, &color) != 0) { drawColor = color.pixel; XSetForeground(disp, drawGC, drawColor); }}/* * Function: XDSetWindowSize * ------------------------- * This function sets the width and height values of the window. */void XDSetWindowSize(double width, double height){ windowWidth = width; windowHeight = height;}/* * Function: XDGetScreenSize * ------------------------- * This function returns the screen size and may be called * prior to the XDOpenDisplay call or from the client fork. */void XDGetScreenSize(double *pScreenWidth, double *pScreenHeight){ StartToOpenDisplay(); *pScreenWidth = screenWidth; *pScreenHeight = screenHeight;}/* * Function: XDGetResolution * ------------------------- * This function returns the screen resolution, possibly modified by * the scale reduction. */void XDGetResolution(double *pXDPI, double *pYDPI){ StartToOpenDisplay(); *pXDPI = xdpi; *pYDPI = ydpi;}/* * Function: XDGetNColors * ---------------------- * This function returns the number of colors supported by the screen. */int XDGetNColors(void){ StartToOpenDisplay(); return (1 << pixelDepth);}/* Private functions *//* * Function: StartToOpenDisplay * Usage: StartToOpenDisplay(); * ---------------------------- * This function checks to see if the display is open and, if * not, does just enough work to ensure that the fixed parameters * are set. */static void StartToOpenDisplay(void){ int scnum; Screen *screen; if (displayIsOpen) return; if ((disp = XOpenDisplay(NULL)) == NULL) { Error("Can't open display"); } scnum = DefaultScreen(disp); screen = ScreenOfDisplay(disp, scnum); pixelDepth = DefaultDepth(disp, scnum); screenWidth = WidthMMOfScreen(screen) / 25.4; screenHeight = HeightMMOfScreen(screen) / 25.4; xdpi = WidthOfScreen(screen) / screenWidth; ydpi = HeightOfScreen(screen) / screenHeight; displayIsOpen = TRUE;}/* * Function: InitGC * Usage: InitGC(); * ---------------- * This function is used as part of the initialization and creates * all of the GC structures used for drawing. */static void InitGC(void){ XGCValues gcv; Window root; int i; gcv.foreground = eraseColor; gcv.background = eraseColor; eraseGC = XCreateGC(disp, osWindow, GCFgBg, &gcv); gcv.foreground = drawColor; mainGC = XCreateGC(disp, mainWindow, GCFgBg, &gcv); drawGC = XCreateGC(disp, osWindow, GCFgBg, &gcv); gcv.fill_style = FillOpaqueStippled; root = DefaultRootWindow(disp); for (i = 0; i < NGrays; i++) { grayStipple[i] = gcv.stipple = XCreateBitmapFromData(disp, root, grayList[i], 8, 8); grayGC[i] = XCreateGC(disp, osWindow, GCFgBg | GCStipple | GCFillStyle, &gcv); }}/* * Function: ForceRedraw * Usage: ForceRedraw(); * --------------------- * This function forces the screen to update itself by sending an * Expose event for the window. */static void ForceRedraw(void){ XEvent event; event.type = Expose; event.xany.window = mainWindow; event.xexpose.count = 0; XSendEvent(disp, mainWindow, False, 0, &event); XFlush(disp);}/* * Function: RedrawWindow * Usage: RedrawWindow(); * ---------------------- * This function redraws the active display window by copying bits * from the offscreen bitmap. */static void RedrawWindow(void){ int itemp; unsigned int width, height, utemp; Window wtemp; if (XGetGeometry(disp, mainWindow, &wtemp, &itemp, &itemp, &width, &height, &utemp, &utemp) == 0) return; XCopyArea(disp, osWindow, mainWindow, mainGC, 0, 0, width, height, 0, 0); redraw = FALSE;}/* * Functions: StartPolygon, AddSegment, EndPolygon * Usage: StartPolygon(); * AddSegment(x0, y0, x1, y1); * AddSegment(x1, y1, x2, y2); * . . . * DisplayPolygon(); * ----------------------------------------------- * These functions implement the notion of a region in the X * world, where the easiest shape to fill is a polygon. Calling * StartPolygon initializes the array polygonPoints so that * subsequent calls to AddSegment will add points to it. * The points in the polygon are assumed to be contiguous, * because the client interface checks for this property. * Because polygons involving arcs can be quite large, the * AddSegment code extends the polygonPoints list if needed * by doubling the size of the array. All storage is freed * after calling DisplayPolygon, which uses the XFillPolygon * call to generate the display. */static void StartPolygon(void){ polygonPoints = NewArray(PStartSize, XPoint); polygonSize = PStartSize; nPolygonPoints = 0;}static void AddSegment(int x0, int y0, int x1, int y1){ XPoint *newPolygon; int i; if (nPolygonPoints >= polygonSize) { polygonSize *= 2; newPolygon = NewArray(polygonSize, XPoint); for (i = 0; i < nPolygonPoints; i++) { newPolygon[i] = polygonPoints[i]; } FreeBlock(polygonPoints); polygonPoints = newPolygon; } if (nPolygonPoints == 0) { polygonPoints[nPolygonPoints].x = x0; polygonPoints[nPolygonPoints].y = y0; nPolygonPoints++; } polygonPoints[nPolygonPoints].x = x1; polygonPoints[nPolygonPoints].y = y1; nPolygonPoints++;}static void DisplayPolygon(void){ GC fillGC; int i, px; if (eraseMode) { fillGC = eraseGC; } else { px = regionGrayScale * (NGrays - 1) + 0.5 - Epsilon; fillGC = grayGC[px]; XSetForeground(disp, fillGC, drawColor); } if (polygonPoints[0].x != polygonPoints[nPolygonPoints-1].x || polygonPoints[0].y != polygonPoints[nPolygonPoints-1].y) { polygonPoints[nPolygonPoints++] = polygonPoints[0]; } XFillPolygon(disp, osWindow, fillGC, polygonPoints, nPolygonPoints, Complex, CoordModeOrigin); FreeBlock(polygonPoints);}/* * Function: RenderArc * Usage: RenderArc(x, y, rx, ry, start, sweep); * --------------------------------------------- * This function is identical to the XDDrawArc function except * that the arc is rendered using line segments as part of a * polygonal region. */static void RenderArc(double x, double y, double rx, double ry, double start, double sweep){ double t, mint, maxt, dt; int ix0, iy0, ix1, iy1; if (sweep < 0) { start += sweep; sweep = -sweep; } dt = atan2(InchesY(1), GLMaxF(fabs(rx), fabs(ry))); mint = GLRadians(start); maxt = GLRadians(start + sweep); ix0 = ScaleX(x + rx * cos(mint)); iy0 = ScaleY(y + ry * sin(mint)); for (t = mint + dt; t < maxt; t += dt) { if (t > maxt - dt / 2) t = maxt; ix1 = ScaleX(x + rx * cos(t)); iy1 = ScaleY(y + ry * sin(t)); AddSegment(ix0, iy0, ix1, iy1); ix0 = ix1; iy0 = iy1; }}/* * Function: SizeFromFontName * Usage: SizeFromFontName(); * -------------------------- * This function is a simple utility for XDSetFont that returns * the font size from an X font name. */static int SizeFromFontName(string fontName){ char *sizePtr; sizePtr = strstr(fontName, "--"); if (sizePtr == NULL) return (-1); return (atoi(sizePtr + 2));}/* Low-level conversion functions *//* * Functions: InchesX, InchesY * Usage: inches = InchesX(pixels); * inches = InchesY(pixels); * -------------------------------- * These functions convert distances measured in pixels to inches. * Because the resolution may not be uniform in the horizontal and * vertical directions, the coordinates are treated separately. */static double InchesX(int x){ return ((double) x / xdpi);}static double InchesY(int y){ return ((double) y / ydpi);}/* * Functions: PixelsX, PixelsY * Usage: pixels = PixelsX(inches); * pixels = PixelsY(inches); * -------------------------------- * These functions convert distances measured in inches to pixels. */static int PixelsX(double x){ return (GLRound(x * xdpi + Epsilon));}static int PixelsY(double y){ return (GLRound(y * ydpi + Epsilon));}/* * Functions: ScaleX, ScaleY * Usage: pixels = ScaleX(inches); * pixels = ScaleY(inches); * ------------------------------- * These functions are like PixelsX and PixelsY but convert coordinates * rather than lengths. The difference is that y-coordinate values must * be inverted top to bottom to support the cartesian coordinates of * the graphics.h model. */static int ScaleX(double x){ return (PixelsX(x));}static int ScaleY(double y){ return (PixelsY(windowHeight - y));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -