Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrachytski <siarhei.rachytski@gmail.com>2011-06-12 19:48:45 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:19:37 +0300
commit9e73efd60264e878375ae08b8767307d17544d27 (patch)
treef763ff6e5c2859643f922c7082acff3e567329da
parenta081d2e5c2d5a24c4e8822f3cdd06e2ac09cfbca (diff)
introduced separate information layer class, which will perform all POI and Text layout.
-rw-r--r--geometry/point2d.hpp9
-rw-r--r--geometry/tree4d.hpp13
-rw-r--r--map/framework.cpp5
-rw-r--r--map/information_display.cpp38
-rw-r--r--map/information_display.hpp3
-rw-r--r--map/render_queue_routine.cpp20
-rw-r--r--yg/glyph_cache.hpp2
-rw-r--r--yg/glyph_cache_impl.hpp14
-rw-r--r--yg/info_layer.cpp129
-rw-r--r--yg/info_layer.hpp49
-rw-r--r--yg/render_state.cpp5
-rw-r--r--yg/render_state.hpp6
-rw-r--r--yg/render_state_updater.cpp5
-rw-r--r--yg/resource_manager.cpp2
-rw-r--r--yg/resource_manager.hpp2
-rw-r--r--yg/skin_page.cpp4
-rw-r--r--yg/text_element.cpp37
-rw-r--r--yg/text_element.hpp14
-rw-r--r--yg/text_renderer.cpp282
-rw-r--r--yg/text_renderer.hpp61
-rw-r--r--yg/yg.pro6
-rw-r--r--yg/yg_tests/screengl_test.cpp4
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();
};
}
}
diff --git a/yg/yg.pro b/yg/yg.pro
index c479aa6532..9cbaf428cd 100644
--- a/yg/yg.pro
+++ b/yg/yg.pro
@@ -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>());
}
};