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@1358 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
3af6cadacb
commit
dad8006d13
7 changed files with 920 additions and 798 deletions
|
|
@ -1,223 +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;
|
||||
}
|
||||
#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.IsNormal())
|
||||
return false;
|
||||
int cw = gi.width;
|
||||
CommonFontInfo fi = GetFontInfo(font);
|
||||
gi = GetGlyphInfo(font, f.mark);
|
||||
if(!gi.IsNormal())
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,117 +1,170 @@
|
|||
#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;
|
||||
}
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
struct CharEntry {
|
||||
GlyphInfo info;
|
||||
word chr;
|
||||
Font font;
|
||||
};
|
||||
|
||||
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 || 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 || 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)
|
||||
{
|
||||
Std(font);
|
||||
unsigned hash = CombineHash(font.GetHashValue(), chr);
|
||||
CharEntry& e = fc_cache[hash & 511];
|
||||
if(e.font != font || e.chr != chr)
|
||||
e = GetGlyphEntry(font, chr, hash);
|
||||
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)
|
||||
{
|
||||
Std(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)
|
||||
{
|
||||
Std(font);
|
||||
double sina;
|
||||
double cosa;
|
||||
int d = 0;
|
||||
if(angle)
|
||||
Draw::SinCos(angle, sina, cosa); //TODO global sin tables!
|
||||
for(int i = 0; i < n; i++) {
|
||||
wchar chr = text[i];
|
||||
GlyphInfo gi = GetGlyphInfo(font, chr);
|
||||
if(gi.IsNormal())
|
||||
if(angle)
|
||||
w.DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &chr, font, ink, 1, NULL);
|
||||
else {
|
||||
int c = 1;
|
||||
int dd = 0;
|
||||
if(!dx)
|
||||
while(c < n) {
|
||||
GlyphInfo gi2 = GetGlyphInfo(font, text[i + c]);
|
||||
if(!gi2.IsNormal())
|
||||
break;
|
||||
c++;
|
||||
dd += gi.width;
|
||||
gi = gi2;
|
||||
}
|
||||
w.DrawTextOp(x + d, y, 0, text + i, font, ink, c, NULL);
|
||||
i += c - 1;
|
||||
d += dd;
|
||||
}
|
||||
else
|
||||
if(gi.IsReplaced()) {
|
||||
FontInfo fi = font.Info();
|
||||
Font fnt = font;
|
||||
fnt.Face(gi.lspc);
|
||||
FontInfo fi2 = fnt.Info();
|
||||
if(angle)
|
||||
w.DrawTextOp(int(x + cosa * d), int(y - sina * (fi.GetAscent() - fi2.GetAscent() + d)),
|
||||
angle, &chr, fnt, ink, 1, NULL);
|
||||
else
|
||||
w.DrawTextOp(x + d, y + fi.GetAscent() - fi2.GetAscent(), 0, &chr, fnt, ink, 1, NULL);
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
else
|
||||
if(gi.IsComposed()) {
|
||||
ComposedGlyph cg;
|
||||
Compose(font, chr, cg);
|
||||
if(angle) {
|
||||
w.DrawTextOp(int(x + cosa * d), int(y - sina * d), angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
w.DrawTextOp(int(x + cosa * (d + cg.mark_pos.x)), int(y - sina * (cg.mark_pos.y + d)), angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
else {
|
||||
w.DrawTextOp(x + d, y, angle, &cg.basic_char, font, ink, 1, NULL);
|
||||
w.DrawTextOp(x + cg.mark_pos.x + d, y + cg.mark_pos.y, angle, &cg.mark_char, cg.mark_font, ink, 1, NULL);
|
||||
}
|
||||
GlyphMetrics(gi, font, chr);
|
||||
}
|
||||
if(dx)
|
||||
d += *dx++;
|
||||
else
|
||||
d += gi.width;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +1,79 @@
|
|||
#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 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);
|
||||
|
||||
struct FaceInfo : Moveable<FaceInfo> {
|
||||
String name;
|
||||
dword info;
|
||||
};
|
||||
|
||||
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
|
||||
#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 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);
|
||||
|
||||
struct FaceInfo : Moveable<FaceInfo> {
|
||||
String name;
|
||||
dword info;
|
||||
};
|
||||
|
||||
Vector<FaceInfo> GetAllFacesSys();
|
||||
|
||||
void Std(Font& font);
|
||||
|
||||
bool IsNormal(Font font, int chr);
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ file
|
|||
Win32.cpp,
|
||||
X11.cpp,
|
||||
Compose.cpp,
|
||||
FontReplace.cpp,
|
||||
FontReplace.cpp charset "UTF-8",
|
||||
FontInfo.cpp,
|
||||
main.cpp charset "UTF-8",
|
||||
app.tpp;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,46 @@
|
|||
#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;
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
static const char *sFontReplacements[] = {
|
||||
"sans-serif",
|
||||
"Arial",
|
||||
"Arial Unicode MS",
|
||||
"Symbol",
|
||||
"文泉驛等寬正黑",
|
||||
"文泉驛正黑",
|
||||
"MS UI Gothic",
|
||||
"MS Mincho",
|
||||
"Arial",
|
||||
"AlArabiya"
|
||||
"FreeSerif",
|
||||
"Kochi Mincho",
|
||||
"Kochi Gothic",
|
||||
"Sazanami Mincho",
|
||||
"Sazanami Gothic",
|
||||
"Gulim",
|
||||
"SimSun",
|
||||
"PMingLiU",
|
||||
};
|
||||
|
||||
bool Replace(Font fnt, int chr, Font& rfnt)
|
||||
{
|
||||
// ASSERT(chr >= 0 && chr <
|
||||
LOG("Replace: " << fnt << ": " << chr);
|
||||
static Vector<int> rface;
|
||||
ONCELOCK {
|
||||
for(int i = 0; i < __countof(sFontReplacements) && rface.GetCount() < 20; i++) {
|
||||
int q = Font::FindFaceNameIndex(sFontReplacements[i]);
|
||||
if(q > 0)
|
||||
rface.Add(q);
|
||||
}
|
||||
}
|
||||
|
||||
Font f = fnt;
|
||||
for(int i = 0; i < rface.GetCount(); i++)
|
||||
if(IsNormal(f.Face(rface[i]), chr)) {
|
||||
rfnt = f;
|
||||
LOG("Replacement: " << rfnt);
|
||||
return true;
|
||||
}
|
||||
LOG("No replace");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,188 +1,222 @@
|
|||
#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
|
||||
#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;
|
||||
}
|
||||
|
||||
#define FONTCACHE 37
|
||||
|
||||
struct FtFaceEntry {
|
||||
Font font;
|
||||
FT_Face face;
|
||||
String path;
|
||||
};
|
||||
|
||||
FT_Face FTFace(Font fnt, String *rpath = NULL)
|
||||
{
|
||||
RTIMING("FTFace");
|
||||
DDUMP(fnt);
|
||||
static FtFaceEntry cache[FONTCACHE];
|
||||
ONCELOCK {
|
||||
for(int i = 0; i < FONTCACHE; i++)
|
||||
cache[i].font.Height(-30000);
|
||||
}
|
||||
FtFaceEntry be;
|
||||
be = cache[0];
|
||||
for(int i = 0; i < FONTCACHE; i++) {
|
||||
FtFaceEntry e = cache[i];
|
||||
if(i)
|
||||
cache[i] = be;
|
||||
if(e.font == fnt) {
|
||||
if(rpath)
|
||||
*rpath = e.path;
|
||||
if(i)
|
||||
cache[0] = e;
|
||||
return e.face;
|
||||
}
|
||||
be = e;
|
||||
}
|
||||
RTIMING("FTFace2");
|
||||
if(be.face) {
|
||||
LOG("Removing " << be.font << " - " << (void *)be.face);
|
||||
FT_Done_Face(be.face);
|
||||
}
|
||||
be.font = fnt;
|
||||
FcPattern *p = CreateFcPattern(fnt, 0);
|
||||
be.face = CreateFTFace(p, &be.path);
|
||||
FcPatternDestroy(p);
|
||||
cache[0] = be;
|
||||
if(rpath)
|
||||
*rpath = be.path;
|
||||
for(int i = 0; i < FONTCACHE; i++)
|
||||
LOG(i << ": " << cache[i].font);
|
||||
return be.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)
|
||||
{
|
||||
RTIMING("GetGlyphInfoSys");
|
||||
GlyphInfo gi;
|
||||
FT_Face face = FTFace(font, NULL);
|
||||
gi.lspc = gi.rspc = 0;
|
||||
gi.width = 0x8000;
|
||||
if(face) {
|
||||
RTIMING("GetGlyphInfoSys 2");
|
||||
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();
|
||||
fi.name = basic_fonts[i];
|
||||
fi.info = (i == 3 || i == 6) ? Font::SCALEABLE|Font::FIXEDPITCH : Font::SCALEABLE;
|
||||
}
|
||||
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.info = 0;
|
||||
int iv;
|
||||
if(FcPatternGetInteger(fs->fonts[i], FC_SPACING, 0, &iv) == 0 && iv == FC_MONO)
|
||||
fi.info |= Font::FIXEDPITCH;
|
||||
FcBool bv;
|
||||
if(FcPatternGetBool(fs->fonts[i], FC_SCALABLE, 0, &bv) == 0 && bv)
|
||||
fi.info |= Font::SCALEABLE;
|
||||
}
|
||||
}
|
||||
FcFontSetDestroy(fs);
|
||||
return list;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,150 +1,179 @@
|
|||
#include "FontInfo.h"
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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());
|
||||
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
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
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.Face(Font::ARIAL);
|
||||
fnt.Height(20);
|
||||
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());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
DoDrawText(w, 100, 300, 300, h, fnt, Black(), h.GetCount(), NULL);
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
SetDefaultCharset(CHARSET_UTF8);
|
||||
|
||||
|
||||
#if 0
|
||||
static dword t[] = { 0x9d15, 0x3092,0x4e26,0xe20,0xf780,0x994,0x636,0xfeb2,0xfebe,0x2126 };
|
||||
VectorMap<String, int> stat;
|
||||
for(int i = 0; i < __countof(t); i++) {
|
||||
int chr = t[i];
|
||||
LOG("-------- " << chr);
|
||||
for(int i = 0; i < Font::GetFaceCount(); i++) {
|
||||
Font fnt;
|
||||
fnt.Height(20);
|
||||
fnt.Face(i);
|
||||
if(GetGlyphInfoSys(fnt, chr).IsNormal()) {
|
||||
LOG(fnt.GetFaceName());
|
||||
stat.GetAdd(fnt.GetFaceName(), 0)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG("--------------------------");
|
||||
Vector<int> o = GetSortOrder(stat.GetValues());
|
||||
for(int i = 0; i < o.GetCount(); i++)
|
||||
LOG(stat.GetKey(o[i]) << ": " << stat[o[i]]);
|
||||
LOG("--------------------------");
|
||||
#endif
|
||||
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());
|
||||
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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue