mirror of https://github.com/buggins/dlangui.git
optimize font glyph cache
This commit is contained in:
parent
da09eeed1c
commit
0fd29831ab
|
@ -105,7 +105,7 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
|
|
||||||
ListWidget list = new ListWidget("tab2", Orientation.Vertical);
|
ListWidget list = new ListWidget("tab2", Orientation.Vertical);
|
||||||
WidgetListAdapter listAdapter = new WidgetListAdapter();
|
WidgetListAdapter listAdapter = new WidgetListAdapter();
|
||||||
for (int i = 0; i < 30; i++)
|
for (int i = 0; i < 3000; i++)
|
||||||
listAdapter.widgets.add((new TextWidget()).text("List item "d ~ to!dstring(i)));
|
listAdapter.widgets.add((new TextWidget()).text("List item "d ~ to!dstring(i)));
|
||||||
list.ownAdapter = listAdapter;
|
list.ownAdapter = listAdapter;
|
||||||
list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
|
||||||
|
|
|
@ -37,77 +37,70 @@ version (USE_OPENGL) {
|
||||||
uint nextGlyphId() { return _nextGlyphId++; }
|
uint nextGlyphId() { return _nextGlyphId++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// font glyph cache
|
||||||
struct GlyphCache
|
struct GlyphCache
|
||||||
{
|
{
|
||||||
Glyph[] _data;
|
Glyph[ushort] _map;
|
||||||
uint _len;
|
|
||||||
|
|
||||||
// find glyph in cache
|
// find glyph in cache
|
||||||
Glyph * find(ushort glyphIndex) {
|
Glyph * find(ushort glyphIndex) {
|
||||||
for (uint i = 0; i < _len; i++) {
|
Glyph * res = (glyphIndex in _map);
|
||||||
Glyph * item = &_data[i];
|
if (res !is null)
|
||||||
if (item.glyphIndex == glyphIndex) {
|
res.lastUsage = 1;
|
||||||
item.lastUsage = 1;
|
return res;
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// put glyph to cache
|
||||||
Glyph * put(ushort glyphIndex, Glyph * glyph) {
|
Glyph * put(ushort glyphIndex, Glyph * glyph) {
|
||||||
if (_len >= _data.length) {
|
_map[glyphIndex] = *glyph;
|
||||||
uint newsize = (_len < 32) ? 32 : _len * 2;
|
Glyph * res = glyphIndex in _map;
|
||||||
_data.length = newsize;
|
|
||||||
}
|
|
||||||
_data[_len++] = *glyph;
|
|
||||||
Glyph * res = &_data[_len - 1];
|
|
||||||
res.lastUsage = 1;
|
res.lastUsage = 1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear usage flags for all entries
|
// clear usage flags for all entries
|
||||||
void checkpoint() {
|
void checkpoint() {
|
||||||
for (uint src = 0; src < _len; src++) {
|
foreach(ref Glyph item; _map) {
|
||||||
_data[src].lastUsage = 0;
|
item.lastUsage = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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() {
|
||||||
uint dst = 0;
|
uint dst = 0;
|
||||||
// notify about destroyed glyphs
|
// notify about destroyed glyphs
|
||||||
version (USE_OPENGL) {
|
version (USE_OPENGL) {
|
||||||
if (_glyphDestroyCallback !is null)
|
if (_glyphDestroyCallback !is null)
|
||||||
for (uint src = 0; src < _len; src++)
|
foreach(ref Glyph item; _map) {
|
||||||
if (_data[src].lastUsage == 0)
|
if (item.lastUsage == 0)
|
||||||
_glyphDestroyCallback(_data[src].id);
|
_glyphDestroyCallback(item.id);
|
||||||
}
|
|
||||||
for (uint src = 0; src < _len; src++) {
|
|
||||||
if (_data[src].lastUsage != 0) {
|
|
||||||
_data[src].lastUsage = 0;
|
|
||||||
if (src != dst) {
|
|
||||||
_data[dst++] = _data[src];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
ushort[] forDelete;
|
||||||
_len = dst;
|
foreach(ref Glyph item; _map)
|
||||||
|
if (item.lastUsage == 0)
|
||||||
|
forDelete ~= item.glyphIndex;
|
||||||
|
foreach(ushort index; forDelete)
|
||||||
|
_map.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes all entries
|
/// removes all entries
|
||||||
void clear() {
|
void clear() {
|
||||||
version (USE_OPENGL) {
|
version (USE_OPENGL) {
|
||||||
if (_glyphDestroyCallback !is null)
|
if (_glyphDestroyCallback !is null)
|
||||||
for (uint src = 0; src < _len; src++)
|
foreach(ref Glyph item; _map) {
|
||||||
_glyphDestroyCallback(_data[src].id);
|
if (item.lastUsage == 0)
|
||||||
|
_glyphDestroyCallback(item.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_data = null;
|
_map.clear();
|
||||||
_len = 0;
|
|
||||||
}
|
}
|
||||||
~this() {
|
~this() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Font object
|
||||||
class Font : RefCountedObject {
|
class Font : RefCountedObject {
|
||||||
abstract @property int size();
|
abstract @property int size();
|
||||||
abstract @property int height();
|
abstract @property int height();
|
||||||
|
@ -127,13 +120,14 @@ class Font : RefCountedObject {
|
||||||
return Point(0,0);
|
return Point(0,0);
|
||||||
return Point(widths[charsMeasured - 1], height);
|
return Point(widths[charsMeasured - 1], height);
|
||||||
}
|
}
|
||||||
// draw text string to buffer
|
/// draw text string to buffer
|
||||||
abstract void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color);
|
abstract void drawText(DrawBuf buf, int x, int y, const dchar[] text, uint color);
|
||||||
|
/// get character glyph information
|
||||||
abstract Glyph * getCharGlyph(dchar ch, bool withImage = true);
|
abstract Glyph * getCharGlyph(dchar ch, bool withImage = true);
|
||||||
|
|
||||||
// clear usage flags for all entries
|
/// clear usage flags for all entries
|
||||||
abstract void checkpoint();
|
abstract void checkpoint();
|
||||||
// removes entries not used after last call of checkpoint() or cleanup()
|
/// removes entries not used after last call of checkpoint() or cleanup()
|
||||||
abstract void cleanup();
|
abstract void cleanup();
|
||||||
|
|
||||||
void clear() {}
|
void clear() {}
|
||||||
|
@ -142,6 +136,7 @@ class Font : RefCountedObject {
|
||||||
}
|
}
|
||||||
alias FontRef = Ref!Font;
|
alias FontRef = Ref!Font;
|
||||||
|
|
||||||
|
/// font instance collection - utility class, for font manager implementations
|
||||||
struct FontList {
|
struct FontList {
|
||||||
FontRef[] _list;
|
FontRef[] _list;
|
||||||
uint _len;
|
uint _len;
|
||||||
|
@ -223,7 +218,8 @@ struct FontList {
|
||||||
|
|
||||||
/// Access points to fonts.
|
/// Access points to fonts.
|
||||||
class FontManager {
|
class FontManager {
|
||||||
static __gshared FontManager _instance;
|
protected static __gshared FontManager _instance;
|
||||||
|
|
||||||
/// sets new font manager singleton instance
|
/// sets new font manager singleton instance
|
||||||
static @property void instance(FontManager manager) {
|
static @property void instance(FontManager manager) {
|
||||||
if (_instance !is null) {
|
if (_instance !is null) {
|
||||||
|
@ -232,6 +228,7 @@ class FontManager {
|
||||||
}
|
}
|
||||||
_instance = manager;
|
_instance = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns font manager singleton instance
|
/// returns font manager singleton instance
|
||||||
static @property FontManager instance() {
|
static @property FontManager instance() {
|
||||||
return _instance;
|
return _instance;
|
||||||
|
|
Loading…
Reference in New Issue