mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-08 14:22:29 -06:00
170 lines
3.9 KiB
C++
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;
|
|
}
|
|
}
|