mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Developing Win32 font metrics
git-svn-id: svn://ultimatepp.org/upp/trunk@1355 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
186475dc3b
commit
e6240bf46b
6 changed files with 680 additions and 520 deletions
|
|
@ -1,53 +1,52 @@
|
|||
#ifndef _FontInfo_FontInfo_h_
|
||||
#define _FontInfo_FontInfo_h_
|
||||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct CommonFontInfo : Moveable<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;
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
int underline_thickness;
|
||||
int underline_position;
|
||||
String path;
|
||||
#endif
|
||||
};
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
|
||||
struct GlyphInfo : Moveable<GlyphInfo> {
|
||||
int16 width;
|
||||
int16 lspc;
|
||||
int16 rspc;
|
||||
|
||||
bool IsMissing() const { return (word)width == (word)0x8000; }
|
||||
};
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
|
||||
struct FaceInfo : Moveable<FaceInfo> {
|
||||
String name;
|
||||
bool scalable;
|
||||
bool fixed;
|
||||
};
|
||||
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
#endif
|
||||
#ifndef _FontInfo_FontInfo_h_
|
||||
#define _FontInfo_FontInfo_h_
|
||||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct CommonFontInfo : Moveable<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;
|
||||
|
||||
#ifdef PLATFORM_POSIX
|
||||
int underline_thickness;
|
||||
int underline_position;
|
||||
String path;
|
||||
#endif
|
||||
};
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
|
||||
struct GlyphInfo : Moveable<GlyphInfo> {
|
||||
int16 width;
|
||||
int16 lspc;
|
||||
int16 rspc;
|
||||
|
||||
bool IsMissing() const { return (word)width == (word)0x8000; }
|
||||
};
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
|
||||
struct FaceInfo : Moveable<FaceInfo> {
|
||||
String name;
|
||||
dword info;
|
||||
};
|
||||
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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> 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<int> 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> 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<int> 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<FaceInfo> *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<FaceInfo> GetAllFacesSys()
|
||||
{
|
||||
Vector<FaceInfo> 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
|
||||
|
|
|
|||
|
|
@ -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<FaceInfo> GetAllFacesSys()
|
||||
{
|
||||
static const char *basic_fonts[] = {
|
||||
"sans-serif",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
};
|
||||
|
||||
Vector<FaceInfo> 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<FaceInfo> GetAllFacesSys()
|
||||
{
|
||||
static const char *basic_fonts[] = {
|
||||
"sans-serif",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
"serif",
|
||||
"sans-serif",
|
||||
"monospace",
|
||||
};
|
||||
|
||||
Vector<FaceInfo> 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
|
||||
|
|
|
|||
|
|
@ -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<FaceInfo> 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<FaceInfo> 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
|
||||
}
|
||||
|
|
|
|||
21
uppdev/trn/trn.cpp
Normal file
21
uppdev/trn/trn.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <Core/Core.h>
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
9
uppdev/trn/trn.upp
Normal file
9
uppdev/trn/trn.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
Core;
|
||||
|
||||
file
|
||||
trn.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue