diff --git a/uppdev/FontInfo/FontInfo.h b/uppdev/FontInfo/FontInfo.h index 68ab72840..9d6b6eadd 100644 --- a/uppdev/FontInfo/FontInfo.h +++ b/uppdev/FontInfo/FontInfo.h @@ -1,53 +1,52 @@ -#ifndef _FontInfo_FontInfo_h_ -#define _FontInfo_FontInfo_h_ - -#include - -using namespace Upp; - -struct CommonFontInfo : Moveable { - 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; - -#ifdef PLATFORM_POSIX - int underline_thickness; - int underline_position; - String path; -#endif -}; - -CommonFontInfo GetFontInfoSys(Font font); - -struct GlyphInfo : Moveable { - int16 width; - int16 lspc; - int16 rspc; - - bool IsMissing() const { return (word)width == (word)0x8000; } -}; - -GlyphInfo GetGlyphInfoSys(Font font, int chr); - -struct FaceInfo : Moveable { - String name; - bool scalable; - bool fixed; -}; - -Vector GetAllFacesSys(); - -#endif +#ifndef _FontInfo_FontInfo_h_ +#define _FontInfo_FontInfo_h_ + +#include + +using namespace Upp; + +struct CommonFontInfo : Moveable { + 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; + +#ifdef PLATFORM_POSIX + int underline_thickness; + int underline_position; + String path; +#endif +}; + +CommonFontInfo GetFontInfoSys(Font font); + +struct GlyphInfo : Moveable { + int16 width; + int16 lspc; + int16 rspc; + + bool IsMissing() const { return (word)width == (word)0x8000; } +}; + +GlyphInfo GetGlyphInfoSys(Font font, int chr); + +struct FaceInfo : Moveable { + String name; + dword info; +}; + +Vector GetAllFacesSys(); + +#endif diff --git a/uppdev/FontInfo/Win32.cpp b/uppdev/FontInfo/Win32.cpp index 619765109..bf22778c1 100644 --- a/uppdev/FontInfo/Win32.cpp +++ b/uppdev/FontInfo/Win32.cpp @@ -1,150 +1,271 @@ -#include "FontInfo.h" - -#ifdef PLATFORM_WIN32 - -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; -} - -#endif +#include "FontInfo.h" + +#ifdef PLATFORM_WIN32 + +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; +} + +static void Win32_GetGlyphIndices(HDC hdc, LPCWSTR s, int n, LPWORD r, DWORD flag) +{ + typedef DWORD (WINAPI *GGIW)(HDC, LPCWSTR, int, LPWORD, DWORD); + static GGIW fn; + ONCELOCK + if(HMODULE hDLL = LoadLibrary("gdi32")) + fn = (GGIW) GetProcAddress(hDLL, "GetGlyphIndicesW"); + if(fn) + fn(hdc, s, n, r, flag); + else + memset(r, 0, n * sizeof(WORD)); +} + +static HDC Win32_IC() +{ + static HDC hdc; + ONCELOCK { + hdc = CreateIC("DISPLAY", NULL, NULL, NULL); + } + return hdc; +} + +GlyphInfo GetGlyphInfoSys(Font font, int chr) +{ + static Font last; + static GlyphInfo li[256]; + + static int lastpage = -1; + + int page = chr >> 8; + if(font != last || page != lastpage) { + last = font; + lastpage = page; + HFONT hfont = CreateWin32Font(font, 0, 0); + if(!hfont) { + GlyphInfo n; + memset(&n, 0, sizeof(GlyphInfo)); + return n; + } + HDC hdc = Win32_IC(); + 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; + } + } + } +#ifndef PLATFORM_WINCE + WORD pos[256]; + WCHAR wch[256]; + for(int i = 0; i < 256; i++) + wch[i] = from + i; + 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; + } + ::SelectObject(hdc, ohfont); +#endif + } + 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 = Win32_IC(); + 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; +} + +static Vector *sList; + +static int CALLBACK Win32_AddFace(const LOGFONT *logfont, const TEXTMETRIC *, dword type, LPARAM param) +{ +#ifdef PLATFORM_WINCE + const wchar *facename = (const wchar *)param; + if(facename && _wcsicmp(logfont->lfFaceName, facename)) + return 1; +#else + const char *facename = (const char *)param; + if(facename && stricmp(logfont->lfFaceName, facename)) + return 1; +#endif + + dword typ = 0; + if((logfont->lfPitchAndFamily & 3) == FIXED_PITCH) + typ |= Font::FIXEDPITCH; + if(type & TRUETYPE_FONTTYPE) + typ |= Font::SCALEABLE; + if(logfont->lfCharSet == SYMBOL_CHARSET) + typ |= Font::SYMBOLTYPE; + else + if(logfont->lfCharSet != 0) + typ |= Font::LOCAL; +#ifdef PLATFORM_WINCE + FontFaceInfo& f = sFontFace().Add(WString(logfont->lfFaceName).ToString()); + f.name = FromSystemCharset(logfont->lfFaceName); +#else + FaceInfo& f = sList->Add(); + f.name = FromSystemCharset(logfont->lfFaceName); + f.info = typ; +#endif + return facename ? 0 : 1; +} + +static int Win32_EnumFace(HDC hdc, const char *face) +{ +#ifdef PLATFORM_WINCE + return EnumFontFamilies(hdc, ToSystemCharset(face), Win32_AddFace, (LPARAM)~ToSystemCharset(face)); +#else + return EnumFontFamilies(hdc, face, Win32_AddFace, (LPARAM)face); +#endif +} + +static void Win32_ForceFace(HDC hdc, const char *face, const char *aface) +{ + if(!aface) + aface = "Arial"; + if(Win32_EnumFace(hdc, face) && Win32_EnumFace(hdc, aface)) + Panic("Missing font " + String(face)); +} + +Vector GetAllFacesSys() +{ + Vector list; + sList = &list; + +#ifdef PLATFORM_WINCE + HDC hdc = CreateDC(NULL, NULL, NULL, NULL); + Win32_ForceFace(hdc, "Tahoma", NULL); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Courier New", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); + Win32_ForceFace(hdc, "Tahoma", "Tahoma"); +#else + HDC hdc = CreateIC("DISPLAY", NULL, NULL, NULL); + Win32_ForceFace(hdc, "Arial", NULL); + Win32_ForceFace(hdc, "Times New Roman", "Arial"); + Win32_ForceFace(hdc, "Courier New", "Arial"); + Win32_ForceFace(hdc, "Times New Roman", "Arial"); + Win32_ForceFace(hdc, "Arial", "Arial"); + Win32_ForceFace(hdc, "Courier New", "Arial"); + Win32_ForceFace(hdc, "Symbol", "Arial"); + Win32_ForceFace(hdc, "WingDings", "Arial"); + Win32_ForceFace(hdc, "Tahoma", "Arial"); +#endif + Win32_EnumFace(hdc, NULL); + DeleteDC(hdc); + return list; +} + +#endif diff --git a/uppdev/FontInfo/X11.cpp b/uppdev/FontInfo/X11.cpp index dff763774..e2f7bdd8d 100644 --- a/uppdev/FontInfo/X11.cpp +++ b/uppdev/FontInfo/X11.cpp @@ -1,185 +1,188 @@ -#include "FontInfo.h" - -#define LTIMING(x) - -#ifdef PLATFORM_X11 - -static FT_Library sFTlib; - -bool sInitFt(void) -{ - if(sFTlib) - return true; - return FT_Init_FreeType(&sFTlib) == 0; -} - -FcPattern *CreateFcPattern(Font font, int angle) -{ - LTIMING("CreateXftFont"); - double sina, cosa; - int hg = abs(font.GetHeight()); - if(hg == 0) hg = 10; - String n = font.GetFaceName(); - const char *face = n; - FcPattern *p = FcPatternCreate(); - FcPatternAddString(p, FC_FAMILY, (FcChar8*)face); - FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0); - FcPatternAddInteger(p, FC_PIXEL_SIZE, hg); - FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100); - FcPatternAddBool(p, FC_MINSPACE, 1); - if(angle) { - FcMatrix mx; - Draw::SinCos(angle, sina, cosa); - mx.xx = cosa; - mx.xy = -sina; - mx.yx = sina; - mx.yy = cosa; - FcPatternAddMatrix(p, FC_MATRIX, &mx); - } - FcResult result; - FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result); - FcPatternDestroy(p); - return m; -} - -FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) { - FT_Face face = NULL; - - int id; - double dsize; - double aspect; - FcChar8 *filename; - - if(!sInitFt()) - return NULL; - - if(FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch) - return NULL; - - if(rpath) - *rpath = (const char *)filename; - - if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch) - dsize = 16; - - if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch) - aspect = 1.0; - - FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0); - FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0); - - if(FT_New_Face (sFTlib, (const char *)filename, 0, &face)) - return NULL; - - FT_Set_Char_Size(face, xsize, ysize, 0, 0); - return face; -} - -FT_Face FTFace(Font fnt, String *rpath = NULL) -{ - static FT_Face cached_face; - static Font cached_font; - if(cached_font != fnt) { - cached_font = fnt; - if(cached_face) - FT_Done_Face(cached_face); - FcPattern *p = CreateFcPattern(cached_font, 0); - cached_face = CreateFTFace(p, rpath); - FcPatternDestroy(p); - } - return cached_face; -} - -CommonFontInfo GetFontInfoSys(Font font) -{ - CommonFontInfo fi; - - FT_Face face = FTFace(font, &fi.path); - if(face) { - fi.ascent = face->size->metrics.ascender >> 6; - fi.descent = -(face->size->metrics.descender >> 6); - fi.height = fi.ascent + fi.descent; - fi.lineheight = face->size->metrics.height >> 6; - fi.external = 0; - fi.internal = 0; - fi.overhang = 0; - fi.maxwidth = face->size->metrics.max_advance >> 6; - fi.avewidth = fi.maxwidth; - fi.default_char = '?'; - fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH; - int hg = abs(font.GetHeight()); - if(hg == 0) hg = 10; - fi.underline_thickness = max(hg / 20, 1); - fi.underline_position = max(hg / 15, int(fi.descent > 0)); - } - return fi; -} - -#define FLOOR(x) ((x) & -64) -#define CEIL(x) (((x)+63) & -64) -#define TRUNC(x) ((x) >> 6) -#define ROUND(x) (((x)+32) & -64) - -GlyphInfo GetGlyphInfoSys(Font font, int chr) -{ - GlyphInfo gi; - FT_Face face = FTFace(font, NULL); - gi.lspc = gi.rspc = 0; - gi.width = 0x8000; - if(face) { - int glyph_index = FT_Get_Char_Index(face, chr); - if(glyph_index && - (FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 || - FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)) { - FT_Glyph_Metrics& m = face->glyph->metrics; - int left = FLOOR(m.horiBearingX); - int width = TRUNC(CEIL(m.horiBearingX + m.width) - left); - gi.width = TRUNC(ROUND(face->glyph->advance.x)); - gi.lspc = TRUNC(left); - gi.rspc = gi.width - width - gi.lspc; - } - } - return gi; -} - -Vector GetAllFacesSys() -{ - static const char *basic_fonts[] = { - "sans-serif", - "serif", - "sans-serif", - "monospace", - "serif", - "sans-serif", - "monospace", - }; - - Vector list; - for(int i = 0; i < __countof(basic_fonts); i++) { - FaceInfo& fi = list.Add(); - f.name = basic_fonts[i]; - f.scaleable = true; - f.fixed = i == 3 || i == 6; - f.compose = sCheckComposed(basic_fonts[i]); - } - FcPattern *p = FcPatternCreate(); - FcObjectSet *os = FcObjectSetBuild(XFT_FAMILY, XFT_SPACING, XFT_SCALABLE, (void *)0); - FcFontSet *fs = FcFontList(NULL, p, os); - FcPatternDestroy(p); - FcObjectSetDestroy(os); - for(int i = 0; i < fs->nfont; i++) { - FcChar8 *family = NULL; - if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) { - FaceInfo& fi = list.Add(); - fi.name = (const char *)family; - int iv; - fi.fixed = FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == XFT_MONO; - FcBool bv; - fi.scalable = FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv; - } - } - FcFontSetDestroy(fs); - return list; -} - -#endif +#include "FontInfo.h" + +#define LTIMING(x) + +#ifdef PLATFORM_X11 + +static FT_Library sFTlib; + +bool sInitFt(void) +{ + if(sFTlib) + return true; + return FT_Init_FreeType(&sFTlib) == 0; +} + +FcPattern *CreateFcPattern(Font font, int angle) +{ + LTIMING("CreateXftFont"); + double sina, cosa; + int hg = abs(font.GetHeight()); + if(hg == 0) hg = 10; + String n = font.GetFaceName(); + const char *face = n; + FcPattern *p = FcPatternCreate(); + FcPatternAddString(p, FC_FAMILY, (FcChar8*)face); + FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0); + FcPatternAddInteger(p, FC_PIXEL_SIZE, hg); + FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100); + FcPatternAddBool(p, FC_MINSPACE, 1); + if(angle) { + FcMatrix mx; + Draw::SinCos(angle, sina, cosa); + mx.xx = cosa; + mx.xy = -sina; + mx.yx = sina; + mx.yy = cosa; + FcPatternAddMatrix(p, FC_MATRIX, &mx); + } + FcResult result; + FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result); + FcPatternDestroy(p); + return m; +} + +FT_Face CreateFTFace(const FcPattern *pattern, String *rpath) { + FT_Face face = NULL; + + int id; + double dsize; + double aspect; + FcChar8 *filename; + + if(!sInitFt()) + return NULL; + + if(FcPatternGetString(pattern, FC_FILE, 0, &filename) != FcResultMatch) + return NULL; + + if(rpath) + *rpath = (const char *)filename; + + if(FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &dsize) != FcResultMatch) + dsize = 16; + + if (FcPatternGetDouble(pattern, FC_ASPECT, 0, &aspect) != FcResultMatch) + aspect = 1.0; + + FT_F26Dot6 ysize = (FT_F26Dot6) (dsize * 64.0); + FT_F26Dot6 xsize = (FT_F26Dot6) (dsize * aspect * 64.0); + + if(FT_New_Face (sFTlib, (const char *)filename, 0, &face)) + return NULL; + + FT_Set_Char_Size(face, xsize, ysize, 0, 0); + return face; +} + +FT_Face FTFace(Font fnt, String *rpath = NULL) +{ + static FT_Face cached_face; + static Font cached_font; + if(cached_font != fnt) { + cached_font = fnt; + if(cached_face) + FT_Done_Face(cached_face); + FcPattern *p = CreateFcPattern(cached_font, 0); + cached_face = CreateFTFace(p, rpath); + FcPatternDestroy(p); + } + return cached_face; +} + +CommonFontInfo GetFontInfoSys(Font font) +{ + CommonFontInfo fi; + + FT_Face face = FTFace(font, &fi.path); + if(face) { + fi.ascent = face->size->metrics.ascender >> 6; + fi.descent = -(face->size->metrics.descender >> 6); + fi.height = fi.ascent + fi.descent; + fi.lineheight = face->size->metrics.height >> 6; + fi.external = 0; + fi.internal = 0; + fi.overhang = 0; + fi.maxwidth = face->size->metrics.max_advance >> 6; + fi.avewidth = fi.maxwidth; + fi.default_char = '?'; + fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH; + int hg = abs(font.GetHeight()); + if(hg == 0) hg = 10; + fi.underline_thickness = max(hg / 20, 1); + fi.underline_position = max(hg / 15, int(fi.descent > 0)); + } + return fi; +} + +#define FLOOR(x) ((x) & -64) +#define CEIL(x) (((x)+63) & -64) +#define TRUNC(x) ((x) >> 6) +#define ROUND(x) (((x)+32) & -64) + +GlyphInfo GetGlyphInfoSys(Font font, int chr) +{ + GlyphInfo gi; + FT_Face face = FTFace(font, NULL); + gi.lspc = gi.rspc = 0; + gi.width = 0x8000; + if(face) { + int glyph_index = FT_Get_Char_Index(face, chr); + if(glyph_index && + (FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP) == 0 || + FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT) == 0)) { + FT_Glyph_Metrics& m = face->glyph->metrics; + int left = FLOOR(m.horiBearingX); + int width = TRUNC(CEIL(m.horiBearingX + m.width) - left); + gi.width = TRUNC(ROUND(face->glyph->advance.x)); + gi.lspc = TRUNC(left); + gi.rspc = gi.width - width - gi.lspc; + } + } + return gi; +} + +Vector GetAllFacesSys() +{ + static const char *basic_fonts[] = { + "sans-serif", + "serif", + "sans-serif", + "monospace", + "serif", + "sans-serif", + "monospace", + }; + + Vector list; + for(int i = 0; i < __countof(basic_fonts); i++) { + FaceInfo& fi = list.Add(); + f.name = basic_fonts[i]; + f.scaleable = true; + f.fixed = i == 3 || i == 6; + f.compose = sCheckComposed(basic_fonts[i]); + } + FcPattern *p = FcPatternCreate(); + FcObjectSet *os = FcObjectSetBuild(XFT_FAMILY, XFT_SPACING, XFT_SCALABLE, (void *)0); + FcFontSet *fs = FcFontList(NULL, p, os); + FcPatternDestroy(p); + FcObjectSetDestroy(os); + for(int i = 0; i < fs->nfont; i++) { + FcChar8 *family = NULL; + if(FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == 0 && family) { + FaceInfo& fi = list.Add(); + fi.name = (const char *)family; + fi.type = 0; + int iv; + if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == FC_MONO) + fi.type |= Font::FIXEDPITCH; + FcBool bv; + if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv) + fi.type |= Font::SCALEABLE; + } + } + FcFontSetDestroy(fs); + return list; +} + +#endif diff --git a/uppdev/FontInfo/main.cpp b/uppdev/FontInfo/main.cpp index 8da983e63..02ff3d4df 100644 --- a/uppdev/FontInfo/main.cpp +++ b/uppdev/FontInfo/main.cpp @@ -1,132 +1,139 @@ -#include "FontInfo.h" - -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); - } - 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); -} -#endif - -GUI_APP_MAIN -{ - { - for(int i = 0; i < 65536; i++) { - GlyphInfo g = GetGlyphInfoSys(Arial(100).Bold(), i); - if(g.IsMissing()) - LOG(i); - } - } - - - Vector fa = GetAllFacesSys(); - for(int i = 0; i < fa.GetCount(); i++) - LOG(fa[i].name << ": scalable: " << fa[i].scalable << ", fixed: " << fa[i].fixed); - CommonFontInfo f = GetFontInfoSys(Arial(100).Bold()); - DDUMP(f.ascent); - DDUMP(f.descent); - DDUMP(f.lineheight); - DDUMP(f.maxwidth); - DDUMP(f.path); - - FontInfo fi = Arial(100).Bold().Info(); - DDUMP(fi.GetAscent()); - DDUMP(fi.GetDescent()); - DDUMP(fi.GetMaxWidth()); - - for(int c = '0'; c < 'z'; c++) { - LOG("-------------------------"); - DDUMP((char)c); - GlyphInfo g = GetGlyphInfoSys(Arial(100).Bold(), c); - DDUMP(g.width); - DDUMP(fi[c]); - DDUMP(g.lspc); - DDUMP(fi.GetLeftSpace(c)); - DDUMP(g.rspc); - DDUMP(fi.GetRightSpace(c)); - } - - -#if 0 - 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 -#endif -} +#include "FontInfo.h" + +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); + } + 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); +} +#endif + +GUI_APP_MAIN +{ + FontInfo fi = Arial(100).Bold().Info(); + DUMP(fi.GetAscent()); + DUMP(fi.GetDescent()); + DUMP(fi.GetMaxWidth()); + + { + int from = 0; + for(int i = 0; i < 65536; i++) { + GlyphInfo g = GetGlyphInfoSys(Arial(100).Bold(), i); + if(g.IsMissing()) { +// if(!fi.HasChar(i)) { + if(from < i) + LOG(from << " - " << i - 1); + from = i + 1; + } + } + if(from < 65535) + LOG(from << " - " << 65535); + } + + Vector fa = GetAllFacesSys(); + for(int i = 0; i < fa.GetCount(); i++) + LOG(fa[i].name << ": scalable: " << (fa[i].info & Font::SCALEABLE) << ", fixed: " << (fa[i].info & Font::FIXEDPITCH)); + CommonFontInfo f = GetFontInfoSys(Arial(100).Bold()); + DUMP(f.ascent); + DUMP(f.descent); + DUMP(f.lineheight); + DUMP(f.maxwidth); +// DUMP(f.path); + + + for(int c = '0'; c < 'z'; c++) { + LOG("-------------------------"); + DUMP((char)c); + GlyphInfo g = GetGlyphInfoSys(Arial(100).Bold(), c); + DUMP(g.width); + DUMP(fi[c]); + DUMP(g.lspc); + DUMP(fi.GetLeftSpace(c)); + DUMP(g.rspc); + DUMP(fi.GetRightSpace(c)); + } + + +#if 0 + 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 +#endif +} diff --git a/uppdev/trn/trn.cpp b/uppdev/trn/trn.cpp new file mode 100644 index 000000000..2ab643d8c --- /dev/null +++ b/uppdev/trn/trn.cpp @@ -0,0 +1,21 @@ +#include + +using namespace Upp; + +int Trn(int x) +{ + if(x % 2) + return x + 1; + else + return x; +} + + +CONSOLE_APP_MAIN +{ + for(;;) { + Cout() << "Zadej cislo x: "; + int cislo = atoi(ReadStdIn()); + Cout() << "Trn(" << cislo << ") = " << Trn(cislo) << "\n"; + } +} diff --git a/uppdev/trn/trn.upp b/uppdev/trn/trn.upp new file mode 100644 index 000000000..43d2dcda5 --- /dev/null +++ b/uppdev/trn/trn.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + trn.cpp; + +mainconfig + "" = ""; +