diff --git a/yg/glyph_cache.cpp b/yg/glyph_cache.cpp index 209eb24944..2ccd3e9b29 100644 --- a/yg/glyph_cache.cpp +++ b/yg/glyph_cache.cpp @@ -14,6 +14,7 @@ #include "../std/vector.hpp" #include "../std/map.hpp" +#include "../base/mutex.hpp" #include @@ -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 GlyphCache::getCharIDX(GlyphKey const & key) { - vector > & 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(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(font), - -1, - 65533 - ); - if (charIDX == 0) - charIDX = FTC_CMapCache_Lookup( - m_impl->m_charMapCache, - reinterpret_cast(font), - -1, - 32 - ); - - return make_pair(font, charIDX); + return m_impl->getCharIDX(key); } GlyphMetrics const GlyphCache::getGlyphMetrics(GlyphKey const & key) { - pair charIDX = getCharIDX(key); - - FTC_ScalerRec fontScaler = - { - reinterpret_cast(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 const GlyphCache::getGlyphInfo(GlyphKey const & key) { - pair charIDX = getCharIDX(key); - - FTC_ScalerRec fontScaler = - { - reinterpret_cast(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 diff --git a/yg/glyph_cache.hpp b/yg/glyph_cache.hpp index 1dc5191081..75e4c907dc 100644 --- a/yg/glyph_cache.hpp +++ b/yg/glyph_cache.hpp @@ -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); }; } diff --git a/yg/glyph_cache_impl.cpp b/yg/glyph_cache_impl.cpp index c04d3da16a..4bbd27bb2c 100644 --- a/yg/glyph_cache_impl.cpp +++ b/yg/glyph_cache_impl.cpp @@ -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 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 = 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 const & font, strings::UniChar symbolCode) + { + if (m_isDebugging) + return 0; + + FTC_FaceID faceID = reinterpret_cast(font.get()); + + return FTC_CMapCache_Lookup( + m_charMapCache, + faceID, + -1, + symbolCode + ); + } + + pair const GlyphCacheImpl::getCharIDX(GlyphKey const & key) + { + if (m_isDebugging) + return make_pair((Font*)0, 0); + + vector > & 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 charIDX = getCharIDX(key); + + FTC_ScalerRec fontScaler = + { + reinterpret_cast(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 const GlyphCacheImpl::getGlyphInfo(GlyphKey const & key) + { + if (m_isDebugging) + { + static bool hasFakeSymbol = false; + static shared_ptr 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 charIDX = getCharIDX(key); + + FTC_ScalerRec fontScaler = + { + reinterpret_cast(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) diff --git a/yg/glyph_cache_impl.hpp b/yg/glyph_cache_impl.hpp index 8d479e9f9f..557d417893 100644 --- a/yg/glyph_cache_impl.hpp +++ b/yg/glyph_cache_impl.hpp @@ -69,6 +69,7 @@ namespace yg typedef vector unicode_blocks_t; unicode_blocks_t m_unicodeBlocks; unicode_blocks_t::iterator m_lastUsedBlock; + bool m_isDebugging; typedef vector > TFonts; TFonts m_fonts; @@ -82,6 +83,11 @@ namespace yg void addFont(char const * fileName); void addFonts(vector const & fontNames); + int getCharIDX(shared_ptr const & font, strings::UniChar symbolCode); + pair const getCharIDX(GlyphKey const & key); + GlyphMetrics const getGlyphMetrics(GlyphKey const & key); + shared_ptr const getGlyphInfo(GlyphKey const & key); + GlyphCacheImpl(GlyphCache::Params const & params); ~GlyphCacheImpl(); }; diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index f0b066f90e..974d919702 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -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.")); diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 18f773c614..e3aecff8ed 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -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 diff --git a/yg/yg_tests/glyph_cache_test.cpp b/yg/yg_tests/glyph_cache_test.cpp index 65e50dcc6f..492b675f91 100644 --- a/yg/yg_tests/glyph_cache_test.cpp +++ b/yg/yg_tests/glyph_cache_test.cpp @@ -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();