📄 graphics.c
字号:
for (i = 0; i < nFonts; i++) { if (StringEqual(name, fontTable[i].name) && size == fontTable[i].size && style == fontTable[i].style) return (i); } return (-1);}/* * Function: SetLineBB * Usage: SetLineBB(&rect, x, y, dx, dy); * -------------------------------------- * This function sets the rectangle dimensions to the bounding * box of the line. */static void SetLineBB(RECT *rp, double x, double y, double dx, double dy){ int x0, y0, x1, y1; x0 = ScaleX(x); y0 = ScaleY(y); x1 = ScaleX(x + dx); y1 = ScaleY(y + dy); rp->top = Min(y0, y1); rp->bottom = Max(y0, y1) + 1; rp->left = Min(x0, x1); rp->right = Max(x0, x1) + 1;}/* * Function: SetArcBB * Usage: SetArcBB(&rect, xc, yc, rx, ry, start, sweep); * ----------------------------------------------------- * This function sets the rectangle dimensions to the bounding * box of the arc segment specified by the remaining arguments. */static void SetArcBB(RECT *rp, double xc, double yc, double rx, double ry, double start, double sweep){ int xmax, xmin, ymax, ymin; int xl, xr, yt, yb; int ix0, iy0, ix1, iy1; xmin = ScaleX(xc - rx); ymin = ScaleY(yc + ry); xmax = xmin + PixelsX(2 * rx); ymax = ymin + PixelsX(2 * ry); if (sweep < 0) { start += sweep; sweep = -sweep; } if (sweep >= 360) { SetRect(rp, xmin, ymin, xmax, ymax); return; } if (start < 0) { start = 360 - fmod(-start, 360); } else { start = fmod(start, 360); } ix0 = ScaleX(xc + rx * cos(Radians(start))); iy0 = ScaleY(yc + ry * sin(Radians(start))); ix1 = ScaleX(xc + rx * cos(Radians(start + sweep))); iy1 = ScaleY(yc + ry * sin(Radians(start + sweep))); if (start + sweep > 360) { xr = xmax; } else { xr = Max(ix0, ix1); } start = fmod(start + 270, 360); if (start + sweep > 360) { yt = ymin; } else { yt = Min(iy0, iy1); } start = fmod(start + 270, 360); if (start + sweep > 360) { xl = xmin; } else { xl = Min(ix0, ix1); } start = fmod(start + 270, 360); if (start + sweep > 360) { yb = ymax; } else { yb = Max(iy0, iy1); } SetRect(rp, xl, yt, xr, yb);}/* * Function: SetTextBB * Usage: SetTextBB(&rect, x, y, text); * ------------------------------------- * This function sets the rectangle dimensions to the bounding * box of the text string using the current font and size. */static void SetTextBB(RECT *rp, double x, double y, string text){ SIZE textSize; int ix, iy; if (!GetTextExtentPoint(osdc, text, strlen(text), &textSize)) { Error("Internal error: Text size calculation failed"); } ix = ScaleX(x); iy = ScaleY(y); SetRect(rp, ix, iy - textSize.cy + fontTable[currentFont].descent, ix + textSize.cx, iy + fontTable[currentFont].descent);}/* * 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 PC * 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. */static void StartPolygon(void){ polygonPoints = NewArray(PStartSize, POINT); polygonSize = PStartSize; nPolygonPoints = 0; SetRect(&polygonBounds, LargeInt, LargeInt, 0, 0);}static void AddSegment(int x0, int y0, int x1, int y1){ if (nPolygonPoints == 0) AddPolygonPoint(x0, y0); AddPolygonPoint(x1, y1);}static void DisplayPolygon(void){ int px; HBRUSH brush, oldBrush; HPEN oldPen, fillPen; PrepareToDraw(); InvalidateRect(graphicsWindow, &polygonBounds, TRUE); if (eraseMode) { px = 0; fillPen = erasePen; } else { px = regionDensity * (NFills - 1) + 0.5 - Epsilon; fillPen = drawPen; } oldPen = (HPEN) SelectObject(osdc, fillPen); brush = CreatePatternBrush(fillBitmaps[px]); if (brush == NULL) { Error("Internal error: Can't load brush"); } oldBrush = (HBRUSH) SelectObject(osdc, brush); Polygon(osdc, polygonPoints, nPolygonPoints); (void) SelectObject(osdc, oldPen); if (oldBrush != NULL) (void) SelectObject(osdc, oldBrush); FreeBlock(polygonPoints); DeleteObject(brush);}/* * Function: AddPolygonPoint * Usage: AddPolygonPoint(x, y); * ----------------------------- * AddPolygonPoint acts as a helper function for AddSegment. This * function does the work, but AddSegment has a more easily understood * interface. */static void AddPolygonPoint(int x, int y){ POINT *newPolygon; int i; if (nPolygonPoints >= polygonSize) { polygonSize *= 2; newPolygon = NewArray(polygonSize, POINT); for (i = 0; i < nPolygonPoints; i++) { newPolygon[i] = polygonPoints[i]; } FreeBlock(polygonPoints); polygonPoints = newPolygon; } polygonBounds.left = Min(polygonBounds.left, x); polygonBounds.right = Max(polygonBounds.right, x); polygonBounds.top = Min(polygonBounds.top, y); polygonBounds.bottom = Max(polygonBounds.bottom, y); polygonPoints[nPolygonPoints].x = x; polygonPoints[nPolygonPoints].y = y; nPolygonPoints++;}/* * Function: InitColors * Usage: InitColors(); * -------------------- * This function defines the built-in colors. */static void InitColors(void){ nColors = 0; DefineColor("Black", 0, 0, 0); DefineColor("Dark Gray", .35, .35, .35); DefineColor("Gray", .6, .6, .6); DefineColor("Light Gray", .75, .75, .75); DefineColor("White", 1, 1, 1); DefineColor("Brown", .35, .20, .05); DefineColor("Red", 1, 0, 0); DefineColor("Orange", 1, .40, .1); DefineColor("Yellow", 1, 1, 0); DefineColor("Green", 0, 1, 0); DefineColor("Blue", 0, 0, 1); DefineColor("Violet", .93, .5, .93); DefineColor("Magenta", 1, 0, 1); DefineColor("Cyan", 0, 1, 1);}/* * Function: FindColorName * Usage: index = FindColorName(name); * ----------------------------------- * This function returns the index of the named color in the * color table, or -1 if the color does not exist. */static int FindColorName(string name){ int i; for (i = 0; i < nColors; i++) { if (StringMatch(name, colorTable[i].name)) return (i); } return (-1);}/* * Utility functions * ----------------- * This section contains several extremely short utility functions * that improve the readability of the code. *//* * Function: StringMatch * Usage: if (StringMatch(s1, s2)) . . . * ------------------------------------- * This function returns TRUE if two strings are equal, ignoring * case distinctions. */static bool StringMatch(string s1, string s2){ register char *cp1, *cp2; cp1 = s1; cp2 = s2; while (tolower(*cp1) == tolower(*cp2)) { if (*cp1 == '\0') return (TRUE); cp1++; cp2++; } return (FALSE);}/* * Function: PrefixMatch * Usage: if (PrefixMatch(prefix, str)) . . . * ------------------------------------------------- * This function returns TRUE if prefix is the initial substring * of str, ignoring differences in case. */static bool PrefixMatch(char *prefix, char *str){ while (*prefix != '\0') { if (tolower(*prefix++) != tolower(*str++)) return (FALSE); } return (TRUE);}/* * Functions: RectWidth, RectHeight * Usage: w = RectWidth(&r); * h = RectHeight(&r); * -------------------------------- * These functions return the width and height of a rectangle. */static int RectWidth(RECT *rp){ return (rp->right - rp->left);}static int RectHeight(RECT *rp){ return (rp->bottom - rp->top);}/* * Functions: SetRectFromSize * Usage: SetRectFromSize(&r, x, y, width, height); * ------------------------------------------------ * This function is similar to SetRect except that it takes width * and height parameters rather than right and bottom. */static void SetRectFromSize(RECT *rp, int x, int y, int width, int height){ SetRect(rp, x, y, x + width, y + height);}/* * Function: Radians * Usage: radians = Radians(degrees); * ---------------------------------- * This functions convert an angle in degrees to radians. */static double Radians(double degrees){ return (degrees * Pi / 180);}/* * Function: Round * Usage: n = Round(x); * -------------------- * This function rounds a double to the nearest integer. */static int Round(double x){ return ((int) floor(x + 0.5));}/* * 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 / xResolution);}static double InchesY(int y){ return ((double) y / yResolution);}/* * 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 (Round(x * xResolution + Epsilon));}static int PixelsY(double y){ return (Round(y * yResolution + 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));}/* * Functions: Min, Max * Usage: min = Min(x, y); * max = Max(x, y); * ----------------------- * These functions find the minimum and maximum of two integers. */static int Min(int x, int y){ return ((x < y) ? x : y);}static int Max(int x, int y){ return ((x > y) ? x : y);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -