diff --git a/uppdev/FontInfo/Compose.cpp b/uppdev/FontInfo/Compose.cpp new file mode 100644 index 000000000..ec681521d --- /dev/null +++ b/uppdev/FontInfo/Compose.cpp @@ -0,0 +1,223 @@ +#include "FontInfo.h" + +enum { + CG_NONE, + CG_CAPITAL, + CG_SMALL +}; + +enum { + CG_GRAVE = 0x60, + CG_ACUTE = 0xb4, + CG_CEDILLA = 0xb8, + CG_MACRON = 175, + CG_CIRCUMFLEX = 0x2c6, + CG_TILDE = 0x2dc, + CG_DOT_ABOVE = 0x2d9, + CG_OGONEK = 0x2db, + CG_STROKE = '-', + CG_BREVE = 0x2d8, + CG_CARON = 0x2c7, + CG_MIDDLE_DOT = 0xb7, + CG_DOUBLE_ACUTE = 0x2dd, + CG_DIAERESIS = 0xa8, + CG_RING_ABOVE = 0x2da, + CG_COMMA_T = ',', + CG_COMMA_UR = 1, + CG_COMMA_URI, +}; + +struct CGInfo { + byte type; + char ascii; + wchar mark; +} +gc_info[128] = { + { CG_CAPITAL, 'A', CG_MACRON }, + { CG_SMALL, 'a', CG_MACRON }, + { CG_CAPITAL, 'A', CG_BREVE }, + { CG_SMALL, 'a', CG_BREVE }, + { CG_CAPITAL, 'A', CG_OGONEK }, + { CG_SMALL, 'a', CG_OGONEK }, + { CG_CAPITAL, 'C', CG_ACUTE }, + { CG_SMALL, 'c', CG_ACUTE }, + { CG_CAPITAL, 'C', CG_CIRCUMFLEX }, + { CG_SMALL, 'c', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'C', CG_DOT_ABOVE }, + { CG_SMALL, 'c', CG_DOT_ABOVE }, + { CG_CAPITAL, 'C', CG_CARON }, + { CG_SMALL, 'c', CG_CARON }, + { CG_CAPITAL, 'D', CG_CARON }, + { CG_SMALL, 'd', CG_COMMA_UR }, + { CG_CAPITAL, 'D', CG_STROKE }, + { CG_SMALL, 'd', CG_STROKE }, + { CG_CAPITAL, 'E', CG_MACRON }, + { CG_SMALL, 'e', CG_MACRON }, + { CG_CAPITAL, 'E', CG_BREVE }, + { CG_SMALL, 'e', CG_BREVE }, + { CG_CAPITAL, 'E', CG_DOT_ABOVE }, + { CG_SMALL, 'e', CG_DOT_ABOVE }, + { CG_CAPITAL, 'E', CG_OGONEK }, + { CG_SMALL, 'e', CG_OGONEK }, + { CG_CAPITAL, 'E', CG_CARON }, + { CG_SMALL, 'e', CG_CARON }, + { CG_CAPITAL, 'G', CG_CIRCUMFLEX }, + { CG_SMALL, 'g', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'G', CG_BREVE }, + { CG_SMALL, 'g', CG_BREVE }, + { CG_CAPITAL, 'G', CG_DOT_ABOVE }, + { CG_SMALL, 'g', CG_DOT_ABOVE }, + { CG_CAPITAL, 'G', CG_CEDILLA }, + { CG_SMALL, 'g', CG_CEDILLA }, + { CG_CAPITAL, 'H', CG_CIRCUMFLEX }, + { CG_SMALL, 'h', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'H', CG_STROKE }, + { CG_SMALL, 'h', CG_STROKE }, + { CG_CAPITAL, 'I', CG_TILDE }, + { CG_SMALL, 'i', CG_TILDE }, + { CG_CAPITAL, 'I', CG_MACRON }, + { CG_SMALL, 'i', CG_MACRON }, + { CG_CAPITAL, 'I', CG_BREVE }, + { CG_SMALL, 'i', CG_BREVE }, + { CG_CAPITAL, 'I', CG_OGONEK }, + { CG_SMALL, 'i', CG_OGONEK }, + { CG_CAPITAL, 'I', CG_DOT_ABOVE }, + { CG_NONE, 0, 0 }, // , CG_SMALL, 'DOTLESS I + { CG_NONE, 0, 0 }, // LATIN CAPITAL LIGATURE IJ + { CG_NONE, 0, 0 }, // LATIN SMALL LIGATURE IJ + { CG_CAPITAL, 'J', CG_CIRCUMFLEX }, + { CG_SMALL, 'j', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'K', CG_CEDILLA }, + { CG_SMALL, 'k', CG_CEDILLA }, + { CG_NONE, 0, 0 }, // CG_SMALL, 'KRA + { CG_CAPITAL, 'L', CG_ACUTE }, + { CG_SMALL, 'l', CG_ACUTE }, + { CG_CAPITAL, 'L', CG_CEDILLA }, + { CG_SMALL, 'l', CG_CEDILLA }, + { CG_CAPITAL, 'L', CG_COMMA_URI }, + { CG_SMALL, 'l', CG_COMMA_UR }, + { CG_CAPITAL, 'L', CG_MIDDLE_DOT }, + { CG_SMALL, 'l', CG_MIDDLE_DOT }, + { CG_CAPITAL, 'L', CG_STROKE }, + { CG_SMALL, 'l', CG_STROKE }, + { CG_CAPITAL, 'N', CG_ACUTE }, + { CG_SMALL, 'n', CG_ACUTE }, + { CG_CAPITAL, 'N', CG_CEDILLA }, + { CG_SMALL, 'n', CG_CEDILLA }, + { CG_CAPITAL, 'N', CG_CARON }, + { CG_SMALL, 'n', CG_CARON }, + { CG_NONE, 0, 0 }, // CG_SMALL, 'N PRECEDED BY APOSTROPHE + { CG_NONE, 0, 0 }, //CG_CAPITAL, 'ENG + { CG_NONE, 0, 0 }, //CG_SMALL, 'ENG + { CG_CAPITAL, 'O', CG_MACRON }, + { CG_SMALL, 'o', CG_MACRON }, + { CG_CAPITAL, 'O', CG_BREVE }, + { CG_SMALL, 'o', CG_BREVE }, + { CG_CAPITAL, 'O', CG_DOUBLE_ACUTE }, + { CG_SMALL, 'o', CG_DOUBLE_ACUTE }, + { CG_NONE, 0, 0 }, // LATIN CAPITAL LIGATURE OE + { CG_NONE, 0, 0 }, // LATIN SMALL LIGATURE OE + { CG_CAPITAL, 'R', CG_ACUTE }, + { CG_SMALL, 'r', CG_ACUTE }, + { CG_CAPITAL, 'R', CG_CEDILLA }, + { CG_SMALL, 'r', CG_CEDILLA }, + { CG_CAPITAL, 'R', CG_CARON }, + { CG_SMALL, 'r', CG_CARON }, + { CG_CAPITAL, 'S', CG_ACUTE }, + { CG_SMALL, 's', CG_ACUTE }, + { CG_CAPITAL, 'S', CG_CIRCUMFLEX }, + { CG_SMALL, 's', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'S', CG_CEDILLA }, + { CG_SMALL, 's', CG_CEDILLA }, + { CG_CAPITAL, 'S', CG_CARON }, + { CG_SMALL, 's', CG_CARON }, + { CG_CAPITAL, 'T', CG_CEDILLA }, + { CG_SMALL, 't', CG_CEDILLA }, + { CG_CAPITAL, 'T', CG_CARON }, + { CG_SMALL, 't', CG_COMMA_T }, + { CG_CAPITAL, 'T', CG_STROKE }, + { CG_SMALL, 't', CG_STROKE }, + { CG_CAPITAL, 'U', CG_TILDE }, + { CG_SMALL, 'u', CG_TILDE }, + { CG_CAPITAL, 'U', CG_MACRON }, + { CG_SMALL, 'u', CG_MACRON }, + { CG_CAPITAL, 'U', CG_BREVE }, + { CG_SMALL, 'u', CG_BREVE }, + { CG_CAPITAL, 'U', CG_RING_ABOVE }, + { CG_SMALL, 'u', CG_RING_ABOVE }, + { CG_CAPITAL, 'U', CG_DOUBLE_ACUTE }, + { CG_SMALL, 'u', CG_DOUBLE_ACUTE }, + { CG_CAPITAL, 'U', CG_OGONEK }, + { CG_SMALL, 'u', CG_OGONEK }, + { CG_CAPITAL, 'W', CG_CIRCUMFLEX }, + { CG_SMALL, 'w', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'Y', CG_CIRCUMFLEX }, + { CG_SMALL, 'y', CG_CIRCUMFLEX }, + { CG_CAPITAL, 'Y', CG_DIAERESIS }, + { CG_CAPITAL, 'Z', CG_ACUTE }, + { CG_SMALL, 'z', CG_ACUTE }, + { CG_CAPITAL, 'Z', CG_DOT_ABOVE }, + { CG_SMALL, 'z', CG_DOT_ABOVE }, + { CG_CAPITAL, 'Z', CG_CARON }, + { CG_SMALL, 'z', CG_CARON }, + { CG_NONE, 0, 0 } // CG_SMALL, 'LONG S +}; + +bool Compose(Font font, int chr, ComposedGlyph& cg) +{ + if(chr < 256 || chr > 256 + 128) + return false; + CGInfo f = gc_info[chr - 256]; + if(f.type == CG_NONE) + return false; + GlyphInfo gi = GetGlyphInfo(font, f.ascii); + if(gi.IsMissing()) + return false; + int cw = gi.width; + CommonFontInfo fi = GetFontInfo(font); + gi = GetGlyphInfo(font, f.mark); + if(gi.IsMissing()) + return false; + int mw = gi.width; + cg.mark_font = font; + cg.mark_pos.x = cg.mark_pos.y = 0; + cg.basic_char = f.ascii; + cg.mark_char = f.mark; + if(cg.mark_char == CG_COMMA_UR && fi.fixedpitch) + cg.mark_char = CG_CARON; + if(cg.mark_char == CG_COMMA_T) { + cg.mark_pos.y -= 3 * font.GetHeight() / 4; + cg.mark_pos.x += 4 * cw / 10; + if(font.IsItalic()) + cg.mark_pos.x += mw / 2; + } + else + if(cg.mark_char == CG_COMMA_UR) { + cg.mark_pos.y -= 2 * font.GetHeight() / 3; + cg.mark_pos.x += cw - mw / 4; + cg.mark_char = ','; + if(font.IsItalic()) + cg.mark_pos.x += mw / 3; + } + else + if(cg.mark_char == CG_COMMA_URI) { + cg.mark_pos.y -= 2 * font.GetHeight() / 3; + cg.mark_pos.x += cw - mw / 2; + cg.mark_char = ','; + if(font.IsItalic()) + cg.mark_pos.x += mw / 3; + } + else + if(cg.mark_char != CG_STROKE) { + if(cg.mark_char != CG_OGONEK && cg.mark_char != CG_CEDILLA && f.type == CG_CAPITAL) { + cg.mark_font = font(9 * font.GetHeight() / 10); + mw = GetGlyphInfo(cg.mark_font, f.mark).width; + cg.mark_pos.y -= cg.mark_char == CG_RING_ABOVE ? font.GetHeight() / 19 + : font.GetHeight() / 10; + } + cg.mark_pos.x += (cw - mw) / 2; + if(font.IsItalic()) + cg.mark_pos.x += mw / 5; + } + return true; +} diff --git a/uppdev/FontInfo/FontInfo.cpp b/uppdev/FontInfo/FontInfo.cpp new file mode 100644 index 000000000..e3b68d1e6 --- /dev/null +++ b/uppdev/FontInfo/FontInfo.cpp @@ -0,0 +1,117 @@ +#include "FontInfo.h" + +struct CharEntry { + GlyphInfo info; + word chr; + Font font; +}; + +CharEntry fc_cache_global[4096]; + +CharEntry GetGlyphEntry(Font font, int chr) +{ + DrawLock __; + unsigned hash = CombineHash(font.GetHashValue(), chr) & 511; + CharEntry& e = fc_cache_global[hash]; + if(e.font != font || e.chr != chr) { + e.font = font; + e.chr = chr; + e.info = GetGlyphInfoSys(font, chr); + if(!e.info.IsNormal()) { + ComposedGlyph cg; + Font rfnt; + if(Compose(font, chr, cg)) { + e.info.lspc = -1; + e.info.rspc = cg.basic_char; + } + else + if(Replace(font, chr, rfnt)) + e.info.lspc = rfnt.GetFace(); + else + e.info.lspc = -2; + } + } + return e; +} + +thread__ CharEntry fc_cache[512]; + +GlyphInfo GetGlyphInfo(Font font, int chr) +{ + unsigned hash = CombineHash(font.GetHashValue(), chr) & 511; + CharEntry& e = fc_cache[hash]; + if(e.font != font || e.chr != chr) + e = GetGlyphEntry(font, chr); + return e.info; +} + +void GlyphMetrics(GlyphInfo& f, Font font, int chr) +{ + if(f.IsReplaced()) + f = GetGlyphInfo(font().Face(f.lspc), chr); + if(f.IsComposed()) { + f = GetGlyphInfo(font, f.rspc); + if(f.IsComposedLM()) + f.rspc += f.width / 2; + } +} + +GlyphInfo GetGlyphMetrics(Font font, int chr) +{ + GlyphInfo f = GetGlyphInfo(font, chr); + if(f.IsMissing()) + f = GetGlyphInfo(font, '?'); + GlyphMetrics(f, font, chr); + return f; +} + +struct FontEntry { + CommonFontInfo info; + Font font; +}; + +thread__ FontEntry fi_cache[64]; + +const CommonFontInfo& GetFontInfo(Font font) +{ + unsigned hash = font.GetHashValue() & 63; + FontEntry& e = fi_cache[hash]; + if(e.font != font) { + DrawLock __; + e.font = font; + e.info = GetFontInfoSys(font); + } + return e.info; +} + +void DoDrawText(Draw& w, int x, int y, int angle, const wchar *text, Font font, Color ink, + int n, const int *dx) +{ + for(int i = 0; i < n; i++) { + wchar chr = text[i]; + GlyphInfo gi = GetGlyphInfo(font, chr); + if(gi.IsNormal()) + w.DrawTextOp(x, y, angle, &chr, font, ink, 1, NULL); + else + if(gi.IsReplaced()) { + FontInfo fi = font.Info(); + Font fnt = font; + fnt.Face(gi.lspc); + FontInfo fi2 = fnt.Info(); + w.DrawTextOp(x, y + fi.GetAscent() - fi2.GetAscent(), angle, &chr, fnt, ink, 1, NULL); + GlyphMetrics(gi, font, chr); + } + else + if(gi.IsComposed()) { + ComposedGlyph cg; + Compose(font, chr, cg); + w.DrawTextOp(x, y, angle, &cg.basic_char, font, ink, 1, NULL); + w.DrawTextOp(x + cg.mark_pos.x, y + cg.mark_pos.y, angle, &cg.mark_char, cg.mark_font, ink, 1, NULL); + GlyphMetrics(gi, font, chr); + } + if(dx) + x += *dx++; + else + x += gi.width; + } +} diff --git a/uppdev/FontInfo/FontInfo.h b/uppdev/FontInfo/FontInfo.h index 9d6b6eadd..2b4517dfe 100644 --- a/uppdev/FontInfo/FontInfo.h +++ b/uppdev/FontInfo/FontInfo.h @@ -37,7 +37,11 @@ struct GlyphInfo : Moveable { int16 lspc; int16 rspc; - bool IsMissing() const { return (word)width == (word)0x8000; } + bool IsNormal() const { return (word)width != 0x8000; } + bool IsComposed() const { return !IsNormal() && (lspc == -1 || lspc == -11); } + bool IsComposedLM() const { return !IsNormal() && lspc == -11; } + bool IsReplaced() const { return !IsNormal() && lspc >= 0; } + bool IsMissing() const { return !IsNormal() && lspc == -2; } }; GlyphInfo GetGlyphInfoSys(Font font, int chr); @@ -49,4 +53,23 @@ struct FaceInfo : Moveable { Vector GetAllFacesSys(); +GlyphInfo GetGlyphInfo(Font font, int chr); +void GlyphMetrics(GlyphInfo& f, Font font, int chr); +GlyphInfo GetGlyphMetrics(Font font, int chr); + +const CommonFontInfo& GetFontInfo(Font font); + +struct ComposedGlyph { + wchar basic_char; + Point mark_pos; + wchar mark_char; + Font mark_font; +}; + +bool Compose(Font fnt, int chr, ComposedGlyph& cs); +bool Replace(Font fnt, int chr, Font& rfnt); + +void DoDrawText(Draw& w, int x, int y, int angle, const wchar *text, Font font, Color ink, + int n, const int *dx); + #endif diff --git a/uppdev/FontInfo/FontInfo.upp b/uppdev/FontInfo/FontInfo.upp index b630a1109..0a9b700f2 100644 --- a/uppdev/FontInfo/FontInfo.upp +++ b/uppdev/FontInfo/FontInfo.upp @@ -4,10 +4,14 @@ uses CtrlLib; file - FontInfo.h, + FontInfo.h charset "UTF-8", Win32.cpp, X11.cpp, - main.cpp; + Compose.cpp, + FontReplace.cpp, + FontInfo.cpp, + main.cpp charset "UTF-8", + app.tpp; mainconfig "" = "GUI"; diff --git a/uppdev/FontInfo/FontReplace.cpp b/uppdev/FontInfo/FontReplace.cpp new file mode 100644 index 000000000..cd950ff6f --- /dev/null +++ b/uppdev/FontInfo/FontReplace.cpp @@ -0,0 +1,44 @@ +#include "FontInfo.h" + +static const char *sFontReplacements[] = { + "Symbol", + "Arial Unicode MS", + "Arial", + "MS UI Gothic", + "MS Mincho", + "Arial", + "Gulim", + "SimSun", + "PMingLiU", +}; + +bool Replace(Font fnt, int chr, Font& rfnt) +{ + static Vector rface; + ONCELOCK { + for(int i = 0; i < __countof(sFontReplacements); i++) { + int q = Font::FindFaceNameIndex(sFontReplacements[i]); + if(q > 0) + rface.Add(q); + } + DDUMP(rface.GetCount()); + } + static Font last; + static Font lastR; + if(last == fnt && GetGlyphInfo(lastR, chr).IsNormal()) { + rfnt = lastR; + return true; + } + Font f = fnt; + for(int i = 0; i < rface.GetCount(); i++) { + f.Face(rface[i]); + DDUMP(f.GetFaceName()); + if(GetGlyphInfo(f, chr).IsNormal()) { + LOG("-----------"); + last = fnt; + rfnt = lastR = f; + return true; + } + } + return false; +} diff --git a/uppdev/FontInfo/Win32.cpp b/uppdev/FontInfo/Win32.cpp index bf22778c1..890480e45 100644 --- a/uppdev/FontInfo/Win32.cpp +++ b/uppdev/FontInfo/Win32.cpp @@ -2,31 +2,46 @@ #ifdef PLATFORM_WIN32 -HFONT CreateWin32Font(Font font, int angle, int chrset) +#define FONTCACHE 37 + +HFONT GetWin32Font(Font fnt, int angle, int chrset) { -#ifdef PLATFORM_WINCE - LOGFONT lfnt; - Zero(lfnt); - lfnt.lfHeight = font.GetHeight() ? -abs(font.GetHeight()) : -12; - lfnt.lfWeight = font.IsBold() ? FW_BOLD : FW_NORMAL; - lfnt.lfItalic = font.IsItalic(); - lfnt.lfUnderline = font.IsUnderline(); - lfnt.lfStrikeOut = font.IsStrikeout(); - wcscpy(lfnt.lfFaceName, ToSystemCharset(font.GetFaceName())); - return CreateFontIndirect(&lfnt); -#else - return CreateFont( - font.GetHeight() ? -abs(font.GetHeight()) : -12, - font.GetWidth(), angle, angle, font.IsBold() ? FW_BOLD : FW_NORMAL, - font.IsItalic(), font.IsUnderline(), font.IsStrikeout(), - chrset, - font.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, - font.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY, - DEFAULT_PITCH|FF_DONTCARE, - font.GetFaceName() - ); -#endif + static Font font[FONTCACHE]; + static HFONT hfont[FONTCACHE]; + ONCELOCK { + for(int i = 0; i < FONTCACHE; i++) + font[i].Face(-1); + } + int q = fnt.GetHashValue() % FONTCACHE; + if(font[q] != fnt) { + font[q] = fnt; + if(hfont[q]) + DeleteObject(hfont[q]); + #ifdef PLATFORM_WINCE + LOGFONT lfnt; + Zero(lfnt); + lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12; + lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL; + lfnt.lfItalic = fnt.IsItalic(); + lfnt.lfUnderline = fnt.IsUnderline(); + lfnt.lfStrikeOut = fnt.IsStrikeout(); + wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName())); + hfont[q] = CreateFontIndirect(&lfnt); + #else + hfont[q] = CreateFont( + fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12, + fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL, + fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(), + chrset, + fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY, + DEFAULT_PITCH|FF_DONTCARE, + fnt.GetFaceName() + ); + #endif + } + return hfont[q]; } int sGetCW(HDC hdc, wchar *h, int n) @@ -57,18 +72,28 @@ static HDC Win32_IC() return hdc; } +#define GLYPHINFOCACHE 31 + GlyphInfo GetGlyphInfoSys(Font font, int chr) { - static Font last; - static GlyphInfo li[256]; - - static int lastpage = -1; + static Font fnt[GLYPHINFOCACHE]; + static int pg[GLYPHINFOCACHE]; + static GlyphInfo li[GLYPHINFOCACHE][256]; + + ONCELOCK { + for(int i = 0; i < GLYPHINFOCACHE; i++) + pg[i] = -1; + } int page = chr >> 8; - if(font != last || page != lastpage) { - last = font; - lastpage = page; - HFONT hfont = CreateWin32Font(font, 0, 0); + int q = CombineHash(font, page) % GLYPHINFOCACHE; + + if(fnt[q] != font || pg[q] != page) { + DDUMP(font); + DDUMP(q); + fnt[q] = font; + pg[q] = page; + HFONT hfont = GetWin32Font(font, 0, 0); if(!hfont) { GlyphInfo n; memset(&n, 0, sizeof(GlyphInfo)); @@ -77,7 +102,7 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr) HDC hdc = Win32_IC(); HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); int from = page << 8; - GlyphInfo *t = li; + GlyphInfo *t = li[q]; if(page >= 32) { wchar h[3]; h[0] = 'x'; @@ -137,20 +162,19 @@ GlyphInfo GetGlyphInfoSys(Font font, int chr) Win32_GetGlyphIndices(hdc, wch, 256, pos, 1); for(int i = 0; i < 256; i++) if(pos[i] == 0xffff) { - li[i].width = 0x8000; - li[i].lspc = li[i].rspc = 0; + li[q][i].width = (int16)0x8000; + li[q][i].lspc = li[q][i].rspc = 0; } - ::SelectObject(hdc, ohfont); #endif } - return li[chr & 255]; + return li[q][chr & 255]; } CommonFontInfo GetFontInfoSys(Font font) { CommonFontInfo fi; memset(&fi, 0, sizeof(fi)); - HFONT hfont = CreateWin32Font(font, 0, 0); + HFONT hfont = GetWin32Font(font, 0, 0); if(hfont) { HDC hdc = Win32_IC(); HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); diff --git a/uppdev/FontInfo/app.tpp/all.i b/uppdev/FontInfo/app.tpp/all.i new file mode 100644 index 000000000..43bec7333 --- /dev/null +++ b/uppdev/FontInfo/app.tpp/all.i @@ -0,0 +1,4 @@ +TOPIC("test$en-us") +#include "test$en-us.tppi" +END_TOPIC + diff --git a/uppdev/FontInfo/app.tpp/test$en-us.tpp b/uppdev/FontInfo/app.tpp/test$en-us.tpp new file mode 100644 index 000000000..d73fc3d8c --- /dev/null +++ b/uppdev/FontInfo/app.tpp/test$en-us.tpp @@ -0,0 +1,5 @@ +topic "ddfff+cčď"; +[ $$0,0#00000000000000000000000000000000:Default] +[{_}%EN-US +[s0; [!Corbel! ddfff`+cčď]&] +[s0; [!Algerian! ďOLIK]] \ No newline at end of file diff --git a/uppdev/FontInfo/app.tpp/test$en-us.tppi b/uppdev/FontInfo/app.tpp/test$en-us.tppi new file mode 100644 index 000000000..6b5146623 --- /dev/null +++ b/uppdev/FontInfo/app.tpp/test$en-us.tppi @@ -0,0 +1,4 @@ +TITLE("ddfff+cčď") +COMPRESSED +120,156,139,86,80,81,49,208,49,80,54,32,0,172,92,82,211,18,75,115,74,98,163,171,227,107,85,93,253,116,67,131,21,162,139,13,172,21,162,21,157,243,139,146,82,115,20,21,82,82,210,210,210,18,180,147,143,244,30,233,143,85,139,133,202,58,230,164,167,22,101,38,230,41,42,28,233,247,247,241,244,142,141,5,0,149,201,33,124, + diff --git a/uppdev/FontInfo/main.cpp b/uppdev/FontInfo/main.cpp index 02ff3d4df..016dafb30 100644 --- a/uppdev/FontInfo/main.cpp +++ b/uppdev/FontInfo/main.cpp @@ -2,59 +2,42 @@ using namespace Upp; -#if 0 - -struct CharEntry { - GlyphInfo info; - word chr; - Font font; -}; - -CharEntry fc_cache_global[4096]; - -CharEntry GetGlyphEntry(Font font, int chr) -{ - DrawLock __; - unsigned hash = CombineHash(font.GetHashValue(), chr) & 511; - CharEntry& e = fc_cache_global[hash]; - if(e.font != font || e.chr != chr) { - e.font = font; - e.chr = chr; - e.info = GetGlyphInfoSys(font, chr); +struct CharDisplay : public Display { + virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const + { + w.DrawRect(r, paper); + w.DrawText(r.left, r.top, AsString(q), StdFont(), ink); + Font fnt; + fnt.FaceName("Bitstream Vera Sans Mono"); + fnt.Height(13); + WString txt((int)q, 1); + w.DrawText(r.left + 40, r.top, txt, Courier(20), ink); + GlyphInfo gi = GetGlyphMetrics(fnt, q); + w.DrawRect(r.left + 60, r.top, gi.width, r.GetHeight(), LtCyan()); + gi = GetGlyphInfo(fnt, q); + if(!gi.IsMissing()) { + if(gi.IsNormal()) + w.DrawText(r.left + 60, r.top, txt, fnt); + else + if(gi.IsReplaced()) + w.DrawText(r.left + 60, r.top, txt, fnt().Face(gi.lspc), Magenta()); + else + if(gi.IsComposed()) { + ComposedGlyph g; + if(Compose(fnt, q, g)) { + w.DrawText(r.left + 60, r.top, WString(g.basic_char, 1), fnt, LtBlue()); + w.DrawText(r.left + 60 + g.mark_pos.x, r.top + g.mark_pos.y, + WString(g.mark_char, 1), g.mark_font, LtRed()); + } + } + } + else + w.DrawText(r.left + 60, r.top, txt, fnt, ink); + w.DrawRect(r.left, r.bottom - 1, r.Width(), 1, Black()); } - return e; -} -thread__ CharEntry fc_cache[512]; - -const GlyphInfo& GetGlyphInfo(Font font, int chr) -{ - unsigned hash = CombineHash(font.GetHashValue(), chr) & 511; - CharEntry& e = fc_cache[hash]; - if(e.font != font || e.chr != chr) - e = GetGlyphEntry(font, chr); - return e.info; -} - -struct FontEntry { - CommonFontInfo info; - Font font; }; -thread__ FontEntry fi_cache[64]; - -const CommonFontInfo& GetFontInfo(Font font) -{ - unsigned hash = font.GetHashValue() & 63; - FontEntry& e = fi_cache[hash]; - if(e.font != font) { - DrawLock __; - e.font = font; - e.info = GetFontInfoSys(font); - } - return e.info; -} - Size GetTextSizeNew(const wchar *text, Font font, int n) { int cx = 0; @@ -65,10 +48,38 @@ Size GetTextSizeNew(const wchar *text, Font font, int n) } return Size(cx, GetFontInfo(font).height); } -#endif + +struct App : TopWindow { + virtual void Paint(Draw& w) { + WString h = "Hello ěščřžýáíéúů "; + for(int i = 0; i < 10; i++) + h.Cat(20000 + i); + w.DrawRect(GetSize(), White()); + Font fnt; + fnt.FaceName("Bitstream Vera Sans Mono"); + fnt.Height(13); + DoDrawText(w, 100, 100, 0, h, fnt, Black(), h.GetCount(), NULL); + } +}; GUI_APP_MAIN { + SetDefaultCharset(CHARSET_UTF8); + App app; + app.Open(); + GetGlyphInfo(Font().FaceName("Bitstream Vera Sans Mono").Height(20), 461); + ColumnList list; + list.SetDisplay(Single()); + list.ItemHeight(25).Columns(12); + for(int i = 32; i < 65536; i++) + list.Add(i); + TopWindow win; +// list.SetCursor(461); + win.Add(list.SizePos()); + win.Run(); + + return; + FontInfo fi = Arial(100).Bold().Info(); DUMP(fi.GetAscent()); DUMP(fi.GetDescent());