mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Developing new font metrics
git-svn-id: svn://ultimatepp.org/upp/trunk@1356 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
ba4d690c8d
commit
98df0b46db
10 changed files with 550 additions and 91 deletions
223
uppdev/FontInfo/Compose.cpp
Normal file
223
uppdev/FontInfo/Compose.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
117
uppdev/FontInfo/FontInfo.cpp
Normal file
117
uppdev/FontInfo/FontInfo.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,11 @@ struct GlyphInfo : Moveable<GlyphInfo> {
|
|||
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<FaceInfo> {
|
|||
|
||||
Vector<FaceInfo> 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
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
44
uppdev/FontInfo/FontReplace.cpp
Normal file
44
uppdev/FontInfo/FontReplace.cpp
Normal file
|
|
@ -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<int> 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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
4
uppdev/FontInfo/app.tpp/all.i
Normal file
4
uppdev/FontInfo/app.tpp/all.i
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
TOPIC("test$en-us")
|
||||
#include "test$en-us.tppi"
|
||||
END_TOPIC
|
||||
|
||||
5
uppdev/FontInfo/app.tpp/test$en-us.tpp
Normal file
5
uppdev/FontInfo/app.tpp/test$en-us.tpp
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
topic "ddfff+cčď";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[{_}%EN-US
|
||||
[s0; [!Corbel! ddfff`+cčď]&]
|
||||
[s0; [!Algerian! ďOLIK]]
|
||||
4
uppdev/FontInfo/app.tpp/test$en-us.tppi
Normal file
4
uppdev/FontInfo/app.tpp/test$en-us.tppi
Normal file
|
|
@ -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,
|
||||
|
||||
|
|
@ -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<CharDisplay>());
|
||||
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());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue