diff --git a/.gitignore b/.gitignore index f3afe3a0cc..b3980d55c4 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,8 @@ android/.classpath android/.cproject android/.project android/assets +# local android scripts, such as debugger helper scrips +android/local qtc_packaging diff --git a/map/draw_processor.cpp b/map/draw_processor.cpp index f731e37225..14b66ad10d 100644 --- a/map/draw_processor.cpp +++ b/map/draw_processor.cpp @@ -1,8 +1,15 @@ #include "draw_processor.hpp" +#include "drawer_yg.hpp" +#include "languages.hpp" + #include "../geometry/screenbase.hpp" #include "../geometry/rect_intersect.hpp" +#include "../indexer/feature_visibility.hpp" +#include "../indexer/drawing_rules.hpp" +#include "../indexer/feature_data.hpp" + #include "../std/bind.hpp" #include "../base/start_mem_debug.hpp" @@ -177,3 +184,239 @@ bool area_tess_points::IsExist() const } } + +namespace fwork +{ + namespace + { + template void assign_point(di::DrawInfo * p, TSrc & src) + { + p->m_point = src.m_point; + } + template void assign_path(di::DrawInfo * p, TSrc & src) + { + p->m_pathes.swap(src.m_points); + } + template void assign_area(di::DrawInfo * p, TSrc & src) + { + p->m_areas.swap(src.m_points); + + ASSERT ( !p->m_areas.empty(), () ); + p->m_areas.back().SetCenter(src.GetCenter()); + } + } + + DrawProcessor::DrawProcessor( m2::RectD const & r, + ScreenBase const & convertor, + shared_ptr const & paintEvent, + int scaleLevel, + yg::GlyphCache * glyphCache) + : m_rect(r), + m_convertor(convertor), + m_paintEvent(paintEvent), + m_zoom(scaleLevel), + m_glyphCache(glyphCache) +#ifdef PROFILER_DRAWING + , m_drawCount(0) +#endif + { + m_keys.reserve(reserve_rules_count); + + GetDrawer()->SetScale(m_zoom); + } + + namespace + { + struct less_depth + { + bool operator() (di::DrawRule const & r1, di::DrawRule const & r2) const + { + return (r1.m_depth < r2.m_depth); + } + }; + + struct less_key + { + bool operator() (drule::Key const & r1, drule::Key const & r2) const + { + if (r1.m_type == r2.m_type) + { + // assume that unique algo leaves the first element (with max priority), others - go away + return (r1.m_priority > r2.m_priority); + } + else + return (r1.m_type < r2.m_type); + } + }; + + struct equal_key + { + bool operator() (drule::Key const & r1, drule::Key const & r2) const + { + // many line and area rules - is ok, other rules - one is enough + if (r1.m_type == drule::line || r1.m_type == drule::area) + return (r1 == r2); + else + return (r1.m_type == r2.m_type); + } + }; + } + + void DrawProcessor::PreProcessKeys() + { + sort(m_keys.begin(), m_keys.end(), less_key()); + m_keys.erase(unique(m_keys.begin(), m_keys.end(), equal_key()), m_keys.end()); + } + +#define GET_POINTS(f, for_each_fun, fun, assign_fun) \ + { \ + f.for_each_fun(fun, m_zoom); \ + if (fun.IsExist()) \ + { \ + isExist = true; \ + assign_fun(ptr.get(), fun); \ + } \ + } + + bool DrawProcessor::operator()(FeatureType const & f) + { + if (m_paintEvent->isCancelled()) + throw redraw_operation_cancelled(); + + // get drawing rules + m_keys.clear(); + string names; // for debug use only, in release it's empty + int type = feature::GetDrawRule(f, m_zoom, m_keys, names); + + if (m_keys.empty()) + { + // Index can pass here invisible features. + // During indexing, features are placed at first visible scale bucket. + // At higher scales it can become invisible - it depends on classificator. + return true; + } + + // remove duplicating identical drawing keys + PreProcessKeys(); + + // get drawing rules for the m_keys array + size_t const count = m_keys.size(); +#ifdef PROFILER_DRAWING + m_drawCount += count; +#endif + + buffer_vector rules; + rules.resize(count); + + int layer = f.GetLayer(); + bool isTransparent = false; + if (layer == feature::LAYER_TRANSPARENT_TUNNEL) + { + layer = 0; + isTransparent = true; + } + + for (size_t i = 0; i < count; ++i) + { + int depth = m_keys[i].m_priority; + if (layer != 0) + depth = (layer * drule::layer_base_priority) + (depth % drule::layer_base_priority); + + rules[i] = di::DrawRule(drule::rules().Find(m_keys[i]), depth, isTransparent); + } + + sort(rules.begin(), rules.end(), less_depth()); + + shared_ptr ptr(new di::DrawInfo( + f.GetPreferredDrawableName(languages::GetCurrentPriorities()), + f.GetRoadNumber(), + (m_zoom > 5) ? f.GetPopulationDrawRank() : 0.0)); + + DrawerYG * pDrawer = GetDrawer(); + + using namespace get_pts; + + bool isExist = false; + switch (type) + { + case feature::GEOM_POINT: + { + typedef get_pts::one_point functor_t; + + functor_t::params p; + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + + functor_t fun(p); + GET_POINTS(f, ForEachPointRef, fun, assign_point) + break; + } + + case feature::GEOM_AREA: + { + typedef filter_screenpts_adapter functor_t; + + functor_t::params p; + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + + functor_t fun(p); + GET_POINTS(f, ForEachTriangleExRef, fun, assign_area) + { + // if area feature has any line-drawing-rules, than draw it like line + for (size_t i = 0; i < m_keys.size(); ++i) + if (m_keys[i].m_type == drule::line) + goto draw_line; + break; + } + } + draw_line: + case feature::GEOM_LINE: + { + typedef filter_screenpts_adapter functor_t; + functor_t::params p; + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + + if (!ptr->m_name.empty()) + { + double fontSize = 0; + for (size_t i = 0; i < count; ++i) + { + if (pDrawer->filter_text_size(rules[i].m_rule)) + fontSize = max((uint8_t)fontSize, pDrawer->get_pathtext_font_size(rules[i].m_rule)); + } + + if (fontSize != 0) + { + double textLength = m_glyphCache->getTextLength(fontSize, ptr->m_name); + typedef calc_length functor_t; + functor_t::params p1; + p1.m_convertor = &m_convertor; + p1.m_rect = &m_rect; + functor_t fun(p1); + + f.ForEachPointRef(fun, m_zoom); + if ((fun.IsExist()) && (fun.m_length > textLength)) + { + textLength += 50; + p.m_startLength = (fun.m_length - textLength) / 2; + p.m_endLength = p.m_startLength + textLength; + } + } + } + + functor_t fun(p); + + GET_POINTS(f, ForEachPointRef, fun, assign_path) + + break; + } + } + + if (isExist) + pDrawer->Draw(ptr.get(), rules.data(), count); + + return true; + } +} diff --git a/map/draw_processor.hpp b/map/draw_processor.hpp index 0195ad6e46..604f236169 100644 --- a/map/draw_processor.hpp +++ b/map/draw_processor.hpp @@ -1,7 +1,13 @@ #pragma once -#include "draw_info.hpp" +#include "draw_info.hpp" +#include "events.hpp" + +#include "../indexer/drawing_rule_def.hpp" +#include "../indexer/feature.hpp" #include "../indexer/cell_id.hpp" // CoordPointT +#include "../indexer/data_header.hpp" +#include "../indexer/feature_data.hpp" #include "../geometry/point2d.hpp" #include "../geometry/rect2d.hpp" @@ -300,3 +306,45 @@ namespace get_pts m2::PointD GetCenter() const { return m_center / (3*m_count); } }; } + +namespace drule { class BaseRule; } +namespace di { class DrawInfo; } + +class redraw_operation_cancelled {}; + +namespace fwork +{ + class DrawProcessor + { + m2::RectD m_rect; + + ScreenBase const & m_convertor; + + shared_ptr m_paintEvent; + vector m_keys; + + int m_zoom; + yg::GlyphCache * m_glyphCache; + +#ifdef PROFILER_DRAWING + size_t m_drawCount; +#endif + + inline DrawerYG * GetDrawer() const { return m_paintEvent->drawer().get(); } + + void PreProcessKeys(); + + static const int reserve_rules_count = 16; + + public: + + DrawProcessor(m2::RectD const & r, + ScreenBase const & convertor, + shared_ptr const & paintEvent, + int scaleLevel, + yg::GlyphCache * glyphCache); + + bool operator() (FeatureType const & f); + }; +} + diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index 0d84a5b733..b42918ba92 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -97,7 +97,7 @@ void DrawerYG::onSize(int w, int h) void DrawerYG::drawSymbol(m2::PointD const & pt, string const & symbolName, yg::EPosition pos, int depth) { - m_pScreen->drawSymbol(pt, m_pSkin->mapSymbol(symbolName.c_str()), pos, depth); + m_pScreen->drawSymbol(pt, symbolName.c_str(), pos, depth); } void DrawerYG::drawCircle(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition pos, int depth) @@ -134,10 +134,12 @@ void DrawerYG::drawSymbol(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition // This rules doesn't mix with other rule-types. uint32_t id = pRule->GetID(m_threadID); - if (id == drule::BaseRule::empty_id) + + string name; + pRule->GetSymbol(name); + +/* if (id == drule::BaseRule::empty_id) { - string name; - pRule->GetSymbol(name); id = m_pSkin->mapSymbol(name.c_str()); if (id != drule::BaseRule::empty_id) @@ -147,9 +149,9 @@ void DrawerYG::drawSymbol(m2::PointD const & pt, rule_ptr_t pRule, yg::EPosition //ASSERT ( false, ("Can't find symbol by id = ", (name)) ); return; } - } + }*/ - m_pScreen->drawSymbol(pt, id, pos, depth); + m_pScreen->drawSymbol(pt, name, pos, depth); } void DrawerYG::drawPath(di::PathInfo const & info, di::DrawRule const * rules, size_t count) diff --git a/map/framework.cpp b/map/framework.cpp index 6ea6d5250e..774d50fb5b 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -31,255 +31,6 @@ using namespace feature; -namespace fwork -{ - namespace - { - template void assign_point(di::DrawInfo * p, TSrc & src) - { - p->m_point = src.m_point; - } - template void assign_path(di::DrawInfo * p, TSrc & src) - { - p->m_pathes.swap(src.m_points); - } - template void assign_area(di::DrawInfo * p, TSrc & src) - { - p->m_areas.swap(src.m_points); - - ASSERT ( !p->m_areas.empty(), () ); - p->m_areas.back().SetCenter(src.GetCenter()); - } - } - - DrawProcessor::DrawProcessor( m2::RectD const & r, - ScreenBase const & convertor, - shared_ptr const & paintEvent, - int scaleLevel, - yg::GlyphCache * glyphCache) - : m_rect(r), - m_convertor(convertor), - m_paintEvent(paintEvent), - m_zoom(scaleLevel), - m_glyphCache(glyphCache) -#ifdef PROFILER_DRAWING - , m_drawCount(0) -#endif - { - m_keys.reserve(reserve_rules_count); - - GetDrawer()->SetScale(m_zoom); - } - - namespace - { - struct less_depth - { - bool operator() (di::DrawRule const & r1, di::DrawRule const & r2) const - { - return (r1.m_depth < r2.m_depth); - } - }; - - struct less_key - { - bool operator() (drule::Key const & r1, drule::Key const & r2) const - { - if (r1.m_type == r2.m_type) - { - // assume that unique algo leaves the first element (with max priority), others - go away - return (r1.m_priority > r2.m_priority); - } - else - return (r1.m_type < r2.m_type); - } - }; - - struct equal_key - { - bool operator() (drule::Key const & r1, drule::Key const & r2) const - { - // many line and area rules - is ok, other rules - one is enough - if (r1.m_type == drule::line || r1.m_type == drule::area) - return (r1 == r2); - else - return (r1.m_type == r2.m_type); - } - }; - } - - void DrawProcessor::PreProcessKeys() - { - sort(m_keys.begin(), m_keys.end(), less_key()); - m_keys.erase(unique(m_keys.begin(), m_keys.end(), equal_key()), m_keys.end()); - } - -#define GET_POINTS(f, for_each_fun, fun, assign_fun) \ - { \ - f.for_each_fun(fun, m_zoom); \ - if (fun.IsExist()) \ - { \ - isExist = true; \ - assign_fun(ptr.get(), fun); \ - } \ - } - - bool DrawProcessor::operator()(FeatureType const & f) - { - if (m_paintEvent->isCancelled()) - throw redraw_operation_cancelled(); - - // get drawing rules - m_keys.clear(); - string names; // for debug use only, in release it's empty - int type = feature::GetDrawRule(f, m_zoom, m_keys, names); - - if (m_keys.empty()) - { - // Index can pass here invisible features. - // During indexing, features are placed at first visible scale bucket. - // At higher scales it can become invisible - it depends on classificator. - return true; - } - - // remove duplicating identical drawing keys - PreProcessKeys(); - - // get drawing rules for the m_keys array - size_t const count = m_keys.size(); -#ifdef PROFILER_DRAWING - m_drawCount += count; -#endif - - buffer_vector rules; - rules.resize(count); - - int layer = f.GetLayer(); - bool isTransparent = false; - if (layer == feature::LAYER_TRANSPARENT_TUNNEL) - { - layer = 0; - isTransparent = true; - } - - for (size_t i = 0; i < count; ++i) - { - int depth = m_keys[i].m_priority; - if (layer != 0) - depth = (layer * drule::layer_base_priority) + (depth % drule::layer_base_priority); - - rules[i] = di::DrawRule(drule::rules().Find(m_keys[i]), depth, isTransparent); - } - - sort(rules.begin(), rules.end(), less_depth()); - - shared_ptr ptr(new di::DrawInfo( - f.GetPreferredDrawableName(languages::GetCurrentPriorities()), - f.GetRoadNumber(), - (m_zoom > 5) ? f.GetPopulationDrawRank() : 0.0)); - - DrawerYG * pDrawer = GetDrawer(); - - using namespace get_pts; - - bool isExist = false; - switch (type) - { - case GEOM_POINT: - { - typedef get_pts::one_point functor_t; - - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - functor_t fun(p); - GET_POINTS(f, ForEachPointRef, fun, assign_point) - break; - } - - case GEOM_AREA: - { - typedef filter_screenpts_adapter functor_t; - - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - functor_t fun(p); - GET_POINTS(f, ForEachTriangleExRef, fun, assign_area) - { - // if area feature has any line-drawing-rules, than draw it like line - for (size_t i = 0; i < m_keys.size(); ++i) - if (m_keys[i].m_type == drule::line) - goto draw_line; - break; - } - } - draw_line: - case GEOM_LINE: - { - typedef filter_screenpts_adapter functor_t; - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - if (!ptr->m_name.empty()) - { - double fontSize = 0; - for (size_t i = 0; i < count; ++i) - { - if (pDrawer->filter_text_size(rules[i].m_rule)) - fontSize = max((uint8_t)fontSize, pDrawer->get_pathtext_font_size(rules[i].m_rule)); - } - - if (fontSize != 0) - { - double textLength = m_glyphCache->getTextLength(fontSize, ptr->m_name); - typedef calc_length functor_t; - functor_t::params p1; - p1.m_convertor = &m_convertor; - p1.m_rect = &m_rect; - functor_t fun(p1); - - f.ForEachPointRef(fun, m_zoom); - if ((fun.IsExist()) && (fun.m_length > textLength)) - { - textLength += 50; - p.m_startLength = (fun.m_length - textLength) / 2; - p.m_endLength = p.m_startLength + textLength; - } - } - } - - functor_t fun(p); - - GET_POINTS(f, ForEachPointRef, fun, assign_path) - - break; - } - } - - if (isExist) - pDrawer->Draw(ptr.get(), rules.data(), count); - - return true; - } -} - -/*template -void FrameWork::AddRedrawCommandSure() -{ - -}*/ - -/* template - void FrameWork::AddRedrawCommand() - { - yg::gl::RenderState const state = m_renderQueue.CopyState(); - if ((state.m_currentScreen != m_navigator.Screen()) && (m_isRedrawEnabled)) - AddRedrawCommandSure(); - }*/ template void FrameWork::AddMap(string const & file) @@ -687,7 +438,39 @@ void FrameWork::AddRedrawCommandSure() shared_ptr const & resourceManager) { m_resourceManager = resourceManager; - m_renderQueue.InitializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); + + if (GetPlatform().IsMultiThreadedRendering()) + m_renderQueue.InitializeGL(primaryContext, m_resourceManager, GetPlatform().VisualScale()); + else + { + /// render single tile on the same thread + shared_ptr frameBuffer(new yg::gl::FrameBuffer()); + + unsigned tileWidth = m_resourceManager->tileTextureWidth(); + unsigned tileHeight = m_resourceManager->tileTextureHeight(); + + shared_ptr depthBuffer(new yg::gl::RenderBuffer(tileWidth, tileHeight, true)); + frameBuffer->setDepthBuffer(depthBuffer); + + DrawerYG::params_t params; + + shared_ptr infoLayer(new yg::InfoLayer()); + + params.m_resourceManager = m_resourceManager; + params.m_frameBuffer = frameBuffer; + params.m_infoLayer = infoLayer; + params.m_glyphCacheID = m_resourceManager->guiThreadGlyphCacheID(); + params.m_useOverlay = true; + params.m_threadID = 0; + + m_tileDrawer = make_shared_ptr(new DrawerYG(GetPlatform().SkinName(), params)); + m_tileDrawer->onSize(tileWidth, tileHeight); + + m_tileDrawer->SetVisualScale(GetPlatform().VisualScale()); + + m2::RectI renderRect(1, 1, tileWidth - 1, tileWidth - 1); + m_tileScreen.OnSize(renderRect); + } } template @@ -840,22 +623,7 @@ void FrameWork::AddRedrawCommandSure() try { threads::MutexGuard lock(m_modelSyn); - -#ifdef PROFILER_DRAWING - using namespace prof; - - start(); - reset(); -#endif - m_model.ForEachFeatureWithScale(selectRect, bind(ref(doDraw), _1), scaleLevel); - -#ifdef PROFILER_DRAWING - end(); - LOG(LPROF, ("ForEachFeature=", metric(), - "FeatureCount=", metric(), - "TextureUpload= ", metric())); -#endif } catch (redraw_operation_cancelled const &) { @@ -871,9 +639,6 @@ void FrameWork::AddRedrawCommandSure() template void FrameWork::Paint(shared_ptr e) { - // Making a copy of actualFrameInfo to compare without synchronizing. - //typename yg::gl::RenderState state = m_renderQueue.CopyState(); - DrawerYG * pDrawer = e->drawer().get(); m_informationDisplay.setScreen(m_navigator.Screen()); @@ -918,6 +683,8 @@ void FrameWork::AddRedrawCommandSure() m_renderQueue.renderState().m_actualScreen, currentScreen);*/ + m_infoLayer.clear(); + m_tiler.seed(currentScreen, currentScreen.GlobalRect().Center(), m_tileSize, @@ -942,19 +709,74 @@ void FrameWork::AddRedrawCommandSure() yg::Color(), m2::RectI(0, 0, tileWidth - 2, tileHeight - 2), m2::RectU(1, 1, tileWidth - 1, tileHeight - 1)); + + m_infoLayer.merge(*tile.m_infoLayer.get(), tile.m_tileScreen.PtoGMatrix() * currentScreen.GtoPMatrix()); } else { - m_renderQueue.TileCache().unlock(); - m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), ri, m_tiler.seqNum()); + if (GetPlatform().IsMultiThreadedRendering()) + { + m_renderQueue.TileCache().unlock(); + m_renderQueue.AddCommand(bind(&this_type::PaintImpl, this, _1, _2, _3, _4), ri, m_tiler.seqNum()); + } + else + { + m_renderQueue.TileCache().unlock(); + shared_ptr paintEvent(new PaintEvent(m_tileDrawer)); + shared_ptr tileTarget = m_resourceManager->renderTargets().Front(true); + + shared_ptr tileInfoLayer(new yg::InfoLayer()); + + m_tileDrawer->screen()->setRenderTarget(tileTarget); + m_tileDrawer->screen()->setInfoLayer(tileInfoLayer); + + m_tileDrawer->beginFrame(); + + m_tileDrawer->clear(yg::Color(m_bgColor.r, m_bgColor.g, m_bgColor.b, 0)); + m2::RectI renderRect(1, 1, m_resourceManager->tileTextureWidth() - 1, m_resourceManager->tileTextureHeight() - 1); + m_tileDrawer->screen()->setClipRect(renderRect); + m_tileDrawer->clear(m_bgColor); + + m_tileScreen.SetFromRect(ri.m_rect); + + m2::RectD selectionRect; + + double inflationSize = 24 * GetPlatform().VisualScale(); + + m_tileScreen.PtoG(m2::Inflate(m2::RectD(renderRect), inflationSize, inflationSize), selectionRect); + + PaintImpl(paintEvent, + m_tileScreen, + selectionRect, + ri.m_drawScale); + + m_tileDrawer->endFrame(); + m_tileDrawer->screen()->resetInfoLayer(); + + yg::Tile tile(tileTarget, tileInfoLayer, m_tileScreen, ri, 0); + m_renderQueue.TileCache().lock(); + m_renderQueue.TileCache().addTile(ri, yg::TileCache::Entry(tile, m_resourceManager)); + m_renderQueue.TileCache().unlock(); + + m_renderQueue.TileCache().touchTile(ri); + tile = m_renderQueue.TileCache().getTile(ri); + m_renderQueue.TileCache().unlock(); + + size_t tileWidth = tile.m_renderTarget->width(); + size_t tileHeight = tile.m_renderTarget->height(); + + pDrawer->screen()->blit(tile.m_renderTarget, tile.m_tileScreen, currentScreen, true, + yg::Color(), + m2::RectI(0, 0, tileWidth - 2, tileHeight - 2), + m2::RectU(1, 1, tileWidth - 1, tileHeight - 1)); + } } } - m_informationDisplay.doDraw(pDrawer); + m_infoLayer.draw(pDrawer->screen().get(), + math::Identity()); -/* m_renderQueue.renderState().m_actualInfoLayer->draw( - pDrawer->screen().get(), - m_renderQueue.renderState().m_actualScreen.PtoGMatrix() * currentScreen.GtoPMatrix());*/ + m_informationDisplay.doDraw(pDrawer); m_locationState.DrawMyPosition(*pDrawer, m_navigator.Screen()); diff --git a/map/framework.hpp b/map/framework.hpp index fa88fb1694..71e5ef0c9a 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -10,11 +10,9 @@ #include "../defines.hpp" -#include "../indexer/drawing_rule_def.hpp" #include "../indexer/mercator.hpp" #include "../indexer/data_header.hpp" #include "../indexer/scales.hpp" -#include "../indexer/feature.hpp" #include "../platform/platform.hpp" #include "../platform/location.hpp" @@ -26,6 +24,7 @@ #include "../yg/skin.hpp" #include "../yg/resource_manager.hpp" #include "../yg/tiler.hpp" +#include "../yg/info_layer.hpp" #include "../coding/file_reader.hpp" #include "../coding/file_writer.hpp" @@ -47,56 +46,17 @@ //#define DRAW_TOUCH_POINTS -namespace di { class DrawInfo; } -namespace drule { class BaseRule; } namespace search { class Engine; } -class redraw_operation_cancelled {}; - struct BenchmarkRectProvider; namespace search { class Result; } typedef function SearchCallbackT; -namespace fwork -{ - class DrawProcessor - { - m2::RectD m_rect; - - ScreenBase const & m_convertor; - - shared_ptr m_paintEvent; - vector m_keys; - - int m_zoom; - yg::GlyphCache * m_glyphCache; - -#ifdef PROFILER_DRAWING - size_t m_drawCount; -#endif - - inline DrawerYG * GetDrawer() const { return m_paintEvent->drawer().get(); } - - void PreProcessKeys(); - - static const int reserve_rules_count = 16; - - public: - - DrawProcessor(m2::RectD const & r, - ScreenBase const & convertor, - shared_ptr const & paintEvent, - int scaleLevel, - yg::GlyphCache * glyphCache); - - bool operator() (FeatureType const & f); - }; -} - - typedef function LocationRetrievedCallbackT; +class DrawerYG; + template < class TModel @@ -121,6 +81,11 @@ class FrameWork shared_ptr m_resourceManager; InformationDisplay m_informationDisplay; + yg::InfoLayer m_infoLayer; + + shared_ptr m_tileDrawer; + ScreenBase m_tileScreen; + /// is AddRedrawCommand enabled? bool m_isRedrawEnabled; double const m_metresMinWidth; diff --git a/map/information_display.cpp b/map/information_display.cpp index f2fbf1adda..1682b9d238 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -14,6 +14,8 @@ #include "../base/mutex.hpp" #include "../base/macros.hpp" +#include "../geometry/transformations.hpp" + #include "../std/fstream.hpp" #include "../std/iomanip.hpp" @@ -426,9 +428,9 @@ void InformationDisplay::drawEmptyModelMessage(DrawerYG * pDrawer) params.m_logText = strings::MakeUniString(s0); yg::StraightTextElement ste0(params); - ste0.offset(m2::PointD(0, -ste0.boundRect().GetGlobalRect().SizeY() - 5)); - ste0.draw(pDrawer->screen().get(), math::Identity()); + math::Matrix m = math::Shift(math::Identity(), m2::PointD(0, -ste0.boundRect().GetGlobalRect().SizeY() - 5)); + ste0.draw(pDrawer->screen().get(), m); params.m_pivot = pt; params.m_logText = strings::MakeUniString(s1); diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index 0c40e6660f..41df163137 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -6,7 +6,7 @@ CONFIG -= app_bundle TEMPLATE = app ROOT_DIR = ../.. -DEPENDENCIES = map indexer platform geometry coding base expat +DEPENDENCIES = map yg indexer platform geometry coding base expat freetype fribidi include($$ROOT_DIR/common.pri) @@ -19,6 +19,14 @@ win32 { } } +!iphone*:!bada*:!android* { + QT += opengl +} + +macx|iphone* { + LIBS += -framework Foundation +} + SOURCES += \ ../../testing/testingmain.cpp \ navigator_test.cpp \ diff --git a/map/render_queue_routine.cpp b/map/render_queue_routine.cpp index 0986f12cfe..6d5bb142d7 100644 --- a/map/render_queue_routine.cpp +++ b/map/render_queue_routine.cpp @@ -146,6 +146,10 @@ void RenderQueueRoutine::Do() m_threadDrawer->screen()->setRenderTarget(tileTarget); + shared_ptr tileInfoLayer(new yg::InfoLayer()); + + m_threadDrawer->screen()->setInfoLayer(tileInfoLayer); + m_threadDrawer->beginFrame(); m_threadDrawer->clear(yg::Color(m_bgColor.r, m_bgColor.g, m_bgColor.b, 0)); @@ -154,7 +158,7 @@ void RenderQueueRoutine::Do() frameScreen.SetFromRect(m_currentCommand->m_rectInfo.m_rect); - m2::RectD selectionRect; // = m_currentCommand->m_rectInfo.m_rect; + m2::RectD selectionRect; double inflationSize = 24 * m_visualScale; @@ -170,6 +174,7 @@ void RenderQueueRoutine::Do() // m_infoLayer->draw(m_threadDrawer->screen().get(), math::Identity()); m_threadDrawer->endFrame(); + m_threadDrawer->screen()->resetInfoLayer(); double duration = timer.ElapsedSeconds(); @@ -184,7 +189,7 @@ void RenderQueueRoutine::Do() if (!m_currentCommand->m_paintEvent->isCancelled()) { - yg::Tile tile(tileTarget, frameScreen, m_currentCommand->m_rectInfo, duration); + yg::Tile tile(tileTarget, tileInfoLayer, frameScreen, m_currentCommand->m_rectInfo, duration); m_renderQueue->TileCache().lock(); m_renderQueue->TileCache().addTile(m_currentCommand->m_rectInfo, yg::TileCache::Entry(tile, m_resourceManager)); m_renderQueue->TileCache().unlock(); diff --git a/yg/glyph_layout.cpp b/yg/glyph_layout.cpp index c7f900e65e..4c78324fd5 100644 --- a/yg/glyph_layout.cpp +++ b/yg/glyph_layout.cpp @@ -12,6 +12,11 @@ namespace yg { + void GlyphLayoutElem::transform(math::Matrix const & m) + { + m_pt = m_pt * m; + } + double GlyphLayout::getKerning(GlyphLayoutElem const & prevElem, GlyphLayoutElem const & curElem) { double res = 0; @@ -56,17 +61,27 @@ namespace yg return res; } + GlyphLayout::GlyphLayout(GlyphLayout const & src, math::Matrix const & m) + : m_firstVisible(src.m_firstVisible), + m_lastVisible(src.m_lastVisible), + m_pivot(src.m_pivot * m) + { + m_entries = src.m_entries; + /// TODO: it's better and faster to transform AARect, not calculate it once again. + computeMinLimitRect(); + } + GlyphLayout::GlyphLayout(GlyphCache * glyphCache, FontDesc const & fontDesc, m2::PointD const & pt, strings::UniString const & visText, yg::EPosition pos) : m_firstVisible(0), - m_lastVisible(visText.size()) + m_lastVisible(visText.size()), + m_pivot(pt) { - m2::PointD pv = pt; - m2::RectD limitRect; + m2::PointD curPt; bool isFirst = true; @@ -77,26 +92,26 @@ namespace yg GlyphMetrics const m = glyphCache->getGlyphMetrics(glyphKey); if (isFirst) { - limitRect = m2::RectD(m.m_xOffset + pv.x, - -m.m_yOffset + pv.y, - m.m_xOffset + pv.x, - -m.m_yOffset + pv.y); + limitRect = m2::RectD(m.m_xOffset, + -m.m_yOffset, + m.m_xOffset, + -m.m_yOffset); isFirst = false; } else - limitRect.Add(m2::PointD(m.m_xOffset + pv.x, -m.m_yOffset + pv.y)); + limitRect.Add(m2::PointD(m.m_xOffset + curPt.x, -m.m_yOffset + curPt.y)); limitRect.Add(m2::PointD(m.m_xOffset + m.m_width, - -(m.m_yOffset + m.m_height)) + pv); + -(m.m_yOffset + m.m_height)) + curPt); GlyphLayoutElem elem; elem.m_sym = visText[i]; elem.m_angle = 0; - elem.m_pt = pv; + elem.m_pt = curPt; elem.m_metrics = m; m_entries.push_back(elem); - pv += m2::PointD(m.m_xAdvance, m.m_yAdvance); + curPt += m2::PointD(m.m_xAdvance, m.m_yAdvance); } limitRect.Inflate(2, 2); @@ -118,12 +133,12 @@ namespace yg m_limitRect = m2::AARectD(limitRect); - offset(ptOffs); - + for (unsigned i = 0; i < m_entries.size(); ++i) + m_entries[i].m_pt += ptOffs; + m_limitRect.Offset(ptOffs); } - GlyphLayout::GlyphLayout(GlyphCache * glyphCache, FontDesc const & fontDesc, m2::PointD const * pts, @@ -155,13 +170,24 @@ namespace yg if (fullLength < strLength) return; + PathPoint arrPathStart(0, ang::AngleD(ang::AngleTo(arrPath.get(0), arrPath.get(1))), arrPath.get(0)); + + m_pivot = arrPath.offsetPoint(arrPathStart, fullLength / 2.0).m_pt; + // offset of the text from path's start double offset = (fullLength - strLength) / 2.0; if (pos & yg::EPosLeft) + { offset = 0; + m_pivot = arrPathStart.m_pt; + } + if (pos & yg::EPosRight) + { offset = (fullLength - strLength); + m_pivot = arrPath.get(arrPath.size() - 1); + } // calculate base line offset double blOffset = 2 - fontDesc.m_size / 2; @@ -182,7 +208,7 @@ namespace yg while (offset < 0 && symPos < count) offset += m_entries[symPos++].m_metrics.m_xAdvance; - PathPoint glyphStartPt = arrPath.offsetPoint(PathPoint(0, ang::AngleD(ang::AngleTo(arrPath.get(0), arrPath.get(1))), arrPath.get(0)), offset); + PathPoint glyphStartPt = arrPath.offsetPoint(arrPathStart, offset); m_firstVisible = symPos; @@ -268,7 +294,18 @@ namespace yg m_lastVisible = symPos + 1; } + /// storing glyph coordinates relative to pivot point. + for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) + m_entries[i].m_pt -= m_pivot; + computeMinLimitRect(); + +// recalcPivot(); + } + + void GlyphLayout::recalcPivot() + { + } void GlyphLayout::computeMinLimitRect() @@ -352,13 +389,16 @@ namespace yg m2::AARectD const GlyphLayout::limitRect() const { - return m_limitRect; + return m2::Offset(m_limitRect, pivot()); } - void GlyphLayout::offset(m2::PointD const & offs) + m2::PointD const & GlyphLayout::pivot() const { - for (unsigned i = 0; i < m_entries.size(); ++i) - m_entries[i].m_pt += offs; - m_limitRect.Offset(offs); + return m_pivot; + } + + void GlyphLayout::setPivot(m2::PointD const & pivot) + { + m_pivot = pivot; } } diff --git a/yg/glyph_layout.hpp b/yg/glyph_layout.hpp index 04649c2f0d..f45c125cce 100644 --- a/yg/glyph_layout.hpp +++ b/yg/glyph_layout.hpp @@ -26,6 +26,8 @@ namespace yg GlyphMetrics m_metrics; ang::AngleD m_angle; m2::PointD m_pt; + + void transform(math::Matrix const & m); }; class GlyphLayout @@ -39,12 +41,15 @@ namespace yg m2::AARectD m_limitRect; + m2::PointD m_pivot; + double getKerning(GlyphLayoutElem const & prevElem, GlyphLayoutElem const & curElem); void computeMinLimitRect(); + void recalcPivot(); public: - GlyphLayout(GlyphLayout const & layout, double shift); + GlyphLayout(GlyphLayout const & layout, math::Matrix const & m); GlyphLayout(GlyphCache * glyphCache, FontDesc const & font, @@ -68,6 +73,8 @@ namespace yg m2::AARectD const limitRect() const; - void offset(m2::PointD const & offs); + m2::PointD const & pivot() const; + + void setPivot(m2::PointD const & pv); }; } diff --git a/yg/info_layer.cpp b/yg/info_layer.cpp index b85cc136f0..49eb2ae8d9 100644 --- a/yg/info_layer.cpp +++ b/yg/info_layer.cpp @@ -49,7 +49,7 @@ namespace yg m_tree.ForEach(bind(&StraightTextElement::draw, _1, r, m)); } - template +/* template void offsetTree(Tree & tree, m2::PointD const & offs, m2::RectD const & rect) { typedef typename Tree::elem_t elem_t; @@ -136,7 +136,7 @@ namespace yg offsetTextTree(offs, rect); offsetPathTexts(offs, rect); offsetSymbols(offs, rect); - } + }*/ void InfoLayer::clear() { @@ -145,17 +145,25 @@ namespace yg m_symbolsMap.clear(); } - void InfoLayer::addStraightText(StraightTextElement const & ste) + void InfoLayer::addStraightTextImpl(StraightTextElement const & ste) { m_tree.ReplaceIf(ste, ste.boundRect().GetGlobalRect(), &better_text); } + void InfoLayer::addStraightText(StraightTextElement const & ste, math::Matrix const & m) + { + if (m == math::Identity()) + addStraightTextImpl(ste); + else + addStraightTextImpl(StraightTextElement(ste, m)); + } + void mark_intersect(bool & flag) { flag = true; } - void InfoLayer::addSymbol(SymbolElement const & se) + void InfoLayer::addSymbolImpl(SymbolElement const & se) { bool isIntersect = false; m2::RectD limitRect = se.boundRect().GetGlobalRect(); @@ -164,7 +172,15 @@ namespace yg m_symbolsMap[se.styleID()].Add(se, limitRect); } - void InfoLayer::addPathText(PathTextElement const & pte) + void InfoLayer::addSymbol(SymbolElement const & se, math::Matrix const & m) + { + if (m == math::Identity()) + addSymbolImpl(se); + else + addSymbolImpl(SymbolElement(se, m)); + } + + void InfoLayer::addPathTextImpl(PathTextElement const & pte) { list & l = m_pathTexts[pte.logText()]; @@ -180,5 +196,24 @@ namespace yg if (doAppend) l.push_back(pte); } + + void InfoLayer::addPathText(PathTextElement const & pte, math::Matrix const & m) + { +/* if (m == math::Identity()) + addPathTextImpl(pte); + else + addPathTextImpl(PathTextElement(pte, m));*/ + } + + void InfoLayer::merge(InfoLayer const & layer, math::Matrix const & m) + { + for (symbols_map_t::const_iterator it = layer.m_symbolsMap.begin(); it != layer.m_symbolsMap.end(); ++it) + it->second.ForEach(bind(&InfoLayer::addSymbol, this, _1, m)); + + layer.m_tree.ForEach(bind(&InfoLayer::addStraightText, this, _1, m)); + + for (path_text_elements::const_iterator it = layer.m_pathTexts.begin(); it != layer.m_pathTexts.end(); ++it) + for_each(it->second.begin(), it->second.end(), bind(&InfoLayer::addPathText, this, _1, m)); + } } diff --git a/yg/info_layer.hpp b/yg/info_layer.hpp index 8c14396ba6..a67fd123ef 100644 --- a/yg/info_layer.hpp +++ b/yg/info_layer.hpp @@ -7,6 +7,8 @@ #include "../geometry/point2d.hpp" #include "../geometry/tree4d.hpp" +#include "../base/matrix.hpp" + #include "../std/map.hpp" #include "../std/list.hpp" @@ -35,22 +37,28 @@ namespace yg typedef map > symbols_map_t; symbols_map_t m_symbolsMap; - void offsetPathTexts(m2::PointD const & offs, m2::RectD const & rect); +/* void offsetPathTexts(m2::PointD const & offs, m2::RectD const & rect); void offsetTextTree(m2::PointD const & offs, m2::RectD const & rect); - void offsetSymbols(m2::PointD const & offs, m2::RectD const & rect); + void offsetSymbols(m2::PointD const & offs, m2::RectD const & rect);*/ + + void addPathTextImpl(PathTextElement const & pte); + void addStraightTextImpl(StraightTextElement const & ste); + void addSymbolImpl(SymbolElement const & se); public: void draw(gl::OverlayRenderer * r, math::Matrix const & m); - void addPathText(PathTextElement const & pte); + void addPathText(PathTextElement const & pte, math::Matrix const & m); - void addStraightText(StraightTextElement const & ste); + void addStraightText(StraightTextElement const & ste, math::Matrix const & m); - void addSymbol(SymbolElement const & se); + void addSymbol(SymbolElement const & se, math::Matrix const & m); - void offset(m2::PointD const & offs, m2::RectD const & rect); +// void offset(m2::PointD const & offs, m2::RectD const & rect); void clear(); + + void merge(InfoLayer const & infoLayer, math::Matrix const & m); }; } diff --git a/yg/overlay_element.cpp b/yg/overlay_element.cpp index bd1a5cc746..cdea08ead5 100644 --- a/yg/overlay_element.cpp +++ b/yg/overlay_element.cpp @@ -35,10 +35,10 @@ namespace yg return res; } - void OverlayElement::offset(m2::PointD const & offs) +/* void OverlayElement::offset(m2::PointD const & offs) { m_pivot += offs; - } + }*/ m2::PointD const & OverlayElement::pivot() const { diff --git a/yg/overlay_element.hpp b/yg/overlay_element.hpp index 3ed1596930..521ae58353 100644 --- a/yg/overlay_element.hpp +++ b/yg/overlay_element.hpp @@ -38,9 +38,8 @@ namespace yg OverlayElement(Params const & p); - virtual void offset(m2::PointD const & offs) = 0; virtual m2::AARectD const boundRect() const = 0; - virtual void draw(gl::OverlayRenderer * screen, math::Matrix const & m) const = 0; + virtual void draw(gl::OverlayRenderer * r, math::Matrix const & m) const = 0; m2::PointD const & pivot() const; void setPivot(m2::PointD const & pv); diff --git a/yg/overlay_renderer.cpp b/yg/overlay_renderer.cpp index a126249f1a..7f3762ab90 100644 --- a/yg/overlay_renderer.cpp +++ b/yg/overlay_renderer.cpp @@ -29,7 +29,7 @@ namespace yg } void OverlayRenderer::drawSymbol(m2::PointD const & pt, - uint32_t styleID, + string const & symbolName, EPosition pos, int depth) { @@ -41,7 +41,8 @@ namespace yg params.m_depth = depth; params.m_position = pos; params.m_pivot = pt; - params.m_styleID = styleID; + params.m_symbolName = symbolName; + params.m_styleID = 0; params.m_skin = skin().get(); SymbolElement se(params); @@ -49,7 +50,7 @@ namespace yg if (!m_infoLayer.get() || !m_useOverlay) se.draw(this, math::Identity()); else - m_infoLayer->addSymbol(se); + m_infoLayer->addSymbol(se, math::Identity()); } void OverlayRenderer::drawCircle(m2::PointD const & pt, @@ -65,7 +66,10 @@ namespace yg params.m_skin = skin().get(); SymbolElement se(params); - se.draw(this, math::Identity()); + + math::Matrix id = math::Identity(); + + se.draw(this, id); } void OverlayRenderer::drawText(FontDesc const & fontDesc, @@ -89,10 +93,12 @@ namespace yg StraightTextElement ste(params); + math::Matrix id = math::Identity(); + if (!m_infoLayer.get() || !m_useOverlay) - ste.draw(this, math::Identity()); + ste.draw(this, id); else - m_infoLayer->addStraightText(ste); + m_infoLayer->addStraightText(ste, id); } bool OverlayRenderer::drawPathText( @@ -118,13 +124,29 @@ namespace yg PathTextElement pte(params); + math::Matrix id = math::Identity(); + if (!m_infoLayer.get() || !m_useOverlay) - pte.draw(this, math::Identity()); + pte.draw(this, id); else - m_infoLayer->addPathText(pte); + m_infoLayer->addPathText(pte, id); return true; } + void OverlayRenderer::setInfoLayer(shared_ptr const & infoLayer) + { + m_infoLayer = infoLayer; + } + + shared_ptr const & OverlayRenderer::infoLayer() const + { + return m_infoLayer; + } + + void OverlayRenderer::resetInfoLayer() + { + m_infoLayer.reset(); + } } } diff --git a/yg/overlay_renderer.hpp b/yg/overlay_renderer.hpp index 2e27da9cf7..eae80a64f6 100644 --- a/yg/overlay_renderer.hpp +++ b/yg/overlay_renderer.hpp @@ -31,7 +31,7 @@ namespace yg OverlayRenderer(Params const & p); /// Drawing POI symbol - void drawSymbol(m2::PointD const & pt, uint32_t styleID, EPosition pos, int depth); + void drawSymbol(m2::PointD const & pt, string const & symbolName, EPosition pos, int depth); /// Drawing circle void drawCircle(m2::PointD const & pt, uint32_t styleID, EPosition pos, int depth); @@ -53,6 +53,12 @@ namespace yg double pathOffset, yg::EPosition pos, double depth); + + void setInfoLayer(shared_ptr const & infoLayer); + + shared_ptr const & infoLayer() const; + + void resetInfoLayer(); }; } } diff --git a/yg/symbol_element.cpp b/yg/symbol_element.cpp index f93c12b32c..ffb2242ca2 100644 --- a/yg/symbol_element.cpp +++ b/yg/symbol_element.cpp @@ -10,19 +10,33 @@ namespace yg { SymbolElement::SymbolElement(Params const & p) : OverlayElement(p), - m_styleID(p.m_styleID) + m_styleID(p.m_styleID), + m_symbolName(p.m_symbolName) { + if (m_styleID == 0) + m_styleID = p.m_skin->mapSymbol(m_symbolName.c_str()); + m_style = p.m_skin->fromID(m_styleID); + if (m_style == 0) LOG(LINFO, ("drawSymbolImpl: styleID=", m_styleID, " wasn't found on the current skin")); + else + m_symbolRect = m_style->m_texRect; + } + + SymbolElement::SymbolElement(SymbolElement const & se, math::Matrix const & m) + : OverlayElement(se), + m_styleID(0), + m_style(0), + m_symbolName(se.m_symbolName), + m_symbolRect(se.m_symbolRect) + { + setPivot(se.pivot() * m); } m2::AARectD const SymbolElement::boundRect() const { - if (m_style == 0) - return m2::AARectD(); - - m2::RectU texRect(m_style->m_texRect); + m2::RectU texRect = m_symbolRect; texRect.Inflate(-1, -1); m2::PointD posPt = tieRect(m2::RectD(texRect), math::Identity()); @@ -30,16 +44,19 @@ namespace yg return m2::RectD(posPt, posPt + m2::PointD(texRect.SizeX(), texRect.SizeY())); } - void SymbolElement::offset(m2::PointD const & offs) - { - OverlayElement::offset(offs); - } - void SymbolElement::draw(gl::OverlayRenderer * r, math::Matrix const & m) const { + if (m_styleID == 0) + { + m_styleID = r->skin()->mapSymbol(m_symbolName.c_str()); + m_style = r->skin()->fromID(m_styleID); + m_symbolRect = m_style->m_texRect; + } + if (m_style == 0) return; - m2::RectU texRect(m_style->m_texRect); + + m2::RectU texRect = m_symbolRect; texRect.Inflate(-1, -1); m2::PointD posPt = tieRect(m2::RectD(texRect), m); diff --git a/yg/symbol_element.hpp b/yg/symbol_element.hpp index 7a384b7691..092f22f160 100644 --- a/yg/symbol_element.hpp +++ b/yg/symbol_element.hpp @@ -11,22 +11,25 @@ namespace yg { private: - uint32_t m_styleID; - ResourceStyle const * m_style; + mutable uint32_t m_styleID; + mutable ResourceStyle const * m_style; + string m_symbolName; + mutable m2::RectU m_symbolRect; public: struct Params : public OverlayElement::Params { Skin * m_skin; + string m_symbolName; uint32_t m_styleID; }; SymbolElement(Params const & p); + SymbolElement(SymbolElement const & se, math::Matrix const & m); m2::AARectD const boundRect() const; void draw(gl::OverlayRenderer * s, math::Matrix const & m) const; - void offset(m2::PointD const & offs); uint32_t styleID() const; }; diff --git a/yg/text_element.cpp b/yg/text_element.cpp index 56db501956..2485f75233 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -52,8 +52,7 @@ namespace yg if ((layout.firstVisible() != 0) || (layout.lastVisible() != visText().size())) return; - m2::PointD pivot = layout.entries()[0].m_pt; - m2::PointD offset = pivot * m - pivot; + m2::PointD pv = pivot() * m; for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) { @@ -63,7 +62,7 @@ namespace yg uint32_t const glyphID = skin->mapGlyph(glyphKey, screen->glyphCache()); CharStyle const * charStyle = static_cast(skin->fromID(glyphID)); - screen->drawGlyph(elem.m_pt + offset, m2::PointD(0.0, 0.0), elem.m_angle, 0, charStyle, depth); + screen->drawGlyph(elem.m_pt + pv, m2::PointD(0.0, 0.0), elem.m_angle, 0, charStyle, depth); } } @@ -75,11 +74,20 @@ namespace yg visText(), p.m_position) { + setPivot(m_glyphLayout.pivot()); + } + + StraightTextElement::StraightTextElement(StraightTextElement const & src, math::Matrix const & m) + : TextElement(src), + m_glyphLayout(src.m_glyphLayout) + { + m_glyphLayout.setPivot(m_glyphLayout.pivot() * m); + setPivot(m_glyphLayout.pivot()); } m2::AARectD const StraightTextElement::boundRect() const { - return m2::AARectD(m_glyphLayout.limitRect()); + return m_glyphLayout.limitRect(); } void StraightTextElement::draw(gl::OverlayRenderer * screen, math::Matrix const & m) const @@ -97,12 +105,6 @@ namespace yg drawTextImpl(m_glyphLayout, screen, m, desc, yg::maxDepth); } - void StraightTextElement::offset(m2::PointD const & offs) - { - TextElement::offset(offs); - m_glyphLayout.offset(offs); - } - PathTextElement::PathTextElement(Params const & p) : TextElement(p), m_glyphLayout(p.m_glyphCache, @@ -114,11 +116,19 @@ namespace yg p.m_pathOffset, p.m_position) { + setPivot(m_glyphLayout.pivot()); + } + + PathTextElement::PathTextElement(PathTextElement const & src, math::Matrix const & m) + : TextElement(src), + m_glyphLayout(src.m_glyphLayout, m) + { + setPivot(m_glyphLayout.pivot()); } m2::AARectD const PathTextElement::boundRect() const { - return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(40, 2)); + return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(40, 2)); //< to create more sparse street names structure } void PathTextElement::draw(gl::OverlayRenderer * screen, math::Matrix const & m) const @@ -132,10 +142,4 @@ namespace yg drawTextImpl(m_glyphLayout, screen, m, desc, yg::maxDepth); } - - void PathTextElement::offset(m2::PointD const & offs) - { - TextElement::offset(offs); - m_glyphLayout.offset(offs); - } } diff --git a/yg/text_element.hpp b/yg/text_element.hpp index 28e0d9391d..5283b02887 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -61,6 +61,7 @@ namespace yg { private: + /// glyph layout aligned to pivot point GlyphLayout m_glyphLayout; public: @@ -69,10 +70,10 @@ namespace yg {}; StraightTextElement(Params const & p); + StraightTextElement(StraightTextElement const & src, math::Matrix const & m); m2::AARectD const boundRect() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; - void offset(m2::PointD const & offs); }; class PathTextElement : public TextElement @@ -92,9 +93,9 @@ namespace yg }; PathTextElement(Params const & p); + PathTextElement(PathTextElement const & src, math::Matrix const & m); m2::AARectD const boundRect() const; void draw(gl::OverlayRenderer * r, math::Matrix const & m) const; - void offset(m2::PointD const & offs); }; } diff --git a/yg/tile.hpp b/yg/tile.hpp index 1a7bfc53a6..f7195823f5 100644 --- a/yg/tile.hpp +++ b/yg/tile.hpp @@ -8,9 +8,12 @@ namespace yg { + class InfoLayer; + struct Tile { shared_ptr m_renderTarget; //< taken from resource manager + shared_ptr m_infoLayer; //< text and POI's ScreenBase m_tileScreen; //< cached to calculate it once, cause tile blitting //< is performed on GUI thread. Tiler::RectInfo m_rectInfo; //< taken from tiler @@ -20,10 +23,12 @@ namespace yg {} Tile(shared_ptr const & renderTarget, + shared_ptr const & infoLayer, ScreenBase const & tileScreen, Tiler::RectInfo const & rectInfo, double duration) : m_renderTarget(renderTarget), + m_infoLayer(infoLayer), m_tileScreen(tileScreen), m_rectInfo(rectInfo), m_duration(duration) diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index da9aacb916..6efd5fa270 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -1227,7 +1227,7 @@ namespace void DoDraw(shared_ptr const & p) { for (int i = 0; i < 40; ++i) - p->drawSymbol(m2::PointD(100 + i, 100), p->skin()->mapSymbol("hospital"), yg::EPosCenter, 0); + p->drawSymbol(m2::PointD(100 + i, 100), "hospital", yg::EPosCenter, 0); } };