diff options
author | rachytski <siarhei.rachytski@gmail.com> | 2011-06-12 19:48:45 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:19:37 +0300 |
commit | 9e73efd60264e878375ae08b8767307d17544d27 (patch) | |
tree | f763ff6e5c2859643f922c7082acff3e567329da | |
parent | a081d2e5c2d5a24c4e8822f3cdd06e2ac09cfbca (diff) |
introduced separate information layer class, which will perform all POI and Text layout.
-rw-r--r-- | geometry/point2d.hpp | 9 | ||||
-rw-r--r-- | geometry/tree4d.hpp | 13 | ||||
-rw-r--r-- | map/framework.cpp | 5 | ||||
-rw-r--r-- | map/information_display.cpp | 38 | ||||
-rw-r--r-- | map/information_display.hpp | 3 | ||||
-rw-r--r-- | map/render_queue_routine.cpp | 20 | ||||
-rw-r--r-- | yg/glyph_cache.hpp | 2 | ||||
-rw-r--r-- | yg/glyph_cache_impl.hpp | 14 | ||||
-rw-r--r-- | yg/info_layer.cpp | 129 | ||||
-rw-r--r-- | yg/info_layer.hpp | 49 | ||||
-rw-r--r-- | yg/render_state.cpp | 5 | ||||
-rw-r--r-- | yg/render_state.hpp | 6 | ||||
-rw-r--r-- | yg/render_state_updater.cpp | 5 | ||||
-rw-r--r-- | yg/resource_manager.cpp | 2 | ||||
-rw-r--r-- | yg/resource_manager.hpp | 2 | ||||
-rw-r--r-- | yg/skin_page.cpp | 4 | ||||
-rw-r--r-- | yg/text_element.cpp | 37 | ||||
-rw-r--r-- | yg/text_element.hpp | 14 | ||||
-rw-r--r-- | yg/text_renderer.cpp | 282 | ||||
-rw-r--r-- | yg/text_renderer.hpp | 61 | ||||
-rw-r--r-- | yg/yg.pro | 6 | ||||
-rw-r--r-- | yg/yg_tests/screengl_test.cpp | 4 |
22 files changed, 316 insertions, 394 deletions
diff --git a/geometry/point2d.hpp b/geometry/point2d.hpp index 503b52bd55..0d5fe6e3f2 100644 --- a/geometry/point2d.hpp +++ b/geometry/point2d.hpp @@ -192,6 +192,15 @@ namespace m2 } template <typename T> + Point<T> const Floor(Point<T> const & pt) + { + Point<T> res; + res.x = floor(pt.x); + res.y = floor(pt.y); + return res; + } + + template <typename T> bool IsPointStrictlyInsideTriangle(Point<T> const & p, Point<T> const & a, Point<T> const & b, Point<T> const & c) { diff --git a/geometry/tree4d.hpp b/geometry/tree4d.hpp index fa3c9de3b7..ed3666cb2a 100644 --- a/geometry/tree4d.hpp +++ b/geometry/tree4d.hpp @@ -10,7 +10,16 @@ namespace m4 { - template <class T> + template <typename T> + struct Traits + { + m2::RectD const LimitRect(T const & t) + { + return t.GetLimitRect(); + } + }; + + template <class T, typename Traits = Traits<T> > class Tree { struct value_t @@ -139,7 +148,7 @@ namespace m4 template <class TCompare> void ReplaceIf(T const & obj, TCompare comp) { - ReplaceIf(obj, obj.GetLimitRect(), comp); + ReplaceIf(obj, Traits::LimitRect(obj), comp); } template <class ToDo> diff --git a/map/framework.cpp b/map/framework.cpp index 3db3b89737..5a28eb2359 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -26,6 +26,7 @@ #include "../version/version.hpp" #include "../yg/internal/opengl.hpp" +#include "../yg/info_layer.hpp" using namespace feature; @@ -883,6 +884,10 @@ void FrameWork<TModel>::AddRedrawCommandSure() m_informationDisplay.doDraw(pDrawer); + m_renderQueue.renderState().m_actualInfoLayer->draw( + pDrawer->screen().get(), + m_renderQueue.renderState().m_actualScreen.PtoGMatrix() * currentScreen.GtoPMatrix()); + m_locationState.DrawMyPosition(*pDrawer, m_navigator.Screen()); e->drawer()->screen()->endFrame(); diff --git a/map/information_display.cpp b/map/information_display.cpp index fdfee16ffb..7fdee898af 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -30,6 +30,9 @@ InformationDisplay::InformationDisplay() for (int i = 0; i < sizeof(m_DebugPts) / sizeof(m2::PointD); ++i) m_DebugPts[i] = m2::PointD(0, 0); + + m_fontDesc = yg::FontDesc(false, 12); + m_emptyMessageFont = yg::FontDesc(false, 14); } void InformationDisplay::setScreen(ScreenBase const & screen) @@ -163,10 +166,8 @@ void InformationDisplay::drawRuler(DrawerYG * pDrawer) pDrawer->screen()->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)), yg::maxDepth); - yg::FontDesc fontDesc = yg::FontDesc::defaultFont; - // m2::RectD textRect = pDrawer->screen()->textRect(fontDesc, scalerText.c_str(), false); - pDrawer->screen()->drawText(fontDesc, + pDrawer->screen()->drawText(m_fontDesc, scalerPts[1] + m2::PointD(7, -7), yg::EPosAboveRight, 0, @@ -190,6 +191,9 @@ void InformationDisplay::drawRuler(DrawerYG * pDrawer) void InformationDisplay::setVisualScale(double visualScale) { m_visualScale = visualScale; + + m_fontDesc.m_size = 12 * visualScale; + m_emptyMessageFont.m_size = 14 * visualScale; } void InformationDisplay::enableCenter(bool doEnable) @@ -211,7 +215,7 @@ void InformationDisplay::drawCenter(DrawerYG * drawer) yg::StraightTextElement::Params params; params.m_depth = yg::maxDepth; - params.m_fontDesc = yg::FontDesc::defaultFont; + params.m_fontDesc = m_fontDesc; params.m_log2vis = false; params.m_pivot = m2::PointD(m_displayRect.maxX() - 10 * m_visualScale, m_displayRect.maxY() - (m_bottomShift + 10) * m_visualScale - 5); @@ -229,7 +233,7 @@ void InformationDisplay::drawCenter(DrawerYG * drawer) yg::Color(187, 187, 187, 128), yg::maxDepth - 1); - ste.draw(drawer->screen().get()); + ste.draw(drawer->screen().get(), math::Identity<double, 3>()); } void InformationDisplay::enableGlobalRect(bool doEnable) @@ -248,7 +252,7 @@ void InformationDisplay::drawGlobalRect(DrawerYG *pDrawer) ostringstream out; out << "(" << m_globalRect.minX() << ", " << m_globalRect.minY() << ", " << m_globalRect.maxX() << ", " << m_globalRect.maxY() << ") Scale : " << m_currentScale; pDrawer->screen()->drawText( - yg::FontDesc::defaultFont, + m_fontDesc, m2::PointD(m_displayRect.minX() + 10, m_displayRect.minY() + m_yOffset), yg::EPosAboveRight, 0, @@ -281,7 +285,7 @@ void InformationDisplay::drawDebugInfo(DrawerYG * drawer) m2::PointD pos = m2::PointD(m_displayRect.minX() + 10, m_displayRect.minY() + m_yOffset); - drawer->screen()->drawText(yg::FontDesc::defaultFont, + drawer->screen()->drawText(m_fontDesc, pos, yg::EPosAboveRight, 0, @@ -309,7 +313,7 @@ void InformationDisplay::drawMemoryWarning(DrawerYG * drawer) ostringstream out; out << "MemoryWarning : " << m_lastMemoryWarning.ElapsedSeconds() << " sec. ago."; - drawer->screen()->drawText(yg::FontDesc::defaultFont, + drawer->screen()->drawText(m_fontDesc, pos, yg::EPosAboveRight, 0, @@ -381,7 +385,7 @@ void InformationDisplay::drawLog(DrawerYG * drawer) yg::StraightTextElement::Params params; params.m_depth = yg::maxDepth; - params.m_fontDesc = yg::FontDesc::defaultFont; + params.m_fontDesc = m_fontDesc; params.m_log2vis = false; params.m_pivot = startPt; params.m_position = yg::EPosAboveRight; @@ -397,7 +401,7 @@ void InformationDisplay::drawLog(DrawerYG * drawer) yg::maxDepth - 1 ); - ste.draw(drawer->screen().get()); + ste.draw(drawer->screen().get(), math::Identity<double, 3>()); } } @@ -420,7 +424,7 @@ void InformationDisplay::drawEmptyModelMessage(DrawerYG * pDrawer) yg::StraightTextElement::Params params; params.m_depth = yg::maxDepth; - params.m_fontDesc = yg::FontDesc::defaultFont; + params.m_fontDesc = m_emptyMessageFont; params.m_log2vis = false; params.m_pivot = pt; params.m_position = yg::EPosCenter; @@ -432,28 +436,28 @@ void InformationDisplay::drawEmptyModelMessage(DrawerYG * pDrawer) yg::StraightTextElement ste0(params); ste0.offset(m2::PointD(0, -ste0.boundRect().GetGlobalRect().SizeY() - 5)); - ste0.draw(pDrawer->screen().get()); + ste0.draw(pDrawer->screen().get(), math::Identity<double, 3>()); params.m_pivot = pt; params.m_logText = strings::FromUtf8(s1); params.m_utf8Text = s1; yg::StraightTextElement ste1(params); - ste1.draw(pDrawer->screen().get()); + ste1.draw(pDrawer->screen().get(), math::Identity<double, 3>()); params.m_pivot.y += ste1.boundRect().GetGlobalRect().SizeY() + 5; params.m_logText = strings::FromUtf8(s2); params.m_utf8Text = s2; yg::StraightTextElement ste2(params); - ste2.draw(pDrawer->screen().get()); + ste2.draw(pDrawer->screen().get(), math::Identity<double, 3>()); params.m_pivot.y += ste2.boundRect().GetGlobalRect().SizeY() + 5; params.m_logText = strings::FromUtf8(s3); params.m_utf8Text = s3; yg::StraightTextElement ste3(params); - ste3.draw(pDrawer->screen().get()); + ste3.draw(pDrawer->screen().get(), math::Identity<double, 3>()); } #endif @@ -490,7 +494,7 @@ void InformationDisplay::drawBenchmarkInfo(DrawerYG * pDrawer) { m_yOffset += 20; m2::PointD pos(m_displayRect.minX() + 10, m_displayRect.minY() + m_yOffset); - pDrawer->screen()->drawText(yg::FontDesc::defaultFont, + pDrawer->screen()->drawText(m_fontDesc, pos, yg::EPosAboveRight, 0, @@ -510,7 +514,7 @@ void InformationDisplay::drawBenchmarkInfo(DrawerYG * pDrawer) << "), duration : " << m_benchmarkInfo[i].m_duration; m_yOffset += 20; pos.y += 20; - pDrawer->screen()->drawText(yg::FontDesc::defaultFont, + pDrawer->screen()->drawText(m_fontDesc, pos, yg::EPosAboveRight, 0, diff --git a/map/information_display.hpp b/map/information_display.hpp index baab4d5761..a44c8a3b1a 100644 --- a/map/information_display.hpp +++ b/map/information_display.hpp @@ -20,6 +20,9 @@ class InformationDisplay { private: + yg::FontDesc m_fontDesc; + yg::FontDesc m_emptyMessageFont; + ScreenBase m_screen; m2::RectI m_displayRect; int m_yOffset; diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 7266330fd8..e7d8e02a46 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -14,6 +14,7 @@ #include "../yg/pen_info.hpp" #include "../yg/skin.hpp" #include "../yg/base_texture.hpp" +#include "../yg/info_layer.hpp" #include "../indexer/scales.hpp" @@ -238,9 +239,6 @@ void RenderQueueRoutine::Do() params.m_renderState = m_renderState; params.m_doPeriodicalUpdate = m_doPeriodicalUpdate; params.m_updateInterval = m_updateInterval; - params.m_textTreeAutoClean = false; - params.m_useTextTree = true; - params.m_doPeriodicalTextUpdate = false; /* params.m_isDebugging = true; params.m_drawPathes = false; params.m_drawAreas = false; @@ -324,7 +322,8 @@ void RenderQueueRoutine::Do() areas.clear(); areas.push_back(curRect); fullRectRepaint = true; - m_threadDrawer->screen()->clearTextTree(); + m_renderState->m_currentInfoLayer->clear(); + m_renderState->m_actualInfoLayer->clear(); m_renderState->m_doRepaintAll = false; } else @@ -349,12 +348,17 @@ void RenderQueueRoutine::Do() if (!redrawTextRect.Intersect(oldRect)) redrawTextRect = m2::RectD(0, 0, 0, 0); - m_threadDrawer->screen()->offsetTextTree( - m_renderState->m_currentScreen.GtoP(prevScreen.PtoG(m2::PointD(0, 0))), + m2::PointD offs(m_renderState->m_currentScreen.GtoP(prevScreen.PtoG(m2::PointD(0, 0)))); + + m_renderState->m_currentInfoLayer->offset( + offs, redrawTextRect); } else - m_threadDrawer->screen()->clearTextTree(); + { + m_renderState->m_currentInfoLayer->clear(); + m_renderState->m_actualInfoLayer->clear(); + } } } @@ -384,7 +388,7 @@ void RenderQueueRoutine::Do() m_renderState->m_currentScreen); } - m_threadDrawer->screen()->setNeedTextRedraw(isPanning); +// m_threadDrawer->screen()->setNeedTextRedraw(isPanning); ScreenBase const & frameScreen = m_currentRenderCommand->m_frameScreen; m2::RectD glbRect; diff --git a/yg/glyph_cache.hpp b/yg/glyph_cache.hpp index 4f025c3c1a..f0324e81fe 100644 --- a/yg/glyph_cache.hpp +++ b/yg/glyph_cache.hpp @@ -11,6 +11,7 @@ namespace yg { + /// glyph metrics struct GlyphMetrics { int m_xAdvance; @@ -21,6 +22,7 @@ namespace yg int m_height; }; + /// full info about single glyph struct GlyphInfo { GlyphMetrics m_metrics; diff --git a/yg/glyph_cache_impl.hpp b/yg/glyph_cache_impl.hpp index 2ddbacd4bd..edeb4b7426 100644 --- a/yg/glyph_cache_impl.hpp +++ b/yg/glyph_cache_impl.hpp @@ -32,7 +32,7 @@ namespace yg { string m_name; - /// @{ Font Tuning + /// @{ font matching tuning /// whitelist has priority over the blacklist in case of duplicates. /// this fonts are promoted to the top of the font list for this block. vector<string> m_whitelist; @@ -54,15 +54,15 @@ namespace yg struct GlyphCacheImpl { FT_Library m_lib; - FT_Stroker m_stroker; + FT_Stroker m_stroker; //< stroker, used to produce stroked glyph outlines - FTC_Manager m_manager; + FTC_Manager m_manager; //< freetype cache manager for all caches - FTC_ImageCache m_glyphMetricsCache; - FTC_ImageCache m_strokedGlyphCache; - FTC_ImageCache m_normalGlyphCache; + FTC_ImageCache m_glyphMetricsCache; //< glyph metrics cache + FTC_ImageCache m_strokedGlyphCache; //< cache of stroked glyph images + FTC_ImageCache m_normalGlyphCache; //< cache of normal glyph images - FTC_CMapCache m_charMapCache; + FTC_CMapCache m_charMapCache; //< cache of glyphID -> glyphIdx mapping typedef vector<UnicodeBlock> unicode_blocks_t; unicode_blocks_t m_unicodeBlocks; diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp new file mode 100644 index 0000000000..1c8148e4d8 --- /dev/null +++ b/yg/info_layer.cpp @@ -0,0 +1,129 @@ +#include "../base/SRC_FIRST.hpp" + +#include "info_layer.hpp" +#include "text_element.hpp" + +#include "../std/bind.hpp" + +namespace yg +{ + m2::RectD const StraightTextElementTraits::LimitRect(StraightTextElement const & elem) + { + return elem.boundRect().GetGlobalRect(); + } + + bool InfoLayer::better_text(StraightTextElement const & r1, StraightTextElement const & r2) + { + if (r1.fontDesc() != r2.fontDesc()) + return r1.fontDesc() > r2.fontDesc(); + if (r1.depth() != r2.depth()) + return r1.depth() > r2.depth(); + return false; + } + + void InfoLayer::draw(gl::TextRenderer *r, math::Matrix<double, 3, 3> const & m) + { + m_tree.ForEach(bind(&StraightTextElement::draw, _1, r, m)); + + list<string> toErase; + + for (path_text_elements::const_iterator it = m_pathTexts.begin(); it != m_pathTexts.end(); ++it) + { + list<PathTextElement> const & l = it->second; + + for (list<PathTextElement>::const_iterator j = l.begin(); j != l.end(); ++j) + j->draw(r, m); + + if (l.empty()) + toErase.push_back(it->first); + } + + for (list<string>::const_iterator it = toErase.begin(); it != toErase.end(); ++it) + m_pathTexts.erase(*it); + } + + void InfoLayer::offsetTextTree(m2::PointD const & offs, m2::RectD const & rect) + { + vector<StraightTextElement> texts; + m_tree.ForEach(MakeBackInsertFunctor(texts)); + m_tree.Clear(); + for (vector<StraightTextElement>::iterator it = texts.begin(); it != texts.end(); ++it) + { + it->offset(offs); + if (it->boundRect().GetGlobalRect().IsIntersect(rect)) + m_tree.Add(*it, it->boundRect().GetGlobalRect()); + } + } + + void InfoLayer::offsetPathTexts(m2::PointD const & offs, m2::RectD const & rect) + { + m2::AARectD aaRect(rect); + + path_text_elements newPathTexts; + + for (path_text_elements::iterator i = m_pathTexts.begin(); i != m_pathTexts.end(); ++i) + { + list<PathTextElement> & l = i->second; + list<PathTextElement>::iterator it = l.begin(); + bool isEmpty = true; + while (it != l.end()) + { + it->offset(offs); + m2::AARectD const & r = it->boundRect(); + if (!aaRect.IsIntersect(r) && !aaRect.IsRectInside(r)) + { + list<PathTextElement>::iterator tempIt = it; + ++tempIt; + l.erase(it); + it = tempIt; + } + else + { + isEmpty = false; + ++it; + } + } + + if (!isEmpty) + newPathTexts[i->first] = l; + } + + /// to clear an empty elements from the map. + m_pathTexts = newPathTexts; + } + + void InfoLayer::offset(m2::PointD const & offs, m2::RectD const & rect) + { + offsetTextTree(offs, rect); + offsetPathTexts(offs, rect); + } + + void InfoLayer::clear() + { + m_tree.Clear(); + m_pathTexts.clear(); + } + + void InfoLayer::addStraightText(StraightTextElement const & ste) + { + m_tree.ReplaceIf(ste, ste.boundRect().GetGlobalRect(), &better_text); + } + + void InfoLayer::addPathText(PathTextElement const & pte) + { + list<PathTextElement> & l = m_pathTexts[pte.utf8Text()]; + + bool doAppend = true; + + for (list<PathTextElement>::const_iterator it = l.begin(); it != l.end(); ++it) + if (it->boundRect().IsIntersect(pte.boundRect())) + { + doAppend = false; + break; + } + + if (doAppend) + l.push_back(pte); + } +} + diff --git a/yg/info_layer.hpp b/yg/info_layer.hpp new file mode 100644 index 0000000000..f05e4397ae --- /dev/null +++ b/yg/info_layer.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "text_element.hpp" + +#include "../geometry/rect2d.hpp" +#include "../geometry/point2d.hpp" +#include "../geometry/tree4d.hpp" + +#include "../std/map.hpp" +#include "../std/list.hpp" + +namespace yg +{ + namespace gl + { + class TextRenderer; + } + + struct StraightTextElementTraits + { + static m2::RectD const LimitRect(StraightTextElement const & elem); + }; + + class InfoLayer + { + private: + + static bool better_text(StraightTextElement const & r1, StraightTextElement const & r2); + + m4::Tree<StraightTextElement, StraightTextElementTraits> m_tree; + typedef map<string, list<PathTextElement> > path_text_elements; + path_text_elements m_pathTexts; + + void offsetPathTexts(m2::PointD const & offs, m2::RectD const & rect); + void offsetTextTree(m2::PointD const & offs, m2::RectD const & rect); + + public: + + void draw(gl::TextRenderer * r, math::Matrix<double, 3, 3> const & m); + + void addPathText(PathTextElement const & pte); + + void addStraightText(StraightTextElement const & ste); + + void offset(m2::PointD const & offs, m2::RectD const & rect); + + void clear(); + }; +} diff --git a/yg/render_state.cpp b/yg/render_state.cpp index 529053f000..8fcdb5a167 100644 --- a/yg/render_state.cpp +++ b/yg/render_state.cpp @@ -3,13 +3,16 @@ #include "render_state.hpp" #include "renderbuffer.hpp" +#include "info_layer.hpp" namespace yg { namespace gl { RenderState::RenderState() - : m_isEmptyModelActual(false), + : m_actualInfoLayer(new yg::InfoLayer()), + m_isEmptyModelActual(false), + m_currentInfoLayer(new yg::InfoLayer()), m_backBufferLayers(1), m_isEmptyModelCurrent(false), m_isResized(false), diff --git a/yg/render_state.hpp b/yg/render_state.hpp index d2bd1bc8ff..a6211898ff 100644 --- a/yg/render_state.hpp +++ b/yg/render_state.hpp @@ -10,6 +10,8 @@ namespace yg { + class InfoLayer; + namespace gl { class BaseTexture; @@ -25,6 +27,8 @@ namespace yg /// @{ /// Bitmap shared_ptr<BaseTexture> m_actualTarget; + /// Information layer + shared_ptr<yg::InfoLayer> m_actualInfoLayer; /// Screen parameters ScreenBase m_actualScreen; /// Empty-model flag @@ -35,6 +39,8 @@ namespace yg /// @{ /// Screen of the rendering operation in progress. ScreenBase m_currentScreen; + /// information layer + shared_ptr<yg::InfoLayer> m_currentInfoLayer; /// at least one backBuffer layer vector<shared_ptr<BaseTexture> > m_backBufferLayers; /// depth buffer used for rendering diff --git a/yg/render_state_updater.cpp b/yg/render_state_updater.cpp index def84de159..ae32028f44 100644 --- a/yg/render_state_updater.cpp +++ b/yg/render_state_updater.cpp @@ -3,6 +3,7 @@ #include "framebuffer.hpp" #include "internal/opengl.hpp" #include "base_texture.hpp" +#include "info_layer.hpp" #include "../base/logging.hpp" @@ -54,9 +55,13 @@ namespace yg { threads::MutexGuard guard(*m_renderState->m_mutex.get()); swap(m_renderState->m_actualTarget, m_renderState->m_backBufferLayers.front()); + swap(m_renderState->m_actualInfoLayer, m_renderState->m_currentInfoLayer); m_renderState->m_actualScreen = m_renderState->m_currentScreen; } + /// copying info layer + *m_renderState->m_currentInfoLayer.get() = *m_renderState->m_actualInfoLayer.get(); + /// blitting will be performed through /// non-multisampled framebuffer for the sake of speed diff --git a/yg/resource_manager.cpp b/yg/resource_manager.cpp index a857b568fc..29f2d93f3e 100644 --- a/yg/resource_manager.cpp +++ b/yg/resource_manager.cpp @@ -197,7 +197,7 @@ namespace yg } } - shared_ptr<GlyphInfo> const ResourceManager::getGlyph(GlyphKey const & key) + shared_ptr<GlyphInfo> const ResourceManager::getGlyphInfo(GlyphKey const & key) { return m_glyphCache.getGlyph(key); } diff --git a/yg/resource_manager.hpp b/yg/resource_manager.hpp index 869913fa69..ae3287ff1c 100644 --- a/yg/resource_manager.hpp +++ b/yg/resource_manager.hpp @@ -94,7 +94,7 @@ namespace yg size_t textureWidth() const; size_t textureHeight() const; - shared_ptr<GlyphInfo> const getGlyph(GlyphKey const & key); + shared_ptr<GlyphInfo> const getGlyphInfo(GlyphKey const & key); GlyphMetrics const getGlyphMetrics(GlyphKey const & key); GlyphCache * getGlyphCache(); diff --git a/yg/skin_page.cpp b/yg/skin_page.cpp index 902effb596..c9e2930d11 100644 --- a/yg/skin_page.cpp +++ b/yg/skin_page.cpp @@ -250,7 +250,7 @@ namespace yg if (foundHandle != m_packer.invalidHandle()) return foundHandle; - shared_ptr<GlyphInfo> gi = m_resourceManager->getGlyph(g); + shared_ptr<GlyphInfo> gi = m_resourceManager->getGlyphInfo(g); m2::Packer::handle_t handle = m_packer.pack(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4); @@ -271,7 +271,7 @@ namespace yg bool SkinPage::hasRoom(GlyphKey const & gk) const { - shared_ptr<GlyphInfo> gi = m_resourceManager->getGlyph(gk); + shared_ptr<GlyphInfo> gi = m_resourceManager->getGlyphInfo(gk); return m_packer.hasRoom(gi->m_metrics.m_width + 4, gi->m_metrics.m_height + 4); } diff --git a/yg/text_element.cpp b/yg/text_element.cpp index 85697bc9e3..6c3d0734f6 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -64,7 +64,8 @@ namespace yg m_logText(p.m_logText), m_log2vis(p.m_log2vis), m_rm(p.m_rm), - m_skin(p.m_skin) + m_skin(p.m_skin), + m_utf8Text(p.m_utf8Text) { if (m_log2vis) m_visText = log2vis(m_logText); @@ -82,16 +83,24 @@ namespace yg return m_visText; } + string const & TextElement::utf8Text() const + { + return m_utf8Text; + } + FontDesc const & TextElement::fontDesc() const { return m_fontDesc; } - void TextElement::drawTextImpl(GlyphLayout const & layout, gl::TextRenderer * screen, FontDesc const & fontDesc, double depth) const + void TextElement::drawTextImpl(GlyphLayout const & layout, gl::TextRenderer * screen, math::Matrix<double, 3, 3> const & m, FontDesc const & fontDesc, double depth) const { - if (layout.lastVisible() != visText().size()) + if ((layout.lastVisible() != visText().size()) && (layout.firstVisible() != 0)) return; + m2::PointD pivot = layout.entries()[0].m_pt; + m2::PointD offset = pivot * m - pivot; + for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) { shared_ptr<Skin> const & skin = screen->skin(); @@ -100,7 +109,7 @@ namespace yg uint32_t const glyphID = skin->mapGlyph(glyphKey, fontDesc.m_isStatic); CharStyle const * charStyle = static_cast<CharStyle const *>(skin->fromID(glyphID)); - screen->drawGlyph(elem.m_pt, m2::PointD(0.0, 0.0), elem.m_angle, 0, charStyle, depth); + screen->drawGlyph(elem.m_pt + offset, m2::PointD(0.0, 0.0), elem.m_angle, 0, charStyle, depth); } } @@ -120,22 +129,22 @@ namespace yg return m2::AARectD(m_glyphLayout.limitRect()); } - void StraightTextElement::draw(gl::TextRenderer * screen) const + void StraightTextElement::draw(gl::TextRenderer * screen, math::Matrix<double, 3, 3> const & m) const { yg::FontDesc desc = m_fontDesc; if (m_fontDesc.m_isMasked) { - drawTextImpl(m_glyphLayout, screen, m_fontDesc, yg::maxDepth); + drawTextImpl(m_glyphLayout, screen, m, m_fontDesc, yg::maxDepth); desc.m_isMasked = false; } - drawTextImpl(m_glyphLayout, screen, desc, yg::maxDepth); + drawTextImpl(m_glyphLayout, screen, m, desc, yg::maxDepth); } - void StraightTextElement::draw(gl::Screen * screen) const +/* void StraightTextElement::draw(gl::Screen * screen) const { draw((gl::TextRenderer*)screen); - } + }*/ void StraightTextElement::offset(m2::PointD const & offs) { @@ -161,22 +170,22 @@ namespace yg return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(40, 2)); } - void PathTextElement::draw(gl::TextRenderer * screen) const + void PathTextElement::draw(gl::TextRenderer * screen, math::Matrix<double, 3, 3> const & m) const { yg::FontDesc desc = m_fontDesc; if (m_fontDesc.m_isMasked) { - drawTextImpl(m_glyphLayout, screen, m_fontDesc, depth()); + drawTextImpl(m_glyphLayout, screen, m, m_fontDesc, depth()); desc.m_isMasked = false; } - drawTextImpl(m_glyphLayout, screen, desc, depth()); + drawTextImpl(m_glyphLayout, screen, m, desc, depth()); } - void PathTextElement::draw(gl::Screen * screen) const +/* void PathTextElement::draw(gl::Screen * screen) const { draw((gl::TextRenderer*)screen); - } + }*/ void PathTextElement::offset(m2::PointD const & offs) { diff --git a/yg/text_element.hpp b/yg/text_element.hpp index c1e9d9e950..82c3c61c20 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -2,6 +2,8 @@ #include "../base/string_utils.hpp" +#include "../base/matrix.hpp" + #include "../geometry/point2d.hpp" #include "../geometry/rect2d.hpp" #include "../geometry/aa_rect2d.hpp" @@ -44,7 +46,7 @@ namespace yg virtual void offset(m2::PointD const & offs) = 0; virtual m2::AARectD const boundRect() const = 0; - virtual void draw(gl::Screen * screen) const = 0; +// virtual void draw(gl::Screen * screen) const = 0; m2::PointD const & pivot() const; void setPivot(m2::PointD const & pv); @@ -75,7 +77,7 @@ namespace yg struct Params : OverlayElement::Params { FontDesc m_fontDesc; - strings::UniString m_logText; + wstring m_logText; bool m_log2vis; ResourceManager * m_rm; Skin * m_skin; @@ -103,8 +105,8 @@ namespace yg StraightTextElement(Params const & p); m2::AARectD const boundRect() const; - void draw(gl::Screen * screen) const; - void draw(gl::TextRenderer * screen) const; +// void draw(gl::Screen * screen) const; + void draw(gl::TextRenderer * screen, math::Matrix<double, 3, 3> const & m) const; void offset(m2::PointD const & offs); }; @@ -127,8 +129,8 @@ namespace yg PathTextElement(Params const & p); m2::AARectD const boundRect() const; - void draw(gl::Screen * screen) const; - void draw(gl::TextRenderer * screen) const; +// void draw(gl::Screen * screen) const; + void draw(gl::TextRenderer * screen, math::Matrix<double, 3, 3> const & m) const; void offset(m2::PointD const & offs); }; } diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index 6eefa427e3..123b46d35a 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -1,19 +1,14 @@ -#include "defines.hpp" #include "text_renderer.hpp" -#include "resource_manager.hpp" -#include "skin.hpp" #include "render_state.hpp" -#include "glyph_layout.hpp" +#include "info_layer.hpp" #include "resource_style.hpp" +#include "resource_manager.hpp" #include "../geometry/angles.hpp" #include "../std/bind.hpp" - #include "../base/string_utils.hpp" -#include "../base/logging.hpp" -#include "../base/stl_add.hpp" namespace yg @@ -22,78 +17,14 @@ namespace yg { TextRenderer::Params::Params() - : m_textTreeAutoClean(true), - m_useTextTree(false), - m_drawTexts(true), - m_doPeriodicalTextUpdate(false) + : m_drawTexts(true) {} TextRenderer::TextRenderer(Params const & params) : base_t(params), - m_needTextRedraw(false), - m_textTreeAutoClean(params.m_textTreeAutoClean), - m_useTextTree(params.m_useTextTree), - m_drawTexts(params.m_drawTexts), - m_doPeriodicalTextUpdate(params.m_doPeriodicalTextUpdate) + m_drawTexts(params.m_drawTexts) {} - TextRenderer::TextObj::TextObj(StraightTextElement const & elem) - : m_elem(elem), m_needRedraw(true), m_frozen(false) - { - } - - void TextRenderer::TextObj::Draw(TextRenderer * pTextRenderer) const - { - /// this value is assigned inside offsetTextRect function to the texts which completely - /// lies inside the testing rect and therefore should be skipped. - if (m_needRedraw) - { - m_elem.draw(pTextRenderer); - m_frozen = true; - } - } - - m2::RectD const TextRenderer::TextObj::GetLimitRect(TextRenderer* pTextRenderer) const - { - return m_elem.boundRect().GetGlobalRect(); - } - - void TextRenderer::TextObj::SetNeedRedraw(bool flag) const - { - m_needRedraw = flag; - } - - bool TextRenderer::TextObj::IsNeedRedraw() const - { - return m_needRedraw; - } - - bool TextRenderer::TextObj::IsFrozen() const - { - return m_frozen; - } - -/* string const & TextRenderer::TextObj::Text() const - { - return m_utf8Text; - } -*/ - void TextRenderer::TextObj::Offset(m2::PointD const & offs) - { - m_elem.offset(offs); - } - - bool TextRenderer::TextObj::better_text(TextObj const & r1, TextObj const & r2) - { - // any text is worse than a frozen one, - // because frozen texts shouldn't be popped out by newly arrived texts. - if (r2.m_frozen) - return false; - if (r1.m_elem.fontDesc() != r2.m_elem.fontDesc()) - return r1.m_elem.fontDesc() > r2.m_elem.fontDesc(); - return (r1.m_elem.depth() > r2.m_elem.depth()); - } - void TextRenderer::drawText(FontDesc const & fontDesc, m2::PointD const & pt, yg::EPosition pos, @@ -117,178 +48,10 @@ namespace yg StraightTextElement ste(params); - if (!m_useTextTree || fontDesc.m_isStatic) - ste.draw(this); + if (!renderState().get() || fontDesc.m_isStatic) + ste.draw(this, math::Identity<double, 3>()); else - { - checkTextRedraw(); - TextObj obj(ste); - m2::RectD r = obj.GetLimitRect(this); - m_tree.ReplaceIf(obj, r, &TextObj::better_text); - } - } - - void TextRenderer::checkTextRedraw() - { - ASSERT(m_useTextTree, ()); - if (m_needTextRedraw) - { - m_needTextRedraw = false; - m_tree.ForEach(bind(&TextObj::Draw, _1, this)); - /// flushing only texts - base_t::flush(skin()->currentTextPage()); - } - } - - void TextRenderer::setClipRect(m2::RectI const & rect) - { - if (m_useTextTree) - { - bool needTextRedraw = m_needTextRedraw; - checkTextRedraw(); - base_t::setClipRect(rect); - setNeedTextRedraw(needTextRedraw); - } - else - base_t::setClipRect(rect); - } - - void TextRenderer::endFrame() - { - if (m_useTextTree) - { - m_tree.ForEach(bind(&TextObj::Draw, _1, this)); - - unsigned pathTextDrawn = 0; - unsigned pathTextGroups = 0; - unsigned maxGroup = 0; - - list<string> toErase; - - for (path_text_elements::const_iterator it = m_pathTexts.begin(); it != m_pathTexts.end(); ++it) - { - list<PathTextElement> const & l = it->second; - - unsigned curGroup = 0; - - for (list<PathTextElement>::const_iterator j = l.begin(); j != l.end(); ++j) - { - j->draw(this); - ++pathTextDrawn; - } - - if (l.empty()) - toErase.push_back(it->first); - - ++pathTextGroups; - - if (maxGroup < l.size()) - maxGroup = l.size(); - - } - - for (list<string>::const_iterator it = toErase.begin(); it != toErase.end(); ++it) - m_pathTexts.erase(*it); - - if (m_textTreeAutoClean) - { - m_tree.Clear(); - m_pathTexts.clear(); - } - - m_needTextRedraw = false; - } - base_t::endFrame(); - } - - void TextRenderer::clearTextTree() - { - ASSERT(m_useTextTree, ()); - m_tree.Clear(); - m_pathTexts.clear(); - } - - void TextRenderer::offsetTexts(m2::PointD const & offs, m2::RectD const & rect) - { - ASSERT(m_useTextTree, ()); - vector<TextObj> texts; - m_tree.ForEach(MakeBackInsertFunctor(texts)); - m_tree.Clear(); - for (vector<TextObj>::iterator it = texts.begin(); it != texts.end(); ++it) - { - it->Offset(offs); - - m2::RectD limitRect = it->GetLimitRect(this); - - /// fully inside shouldn't be rendered - if (rect.IsRectInside(limitRect)) - it->SetNeedRedraw(false); - else - /// intersecting the borders, should be re-rendered - if (rect.IsIntersect(limitRect)) - it->SetNeedRedraw(true); - - if (limitRect.IsIntersect(rect)) - m_tree.Add(*it, limitRect); - } - } - - void TextRenderer::offsetPathTexts(m2::PointD const & offs, m2::RectD const & rect) - { - ASSERT(m_useTextTree, ()); - - m2::AARectD aaRect(rect); - - path_text_elements newPathTexts; - - for (path_text_elements::iterator i = m_pathTexts.begin(); i != m_pathTexts.end(); ++i) - { - list<PathTextElement> & l = i->second; - list<PathTextElement>::iterator it = l.begin(); - bool isEmpty = true; - while (it != l.end()) - { - it->offset(offs); - m2::AARectD const & r = it->boundRect(); - if (!aaRect.IsIntersect(r) && !aaRect.IsRectInside(r)) - { - list<PathTextElement>::iterator tempIt = it; - ++tempIt; - l.erase(it); - it = tempIt; - } - else - { - isEmpty = false; - ++it; - } - } - - if (!isEmpty) - newPathTexts[i->first] = l; - } - - /// to clear an empty elements from the map. - m_pathTexts = newPathTexts; - } - - void TextRenderer::offsetTextTree(m2::PointD const & offs, m2::RectD const & rect) - { - offsetTexts(offs, rect); - offsetPathTexts(offs, rect); - } - - void TextRenderer::setNeedTextRedraw(bool flag) - { - ASSERT(m_useTextTree, ()); - m_needTextRedraw = flag; - } - - void TextRenderer::updateActualTarget() - { - if (m_useTextTree) - setNeedTextRedraw(m_doPeriodicalTextUpdate); - base_t::updateActualTarget(); + renderState()->m_currentInfoLayer->addStraightText(ste); } bool TextRenderer::drawPathText( @@ -305,7 +68,7 @@ namespace yg params.m_fullLength = fullLength; params.m_pathOffset = pathOffset; params.m_fontDesc = fontDesc; - params.m_logText = strings::MakeUniString(utf8Text); + params.m_logText = strings::FromUtf8(utf8Text); params.m_depth = depth; params.m_log2vis = true; params.m_rm = resourceManager().get(); @@ -315,26 +78,10 @@ namespace yg PathTextElement pte(params); - if (!m_useTextTree || fontDesc.m_isStatic) - pte.draw(this); + if (!renderState().get() || fontDesc.m_isStatic) + pte.draw(this, math::Identity<double, 3>()); else - { - checkTextRedraw(); - - list<PathTextElement> & l = m_pathTexts[utf8Text]; - - bool doAppend = true; - - for (list<PathTextElement>::const_iterator it = l.begin(); it != l.end(); ++it) - if (it->boundRect().IsIntersect(pte.boundRect())) - { - doAppend = false; - break; - } - - if (doAppend) - l.push_back(pte); - } + renderState()->m_currentInfoLayer->addPathText(pte); return true; } @@ -355,12 +102,5 @@ namespace yg depth, p->m_pageID); } - - void TextRenderer::drawPath(m2::PointD const * points, size_t pointsCount, double offset, uint32_t styleID, double depth) - { - if (m_useTextTree) - checkTextRedraw(); - base_t::drawPath(points, pointsCount, offset, styleID, depth); - } } } diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index 31ea2f26f7..0290b9c0f9 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -9,46 +9,15 @@ #include "../std/shared_ptr.hpp" + namespace yg { - class ResourceManager; namespace gl { - class BaseTexture; - class TextRenderer : public ShapeRenderer { - public: - - class TextObj - { - StraightTextElement m_elem; - mutable bool m_needRedraw; - mutable bool m_frozen; - - public: - - TextObj(StraightTextElement const & elem); - void Draw(TextRenderer * pTextRenderer) const; - m2::RectD const GetLimitRect(TextRenderer * pTextRenderer) const; - void SetNeedRedraw(bool needRedraw) const; - bool IsNeedRedraw() const; - bool IsFrozen() const; - void Offset(m2::PointD const & pt); - string const & Text() const; - - static bool better_text(TextObj const & r1, TextObj const & r2); - }; - private: - m4::Tree<TextObj> m_tree; - typedef map<string, list<PathTextElement> > path_text_elements; - path_text_elements m_pathTexts; - - void checkTextRedraw(); - bool m_needTextRedraw; - bool drawPathTextImpl(FontDesc const & fontDesc, m2::PointD const * path, size_t s, @@ -67,10 +36,7 @@ namespace yg double depth, bool log2vis); - bool m_textTreeAutoClean; - bool m_useTextTree; bool m_drawTexts; - bool m_doPeriodicalTextUpdate; public: @@ -78,10 +44,7 @@ namespace yg struct Params : base_t::Params { - bool m_textTreeAutoClean; - bool m_useTextTree; bool m_drawTexts; - bool m_doPeriodicalTextUpdate; Params(); }; @@ -112,28 +75,6 @@ namespace yg double pathOffset, yg::EPosition pos, double depth); - - - void setClipRect(m2::RectI const & rect); - - void endFrame(); - - void clearTextTree(); - /// shift all elements in the tree by the specified offset - /// leaving only those elements, which intersect the specified rect - /// boosting their priority to the top for them not to be filtered away, - /// when the new texts arrive - void offsetTextTree(m2::PointD const & offs, m2::RectD const & r); - - void offsetTexts(m2::PointD const & offs, m2::RectD const & r); - void offsetPathTexts(m2::PointD const & offs, m2::RectD const & r); - - /// flush texts upon any function call. - void setNeedTextRedraw(bool flag); - - void drawPath(m2::PointD const * points, size_t pointsCount, double offset, uint32_t styleID, double depth); - - void updateActualTarget(); }; } } @@ -58,7 +58,8 @@ SOURCES += \ font_desc.cpp \ glyph_layout.cpp \ text_element.cpp \ - text_path.cpp + text_path.cpp \ + info_layer.cpp HEADERS += \ internal/opengl.hpp \ @@ -109,7 +110,8 @@ HEADERS += \ font_desc.hpp \ glyph_layout.hpp \ text_element.hpp \ - text_path.hpp + text_path.hpp \ + info_layer.hpp win32 { HEADERS += internal/opengl_win32.hpp diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 58d21163b4..1a058bca5e 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -886,7 +886,7 @@ namespace yg::StraightTextElement ste(params); p->drawPath(&m_path[0], m_path.size(), 0, p->skin()->mapPenInfo(m_penInfo), 0); - ste.draw(p.get()); + ste.draw(p.get(), math::Identity<double, 3>()); } }; @@ -930,7 +930,7 @@ namespace yg::PathTextElement pte(params); p->drawPath(&m_path[0], m_path.size(), 0, p->skin()->mapPenInfo(m_penInfo), 0); - pte.draw(p.get()); + pte.draw(p.get(), math::Identity<double, 3>()); } }; |