ultimatepp/uppdev/FontInfo/FontInfo.cpp
cxl 0385cf0c68 Developing new font metrics
git-svn-id: svn://ultimatepp.org/upp/trunk@1358 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-07-05 14:48:01 +00:00

170 lines
3.9 KiB
C++

#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;
}
}