From fc74aa11aff9000c65a4f338288a19b97a5ffe7b Mon Sep 17 00:00:00 2001 From: cxl Date: Tue, 20 Sep 2011 13:21:47 +0000 Subject: [PATCH] CtrlCore: ReSkin (former SyncCh) now public, refactored SetStdFont handling git-svn-id: svn://ultimatepp.org/upp/trunk@3894 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CtrlCore/Ctrl.cpp | 38 +- uppsrc/CtrlCore/CtrlCore.h | 5 +- uppsrc/CtrlCore/Win32Proc.cpp | 2 +- uppsrc/CtrlCore/Win32Wnd.cpp | 2 +- uppsrc/CtrlCore/X11App.cpp | 2 +- uppsrc/Draw/Font.cpp | 807 +++++++++++++++++----------------- 6 files changed, 434 insertions(+), 422 deletions(-) diff --git a/uppsrc/CtrlCore/Ctrl.cpp b/uppsrc/CtrlCore/Ctrl.cpp index 25a821ef0..62b80d549 100644 --- a/uppsrc/CtrlCore/Ctrl.cpp +++ b/uppsrc/CtrlCore/Ctrl.cpp @@ -548,7 +548,6 @@ bool Ctrl::IsOcxChild() Ctrl::Ctrl() { GuiLock __; - SyncCh(); LLOG("Ctrl::Ctrl"); GuiPlatformConstruct(); destroying = false; @@ -710,7 +709,7 @@ Size Ctrl::Csize; void InitRichTextZoom() { SetRichTextStdScreenZoom(Ctrl::HorzLayoutZoom(96), 600); - ChInvalidate(); + Ctrl::ReSkin(); } void Ctrl::Csizeinit() @@ -732,14 +731,14 @@ void Ctrl::SetZoomSize(Size sz, Size bsz) GuiLock __; Csize = sz; Dsize = bsz; - ChInvalidate(); + ReSkin(); } void Ctrl::NoLayoutZoom() { GuiLock __; Csize = Dsize = Size(1, 1); - ChInvalidate(); + ReSkin(); } void Ctrl::GetZoomRatio(Size& m, Size& d) @@ -880,6 +879,12 @@ void Modality::End() active = NULL; } +extern void (*whenSetStdFont)(); + +INITBLOCK { + whenSetStdFont = &Ctrl::ReSkin; +} + void (*s_chdefault)(); void (*Ctrl::skin)(); @@ -895,17 +900,16 @@ void Ctrl::SetSkin(void (*_skin)()) { GuiLock __; skin = _skin; - ChSync(); - Vector ctrl = GetTopCtrls(); - for(int i = 0; i < ctrl.GetCount(); i++) { - ctrl[i]->RefreshLayoutDeep(); - ctrl[i]->RefreshFrame(); - } + ReSkin(); } -void Ctrl::ChSync() +void Ctrl::ReSkin() { GuiLock __; + static int lock; + if(lock) + return; + lock++; if(s_chdefault) (*s_chdefault)(); if(skin) @@ -913,12 +917,12 @@ void Ctrl::ChSync() Csize.cx = Dsize.cx = 0; Csizeinit(); ChFinish(); -} - -void Ctrl::SyncCh() -{ - if(ChIsInvalidated()) - ChSync(); + Vector ctrl = GetTopCtrls(); + for(int i = 0; i < ctrl.GetCount(); i++) { + ctrl[i]->RefreshLayoutDeep(); + ctrl[i]->RefreshFrame(); + } + lock--; } void Ctrl::Xmlize(XmlIO xml) diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index 5742f19bd..0fd61389d 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -497,9 +497,6 @@ private: void RemoveChild0(Ctrl *q); - static void SyncCh(); - static void ChSync(); - static int FindMoveCtrl(const VectorMap& m, Ctrl *x); static MoveCtrl *FindMoveCtrlPtr(VectorMap& m, Ctrl *x); @@ -1221,6 +1218,8 @@ public: static void GlobalBackPaintHint(); static void GlobalBackBuffer(bool b = true); + static void ReSkin(); + String Name() const; #ifdef _DEBUG diff --git a/uppsrc/CtrlCore/Win32Proc.cpp b/uppsrc/CtrlCore/Win32Proc.cpp index d93b3119f..861761173 100644 --- a/uppsrc/CtrlCore/Win32Proc.cpp +++ b/uppsrc/CtrlCore/Win32Proc.cpp @@ -468,7 +468,7 @@ LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { #endif case WM_SETTINGCHANGE: case 0x031A: // WM_THEMECHANGED - ChSync(); + ReSkin(); RefreshLayoutDeep(); RefreshFrame(); break; diff --git a/uppsrc/CtrlCore/Win32Wnd.cpp b/uppsrc/CtrlCore/Win32Wnd.cpp index a2b36c753..9e82855ff 100644 --- a/uppsrc/CtrlCore/Win32Wnd.cpp +++ b/uppsrc/CtrlCore/Win32Wnd.cpp @@ -304,7 +304,7 @@ void Ctrl::InitWin32(HINSTANCE hInstance) ILOG("Windows"); Windows(); //?? TRC: what's the use of this? - ChSync(); + ReSkin(); OleInitialize(NULL); diff --git a/uppsrc/CtrlCore/X11App.cpp b/uppsrc/CtrlCore/X11App.cpp index 247241cb3..8110b3e1f 100644 --- a/uppsrc/CtrlCore/X11App.cpp +++ b/uppsrc/CtrlCore/X11App.cpp @@ -409,7 +409,7 @@ void Ctrl::InitX11(const char *display) SetStdFont(Arial(12)); - ChSync(); + ReSkin(); GUI_GlobalStyle_Write(GUISTYLE_XP); GUI_DragFullWindow_Write(1); diff --git a/uppsrc/Draw/Font.cpp b/uppsrc/Draw/Font.cpp index 5ad34bb4b..bfed6cf6a 100644 --- a/uppsrc/Draw/Font.cpp +++ b/uppsrc/Draw/Font.cpp @@ -1,399 +1,408 @@ -#include "Draw.h" - -#define LLOG(x) - -NAMESPACE_UPP - -CommonFontInfo GetFontInfoSys(Font font); -GlyphInfo GetGlyphInfoSys(Font font, int chr); -void GetStdFontSys(String& name, int& height); -Vector GetAllFacesSys(); - -bool Replace(Font fnt, int chr, Font& rfnt); - -void Std(Font& font) -{ - if(IsNull(font)) - font = StdFont(); - if(font.GetFace() == 0) - font.Face(GetStdFont().GetFace()); - if(font.GetHeight() == 0) - font.Height(GetStdFont().GetHeight()); -} - -Size Font::StdFontSize; -Font Font::AStdFont; - -INITBLOCK { - RichValue::Register(); -} - -const Vector& Font::List() -{ - static Vector *q; - ONCELOCK { - static Vector x; - x = GetAllFacesSys(); - q = &x; - } - return *q; -} - -void sInitFonts() -{ - Font::List(); - GetStdFont(); -} - -INITBLOCK { - sInitFonts(); -} - -int Font::GetFaceCount() -{ - return List().GetCount(); -} - -String Font::GetFaceName(int index) -{ - if(index == 0) - return "STDFONT"; - const Vector& l = List(); - if(index >= 0 && index < l.GetCount()) - return l[index].name; - return Null; -} - -dword Font::GetFaceInfo(int index) -{ - const Vector& l = List(); - if(index >= 0 && index < l.GetCount()) - return l[index].info; - return 0; -} - -int FontFilter(int c) -{ - return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0; -} - -int Font::FindFaceNameIndex(const String& name) { - if(name == "STDFONT") - return 0; - for(int i = 1; i < GetFaceCount(); i++) - if(GetFaceName(i) == name) - return i; - String n = Filter(name, FontFilter); - for(int i = 1; i < GetFaceCount(); i++) - if(Filter(GetFaceName(i), FontFilter) == n) - return i; - return 0; -} - -void Font::SyncStdFont() -{ - DrawLock __; - StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy()); -} - -void Font::SetStdFont(Font font) -{ - DrawLock __; - InitStdFont(); - AStdFont = font; - SyncStdFont(); - ChInvalidate(); -} - -void Font::InitStdFont() -{ - ONCELOCK { - DrawLock __; - List(); - AStdFont = Arial(12); - String name; - int height = 0; - GetStdFontSys(name, height); -#ifdef PLATFORM_WIN32 -#ifdef flagWINGL - AStdFont = Font(FindFaceNameIndex("Tahoma"), 12); -#else - int q = FindFaceNameIndex(name); - if(q <= 0) - q = FindFaceNameIndex("Tahoma"); - if(q <= 0) - q = FindFaceNameIndex("Microsoft Sans Serif"); - if(q <= 0) - q = FindFaceNameIndex("MS Sans Serif"); - if(q > 0) - AStdFont = Font(q, max(height, 1)); -#endif - SyncStdFont(); -#endif - } -} - -Font Font::GetStdFont() -{ - InitStdFont(); - return AStdFont; -} - -Size Font::GetStdFontSize() -{ - InitStdFont(); - return StdFontSize; -} - -Font StdFont() -{ - return Font(0, -32000); -} - -int Font::GetHeight() const -{ - return v.height == -32000 ? GetStdFont().GetHeight() : v.height; -} - -String Font::GetFaceName() const { - if(IsNullInstance()) return String(); - if(GetFace() == 0) - return "STDFONT"; - return GetFaceName(GetFace()); -} - -dword Font::GetFaceInfo() const { - if(IsNullInstance()) return 0; - return GetFaceInfo(GetFace()); -} - -Font& Font::FaceName(const String& name) { - int n = FindFaceNameIndex(name); - Face(n < 0 ? 0xffff : n); - return *this; -} - -void Font::Serialize(Stream& s) { - int version = 1; - s / version; - if(version >= 1) { - enum { - OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED, - OLD_ROMAN, - OLD_ARIAL, - OLD_COURIER, - }; - int f = GetFace(); - if(f > COURIER) - f = -1; - s / f; - String name; - if(f == OLD_ROMAN) - f = ROMAN; - if(f == OLD_ARIAL) - f = ARIAL; - if(f == OLD_COURIER) - f = COURIER; - if(f < 0) { - name = GetFaceName(); - s % name; - } - if(s.IsLoading()) - if(f >= 0) - Face(f); - else - FaceName(name); - } - else { - String name = GetFaceName(); - s % name; - if(s.IsLoading()) { - FaceName(name); - if(IsNullInstance()) - Face(COURIER); - } - } - s % v.flags % v.height % v.width; -} - -template<> -String AsString(const Font& f) { - if(IsNull(f)) return ""; - String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight()); - if(f.IsBold()) - s += " Bold"; - if(f.IsItalic()) - s += " Italic"; - if(f.IsUnderline()) - s += " Underline"; - if(f.IsStrikeout()) - s += " Strikeout"; - return s + '>'; -} - -struct CharEntry { - int64 font; - GlyphInfo info; - word chr; -}; - -CharEntry fc_cache_global[4093]; - -bool IsNormal(Font font, int chr) -{ - DrawLock __; - CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093]; - if(e.font == font.AsInt64() || e.chr == chr) - return e.info.IsNormal(); - return GetGlyphInfoSys(font, chr).IsNormal(); -} - -CharEntry GetGlyphEntry(Font font, int chr, unsigned hash) -{ - DrawLock __; - CharEntry& e = fc_cache_global[hash % 4093]; - if(e.font != font.AsInt64() || e.chr != chr) { - e.font = font.AsInt64(); - 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(); - e.info.rspc = rfnt.GetHeight(); - } - else - e.info.lspc = -2; - } - } - return e; -} - -thread__ CharEntry fc_cache[512]; - -GlyphInfo GetGlyphInfo(Font font, int chr) -{ - Std(font); - unsigned hash = CombineHash(font.GetHashValue(), chr); - CharEntry& e = fc_cache[hash & 511]; - if(e.font != font.AsInt64() || e.chr != chr) - e = GetGlyphEntry(font, chr, hash); - return e.info; -} - -bool Font::IsNormal(int ch) const -{ - return GetGlyphInfo(*this, ch).IsNormal(); -} - -bool Font::IsComposed(int ch) const -{ - return GetGlyphInfo(*this, ch).IsComposed(); -} - -bool Font::IsReplaced(int ch) const -{ - return GetGlyphInfo(*this, ch).IsReplaced(); -} - -bool Font::IsMissing(int ch) const -{ - return GetGlyphInfo(*this, ch).IsMissing(); -} - -int Font::HasChar(int ch) const -{ - return !GetGlyphInfo(*this, ch).IsMissing(); -} - -void GlyphMetrics(GlyphInfo& f, Font font, int chr) -{ - if(f.IsReplaced()) - f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), 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; - int64 font; -}; - -thread__ FontEntry fi_cache[64]; - -const CommonFontInfo& GetFontInfo(Font font) -{ - Std(font); - unsigned hash = font.GetHashValue() & 63; - FontEntry& e = fi_cache[hash]; - if(e.font != font.AsInt64()) { - DrawLock __; - e.font = font.AsInt64(); - e.info = GetFontInfoSys(font); - } - return e.info; -} - -int Font::GetWidth(int c) const { - return GetGlyphMetrics(*this, c).width; -} - -int Font::GetLeftSpace(int c) const { - return GetGlyphMetrics(*this, c).lspc; -} - -int Font::GetRightSpace(int c) const { - return GetGlyphMetrics(*this, c).rspc; -} - -thread__ int64 lastFiFont = INT_MIN; -thread__ CommonFontInfo lastFontInfo; -thread__ int64 lastStdFont = INT_MIN; - - -const CommonFontInfo& Font::Fi() const -{ -#ifdef PLATFORM_OSX11 -// known leak on MacOSX here: getAllCarbonLazyValues2000 calls Core.h op new() -// should not call UPP op new() -// from GetFontInfo() ... XftFontOpenPattern() ... getAllCarbonLazyValues2000() -> new() - MemoryIgnoreLeaksBlock __; -#endif - - if(lastStdFont != AStdFont.AsInt64()) { - lastFiFont = INT_MIN; - lastStdFont = AStdFont.AsInt64(); - } - if(AsInt64() == lastFiFont) - return lastFontInfo; - lastFontInfo = GetFontInfo(*this); - lastFiFont = AsInt64(); - return lastFontInfo; -} - -FontInfo Font::Info() const -{ - FontInfo h; - h.font = *this; - return h; -} - -END_UPP_NAMESPACE +#include "Draw.h" + +#define LLOG(x) + +NAMESPACE_UPP + +CommonFontInfo GetFontInfoSys(Font font); +GlyphInfo GetGlyphInfoSys(Font font, int chr); +void GetStdFontSys(String& name, int& height); +Vector GetAllFacesSys(); + +bool Replace(Font fnt, int chr, Font& rfnt); + +void Std(Font& font) +{ + if(IsNull(font)) + font = StdFont(); + if(font.GetFace() == 0) + font.Face(GetStdFont().GetFace()); + if(font.GetHeight() == 0) + font.Height(GetStdFont().GetHeight()); +} + +Size Font::StdFontSize; +Font Font::AStdFont; + +INITBLOCK { + RichValue::Register(); +} + +const Vector& Font::List() +{ + static Vector *q; + ONCELOCK { + static Vector x; + x = GetAllFacesSys(); + q = &x; + } + return *q; +} + +void sInitFonts() +{ + Font::List(); + GetStdFont(); +} + +INITBLOCK { + sInitFonts(); +} + +int Font::GetFaceCount() +{ + return List().GetCount(); +} + +String Font::GetFaceName(int index) +{ + if(index == 0) + return "STDFONT"; + const Vector& l = List(); + if(index >= 0 && index < l.GetCount()) + return l[index].name; + return Null; +} + +dword Font::GetFaceInfo(int index) +{ + const Vector& l = List(); + if(index >= 0 && index < l.GetCount()) + return l[index].info; + return 0; +} + +int FontFilter(int c) +{ + return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0; +} + +int Font::FindFaceNameIndex(const String& name) { + if(name == "STDFONT") + return 0; + for(int i = 1; i < GetFaceCount(); i++) + if(GetFaceName(i) == name) + return i; + String n = Filter(name, FontFilter); + for(int i = 1; i < GetFaceCount(); i++) + if(Filter(GetFaceName(i), FontFilter) == n) + return i; + return 0; +} + +void Font::SyncStdFont() +{ + DrawLock __; + StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy()); + DDUMP(StdFontSize); + DDUMP(AStdFont.GetHeight()); +} + +void (*whenSetStdFont)(); + +void Font::SetStdFont(Font font) +{ + DrawLock __; + static int x = 0; + if(x) return; + x++; + InitStdFont(); + AStdFont = font; + SyncStdFont(); + if(whenSetStdFont) + (*whenSetStdFont)(); + x--; +} + +void Font::InitStdFont() +{ + ONCELOCK { + DrawLock __; + List(); + AStdFont = Arial(12); + String name; + int height = 0; + GetStdFontSys(name, height); +#ifdef PLATFORM_WIN32 +#ifdef flagWINGL + AStdFont = Font(FindFaceNameIndex("Tahoma"), 12); +#else + int q = FindFaceNameIndex(name); + if(q <= 0) + q = FindFaceNameIndex("Tahoma"); + if(q <= 0) + q = FindFaceNameIndex("Microsoft Sans Serif"); + if(q <= 0) + q = FindFaceNameIndex("MS Sans Serif"); + if(q > 0) + AStdFont = Font(q, max(height, 1)); +#endif + SyncStdFont(); +#endif + } +} + +Font Font::GetStdFont() +{ + InitStdFont(); + return AStdFont; +} + +Size Font::GetStdFontSize() +{ + InitStdFont(); + return StdFontSize; +} + +Font StdFont() +{ + return Font(0, -32000); +} + +int Font::GetHeight() const +{ + return v.height == -32000 ? GetStdFont().GetHeight() : v.height; +} + +String Font::GetFaceName() const { + if(IsNullInstance()) return String(); + if(GetFace() == 0) + return "STDFONT"; + return GetFaceName(GetFace()); +} + +dword Font::GetFaceInfo() const { + if(IsNullInstance()) return 0; + return GetFaceInfo(GetFace()); +} + +Font& Font::FaceName(const String& name) { + int n = FindFaceNameIndex(name); + Face(n < 0 ? 0xffff : n); + return *this; +} + +void Font::Serialize(Stream& s) { + int version = 1; + s / version; + if(version >= 1) { + enum { + OLD_STDFONT, OLD_SCREEN_SERIF, OLD_SCREEN_SANS, OLD_SCREEN_FIXED, + OLD_ROMAN, + OLD_ARIAL, + OLD_COURIER, + }; + int f = GetFace(); + if(f > COURIER) + f = -1; + s / f; + String name; + if(f == OLD_ROMAN) + f = ROMAN; + if(f == OLD_ARIAL) + f = ARIAL; + if(f == OLD_COURIER) + f = COURIER; + if(f < 0) { + name = GetFaceName(); + s % name; + } + if(s.IsLoading()) + if(f >= 0) + Face(f); + else + FaceName(name); + } + else { + String name = GetFaceName(); + s % name; + if(s.IsLoading()) { + FaceName(name); + if(IsNullInstance()) + Face(COURIER); + } + } + s % v.flags % v.height % v.width; +} + +template<> +String AsString(const Font& f) { + if(IsNull(f)) return ""; + String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight()); + if(f.IsBold()) + s += " Bold"; + if(f.IsItalic()) + s += " Italic"; + if(f.IsUnderline()) + s += " Underline"; + if(f.IsStrikeout()) + s += " Strikeout"; + return s + '>'; +} + +struct CharEntry { + int64 font; + GlyphInfo info; + word chr; +}; + +CharEntry fc_cache_global[4093]; + +bool IsNormal(Font font, int chr) +{ + DrawLock __; + CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093]; + if(e.font == font.AsInt64() || e.chr == chr) + return e.info.IsNormal(); + return GetGlyphInfoSys(font, chr).IsNormal(); +} + +CharEntry GetGlyphEntry(Font font, int chr, unsigned hash) +{ + DrawLock __; + CharEntry& e = fc_cache_global[hash % 4093]; + if(e.font != font.AsInt64() || e.chr != chr) { + e.font = font.AsInt64(); + 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(); + e.info.rspc = rfnt.GetHeight(); + } + else + e.info.lspc = -2; + } + } + return e; +} + +thread__ CharEntry fc_cache[512]; + +GlyphInfo GetGlyphInfo(Font font, int chr) +{ + Std(font); + unsigned hash = CombineHash(font.GetHashValue(), chr); + CharEntry& e = fc_cache[hash & 511]; + if(e.font != font.AsInt64() || e.chr != chr) + e = GetGlyphEntry(font, chr, hash); + return e.info; +} + +bool Font::IsNormal(int ch) const +{ + return GetGlyphInfo(*this, ch).IsNormal(); +} + +bool Font::IsComposed(int ch) const +{ + return GetGlyphInfo(*this, ch).IsComposed(); +} + +bool Font::IsReplaced(int ch) const +{ + return GetGlyphInfo(*this, ch).IsReplaced(); +} + +bool Font::IsMissing(int ch) const +{ + return GetGlyphInfo(*this, ch).IsMissing(); +} + +int Font::HasChar(int ch) const +{ + return !GetGlyphInfo(*this, ch).IsMissing(); +} + +void GlyphMetrics(GlyphInfo& f, Font font, int chr) +{ + if(f.IsReplaced()) + f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), 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; + int64 font; +}; + +thread__ FontEntry fi_cache[64]; + +const CommonFontInfo& GetFontInfo(Font font) +{ + Std(font); + unsigned hash = font.GetHashValue() & 63; + FontEntry& e = fi_cache[hash]; + if(e.font != font.AsInt64()) { + DrawLock __; + e.font = font.AsInt64(); + e.info = GetFontInfoSys(font); + } + return e.info; +} + +int Font::GetWidth(int c) const { + return GetGlyphMetrics(*this, c).width; +} + +int Font::GetLeftSpace(int c) const { + return GetGlyphMetrics(*this, c).lspc; +} + +int Font::GetRightSpace(int c) const { + return GetGlyphMetrics(*this, c).rspc; +} + +thread__ int64 lastFiFont = INT_MIN; +thread__ CommonFontInfo lastFontInfo; +thread__ int64 lastStdFont = INT_MIN; + + +const CommonFontInfo& Font::Fi() const +{ +#ifdef PLATFORM_OSX11 +// known leak on MacOSX here: getAllCarbonLazyValues2000 calls Core.h op new() +// should not call UPP op new() +// from GetFontInfo() ... XftFontOpenPattern() ... getAllCarbonLazyValues2000() -> new() + MemoryIgnoreLeaksBlock __; +#endif + + if(lastStdFont != AStdFont.AsInt64()) { + lastFiFont = INT_MIN; + lastStdFont = AStdFont.AsInt64(); + } + if(AsInt64() == lastFiFont) + return lastFontInfo; + lastFontInfo = GetFontInfo(*this); + lastFiFont = AsInt64(); + return lastFontInfo; +} + +FontInfo Font::Info() const +{ + FontInfo h; + h.font = *this; + return h; +} + +END_UPP_NAMESPACE