From 36d13856f54de74d79e04fa38c793f6d3b364178 Mon Sep 17 00:00:00 2001 From: rachytski Date: Wed, 8 Jun 2011 22:10:13 +0300 Subject: [PATCH] much better drawPathText implementation. --- geometry/aa_rect2d.hpp | 176 ++++++++++++++++++------ geometry/geometry_tests/aarect_test.cpp | 15 ++ map/framework.cpp | 11 +- map/information_display.cpp | 2 +- map/map_tests/draw_processor_test.cpp | 48 +++++++ map/map_tests/map_tests.pro | 1 + yg/glyph_layout.cpp | 141 ++++++++++++------- yg/glyph_layout.hpp | 6 +- yg/shape_renderer.cpp | 27 ++++ yg/shape_renderer.hpp | 3 + yg/text_element.cpp | 29 ++-- yg/text_element.hpp | 9 +- yg/text_renderer.cpp | 9 +- yg/yg_tests/screengl_test.cpp | 59 ++++---- 14 files changed, 391 insertions(+), 145 deletions(-) create mode 100644 map/map_tests/draw_processor_test.cpp diff --git a/geometry/aa_rect2d.hpp b/geometry/aa_rect2d.hpp index 42b9210ea5..4f0096d79c 100644 --- a/geometry/aa_rect2d.hpp +++ b/geometry/aa_rect2d.hpp @@ -2,6 +2,8 @@ #include "point2d.hpp" #include "rect2d.hpp" +#include "rect_intersect.hpp" +#include "../base/math.hpp" #include namespace m2 @@ -21,11 +23,8 @@ namespace m2 Point const & fromI, Point const & fromJ, Point const & toI, - Point const & toJ) + Point const & toJ) const { - Point i(1, 0); - Point j(0, 1); - Point res; res.x = p.x * DotProduct(fromI, toI) + p.y * DotProduct(fromJ, toI); @@ -34,76 +33,118 @@ namespace m2 return res; } - Point const CoordConvertTo(Point const & p) - { - Point i(1, 0); - Point j(0, 1); - - Point res; - - res.x = p.x * DotProduct(i, m_i) + p.y * DotProduct(j, m_i); - res.y = p.x * DotProduct(i, m_j) + p.y * DotProduct(j, m_j); - - return res; - } - - Point const CoordConvertFrom(Point const & p) - { - Point res; - - Point i(1, 0); - Point j(0, 1); - - res.x = p.x * DotProduct(m_i, i) + p.y * DotProduct(m_j, i); - res.y = p.x * DotProduct(m_i, j) + p.y * DotProduct(m_j, j); - - return res; - } - public: + AARect(){} + + /// creating from regular rect + AARect(Rect const & r) + : m_i(1, 0), m_j(0, 1), + m_zero(r == Rect() ? Point(0, 0) : Point(r.minX(), r.minY())), + m_rect(r == Rect() ? Rect() : Rect(0, 0, r.SizeX(), r.SizeY())) + { + } + AARect(Point const & zero, T const & angle, Rect const & r) : m_i(cos(angle), sin(angle)), m_j(-sin(angle), cos(angle)), - m_zero(CoordConvertTo(zero)), + m_zero(Convert(zero, Point(1, 0), Point(0, 1), m_i, m_j)), m_rect(r) { } - bool IsPointInside(Point const & pt); - bool IsIntersect(AARect const & r); + Point const & zero() const + { + return m_zero; + } - Point const ConvertTo(Point const & p) + Point const & i() const + { + return m_i; + } + + Point const & j() const + { + return m_j; + } + + bool IsPointInside(Point const & pt) const + { + return m_rect.IsPointInside(ConvertTo(pt)); + } + + bool IsRectInside(AARect const & r) const + { + m2::Point pts[4]; + r.GetGlobalPoints(pts); + ConvertTo(pts, 4); + return m_rect.IsPointInside(pts[0]) + && m_rect.IsPointInside(pts[1]) + && m_rect.IsPointInside(pts[2]) + && m_rect.IsPointInside(pts[3]); + } + + bool IsIntersect(AARect const & r) const + { + m2::Point pts[4]; + if (r.GetLocalRect() == Rect()) + return false; + r.GetGlobalPoints(pts); + ConvertTo(pts, 4); + + m2::Rect r1(pts[0], pts[0]); + r1.Add(pts[1]); + r1.Add(pts[2]); + r1.Add(pts[3]); + + if (!GetLocalRect().IsIntersect(r1)) + return false; + + if (r.IsRectInside(*this)) + return true; + + if (IsRectInside(r)) + return true; + + return Intersect(GetLocalRect(), pts[0], pts[1]) + || Intersect(GetLocalRect(), pts[1], pts[2]) + || Intersect(GetLocalRect(), pts[2], pts[3]) + || Intersect(GetLocalRect(), pts[3], pts[0]); + } + + /// Convert into coordinate system of this AARect + Point const ConvertTo(Point const & p) const { m2::PointD i(1, 0); m2::PointD j(0, 1); - return Convert(p - Convert(m_zero, m_i, m_j, i, j), i, j, m_i, m_j); + m2::PointD res = Convert(p - Convert(m_zero, m_i, m_j, i, j), i, j, m_i, m_j); } - void ConvertTo(Point * pts, size_t count) + void ConvertTo(Point * pts, size_t count) const { for (size_t i = 0; i < count; ++i) pts[i] = ConvertTo(pts[i]); } - Point const ConvertFrom(Point const & p) + /// Convert into global coordinates from the local coordinates of this AARect + Point const ConvertFrom(Point const & p) const { m2::PointD i(1, 0); m2::PointD j(0, 1); return Convert(p + m_zero, m_i, m_j, i, j); } - void ConvertFrom(Point * pts, size_t count) + void ConvertFrom(Point * pts, size_t count) const { for (size_t i = 0; i < count; ++i) pts[i] = ConvertFrom(pts[i]); } - Rect const GetLocalRect() + Rect const GetLocalRect() const { return m_rect; } - Rect const GetGlobalRect() + Rect const GetGlobalRect() const { Point pts[4]; GetGlobalPoints(pts); @@ -117,15 +158,60 @@ namespace m2 return res; } - void GetGlobalPoints(Point * pts) + template + void GetGlobalPoints(Point * pts) const { - pts[0] = ConvertFrom(Point(m_rect.minX(), m_rect.minY())); - pts[1] = ConvertFrom(Point(m_rect.minX(), m_rect.maxY())); - pts[2] = ConvertFrom(Point(m_rect.maxX(), m_rect.maxY())); - pts[3] = ConvertFrom(Point(m_rect.maxX(), m_rect.minY())); + pts[0] = Point(ConvertFrom(Point(m_rect.minX(), m_rect.minY()))); + pts[1] = Point(ConvertFrom(Point(m_rect.minX(), m_rect.maxY()))); + pts[2] = Point(ConvertFrom(Point(m_rect.maxX(), m_rect.maxY()))); + pts[3] = Point(ConvertFrom(Point(m_rect.maxX(), m_rect.minY()))); + } + + template + void Inflate(U const & dx, U const & dy) + { + m_rect.Inflate(dx, dy); + } + + void Add(AARect const & r) + { + Point pts[4]; + r.GetGlobalPoints(pts); + ConvertTo(pts, 4); + m_rect.Add(pts[0]); + m_rect.Add(pts[1]); + m_rect.Add(pts[2]); + m_rect.Add(pts[3]); + } + + void Offset(Point const & p) + { + m_zero = ConvertTo(ConvertFrom(m_zero) + p); } }; + template + AARect const Offset(AARect const & r, Point const & pt) + { + AARect res(r); + res.Offset(pt); + return res; + } + + template + AARect const Inflate(AARect const & r, U const & dx, U const & dy) + { + AARect res = r; + res.Inflate(dx, dy); + return res; + } + + template + AARect const Inflate(AARect const & r, Point const & pt) + { + return Inflate(r, pt.x, pt.y); + } + typedef AARect AARectD; typedef AARect AARectF; } diff --git a/geometry/geometry_tests/aarect_test.cpp b/geometry/geometry_tests/aarect_test.cpp index 2f7960921c..0db9f895bb 100644 --- a/geometry/geometry_tests/aarect_test.cpp +++ b/geometry/geometry_tests/aarect_test.cpp @@ -48,3 +48,18 @@ UNIT_TEST(AARect_TestIntersection) TEST(r1.GetLocalRect().IsIntersect(r2) == false, ()); } +UNIT_TEST(AARect_TestIsIntersect) +{ + m2::AARectD r0(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, 0, 50, 20)); + m2::AARectD r1(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, -10, 50, 10)); + m2::AARectD r2(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, -21, 50, -1)); + + TEST(r0.IsIntersect(r1), ()); + TEST(r1.IsIntersect(r2), ()); + TEST(!r0.IsIntersect(r2), ()); + TEST(r1.IsIntersect(r2), ()); + + m2::AARectD r3(m2::PointD(50, 50), math::pi / 8, m2::RectD(0, 0, 80, 30)); + TEST(r0.IsIntersect(r3), ()); +} + diff --git a/map/framework.cpp b/map/framework.cpp index dc11ef9c2d..abeed0199d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -149,6 +149,14 @@ namespace fwork m_drawCount += count; #endif + // remove duplicating identical drawing keys + PreProcessKeys(); + +#ifdef PROFILER_DRAWING + m_drawCount += m_keys.size(); +#endif + + buffer_vector rules; rules.resize(count); @@ -230,7 +238,7 @@ namespace fwork for (size_t i = 0; i < count; ++i) { if (pDrawer->filter_text_size(rules[i].m_rule)) - fontSize = pDrawer->get_pathtext_font_size(rules[i].m_rule); + fontSize = max((uint8_t)fontSize, pDrawer->get_pathtext_font_size(rules[i].m_rule)); } if (fontSize != 0) @@ -255,6 +263,7 @@ namespace fwork functor_t fun(p); GET_POINTS(f, ForEachPointRef, fun, assign_path) + break; } } diff --git a/map/information_display.cpp b/map/information_display.cpp index a6c846bfe5..f87fe9147b 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -222,7 +222,7 @@ void InformationDisplay::drawCenter(DrawerYG * drawer) yg::StraightTextElement ste(params); - m2::RectD bgRect = m2::Inflate(ste.boundRect(), 5.0, 5.0); + m2::AARectD bgRect = m2::Inflate(ste.boundRect(), 5.0, 5.0); drawer->screen()->drawRectangle( bgRect, diff --git a/map/map_tests/draw_processor_test.cpp b/map/map_tests/draw_processor_test.cpp new file mode 100644 index 0000000000..4c79ce2590 --- /dev/null +++ b/map/map_tests/draw_processor_test.cpp @@ -0,0 +1,48 @@ +#include "../../base/SRC_FIRST.hpp" + +#include "../../testing/testing.hpp" +#include "../../geometry/screenbase.hpp" +#include "../../base/logging.hpp" + +#include "../draw_processor.hpp" + + +UNIT_TEST(PathPoints_DeadZoneClipping) +{ + m2::PointD pts[10] = + { + m2::PointD(0, 0), + m2::PointD(10, 0), + m2::PointD(10, 10), + m2::PointD(20, 10), + m2::PointD(20, 0), + m2::PointD(30, 0), + m2::PointD(30, 20), + m2::PointD(80, 20), + m2::PointD(80, 0), + m2::PointD(90, 0) + }; + + ScreenBase s; + s.OnSize(45 - 640, 0, 640, 480); + + m2::RectD r = s.GlobalRect(); + + get_pts::path_points::params p; + p.m_startLength = 80; + p.m_endLength = 90; + p.m_convertor = &s; + p.m_rect = &r; + get_pts::path_points fun(p); + + for (unsigned i = 0; i < 10; ++i) + fun(pts[i]); + + fun.IsExist(); + + int pathCount = fun.m_points.size(); + + di::PathInfo pi = fun.m_points.front(); + vector pts1 = fun.m_points.front().m_path; +// LOG(LINFO, (pts1)); +} diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index b9bf37ff8f..0c40e6660f 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -24,3 +24,4 @@ SOURCES += \ navigator_test.cpp \ map_foreach_test.cpp \ debug_features_test.cpp \ + draw_processor_test.cpp diff --git a/yg/glyph_layout.cpp b/yg/glyph_layout.cpp index 514b6465f7..94feeec1ab 100644 --- a/yg/glyph_layout.cpp +++ b/yg/glyph_layout.cpp @@ -201,6 +201,10 @@ namespace yg { m2::PointD pv = pt; + m2::RectD limitRect; + + bool isFirst = true; + for (size_t i = 0; i < text.size(); ++i) { GlyphKey glyphKey(text[i], fontDesc.m_size, fontDesc.m_isMasked, fontDesc.m_color); @@ -211,16 +215,19 @@ namespace yg CharStyle const * p = static_cast(skin->fromID(glyphID)); if (p != 0) { - if (i == 0) - m_limitRect = m2::RectD(p->m_xOffset + pv.x, - -p->m_yOffset + pv.y, - p->m_xOffset + pv.x, - -p->m_yOffset + pv.y); + if (isFirst) + { + limitRect = m2::RectD(p->m_xOffset + pv.x, + -p->m_yOffset + pv.y, + p->m_xOffset + pv.x, + -p->m_yOffset + pv.y); + isFirst = false; + } else - m_limitRect.Add(m2::PointD(p->m_xOffset, -p->m_yOffset) + pv); + limitRect.Add(m2::PointD(p->m_xOffset, -p->m_yOffset) + pv); - m_limitRect.Add(m2::PointD(p->m_xOffset + p->m_texRect.SizeX() - 4, - -(p->m_yOffset + (int)p->m_texRect.SizeY() - 4)) + pv); + limitRect.Add(m2::PointD(p->m_xOffset + p->m_texRect.SizeX() - 4, + -(p->m_yOffset + (int)p->m_texRect.SizeY() - 4)) + pv); } @@ -229,29 +236,29 @@ namespace yg elem.m_sym = text[i]; elem.m_angle = 0; elem.m_pt = pv; - elem.m_metrics.m_height = p->m_texRect.SizeY() - 4; - elem.m_metrics.m_width = p->m_texRect.SizeX() - 4; - elem.m_metrics.m_xAdvance = p->m_xAdvance; - elem.m_metrics.m_xOffset = p->m_xOffset; - elem.m_metrics.m_yOffset = p->m_yOffset; + elem.m_metrics.m_height = p ? p->m_texRect.SizeY() - 4 : 0; + elem.m_metrics.m_width = p ? p->m_texRect.SizeX() - 4 : 0; + elem.m_metrics.m_xAdvance = p ? p->m_xAdvance : 0; + elem.m_metrics.m_xOffset = p ? p->m_xOffset : 0; + elem.m_metrics.m_yOffset = p ? p->m_yOffset : 0; elem.m_metrics.m_yAdvance = 0; m_entries.push_back(elem); - pv += m2::PointD(p->m_xAdvance, 0); + pv += m2::PointD(p ? p->m_xAdvance : 0, 0); } else { GlyphMetrics const m = resourceManager->getGlyphMetrics(glyphKey); if (i == 0) - m_limitRect = m2::RectD(m.m_xOffset + pv.x, + limitRect = m2::RectD(m.m_xOffset + pv.x, -m.m_yOffset + pv.y, m.m_xOffset + pv.x, -m.m_yOffset + pv.y); else - m_limitRect.Add(m2::PointD(m.m_xOffset, -m.m_yOffset) + pv); + limitRect.Add(m2::PointD(m.m_xOffset, -m.m_yOffset) + pv); - m_limitRect.Add(m2::PointD(m.m_xOffset + m.m_width, + limitRect.Add(m2::PointD(m.m_xOffset + m.m_width, -(m.m_yOffset + m.m_height)) + pv); GlyphLayoutElem elem; @@ -265,24 +272,28 @@ namespace yg } } - m_limitRect.Inflate(2, 2); + limitRect.Inflate(2, 2); - m2::PointD ptOffs(-m_limitRect.SizeX() / 2, - -m_limitRect.SizeY() / 2); + m2::PointD ptOffs(-limitRect.SizeX() / 2, + -limitRect.SizeY() / 2); /// adjusting according to position if (pos & EPosLeft) - ptOffs += m2::PointD(-m_limitRect.SizeX() / 2, 0); + ptOffs += m2::PointD(-limitRect.SizeX() / 2, 0); if (pos & EPosRight) - ptOffs += m2::PointD(m_limitRect.SizeX() / 2, 0); + ptOffs += m2::PointD(limitRect.SizeX() / 2, 0); if (pos & EPosAbove) - ptOffs += m2::PointD(0, m_limitRect.SizeY() / 2); + ptOffs += m2::PointD(0, limitRect.SizeY() / 2); if (pos & EPosUnder) - ptOffs += m2::PointD(0, -m_limitRect.SizeY() / 2); + ptOffs += m2::PointD(0, -limitRect.SizeY() / 2); + + m_limitRect = m2::AARectD(limitRect); offset(ptOffs); + + } @@ -423,33 +434,71 @@ namespace yg m_lastVisible = symPos + 1; } - bool isFirst = true; + computeMinLimitRect(); + } + + void GlyphLayout::computeMinLimitRect() + { + map rects; for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) { - m2::AARectD symRectAA( - m_entries[i].m_pt.Move(m_entries[i].m_metrics.m_height, m_entries[i].m_angle - math::pi / 2), - m_entries[i].m_angle, - m2::RectD(m_entries[i].m_metrics.m_xOffset, - m_entries[i].m_metrics.m_yOffset, - m_entries[i].m_metrics.m_xOffset + m_entries[i].m_metrics.m_width, - m_entries[i].m_metrics.m_yOffset + m_entries[i].m_metrics.m_height)); - - m2::PointD pts[4]; - symRectAA.GetGlobalPoints(pts); - - if (isFirst) + if (m_entries[i].m_metrics.m_width != 0) { - m_limitRect = m2::RectD(pts[0].x, pts[0].y, pts[0].x, pts[0].y); - isFirst = false; - } - else - m_limitRect.Add(pts[0]); + map::iterator it = rects.find(m_entries[i].m_angle); - m_limitRect.Add(pts[1]); - m_limitRect.Add(pts[2]); - m_limitRect.Add(pts[3]); + if (it == rects.end()) + { + m2::AARectD symRectAA( + m_entries[i].m_pt.Move(m_entries[i].m_metrics.m_height, m_entries[i].m_angle - math::pi / 2), + m_entries[i].m_angle, + m2::RectD(m_entries[i].m_metrics.m_xOffset, + m_entries[i].m_metrics.m_yOffset, + m_entries[i].m_metrics.m_xOffset + m_entries[i].m_metrics.m_width, + m_entries[i].m_metrics.m_yOffset + m_entries[i].m_metrics.m_height + )); + + rects[m_entries[i].m_angle] = symRectAA; + } + } } + + for (unsigned i = m_firstVisible; i < m_lastVisible; ++i) + { + if (m_entries[i].m_metrics.m_width != 0) + { + m2::AARectD symRectAA( + m_entries[i].m_pt.Move(m_entries[i].m_metrics.m_height, m_entries[i].m_angle - math::pi / 2), + m_entries[i].m_angle, + m2::RectD(m_entries[i].m_metrics.m_xOffset, + m_entries[i].m_metrics.m_yOffset, + m_entries[i].m_metrics.m_xOffset + m_entries[i].m_metrics.m_width, + m_entries[i].m_metrics.m_yOffset + m_entries[i].m_metrics.m_height)); + + for (map::iterator it = rects.begin(); it != rects.end(); ++it) + it->second.Add(symRectAA); + } + } + + double square = numeric_limits::max(); + + for (map::iterator it = rects.begin(); it != rects.end(); ++it) + { + m2::RectD r = it->second.GetLocalRect(); + if (square > r.SizeX() * r.SizeY()) + { + m_limitRect = it->second; + square = r.SizeX() * r.SizeY(); + } + } + + m2::PointD zero = m_limitRect.zero(); + zero = m_limitRect.ConvertFrom(zero); + + double dx = zero.x - floor(zero.x); + double dy = zero.y - floor(zero.y); + + m_limitRect.Offset(m2::PointD(-dx, -dy)); } size_t GlyphLayout::firstVisible() const @@ -467,7 +516,7 @@ namespace yg return m_entries; } - m2::RectD const GlyphLayout::limitRect() const + m2::AARectD const GlyphLayout::limitRect() const { return m_limitRect; } diff --git a/yg/glyph_layout.hpp b/yg/glyph_layout.hpp index 83e7e1dfc2..f4a57d8911 100644 --- a/yg/glyph_layout.hpp +++ b/yg/glyph_layout.hpp @@ -3,6 +3,7 @@ #include "defines.hpp" #include "../geometry/rect2d.hpp" #include "../geometry/point2d.hpp" +#include "../geometry/aa_rect2d.hpp" #include "../std/vector.hpp" #include "../std/string.hpp" @@ -37,9 +38,10 @@ namespace yg vector m_entries; - m2::RectD m_limitRect; + m2::AARectD m_limitRect; double getKerning(GlyphLayoutElem const & prevElem, GlyphLayoutElem const & curElem); + void computeMinLimitRect(); public: @@ -66,7 +68,7 @@ namespace yg vector const & entries() const; - m2::RectD const limitRect() const; + m2::AARectD const limitRect() const; void offset(m2::PointD const & offs); }; diff --git a/yg/shape_renderer.cpp b/yg/shape_renderer.cpp index 7e9d9c5cd3..ca7413ce25 100644 --- a/yg/shape_renderer.cpp +++ b/yg/shape_renderer.cpp @@ -69,6 +69,33 @@ namespace yg drawTrianglesList(§orPts[0], sectorPts.size(), skin()->mapColor(c), depth); } + void ShapeRenderer::drawRectangle(m2::AARectD const & r, yg::Color const & c, double depth) + { + ResourceStyle const * style = skin()->fromID(skin()->mapColor(c)); + + if (style == 0) + { + LOG(LINFO, ("cannot map color")); + return; + } + + m2::PointF rectPts[4]; + + r.GetGlobalPoints(rectPts); + swap(rectPts[2], rectPts[3]); + + m2::PointF texPt = skin()->pages()[style->m_pageID]->texture()->mapPixel(style->m_texRect.Center()); + + addTexturedStripStrided( + rectPts, + sizeof(m2::PointF), + &texPt, + 0, + 4, + depth, + style->m_pageID); + } + void ShapeRenderer::drawRectangle(m2::RectD const & r, yg::Color const & c, double depth) { ResourceStyle const * style = skin()->fromID(skin()->mapColor(c)); diff --git a/yg/shape_renderer.hpp b/yg/shape_renderer.hpp index 6a8d203b85..af5f5f2ba5 100644 --- a/yg/shape_renderer.hpp +++ b/yg/shape_renderer.hpp @@ -1,6 +1,8 @@ #pragma once #include "path_renderer.hpp" +#include "../geometry/rect2d.hpp" +#include "../geometry/aa_rect2d.hpp" namespace yg { @@ -19,6 +21,7 @@ namespace yg void drawSector(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth); void fillSector(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth); + void drawRectangle(m2::AARectD const & r, yg::Color const & c, double depth); void drawRectangle(m2::RectD const & r, yg::Color const & c, double depth); }; } diff --git a/yg/text_element.cpp b/yg/text_element.cpp index 050b7a7b98..a4ab13407d 100644 --- a/yg/text_element.cpp +++ b/yg/text_element.cpp @@ -57,6 +57,7 @@ namespace yg : OverlayElement(p), m_fontDesc(p.m_fontDesc), m_utf8Text(p.m_utf8Text), + m_text(strings::FromUtf8(p.m_utf8Text)), m_depth(p.m_depth), m_log2vis(p.m_log2vis), m_rm(p.m_rm), @@ -69,6 +70,11 @@ namespace yg return m_utf8Text; } + wstring const & TextElement::text() const + { + return m_text; + } + FontDesc const & TextElement::fontDesc() const { return m_fontDesc; @@ -81,6 +87,8 @@ namespace yg void TextElement::drawTextImpl(GlyphLayout const & layout, gl::TextRenderer * screen, FontDesc const & fontDesc, double depth) const { + if (layout.lastVisible() != text().size()) + return; for (unsigned i = layout.firstVisible(); i < layout.lastVisible(); ++i) { shared_ptr skin = screen->skin(); @@ -103,9 +111,9 @@ namespace yg { } - m2::RectD const StraightTextElement::boundRect() const + m2::AARectD const StraightTextElement::boundRect() const { - return m_glyphLayout.limitRect(); + return m2::AARectD(m_glyphLayout.limitRect()); } void StraightTextElement::draw(gl::TextRenderer * screen) const @@ -146,29 +154,22 @@ namespace yg copy(p.m_pts, p.m_pts + p.m_ptsCount, m_pts.begin()); } - m2::RectD const PathTextElement::boundRect() const + m2::AARectD const PathTextElement::boundRect() const { - return m_glyphLayout.limitRect(); + return m2::Inflate(m_glyphLayout.limitRect(), m2::PointD(40, 2)); } void PathTextElement::draw(gl::TextRenderer * screen) const { -/* yg::PenInfo penInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0); - screen->drawPath(&m_pts[0], m_pts.size(), 0, screen->skin()->mapPenInfo(penInfo), yg::maxDepth - 2); - if (boundRect().SizeX() > 500) - { - LOG(LINFO, (strings::FromUtf8(utf8Text()).c_str())); - } - screen->drawRectangle(boundRect(), yg::Color(rand() % 255, rand() % 255, rand() % 255, 64), yg::maxDepth - 3); -*/ +// screen->drawRectangle(boundRect(), yg::Color(0, 0, 255, 32), yg::maxDepth - 3); yg::FontDesc desc = m_fontDesc; if (m_fontDesc.m_isMasked) { - drawTextImpl(m_glyphLayout, screen, m_fontDesc, yg::maxDepth); + drawTextImpl(m_glyphLayout, screen, m_fontDesc, m_depth); desc.m_isMasked = false; } - drawTextImpl(m_glyphLayout, screen, desc, yg::maxDepth); + drawTextImpl(m_glyphLayout, screen, desc, m_depth); } void PathTextElement::draw(gl::Screen * screen) const diff --git a/yg/text_element.hpp b/yg/text_element.hpp index ef0cb283b2..674e134bdf 100644 --- a/yg/text_element.hpp +++ b/yg/text_element.hpp @@ -2,6 +2,7 @@ #include "../geometry/point2d.hpp" #include "../geometry/rect2d.hpp" +#include "../geometry/aa_rect2d.hpp" #include "../std/shared_ptr.hpp" @@ -38,7 +39,7 @@ namespace yg OverlayElement(Params const & p); virtual void offset(m2::PointD const & offs) = 0; - virtual m2::RectD const boundRect() const = 0; + virtual m2::AARectD const boundRect() const = 0; virtual void draw(gl::Screen * screen) const = 0; m2::PointD const & pivot() const; @@ -55,6 +56,7 @@ namespace yg /// text-element specific FontDesc m_fontDesc; string m_utf8Text; + wstring m_text; double m_depth; bool m_log2vis; shared_ptr m_rm; @@ -77,6 +79,7 @@ namespace yg void drawTextImpl(GlyphLayout const & layout, gl::TextRenderer * screen, FontDesc const & desc, double depth) const; wstring const log2vis(wstring const & str); string const & utf8Text() const; + wstring const & text() const; FontDesc const & fontDesc() const; double depth() const; }; @@ -94,7 +97,7 @@ namespace yg StraightTextElement(Params const & p); - m2::RectD const boundRect() const; + m2::AARectD const boundRect() const; void draw(gl::Screen * screen) const; void draw(gl::TextRenderer * screen) const; void offset(m2::PointD const & offs); @@ -119,7 +122,7 @@ namespace yg PathTextElement(Params const & p); - m2::RectD const boundRect() const; + m2::AARectD const boundRect() const; void draw(gl::Screen * screen) const; void draw(gl::TextRenderer * screen) const; void offset(m2::PointD const & offs); diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index 0aa5615372..8a71c3e289 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -53,7 +53,7 @@ namespace yg m2::RectD const TextRenderer::TextObj::GetLimitRect(TextRenderer* pTextRenderer) const { - return m_elem.boundRect(); + return m_elem.boundRect().GetGlobalRect(); } void TextRenderer::TextObj::SetNeedRedraw(bool flag) const @@ -238,6 +238,8 @@ namespace yg { ASSERT(m_useTextTree, ()); + m2::AARectD aaRect(rect); + for (path_text_elements::iterator i = m_pathTexts.begin(); i != m_pathTexts.end(); ++i) { list & l = i->second; @@ -245,8 +247,8 @@ namespace yg while (it != l.end()) { it->offset(offs); - m2::RectD const & r = it->boundRect(); - if (!rect.IsIntersect(r) && !rect.IsRectInside(r)) + m2::AARectD const & r = it->boundRect(); + if (!aaRect.IsIntersect(r) && !aaRect.IsRectInside(r)) { list::iterator tempIt = it; ++tempIt; @@ -256,7 +258,6 @@ namespace yg else ++it; } - } } diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 211134414a..d98eacaccf 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -716,18 +716,8 @@ namespace params.m_utf8Text = "Simplicity is the ultimate sophistication"; yg::StraightTextElement ste(params); - m2::RectD r = ste.boundRect(); - - m2::PointD pts[6] = { - m2::PointD(r.minX(), r.minY()), - m2::PointD(r.maxX(), r.minY()), - m2::PointD(r.maxX(), r.maxY()), - m2::PointD(r.minX(), r.minY()), - m2::PointD(r.maxX(), r.maxY()), - m2::PointD(r.minX(), r.maxY()) - }; - - p->drawTrianglesList(pts, 6, p->skin()->mapColor(yg::Color(0, 0, 255, 255)), 0); + m2::AARectD r = ste.boundRect(); + p->drawRectangle(r, yg::Color(0, 0, 255, 255), 0); base_t::DoDraw(p); } @@ -750,18 +740,8 @@ namespace params.m_utf8Text = "Simplicity is the ultimate sophistication"; yg::StraightTextElement ste(params); - m2::RectD r = ste.boundRect(); - - m2::PointD pts[6] = { - m2::PointD(r.minX(), r.minY()), - m2::PointD(r.maxX(), r.minY()), - m2::PointD(r.maxX(), r.maxY()), - m2::PointD(r.minX(), r.minY()), - m2::PointD(r.maxX(), r.maxY()), - m2::PointD(r.minX(), r.maxY()) - }; - - p->drawTrianglesList(pts, 6, p->skin()->mapColor(yg::Color(0, 0, 255, 255)), 0); + m2::AARectD r = ste.boundRect(); + p->drawRectangle(r, yg::Color(0, 0, 255, 255), 0); base_t::DoDraw(p); } @@ -1114,6 +1094,26 @@ namespace } }; + struct TestDrawAARect + { + public: + void DoDraw(shared_ptr p) + { + m2::AARectD r[3] = + { + m2::AARectD(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, 0, 50, 20)), + m2::AARectD(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, -10, 50, 10)), + m2::AARectD(m2::PointD(100, 100), math::pi / 6, m2::RectD(0, -22, 50, -2)) + }; + + p->drawRectangle(r[0], yg::Color(255, 0, 0, 128), yg::maxDepth - 2); + if (!r[0].IsIntersect(r[1])) + p->drawRectangle(r[1], yg::Color(0, 255, 0, 128), yg::maxDepth - 1); + if (!r[0].IsIntersect(r[2])) + p->drawRectangle(r[1], yg::Color(0, 0, 255, 128), yg::maxDepth); + } + }; + struct TestDrawSector { public: @@ -1286,15 +1286,15 @@ namespace // UNIT_TEST_GL(TestDrawStringWithColor); // UNIT_TEST_GL(TestDrawUnicodeSymbols); // UNIT_TEST_GL(TestDrawTextRectWithFixedFont); -// UNIT_TEST_GL(TestDrawTextRect); +// UNIT_TEST_GL(TestDrawTextRect); // UNIT_TEST_GL(TestDrawStringOnString); // UNIT_TEST_GL(TestDrawTextOnPathInteractive); // UNIT_TEST_GL(TestDrawTextOnPathBigSymbols); - UNIT_TEST_GL(TestDrawTextOnPath); - UNIT_TEST_GL(TestDrawTextOnPathZigZag); - UNIT_TEST_GL(TestDrawTextOnPathWithOffset); +// UNIT_TEST_GL(TestDrawTextOnPath); +// UNIT_TEST_GL(TestDrawTextOnPathZigZag); +// UNIT_TEST_GL(TestDrawTextOnPathWithOffset); // UNIT_TEST_GL(TestDrawStraightTextElement); - UNIT_TEST_GL(TestDrawPathTextElement); +// UNIT_TEST_GL(TestDrawPathTextElement); // UNIT_TEST_GL(TestDrawTextOverflow); // UNIT_TEST_GL(TestDrawTextFiltering); // UNIT_TEST_GL(TestDrawRandomTextFiltering); @@ -1307,6 +1307,7 @@ namespace // UNIT_TEST_GL(TestDrawPathSolid1PX); // UNIT_TEST_GL(TestDrawPathSolid2PX); // UNIT_TEST_GL(TestDrawPathSolid); + UNIT_TEST_GL(TestDrawAARect); // UNIT_TEST_GL(TestDrawSector); // UNIT_TEST_GL(TestDrawPathSolidDiffWidth); // UNIT_TEST_GL(TestDrawPathZigZag);