fix glyph-exists? for label

svn: r1601
This commit is contained in:
Matthew Flatt 2005-12-12 23:24:52 +00:00
parent b4a2f0570e
commit 029e7e85a3
2 changed files with 125 additions and 19 deletions

View File

@ -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

View File

@ -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);