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@1360 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
f37a27a8d4
commit
156ba63fc3
6 changed files with 44 additions and 808 deletions
|
|
@ -1,223 +1,2 @@
|
|||
#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;
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,170 +1,6 @@
|
|||
#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;
|
||||
}
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
void DoDrawText(Draw& w, int x, int y, int angle, const wchar *text, Font font, Color ink,
|
||||
int n, const int *dx)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,79 +1,30 @@
|
|||
#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
|
||||
#ifndef _FontInfo_FontInfo_h_
|
||||
#define _FontInfo_FontInfo_h_
|
||||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font);
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,46 +1,2 @@
|
|||
#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;
|
||||
}
|
||||
#include "FontInfo.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,294 +2,4 @@
|
|||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
#define FONTCACHE 37
|
||||
|
||||
HFONT GetWin32Font(Font fnt, int angle, int chrset)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#define GLYPHINFOCACHE 31
|
||||
|
||||
GlyphInfo GetGlyphInfoSys(Font font, int chr)
|
||||
{
|
||||
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;
|
||||
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));
|
||||
return n;
|
||||
}
|
||||
HDC hdc = Win32_IC();
|
||||
HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont);
|
||||
int from = page << 8;
|
||||
GlyphInfo *t = li[q];
|
||||
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[q][i].width = (int16)0x8000;
|
||||
li[q][i].lspc = li[q][i].rspc = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return li[q][chr & 255];
|
||||
}
|
||||
|
||||
CommonFontInfo GetFontInfoSys(Font font)
|
||||
{
|
||||
CommonFontInfo fi;
|
||||
memset(&fi, 0, sizeof(fi));
|
||||
HFONT hfont = GetWin32Font(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
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ GUI_APP_MAIN
|
|||
|
||||
DUMP(GUI_PopUpEffect());
|
||||
RichEditWithToolBar e;
|
||||
Vector<int> h;
|
||||
for(int i = 0; i < Font::GetFaceCount(); i++)
|
||||
h.Add(i);
|
||||
e.FontFaces(h);
|
||||
|
||||
DUMP(ScrollBarSize());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue