fix freetype support

This commit is contained in:
Vadim Lopatin 2014-04-24 09:42:23 +04:00
parent 6bb605dde9
commit 5472b2456b
4 changed files with 53 additions and 41 deletions

View File

@ -146,9 +146,6 @@ struct Glyph
uint id; uint id;
} }
///< 8: character
//uint glyphIndex;
///< 4: width of glyph black box ///< 4: width of glyph black box
ubyte blackBoxX; ubyte blackBoxX;
///< 5: height of glyph black box ///< 5: height of glyph black box
@ -158,9 +155,9 @@ struct Glyph
///< 7: Y origin for glyph ///< 7: Y origin for glyph
byte originY; byte originY;
///< 10: full width of glyph ///< 8: full width of glyph
ubyte width; ubyte width;
///< 11: usage flag, to handle cleanup of unused glyphs ///< 9: usage flag, to handle cleanup of unused glyphs
ubyte lastUsage; ubyte lastUsage;
///< 12: glyph data, arbitrary size ///< 12: glyph data, arbitrary size
ubyte[] glyph; ubyte[] glyph;

View File

@ -57,13 +57,13 @@ version (USE_OPENGL) {
uint nextGlyphId() { return _nextGlyphId++; } uint nextGlyphId() { return _nextGlyphId++; }
} }
/// glyph image cache
struct GlyphCache struct GlyphCache
{ {
alias glyph_ptr = Glyph*; alias glyph_ptr = Glyph*;
private glyph_ptr[][1024] _glyphs; private glyph_ptr[][1024] _glyphs;
Glyph * find(uint ch) { Glyph * find(dchar ch) {
ch = ch & 0xF_FFFF; ch = ch & 0xF_FFFF;
//if (_array is null) //if (_array is null)
// _array = new Glyph[0x10000]; // _array = new Glyph[0x10000];
@ -71,55 +71,70 @@ struct GlyphCache
glyph_ptr[] row = _glyphs[p]; glyph_ptr[] row = _glyphs[p];
if (row is null) if (row is null)
return null; return null;
ushort i = ch & 0xFF; uint i = ch & 0xFF;
return row[i]; Glyph * res = row[i];
if (!res)
return null;
res.lastUsage = 1;
return res;
} }
/// put glyph to cache /// put glyph to cache
Glyph * put(uint ch, Glyph * glyph) { Glyph * put(dchar ch, Glyph * glyph) {
ch = ch & 0xF_FFFF;
uint p = ch >> 8; uint p = ch >> 8;
uint i = ch & 0xFF; uint i = ch & 0xFF;
if (_glyphs[p] is null) if (_glyphs[p] is null)
_glyphs[p] = new glyph_ptr[256]; _glyphs[p] = new glyph_ptr[256];
_glyphs[p][i] = glyph; _glyphs[p][i] = glyph;
glyph.lastUsage = 1;
return glyph; return glyph;
} }
/// removes entries not used after last call of checkpoint() or cleanup() /// removes entries not used after last call of checkpoint() or cleanup()
void cleanup() { void cleanup() {
// TODO foreach(part; _glyphs) {
if (part !is null)
foreach(item; part) {
if (item && !item.lastUsage) {
version (USE_OPENGL) {
// notify about destroyed glyphs
if (_glyphDestroyCallback !is null) {
_glyphDestroyCallback(item.id);
}
}
destroy(item);
}
}
}
} }
// clear usage flags for all entries // clear usage flags for all entries
void checkpoint() { void checkpoint() {
foreach(part; _glyphs) {
if (part !is null)
foreach(item; part) {
if (item)
item.lastUsage = 0;
}
}
} }
/// removes all entries /// removes all entries
void clear() { void clear() {
// notify about destroyed glyphs foreach(part; _glyphs) {
version (USE_OPENGL) {
if (_glyphDestroyCallback !is null) {
foreach(part; _glyphs) {
if (part !is null)
foreach(item; part) {
if (item)
_glyphDestroyCallback(item.id);
}
}
}
}
/*
foreach(ref Glyph[] part; _glyphs) {
if (part !is null) if (part !is null)
foreach(ref Glyph item; part) { foreach(item; part) {
if (item.glyphIndex) { if (item) {
item.glyphIndex = 0;
item.glyph = null;
version (USE_OPENGL) { version (USE_OPENGL) {
item.id = 0; // notify about destroyed glyphs
if (_glyphDestroyCallback !is null) {
_glyphDestroyCallback(item.id);
}
} }
destroy(item);
} }
} }
} }
*/
} }
~this() { ~this() {
clear(); clear();

View File

@ -341,17 +341,16 @@ class FreeTypeFont : Font {
return false; return false;
} }
private Glyph tmpGlyphInfo;
override Glyph * getCharGlyph(dchar ch, bool withImage = true) { override Glyph * getCharGlyph(dchar ch, bool withImage = true) {
if (ch > 0xFFFF) // do not support unicode chars above 0xFFFF - due to cache limitations if (ch > 0xFFFF) // do not support unicode chars above 0xFFFF - due to cache limitations
return null; return null;
long measureStart = std.datetime.Clock.currStdTime; //long measureStart = std.datetime.Clock.currStdTime;
Glyph * found = _glyphCache.find(cast(ushort)ch); Glyph * found = _glyphCache.find(cast(ushort)ch);
long measureEnd = std.datetime.Clock.currStdTime; //long measureEnd = std.datetime.Clock.currStdTime;
long duration = measureEnd - measureStart; //long duration = measureEnd - measureStart;
//if (duration > 10000) //if (duration > 10000)
if (duration > 10000) //if (duration > 10000)
Log.d("ft _glyphCache.find took ", duration / 10, " ns"); // Log.d("ft _glyphCache.find took ", duration / 10, " ns");
if (found !is null) if (found !is null)
return found; return found;
Log.v("Glyph ", ch, " is not found in cache, getting from font"); Log.v("Glyph ", ch, " is not found in cache, getting from font");
@ -361,11 +360,12 @@ class FreeTypeFont : Font {
if (!findGlyph(ch, '?', index, file)) if (!findGlyph(ch, '?', index, file))
return null; return null;
} }
if (!file.getGlyphInfo(ch, tmpGlyphInfo, 0, withImage)) Glyph * glyph = new Glyph;
if (!file.getGlyphInfo(ch, *glyph, 0, withImage))
return null; return null;
if (withImage) if (withImage)
return _glyphCache.put(cast(ushort)ch, &tmpGlyphInfo); return _glyphCache.put(ch, glyph);
return &tmpGlyphInfo; return glyph;
} }
// draw text string to buffer // draw text string to buffer

View File

@ -659,7 +659,7 @@ int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
Platform.setInstance(platform); Platform.setInstance(platform);
if (false) { if (true) {
/// testing freetype font manager /// testing freetype font manager
import dlangui.graphics.ftfonts; import dlangui.graphics.ftfonts;
import win32.shlobj; import win32.shlobj;