added debugging code into GlyphCache.

This commit is contained in:
rachytski 2012-01-19 12:43:47 +04:00 committed by Alex Zolotarev
parent 07a2aceb0f
commit 94dfe0b50a
7 changed files with 279 additions and 191 deletions

View file

@ -14,6 +14,7 @@
#include "../std/vector.hpp"
#include "../std/map.hpp"
#include "../base/mutex.hpp"
#include <boost/gil/gil_all.hpp>
@ -52,14 +53,6 @@ namespace yg
{
}
struct RawGlyphInfo : public GlyphInfo
{
~RawGlyphInfo()
{
delete m_bitmapData;
}
};
struct FTGlyphInfo : public GlyphInfo
{
FTC_Node m_node;
@ -75,8 +68,8 @@ namespace yg
}
};
GlyphCache::Params::Params(string const & blocksFile, string const & whiteListFile, string const & blackListFile, size_t maxSize)
: m_blocksFile(blocksFile), m_whiteListFile(whiteListFile), m_blackListFile(blackListFile), m_maxSize(maxSize)
GlyphCache::Params::Params(string const & blocksFile, string const & whiteListFile, string const & blackListFile, size_t maxSize, bool isDebugging)
: m_blocksFile(blocksFile), m_whiteListFile(whiteListFile), m_blackListFile(blackListFile), m_maxSize(maxSize), m_isDebugging(isDebugging)
{}
GlyphCache::GlyphCache()
@ -98,174 +91,17 @@ namespace yg
pair<Font*, int> GlyphCache::getCharIDX(GlyphKey const & key)
{
vector<shared_ptr<Font> > & fonts = m_impl->getFonts(key.m_symbolCode);
Font * font = 0;
int charIDX;
for (size_t i = 0; i < fonts.size(); ++i)
{
font = fonts[i].get();
FTC_FaceID faceID = reinterpret_cast<FTC_FaceID>(font);
charIDX = FTC_CMapCache_Lookup(
m_impl->m_charMapCache,
faceID,
-1,
key.m_symbolCode
);
if (charIDX != 0)
return make_pair(font, charIDX);
}
#ifdef DEBUG
for (size_t i = 0; i < m_impl->m_unicodeBlocks.size(); ++i)
{
if (m_impl->m_unicodeBlocks[i].hasSymbol(key.m_symbolCode))
{
LOG(LINFO, ("Symbol", key.m_symbolCode, "not found, unicodeBlock=", m_impl->m_unicodeBlocks[i].m_name));
break;
}
}
#endif
font = fonts.front().get();
/// taking substitution character from the first font in the list
charIDX = FTC_CMapCache_Lookup(
m_impl->m_charMapCache,
reinterpret_cast<FTC_FaceID>(font),
-1,
65533
);
if (charIDX == 0)
charIDX = FTC_CMapCache_Lookup(
m_impl->m_charMapCache,
reinterpret_cast<FTC_FaceID>(font),
-1,
32
);
return make_pair(font, charIDX);
return m_impl->getCharIDX(key);
}
GlyphMetrics const GlyphCache::getGlyphMetrics(GlyphKey const & key)
{
pair<Font*, int> charIDX = getCharIDX(key);
FTC_ScalerRec fontScaler =
{
reinterpret_cast<FTC_FaceID>(charIDX.first),
key.m_fontSize,
key.m_fontSize,
1,
0,
0
};
FT_Glyph glyph = 0;
FTCHECK(FTC_ImageCache_LookupScaler(
m_impl->m_glyphMetricsCache,
&fontScaler,
FT_LOAD_DEFAULT,
charIDX.second,
&glyph,
0));
FT_BBox cbox;
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
GlyphMetrics m =
{
glyph->advance.x >> 16,
glyph->advance.y >> 16,
cbox.xMin, cbox.yMin,
cbox.xMax - cbox.xMin, cbox.yMax - cbox.yMin
};
return m;
return m_impl->getGlyphMetrics(key);
}
shared_ptr<GlyphInfo> const GlyphCache::getGlyphInfo(GlyphKey const & key)
{
pair<Font *, int> charIDX = getCharIDX(key);
FTC_ScalerRec fontScaler =
{
reinterpret_cast<FTC_FaceID>(charIDX.first),
key.m_fontSize,
key.m_fontSize,
1,
0,
0
};
FT_Glyph glyph = 0;
FTC_Node node;
GlyphInfo * info = 0;
if (key.m_isMask)
{
FTCHECK(FTC_StrokedImageCache_LookupScaler(
m_impl->m_strokedGlyphCache,
&fontScaler,
m_impl->m_stroker,
FT_LOAD_DEFAULT,
charIDX.second,
&glyph,
&node
));
// info = new FTGlyphInfo(node, m_impl->m_manager);
}
else
{
FTCHECK(FTC_ImageCache_LookupScaler(
m_impl->m_normalGlyphCache,
&fontScaler,
FT_LOAD_DEFAULT | FT_LOAD_RENDER,
charIDX.second,
&glyph,
&node
));
// info = new FTGlyphInfo(node, m_impl->m_manager);
}
info = new RawGlyphInfo();
FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
info->m_metrics.m_height = bitmapGlyph ? bitmapGlyph->bitmap.rows : 0;
info->m_metrics.m_width = bitmapGlyph ? bitmapGlyph->bitmap.width : 0;
info->m_metrics.m_xOffset = bitmapGlyph ? bitmapGlyph->left : 0;
info->m_metrics.m_yOffset = bitmapGlyph ? bitmapGlyph->top - info->m_metrics.m_height : 0;
info->m_metrics.m_xAdvance = bitmapGlyph ? int(bitmapGlyph->root.advance.x >> 16) : 0;
info->m_metrics.m_yAdvance = bitmapGlyph ? int(bitmapGlyph->root.advance.y >> 16) : 0;
info->m_color = key.m_color;
info->m_bitmapData = 0;
info->m_bitmapPitch = 0;
if ((info->m_metrics.m_width != 0) && (info->m_metrics.m_height != 0))
{
// info->m_bitmapData = bitmapGlyph->bitmap.buffer;
// info->m_bitmapPitch = bitmapGlyph->bitmap.pitch;
info->m_bitmapPitch = bitmapGlyph->bitmap.pitch;
info->m_bitmapData = new unsigned char[info->m_bitmapPitch * info->m_metrics.m_height];
memcpy(info->m_bitmapData, bitmapGlyph->bitmap.buffer, info->m_bitmapPitch * info->m_metrics.m_height);
}
FTC_Node_Unref(node, m_impl->m_manager);
return make_shared_ptr(info);
return m_impl->getGlyphInfo(key);
}
double GlyphCache::getTextLength(double fontSize, string const & text)
@ -281,9 +117,12 @@ namespace yg
return len;
}
threads::Mutex m;
strings::UniString GlyphCache::log2vis(strings::UniString const & str)
{
// FriBidiEnv e;
threads::MutexGuard g(m);
size_t const count = str.size();
strings::UniString res(count);
FriBidiParType dir = FRIBIDI_PAR_LTR; // requested base direction

View file

@ -76,7 +76,12 @@ namespace yg
string m_whiteListFile;
string m_blackListFile;
size_t m_maxSize;
Params(string const & blocksFile, string const & whiteListFile, string const & blackListFile, size_t maxSize);
bool m_isDebugging;
Params(string const & blocksFile,
string const & whiteListFile,
string const & blackListFile,
size_t maxSize,
bool isDebugging);
};
GlyphCache();
@ -94,7 +99,7 @@ namespace yg
double getTextLength(double fontSize, string const & text);
strings::UniString log2vis(strings::UniString const & str);
static strings::UniString log2vis(strings::UniString const & str);
};
}

View file

@ -12,6 +12,14 @@
namespace yg
{
struct RawGlyphInfo : public GlyphInfo
{
~RawGlyphInfo()
{
delete m_bitmapData;
}
};
UnicodeBlock::UnicodeBlock(string const & name, strings::UniChar start, strings::UniChar end)
: m_name(name), m_start(start), m_end(end)
{}
@ -186,6 +194,9 @@ namespace yg
void GlyphCacheImpl::addFonts(vector<string> const & fontNames)
{
if (m_isDebugging)
return;
for (size_t i = 0; i < fontNames.size(); ++i)
addFont(fontNames[i].c_str());
@ -226,6 +237,8 @@ namespace yg
void GlyphCacheImpl::addFont(char const * fileName)
{
if (m_isDebugging)
return;
ReaderPtr<Reader> reader = GetPlatform().GetReader(fileName);
m_fonts.push_back(make_shared_ptr(new Font(reader)));
@ -383,30 +396,248 @@ namespace yg
GlyphCacheImpl::GlyphCacheImpl(GlyphCache::Params const & params)
{
m_isDebugging = params.m_isDebugging;
initBlocks(params.m_blocksFile);
initFonts(params.m_whiteListFile, params.m_blackListFile);
FTCHECK(FT_Init_FreeType(&m_lib));
if (!m_isDebugging)
{
FTCHECK(FT_Init_FreeType(&m_lib));
/// Initializing caches
FTCHECK(FTC_Manager_New(m_lib, 3, 10, params.m_maxSize, &RequestFace, 0, &m_manager));
/// Initializing caches
FTCHECK(FTC_Manager_New(m_lib, 3, 10, params.m_maxSize, &RequestFace, 0, &m_manager));
FTCHECK(FTC_ImageCache_New(m_manager, &m_normalGlyphCache));
FTCHECK(FTC_StrokedImageCache_New(m_manager, &m_strokedGlyphCache));
FTCHECK(FTC_ImageCache_New(m_manager, &m_glyphMetricsCache));
FTCHECK(FTC_ImageCache_New(m_manager, &m_normalGlyphCache));
FTCHECK(FTC_StrokedImageCache_New(m_manager, &m_strokedGlyphCache));
FTCHECK(FTC_ImageCache_New(m_manager, &m_glyphMetricsCache));
/// Initializing stroker
FTCHECK(FT_Stroker_New(m_lib, &m_stroker));
FT_Stroker_Set(m_stroker, 2 * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
/// Initializing stroker
FTCHECK(FT_Stroker_New(m_lib, &m_stroker));
FT_Stroker_Set(m_stroker, 2 * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
FTCHECK(FTC_CMapCache_New(m_manager, &m_charMapCache));
FTCHECK(FTC_CMapCache_New(m_manager, &m_charMapCache));
}
else
{
/// initialize fake bitmap
}
}
GlyphCacheImpl::~GlyphCacheImpl()
{
FTC_Manager_Done(m_manager);
FT_Stroker_Done(m_stroker);
FT_Done_FreeType(m_lib);
if (!m_isDebugging)
{
FTC_Manager_Done(m_manager);
FT_Stroker_Done(m_stroker);
FT_Done_FreeType(m_lib);
}
}
int GlyphCacheImpl::getCharIDX(shared_ptr<Font> const & font, strings::UniChar symbolCode)
{
if (m_isDebugging)
return 0;
FTC_FaceID faceID = reinterpret_cast<FTC_FaceID>(font.get());
return FTC_CMapCache_Lookup(
m_charMapCache,
faceID,
-1,
symbolCode
);
}
pair<Font*, int> const GlyphCacheImpl::getCharIDX(GlyphKey const & key)
{
if (m_isDebugging)
return make_pair((Font*)0, 0);
vector<shared_ptr<Font> > & fonts = getFonts(key.m_symbolCode);
Font * font = 0;
int charIDX;
for (size_t i = 0; i < fonts.size(); ++i)
{
charIDX = getCharIDX(fonts[i], key.m_symbolCode);
if (charIDX != 0)
return make_pair(fonts[i].get(), charIDX);
}
#ifdef DEBUG
for (size_t i = 0; i < m_unicodeBlocks.size(); ++i)
{
if (m_unicodeBlocks[i].hasSymbol(key.m_symbolCode))
{
LOG(LINFO, ("Symbol", key.m_symbolCode, "not found, unicodeBlock=", m_unicodeBlocks[i].m_name));
break;
}
}
#endif
font = fonts.front().get();
/// taking substitution character from the first font in the list
charIDX = getCharIDX(fonts.front(), 65533);
if (charIDX == 0)
charIDX = getCharIDX(fonts.front(), 32);
return make_pair(font, charIDX);
}
GlyphMetrics const GlyphCacheImpl::getGlyphMetrics(GlyphKey const & key)
{
if (m_isDebugging)
{
GlyphMetrics m =
{
10,
0,
0, 0,
10, 20
};
return m;
}
pair<Font*, int> charIDX = getCharIDX(key);
FTC_ScalerRec fontScaler =
{
reinterpret_cast<FTC_FaceID>(charIDX.first),
key.m_fontSize,
key.m_fontSize,
1,
0,
0
};
FT_Glyph glyph = 0;
FTCHECK(FTC_ImageCache_LookupScaler(
m_glyphMetricsCache,
&fontScaler,
FT_LOAD_DEFAULT,
charIDX.second,
&glyph,
0));
FT_BBox cbox;
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
GlyphMetrics m =
{
glyph->advance.x >> 16,
glyph->advance.y >> 16,
cbox.xMin, cbox.yMin,
cbox.xMax - cbox.xMin, cbox.yMax - cbox.yMin
};
return m;
}
shared_ptr<GlyphInfo> const GlyphCacheImpl::getGlyphInfo(GlyphKey const & key)
{
if (m_isDebugging)
{
static bool hasFakeSymbol = false;
static shared_ptr<GlyphInfo> fakeSymbol;
if (!hasFakeSymbol)
{
fakeSymbol.reset(new RawGlyphInfo());
fakeSymbol->m_metrics = getGlyphMetrics(key);
fakeSymbol->m_color = yg::Color(0, 0, 255, 255);
fakeSymbol->m_bitmapPitch = (fakeSymbol->m_metrics.m_width + 7) / 8 * 8;
fakeSymbol->m_bitmapData = new unsigned char[fakeSymbol->m_bitmapPitch * fakeSymbol->m_metrics.m_height];
for (unsigned i = 0; i < fakeSymbol->m_bitmapPitch * fakeSymbol->m_metrics.m_height; ++i)
fakeSymbol->m_bitmapData[i] = 0xFF;
hasFakeSymbol = true;
}
return fakeSymbol;
}
pair<Font *, int> charIDX = getCharIDX(key);
FTC_ScalerRec fontScaler =
{
reinterpret_cast<FTC_FaceID>(charIDX.first),
key.m_fontSize,
key.m_fontSize,
1,
0,
0
};
FT_Glyph glyph = 0;
FTC_Node node;
GlyphInfo * info = 0;
if (key.m_isMask)
{
FTCHECK(FTC_StrokedImageCache_LookupScaler(
m_strokedGlyphCache,
&fontScaler,
m_stroker,
FT_LOAD_DEFAULT,
charIDX.second,
&glyph,
&node
));
// info = new FTGlyphInfo(node, m_manager);
}
else
{
FTCHECK(FTC_ImageCache_LookupScaler(
m_normalGlyphCache,
&fontScaler,
FT_LOAD_DEFAULT | FT_LOAD_RENDER,
charIDX.second,
&glyph,
&node
));
// info = new FTGlyphInfo(node, m_manager);
}
info = new RawGlyphInfo();
FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph;
info->m_metrics.m_height = bitmapGlyph ? bitmapGlyph->bitmap.rows : 0;
info->m_metrics.m_width = bitmapGlyph ? bitmapGlyph->bitmap.width : 0;
info->m_metrics.m_xOffset = bitmapGlyph ? bitmapGlyph->left : 0;
info->m_metrics.m_yOffset = bitmapGlyph ? bitmapGlyph->top - info->m_metrics.m_height : 0;
info->m_metrics.m_xAdvance = bitmapGlyph ? int(bitmapGlyph->root.advance.x >> 16) : 0;
info->m_metrics.m_yAdvance = bitmapGlyph ? int(bitmapGlyph->root.advance.y >> 16) : 0;
info->m_color = key.m_color;
info->m_bitmapData = 0;
info->m_bitmapPitch = 0;
if ((info->m_metrics.m_width != 0) && (info->m_metrics.m_height != 0))
{
// info->m_bitmapData = bitmapGlyph->bitmap.buffer;
// info->m_bitmapPitch = bitmapGlyph->bitmap.pitch;
info->m_bitmapPitch = bitmapGlyph->bitmap.pitch;
info->m_bitmapData = new unsigned char[info->m_bitmapPitch * info->m_metrics.m_height];
memcpy(info->m_bitmapData, bitmapGlyph->bitmap.buffer, info->m_bitmapPitch * info->m_metrics.m_height);
}
FTC_Node_Unref(node, m_manager);
return make_shared_ptr(info);
}
FT_Error GlyphCacheImpl::RequestFace(FTC_FaceID faceID, FT_Library library, FT_Pointer /*requestData*/, FT_Face * face)

View file

@ -69,6 +69,7 @@ namespace yg
typedef vector<UnicodeBlock> unicode_blocks_t;
unicode_blocks_t m_unicodeBlocks;
unicode_blocks_t::iterator m_lastUsedBlock;
bool m_isDebugging;
typedef vector<shared_ptr<Font> > TFonts;
TFonts m_fonts;
@ -82,6 +83,11 @@ namespace yg
void addFont(char const * fileName);
void addFonts(vector<string> const & fontNames);
int getCharIDX(shared_ptr<Font> const & font, strings::UniChar symbolCode);
pair<Font*, int> const getCharIDX(GlyphKey const & key);
GlyphMetrics const getGlyphMetrics(GlyphKey const & key);
shared_ptr<GlyphInfo> const getGlyphInfo(GlyphKey const & key);
GlyphCacheImpl(GlyphCache::Params const & params);
~GlyphCacheImpl();
};

View file

@ -316,7 +316,8 @@ namespace yg
ResourceManager::GlyphCacheParams::GlyphCacheParams()
: m_glyphCacheMemoryLimit(0),
m_glyphCacheCount(0),
m_renderThreadCount(0)
m_renderThreadCount(0),
m_isDebugging(false)
{}
ResourceManager::GlyphCacheParams::GlyphCacheParams(string const & unicodeBlockFile,
@ -324,13 +325,15 @@ namespace yg
string const & blackListFile,
size_t glyphCacheMemoryLimit,
size_t glyphCacheCount,
size_t renderThreadCount)
size_t renderThreadCount,
bool isDebugging)
: m_unicodeBlockFile(unicodeBlockFile),
m_whiteListFile(whiteListFile),
m_blackListFile(blackListFile),
m_glyphCacheMemoryLimit(glyphCacheMemoryLimit),
m_glyphCacheCount(glyphCacheCount),
m_renderThreadCount(renderThreadCount)
m_renderThreadCount(renderThreadCount),
m_isDebugging(isDebugging)
{}
ResourceManager::Params::Params()
@ -484,7 +487,7 @@ namespace yg
LOG(LDEBUG, ("allocating ", p.m_glyphCacheCount, " glyphCaches, ", p.m_glyphCacheMemoryLimit, " bytes total."));
for (size_t i = 0; i < p.m_glyphCacheCount; ++i)
m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(p.m_unicodeBlockFile, p.m_whiteListFile, p.m_blackListFile, p.m_glyphCacheMemoryLimit / p.m_glyphCacheCount)));
m_glyphCaches.push_back(GlyphCache(GlyphCache::Params(p.m_unicodeBlockFile, p.m_whiteListFile, p.m_blackListFile, p.m_glyphCacheMemoryLimit / p.m_glyphCacheCount, p.m_isDebugging)));
}
else
LOG(LERROR, ("no params to init glyph caches."));

View file

@ -157,13 +157,16 @@ namespace yg
size_t m_glyphCacheCount;
size_t m_renderThreadCount;
bool m_isDebugging;
GlyphCacheParams();
GlyphCacheParams(string const & unicodeBlockFile,
string const & whiteListFile,
string const & blackListFile,
size_t glyphCacheMemoryLimit,
size_t glyphCacheCount,
size_t renderThreadCount);
size_t renderThreadCount,
bool isDebugging = false);
};
struct Params

View file

@ -9,7 +9,8 @@ UNIT_TEST(GlyphCacheTest_Main)
"unicode_blocks.txt",
"fonts_whitelist.txt",
"fonts_blacklist.txt",
200000));
200000,
false));
string const path = GetPlatform().WritableDir();