diff --git a/uppdev/AccessKey/AccessKey.upp b/uppdev/AccessKey/AccessKey.upp index c79da13f7..35e8cccee 100644 --- a/uppdev/AccessKey/AccessKey.upp +++ b/uppdev/AccessKey/AccessKey.upp @@ -1,6 +1,9 @@ uses CtrlLib; +include + gdfgsdfg; + file AccessKey.h, test.key, diff --git a/uppdev/FontInfo/FontInfo.h b/uppdev/FontInfo/FontInfo.h new file mode 100644 index 000000000..ffabaa343 --- /dev/null +++ b/uppdev/FontInfo/FontInfo.h @@ -0,0 +1,36 @@ +#ifndef _FontInfo_FontInfo_h_ +#define _FontInfo_FontInfo_h_ + +#include + +using namespace Upp; + +struct CommonFontInfo { + int ascent; + int descent; + int external; + int internal; + int height; + int lineheight; + int overhang; + int avewidth; + int maxwidth; + int firstchar; + int charcount; + int default_char; + int spacebefore; + int spaceafter; + bool fixedpitch; + bool scaleable; +}; + +struct GlyphInfo { + int16 width; + int16 lspc; + int16 rspc; +}; + +GlyphInfo GetGlyphInfoSys(Font font, int chr); +CommonFontInfo GetFontInfoSys(Font font); + +#endif diff --git a/uppdev/FontInfo/FontInfo.upp b/uppdev/FontInfo/FontInfo.upp new file mode 100644 index 000000000..95824d2eb --- /dev/null +++ b/uppdev/FontInfo/FontInfo.upp @@ -0,0 +1,13 @@ +optimize_speed; + +uses + CtrlLib; + +file + FontInfo.h, + Win32.cpp, + main.cpp; + +mainconfig + "" = "GUI"; + diff --git a/uppdev/FontInfo/Win32.cpp b/uppdev/FontInfo/Win32.cpp new file mode 100644 index 000000000..6a24afd1b --- /dev/null +++ b/uppdev/FontInfo/Win32.cpp @@ -0,0 +1,146 @@ +#include "FontInfo.h" + +HFONT CreateWin32Font(Font font, 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 +} + +int sGetCW(HDC hdc, wchar *h, int n) +{ + SIZE sz; + return GetTextExtentPoint32W(hdc, h, n, &sz) ? sz.cx : 0; +} + +GlyphInfo GetGlyphInfoSys(Font font, int chr) +{ + static Font last; + static GlyphInfo li[256]; + static int lastpage = -1; + + int page = chr >> 8; + if(page == lastpage) + return li[chr & 255]; + + HFONT hfont = CreateWin32Font(font, 0, 0); + if(!hfont) { + GlyphInfo n; + memset(&n, 0, sizeof(GlyphInfo)); + return n; + } + HDC hdc = ScreenHDC(); + HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); + int from = page << 8; + GlyphInfo *t = li; + if(page >= 32) { + wchar h[3]; + h[0] = 'x'; + h[1] = 'x'; + h[2] = 'x'; + int w0 = sGetCW(hdc, h, 2); + for(int i = 0; i < 256; i++) { + h[1] = from + i; + t[i].width = sGetCW(hdc, h, 3) - w0; + t[i].lspc = t[i].rspc = 0; + } + } + else { + bool abca = false, abcw = false; + Buffer abc(256); + abcw = ::GetCharABCWidths(hdc, from, from + 256 - 1, abc); +#ifndef PLATFORM_WINCE + if(!abcw) + abca = ::GetCharABCWidthsA(hdc, from, from + 256 - 1, abc); +#endif + if(abcw) + { + for(ABC *s = abc, *lim = abc + 256; s < lim; s++, t++) + { + t->width = s->abcA + s->abcB + s->abcC; + t->lspc = s->abcA; + t->rspc = s->abcC; + } + } + else + { + Buffer wb(256); +#ifdef PLATFORM_WINCE + ::GetCharWidth32(hdc, from, from + 256 - 1, wb); +#else + ::GetCharWidthW(hdc, from, from + 256 - 1, wb); +#endif + for(int *s = wb, *lim = wb + 256; s < lim; s++, t++) + { + t->width = *s - GetFontInfoSys(font).overhang; + if(abca) + { + ABC aa = abc[(byte)ToAscii(from++)]; + t->lspc = aa.abcA; + t->rspc = aa.abcC; + } + else + t->lspc = t->rspc = 0; + } + } + } + ::SelectObject(hdc, ohfont); + return li[chr & 255]; +} + +CommonFontInfo GetFontInfoSys(Font font) +{ + CommonFontInfo fi; + memset(&fi, 0, sizeof(fi)); + HFONT hfont = CreateWin32Font(font, 0, 0); + if(hfont) { + HDC hdc = ScreenHDC(); + HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont); + TEXTMETRIC tm; + ::GetTextMetrics(hdc, &tm); + fi.ascent = tm.tmAscent; + fi.descent = tm.tmDescent; + fi.external = tm.tmExternalLeading; + fi.internal = tm.tmInternalLeading; + fi.height = fi.ascent + fi.descent; + fi.lineheight = fi.height + fi.external; + fi.overhang = tm.tmOverhang; + fi.avewidth = tm.tmAveCharWidth; + fi.maxwidth = tm.tmMaxCharWidth; + fi.firstchar = tm.tmFirstChar; + fi.charcount = tm.tmLastChar - tm.tmFirstChar + 1; + fi.default_char = tm.tmDefaultChar; + fi.fixedpitch = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0; + fi.scaleable = tm.tmPitchAndFamily & TMPF_TRUETYPE; + if(fi.scaleable) { + ABC abc; + GetCharABCWidths(hdc, 'o', 'o', &abc); + fi.spacebefore = abc.abcA; + fi.spaceafter = abc.abcC; + } + else + fi.spacebefore = fi.spaceafter = 0; + ::SelectObject(hdc, ohfont); + } + return fi; +} diff --git a/uppdev/FontInfo/init b/uppdev/FontInfo/init new file mode 100644 index 000000000..97f0f6817 --- /dev/null +++ b/uppdev/FontInfo/init @@ -0,0 +1,4 @@ +#ifndef _FontInfo_icpp_init_stub +#define _FontInfo_icpp_init_stub +#include "CtrlLib/init" +#endif diff --git a/uppdev/FontInfo/main.cpp b/uppdev/FontInfo/main.cpp new file mode 100644 index 000000000..57bf3aa0e --- /dev/null +++ b/uppdev/FontInfo/main.cpp @@ -0,0 +1,90 @@ +#include "FontInfo.h" + +using namespace Upp; + +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); + } + 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; + const wchar *wtext = (const wchar *)text; + while(n > 0) { + cx += GetGlyphInfo(font, *wtext++).width; + n--; + } + return Size(cx, GetFontInfo(font).height); +} + +GUI_APP_MAIN +{ + WString x = "Just a little test!"; + RDUMP(GetTextSize(x, Arial(20), x.GetCount())); + RDUMP(GetTextSizeNew(x, Arial(20), x.GetCount())); + RDUMP(sizeof(GlyphInfo)); + RDUMP(sizeof(CharEntry)); + RDUMP(sizeof(CommonFontInfo)); + #ifndef _DEBUG + int cx = 0; + { + RTIMING("Old"); + for(int i = 0; i < 1000000; i++) { + cx += GetTextSize(x, Arial(20), x.GetCount()).cx; + } + } + { + RTIMING("New"); + for(int i = 0; i < 1000000; i++) { + cx += GetTextSizeNew(x, Arial(20), x.GetCount()).cx; + } + } + #endif +}