From 8fa6b56fff57e7e8cccc4b5bbb1f27be54a91220 Mon Sep 17 00:00:00 2001 From: rachytski Date: Sun, 1 May 2011 21:50:43 +0300 Subject: [PATCH] correct handling of pathOffset and penInfo.m_offset parameters in drawPath() function. --- .../cell_covering_visualize_test.cpp | 2 +- map/drawer_yg.cpp | 2 +- map/information_display.cpp | 4 +- yg/path_renderer.cpp | 39 +++++---- yg/path_renderer.hpp | 2 +- yg/pen_info.cpp | 58 ++++++++++--- yg/shape_renderer.cpp | 4 +- yg/text_renderer.cpp | 4 +- yg/text_renderer.hpp | 2 +- yg/yg_tests/screengl_test.cpp | 84 +++++++++++++------ yg/yg_tests/screenglglobal_test.cpp | 2 +- 11 files changed, 137 insertions(+), 66 deletions(-) diff --git a/indexer/indexer_tests/cell_covering_visualize_test.cpp b/indexer/indexer_tests/cell_covering_visualize_test.cpp index e604da7adf..924161eeac 100644 --- a/indexer/indexer_tests/cell_covering_visualize_test.cpp +++ b/indexer/indexer_tests/cell_covering_visualize_test.cpp @@ -58,7 +58,7 @@ namespace std::vector pts; for (size_t j = 0; j < m_lines[i].size(); ++j) pts.push_back(m_screenBase.GtoP(m2::PointD(m_lines[i][j].first, m_lines[i][j].second))); - pScreen->drawPath(&pts[0], pts.size(), m_skin->mapPenInfo(yg::PenInfo(yg::Color(0, 255, 0, 255), 2, 0, 0, 0)), 0); + pScreen->drawPath(&pts[0], pts.size(), 0, m_skin->mapPenInfo(yg::PenInfo(yg::Color(0, 255, 0, 255), 2, 0, 0, 0)), 0); } } diff --git a/map/drawer_yg.cpp b/map/drawer_yg.cpp index 0b69ee1b61..66a82bb049 100644 --- a/map/drawer_yg.cpp +++ b/map/drawer_yg.cpp @@ -187,7 +187,7 @@ void DrawerYG::drawPath(vector const & pts, di::DrawRule const * rul // draw path with array of rules for (size_t i = 0; i < count; ++i) - m_pScreen->drawPath(&pts[0], pts.size(), rules[i].m_rule->GetID(), rules[i].m_depth); + m_pScreen->drawPath(&pts[0], pts.size(), 0, rules[i].m_rule->GetID(), rules[i].m_depth); } void DrawerYG::drawArea(vector const & pts, rule_ptr_t pRule, int depth) diff --git a/map/information_display.cpp b/map/information_display.cpp index b7f22232fd..10aa8074bb 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -152,7 +152,7 @@ void InformationDisplay::drawRuler(DrawerYG * pDrawer) scalerPts[3] = scalerPts[2] + m2::PointD(0, -14 * m_visualScale); pDrawer->screen()->drawPath( - scalerPts, 4, + scalerPts, 4, 0, pDrawer->screen()->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 255), 2, 0, 0, 0)), yg::maxDepth); @@ -174,7 +174,7 @@ void InformationDisplay::drawRuler(DrawerYG * pDrawer) minPixPath[3] = minPixPath[2] + m2::PointD(0, -14); pDrawer->screen()->drawPath( - minPixPath, 4, + minPixPath, 4, 0, pDrawer->screen()->skin()->mapPenInfo(yg::PenInfo(yg::Color(255, 0, 0, 255), 4, 0, 0, 0)), yg::maxDepth); */ diff --git a/yg/path_renderer.cpp b/yg/path_renderer.cpp index 395ea7dfe5..383e0d1544 100644 --- a/yg/path_renderer.cpp +++ b/yg/path_renderer.cpp @@ -17,7 +17,7 @@ namespace yg : base_t(params), m_drawPathes(params.m_drawPathes) {} - void PathRenderer::drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth) + void PathRenderer::drawPath(m2::PointD const * points, size_t pointsCount, double offset, uint32_t styleID, double depth) { ++m_pathCount; m_pointsCount += pointsCount; @@ -25,14 +25,6 @@ namespace yg if (!m_drawPathes) return; - #ifdef PROFILER_YG - prof::block draw_path_block; - #endif - - //#ifdef DEBUG_DRAW_PATH - // LineStyle const * lineStyle = reinterpret_cast(styleID); - //#else - ASSERT_GREATER_OR_EQUAL(pointsCount, 2, ()); ResourceStyle const * style(skin()->fromID(styleID)); @@ -44,7 +36,6 @@ namespace yg ASSERT(style->m_cat == ResourceStyle::ELineStyle, ()); LineStyle const * lineStyle = static_cast(style); - //#endif if (lineStyle->m_isSolid) { @@ -54,6 +45,8 @@ namespace yg float rawTileStartLen = 0; + bool skipToOffset = true; + for (size_t i = 0; i < pointsCount - 1; ++i) { m2::PointD dir = points[i + 1] - points[i]; @@ -65,12 +58,24 @@ namespace yg /// The remaining length of the segment float segLenRemain = segLen; + if (skipToOffset) + { + offset -= segLen; + if (offset >= 0) + continue; + else + { + skipToOffset = false; + segLenRemain = -offset; + } + } + /// Geometry width. It's 1px wider than the pattern width. - int geomWidth = lineStyle->m_isSolid ? lineStyle->m_penInfo.m_w : lineStyle->m_penInfo.m_w + 4 - 2 * aaShift(); + int geomWidth = lineStyle->m_penInfo.m_w + 4 - 2 * aaShift(); float geomHalfWidth = geomWidth / 2.0; /// Starting point of the tiles on this segment - m2::PointF rawTileStartPt = points[i]; + m2::PointF rawTileStartPt = points[i] + dir * (segLen - segLenRemain); /// Tiling procedes as following : /// The leftmost tile goes antialiased at left and non-antialiased at right. @@ -81,15 +86,15 @@ namespace yg float rawTileLen = 0; while (segLenRemain > 0) { - rawTileLen = (lineStyle->m_isWrapped || lineStyle->m_isSolid) + rawTileLen = lineStyle->m_isWrapped ? segLen : std::min(((float)lineStyle->rawTileLen() - rawTileStartLen), segLenRemain); - float texMaxY = lineStyle->m_isSolid ? lineStyle->m_texRect.minY() + 1 : lineStyle->m_texRect.maxY() - aaShift(); - float texMinY = lineStyle->m_isSolid ? lineStyle->m_texRect.minY() + 1 : lineStyle->m_texRect.minY() + aaShift(); + float texMaxY = lineStyle->m_texRect.maxY() - aaShift(); + float texMinY = lineStyle->m_texRect.minY() + aaShift(); - float texMinX = lineStyle->m_isSolid ? lineStyle->m_texRect.minX() + 1 : lineStyle->m_isWrapped ? 0 : lineStyle->m_texRect.minX() + 2 + rawTileStartLen; - float texMaxX = lineStyle->m_isSolid ? lineStyle->m_texRect.minX() + 1 : texMinX + rawTileLen; + float texMinX = lineStyle->m_isWrapped ? 0 : lineStyle->m_texRect.minX() + 2 + rawTileStartLen; + float texMaxX = texMinX + rawTileLen; rawTileStartLen += rawTileLen; if (rawTileStartLen >= lineStyle->rawTileLen()) diff --git a/yg/path_renderer.hpp b/yg/path_renderer.hpp index 6cb8b069cb..95edb2cad5 100644 --- a/yg/path_renderer.hpp +++ b/yg/path_renderer.hpp @@ -29,7 +29,7 @@ namespace yg PathRenderer(Params const & params); - void drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth); + void drawPath(m2::PointD const * points, size_t pointsCount, double offset, uint32_t styleID, double depth); void beginFrame(); void endFrame(); diff --git a/yg/pen_info.cpp b/yg/pen_info.cpp index 15636fffa6..d21142d739 100644 --- a/yg/pen_info.cpp +++ b/yg/pen_info.cpp @@ -2,6 +2,7 @@ #include "../std/algorithm.hpp" #include "../std/iterator.hpp" #include "../std/numeric.hpp" +#include "../base/logging.hpp" namespace yg { @@ -19,9 +20,52 @@ namespace yg m_isSolid = true; else { - buffer_vector vec; - copy(pattern, pattern + patternSize, back_inserter(vec)); + buffer_vector tmpV; + copy(pattern, pattern + patternSize, back_inserter(tmpV)); + + if (tmpV.size() % 2) + tmpV.push_back(0); + double length = 0; + + length = accumulate(tmpV.begin(), tmpV.end(), 0); + + int i = 0; + + buffer_vector vec; + + if ((offset >= length) || (offset < 0)) + offset -= floor(offset / length) * length; + + length = 0; + + /// shifting pattern + while (true) + { + if (length + tmpV[i] > offset) + { + //we're inside, let's split the pattern + + if (i % 2 == 1) + vec.push_back(0); + + vec.push_back(length + tmpV[i] - offset); + std::copy(tmpV.data() + i + 1, tmpV.end(), back_inserter(vec)); + std::copy(tmpV.begin(), tmpV.data() + i, back_inserter(vec)); + vec.push_back(offset - length); + + if (i % 2 == 0) + vec.push_back(0); + + break; + } + else + length += tmpV[i++]; + } + + /// ensuring that a minimal element has a length of 2px + + length = 0; for (size_t i = 0; i < vec.size(); ++i) { if ((vec[i] < 2) && (vec[i] > 0)) @@ -33,16 +77,6 @@ namespace yg m_pat.reserve(periods * vec.size()); for (int i = 0; i < periods; ++i) copy(vec.begin(), vec.end(), back_inserter(m_pat)); - -/* copy(pattern, pattern + patternSize, back_inserter(m_pat)); - double length = 0; - for (size_t i = 0; i < m_pat.size(); ++i) - { - if ((m_pat[i] < 2) && (m_pat[i] > 0)) - m_pat[i] = 2; - length += m_pat[i]; - } -*/ } } diff --git a/yg/shape_renderer.cpp b/yg/shape_renderer.cpp index b691b2815c..42f76273a7 100644 --- a/yg/shape_renderer.cpp +++ b/yg/shape_renderer.cpp @@ -17,7 +17,7 @@ namespace yg vector pts; approximateArc(center, startA, endA, r, pts); - drawPath(&pts[0], pts.size(), skin()->mapPenInfo(yg::PenInfo(c, 3, 0, 0, 0)), depth); + drawPath(&pts[0], pts.size(), 0, skin()->mapPenInfo(yg::PenInfo(c, 3, 0, 0, 0)), depth); } void ShapeRenderer::approximateArc(m2::PointD const & center, double startA, double endA, double r, vector & pts) @@ -38,7 +38,7 @@ namespace yg approximateArc(center, startA, endA, r, pts); pts.push_back(center); - drawPath(&pts[0], pts.size(), skin()->mapPenInfo(yg::PenInfo(c, 2, 0, 0, 0)), depth); + drawPath(&pts[0], pts.size(), 0, skin()->mapPenInfo(yg::PenInfo(c, 2, 0, 0, 0)), depth); } void ShapeRenderer::fillSector(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth) diff --git a/yg/text_renderer.cpp b/yg/text_renderer.cpp index ad96a997b0..bfcb18e805 100644 --- a/yg/text_renderer.cpp +++ b/yg/text_renderer.cpp @@ -496,11 +496,11 @@ namespace yg p->m_pageID); } - void TextRenderer::drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth) + 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, styleID, depth); + base_t::drawPath(points, pointsCount, offset, styleID, depth); } } } diff --git a/yg/text_renderer.hpp b/yg/text_renderer.hpp index f18fad3b51..777ec980a8 100644 --- a/yg/text_renderer.hpp +++ b/yg/text_renderer.hpp @@ -146,7 +146,7 @@ namespace yg /// flush texts upon any function call. void setNeedTextRedraw(bool flag); - void drawPath(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth); + void drawPath(m2::PointD const * points, size_t pointsCount, double offset, uint32_t styleID, double depth); void updateActualTarget(); }; diff --git a/yg/yg_tests/screengl_test.cpp b/yg/yg_tests/screengl_test.cpp index 38cf9267e8..2e9e6ec185 100644 --- a/yg/yg_tests/screengl_test.cpp +++ b/yg/yg_tests/screengl_test.cpp @@ -48,13 +48,14 @@ namespace // double pat [] = {7, 7, 10, 10}; double pat1 [] = {1, 1}; - p->drawPath(pts, 3, p->skin()->mapPenInfo(yg::PenInfo(yg::Color(0xFF, 0xFF, 0xFF, 0xFF), 2, pat1, 2, 0)), 0); + p->drawPath(pts, 3, 0, p->skin()->mapPenInfo(yg::PenInfo(yg::Color(0xFF, 0xFF, 0xFF, 0xFF), 2, pat1, 2, 0)), 0); } }; struct TestDrawPathBase { std::vector > m_pathes; + std::vector m_pathOffsets; //std::vector > m_patterns; std::vector m_penInfos; std::vector m_depthes; @@ -77,11 +78,13 @@ namespace yg::Color const & color = yg::Color(255, 255, 255, 255), double width = 2, double depth = 0, - double offset = 0) + double pathOffset = 0, + double penOffset = 0) { m_pathes.push_back(points); + m_pathOffsets.push_back(pathOffset); //m_patterns.push_back(pattern); - m_penInfos.push_back(yg::PenInfo(color, width, pattern.empty() ? 0 : &pattern[0], pattern.size(), offset)); + m_penInfos.push_back(yg::PenInfo(color, width, pattern.empty() ? 0 : &pattern[0], pattern.size(), penOffset)); m_depthes.push_back(depth); } @@ -94,9 +97,9 @@ namespace { for (size_t i = 0; i < m_pathes.size(); ++i) { - p->drawPath(&m_pathes[i][0], m_pathes[i].size(), p->skin()->mapPenInfo(m_penInfos[i]), m_depthes[i]); + p->drawPath(&m_pathes[i][0], m_pathes[i].size(), m_pathOffsets[i], p->skin()->mapPenInfo(m_penInfos[i]), m_depthes[i]); if (m_drawAxis) - p->drawPath(&m_pathes[i][0], m_pathes[i].size(), p->skin()->mapPenInfo(m_axisPenInfo), m_depthes[i]); + p->drawPath(&m_pathes[i][0], m_pathes[i].size(), 0, p->skin()->mapPenInfo(m_axisPenInfo), m_depthes[i]); } } @@ -140,7 +143,7 @@ namespace } }; - struct PathWithOffset : TestDrawPathBase + struct TestDrawPathWithOffset : TestDrawPathBase { typedef TestDrawPathBase base_t; @@ -153,21 +156,50 @@ namespace vector pts; vector pattern; - pts.push_back(m2::PointD(100, 100)); pts.push_back(m2::PointD(200, 100)); + pts.push_back(m2::PointD(400, 100)); pattern.push_back(20); pattern.push_back(30); - /// The path should start from -10px offset. -// AddTest(pts, pattern, yg::Color(0, 0, 255, 255), 4, 0, -10); + /// The path should start from -10px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, -10); pts.clear(); - pts.push_back(m2::PointD(100, 200)); - pts.push_back(m2::PointD(200, 200)); + pts.push_back(m2::PointD(200, 110)); + pts.push_back(m2::PointD(400, 110)); + + /// The path should start from 0px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, 0); + + pts.clear(); + pts.push_back(m2::PointD(200, 120)); + pts.push_back(m2::PointD(400, 120)); + + /// The path should start from 60px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, 60); + + pts.clear(); + pts.push_back(m2::PointD(200, 130)); + pts.push_back(m2::PointD(400, 130)); + + /// The path should start from 0px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, 0, -10); + + pts.clear(); + pts.push_back(m2::PointD(200, 140)); + pts.push_back(m2::PointD(400, 140)); + + /// The path should start from 60px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, 0, 0); + + pts.clear(); + pts.push_back(m2::PointD(200, 150)); + pts.push_back(m2::PointD(400, 150)); + + /// The path should start from 60px path offset. + AddTest(pts, pattern, yg::Color(0, 0, 0, 255), 4, 0, 0, 60); - /// The path should start from 60px offset. - AddTest(pts, pattern, yg::Color(0, 0, 255, 255), 4, 0, 60); } }; @@ -561,7 +593,7 @@ namespace { m2::PointD path[2] = {m2::PointD(100, 200), m2::PointD(1000, 200)}; double pat[2] = {2, 2}; - p->drawPath(path, sizeof(path) / sizeof(m2::PointD), p->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 0xFF), 2, pat, 2, 0)), 0); + p->drawPath(path, sizeof(path) / sizeof(m2::PointD), 0, p->skin()->mapPenInfo(yg::PenInfo(yg::Color(0, 0, 0, 0xFF), 2, pat, 2, 0)), 0); yg::FontDesc fontDesc(false, 20, yg::Color(0, 0, 0, 0), true, yg::Color(255, 255, 255, 255)); @@ -622,7 +654,7 @@ namespace yg::FontDesc fontDesc(false, 20, yg::Color(0, 0, 0, 0), true, yg::Color(255, 255, 255, 255)); p->drawText(fontDesc, m2::PointD(40, 50), yg::EPosAboveRight, 0, "S", 0, true); - p->drawPath(&path[0], path.size(), p->skin()->mapPenInfo(solidPenInfo), 0); + p->drawPath(&path[0], path.size(), 0, p->skin()->mapPenInfo(solidPenInfo), 0); } }; @@ -717,7 +749,7 @@ namespace void DoDraw(shared_ptr p) { - p->drawPath(&m_path[0], m_path.size(), p->skin()->mapPenInfo(m_penInfo), 0); + p->drawPath(&m_path[0], m_path.size(), 0, p->skin()->mapPenInfo(m_penInfo), 0); yg::FontDesc fontDesc(false, 10); p->drawPathText(fontDesc, &m_path[0], m_path.size(), m_text, calc_length(m_path), 0.0, yg::EPosCenter, 0); } @@ -743,7 +775,7 @@ namespace void DoDraw(shared_ptr p) { - p->drawPath(&m_path[0], m_path.size(), p->skin()->mapPenInfo(m_penInfo), 0); + p->drawPath(&m_path[0], m_path.size(), 0, p->skin()->mapPenInfo(m_penInfo), 0); yg::FontDesc fontDesc(false, 10); p->drawPathText(fontDesc, &m_path[0], m_path.size(), m_text, calc_length(m_path), 0.0, yg::EPosCenter, 0); } @@ -753,7 +785,7 @@ namespace { void DoDraw(shared_ptr p) { - p->drawPath(&m_path[0], m_path.size(), p->skin()->mapPenInfo(m_penInfo), 0); + p->drawPath(&m_path[0], m_path.size(), 0, p->skin()->mapPenInfo(m_penInfo), 0); double const len = calc_length(m_path); yg::FontDesc fontDesc(false, 10); @@ -922,7 +954,7 @@ namespace uint32_t triangleListID = p->skin()->mapPenInfo(triangleListRule); uint32_t lineLoopID = p->skin()->mapPenInfo(lineLoopRule); - p->drawPath((m2::PointD const *)&m_vertices[0], m_vertices.size(), inputDataID, 0); + p->drawPath((m2::PointD const *)&m_vertices[0], m_vertices.size(), 0, inputDataID, 0); for (size_t i = 0; i < m_d.indices().size(); ++i) { @@ -945,7 +977,7 @@ namespace } for (size_t j = 0; j < poly.size(); ++j) - p->drawPath(&poly[j][0], poly[j].size(), triangleFanID, 0); + p->drawPath(&poly[j][0], poly[j].size(), 0, triangleFanID, 0); break; } case tess::TrianglesList: @@ -965,7 +997,7 @@ namespace } for (size_t j = 0; j < poly.size(); ++j) - p->drawPath(&poly[j][0], poly[j].size(), triangleListID, 0); + p->drawPath(&poly[j][0], poly[j].size(), 0, triangleListID, 0); break; } case tess::TrianglesStrip: @@ -983,7 +1015,7 @@ namespace } for (size_t j = 0; j < poly.size(); ++j) - p->drawPath(&poly[j][0], poly[j].size(), triangleFanID, 0); + p->drawPath(&poly[j][0], poly[j].size(), 0, triangleFanID, 0); break; } case tess::LineLoop: @@ -997,7 +1029,7 @@ namespace poly.back().push_back(poly.back()[0]); - p->drawPath(&poly[0][0], poly[0].size(), lineLoopID, 0); + p->drawPath(&poly[0][0], poly[0].size(), 0, lineLoopID, 0); break; } } @@ -1034,8 +1066,8 @@ namespace // UNIT_TEST_GL(TestDrawUnicodeSymbols); // UNIT_TEST_GL(TestDrawTextRectWithFixedFont); // UNIT_TEST_GL(TestDrawStringOnString); -// UNIT_TEST_GL(TestDrawTextOnPath); - UNIT_TEST_GL(TestDrawTextOnPathZigZag); +// UNIT_TEST_GL(TestDrawTextOnPath); +// UNIT_TEST_GL(TestDrawTextOnPathZigZag); // UNIT_TEST_GL(TestDrawTextOnPathWithOffset); // UNIT_TEST_GL(TestDrawTextOverflow); // UNIT_TEST_GL(TestDrawTextFiltering); @@ -1044,7 +1076,7 @@ namespace // UNIT_TEST_GL(TestDrawPoly); // UNIT_TEST_GL(TestDrawSolidRect); // UNIT_TEST_GL(TestDrawPathWithSkinPageMiss); -// UNIT_TEST_GL(TestDrawPathWithOffset); + UNIT_TEST_GL(TestDrawPathWithOffset); // UNIT_TEST_GL(TestDrawPathJoin); // UNIT_TEST_GL(TestDrawPathSolid1PX); // UNIT_TEST_GL(TestDrawPathSolid2PX); diff --git a/yg/yg_tests/screenglglobal_test.cpp b/yg/yg_tests/screenglglobal_test.cpp index f2305824ef..01a9a8cc88 100644 --- a/yg/yg_tests/screenglglobal_test.cpp +++ b/yg/yg_tests/screenglglobal_test.cpp @@ -44,7 +44,7 @@ namespace toPixel(pts); - p->drawPath(&pts[0], pts.size(), p->skin()->mapPenInfo(yg::PenInfo(yg::Color(255, 0, 0, 255), 2, 0, 0, 0)), 0); + p->drawPath(&pts[0], pts.size(), 0, p->skin()->mapPenInfo(yg::PenInfo(yg::Color(255, 0, 0, 255), 2, 0, 0, 0)), 0); } };