📄 tkfont.c
字号:
/* * tkFont.c -- * * This file maintains a database of fonts for the Tk toolkit. * It also provides several utility procedures for measuring and * displaying text. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkFont.c 1.74 97/10/10 14:34:11 */#include "tkInt.h"#include "tkFont.h"/* * The following structure is used to keep track of all the fonts that * exist in the current application. It must be stored in the * TkMainInfo for the application. */ typedef struct TkFontInfo { Tcl_HashTable fontCache; /* Map a string to an existing Tk_Font. * Keys are CachedFontKey structs, values are * TkFont structs. */ Tcl_HashTable namedTable; /* Map a name to a set of attributes for a * font, used when constructing a Tk_Font from * a named font description. Keys are * Tk_Uids, values are NamedFont structs. */ TkMainInfo *mainPtr; /* Application that owns this structure. */ int updatePending; } TkFontInfo;/* * The following structure is used as a key in the fontCache. */typedef struct CachedFontKey { Display *display; /* Display for which font was constructed. */ Tk_Uid string; /* String that describes font. */} CachedFontKey;/* * The following data structure is used to keep track of the font attributes * for each named font that has been defined. The named font is only deleted * when the last reference to it goes away. */typedef struct NamedFont { int refCount; /* Number of users of named font. */ int deletePending; /* Non-zero if font should be deleted when * last reference goes away. */ TkFontAttributes fa; /* Desired attributes for named font. */} NamedFont; /* * The following two structures are used to keep track of string * measurement information when using the text layout facilities. * * A LayoutChunk represents a contiguous range of text that can be measured * and displayed by low-level text calls. In general, chunks will be * delimited by newlines and tabs. Low-level, platform-specific things * like kerning and non-integer character widths may occur between the * characters in a single chunk, but not between characters in different * chunks. * * A TextLayout is a collection of LayoutChunks. It can be displayed with * respect to any origin. It is the implementation of the Tk_TextLayout * opaque token. */typedef struct LayoutChunk { CONST char *start; /* Pointer to simple string to be displayed. * This is a pointer into the TkTextLayout's * string. */ int numChars; /* The number of characters in this chunk. */ int numDisplayChars; /* The number of characters to display when * this chunk is displayed. Can be less than * numChars if extra space characters were * absorbed by the end of the chunk. This * will be < 0 if this is a chunk that is * holding a tab or newline. */ int x, y; /* The origin of the first character in this * chunk with respect to the upper-left hand * corner of the TextLayout. */ int totalWidth; /* Width in pixels of this chunk. Used * when hit testing the invisible spaces at * the end of a chunk. */ int displayWidth; /* Width in pixels of the displayable * characters in this chunk. Can be less than * width if extra space characters were * absorbed by the end of the chunk. */} LayoutChunk;typedef struct TextLayout { Tk_Font tkfont; /* The font used when laying out the text. */ CONST char *string; /* The string that was layed out. */ int width; /* The maximum width of all lines in the * text layout. */ int numChunks; /* Number of chunks actually used in * following array. */ LayoutChunk chunks[1]; /* Array of chunks. The actual size will * be maxChunks. THIS FIELD MUST BE THE LAST * IN THE STRUCTURE. */} TextLayout;/* * The following structures are used as two-way maps between the values for * the fields in the TkFontAttributes structure and the strings used in * Tcl, when parsing both option-value format and style-list format font * name strings. */static TkStateMap weightMap[] = { {TK_FW_NORMAL, "normal"}, {TK_FW_BOLD, "bold"}, {TK_FW_UNKNOWN, NULL}};static TkStateMap slantMap[] = { {TK_FS_ROMAN, "roman"}, {TK_FS_ITALIC, "italic"}, {TK_FS_UNKNOWN, NULL}};static TkStateMap underlineMap[] = { {1, "underline"}, {0, NULL}};static TkStateMap overstrikeMap[] = { {1, "overstrike"}, {0, NULL}};/* * The following structures are used when parsing XLFD's into a set of * TkFontAttributes. */static TkStateMap xlfdWeightMap[] = { {TK_FW_NORMAL, "normal"}, {TK_FW_NORMAL, "medium"}, {TK_FW_NORMAL, "book"}, {TK_FW_NORMAL, "light"}, {TK_FW_BOLD, "bold"}, {TK_FW_BOLD, "demi"}, {TK_FW_BOLD, "demibold"}, {TK_FW_NORMAL, NULL} /* Assume anything else is "normal". */}; static TkStateMap xlfdSlantMap[] = { {TK_FS_ROMAN, "r"}, {TK_FS_ITALIC, "i"}, {TK_FS_OBLIQUE, "o"}, {TK_FS_ROMAN, NULL} /* Assume anything else is "roman". */};static TkStateMap xlfdSetwidthMap[] = { {TK_SW_NORMAL, "normal"}, {TK_SW_CONDENSE, "narrow"}, {TK_SW_CONDENSE, "semicondensed"}, {TK_SW_CONDENSE, "condensed"}, {TK_SW_UNKNOWN, NULL}};static TkStateMap xlfdCharsetMap[] = { {TK_CS_NORMAL, "iso8859"}, {TK_CS_SYMBOL, "adobe"}, {TK_CS_SYMBOL, "sun"}, {TK_CS_OTHER, NULL}}; /* * The following structure and defines specify the valid builtin options * when configuring a set of font attributes. */static char *fontOpt[] = { "-family", "-size", "-weight", "-slant", "-underline", "-overstrike", NULL};#define FONT_FAMILY 0#define FONT_SIZE 1#define FONT_WEIGHT 2#define FONT_SLANT 3#define FONT_UNDERLINE 4#define FONT_OVERSTRIKE 5#define FONT_NUMFIELDS 6 /* Length of fontOpt array. */#define GetFontAttributes(tkfont) \ ((CONST TkFontAttributes *) &((TkFont *) (tkfont))->fa)#define GetFontMetrics(tkfont) \ ((CONST TkFontMetrics *) &((TkFont *) (tkfont))->fm)static int ConfigAttributesObj _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[], TkFontAttributes *faPtr));static int FieldSpecified _ANSI_ARGS_((CONST char *field));static int GetAttributeInfoObj _ANSI_ARGS_((Tcl_Interp *interp, CONST TkFontAttributes *faPtr, Tcl_Obj *objPtr));static LayoutChunk * NewChunk _ANSI_ARGS_((TextLayout **layoutPtrPtr, int *maxPtr, CONST char *start, int numChars, int curX, int newX, int y));static int ParseFontNameObj _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, TkFontAttributes *faPtr));static void RecomputeWidgets _ANSI_ARGS_((TkWindow *winPtr));static void TheWorldHasChanged _ANSI_ARGS_(( ClientData clientData));static void UpdateDependantFonts _ANSI_ARGS_((TkFontInfo *fiPtr, Tk_Window tkwin, Tcl_HashEntry *namedHashPtr)); /* *--------------------------------------------------------------------------- * * TkFontPkgInit -- * * This procedure is called when an application is created. It * initializes all the structures that are used by the font * package on a per application basis. * * Results: * Returns a token that must be stored in the TkMainInfo for this * application. * * Side effects: * Memory allocated. * *--------------------------------------------------------------------------- */voidTkFontPkgInit(mainPtr) TkMainInfo *mainPtr; /* The application being created. */{ TkFontInfo *fiPtr; fiPtr = (TkFontInfo *) ckalloc(sizeof(TkFontInfo)); Tcl_InitHashTable(&fiPtr->fontCache, sizeof(CachedFontKey) / sizeof(int)); Tcl_InitHashTable(&fiPtr->namedTable, TCL_ONE_WORD_KEYS); fiPtr->mainPtr = mainPtr; fiPtr->updatePending = 0; mainPtr->fontInfoPtr = fiPtr;}/* *--------------------------------------------------------------------------- * * TkFontPkgFree -- * * This procedure is called when an application is deleted. It * deletes all the structures that were used by the font package * for this application. * * Results: * None. * * Side effects: * Memory freed. * *--------------------------------------------------------------------------- */voidTkFontPkgFree(mainPtr) TkMainInfo *mainPtr; /* The application being deleted. */{ TkFontInfo *fiPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; fiPtr = mainPtr->fontInfoPtr; if (fiPtr->fontCache.numEntries != 0) { panic("TkFontPkgFree: all fonts should have been freed already"); } Tcl_DeleteHashTable(&fiPtr->fontCache); hPtr = Tcl_FirstHashEntry(&fiPtr->namedTable, &search); while (hPtr != NULL) { ckfree((char *) Tcl_GetHashValue(hPtr)); hPtr = Tcl_NextHashEntry(&search); } Tcl_DeleteHashTable(&fiPtr->namedTable); if (fiPtr->updatePending != 0) { Tcl_CancelIdleCall(TheWorldHasChanged, (ClientData) fiPtr); } ckfree((char *) fiPtr);}/* *--------------------------------------------------------------------------- * * Tk_FontObjCmd -- * * This procedure is implemented to process the "font" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */intTk_FontObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ int index; Tk_Window tkwin; TkFontInfo *fiPtr; static char *optionStrings[] = { "actual", "configure", "create", "delete", "families", "measure", "metrics", "names", NULL }; enum options { FONT_ACTUAL, FONT_CONFIGURE, FONT_CREATE, FONT_DELETE, FONT_FAMILIES, FONT_MEASURE, FONT_METRICS, FONT_NAMES }; tkwin = (Tk_Window) clientData; fiPtr = ((TkWindow *) tkwin)->mainPtr->fontInfoPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case FONT_ACTUAL: { int skip, result; Tk_Font tkfont; Tcl_Obj *objPtr; CONST TkFontAttributes *faPtr; skip = TkGetDisplayOf(interp, objc - 3, objv + 3, &tkwin); if (skip < 0) { return TCL_ERROR; } if ((objc < 3) || (objc - skip > 4)) { Tcl_WrongNumArgs(interp, 2, objv, "font ?-displayof window? ?option?"); return TCL_ERROR; } tkfont = Tk_GetFontFromObj(interp, tkwin, objv[2]); if (tkfont == NULL) { return TCL_ERROR; } objc -= skip; objv += skip; faPtr = GetFontAttributes(tkfont); objPtr = NULL; if (objc > 3) { objPtr = objv[3]; } result = GetAttributeInfoObj(interp, faPtr, objPtr); Tk_FreeFont(tkfont); return result; } case FONT_CONFIGURE: { int result; char *string; Tcl_Obj *objPtr; NamedFont *nfPtr; Tcl_HashEntry *namedHashPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "fontname ?options?"); return TCL_ERROR; } string = Tk_GetUid(Tcl_GetStringFromObj(objv[2], NULL)); namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, string); nfPtr = NULL; /* lint. */ if (namedHashPtr != NULL) { nfPtr = (NamedFont *) Tcl_GetHashValue(namedHashPtr); } if ((namedHashPtr == NULL) || (nfPtr->deletePending != 0)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "named font \"", string, "\" doesn't exist", NULL); return TCL_ERROR; } if (objc == 3) { objPtr = NULL; } else if (objc == 4) { objPtr = objv[3]; } else { result = ConfigAttributesObj(interp, tkwin, objc - 3, objv + 3, &nfPtr->fa); UpdateDependantFonts(fiPtr, tkwin, namedHashPtr); return result; } return GetAttributeInfoObj(interp, &nfPtr->fa, objPtr); } case FONT_CREATE: { int skip, i; char *name; char buf[32]; TkFontAttributes fa; Tcl_HashEntry *namedHashPtr; skip = 3; if (objc < 3) { name = NULL; } else { name = Tcl_GetStringFromObj(objv[2], NULL); if (name[0] == '-') { name = NULL; } } if (name == NULL) { /* * No font name specified. Generate one of the form "fontX". */ for (i = 1; ; i++) { sprintf(buf, "font%d", i); namedHashPtr = Tcl_FindHashEntry(&fiPtr->namedTable, Tk_GetUid(buf)); if (namedHashPtr == NULL) { break; } } name = buf; skip = 2; } TkInitFontAttributes(&fa); if (ConfigAttributesObj(interp, tkwin, objc - skip, objv + skip, &fa) != TCL_OK) { return TCL_ERROR; } if (TkCreateNamedFont(interp, tkwin, name, &fa) != TCL_OK) { return TCL_ERROR; } Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -