📄 tkfont.c
字号:
int numChars; /* Number of characters to consider from * string, or < 0 for strlen(). */ int wrapLength; /* Longest permissible line length, in * pixels. <= 0 means no automatic wrapping: * just let lines get as long as needed. */ Tk_Justify justify; /* How to justify lines. */ int flags; /* Flag bits OR-ed together. * TK_IGNORE_TABS means that tab characters * should not be expanded. TK_IGNORE_NEWLINES * means that newline characters should not * cause a line break. */ int *widthPtr; /* Filled with width of string. */ int *heightPtr; /* Filled with height of string. */{ TkFont *fontPtr; CONST char *start, *end, *special; int n, y, charsThisChunk, maxChunks; int baseline, height, curX, newX, maxWidth; TextLayout *layoutPtr; LayoutChunk *chunkPtr; CONST TkFontMetrics *fmPtr;#define MAX_LINES 50 int staticLineLengths[MAX_LINES]; int *lineLengths; int maxLines, curLine, layoutHeight; lineLengths = staticLineLengths; maxLines = MAX_LINES; fontPtr = (TkFont *) tkfont; fmPtr = &fontPtr->fm; height = fmPtr->ascent + fmPtr->descent; if (numChars < 0) { numChars = strlen(string); } maxChunks = 1; layoutPtr = (TextLayout *) ckalloc(sizeof(TextLayout) + (maxChunks - 1) * sizeof(LayoutChunk)); layoutPtr->tkfont = tkfont; layoutPtr->string = string; layoutPtr->numChunks = 0; baseline = fmPtr->ascent; maxWidth = 0; /* * Divide the string up into simple strings and measure each string. */ curX = 0; end = string + numChars; special = string; flags &= TK_IGNORE_TABS | TK_IGNORE_NEWLINES; flags |= TK_WHOLE_WORDS | TK_AT_LEAST_ONE; curLine = 0; for (start = string; start < end; ) { if (start >= special) { /* * Find the next special character in the string. */ for (special = start; special < end; special++) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*special == '\n') || (*special == '\r')) { break; } } if (!(flags & TK_IGNORE_TABS)) { if (*special == '\t') { break; } } } } /* * Special points at the next special character (or the end of the * string). Process characters between start and special. */ chunkPtr = NULL; if (start < special) { charsThisChunk = Tk_MeasureChars(tkfont, start, special - start, wrapLength - curX, flags, &newX); newX += curX; flags &= ~TK_AT_LEAST_ONE; if (charsThisChunk > 0) { chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, charsThisChunk, curX, newX, baseline); start += charsThisChunk; curX = newX; } } if ((start == special) && (special < end)) { /* * Handle the special character. */ chunkPtr = NULL; if (*special == '\t') { newX = curX + fontPtr->tabWidth; newX -= newX % fontPtr->tabWidth; NewChunk(&layoutPtr, &maxChunks, start, 1, curX, newX, baseline)->numDisplayChars = -1; start++; if ((start < end) && ((wrapLength <= 0) || (newX <= wrapLength))) { /* * More chars can still fit on this line. */ curX = newX; flags &= ~TK_AT_LEAST_ONE; continue; } } else { NewChunk(&layoutPtr, &maxChunks, start, 1, curX, 1000000000, baseline)->numDisplayChars = -1; start++; goto wrapLine; } } /* * No more characters are going to go on this line, either because * no more characters can fit or there are no more characters left. * Consume all extra spaces at end of line. */ while ((start < end) && isspace(UCHAR(*start))) { if (!(flags & TK_IGNORE_NEWLINES)) { if ((*start == '\n') || (*start == '\r')) { break; } } if (!(flags & TK_IGNORE_TABS)) { if (*start == '\t') { break; } } start++; } if (chunkPtr != NULL) { /* * Append all the extra spaces on this line to the end of the * last text chunk. */ charsThisChunk = start - (chunkPtr->start + chunkPtr->numChars); if (charsThisChunk > 0) { chunkPtr->numChars += Tk_MeasureChars(tkfont, chunkPtr->start + chunkPtr->numChars, charsThisChunk, 0, 0, &chunkPtr->totalWidth); chunkPtr->totalWidth += curX; } } wrapLine: flags |= TK_AT_LEAST_ONE; /* * Save current line length, then move current position to start of * next line. */ if (curX > maxWidth) { maxWidth = curX; } /* * Remember width of this line, so that all chunks on this line * can be centered or right justified, if necessary. */ if (curLine >= maxLines) { int *newLengths; newLengths = (int *) ckalloc(2 * maxLines * sizeof(int)); memcpy((void *) newLengths, lineLengths, maxLines * sizeof(int)); if (lineLengths != staticLineLengths) { ckfree((char *) lineLengths); } lineLengths = newLengths; maxLines *= 2; } lineLengths[curLine] = curX; curLine++; curX = 0; baseline += height; } /* * If last line ends with a newline, then we need to make a 0 width * chunk on the next line. Otherwise "Hello" and "Hello\n" are the * same height. */ if ((layoutPtr->numChunks > 0) && ((flags & TK_IGNORE_NEWLINES) == 0)) { if (layoutPtr->chunks[layoutPtr->numChunks - 1].start[0] == '\n') { chunkPtr = NewChunk(&layoutPtr, &maxChunks, start, 0, curX, 1000000000, baseline); chunkPtr->numDisplayChars = -1; baseline += height; } } /* * Using maximum line length, shift all the chunks so that the lines are * all justified correctly. */ curLine = 0; chunkPtr = layoutPtr->chunks; y = chunkPtr->y; for (n = 0; n < layoutPtr->numChunks; n++) { int extra; if (chunkPtr->y != y) { curLine++; y = chunkPtr->y; } extra = maxWidth - lineLengths[curLine]; if (justify == TK_JUSTIFY_CENTER) { chunkPtr->x += extra / 2; } else if (justify == TK_JUSTIFY_RIGHT) { chunkPtr->x += extra; } chunkPtr++; } layoutPtr->width = maxWidth; layoutHeight = baseline - fmPtr->ascent; if (layoutPtr->numChunks == 0) { layoutHeight = height; /* * This fake chunk is used by the other procedures so that they can * pretend that there is a chunk with no chars in it, which makes * the coding simpler. */ layoutPtr->numChunks = 1; layoutPtr->chunks[0].start = string; layoutPtr->chunks[0].numChars = 0; layoutPtr->chunks[0].numDisplayChars = -1; layoutPtr->chunks[0].x = 0; layoutPtr->chunks[0].y = fmPtr->ascent; layoutPtr->chunks[0].totalWidth = 0; layoutPtr->chunks[0].displayWidth = 0; } if (widthPtr != NULL) { *widthPtr = layoutPtr->width; } if (heightPtr != NULL) { *heightPtr = layoutHeight; } if (lineLengths != staticLineLengths) { ckfree((char *) lineLengths); } return (Tk_TextLayout) layoutPtr;}/* *--------------------------------------------------------------------------- * * Tk_FreeTextLayout -- * * This procedure is called to release the storage associated with * a Tk_TextLayout when it is no longer needed. * * Results: * None. * * Side effects: * Memory is freed. * *--------------------------------------------------------------------------- */voidTk_FreeTextLayout(textLayout) Tk_TextLayout textLayout; /* The text layout to be released. */{ TextLayout *layoutPtr; layoutPtr = (TextLayout *) textLayout; if (layoutPtr != NULL) { ckfree((char *) layoutPtr); }}/* *--------------------------------------------------------------------------- * * Tk_DrawTextLayout -- * * Use the information in the Tk_TextLayout token to display a * multi-line, justified string of text. * * This procedure is useful for simple widgets that need to * display single-font, multi-line text and want Tk to handle * the details. * * Results: * None. * * Side effects: * Text drawn on the screen. * *--------------------------------------------------------------------------- */voidTk_DrawTextLayout(display, drawable, gc, layout, x, y, firstChar, lastChar) Display *display; /* Display on which to draw. */ Drawable drawable; /* Window or pixmap in which to draw. */ GC gc; /* Graphics context to use for drawing text. */ Tk_TextLayout layout; /* Layout information, from a previous call * to Tk_ComputeTextLayout(). */ int x, y; /* Upper-left hand corner of rectangle in * which to draw (pixels). */ int firstChar; /* The index of the first character to draw * from the given text item. 0 specfies the * beginning. */ int lastChar; /* The index just after the last character * to draw from the given text item. A number * < 0 means to draw all characters. */{ TextLayout *layoutPtr; int i, numDisplayChars, drawX; LayoutChunk *chunkPtr; layoutPtr = (TextLayout *) layout; if (layoutPtr == NULL) { return; } if (lastChar < 0) { lastChar = 100000000; } chunkPtr = layoutPtr->chunks; for (i = 0; i < layoutPtr->numChunks; i++) { numDisplayChars = chunkPtr->numDisplayChars; if ((numDisplayChars > 0) && (firstChar < numDisplayChars)) { if (firstChar <= 0) { drawX = 0; firstChar = 0; } else { Tk_MeasureChars(layoutPtr->tkfont, chunkPtr->start, firstChar, 0, 0, &drawX); } if (lastChar < numDisplayChars) { numDisplayChars = lastChar; } Tk_DrawChars(display, drawable, gc, layoutPtr->tkfont, chunkPtr->start + firstChar, numDisplayChars - firstChar, x + chunkPtr->x + drawX, y + chunkPtr->y); } firstChar -= chunkPtr->numChars; lastChar -= chunkPtr->numChars; if (lastChar <= 0) { break; } chunkPtr++; }}/* *--------------------------------------------------------------------------- * * Tk_UnderlineTextLayout -- * * Use the information in the Tk_TextLayout token to display an * underline below an individual character. This procedure does * not draw the text, just the underline. * * This procedure is useful for simple widgets that need to * display single-font, multi-line text with an individual * character underlined and want Tk to handle the details. * To display larger amounts of underlined text, construct * and use an underlined font. * * Results: * None. * * Side effects: * Underline drawn on the screen. * *--------------------------------------------------------------------------- */voidTk_UnderlineTextLayout(display, drawable, gc, layout, x, y, underline) Display *display; /* Display on which to draw. */ Drawable drawable; /* Window or pixmap in which to draw. */ GC gc; /* Graphics context to use for drawing text. */ Tk_TextLayout layout; /* Layout information, from a previous call * to Tk_ComputeTextLayout(). */ int x, y; /* Upper-left hand corner of rectangle in * which to draw (pixels). */ int underline; /* Index of the single character to * underline, or -1 for no underline. */{ TextLayout *layoutPtr; TkFont *fontPtr; int xx, yy, width, height; if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0) && (width != 0)) { layoutPtr = (TextLayout *) layout; fontPtr = (TkFont *) layoutPtr->tkfont; XFillRectangle(display, drawable, gc, x + xx, y + yy + fontPtr->fm.ascent + fontPtr->underlinePos, (unsigned int) width, (unsigned int) fontPtr->underlineHeight); }}/* *--------------------------------------------------------------------------- * * Tk_PointToChar -- * * Use the information in the Tk_TextLayout token to determine the * character closest to the given point. The point must be * specified with respect to the upper-left hand corner of the * text layout, which is considered to be located at (0, 0). * * Any point whose y-value is less that 0 will be considered closest * to the first character in the text layout; any point whose y-value * is greater than the height of the text layout will be considered * closest to the last character in the text layout. * * Any point whose x-value is less than 0 will be considered closest * to the first character on that line; any point whose x-value is * greater than the width of the text layout will be considered * closest to the last character on that line. * * Results: * The return value is the index of the character that was * closest to the point. Given a text layout with no characters, * the value 0 will always be returned, referring to a hypothetical * zero-width placeholder character. * * Side effects: * None. * *--------------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -