From b301b209c17a7a2f65514a9160d703855c1acbc0 Mon Sep 17 00:00:00 2001 From: rachytski Date: Tue, 28 Dec 2010 00:38:46 +0200 Subject: [PATCH] added getGlyphMetrics function. --- yg/glyph_cache.cpp | 95 +++++++++++++++++++++++++++++++++++------ yg/glyph_cache.hpp | 13 +++++- yg/glyph_cache_impl.cpp | 1 + yg/glyph_cache_impl.hpp | 1 + yg/resource_manager.cpp | 5 +++ yg/resource_manager.hpp | 1 + yg/skin_page.cpp | 20 ++++----- 7 files changed, 111 insertions(+), 25 deletions(-) diff --git a/yg/glyph_cache.cpp b/yg/glyph_cache.cpp index 4911881e90..8da91028cd 100644 --- a/yg/glyph_cache.cpp +++ b/yg/glyph_cache.cpp @@ -37,10 +37,12 @@ namespace yg m_impl->m_fonts.push_back(make_shared_ptr(new Font(fileName))); } - shared_ptr const GlyphCache::getGlyph(GlyphKey const & key) + int GlyphCache::getCharIDX(GlyphKey const & key) { Font * font = m_impl->m_fonts.back().get(); + FTC_FaceID faceID = reinterpret_cast(font); + FTC_ScalerRec fontScaler = { faceID, @@ -75,6 +77,67 @@ namespace yg ); } + return charIDX; + } + + GlyphMetrics const GlyphCache::getGlyphMetrics(GlyphKey const & key) + { + Font * font = m_impl->m_fonts.back().get(); + + FTC_FaceID faceID = reinterpret_cast(font); + + FTC_ScalerRec fontScaler = + { + faceID, + key.m_fontSize, + key.m_fontSize, + 1, + 0, + 0 + }; + + int charIDX = getCharIDX(key); + + FT_Glyph glyph = 0; + + FTCHECK(FTC_ImageCache_LookupScaler( + m_impl->m_glyphMetricsCache, + &fontScaler, + FT_LOAD_DEFAULT, + charIDX, + &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 GlyphCache::getGlyph(GlyphKey const & key) + { + Font * font = m_impl->m_fonts.back().get(); + FTC_FaceID faceID = reinterpret_cast(font); + FTC_ScalerRec fontScaler = + { + faceID, + key.m_fontSize, + key.m_fontSize, + 1, + 0, + 0 + }; + + int charIDX = getCharIDX(key); + FT_Glyph glyph = 0; //FTC_Node glyphNode; @@ -97,31 +160,37 @@ namespace yg 0 )); + /// glyph could appear in cache from getGlyphMetrics method, + /// so we should explicitly check this situation +// if (glyph.format == FT_GLYPH_FORMAT_OUTLINE) +// FTCHECK(FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1)); + FT_BitmapGlyph bitmapGlyph = (FT_BitmapGlyph)glyph; shared_ptr info(new GlyphInfo()); - info->m_height = bitmapGlyph ? bitmapGlyph->bitmap.rows : 0; - info->m_width = bitmapGlyph ? bitmapGlyph->bitmap.width : 0; - info->m_xOffset = bitmapGlyph ? bitmapGlyph->left : 0; - info->m_yOffset = bitmapGlyph ? bitmapGlyph->top - info->m_height : 0; - info->m_xAdvance = bitmapGlyph ? int(bitmapGlyph->root.advance.x >> 16) : 0; + 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_isMask ? yg::Color(255, 255, 255, 0) : yg::Color(0, 0, 0, 0); - if ((info->m_width != 0) && (info->m_height != 0)) + if ((info->m_metrics.m_width != 0) && (info->m_metrics.m_height != 0)) { - info->m_bitmap.resize(info->m_width * info->m_height * sizeof(DATA_TRAITS::pixel_t)); + info->m_bitmap.resize(info->m_metrics.m_width * info->m_metrics.m_height * sizeof(DATA_TRAITS::pixel_t)); DATA_TRAITS::view_t dstView = gil::interleaved_view( - info->m_width, - info->m_height, + info->m_metrics.m_width, + info->m_metrics.m_height, (DATA_TRAITS::pixel_t*)&info->m_bitmap[0], - info->m_width * sizeof(DATA_TRAITS::pixel_t) + info->m_metrics.m_width * sizeof(DATA_TRAITS::pixel_t) ); gil::gray8c_view_t srcView = gil::interleaved_view( - info->m_width, - info->m_height, + info->m_metrics.m_width, + info->m_metrics.m_height, (gil::gray8_pixel_t*)bitmapGlyph->bitmap.buffer, bitmapGlyph->bitmap.pitch ); diff --git a/yg/glyph_cache.hpp b/yg/glyph_cache.hpp index de0ed430ff..2f92581372 100644 --- a/yg/glyph_cache.hpp +++ b/yg/glyph_cache.hpp @@ -5,15 +5,20 @@ namespace yg { - struct GlyphInfo + struct GlyphMetrics { int m_xAdvance; + int m_yAdvance; int m_xOffset; int m_yOffset; int m_width; int m_height; - yg::Color m_color; + }; + struct GlyphInfo + { + GlyphMetrics m_metrics; + yg::Color m_color; vector m_bitmap; void dump(char const * fileName); @@ -44,6 +49,10 @@ namespace yg void reset(); void addFont(char const * fileName); + int getCharIDX(GlyphKey const & key); + shared_ptr const getGlyph(GlyphKey const & key); + /// return control box(could be slightly larger than the precise bound box). + GlyphMetrics const getGlyphMetrics(GlyphKey const & key); }; } diff --git a/yg/glyph_cache_impl.cpp b/yg/glyph_cache_impl.cpp index 6b02ea5051..64b5ba9d63 100644 --- a/yg/glyph_cache_impl.cpp +++ b/yg/glyph_cache_impl.cpp @@ -27,6 +27,7 @@ namespace yg FTCHECK(FTC_Manager_New(m_lib, 3, 10, maxSize, &RequestFace, 0, &m_manager)); FTCHECK(FTC_ImageCache_New(m_manager, &m_normalGlyphCache)); + FTCHECK(FTC_ImageCache_New(m_manager, &m_glyphMetricsCache)); /// Initializing stroker FTCHECK(FT_Stroker_New(m_lib, &m_stroker)); diff --git a/yg/glyph_cache_impl.hpp b/yg/glyph_cache_impl.hpp index 6d66acc832..e9a63b2bc8 100644 --- a/yg/glyph_cache_impl.hpp +++ b/yg/glyph_cache_impl.hpp @@ -29,6 +29,7 @@ namespace yg FTC_Manager m_manager; + FTC_ImageCache m_glyphMetricsCache; FTC_ImageCache m_strokedGlyphCache; FTC_ImageCache m_normalGlyphCache; diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index 25a954fa67..bcb9e05a04 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -151,6 +151,11 @@ namespace yg return m_glyphCache.getGlyph(key); } + GlyphMetrics const ResourceManager::getGlyphMetrics(GlyphKey const & key) + { + return m_glyphCache.getGlyphMetrics(key); + } + void ResourceManager::addFont(char const * fileName) { m_glyphCache.addFont(fileName); diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index b9f61f6c8d..ec67eb85ea 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -61,6 +61,7 @@ namespace yg void freeTexture(shared_ptr const & texture, bool doSignal = false); shared_ptr const getGlyph(GlyphKey const & key); + GlyphMetrics const getGlyphMetrics(GlyphKey const & key); void addFont(char const * fileName); }; diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index 1bb35df262..d66ed9995f 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -178,8 +178,8 @@ namespace yg shared_ptr gi = m_resourceManager->getGlyph(g); - m2::Packer::handle_t handle = m_packer.pack(gi->m_width + 4, - gi->m_height + 4); + m2::Packer::handle_t handle = m_packer.pack(gi->m_metrics.m_width + 4, + gi->m_metrics.m_height + 4); m2::RectU texRect = m_packer.find(handle).second; m_glyphUploadCommands.push_back(GlyphUploadCmd(gi, texRect)); @@ -188,9 +188,9 @@ namespace yg m_styles[handle] = boost::shared_ptr( new CharStyle(texRect, m_pageID, - gi->m_xOffset, - gi->m_yOffset, - gi->m_xAdvance)); + gi->m_metrics.m_xOffset, + gi->m_metrics.m_yOffset, + gi->m_metrics.m_xAdvance)); return m_glyphMap[g]; } @@ -198,7 +198,7 @@ namespace yg bool SkinPage::hasRoom(GlyphKey const & gk) const { shared_ptr gi = m_resourceManager->getGlyph(gk); - return m_packer.hasRoom(gi->m_width + 4, gi->m_height + 4); + return m_packer.hasRoom(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4); } @@ -379,13 +379,13 @@ namespace yg v(rect.SizeX() - 1, y) = pxTranslucent; } - if ((gi->m_width != 0) && (gi->m_height != 0)) + if ((gi->m_metrics.m_width != 0) && (gi->m_metrics.m_height != 0)) { TDynamicTexture::const_view_t srcView = gil::interleaved_view( - gi->m_width, - gi->m_height, + gi->m_metrics.m_width, + gi->m_metrics.m_height, (TDynamicTexture::pixel_t*)&gi->m_bitmap[0], - gi->m_width * sizeof(TDynamicTexture::pixel_t) + gi->m_metrics.m_width * sizeof(TDynamicTexture::pixel_t) ); for (size_t y = 2; y < rect.SizeY() - 2; ++y)