4 * Contains the Windows implementation of the platform-independant
5 * font package interface.
7 * Copyright (c) 1994 Software Research Associates, Inc.
8 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
9 * Copyright (c) 1998-1999 by Scriptics Corporation.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
21 * The following structure represents a font family. It is assumed that
22 * all screen fonts constructed from the same "font family" share certain
23 * properties; all screen fonts with the same "font family" point to a
24 * shared instance of this structure. The most important shared property
25 * is the character existence metrics, used to determine if a screen font
26 * can display a given Unicode character.
28 * Under Windows, a "font family" is uniquely identified by its face name.
31 #define FONTMAP_SHIFT 10
33 #define FONTMAP_PAGES (1 << (sizeof(Tcl_UniChar)*8 - FONTMAP_SHIFT))
34 #define FONTMAP_BITSPERPAGE (1 << FONTMAP_SHIFT)
36 typedef struct FontFamily {
37 struct FontFamily *nextPtr; /* Next in list of all known font families. */
38 int refCount; /* How many SubFonts are referring to this
39 * FontFamily. When the refCount drops to
40 * zero, this FontFamily may be freed. */
45 Tk_Uid faceName; /* Face name key for this FontFamily. */
51 Tcl_Encoding encoding; /* Encoding for this font family. */
52 int isSymbolFont; /* Non-zero if this is a symbol font. */
53 int isWideFont; /* 1 if this is a double-byte font, 0
55 BOOL (WINAPI *textOutProc)(HDC, int, int, TCHAR *, int);
56 /* The procedure to use to draw text after
57 * it has been converted from UTF-8 to the
58 * encoding of this font. */
59 BOOL (WINAPI *getTextExtentPoint32Proc)(HDC, TCHAR *, int, LPSIZE);
60 /* The procedure to use to measure text after
61 * it has been converted from UTF-8 to the
62 * encoding of this font. */
64 char *fontMap[FONTMAP_PAGES];
65 /* Two-level sparse table used to determine
66 * quickly if the specified character exists.
67 * As characters are encountered, more pages
68 * in this table are dynamically added. The
69 * contents of each page is a bitmask
70 * consisting of FONTMAP_BITSPERPAGE bits,
71 * representing whether this font can be used
72 * to display the given character at the
73 * corresponding bit position. The high bits
74 * of the character are used to pick which
75 * page of the table is used. */
78 * Cached Truetype font info.
81 int segCount; /* The length of the following arrays. */
82 USHORT *startCount; /* Truetype information about the font, */
83 USHORT *endCount; /* indicating which characters this font
84 * can display (malloced). The format of
85 * this information is (relatively) compact,
86 * but would take longer to search than
87 * indexing into the fontMap[][] table. */
91 * The following structure encapsulates an individual screen font. A font
92 * object is made up of however many SubFonts are necessary to display a
93 * stream of multilingual characters.
96 typedef struct SubFont {
97 char **fontMap; /* Pointer to font map from the FontFamily,
98 * cached here to save a dereference. */
99 HFONT hFont; /* The specific screen font that will be
100 * used when displaying/measuring chars
101 * belonging to the FontFamily. */
102 FontFamily *familyPtr; /* The FontFamily for this SubFont. */
106 * The following structure represents Windows' implementation of a font
110 #define SUBFONT_SPACE 3
111 #define BASE_CHARS 128
113 typedef struct WinFont {
114 TkFont font; /* Stuff used by generic font package. Must
115 * be first in structure. */
116 SubFont staticSubFonts[SUBFONT_SPACE];
117 /* Builtin space for a limited number of
119 int numSubFonts; /* Length of following array. */
120 SubFont *subFontArray; /* Array of SubFonts that have been loaded
121 * in order to draw/measure all the characters
122 * encountered by this font so far. All fonts
123 * start off with one SubFont initialized by
124 * AllocFont() from the original set of font
125 * attributes. Usually points to
126 * staticSubFonts, but may point to malloced
127 * space if there are lots of SubFonts. */
129 HWND hwnd; /* Toplevel window of application that owns
130 * this font, used for getting HDC for
131 * offscreen measurements. */
132 int pixelSize; /* Original pixel size used when font was
134 int widths[BASE_CHARS]; /* Widths of first 128 chars in the base
135 * font, for handling common case. The base
136 * font is always used to draw characters
137 * between 0x0000 and 0x007f. */
141 * The following structure is passed as the LPARAM when calling the font
142 * enumeration procedure to determine if a font can support the given
146 typedef struct CanUse {
149 Tcl_DString *nameTriedPtr;
155 * The following structure is used to map between the Tcl strings that
156 * represent the system fonts and the numbers used by Windows.
159 static TkStateMap systemMap[] = {
160 {ANSI_FIXED_FONT, "ansifixed"},
161 {ANSI_VAR_FONT, "ansi"},
162 {DEVICE_DEFAULT_FONT, "device"},
163 {OEM_FIXED_FONT, "oemfixed"},
164 {SYSTEM_FIXED_FONT, "systemfixed"},
165 {SYSTEM_FONT, "system"},
169 typedef struct ThreadSpecificData {
170 FontFamily *fontFamilyList; /* The list of font families that are
171 * currently loaded. As screen fonts
172 * are loaded, this list grows to hold
173 * information about what characters
174 * exist in each font family. */
175 Tcl_HashTable uidTable;
176 } ThreadSpecificData;
177 static Tcl_ThreadDataKey dataKey;
180 * Information cached about the system at startup time.
183 static Tcl_Encoding unicodeEncoding;
184 static Tcl_Encoding systemEncoding;
187 * Procedures used only in this file.
190 static FontFamily * AllocFontFamily(HDC hdc, HFONT hFont, int base);
191 static SubFont * CanUseFallback(HDC hdc, WinFont *fontPtr,
192 char *fallbackName, int ch);
193 static SubFont * CanUseFallbackWithAliases(HDC hdc, WinFont *fontPtr,
194 char *faceName, int ch, Tcl_DString *nameTriedPtr);
195 static int FamilyExists(HDC hdc, CONST char *faceName);
196 static char * FamilyOrAliasExists(HDC hdc, CONST char *faceName);
197 static SubFont * FindSubFontForChar(WinFont *fontPtr, int ch);
198 static void FontMapInsert(SubFont *subFontPtr, int ch);
199 static void FontMapLoadPage(SubFont *subFontPtr, int row);
200 static int FontMapLookup(SubFont *subFontPtr, int ch);
201 static void FreeFontFamily(FontFamily *familyPtr);
202 static HFONT GetScreenFont(CONST TkFontAttributes *faPtr,
203 CONST char *faceName, int pixelSize);
204 static void InitFont(Tk_Window tkwin, HFONT hFont,
205 int overstrike, WinFont *tkFontPtr);
206 static void InitSubFont(HDC hdc, HFONT hFont, int base,
207 SubFont *subFontPtr);
208 static int LoadFontRanges(HDC hdc, HFONT hFont,
209 USHORT **startCount, USHORT **endCount,
211 static void MultiFontTextOut(HDC hdc, WinFont *fontPtr,
212 CONST char *source, int numBytes, int x, int y);
213 static void ReleaseFont(WinFont *fontPtr);
214 static void ReleaseSubFont(SubFont *subFontPtr);
215 static int SeenName(CONST char *name, Tcl_DString *dsPtr);
216 static void SwapLong(PULONG p);
217 static void SwapShort(USHORT *p);
218 static int CALLBACK WinFontCanUseProc(ENUMLOGFONT *lfPtr,
219 NEWTEXTMETRIC *tmPtr, int fontType,
221 static int CALLBACK WinFontExistProc(ENUMLOGFONT *lfPtr,
222 NEWTEXTMETRIC *tmPtr, int fontType,
224 static int CALLBACK WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr,
225 NEWTEXTMETRIC *tmPtr, int fontType,
229 *-------------------------------------------------------------------------
233 * This procedure is called when an application is created. It
234 * initializes all the structures that are used by the
235 * platform-dependent code on a per application basis.
244 *-------------------------------------------------------------------------
249 TkMainInfo *mainPtr) /* The application being created. */
251 unicodeEncoding = Tcl_GetEncoding(NULL, "unicode");
252 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
254 * If running NT, then we will be calling some Unicode functions
255 * explictly. So, even if the Tcl system encoding isn't Unicode,
256 * make sure we convert to/from the Unicode char set.
259 systemEncoding = unicodeEncoding;
264 *---------------------------------------------------------------------------
266 * TkpGetNativeFont --
268 * Map a platform-specific native font name to a TkFont.
271 * The return value is a pointer to a TkFont that represents the
272 * native font. If a native font by the given name could not be
273 * found, the return value is NULL.
275 * Every call to this procedure returns a new TkFont structure,
276 * even if the name has already been seen before. The caller should
277 * call TkpDeleteFont() when the font is no longer needed.
279 * The caller is responsible for initializing the memory associated
280 * with the generic TkFont when this function returns and releasing
281 * the contents of the generic TkFont before calling TkpDeleteFont().
286 *---------------------------------------------------------------------------
291 Tk_Window tkwin, /* For display where font will be used. */
292 CONST char *name) /* Platform-specific font name. */
297 object = TkFindStateNum(NULL, NULL, systemMap, name);
302 tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
303 fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
304 InitFont(tkwin, GetStockObject(object), 0, fontPtr);
306 return (TkFont *) fontPtr;
310 *---------------------------------------------------------------------------
312 * TkpGetFontFromAttributes --
314 * Given a desired set of attributes for a font, find a font with
315 * the closest matching attributes.
318 * The return value is a pointer to a TkFont that represents the
319 * font with the desired attributes. If a font with the desired
320 * attributes could not be constructed, some other font will be
321 * substituted automatically. NULL is never returned.
323 * Every call to this procedure returns a new TkFont structure,
324 * even if the specified attributes have already been seen before.
325 * The caller should call TkpDeleteFont() to free the platform-
326 * specific data when the font is no longer needed.
328 * The caller is responsible for initializing the memory associated
329 * with the generic TkFont when this function returns and releasing
330 * the contents of the generic TkFont before calling TkpDeleteFont().
335 *---------------------------------------------------------------------------
339 TkpGetFontFromAttributes(
340 TkFont *tkFontPtr, /* If non-NULL, store the information in
341 * this existing TkFont structure, rather than
342 * allocating a new structure to hold the
343 * font; the existing contents of the font
344 * will be released. If NULL, a new TkFont
345 * structure is allocated. */
346 Tk_Window tkwin, /* For display where font will be used. */
347 CONST TkFontAttributes *faPtr)
348 /* Set of attributes to match. */
356 char ***fontFallbacks;
357 char *faceName, *fallback, *actualName;
359 tkwin = (Tk_Window) ((TkWindow *) tkwin)->mainPtr->winPtr;
360 window = Tk_WindowId(tkwin);
361 hwnd = (window == None) ? NULL : TkWinGetHWND(window);
365 * Algorithm to get the closest font name to the one requested.
368 * try all aliases for fontname
369 * foreach fallback for fontname
371 * try all aliases for the fallback
374 faceName = faPtr->family;
375 if (faceName != NULL) {
376 actualName = FamilyOrAliasExists(hdc, faceName);
377 if (actualName != NULL) {
378 faceName = actualName;
381 fontFallbacks = TkFontGetFallbacks();
382 for (i = 0; fontFallbacks[i] != NULL; i++) {
383 for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
384 if (strcasecmp(faceName, fallback) == 0) {
388 if (fallback != NULL) {
389 for (j = 0; (fallback = fontFallbacks[i][j]) != NULL; j++) {
390 actualName = FamilyOrAliasExists(hdc, fallback);
391 if (actualName != NULL) {
392 faceName = actualName;
401 ReleaseDC(hwnd, hdc);
403 hFont = GetScreenFont(faPtr, faceName, TkFontGetPixels(tkwin, faPtr->size));
404 if (tkFontPtr == NULL) {
405 fontPtr = (WinFont *) ckalloc(sizeof(WinFont));
407 fontPtr = (WinFont *) tkFontPtr;
408 ReleaseFont(fontPtr);
410 InitFont(tkwin, hFont, faPtr->overstrike, fontPtr);
412 return (TkFont *) fontPtr;
416 *---------------------------------------------------------------------------
420 * Called to release a font allocated by TkpGetNativeFont() or
421 * TkpGetFontFromAttributes(). The caller should have already
422 * released the fields of the TkFont that are used exclusively by
423 * the generic TkFont code.
429 * TkFont is deallocated.
431 *---------------------------------------------------------------------------
436 TkFont *tkFontPtr) /* Token of font to be deleted. */
440 fontPtr = (WinFont *) tkFontPtr;
441 ReleaseFont(fontPtr);
445 *---------------------------------------------------------------------------
447 * TkpGetFontFamilies, WinFontFamilyEnumProc --
449 * Return information about the font families that are available
450 * on the display of the given window.
453 * Modifies interp's result object to hold a list of all the available
459 *---------------------------------------------------------------------------
464 Tcl_Interp *interp, /* Interp to hold result. */
465 Tk_Window tkwin) /* For display to query. */
471 window = Tk_WindowId(tkwin);
472 hwnd = (window == None) ? NULL : TkWinGetHWND(window);
476 * On any version NT, there may fonts with international names.
477 * Use the NT-only Unicode version of EnumFontFamilies to get the
478 * font names. If we used the ANSI version on a non-internationalized
479 * version of NT, we would get font names with '?' replacing all
480 * the international characters.
482 * On a non-internationalized verson of 95, fonts with international
483 * names are not allowed, so the ANSI version of EnumFontFamilies will
484 * work. On an internationalized version of 95, there may be fonts with
485 * international names; the ANSI version will work, fetching the
486 * name in the system code page. Can't use the Unicode version of
487 * EnumFontFamilies because it only exists under NT.
490 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
491 EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc,
494 EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontFamilyEnumProc,
497 ReleaseDC(hwnd, hdc);
501 WinFontFamilyEnumProc(
502 ENUMLOGFONT *lfPtr, /* Logical-font data. */
503 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
504 int fontType, /* Type of font (not used). */
505 LPARAM lParam) /* Result object to hold result. */
508 Tcl_DString faceString;
512 interp = (Tcl_Interp *) lParam;
513 faceName = lfPtr->elfLogFont.lfFaceName;
514 Tcl_ExternalToUtfDString(systemEncoding, faceName, -1, &faceString);
515 strPtr = Tcl_NewStringObj(Tcl_DStringValue(&faceString),
516 Tcl_DStringLength(&faceString));
517 Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), strPtr);
518 Tcl_DStringFree(&faceString);
523 *-------------------------------------------------------------------------
527 * A function used by the testing package for querying the actual
528 * screen fonts that make up a font object.
531 * Modifies interp's result object to hold a list containing the
532 * names of the screen fonts that make up the given font object.
537 *-------------------------------------------------------------------------
542 Tcl_Interp *interp, /* Interp to hold result. */
543 Tk_Font tkfont) /* Font object to query. */
547 FontFamily *familyPtr;
548 Tcl_Obj *resultPtr, *strPtr;
550 resultPtr = Tcl_GetObjResult(interp);
551 fontPtr = (WinFont *) tkfont;
552 for (i = 0; i < fontPtr->numSubFonts; i++) {
553 familyPtr = fontPtr->subFontArray[i].familyPtr;
554 strPtr = Tcl_NewStringObj(familyPtr->faceName, -1);
555 Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
560 *---------------------------------------------------------------------------
564 * Determine the number of bytes from the string that will fit
565 * in the given horizontal span. The measurement is done under the
566 * assumption that Tk_DrawChars() will be used to actually display
570 * The return value is the number of bytes from source that
571 * fit into the span that extends from 0 to maxLength. *lengthPtr is
572 * filled with the x-coordinate of the right edge of the last
573 * character that did fit.
578 *---------------------------------------------------------------------------
583 Tk_Font tkfont, /* Font in which characters will be drawn. */
584 CONST char *source, /* UTF-8 string to be displayed. Need not be
585 * '\0' terminated. */
586 int numBytes, /* Maximum number of bytes to consider
587 * from source string. */
588 int maxLength, /* If >= 0, maxLength specifies the longest
589 * permissible line length in pixels; don't
590 * consider any character that would cross
591 * this x-position. If < 0, then line length
592 * is unbounded and the flags argument is
594 int flags, /* Various flag bits OR-ed together:
595 * TK_PARTIAL_OK means include the last char
596 * which only partially fit on this line.
597 * TK_WHOLE_WORDS means stop on a word
598 * boundary, if possible.
599 * TK_AT_LEAST_ONE means return at least one
600 * character even if no characters fit. */
601 int *lengthPtr) /* Filled with x-location just after the
602 * terminating character. */
608 SubFont *lastSubFontPtr;
611 * According to Microsoft tech support, Windows does not use kerning
612 * or fractional character widths when displaying text on the screen.
613 * So that means we can safely measure individual characters or spans
614 * of characters and add up the widths w/o any "off-by-one-pixel"
618 fontPtr = (WinFont *) tkfont;
620 hdc = GetDC(fontPtr->hwnd);
621 lastSubFontPtr = &fontPtr->subFontArray[0];
622 oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
627 } else if (maxLength < 0) {
630 FontFamily *familyPtr;
631 Tcl_DString runString;
632 SubFont *thisSubFontPtr;
633 CONST char *p, *end, *next;
636 * A three step process:
637 * 1. Find a contiguous range of characters that can all be
638 * represented by a single screen font.
639 * 2. Convert those chars to the encoding of that font.
640 * 3. Measure converted chars.
644 end = source + numBytes;
645 for (p = source; p < end; ) {
646 next = p + Tcl_UtfToUniChar(p, &ch);
647 thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
648 if (thisSubFontPtr != lastSubFontPtr) {
649 familyPtr = lastSubFontPtr->familyPtr;
650 Tcl_UtfToExternalDString(familyPtr->encoding, source,
651 p - source, &runString);
652 (*familyPtr->getTextExtentPoint32Proc)(hdc,
653 Tcl_DStringValue(&runString),
654 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
657 Tcl_DStringFree(&runString);
658 lastSubFontPtr = thisSubFontPtr;
661 SelectObject(hdc, lastSubFontPtr->hFont);
665 familyPtr = lastSubFontPtr->familyPtr;
666 Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
668 (*familyPtr->getTextExtentPoint32Proc)(hdc,
669 Tcl_DStringValue(&runString),
670 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
673 Tcl_DStringFree(&runString);
679 FontFamily *familyPtr;
680 SubFont *thisSubFontPtr;
681 CONST char *term, *end, *p, *next;
682 int newX, termX, sawNonSpace, dstWrote;
685 * How many chars will fit in the space allotted?
686 * This first version may be inefficient because it measures
687 * every character individually. There is a function call that
688 * can measure multiple characters at once and return the
689 * offset of each of them, but it only works on NT, even though
690 * the documentation claims it works for 95.
691 * TODO: verify that GetTextExtentExPoint is still broken in '95, and
692 * possibly use it for NT anyway since it should be much faster and
696 next = source + Tcl_UtfToUniChar(source, &ch);
697 newX = curX = termX = 0;
700 end = source + numBytes;
702 sawNonSpace = (ch > 255) || !isspace(ch);
703 for (p = source; ; ) {
704 if (ch < BASE_CHARS) {
705 newX += fontPtr->widths[ch];
707 thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
708 if (thisSubFontPtr != lastSubFontPtr) {
709 SelectObject(hdc, thisSubFontPtr->hFont);
710 lastSubFontPtr = thisSubFontPtr;
712 familyPtr = lastSubFontPtr->familyPtr;
713 Tcl_UtfToExternal(NULL, familyPtr->encoding, p, next - p,
714 0, NULL, buf, sizeof(buf), NULL, &dstWrote, NULL);
715 (*familyPtr->getTextExtentPoint32Proc)(hdc, buf,
716 dstWrote >> familyPtr->isWideFont, &size);
719 if (newX > maxLength) {
730 next += Tcl_UtfToUniChar(next, &ch);
731 if ((ch < 256) && isspace(ch)) {
743 * P points to the first character that doesn't fit in the desired
744 * span. Use the flags to figure out what to return.
747 if ((flags & TK_PARTIAL_OK) && (p < end) && (curX < maxLength)) {
749 * Include the first character that didn't quite fit in the desired
750 * span. The width returned will include the width of that extra
755 p += Tcl_UtfToUniChar(p, &ch);
757 if ((flags & TK_AT_LEAST_ONE) && (term == source) && (p < end)) {
760 if (term == source) {
761 term += Tcl_UtfToUniChar(term, &ch);
764 } else if ((p >= end) || !(flags & TK_WHOLE_WORDS)) {
770 curByte = term - source;
773 SelectObject(hdc, oldFont);
774 ReleaseDC(fontPtr->hwnd, hdc);
781 *---------------------------------------------------------------------------
785 * Draw a string of characters on the screen.
791 * Information gets drawn on the screen.
793 *---------------------------------------------------------------------------
798 Display *display, /* Display on which to draw. */
799 Drawable drawable, /* Window or pixmap in which to draw. */
800 GC gc, /* Graphics context for drawing characters. */
801 Tk_Font tkfont, /* Font in which characters will be drawn;
802 * must be the same as font used in GC. */
803 CONST char *source, /* UTF-8 string to be displayed. Need not be
804 * '\0' terminated. All Tk meta-characters
805 * (tabs, control characters, and newlines)
806 * should be stripped out of the string that
807 * is passed to this function. If they are
808 * not stripped out, they will be displayed as
809 * regular printing characters. */
810 int numBytes, /* Number of bytes in string. */
811 int x, int y) /* Coordinates at which to place origin of
812 * string when drawing. */
818 fontPtr = (WinFont *) gc->font;
821 if (drawable == None) {
825 dc = TkWinGetDrawableDC(display, drawable, &state);
827 SetROP2(dc, tkpWinRopModes[gc->function]);
829 if ((gc->fill_style == FillStippled
830 || gc->fill_style == FillOpaqueStippled)
831 && gc->stipple != None) {
832 TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
833 HBRUSH oldBrush, stipple;
834 HBITMAP oldBitmap, bitmap;
839 if (twdPtr->type != TWD_BITMAP) {
840 panic("unexpected drawable type in stipple");
844 * Select stipple pattern into destination dc.
847 dcMem = CreateCompatibleDC(dc);
849 stipple = CreatePatternBrush(twdPtr->bitmap.handle);
850 SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
851 oldBrush = SelectObject(dc, stipple);
853 SetTextAlign(dcMem, TA_LEFT | TA_BASELINE);
854 SetTextColor(dcMem, gc->foreground);
855 SetBkMode(dcMem, TRANSPARENT);
856 SetBkColor(dcMem, RGB(0, 0, 0));
859 * Compute the bounding box and create a compatible bitmap.
862 GetTextExtentPoint(dcMem, source, numBytes, &size);
863 GetTextMetrics(dcMem, &tm);
864 size.cx -= tm.tmOverhang;
865 bitmap = CreateCompatibleBitmap(dc, size.cx, size.cy);
866 oldBitmap = SelectObject(dcMem, bitmap);
869 * The following code is tricky because fonts are rendered in multiple
870 * colors. First we draw onto a black background and copy the white
871 * bits. Then we draw onto a white background and copy the black bits.
872 * Both the foreground and background bits of the font are ANDed with
873 * the stipple pattern as they are copied.
876 PatBlt(dcMem, 0, 0, size.cx, size.cy, BLACKNESS);
877 MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
878 BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
880 PatBlt(dcMem, 0, 0, size.cx, size.cy, WHITENESS);
881 MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
882 BitBlt(dc, x, y - tm.tmAscent, size.cx, size.cy, dcMem,
886 * Destroy the temporary bitmap and restore the device context.
889 SelectObject(dcMem, oldBitmap);
890 DeleteObject(bitmap);
892 SelectObject(dc, oldBrush);
893 DeleteObject(stipple);
895 SetTextAlign(dc, TA_LEFT | TA_BASELINE);
896 SetTextColor(dc, gc->foreground);
897 SetBkMode(dc, TRANSPARENT);
898 MultiFontTextOut(dc, fontPtr, source, numBytes, x, y);
900 TkWinReleaseDrawableDC(drawable, dc, &state);
904 *-------------------------------------------------------------------------
906 * MultiFontTextOut --
908 * Helper function for Tk_DrawChars. Draws characters, using the
909 * various screen fonts in fontPtr to draw multilingual characters.
910 * Note: No bidirectional support.
916 * Information gets drawn on the screen.
917 * Contents of fontPtr may be modified if more subfonts were loaded
918 * in order to draw all the multilingual characters in the given
921 *-------------------------------------------------------------------------
926 HDC hdc, /* HDC to draw into. */
927 WinFont *fontPtr, /* Contains set of fonts to use when drawing
928 * following string. */
929 CONST char *source, /* Potentially multilingual UTF-8 string. */
930 int numBytes, /* Length of string in bytes. */
931 int x, int y) /* Coordinates at which to place origin *
932 * of string when drawing. */
937 FontFamily *familyPtr;
938 Tcl_DString runString;
939 CONST char *p, *end, *next;
940 SubFont *lastSubFontPtr, *thisSubFontPtr;
942 lastSubFontPtr = &fontPtr->subFontArray[0];
943 oldFont = SelectObject(hdc, lastSubFontPtr->hFont);
945 end = source + numBytes;
946 for (p = source; p < end; ) {
947 next = p + Tcl_UtfToUniChar(p, &ch);
948 thisSubFontPtr = FindSubFontForChar(fontPtr, ch);
949 if (thisSubFontPtr != lastSubFontPtr) {
951 familyPtr = lastSubFontPtr->familyPtr;
952 Tcl_UtfToExternalDString(familyPtr->encoding, source,
953 p - source, &runString);
954 (*familyPtr->textOutProc)(hdc, x, y,
955 Tcl_DStringValue(&runString),
956 Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
957 (*familyPtr->getTextExtentPoint32Proc)(hdc,
958 Tcl_DStringValue(&runString),
959 Tcl_DStringLength(&runString) >> familyPtr->isWideFont,
962 Tcl_DStringFree(&runString);
964 lastSubFontPtr = thisSubFontPtr;
966 SelectObject(hdc, lastSubFontPtr->hFont);
971 familyPtr = lastSubFontPtr->familyPtr;
972 Tcl_UtfToExternalDString(familyPtr->encoding, source, p - source,
974 (*familyPtr->textOutProc)(hdc, x, y, Tcl_DStringValue(&runString),
975 Tcl_DStringLength(&runString) >> familyPtr->isWideFont);
976 Tcl_DStringFree(&runString);
978 SelectObject(hdc, oldFont);
982 *---------------------------------------------------------------------------
986 * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes().
987 * Initializes the memory for a new WinFont that wraps the
988 * platform-specific data.
990 * The caller is responsible for initializing the fields of the
991 * WinFont that are used exclusively by the generic TkFont code, and
992 * for releasing those fields before calling TkpDeleteFont().
995 * Fills the WinFont structure.
1000 *---------------------------------------------------------------------------
1005 Tk_Window tkwin, /* Main window of interp in which font will
1006 * be used, for getting HDC. */
1007 HFONT hFont, /* Windows token for font. */
1008 int overstrike, /* The overstrike attribute of logfont used
1009 * to allocate this font. For some reason,
1010 * the TEXTMETRICs may contain incorrect info
1011 * in the tmStruckOut field. */
1012 WinFont *fontPtr) /* Filled with information constructed from
1013 * the above arguments. */
1020 TkFontMetrics *fmPtr;
1021 Tcl_Encoding encoding;
1022 Tcl_DString faceString;
1023 TkFontAttributes *faPtr;
1024 char buf[LF_FACESIZE * sizeof(WCHAR)];
1026 window = Tk_WindowId(tkwin);
1027 hwnd = (window == None) ? NULL : TkWinGetHWND(window);
1029 oldFont = SelectObject(hdc, hFont);
1031 GetTextMetrics(hdc, &tm);
1034 * On any version NT, there may fonts with international names.
1035 * Use the NT-only Unicode version of GetTextFace to get the font's
1036 * name. If we used the ANSI version on a non-internationalized
1037 * version of NT, we would get a font name with '?' replacing all
1038 * the international characters.
1040 * On a non-internationalized verson of 95, fonts with international
1041 * names are not allowed, so the ANSI version of GetTextFace will work.
1042 * On an internationalized version of 95, there may be fonts with
1043 * international names; the ANSI version will work, fetching the
1044 * name in the international system code page. Can't use the Unicode
1045 * version of GetTextFace because it only exists under NT.
1048 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1049 GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
1051 GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
1053 Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
1055 fontPtr->font.fid = (Font) fontPtr;
1057 faPtr = &fontPtr->font.fa;
1058 faPtr->family = Tk_GetUid(Tcl_DStringValue(&faceString));
1059 faPtr->size = TkFontGetPoints(tkwin, -(tm.tmHeight - tm.tmInternalLeading));
1060 faPtr->weight = (tm.tmWeight > FW_MEDIUM) ? TK_FW_BOLD : TK_FW_NORMAL;
1061 faPtr->slant = (tm.tmItalic != 0) ? TK_FS_ITALIC : TK_FS_ROMAN;
1062 faPtr->underline = (tm.tmUnderlined != 0) ? 1 : 0;
1063 faPtr->overstrike = overstrike;
1065 fmPtr = &fontPtr->font.fm;
1066 fmPtr->ascent = tm.tmAscent;
1067 fmPtr->descent = tm.tmDescent;
1068 fmPtr->maxWidth = tm.tmMaxCharWidth;
1069 fmPtr->fixed = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1071 fontPtr->hwnd = hwnd;
1072 fontPtr->pixelSize = tm.tmHeight - tm.tmInternalLeading;
1074 fontPtr->numSubFonts = 1;
1075 fontPtr->subFontArray = fontPtr->staticSubFonts;
1076 InitSubFont(hdc, hFont, 1, &fontPtr->subFontArray[0]);
1078 encoding = fontPtr->subFontArray[0].familyPtr->encoding;
1079 if (encoding == unicodeEncoding) {
1080 GetCharWidthW(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
1082 GetCharWidthA(hdc, 0, BASE_CHARS - 1, fontPtr->widths);
1084 Tcl_DStringFree(&faceString);
1086 SelectObject(hdc, oldFont);
1087 ReleaseDC(hwnd, hdc);
1091 *-------------------------------------------------------------------------
1095 * Called to release the windows-specific contents of a TkFont.
1096 * The caller is responsible for freeing the memory used by the
1105 *---------------------------------------------------------------------------
1110 WinFont *fontPtr) /* The font to delete. */
1114 for (i = 0; i < fontPtr->numSubFonts; i++) {
1115 ReleaseSubFont(&fontPtr->subFontArray[i]);
1117 if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
1118 ckfree((char *) fontPtr->subFontArray);
1123 *-------------------------------------------------------------------------
1127 * Wrap a screen font and load the FontFamily that represents
1128 * it. Used to prepare a SubFont so that characters can be mapped
1129 * from UTF-8 to the charset of the font.
1132 * The subFontPtr is filled with information about the font.
1137 *-------------------------------------------------------------------------
1142 HDC hdc, /* HDC in which font can be selected. */
1143 HFONT hFont, /* The screen font. */
1144 int base, /* Non-zero if this SubFont is being used
1145 * as the base font for a font object. */
1146 SubFont *subFontPtr) /* Filled with SubFont constructed from
1147 * above attributes. */
1149 subFontPtr->hFont = hFont;
1150 subFontPtr->familyPtr = AllocFontFamily(hdc, hFont, base);
1151 subFontPtr->fontMap = subFontPtr->familyPtr->fontMap;
1155 *-------------------------------------------------------------------------
1159 * Called to release the contents of a SubFont. The caller is
1160 * responsible for freeing the memory used by the SubFont itself.
1166 * Memory and resources are freed.
1168 *---------------------------------------------------------------------------
1173 SubFont *subFontPtr) /* The SubFont to delete. */
1175 DeleteObject(subFontPtr->hFont);
1176 FreeFontFamily(subFontPtr->familyPtr);
1180 *-------------------------------------------------------------------------
1182 * AllocFontFamily --
1184 * Find the FontFamily structure associated with the given font
1185 * name. The information should be stored by the caller in a
1186 * SubFont and used when determining if that SubFont supports a
1189 * Cannot use the string name used to construct the font as the
1190 * key, because the capitalization may not be canonical. Therefore
1191 * use the face name actually retrieved from the font metrics as
1195 * A pointer to a FontFamily. The reference count in the FontFamily
1196 * is automatically incremented. When the SubFont is released, the
1197 * reference count is decremented. When no SubFont is using this
1198 * FontFamily, it may be deleted.
1201 * A new FontFamily structure will be allocated if this font family
1202 * has not been seen. TrueType character existence metrics are
1203 * loaded into the FontFamily structure.
1205 *-------------------------------------------------------------------------
1210 HDC hdc, /* HDC in which font can be selected. */
1211 HFONT hFont, /* Screen font whose FontFamily is to be
1213 int base) /* Non-zero if this font family is to be
1214 * used in the base font of a font object. */
1217 FontFamily *familyPtr;
1218 Tcl_DString faceString;
1219 Tcl_Encoding encoding;
1220 char buf[LF_FACESIZE * sizeof(WCHAR)];
1221 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1222 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1224 hFont = SelectObject(hdc, hFont);
1225 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1226 GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf);
1228 GetTextFaceA(hdc, LF_FACESIZE, (char *) buf);
1230 Tcl_ExternalToUtfDString(systemEncoding, buf, -1, &faceString);
1231 faceName = Tk_GetUid(Tcl_DStringValue(&faceString));
1232 Tcl_DStringFree(&faceString);
1233 hFont = SelectObject(hdc, hFont);
1235 familyPtr = tsdPtr->fontFamilyList;
1236 for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) {
1237 if (familyPtr->faceName == faceName) {
1238 familyPtr->refCount++;
1243 familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily));
1244 memset(familyPtr, 0, sizeof(FontFamily));
1245 familyPtr->nextPtr = tsdPtr->fontFamilyList;
1246 tsdPtr->fontFamilyList = familyPtr;
1249 * Set key for this FontFamily.
1252 familyPtr->faceName = faceName;
1255 * An initial refCount of 2 means that FontFamily information will
1256 * persist even when the SubFont that loaded the FontFamily is released.
1257 * Change it to 1 to cause FontFamilies to be unloaded when not in use.
1260 familyPtr->refCount = 2;
1262 familyPtr->segCount = LoadFontRanges(hdc, hFont, &familyPtr->startCount,
1263 &familyPtr->endCount, &familyPtr->isSymbolFont);
1266 if (familyPtr->isSymbolFont != 0) {
1268 * Symbol fonts are handled specially. For instance, Unicode 0393
1269 * (GREEK CAPITAL GAMMA) must be mapped to Symbol character 0047
1270 * (GREEK CAPITAL GAMMA), because the Symbol font doesn't have a
1271 * GREEK CAPITAL GAMMA at location 0393. If Tk interpreted the
1272 * Symbol font using the Unicode encoding, it would decide that
1273 * the Symbol font has no GREEK CAPITAL GAMMA, because the Symbol
1274 * encoding (of course) reports that character 0393 doesn't exist.
1276 * With non-symbol Windows fonts, such as Times New Roman, if the
1277 * font has a GREEK CAPITAL GAMMA, it will be found in the correct
1278 * Unicode location (0393); the GREEK CAPITAL GAMMA will not be off
1279 * hiding at some other location.
1282 encoding = Tcl_GetEncoding(NULL, faceName);
1285 if (encoding == NULL) {
1286 encoding = Tcl_GetEncoding(NULL, "unicode");
1287 familyPtr->textOutProc =
1288 (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutW;
1289 familyPtr->getTextExtentPoint32Proc =
1290 (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32W;
1291 familyPtr->isWideFont = 1;
1293 familyPtr->textOutProc =
1294 (BOOL (WINAPI *)(HDC, int, int, TCHAR *, int)) TextOutA;
1295 familyPtr->getTextExtentPoint32Proc =
1296 (BOOL (WINAPI *)(HDC, TCHAR *, int, LPSIZE)) GetTextExtentPoint32A;
1297 familyPtr->isWideFont = 0;
1300 familyPtr->encoding = encoding;
1306 *-------------------------------------------------------------------------
1310 * Called to free a FontFamily when the SubFont is finished using it.
1311 * Frees the contents of the FontFamily and the memory used by the
1312 * FontFamily itself.
1320 *-------------------------------------------------------------------------
1325 FontFamily *familyPtr) /* The FontFamily to delete. */
1328 FontFamily **familyPtrPtr;
1329 ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1330 Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1332 if (familyPtr == NULL) {
1335 familyPtr->refCount--;
1336 if (familyPtr->refCount > 0) {
1339 for (i = 0; i < FONTMAP_PAGES; i++) {
1340 if (familyPtr->fontMap[i] != NULL) {
1341 ckfree(familyPtr->fontMap[i]);
1344 if (familyPtr->startCount != NULL) {
1345 ckfree((char *) familyPtr->startCount);
1347 if (familyPtr->endCount != NULL) {
1348 ckfree((char *) familyPtr->endCount);
1350 if (familyPtr->encoding != unicodeEncoding) {
1351 Tcl_FreeEncoding(familyPtr->encoding);
1358 for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) {
1359 if (*familyPtrPtr == familyPtr) {
1360 *familyPtrPtr = familyPtr->nextPtr;
1363 familyPtrPtr = &(*familyPtrPtr)->nextPtr;
1366 ckfree((char *) familyPtr);
1370 *-------------------------------------------------------------------------
1372 * FindSubFontForChar --
1374 * Determine which screen font is necessary to use to display the
1375 * given character. If the font object does not have a screen font
1376 * that can display the character, another screen font may be loaded
1377 * into the font object, following a set of preferred fallback rules.
1380 * The return value is the SubFont to use to display the given
1384 * The contents of fontPtr are modified to cache the results
1385 * of the lookup and remember any SubFonts that were dynamically
1388 *-------------------------------------------------------------------------
1393 WinFont *fontPtr, /* The font object with which the character
1394 * will be displayed. */
1395 int ch) /* The Unicode character to be displayed. */
1400 char **aliases, **anyFallbacks;
1401 char ***fontFallbacks;
1403 SubFont *subFontPtr;
1406 if (ch < BASE_CHARS) {
1407 return &fontPtr->subFontArray[0];
1410 for (i = 0; i < fontPtr->numSubFonts; i++) {
1411 if (FontMapLookup(&fontPtr->subFontArray[i], ch)) {
1412 return &fontPtr->subFontArray[i];
1417 * Keep track of all face names that we check, so we don't check some
1418 * name multiple times if it can be reached by multiple paths.
1421 Tcl_DStringInit(&ds);
1422 hdc = GetDC(fontPtr->hwnd);
1424 aliases = TkFontGetAliasList(fontPtr->font.fa.family);
1426 fontFallbacks = TkFontGetFallbacks();
1427 for (i = 0; fontFallbacks[i] != NULL; i++) {
1428 for (j = 0; fontFallbacks[i][j] != NULL; j++) {
1429 fallbackName = fontFallbacks[i][j];
1430 if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) {
1432 * If the base font has a fallback...
1436 } else if (aliases != NULL) {
1438 * Or if an alias for the base font has a fallback...
1441 for (k = 0; aliases[k] != NULL; k++) {
1442 if (strcasecmp(aliases[k], fallbackName) == 0) {
1451 * ...then see if we can use one of the fallbacks, or an
1452 * alias for one of the fallbacks.
1456 for (j = 0; fontFallbacks[i][j] != NULL; j++) {
1457 fallbackName = fontFallbacks[i][j];
1458 subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
1460 if (subFontPtr != NULL) {
1467 * See if we can use something from the global fallback list.
1470 anyFallbacks = TkFontGetGlobalClass();
1471 for (i = 0; anyFallbacks[i] != NULL; i++) {
1472 fallbackName = anyFallbacks[i];
1473 subFontPtr = CanUseFallbackWithAliases(hdc, fontPtr, fallbackName,
1475 if (subFontPtr != NULL) {
1481 * Try all face names available in the whole system until we
1482 * find one that can be used.
1486 canUse.fontPtr = fontPtr;
1487 canUse.nameTriedPtr = &ds;
1489 canUse.subFontPtr = NULL;
1490 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1491 EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc,
1494 EnumFontFamiliesA(hdc, NULL, (FONTENUMPROCA) WinFontCanUseProc,
1497 subFontPtr = canUse.subFontPtr;
1500 Tcl_DStringFree(&ds);
1502 if (subFontPtr == NULL) {
1504 * No font can display this character. We will use the base font
1505 * and have it display the "unknown" character.
1508 subFontPtr = &fontPtr->subFontArray[0];
1509 FontMapInsert(subFontPtr, ch);
1511 ReleaseDC(fontPtr->hwnd, hdc);
1517 ENUMLOGFONT *lfPtr, /* Logical-font data. */
1518 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
1519 int fontType, /* Type of font (not used). */
1520 LPARAM lParam) /* Result object to hold result. */
1527 SubFont *subFontPtr;
1528 Tcl_DString faceString;
1529 Tcl_DString *nameTriedPtr;
1531 canUsePtr = (CanUse *) lParam;
1533 hdc = canUsePtr->hdc;
1534 fontPtr = canUsePtr->fontPtr;
1535 nameTriedPtr = canUsePtr->nameTriedPtr;
1537 fallbackName = lfPtr->elfLogFont.lfFaceName;
1538 Tcl_ExternalToUtfDString(systemEncoding, fallbackName, -1, &faceString);
1539 fallbackName = Tcl_DStringValue(&faceString);
1541 if (SeenName(fallbackName, nameTriedPtr) == 0) {
1542 subFontPtr = CanUseFallback(hdc, fontPtr, fallbackName, ch);
1543 if (subFontPtr != NULL) {
1544 canUsePtr->subFontPtr = subFontPtr;
1545 Tcl_DStringFree(&faceString);
1549 Tcl_DStringFree(&faceString);
1554 *-------------------------------------------------------------------------
1558 * See if the screen font can display the given character.
1561 * The return value is 0 if the screen font cannot display the
1562 * character, non-zero otherwise.
1565 * New pages are added to the font mapping cache whenever the
1566 * character belongs to a page that hasn't been seen before.
1567 * When a page is loaded, information about all the characters on
1568 * that page is stored, not just for the single character in
1571 *-------------------------------------------------------------------------
1576 SubFont *subFontPtr, /* Contains font mapping cache to be queried
1577 * and possibly updated. */
1578 int ch) /* Character to be tested. */
1582 row = ch >> FONTMAP_SHIFT;
1583 if (subFontPtr->fontMap[row] == NULL) {
1584 FontMapLoadPage(subFontPtr, row);
1586 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
1587 return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1;
1591 *-------------------------------------------------------------------------
1595 * Tell the font mapping cache that the given screen font should be
1596 * used to display the specified character. This is called when no
1597 * font on the system can be be found that can display that
1598 * character; we lie to the font and tell it that it can display
1599 * the character, otherwise we would end up re-searching the entire
1600 * fallback hierarchy every time that character was seen.
1606 * New pages are added to the font mapping cache whenever the
1607 * character belongs to a page that hasn't been seen before.
1608 * When a page is loaded, information about all the characters on
1609 * that page is stored, not just for the single character in
1612 *-------------------------------------------------------------------------
1617 SubFont *subFontPtr, /* Contains font mapping cache to be
1619 int ch) /* Character to be added to cache. */
1623 row = ch >> FONTMAP_SHIFT;
1624 if (subFontPtr->fontMap[row] == NULL) {
1625 FontMapLoadPage(subFontPtr, row);
1627 bitOffset = ch & (FONTMAP_BITSPERPAGE - 1);
1628 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1632 *-------------------------------------------------------------------------
1634 * FontMapLoadPage --
1636 * Load information about all the characters on a given page.
1637 * This information consists of one bit per character that indicates
1638 * whether the associated HFONT can (1) or cannot (0) display the
1639 * characters on the page.
1647 *-------------------------------------------------------------------------
1651 SubFont *subFontPtr, /* Contains font mapping cache to be
1653 int row) /* Index of the page to be loaded into
1656 FontFamily *familyPtr;
1657 Tcl_Encoding encoding;
1658 char src[TCL_UTF_MAX], buf[16];
1659 USHORT *startCount, *endCount;
1660 int i, j, bitOffset, end, segCount;
1662 subFontPtr->fontMap[row] = (char *) ckalloc(FONTMAP_BITSPERPAGE / 8);
1663 memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8);
1665 familyPtr = subFontPtr->familyPtr;
1666 encoding = familyPtr->encoding;
1668 if (familyPtr->encoding == unicodeEncoding) {
1670 * Font is Unicode. Few fonts are going to have all characters, so
1671 * examine the TrueType character existence metrics to determine
1672 * what characters actually exist in this font.
1675 segCount = familyPtr->segCount;
1676 startCount = familyPtr->startCount;
1677 endCount = familyPtr->endCount;
1680 end = (row + 1) << FONTMAP_SHIFT;
1681 for (i = row << FONTMAP_SHIFT; i < end; i++) {
1682 for ( ; j < segCount; j++) {
1683 if (endCount[j] >= i) {
1684 if (startCount[j] <= i) {
1685 bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
1686 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1692 } else if (familyPtr->isSymbolFont) {
1694 * Assume that a symbol font with a known encoding has all the
1695 * characters that its encoding claims it supports.
1697 * The test for "encoding == unicodeEncoding"
1698 * must occur before this case, to catch all symbol fonts (such
1699 * as {Comic Sans MS} or Wingdings) for which we don't have
1700 * encoding information; those symbol fonts are treated as if
1701 * they were in the Unicode encoding and their symbolic
1702 * character existence metrics are treated as if they were Unicode
1703 * character existence metrics. This way, although we don't know
1704 * the proper Unicode -> symbol font mapping, we can install the
1705 * symbol font as the base font and access its glyphs.
1708 end = (row + 1) << FONTMAP_SHIFT;
1709 for (i = row << FONTMAP_SHIFT; i < end; i++) {
1710 if (Tcl_UtfToExternal(NULL, encoding, src,
1711 Tcl_UniCharToUtf(i, src), TCL_ENCODING_STOPONERROR, NULL,
1712 buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK) {
1715 bitOffset = i & (FONTMAP_BITSPERPAGE - 1);
1716 subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7);
1722 *---------------------------------------------------------------------------
1724 * CanUseFallbackWithAliases --
1726 * Helper function for FindSubFontForChar. Determine if the
1727 * specified face name (or an alias of the specified face name)
1728 * can be used to construct a screen font that can display the
1732 * See CanUseFallback().
1735 * If the name and/or one of its aliases was rejected, the
1736 * rejected string is recorded in nameTriedPtr so that it won't
1739 *---------------------------------------------------------------------------
1743 CanUseFallbackWithAliases(
1744 HDC hdc, /* HDC in which font can be selected. */
1745 WinFont *fontPtr, /* The font object that will own the new
1747 char *faceName, /* Desired face name for new screen font. */
1748 int ch, /* The Unicode character that the new
1749 * screen font must be able to display. */
1750 Tcl_DString *nameTriedPtr) /* Records face names that have already
1751 * been tried. It is possible for the same
1752 * face name to be queried multiple times when
1753 * trying to find a suitable screen font. */
1757 SubFont *subFontPtr;
1759 if (SeenName(faceName, nameTriedPtr) == 0) {
1760 subFontPtr = CanUseFallback(hdc, fontPtr, faceName, ch);
1761 if (subFontPtr != NULL) {
1765 aliases = TkFontGetAliasList(faceName);
1766 if (aliases != NULL) {
1767 for (i = 0; aliases[i] != NULL; i++) {
1768 if (SeenName(aliases[i], nameTriedPtr) == 0) {
1769 subFontPtr = CanUseFallback(hdc, fontPtr, aliases[i], ch);
1770 if (subFontPtr != NULL) {
1780 *---------------------------------------------------------------------------
1784 * Used to determine we have already tried and rejected the given
1785 * face name when looking for a screen font that can support some
1786 * Unicode character.
1789 * The return value is 0 if this face name has not already been seen,
1790 * non-zero otherwise.
1795 *---------------------------------------------------------------------------
1800 CONST char *name, /* The name to check. */
1801 Tcl_DString *dsPtr) /* Contains names that have already been
1804 CONST char *seen, *end;
1806 seen = Tcl_DStringValue(dsPtr);
1807 end = seen + Tcl_DStringLength(dsPtr);
1808 while (seen < end) {
1809 if (strcasecmp(seen, name) == 0) {
1812 seen += strlen(seen) + 1;
1814 Tcl_DStringAppend(dsPtr, (char *) name, (int) (strlen(name) + 1));
1819 *-------------------------------------------------------------------------
1823 * If the specified screen font has not already been loaded into
1824 * the font object, determine if it can display the given character.
1827 * The return value is a pointer to a newly allocated SubFont, owned
1828 * by the font object. This SubFont can be used to display the given
1829 * character. The SubFont represents the screen font with the base set
1830 * of font attributes from the font object, but using the specified
1831 * font name. NULL is returned if the font object already holds
1832 * a reference to the specified physical font or if the specified
1833 * physical font cannot display the given character.
1836 * The font object's subFontArray is updated to contain a reference
1837 * to the newly allocated SubFont.
1839 *-------------------------------------------------------------------------
1844 HDC hdc, /* HDC in which font can be selected. */
1845 WinFont *fontPtr, /* The font object that will own the new
1847 char *faceName, /* Desired face name for new screen font. */
1848 int ch) /* The Unicode character that the new
1849 * screen font must be able to display. */
1855 if (FamilyExists(hdc, faceName) == 0) {
1860 * Skip all fonts we've already used.
1863 for (i = 0; i < fontPtr->numSubFonts; i++) {
1864 if (faceName == fontPtr->subFontArray[i].familyPtr->faceName) {
1870 * Load this font and see if it has the desired character.
1873 hFont = GetScreenFont(&fontPtr->font.fa, faceName, fontPtr->pixelSize);
1874 InitSubFont(hdc, hFont, 0, &subFont);
1875 if (((ch < 256) && (subFont.familyPtr->isSymbolFont))
1876 || (FontMapLookup(&subFont, ch) == 0)) {
1878 * Don't use a symbol font as a fallback font for characters below
1882 ReleaseSubFont(&subFont);
1886 if (fontPtr->numSubFonts >= SUBFONT_SPACE) {
1889 newPtr = (SubFont *) ckalloc(sizeof(SubFont)
1890 * (fontPtr->numSubFonts + 1));
1891 memcpy((char *) newPtr, fontPtr->subFontArray,
1892 fontPtr->numSubFonts * sizeof(SubFont));
1893 if (fontPtr->subFontArray != fontPtr->staticSubFonts) {
1894 ckfree((char *) fontPtr->subFontArray);
1896 fontPtr->subFontArray = newPtr;
1898 fontPtr->subFontArray[fontPtr->numSubFonts] = subFont;
1899 fontPtr->numSubFonts++;
1900 return &fontPtr->subFontArray[fontPtr->numSubFonts - 1];
1904 *---------------------------------------------------------------------------
1908 * Given the name and other attributes, construct an HFONT.
1909 * This is where all the alias and fallback substitution bottoms
1913 * The screen font that corresponds to the attributes.
1918 *---------------------------------------------------------------------------
1923 CONST TkFontAttributes *faPtr,
1924 /* Desired font attributes for new HFONT. */
1925 CONST char *faceName, /* Overrides font family specified in font
1927 int pixelSize) /* Overrides size specified in font
1934 lf.lfHeight = -pixelSize;
1936 lf.lfEscapement = 0;
1937 lf.lfOrientation = 0;
1938 lf.lfWeight = (faPtr->weight == TK_FW_NORMAL) ? FW_NORMAL : FW_BOLD;
1939 lf.lfItalic = faPtr->slant;
1940 lf.lfUnderline = faPtr->underline;
1941 lf.lfStrikeOut = faPtr->overstrike;
1942 lf.lfCharSet = DEFAULT_CHARSET;
1943 lf.lfOutPrecision = OUT_TT_PRECIS;
1944 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
1945 lf.lfQuality = DEFAULT_QUALITY;
1946 lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1948 Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &ds);
1950 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
1951 Tcl_UniChar *src, *dst;
1954 * We can only store up to LF_FACESIZE wide characters
1956 if (Tcl_DStringLength(&ds) >= (LF_FACESIZE * sizeof(WCHAR))) {
1957 Tcl_DStringSetLength(&ds, LF_FACESIZE);
1959 src = (Tcl_UniChar *) Tcl_DStringValue(&ds);
1960 dst = (Tcl_UniChar *) lf.lfFaceName;
1961 while (*src != '\0') {
1965 hFont = CreateFontIndirectW(&lf);
1968 * We can only store up to LF_FACESIZE characters
1970 if (Tcl_DStringLength(&ds) >= LF_FACESIZE) {
1971 Tcl_DStringSetLength(&ds, LF_FACESIZE);
1973 strcpy((char *) lf.lfFaceName, Tcl_DStringValue(&ds));
1974 hFont = CreateFontIndirectA((LOGFONTA *) &lf);
1976 Tcl_DStringFree(&ds);
1981 *-------------------------------------------------------------------------
1983 * FamilyExists, FamilyOrAliasExists, WinFontExistsProc --
1985 * Determines if any physical screen font exists on the system with
1986 * the given family name. If the family exists, then it should be
1987 * possible to construct some physical screen font with that family
1991 * The return value is 0 if the specified font family does not exist,
1992 * non-zero otherwise.
1997 *-------------------------------------------------------------------------
2002 HDC hdc, /* HDC in which font family will be used. */
2003 CONST char *faceName) /* Font family to query. */
2006 Tcl_DString faceString;
2009 * Just immediately rule out the following fonts, because they look so
2010 * ugly on windows. The caller's fallback mechanism will cause the
2011 * corresponding appropriate TrueType fonts to be selected.
2014 if (strcasecmp(faceName, "Courier") == 0) {
2017 if (strcasecmp(faceName, "Times") == 0) {
2020 if (strcasecmp(faceName, "Helvetica") == 0) {
2024 Tcl_UtfToExternalDString(systemEncoding, faceName, -1, &faceString);
2027 * If the family exists, WinFontExistProc() will be called and
2028 * EnumFontFamilies() will return whatever WinFontExistProc() returns.
2029 * If the family doesn't exist, EnumFontFamilies() will just return a
2033 if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
2034 result = EnumFontFamiliesW(hdc, (WCHAR *) Tcl_DStringValue(&faceString),
2035 (FONTENUMPROCW) WinFontExistProc, 0);
2037 result = EnumFontFamiliesA(hdc, (char *) Tcl_DStringValue(&faceString),
2038 (FONTENUMPROCA) WinFontExistProc, 0);
2040 Tcl_DStringFree(&faceString);
2041 return (result == 0);
2045 FamilyOrAliasExists(
2047 CONST char *faceName)
2052 if (FamilyExists(hdc, faceName) != 0) {
2053 return (char *) faceName;
2055 aliases = TkFontGetAliasList(faceName);
2056 if (aliases != NULL) {
2057 for (i = 0; aliases[i] != NULL; i++) {
2058 if (FamilyExists(hdc, aliases[i]) != 0) {
2068 ENUMLOGFONT *lfPtr, /* Logical-font data. */
2069 NEWTEXTMETRIC *tmPtr, /* Physical-font data (not used). */
2070 int fontType, /* Type of font (not used). */
2071 LPARAM lParam) /* EnumFontData to hold result. */
2077 * The following data structures are used when querying a TrueType font file
2078 * to determine which characters the font supports.
2081 #pragma pack(1) /* Structures are byte aligned in file. */
2083 #define CMAPHEX 0x636d6170 /* Key for character map resource. */
2085 typedef struct CMAPTABLE {
2086 USHORT version; /* Table version number (0). */
2087 USHORT numTables; /* Number of encoding tables following. */
2090 typedef struct ENCODINGTABLE {
2091 USHORT platform; /* Platform for which data is targeted.
2092 * 3 means data is for Windows. */
2093 USHORT encoding; /* How characters in font are encoded.
2094 * 1 means that the following subtable is
2095 * keyed based on Unicode. */
2096 ULONG offset; /* Byte offset from beginning of CMAPTABLE
2097 * to the subtable for this encoding. */
2100 typedef struct ANYTABLE {
2101 USHORT format; /* Format number. */
2102 USHORT length; /* The actual length in bytes of this
2104 USHORT version; /* Version number (starts at 0). */
2107 typedef struct BYTETABLE {
2108 USHORT format; /* Format number is set to 0. */
2109 USHORT length; /* The actual length in bytes of this
2111 USHORT version; /* Version number (starts at 0). */
2112 BYTE glyphIdArray[256]; /* Array that maps up to 256 single-byte char
2113 * codes to glyph indices. */
2116 typedef struct SUBHEADER {
2117 USHORT firstCode; /* First valid low byte for subHeader. */
2118 USHORT entryCount; /* Number valid low bytes for subHeader. */
2119 SHORT idDelta; /* Constant adder to get base glyph index. */
2120 USHORT idRangeOffset; /* Byte offset from here to appropriate
2121 * glyphIndexArray. */
2124 typedef struct HIBYTETABLE {
2125 USHORT format; /* Format number is set to 2. */
2126 USHORT length; /* The actual length in bytes of this
2128 USHORT version; /* Version number (starts at 0). */
2129 USHORT subHeaderKeys[256]; /* Maps high bytes to subHeaders: value is
2130 * subHeader index * 8. */
2132 SUBHEADER subHeaders[]; /* Variable-length array of SUBHEADERs. */
2133 USHORT glyphIndexArray[]; /* Variable-length array containing subarrays
2134 * used for mapping the low byte of 2-byte
2139 typedef struct SEGMENTTABLE {
2140 USHORT format; /* Format number is set to 4. */
2141 USHORT length; /* The actual length in bytes of this
2143 USHORT version; /* Version number (starts at 0). */
2144 USHORT segCountX2; /* 2 x segCount. */
2145 USHORT searchRange; /* 2 x (2**floor(log2(segCount))). */
2146 USHORT entrySelector; /* log2(searchRange/2). */
2147 USHORT rangeShift; /* 2 x segCount - searchRange. */
2149 USHORT endCount[segCount] /* End characterCode for each segment. */
2150 USHORT reservedPad; /* Set to 0. */
2151 USHORT startCount[segCount];/* Start character code for each segment. */
2152 USHORT idDelta[segCount]; /* Delta for all character in segment. */
2153 USHORT idRangeOffset[segCount]; /* Offsets into glyphIdArray or 0. */
2154 USHORT glyphIdArray[] /* Glyph index array. */
2158 typedef struct TRIMMEDTABLE {
2159 USHORT format; /* Format number is set to 6. */
2160 USHORT length; /* The actual length in bytes of this
2162 USHORT version; /* Version number (starts at 0). */
2163 USHORT firstCode; /* First character code of subrange. */
2164 USHORT entryCount; /* Number of character codes in subrange. */
2166 USHORT glyphIdArray[]; /* Array of glyph index values for
2167 character codes in the range. */
2171 typedef union SUBTABLE {
2175 SEGMENTTABLE segment;
2176 TRIMMEDTABLE trimmed;
2182 *-------------------------------------------------------------------------
2186 * Given an HFONT, get the information about the characters that
2187 * this font can display.
2190 * If the font has no Unicode character information, the return value
2191 * is 0 and *startCountPtr and *endCountPtr are filled with NULL.
2192 * Otherwise, *startCountPtr and *endCountPtr are set to pointers to
2193 * arrays of TrueType character existence information and the return
2194 * value is the length of the arrays (the two arrays are always the
2195 * same length as each other).
2200 *-------------------------------------------------------------------------
2205 HDC hdc, /* HDC into which font can be selected. */
2206 HFONT hFont, /* HFONT to query. */
2207 USHORT **startCountPtr, /* Filled with malloced pointer to
2208 * character range information. */
2209 USHORT **endCountPtr, /* Filled with malloced pointer to
2210 * character range information. */
2213 int n, i, swapped, offset, cbData, segCount;
2215 USHORT *startCount, *endCount;
2216 CMAPTABLE cmapTable;
2217 ENCODINGTABLE encTable;
2226 hFont = SelectObject(hdc, hFont);
2242 n = GetFontData(hdc, cmapKey, 0, &cmapTable, sizeof(cmapTable));
2243 if (n != GDI_ERROR) {
2245 SwapShort(&cmapTable.numTables);
2247 for (i = 0; i < cmapTable.numTables; i++) {
2248 offset = sizeof(cmapTable) + i * sizeof(encTable);
2249 GetFontData(hdc, cmapKey, offset, &encTable, sizeof(encTable));
2251 SwapShort(&encTable.platform);
2252 SwapShort(&encTable.encoding);
2253 SwapLong(&encTable.offset);
2255 if (encTable.platform != 3) {
2257 * Not Microsoft encoding.
2262 if (encTable.encoding == 0) {
2264 } else if (encTable.encoding != 1) {
2268 GetFontData(hdc, cmapKey, encTable.offset, &subTable,
2271 SwapShort(&subTable.any.format);
2273 if (subTable.any.format == 4) {
2275 SwapShort(&subTable.segment.segCountX2);
2277 segCount = subTable.segment.segCountX2 / 2;
2278 cbData = segCount * sizeof(USHORT);
2280 startCount = (USHORT *) ckalloc(cbData);
2281 endCount = (USHORT *) ckalloc(cbData);
2283 offset = encTable.offset + sizeof(subTable.segment);
2284 GetFontData(hdc, cmapKey, offset, endCount, cbData);
2285 offset += cbData + sizeof(USHORT);
2286 GetFontData(hdc, cmapKey, offset, startCount, cbData);
2288 for (i = 0; i < segCount; i++) {
2289 SwapShort(&endCount[i]);
2290 SwapShort(&startCount[i]);
2293 if (*symbolPtr != 0) {
2295 * Empirically determined: When a symbol font is
2296 * loaded, the character existence metrics obtained
2297 * from the system are mildly wrong. If the real range
2298 * of the symbol font is from 0020 to 00FE, then the
2299 * metrics are reported as F020 to F0FE. When we load
2300 * a symbol font, we must fix the character existence
2303 * Symbol fonts should only use the symbol encoding
2304 * for 8-bit characters [note Bug: 2406]
2307 for (i = 0; i < segCount; i++) {
2308 if (((startCount[i] & 0xff00) == 0xf000)
2309 && ((endCount[i] & 0xff00) == 0xf000)) {
2310 startCount[i] &= 0xff;
2311 endCount[i] &= 0xff;
2318 SelectObject(hdc, hFont);
2320 *startCountPtr = startCount;
2321 *endCountPtr = endCount;
2326 *-------------------------------------------------------------------------
2328 * SwapShort, SwapLong --
2330 * Helper functions to convert the data loaded from TrueType font
2331 * files to Intel byte ordering.
2334 * Bytes of input value are swapped and stored back in argument.
2339 *-------------------------------------------------------------------------
2343 SwapShort(PUSHORT p)
2345 *p = (SHORT)(HIBYTE(*p) + (LOBYTE(*p) << 8));
2353 temp = (LONG) ((BYTE) *p);
2357 temp += (LONG) ((BYTE) *p);
2361 temp += (LONG) ((BYTE) *p);
2365 temp += (LONG) ((BYTE) *p);