diff --git a/indexer/feature.cpp b/indexer/feature.cpp index cf37cec6b5..26017c6834 100644 --- a/indexer/feature.cpp +++ b/indexer/feature.cpp @@ -127,6 +127,7 @@ bool FeatureBuilder1::operator == (FeatureBuilder1 const & fb) const m_Layer != fb.m_Layer || m_Name != fb.m_Name || m_bPoint != fb.m_bPoint || + m_bLinear != fb.m_bLinear || m_bArea != fb.m_bArea) { return false; diff --git a/map/draw_info.hpp b/map/draw_info.hpp index b591708581..fba792b873 100644 --- a/map/draw_info.hpp +++ b/map/draw_info.hpp @@ -17,7 +17,7 @@ namespace di vector m_path; // -1.0 means "not" initialized - PathInfo() : m_length(-1.0), m_offset(-1.0) {} + PathInfo(double offset = -1.0) : m_length(-1.0), m_offset(offset) {} void swap(PathInfo & r) { @@ -33,19 +33,27 @@ namespace di size_t size() const { return m_path.size(); } - // lazy evaluation of path's length + void SetLength(double len) { m_length = len; } + double GetLength() const { // m_length not initialized - calculate it - if (m_length < 0.0) - { - m_length = 0.0; - for (size_t i = 1; i < m_path.size(); ++i) - m_length += m_path[i-1].Length(m_path[i]); - } + //if (m_length < 0.0) + //{ + // m_length = 0.0; + // for (size_t i = 1; i < m_path.size(); ++i) + // m_length += m_path[i-1].Length(m_path[i]); + //} + ASSERT ( m_length > 0.0, (m_length) ); return m_length; } + + double GetOffset() const + { + ASSERT ( m_offset >= 0.0, (m_offset) ); + return m_offset; + } }; class AreaInfo diff --git a/map/draw_processor.cpp b/map/draw_processor.cpp index 53f7d81153..31744e7904 100644 --- a/map/draw_processor.cpp +++ b/map/draw_processor.cpp @@ -3,8 +3,11 @@ #include "../geometry/screenbase.hpp" #include "../geometry/rect_intersect.hpp" +#include "../std/bind.hpp" + #include "../base/start_mem_debug.hpp" + namespace get_pts { using namespace di; @@ -34,12 +37,12 @@ void one_point::operator() (CoordPointT const & p) else m_exist = false; } -void path_points::StartPL() +void path_points::StartPL(m2::PointD const & pt) { EndPL(); - m_points.push_back(PathInfo()); - push_point(m_prev); + m_points.push_back(PathInfo(m_length + m_prev.Length(pt))); + push_point(pt); m_newPL = false; } @@ -59,13 +62,18 @@ void path_points::simple_filtration(m2::PointD const & pt) else { if (m_newPL) - StartPL(); + StartPL(m_prev); push_point(pt); } + + m_length += m_prev.Length(pt); } else + { m_prevPt = true; + m_length = 0.0; + } m_prev = pt; } @@ -76,27 +84,30 @@ void path_points::best_filtration(m2::PointD const & pt) { m2::PointD prev = m_prev; m2::PointD curr = pt; + if (!m2::Intersect(m_rect, prev, curr)) m_newPL = true; else { if (!equal_glb_pts(prev, m_prev)) - { - m_prev = prev; m_newPL = true; - } if (m_newPL) - StartPL(); + StartPL(prev); push_point(curr); if (!equal_glb_pts(curr, pt)) m_newPL = true; } + + m_length += m_prev.Length(pt); } else + { m_prevPt = true; + m_length = 0.0; + } m_prev = pt; } @@ -109,6 +120,15 @@ void path_points::operator() (m2::PointD const & p) best_filtration(p); } +bool path_points::IsExist() +{ + // finally, assign whole length to every cutted path + for_each(m_points.begin(), m_points.end(), bind(&di::PathInfo::SetLength, _1, m_length)); + + EndPL(); + return base_type::IsExist(); +} + void area_tess_points::StartPrimitive(size_t ptsCount) { m_points.push_back(AreaInfo()); diff --git a/map/draw_processor.hpp b/map/draw_processor.hpp index 0a08766905..166c403ce8 100644 --- a/map/draw_processor.hpp +++ b/map/draw_processor.hpp @@ -112,9 +112,10 @@ namespace get_pts bool m_newPL, m_prevPt; m2::PointD m_prev; - size_t m_count; - void StartPL(); + double m_length; + + void StartPL(m2::PointD const & pt); void EndPL(); static bool equal_glb_pts(m2::PointD const & p1, m2::PointD const & p2) @@ -127,17 +128,13 @@ namespace get_pts public: path_points(ScreenBase const & convertor, m2::RectD const & rect) - : base_type(convertor, rect), m_newPL(true), m_prevPt(false) + : base_type(convertor, rect), m_newPL(true), m_prevPt(false), m_length(0.0) { } void operator() (m2::PointD const & p); - bool IsExist() - { - EndPL(); - return base_type::IsExist(); - } + bool IsExist(); }; /// @name Policies for filling area. diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index c3da196298..73aaecafcc 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -142,7 +142,7 @@ void DrawerYG::drawArea(vector const & pts, rule_ptr_t pRule, int de uint8_t DrawerYG::get_font_size(rule_ptr_t pRule) { - /// @todo calc font size + /// @todo calculate font size return static_cast(pRule->GetTextHeight() * m_scale * m_visualScale); } @@ -152,11 +152,14 @@ void DrawerYG::drawText(m2::PointD const & pt, string const & name, rule_ptr_t p m_pScreen->drawText(pt, 0.0, fontSize, name, depth); } -void DrawerYG::drawPathText(vector const & pts, double pathLength, string const & name, rule_ptr_t pRule, int /*depth*/) +void DrawerYG::drawPathText(di::PathInfo const & info, string const & name, rule_ptr_t pRule, int /*depth*/) { uint8_t fontSize = get_font_size(pRule) - 2; if (fontSize >= yg::minTextSize * m_visualScale) - m_pScreen->drawPathText(&pts[0], pts.size(), fontSize, name, pathLength, yg::gl::Screen::middle_line, true, yg::maxDepth); + { + m_pScreen->drawPathText(&info.m_path[0], info.m_path.size(), fontSize, name, info.GetLength(), info.GetOffset(), + yg::gl::Screen::middle_line, true, yg::maxDepth); + } } shared_ptr DrawerYG::screen() const @@ -231,7 +234,7 @@ void DrawerYG::Draw(di::DrawInfo const * pInfo, rule_ptr_t pRule, int depth) if (isPath && !isArea && isN) { for (list::const_iterator i = pInfo->m_pathes.begin(); i != pInfo->m_pathes.end(); ++i) - drawPathText(i->m_path, i->GetLength(), pInfo->m_name, pRule, depth); + drawPathText(*i, pInfo->m_name, pRule, depth); } // draw point text diff --git a/map/drawer_yg.hpp b/map/drawer_yg.hpp index 8487f0d8e6..ce4ad78d63 100644 --- a/map/drawer_yg.hpp +++ b/map/drawer_yg.hpp @@ -61,7 +61,7 @@ protected: void drawArea(vector const & pts, rule_ptr_t pRule, int depth); void drawText(m2::PointD const & pt, string const & name, rule_ptr_t pRule, int depth); - void drawPathText(vector const & pts, double pathLength, string const & name, rule_ptr_t pRule, int depth); + void drawPathText(di::PathInfo const & info, string const & name, rule_ptr_t pRule, int depth); typedef shared_ptr texture_t; typedef shared_ptr frame_buffer_t; diff --git a/yg/geometry_batcher.cpp b/yg/geometry_batcher.cpp index d1a08425be..4f264d7f10 100644 --- a/yg/geometry_batcher.cpp +++ b/yg/geometry_batcher.cpp @@ -619,9 +619,11 @@ namespace yg * / or \ * o \ */ - double const a = ang::AngleTo(get(0), get(1)); - if (fabs(a) > math::pi / 2.0) - m_reverse = true; + + /// @todo temporary removed - need to synchronize with path offset + //double const a = ang::AngleTo(get(0), get(1)); + //if (fabs(a) > math::pi / 2.0) + // m_reverse = true; } size_t size() const { return m_size; } @@ -659,16 +661,18 @@ namespace yg return true; } - void GeometryBatcher::drawPathText(m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, TextPos pos, bool isMasked, double depth, bool isFixedFont) + void GeometryBatcher::drawPathText( + m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, + double fullLength, double pathOffset, TextPos pos, bool isMasked, double depth, bool isFixedFont) { if (isMasked) - drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, true, depth, isFixedFont); - drawPathTextImpl(path, s, fontSize, utf8Text, pathLength, pos, false, depth, isFixedFont); + drawPathTextImpl(path, s, fontSize, utf8Text, fullLength, pathOffset, pos, true, depth, isFixedFont); + drawPathTextImpl(path, s, fontSize, utf8Text, fullLength, pathOffset, pos, false, depth, isFixedFont); } - void GeometryBatcher::drawPathTextImpl(m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, TextPos pos, bool fromMask, double depth, bool isFixedFont) + void GeometryBatcher::drawPathTextImpl( + m2::PointD const * path, size_t s, uint8_t fontSize, string const & utf8Text, + double fullLength, double pathOffset, TextPos pos, bool fromMask, double depth, bool isFixedFont) { pts_array arrPath(path, s); @@ -679,7 +683,7 @@ namespace yg // fontSize = translateFontSize(fontSize); - // calc base line offset + // calculate base line offset float blOffset = 2; switch (pos) { @@ -688,34 +692,45 @@ namespace yg case above_line: blOffset -= 0; break; } - // calc string length + size_t const count = text.size(); + vector glyphs(count); + + // get vector of glyphs and calculate string length double strLength = 0.0; - for (size_t i = 0; i < text.size(); ++i) + for (size_t i = 0; i < count; ++i) { - uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask), isFixedFont); - CharStyle const * p = static_cast(m_skin->fromID(glyphID)); - strLength += p->m_xAdvance; + uint32_t const glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask), isFixedFont); + glyphs[i] = static_cast(m_skin->fromID(glyphID)); + strLength += glyphs[i]->m_xAdvance; } - // offset of the text fromt path's start - double offset = (pathLength - strLength) / 2.0; + // offset of the text from path's start + double offset = (fullLength - strLength) / 2.0; if (offset < 0.0) return; + offset -= pathOffset; + if (-offset >= strLength) return; + + // find first visible glyph + size_t i = 0; + while (offset < 0) + { + offset += glyphs[i]->m_xAdvance; + ++i; + } size_t ind = 0; m2::PointD ptOrg = arrPath[0]; double angle = angle_not_inited; - for (size_t i = 0; i < text.size(); ++i) + // draw visible glyphs + for (; i < count; ++i) { if (!CalcPointAndAngle(arrPath, offset, ind, ptOrg, angle)) break; - uint32_t glyphID = m_skin->mapGlyph(GlyphKey(text[i], fontSize, fromMask), isFixedFont); - CharStyle const * p = static_cast(m_skin->fromID(glyphID)); + drawGlyph(ptOrg, m2::PointD(0.0, 0.0), angle, blOffset, glyphs[i], depth); - drawGlyph(ptOrg, m2::PointD(0.0, 0.0), angle, blOffset, p, depth); - - offset = p->m_xAdvance; + offset = glyphs[i]->m_xAdvance; } } diff --git a/yg/geometry_batcher.hpp b/yg/geometry_batcher.hpp index 9938765e0b..489528a134 100644 --- a/yg/geometry_batcher.hpp +++ b/yg/geometry_batcher.hpp @@ -85,7 +85,8 @@ namespace yg size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, + double fullLength, + double pathOffset, TextPos pos, bool fromMask, double depth, @@ -142,7 +143,8 @@ namespace yg size_t s, uint8_t fontSize, string const & utf8Text, - double pathLength, + double fullLength, + double pathOffset, TextPos pos, bool isMasked, double depth, diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 314b6a5d1e..52eaffabf3 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -521,7 +521,7 @@ namespace void DoDraw(shared_ptr p) { p->drawPath(&m_path[0], m_path.size(), p->skin()->mapPenInfo(m_penInfo), 0); - p->drawPathText(&m_path[0], m_path.size(), 10, m_text, calc_length(m_path), yg::gl::Screen::middle_line, true, 0); + p->drawPathText(&m_path[0], m_path.size(), 10, m_text, calc_length(m_path), 0.0, yg::gl::Screen::middle_line, true, 0); } }; @@ -532,8 +532,8 @@ namespace p->drawPath(&m_path[0], m_path.size(), p->skin()->mapPenInfo(m_penInfo), 0); double const len = calc_length(m_path); - p->drawPathText(&m_path[0], m_path.size(), 10, m_text, len, yg::gl::Screen::above_line, true, 0); - p->drawPathText(&m_path[0], m_path.size(), 10, m_text, len, yg::gl::Screen::under_line, true, 0); + p->drawPathText(&m_path[0], m_path.size(), 10, m_text, len, 0.0, yg::gl::Screen::above_line, true, 0); + p->drawPathText(&m_path[0], m_path.size(), 10, m_text, len, 0.0, yg::gl::Screen::under_line, true, 0); } };