diff --git a/src/wxwindow/include/msw/wx_gdi.h b/src/wxwindow/include/msw/wx_gdi.h index e8389ab77b..f705eb3032 100644 --- a/src/wxwindow/include/msw/wx_gdi.h +++ b/src/wxwindow/include/msw/wx_gdi.h @@ -50,6 +50,9 @@ class wxFont: public wxbFont Bool GlyphAvailableNow(int c, HDC hdc, int screen_font); wxFont *Substitute(int c, HDC hdc, int screen_font); + + Bool ScreenGlyphAvailabilityCached(int c, Bool for_label, Bool *avail); + void CacheScreenGlyphAvailability(int c, Bool for_label, Bool avail); }; class wxColourMap: public wxObject diff --git a/src/wxwindow/src/msw/wx_gdi.cxx b/src/wxwindow/src/msw/wx_gdi.cxx index ebf2684ea4..830f8f2630 100644 --- a/src/wxwindow/src/msw/wx_gdi.cxx +++ b/src/wxwindow/src/msw/wx_gdi.cxx @@ -34,6 +34,8 @@ int pen_count, brush_count, font_count, bitmap_count; # define COUNT_M(c) #endif +#pragma optimize("", off) + void RegisterGDIObject(HANDLE x); void DeleteRegisteredGDIObject(HANDLE x); @@ -196,6 +198,7 @@ static int glyph_exists_in_selected_font(HDC hdc, int c) typedef struct { HDC hdc; int c; + int just_face; int just_tt; wchar_t *face; } GlyphFindData; @@ -214,7 +217,10 @@ static int CALLBACK glyph_exists(ENUMLOGFONTW FAR* lpelf, /* This font might work... */ int ok = 1; - if (gfd->just_tt) + if (gfd->just_face) + ok = !memcmp(gfd->face, lpelf->elfLogFont.lfFaceName, + wx_wstrlen(gfd->face)); + else if (gfd->just_tt) ok = (type == TRUETYPE_FONTTYPE); else ok = (type != TRUETYPE_FONTTYPE); @@ -242,7 +248,7 @@ static int CALLBACK glyph_exists(ENUMLOGFONTW FAR* lpelf, DeleteObject(cfont); - if (gfd->face) { + if (gfd->face && !gfd->just_face) { memcpy(gfd->face, lpelf->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t)); } @@ -263,6 +269,7 @@ Bool wxFont::GlyphAvailable(int c, HDC hdc, int screen_font) gfd.hdc = hdc; gfd.c = c; gfd.face = NULL; + gfd.just_face = 0; gfd.just_tt = 1; if (!EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW)glyph_exists, (LPARAM)&gfd)) @@ -275,6 +282,36 @@ Bool wxFont::GlyphAvailable(int c, HDC hdc, int screen_font) return 0; } +Bool wxFont::ScreenGlyphAvailabilityCached(int c, Bool for_label, Bool *avail) +{ + if (glyph_cache) { + Scheme_Hash_Table *ht; + Scheme_Object *v; + ht = (Scheme_Hash_Table *)glyph_cache; + if (for_label) + c = -(c + 1); + v = scheme_hash_get(ht, scheme_make_integer(c)); + if (v) { + *avail = SCHEME_TRUEP(v); + return TRUE; + } + } + return FALSE; +} + +void wxFont::CacheScreenGlyphAvailability(int c, Bool for_label, Bool avail) +{ + Scheme_Hash_Table *ht; + ht = (Scheme_Hash_Table *)glyph_cache; + if (!ht) { + ht = scheme_make_hash_table(SCHEME_hash_ptr); + glyph_cache = ht; + } + if (for_label) + c = -(c + 1); + scheme_hash_set(ht, scheme_make_integer(c), avail ? scheme_true : scheme_false); +} + Bool wxFont::GlyphAvailableNow(int c, HDC hdc, int screen_font) { Bool avail; @@ -282,26 +319,15 @@ Bool wxFont::GlyphAvailableNow(int c, HDC hdc, int screen_font) if (redirect) return redirect->GlyphAvailableNow(c, hdc, screen_font); - if (screen_font && glyph_cache) { - Scheme_Hash_Table *ht; - Scheme_Object *v; - ht = (Scheme_Hash_Table *)glyph_cache; - v = scheme_hash_get(ht, scheme_make_integer(c)); - if (v) { - return SCHEME_TRUEP(v); - } + if (screen_font) { + if (ScreenGlyphAvailabilityCached(c, 0, &avail)) + return avail; } avail = glyph_exists_in_selected_font(hdc, c); if (screen_font) { - Scheme_Hash_Table *ht; - ht = (Scheme_Hash_Table *)glyph_cache; - if (!ht) { - ht = scheme_make_hash_table(SCHEME_hash_ptr); - glyph_cache = ht; - } - scheme_hash_set(ht, scheme_make_integer(c), avail ? scheme_true : scheme_false); + CacheScreenGlyphAvailability(c, 0, avail); } return avail; @@ -310,11 +336,14 @@ Bool wxFont::GlyphAvailableNow(int c, HDC hdc, int screen_font) Bool wxFont::ScreenGlyphAvailable(int c, Bool for_label) { HDC hdc; - Bool r; + Bool r, avail; if (redirect) return redirect->ScreenGlyphAvailable(c, for_label); + if (ScreenGlyphAvailabilityCached(c, for_label, &avail)) + return avail; + hdc = ::GetDC(NULL); if (for_label) { @@ -324,12 +353,85 @@ Bool wxFont::ScreenGlyphAvailable(int c, Bool for_label) old = (HFONT)::SelectObject(hdc, cfont); r = glyph_exists_in_selected_font(hdc, c); ::SelectObject(hdc, old); + + if (!r) { + /* Look for font links */ + HKEY key; + DWORD nlen, vlen, vlen2; + wchar_t value_name[256], *value; + char *face; + face = wxTheFontNameDirectory->GetScreenName(fontid, weight, style); + if (face) { + if (ERROR_SUCCESS + == RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink", + 0, KEY_READ, + &key)) { + int i = 0; + nlen = 256; + vlen = 0; + while (ERROR_SUCCESS + == RegEnumValueW(key, i, value_name, &nlen, + NULL, NULL, NULL, &vlen)) { + if (!strcmp(face, wxNARROW_STRING(value_name))) { + value = (wchar_t *)(new WXGC_ATOMIC char[vlen]); + vlen2 = vlen; + nlen++; + if (ERROR_SUCCESS + == RegEnumValueW(key, i, value_name, &nlen, + NULL, NULL, (BYTE *)value, &vlen2)) { + if (vlen2 == vlen) { + int j, k; + vlen >>= 1; + r = 0; + for (j = 0; j < vlen; j++) { + if (value[j] == ',') { + j++; + for (k = j; k < vlen; k++) { + if (!value[k]) + break; + } + /* Range from j (inclusive) to k (exclusive) is a font name */ + { + GlyphFindData gfd; + wchar_t *face; + face = (wchar_t *)(new WXGC_ATOMIC char[(k - j + 1) * sizeof(wchar_t)]); + memcpy(face, value + j, (k - j) * sizeof(wchar_t)); + face[k - j] = 0; + + gfd.hdc = hdc; + gfd.c = c; + gfd.face = face; + gfd.just_tt = 0; + gfd.just_face = 1; + + if (!EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW)glyph_exists, (LPARAM)&gfd)) { + r = 1; + break; + } + } + } + } + if (r) + break; + } + } + break; + } + i++; + } + RegCloseKey(key); + } + } + } } else { r = GlyphAvailable(c, hdc, 1); } ReleaseDC(NULL, hdc); + CacheScreenGlyphAvailability(c, for_label, r); + return r; } @@ -359,7 +461,8 @@ wxFont *wxFont::Substitute(int c, HDC dc, Bool screen_font) gfd.hdc = dc; gfd.c = c; gfd.face = facebuf; - + gfd.just_face = 0; + gfd.just_tt = 1; found = !EnumFontFamiliesW(dc, NULL, (FONTENUMPROCW)glyph_exists, (LPARAM)&gfd);