Developing newdraw

git-svn-id: svn://ultimatepp.org/upp/trunk@1359 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-07-05 14:48:03 +00:00
parent dad8006d13
commit 379bc287f1
5 changed files with 1545 additions and 1405 deletions

File diff suppressed because it is too large Load diff

View file

@ -52,6 +52,7 @@ file
DrawX11.h,
DrawX11.cpp,
DrawOpX11.cpp,
DrawTextX11.cpp,
BackDraw.h,
BackDraw.cpp,
Image readonly separator,

View file

@ -298,93 +298,6 @@ void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Co
XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_old);
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx) {
LTIMING("DrawText");
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
//TODO - X11 seems to crash when displaying too long strings (?)
int ox = x + actual_offset.x;
int oy = y + actual_offset.y;
SetForeground(ink);
SetFont(font, angle);
const FontInfo::Data *fd = lastFont.ptr;
XftColor c;
c.color.red = ink.GetR() << 8;
c.color.green = ink.GetG() << 8;
c.color.blue = ink.GetB() << 8;
c.color.alpha = 0xffff;
c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB());
if(angle) {
int xpos = 0;
for(int i = 0; i < n; i++) {
wchar h = text[i];
XftDrawString16(xftdraw, &c, fd->xftfont,
int(ox + xpos * fd->cosa + fd->offset.cx),
int(oy - xpos * fd->sina + fd->offset.cy),
(FcChar16 *)&h, 1);
xpos += dx ? dx[i] : lastFont[text[i]];
}
if(font.IsUnderline() || font.IsStrikeout()) {
x += fd->offset.cx;
y += fd->offset.cy;
if(font.IsUnderline())
DrawLine(
int(x + fd->underline_position * fd->sina),
int(y + fd->underline_position * fd->cosa),
int(x + xpos * fd->cosa + fd->underline_position * fd->sina),
int(y - xpos * fd->sina + fd->underline_position * fd->cosa),
fd->underline_thickness,
ink
);
if(font.IsStrikeout()) {
int p = 2 * fd->ascent / 3;
DrawLine(
int(x + p * fd->sina),
int(y + p * fd->cosa),
int(x + xpos * fd->cosa + p * fd->sina),
int(y - xpos * fd->sina + p * fd->cosa),
fd->underline_thickness,
ink
);
}
}
}
else {
if(dx) {
int xpos = ox;
Buffer<XftCharSpec> ch(n);
for(int i = 0; i < n; i++) {
ch[i].ucs4 = text[i];
ch[i].x = xpos;
ch[i].y = oy + fd->ascent;
xpos += dx[i];
}
XftDrawCharSpec(xftdraw, &c, fd->xftfont, ch, n);
}
else
XftDrawString16(xftdraw, &c, fd->xftfont, ox, oy + fd->ascent,
(FcChar16 *)text, n);
LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue
<< ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel));
if(font.IsUnderline() || font.IsStrikeout()) {
int cx;
if(dx && n > 0) {
cx = 0;
Sum(cx, dx, dx + n - 1);
cx += lastFont[text[n - 1]];
}
else
cx = GetTextSize(text, font, n).cx;
if(font.IsUnderline())
DrawRect(x, y + lastFont.GetAscent() + lastFont.ptr->underline_position,
cx, lastFont.ptr->underline_thickness, ink);
if(font.IsStrikeout())
DrawRect(x, y + 2 * lastFont.GetAscent() / 3,
cx, lastFont.ptr->underline_thickness, ink);
}
}
}
#endif
END_UPP_NAMESPACE

View file

@ -0,0 +1,221 @@
#include "Draw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
#define LTIMING(x)
#define LLOG(x)
extern int gtk_antialias;
extern int gtk_hinting;
extern String gtk_hintstyle;
extern String gtk_rgba;
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());
}
XftFont *CreateXftFont(Font font, int angle)
{
LTIMING("CreateXftFont");
XftFont *xftfont;
double sina, cosa;
Std(font);
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int i = font.GetFace();
if(i < 0 || i >= Font::GetFaceCount())
i = 0;
String face = font.GetFaceName();
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);
if(font.IsNonAntiAliased() || gtk_antialias >= 0) {
FcPatternDel(m, FC_ANTIALIAS);
FcPatternAddBool(m, FC_ANTIALIAS,
font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse);
}
if(gtk_hinting >= 0) {
FcPatternDel(m, FC_HINTING);
FcPatternAddBool(m, FC_HINTING, gtk_hinting);
}
const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" };
for(int i = 0; i < 4; i++)
if(gtk_hintstyle == hs[i]) {
FcPatternDel(m, FC_HINT_STYLE);
FcPatternAddInteger(m, FC_HINT_STYLE, i);
}
const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" };
for(int i = 0; i < __countof(rgba); i++)
if(gtk_rgba == rgba[i]) {
FcPatternDel(m, FC_RGBA);
FcPatternAddInteger(m, FC_RGBA, i);
}
xftfont = XftFontOpenPattern(Xdisplay, m);
FcPatternDestroy(p);
return xftfont;
}
#define FONTCACHE 37
struct XftEntry {
Font font;
int angle;
XftFont *xftfont;
};
XftFont *GetXftFont(Font fnt, int angle)
{
static XftEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
XftEntry be;
be = cache[0];
for(int i = 0; i < FONTCACHE; i++) {
XftEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.xftfont;
}
be = e;
}
if(be.xftfont) {
XftFontClose(Xdisplay, be.xftfont);
}
be.font = fnt;
be.angle = angle;
be.xftfont = CreateXftFont(fnt, angle);
cache[0] = be;
return be.xftfont;
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx) {
DrawLock __;
LTIMING("DrawText");
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
//TODO - X11 seems to crash when displaying too long strings (?)
int ox = x + actual_offset.x;
int oy = y + actual_offset.y;
SetForeground(ink);
SetFont(font, angle);
const FontInfo::Data *fd = lastFont.ptr;
XftColor c;
c.color.red = ink.GetR() << 8;
c.color.green = ink.GetG() << 8;
c.color.blue = ink.GetB() << 8;
c.color.alpha = 0xffff;
c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB());
XftFont *xftfont = GetXftFont(font, angle);
Size offset = Point(0, 0);
double sina, cosa;
int ascent = font.Info().GetAscent();
if(angle) {
SinCos(angle, sina, cosa);
offset.cx = fround(ascent * sina);
offset.cy = fround(ascent * cosa);
}
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int underline_thickness = max(hg / 20, 1);
int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0));
if(angle) {
int xpos = 0;
for(int i = 0; i < n; i++) {
wchar h = text[i];
XftDrawString16(xftdraw, &c, xftfont,
int(ox + xpos * cosa + offset.cx),
int(oy - xpos * sina + offset.cy),
(FcChar16 *)&h, 1);
xpos += dx ? dx[i] : lastFont[text[i]];
}
if(font.IsUnderline() || font.IsStrikeout()) {
x += offset.cx;
y += offset.cy;
if(font.IsUnderline())
DrawLine(
int(x + underline_position * sina),
int(y + underline_position * cosa),
int(x + xpos * cosa + underline_position * sina),
int(y - xpos * sina + underline_position * cosa),
underline_thickness,
ink
);
if(font.IsStrikeout()) {
int p = 2 * ascent / 3;
DrawLine(
int(x + p * sina),
int(y + p * cosa),
int(x + xpos * cosa + p * sina),
int(y - xpos * sina + p * cosa),
underline_thickness,
ink
);
}
}
}
else {
if(dx) {
int xpos = ox;
Buffer<XftCharSpec> ch(n);
for(int i = 0; i < n; i++) {
ch[i].ucs4 = text[i];
ch[i].x = xpos;
ch[i].y = oy + ascent;
xpos += dx[i];
}
XftDrawCharSpec(xftdraw, &c, xftfont, ch, n);
}
else
XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent,
(FcChar16 *)text, n);
LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue
<< ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel));
if(font.IsUnderline() || font.IsStrikeout()) {
int cx;
if(dx && n > 0) {
cx = 0;
Sum(cx, dx, dx + n - 1);
cx += lastFont[text[n - 1]];
}
else
cx = GetTextSize(text, font, n).cx;
if(font.IsUnderline())
DrawRect(x, y + lastFont.GetAscent() + lastFont.ptr->underline_position,
cx, lastFont.ptr->underline_thickness, ink);
if(font.IsStrikeout())
DrawRect(x, y + 2 * lastFont.GetAscent() / 3,
cx, lastFont.ptr->underline_thickness, ink);
}
}
}
#endif
END_UPP_NAMESPACE

View file

@ -1,306 +1,306 @@
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
void InitPlatformFonts();
Size FontInfo::StdFontSize;
Font FontInfo::AStdFont;
int FontInfo::FontCacheMax = 32;
int FontInfo::FontCached;
void FreeFonts();
enum FontHashConst { FONTHASH = 97 };
//# Pretty ugly code....
FontInfo::Data *FontInfo::GetFontHash(int i) {
static byte buff[FONTHASH * sizeof(FontLink)];
static FontLink *fonthash;
ONCELOCK {
fonthash = (FontLink *)buff;
for(int i = 0; i < FONTHASH; i++)
fonthash[i].LinkSelfAll();
}
ASSERT(i >= 0 && i < FONTHASH);
return (FontInfo::Data *)&fonthash[i];
}
//# Pretty ugly code....
FontInfo::Data *FontInfo::GetFontLru() {
static byte buff[sizeof(FontLink)];
static FontLink *fontlru;
ONCELOCK {
fontlru = new(buff) FontLink;
}
return (FontInfo::Data *)fontlru;
}
INITBLOCK {
RichValue<Font>::Register();
}
void FontInfo::InitFonts()
{
ONCELOCK {
static bool b;
if(b) return;
b = true;
DrawLock __;
GetFontHash(0);
GetFontLru();
InitPlatformFonts();
}
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const char *name) {
FontInfo::InitFonts();
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
FontInfo::FontInfo()
{
ptr = NULL;
charset = CHARSET_UNICODE;
InitFonts();
}
SystemDraw& ScreenInfo();
FontInfo Font::Info() const
{
DrawLock __;
return FontInfo::AcquireFontInfo(*this, 0);
}
void FontInfo::SyncStdFont()
{
FontInfo fi = AStdFont.Info();
FontInfo bfi = AStdFont().Bold().Info();
StdFontSize = Size(fi.GetAveWidth(), bfi.GetHeight());
}
void FontInfo::SetStdFont(Font font)
{
DrawLock __;
InitFonts();
AStdFont = font;
SyncStdFont();
}
Size FontInfo::GetStdFontSize()
{
ONCELOCK {
SyncStdFont();
}
return StdFontSize;
}
Font StdFont()
{
return Font(0, FontInfo::GetStdFont().GetHeight());
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % flags % height % width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
void FontInfo::FreeFonts() {
FontCacheMax = FontCached = 0;
for(int i = 0; i < FONTHASH; i++)
GetFontHash(i)->DeleteList(HASH);
}
FontInfo::FontInfo(const FontInfo& f)
{
Retain(f);
}
FontInfo& FontInfo::operator=(const FontInfo& f)
{
Release();
Retain(f);
return *this;
}
bool FontInfo::IsEqual(byte _charset, Font f, int angle) const
{
return ptr && ptr->font == f && ptr->angle == angle && charset == _charset;
}
FontInfo::CharMetrics FontInfo::GetCM(int c) const
{
if(c < 0) c = (byte)c;
if(charset != CHARSET_UNICODE)
c = ToUnicode(c, charset);
ASSERT(c < 65536);
if(c >= 65536) {
CharMetrics h;
h.width = h.lspc = h.rspc = 0;
return h;
}
if(c < 2048)
return GetPage(c >> 5)[c & 31];
Mutex::Lock __(ptr->xmutex);
Kinfo& ki = ptr->kinfo.At((c >> 10) - 2);
if(!ki.flags) {
ki.flags = new byte[128];
memset(ki.flags, 0, 128);
ptr->GetMetrics(&ki.std, c, 1);
}
int fi = (c >> 3) & 127;
int fm = 1 << (c & 7);
if(ki.flags[fi] & fm)
return ki.std;
int q = ptr->xx.Find(c);
if(q >= 0)
return ptr->xx[q];
CharMetrics m;
ptr->GetMetrics(&m, c, 1);
if(m == ki.std)
ki.flags[fi] |= fm;
else
ptr->xx.Add(c, m);
return m;
}
int FontInfo::GetWidth(int c) const {
return GetCM(c).width;
}
int FontInfo::GetLeftSpace(int c) const {
return GetCM(c).lspc;
}
int FontInfo::GetRightSpace(int c) const {
return GetCM(c).rspc;
}
void FontInfo::Release()
{
DrawLock __;
if(ptr) {
ASSERT(ptr->refcount > 0);
LLOG("Release " << (void *)ptr << " count:" << ptr->count);
if(--ptr->refcount == 0) {
if(FontCacheMax == 0) {
delete ptr;
return;
}
FontInfo::Data *lru = GetFontLru();
ptr->LinkAfter(lru, LRU);
FontCached++;
LLOG("Placed to cache " << ptr->ptr << " cached:" << FontCached);
while(FontCached > FontCacheMax) {
ASSERT(lru->GetPrev(LRU) != lru);
FontCached--;
LLOG("Deleting from cache " << lru->GetPrev(LRU)->ptr <<
" cached: " << FontCached);
delete lru->GetPrev(LRU);
}
}
}
}
void FontInfo::Retain(const FontInfo& f)
{
DrawLock __;
ptr = f.ptr;
ptr->refcount++;
charset = f.charset;
}
FontInfo::CharMetrics *FontInfo::CreateMetricsPage(int page) const
{
DrawLock __;
CharMetrics *cm;
cm = new CharMetrics[32];
ptr->GetMetrics(cm, page << 5, 32);
if(page >= 8 && page < 12)
ComposeMetrics(ptr->font, cm, page);
return cm;
}
FontInfo::CharMetrics *FontInfo::GetPage(int page) const
{
ASSERT(page >= 0 && page < 64);
ONCELOCK_PTR(ptr->base[page], CreateMetricsPage(page));
return ptr->base[page];
}
END_UPP_NAMESPACE
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
void InitPlatformFonts();
Size FontInfo::StdFontSize;
Font FontInfo::AStdFont;
int FontInfo::FontCacheMax = 32;
int FontInfo::FontCached;
void FreeFonts();
enum FontHashConst { FONTHASH = 97 };
//# Pretty ugly code....
FontInfo::Data *FontInfo::GetFontHash(int i) {
static byte buff[FONTHASH * sizeof(FontLink)];
static FontLink *fonthash;
ONCELOCK {
fonthash = (FontLink *)buff;
for(int i = 0; i < FONTHASH; i++)
fonthash[i].LinkSelfAll();
}
ASSERT(i >= 0 && i < FONTHASH);
return (FontInfo::Data *)&fonthash[i];
}
//# Pretty ugly code....
FontInfo::Data *FontInfo::GetFontLru() {
static byte buff[sizeof(FontLink)];
static FontLink *fontlru;
ONCELOCK {
fontlru = new(buff) FontLink;
}
return (FontInfo::Data *)fontlru;
}
INITBLOCK {
RichValue<Font>::Register();
}
void FontInfo::InitFonts()
{
ONCELOCK {
static bool b;
if(b) return;
b = true;
DrawLock __;
GetFontHash(0);
GetFontLru();
InitPlatformFonts();
}
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const char *name) {
FontInfo::InitFonts();
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
FontInfo::FontInfo()
{
ptr = NULL;
charset = CHARSET_UNICODE;
InitFonts();
}
SystemDraw& ScreenInfo();
FontInfo Font::Info() const
{
DrawLock __;
return FontInfo::AcquireFontInfo(*this, 0);
}
void FontInfo::SyncStdFont()
{
FontInfo fi = AStdFont.Info();
FontInfo bfi = AStdFont().Bold().Info();
StdFontSize = Size(fi.GetAveWidth(), bfi.GetHeight());
}
void FontInfo::SetStdFont(Font font)
{
DrawLock __;
InitFonts();
AStdFont = font;
SyncStdFont();
}
Size FontInfo::GetStdFontSize()
{
ONCELOCK {
SyncStdFont();
}
return StdFontSize;
}
Font StdFont()
{
return Font(0, FontInfo::GetStdFont().GetHeight());
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % v.flags % v.height % v.width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
void FontInfo::FreeFonts() {
FontCacheMax = FontCached = 0;
for(int i = 0; i < FONTHASH; i++)
GetFontHash(i)->DeleteList(HASH);
}
FontInfo::FontInfo(const FontInfo& f)
{
Retain(f);
}
FontInfo& FontInfo::operator=(const FontInfo& f)
{
Release();
Retain(f);
return *this;
}
bool FontInfo::IsEqual(byte _charset, Font f, int angle) const
{
return ptr && ptr->font == f && ptr->angle == angle && charset == _charset;
}
FontInfo::CharMetrics FontInfo::GetCM(int c) const
{
if(c < 0) c = (byte)c;
if(charset != CHARSET_UNICODE)
c = ToUnicode(c, charset);
ASSERT(c < 65536);
if(c >= 65536) {
CharMetrics h;
h.width = h.lspc = h.rspc = 0;
return h;
}
if(c < 2048)
return GetPage(c >> 5)[c & 31];
Mutex::Lock __(ptr->xmutex);
Kinfo& ki = ptr->kinfo.At((c >> 10) - 2);
if(!ki.flags) {
ki.flags = new byte[128];
memset(ki.flags, 0, 128);
ptr->GetMetrics(&ki.std, c, 1);
}
int fi = (c >> 3) & 127;
int fm = 1 << (c & 7);
if(ki.flags[fi] & fm)
return ki.std;
int q = ptr->xx.Find(c);
if(q >= 0)
return ptr->xx[q];
CharMetrics m;
ptr->GetMetrics(&m, c, 1);
if(m == ki.std)
ki.flags[fi] |= fm;
else
ptr->xx.Add(c, m);
return m;
}
int FontInfo::GetWidth(int c) const {
return GetCM(c).width;
}
int FontInfo::GetLeftSpace(int c) const {
return GetCM(c).lspc;
}
int FontInfo::GetRightSpace(int c) const {
return GetCM(c).rspc;
}
void FontInfo::Release()
{
DrawLock __;
if(ptr) {
ASSERT(ptr->refcount > 0);
LLOG("Release " << (void *)ptr << " count:" << ptr->count);
if(--ptr->refcount == 0) {
if(FontCacheMax == 0) {
delete ptr;
return;
}
FontInfo::Data *lru = GetFontLru();
ptr->LinkAfter(lru, LRU);
FontCached++;
LLOG("Placed to cache " << ptr->ptr << " cached:" << FontCached);
while(FontCached > FontCacheMax) {
ASSERT(lru->GetPrev(LRU) != lru);
FontCached--;
LLOG("Deleting from cache " << lru->GetPrev(LRU)->ptr <<
" cached: " << FontCached);
delete lru->GetPrev(LRU);
}
}
}
}
void FontInfo::Retain(const FontInfo& f)
{
DrawLock __;
ptr = f.ptr;
ptr->refcount++;
charset = f.charset;
}
FontInfo::CharMetrics *FontInfo::CreateMetricsPage(int page) const
{
DrawLock __;
CharMetrics *cm;
cm = new CharMetrics[32];
ptr->GetMetrics(cm, page << 5, 32);
if(page >= 8 && page < 12)
ComposeMetrics(ptr->font, cm, page);
return cm;
}
FontInfo::CharMetrics *FontInfo::GetPage(int page) const
{
ASSERT(page >= 0 && page < 64);
ONCELOCK_PTR(ptr->base[page], CreateMetricsPage(page));
return ptr->base[page];
}
END_UPP_NAMESPACE