📄 tkunixfont.c
字号:
} } Tcl_CreateHashEntry(&familyTable, family, &new); } hPtr = Tcl_FirstHashEntry(&familyTable, &search); while (hPtr != NULL) { Tcl_AppendElement(interp, Tcl_GetHashKey(&familyTable, hPtr)); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&familyTable); XFreeFontNames(nameList);}/* *--------------------------------------------------------------------------- * * Tk_MeasureChars -- * * Determine the number of characters from the string that will fit * in the given horizontal span. The measurement is done under the * assumption that Tk_DrawChars() will be used to actually display * the characters. * * Results: * The return value is the number of characters from source that * fit into the span that extends from 0 to maxLength. *lengthPtr is * filled with the x-coordinate of the right edge of the last * character that did fit. * * Side effects: * None. * *--------------------------------------------------------------------------- */intTk_MeasureChars(tkfont, source, numChars, maxLength, flags, lengthPtr) Tk_Font tkfont; /* Font in which characters will be drawn. */ CONST char *source; /* Characters to be displayed. Need not be * '\0' terminated. */ int numChars; /* Maximum number of characters to consider * from source string. */ int maxLength; /* If > 0, maxLength specifies the longest * permissible line length; don't consider any * character that would cross this * x-position. If <= 0, then line length is * unbounded and the flags argument is * ignored. */ int flags; /* Various flag bits OR-ed together: * TK_PARTIAL_OK means include the last char * which only partially fit on this line. * TK_WHOLE_WORDS means stop on a word * boundary, if possible. * TK_AT_LEAST_ONE means return at least one * character even if no characters fit. */ int *lengthPtr; /* Filled with x-location just after the * terminating character. */{ UnixFont *fontPtr; CONST char *p; /* Current character. */ CONST char *term; /* Pointer to most recent character that * may legally be a terminating character. */ int termX; /* X-position just after term. */ int curX; /* X-position corresponding to p. */ int newX; /* X-position corresponding to p+1. */ int c, sawNonSpace; fontPtr = (UnixFont *) tkfont; if (numChars == 0) { *lengthPtr = 0; return 0; } if (maxLength <= 0) { maxLength = INT_MAX; } newX = curX = termX = 0; p = term = source; sawNonSpace = !isspace(UCHAR(*p)); /* * Scan the input string one character at a time, calculating width. */ for (c = UCHAR(*p); ; ) { newX += fontPtr->widths[c]; if (newX > maxLength) { break; } curX = newX; numChars--; p++; if (numChars == 0) { term = p; termX = curX; break; } c = UCHAR(*p); if (isspace(c)) { if (sawNonSpace) { term = p; termX = curX; sawNonSpace = 0; } } else { sawNonSpace = 1; } } /* * P points to the first character that doesn't fit in the desired * span. Use the flags to figure out what to return. */ if ((flags & TK_PARTIAL_OK) && (numChars > 0) && (curX < maxLength)) { /* * Include the first character that didn't quite fit in the desired * span. The width returned will include the width of that extra * character. */ numChars--; curX = newX; p++; } if ((flags & TK_AT_LEAST_ONE) && (term == source) && (numChars > 0)) { term = p; termX = curX; if (term == source) { term++; termX = newX; } } else if ((numChars == 0) || !(flags & TK_WHOLE_WORDS)) { term = p; termX = curX; } *lengthPtr = termX; return term-source;}/* *--------------------------------------------------------------------------- * * Tk_DrawChars, DrawChars -- * * Draw a string of characters on the screen. Tk_DrawChars() * expands control characters that occur in the string to \X or * \xXX sequences. DrawChars() just draws the strings. * * Results: * None. * * Side effects: * Information gets drawn on the screen. * *--------------------------------------------------------------------------- */voidTk_DrawChars(display, drawable, gc, tkfont, source, numChars, x, y) Display *display; /* Display on which to draw. */ Drawable drawable; /* Window or pixmap in which to draw. */ GC gc; /* Graphics context for drawing characters. */ Tk_Font tkfont; /* Font in which characters will be drawn; * must be the same as font used in GC. */ CONST char *source; /* Characters to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) * should be stripped out of the string that * is passed to this function. If they are * not stripped out, they will be displayed as * regular printing characters. */ int numChars; /* Number of characters in string. */ int x, y; /* Coordinates at which to place origin of * string when drawing. */{ UnixFont *fontPtr; CONST char *p; int i, type; char buf[4]; fontPtr = (UnixFont *) tkfont; p = source; for (i = 0; i < numChars; i++) { type = fontPtr->types[UCHAR(*p)]; if (type != NORMAL) { DrawChars(display, drawable, gc, fontPtr, source, p - source, x, y); x += XTextWidth(fontPtr->fontStructPtr, source, p - source); if (type == REPLACE) { DrawChars(display, drawable, gc, fontPtr, buf, GetControlCharSubst(UCHAR(*p), buf), x, y); x += fontPtr->widths[UCHAR(*p)]; } source = p + 1; } p++; } DrawChars(display, drawable, gc, fontPtr, source, p - source, x, y);}static voidDrawChars(display, drawable, gc, fontPtr, source, numChars, x, y) Display *display; /* Display on which to draw. */ Drawable drawable; /* Window or pixmap in which to draw. */ GC gc; /* Graphics context for drawing characters. */ UnixFont *fontPtr; /* Font in which characters will be drawn; * must be the same as font used in GC. */ CONST char *source; /* Characters to be displayed. Need not be * '\0' terminated. All Tk meta-characters * (tabs, control characters, and newlines) * should be stripped out of the string that * is passed to this function. If they are * not stripped out, they will be displayed as * regular printing characters. */ int numChars; /* Number of characters in string. */ int x, y; /* Coordinates at which to place origin of * string when drawing. */{ /* * Perform a quick sanity check to ensure we won't overflow the X * coordinate space. */ if ((x + (fontPtr->fontStructPtr->max_bounds.width * numChars) > 0x7fff)) { int length; /* * The string we are being asked to draw is too big and would overflow * the X coordinate space. Unfortunatley X servers aren't too bright * and so they won't deal with this case cleanly. We need to truncate * the string before sending it to X. */ numChars = Tk_MeasureChars((Tk_Font) fontPtr, source, numChars, 0x7fff - x, 0, &length); } XDrawString(display, drawable, gc, x, y, source, numChars); if (fontPtr->font.fa.underline != 0) { XFillRectangle(display, drawable, gc, x, y + fontPtr->underlinePos, (unsigned) XTextWidth(fontPtr->fontStructPtr, source, numChars), (unsigned) fontPtr->barHeight); } if (fontPtr->font.fa.overstrike != 0) { y -= fontPtr->font.fm.descent + (fontPtr->font.fm.ascent) / 10; XFillRectangle(display, drawable, gc, x, y, (unsigned) XTextWidth(fontPtr->fontStructPtr, source, numChars), (unsigned) fontPtr->barHeight); }}/* *--------------------------------------------------------------------------- * * AllocFont -- * * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). * Allocates and intializes the memory for a new TkFont that * wraps the platform-specific data. * * Results: * Returns pointer to newly constructed TkFont. * * The caller is responsible for initializing the fields of the * TkFont that are used exclusively by the generic TkFont code, and * for releasing those fields before calling TkpDeleteFont(). * * Side effects: * Memory allocated. * *--------------------------------------------------------------------------- */ static UnixFont *AllocFont(tkFontPtr, tkwin, fontStructPtr, fontName) TkFont *tkFontPtr; /* If non-NULL, store the information in * this existing TkFont structure, rather than * allocating a new structure to hold the * font; the existing contents of the font * will be released. If NULL, a new TkFont * structure is allocated. */ Tk_Window tkwin; /* For display where font will be used. */ XFontStruct *fontStructPtr; /* X information about font. */ CONST char *fontName; /* The string passed to XLoadQueryFont() to * construct the fontStructPtr. */{ UnixFont *fontPtr; unsigned long value; int i, width, firstChar, lastChar, n, replaceOK; char *name, *p; char buf[4]; TkXLFDAttributes xa; double d; if (tkFontPtr != NULL) { fontPtr = (UnixFont *) tkFontPtr; XFreeFont(fontPtr->display, fontPtr->fontStructPtr); } else { fontPtr = (UnixFont *) ckalloc(sizeof(UnixFont)); } /* * Encapsulate the generic stuff in the TkFont. */ fontPtr->font.fid = fontStructPtr->fid; if (XGetFontProperty(fontStructPtr, XA_FONT, &value) && (value != 0)) { name = Tk_GetAtomName(tkwin, (Atom) value); TkInitFontAttributes(&xa.fa); if (TkParseXLFD(name, &xa) == TCL_OK) { goto ok; } } TkInitFontAttributes(&xa.fa); if (TkParseXLFD(fontName, &xa) != TCL_OK) { TkInitFontAttributes(&fontPtr->font.fa); fontPtr->font.fa.family = Tk_GetUid(fontName); } else { ok: fontPtr->font.fa = xa.fa; } if (fontPtr->font.fa.pointsize < 0) { d = -fontPtr->font.fa.pointsize * 72 / 25.4; d *= WidthMMOfScreen(Tk_Screen(tkwin)); d /= WidthOfScreen(Tk_Screen(tkwin)); d += 0.5; fontPtr->font.fa.pointsize = (int) d; } fontPtr->font.fm.ascent = fontStructPtr->ascent; fontPtr->font.fm.descent = fontStructPtr->descent; fontPtr->font.fm.maxWidth = fontStructPtr->max_bounds.width; fontPtr->font.fm.fixed = 1; fontPtr->display = Tk_Display(tkwin); fontPtr->fontStructPtr = fontStructPtr; /* * Classify the characters. */ firstChar = fontStructPtr->min_char_or_byte2; lastChar = fontStructPtr->max_char_or_byte2; for (i = 0; i < 256; i++) { if ((i == 0177) || (i < firstChar) || (i > lastChar)) { fontPtr->types[i] = REPLACE; } else { fontPtr->types[i] = NORMAL; } } /* * Compute the widths for all the normal characters. Any other * characters are given an initial width of 0. Also, this determines * if this is a fixed or variable width font, by comparing the widths * of all the normal characters. */ width = 0; for (i = 0; i < 256; i++) { if (fontPtr->types[i] != NORMAL) { n = 0; } else if (fontStructPtr->per_char == NULL) { n = fontStructPtr->max_bounds.width; } else { n = fontStructPtr->per_char[i - firstChar].width; } fontPtr->widths[i] = n; if (n != 0) { if (width == 0) { width = n; } else if (width != n) { fontPtr->font.fm.fixed = 0; } } } /* * Compute the widths of the characters that should be replaced with * control character expansions. If the appropriate chars are not * available in this font, then control character expansions will not * be used; control chars will be invisible & zero-width. */ replaceOK = 1; for (p = hexChars; *p != '\0'; p++) { if ((UCHAR(*p) < firstChar) || (UCHAR(*p) > lastChar)) { replaceOK = 0; break; } } for (i = 0; i < 256; i++) { if (fontPtr->types[i] == REPLACE) { if (replaceOK) { n = GetControlCharSubst(i, buf); for ( ; --n >= 0; ) { fontPtr->widths[i] += fontPtr->widths[UCHAR(buf[n])]; } } else { fontPtr->types[i] = SKIP; } } } if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_POSITION, &value)) { fontPtr->underlinePos = value; } else { /* * If the XA_UNDERLINE_POSITION property does not exist, the X * manual recommends using the following value: */ fontPtr->underlinePos = fontStructPtr->descent / 2; } fontPtr->barHeight = 0; if (XGetFontProperty(fontStructPtr, XA_UNDERLINE_THICKNESS, &value)) { /* * Sometimes this is 0 even though it shouldn't be. */ fontPtr->barHeight = value; } if (fontPtr->barHeight == 0) { /* * If the XA_UNDERLINE_THICKNESS property does not exist, the X * manual recommends using the width of the stem on a capital * letter. I don't know of a way to get the stem width of a letter, * so guess and use 1/3 the width of a capital I. */ fontPtr->barHeight = fontPtr->widths['I'] / 3; if (fontPtr->barHeight == 0) { fontPtr->barHeight = 1; } } if (fontPtr->underlinePos + fontPtr->barHeight > fontStructPtr->descent) { /* * If this set of cobbled together values would cause the bottom of * the underline bar to stick below the descent of the font, jack * the underline up a bit higher. */ fontPtr->barHeight = fontStructPtr->descent - fontPtr->underlinePos; if (fontPtr->barHeight == 0) { fontPtr->underlinePos--; fontPtr->barHeight = 1; } } return fontPtr;}/* *--------------------------------------------------------------------------- * * GetControlCharSubst -- * * When displaying text in a widget, a backslashed escape sequence * is substituted for control characters that occur in the text. * Given a control character, fill in a buffer with the replacement * string that should be displayed. * * Results: * The return value is the length of the substitute string. buf is * filled with the substitute string; it is not '\0' terminated. * * Side effects: * None. * *--------------------------------------------------------------------------- */static intGetControlCharSubst(c, buf) int c; /* The control character to be replaced. */ char buf[4]; /* Buffer that gets replacement string. It * only needs to be 4 characters long. */{ buf[0] = '\\'; if ((c < sizeof(mapChars)) && (mapChars[c] != 0)) { buf[1] = mapChars[c]; return 2; } else { buf[1] = 'x'; buf[2] = hexChars[(c >> 4) & 0xf]; buf[3] = hexChars[c & 0xf]; return 4; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -