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

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorExMix <rahuba.youri@mapswithme.com>2015-01-06 11:58:47 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:35:51 +0300
commit181017b90d8153724b7ed75f76509f979d51fe7e (patch)
tree4cf8fefce3fe4cfbec14dc05eb696a09b2e03e36
parent085d6fdf963b823335c5d6717f72a047d8488449 (diff)
[drape] path text adaptation
-rw-r--r--drape_frontend/apply_feature_functors.cpp2
-rw-r--r--drape_frontend/path_symbol_shape.cpp4
-rw-r--r--drape_frontend/path_text_shape.cpp216
-rw-r--r--drape_frontend/path_text_shape.hpp2
-rw-r--r--drape_frontend/text_layout.cpp100
-rw-r--r--drape_frontend/text_layout.hpp50
-rw-r--r--geometry/geometry_tests/spline_test.cpp52
-rw-r--r--geometry/spline.cpp121
-rw-r--r--geometry/spline.hpp10
9 files changed, 312 insertions, 245 deletions
diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp
index 913a1ad07f..4a4897a33e 100644
--- a/drape_frontend/apply_feature_functors.cpp
+++ b/drape_frontend/apply_feature_functors.cpp
@@ -357,7 +357,7 @@ void ApplyLineFeature::Finish()
while (!it.BeginAgain())
{
m_context.InsertShape(m_tileKey, dp::MovePointer<MapShape>(new TextShape(it.m_pos, viewParams)));
- it.Step(splineStep);
+ it.Advance(splineStep);
}
}
}
diff --git a/drape_frontend/path_symbol_shape.cpp b/drape_frontend/path_symbol_shape.cpp
index ddc8b9ded5..f4535c9936 100644
--- a/drape_frontend/path_symbol_shape.cpp
+++ b/drape_frontend/path_symbol_shape.cpp
@@ -36,7 +36,7 @@ void PathSymbolShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<d
m2::Spline::iterator splineIter = m_spline.CreateIterator();
double pToGScale = 1.0 / m_params.m_baseGtoPScale;
- splineIter.Step(m_params.m_offset * pToGScale);
+ splineIter.Advance(m_params.m_offset * pToGScale);
float step = m_params.m_step * pToGScale;
glsl::vec2 dummy(0.0, 0.0);
while (!splineIter.BeginAgain())
@@ -53,7 +53,7 @@ void PathSymbolShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<d
buffer.push_back(gpu::SolidTexturingVertex(glsl::vec3(pivot - d - n, m_params.m_depth), dummy, glsl::ToVec2(rect.LeftBottom())));
buffer.push_back(gpu::SolidTexturingVertex(glsl::vec3(pivot + d + n, m_params.m_depth), dummy, glsl::ToVec2(rect.RightTop())));
buffer.push_back(gpu::SolidTexturingVertex(glsl::vec3(pivot + d - n, m_params.m_depth), dummy, glsl::ToVec2(rect.RightBottom())));
- splineIter.Step(step);
+ splineIter.Advance(step);
}
if (buffer.empty())
diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp
index 261f0bee94..5c7c9b977e 100644
--- a/drape_frontend/path_text_shape.cpp
+++ b/drape_frontend/path_text_shape.cpp
@@ -7,7 +7,6 @@
#include "../drape/attribute_provider.hpp"
#include "../drape/glstate.hpp"
#include "../drape/batcher.hpp"
-#include "../drape/texture_set_holder.hpp"
#include "../base/math.hpp"
#include "../base/logging.hpp"
@@ -25,27 +24,9 @@ using m2::Spline;
namespace
{
- struct AccumulateRect
- {
- ScreenBase const & m_screen;
- m2::RectD m_pixelRect;
- AccumulateRect(ScreenBase const & screen)
- : m_screen(screen)
- {
- }
-
- void operator()(m2::PointF const & pt)
- {
- m_pixelRect.Add(m_screen.GtoP(pt));
- }
-
- };
-
class PathTextHandle : public dp::OverlayHandle
{
public:
- static const uint8_t PathGlyphPositionID = 1;
-
PathTextHandle(m2::SharedSpline const & spl,
df::SharedTextLayout const & layout,
float const mercatorOffset,
@@ -53,151 +34,75 @@ namespace
: OverlayHandle(FeatureID(), dp::Center, depth)
, m_spline(spl)
, m_layout(layout)
- , m_splineOffset(mercatorOffset)
{
+ m_centerPointIter = m_spline.CreateIterator();
+ m_centerPointIter.Advance(mercatorOffset);
+ m_normals.resize(4 * m_layout->GetGlyphCount());
}
void Update(ScreenBase const & screen)
{
- m_scalePtoG = screen.GetScale();
- GetBegEnd(m_begin, m_end);
-
- SetIsValid(!m_begin.BeginAgain() && !m_end.BeginAgain());
- if (!IsValid())
+ if (m_layout->CacheDynamicGeometry(m_centerPointIter, screen, m_normals))
+ {
+ SetIsValid(true);
return;
+ }
- if (screen.GtoP(m_end.m_pos).x < screen.GtoP(m_begin.m_pos).x)
- m_isForward = false;
- else
- m_isForward = true;
+ SetIsValid(false);
}
m2::RectD GetPixelRect(ScreenBase const & screen) const
{
ASSERT(IsValid(), ());
- ASSERT(!m_begin.BeginAgain(), ());
- ASSERT(!m_end.BeginAgain(), ());
-
- AccumulateRect f(screen);
- m_spline->ForEachNode(m_begin, m_end, f);
- float const pixelHeight = m_layout->GetPixelHeight();
- f.m_pixelRect.Inflate(2 * pixelHeight, 2 * pixelHeight);
- return f.m_pixelRect;
- }
+ m2::PointD pixelPivot(screen.GtoP(m_centerPointIter.m_pos));
+ m2::RectD result;
+ for (gpu::TextDynamicVertex const & v : m_normals)
+ result.Add(pixelPivot + glsl::ToPoint(v.m_normal));
+
+ return result;
+ }
void GetPixelShape(ScreenBase const & screen, Rects & rects) const
{
- rects = m_bboxes;
+ ASSERT(IsValid(), ());
+
+ m2::PointD pixelPivot(screen.GtoP(m_centerPointIter.m_pos));
+ for (size_t quadIndex = 0; quadIndex < m_normals.size(); quadIndex += 4)
+ {
+ m2::RectF r;
+ r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex].m_normal));
+ r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 1].m_normal));
+ r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 2].m_normal));
+ r.Add(pixelPivot + glsl::ToPoint(m_normals[quadIndex + 3].m_normal));
+ rects.push_back(r);
+ }
}
void GetAttributeMutation(dp::RefPointer<dp::AttributeBufferMutator> mutator, ScreenBase const & screen) const
{
ASSERT(IsValid(), ());
- uint32_t byteCount = 4 * m_layout->GetGlyphCount() * sizeof(glsl::vec2);
- void * buffer = mutator->AllocateMutationBuffer(byteCount);
- df::IntrusiveVector<glsl::vec2> positions(buffer, byteCount);
- // m_splineOffset set offset to Center of text.
- // By this we calc offset for start of text in mercator
- m_layout->LayoutPathText(m_begin, m_scalePtoG, positions, m_isForward, m_bboxes, screen);
- TOffsetNode const & node = GetOffsetNode(PathGlyphPositionID);
+ TOffsetNode const & node = GetOffsetNode(gpu::TextDynamicVertex::GetDynamicStreamID());
+ ASSERT(node.first.GetElementSize() == sizeof(gpu::TextDynamicVertex), ());
+ ASSERT(node.second.m_count == m_normals.size(), ());
+
+ uint32_t byteCount = m_normals.size() * sizeof(gpu::TextDynamicVertex);
+ void * buffer = mutator->AllocateMutationBuffer(byteCount);
+ memcpy(buffer, m_normals.data(), byteCount);
dp::MutateNode mutateNode;
mutateNode.m_region = node.second;
- mutateNode.m_data = dp::MakeStackRefPointer<void>(buffer);
+ mutateNode.m_data = dp::MakeStackRefPointer(buffer);
mutator->AddMutation(node.first, mutateNode);
}
private:
- void GetBegEnd(Spline::iterator & beg, Spline::iterator & end) const
- {
- beg = m_spline.CreateIterator();
- end = m_spline.CreateIterator();
- float const textLength = m_layout->GetPixelLength() * m_scalePtoG;
- float const step = max(0.0f, m_splineOffset - textLength / 2.0f);
- if (step > 0.0f)
- beg.Step(step);
- end.Step(step + textLength);
- }
-
- private:
m2::SharedSpline m_spline;
- m2::Spline::iterator m_begin;
- m2::Spline::iterator m_end;
- mutable Rects m_bboxes;
+ m2::Spline::iterator m_centerPointIter;
+ gpu::TTextDynamicVertexBuffer m_normals;
df::SharedTextLayout m_layout;
- float m_scalePtoG;
- float m_splineOffset;
- bool m_isForward;
};
-
- void BatchPathText(m2::SharedSpline const & spline,
- buffer_vector<float, 32> const & offsets,
- float depth,
- dp::RefPointer<dp::Batcher> batcher,
- df::SharedTextLayout const & layout,
- vector<glsl::vec2> & positions,
- vector<glsl::Quad4> & texCoord,
- vector<glsl::Quad4> & fontColor,
- vector<glsl::Quad1> & index,
- dp::RefPointer<dp::TextureSetHolder> textures)
- {
- ASSERT(!offsets.empty(), ());
- layout->InitPathText(depth, texCoord, fontColor, index, textures);
-
- dp::GLState state(gpu::PATH_FONT_PROGRAM, dp::GLState::OverlayLayer);
- state.SetTextureSet(layout->GetTextureSet());
- state.SetBlending(dp::Blending(true));
-
- for (size_t i = 0; i < offsets.size(); ++i)
- {
- dp::AttributeProvider provider(4, 4 * layout->GetGlyphCount());
- {
- dp::BindingInfo positionBind(1, PathTextHandle::PathGlyphPositionID);
- dp::BindingDecl & decl = positionBind.GetBindingDecl(0);
- decl.m_attributeName = "a_position";
- decl.m_componentCount = 2;
- decl.m_componentType = gl_const::GLFloatType;
- decl.m_offset = 0;
- decl.m_stride = 0;
- provider.InitStream(0, positionBind, dp::MakeStackRefPointer(&positions[0]));
- }
- {
- dp::BindingInfo texCoordBind(1);
- dp::BindingDecl & decl = texCoordBind.GetBindingDecl(0);
- decl.m_attributeName = "a_texcoord";
- decl.m_componentCount = 4;
- decl.m_componentType = gl_const::GLFloatType;
- decl.m_offset = 0;
- decl.m_stride = 0;
- provider.InitStream(1, texCoordBind, dp::MakeStackRefPointer(&texCoord[0]));
- }
- {
- dp::BindingInfo fontColorBind(1);
- dp::BindingDecl & decl = fontColorBind.GetBindingDecl(0);
- decl.m_attributeName = "a_color";
- decl.m_componentCount = 4;
- decl.m_componentType = gl_const::GLFloatType;
- decl.m_offset = 0;
- decl.m_stride = 0;
- provider.InitStream(2, fontColorBind, dp::MakeStackRefPointer(&fontColor[0]));
- }
- {
- dp::BindingInfo outlineColorBind(1);
- dp::BindingDecl & decl = outlineColorBind.GetBindingDecl(0);
- decl.m_attributeName = "a_index";
- decl.m_componentCount = 1;
- decl.m_componentType = gl_const::GLFloatType;
- decl.m_offset = 0;
- decl.m_stride = 0;
- provider.InitStream(3, outlineColorBind, dp::MakeStackRefPointer(&index[0]));
- }
-
- dp::OverlayHandle * handle = new PathTextHandle(spline, layout, offsets[i], depth);
- batcher->InsertListOfStrip(state, dp::MakeStackRefPointer(&provider), dp::MovePointer(handle), 4);
- }
- }
}
namespace df
@@ -210,11 +115,11 @@ PathTextShape::PathTextShape(m2::SharedSpline const & spline,
{
}
-void PathTextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const
+void PathTextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureManager> textures) const
{
- SharedTextLayout layout(new TextLayout(strings::MakeUniString(m_params.m_text),
- m_params.m_textFont,
- textures));
+ PathTextLayout * layout = new PathTextLayout(strings::MakeUniString(m_params.m_text),
+ m_params.m_textFont.m_size,
+ textures);
uint32_t glyphCount = layout->GetGlyphCount();
if (glyphCount == 0)
@@ -239,10 +144,6 @@ void PathTextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp:
float const minPeriodSize = etalonEmpty + textLength;
float const twoTextAndEmpty = minPeriodSize + textLength;
- vector<glsl::vec2> positions(glyphCount, glsl::vec2(0.0, 0.0));
- vector<glsl::Quad4> texCoords(glyphCount);
- vector<glsl::Quad4> fontColor(glyphCount);
- vector<glsl::Quad1> index(glyphCount);
buffer_vector<float, 32> offsets;
float const scalePtoG = 1.0f / m_params.m_baseGtoPScale;
@@ -278,8 +179,39 @@ void PathTextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp:
offsets.push_back((textHalfLength + (textLength + offset) * (i + 1)) * scalePtoG);
}
- BatchPathText(m_spline, offsets, m_params.m_depth, batcher, layout,
- positions, texCoords, fontColor, index, textures);
+ dp::TextureManager::ColorRegion color;
+ dp::TextureManager::ColorRegion outline;
+ textures->GetColorRegion(m_params.m_textFont.m_color, color);
+ textures->GetColorRegion(m_params.m_textFont.m_outlineColor, outline);
+
+ dp::GLState state(gpu::TEXT_PROGRAM, dp::GLState::OverlayLayer);
+ state.SetBlending(dp::Blending(true));
+ state.SetColorTexture(color.GetTexture());
+ state.SetMaskTexture(layout->GetMaskTexture());
+
+ ASSERT(!offsets.empty(), ());
+ gpu::TTextStaticVertexBuffer staticBuffer;
+ gpu::TTextDynamicVertexBuffer dynBuffer;
+ SharedTextLayout layoutPtr(layout);
+ for (float offset : offsets)
+ {
+ staticBuffer.clear();
+ dynBuffer.clear();
+
+ Spline::iterator iter = m_spline.CreateIterator();
+ iter.Advance(offset);
+ layout->CacheStaticGeometry(glsl::vec3(glsl::ToVec2(iter.m_pos), m_params.m_depth),
+ color, outline, staticBuffer);
+
+ dynBuffer.resize(staticBuffer.size(), gpu::TextDynamicVertex(glsl::vec2(0.0, 0.0)));
+
+ dp::AttributeProvider provider(2, staticBuffer.size());
+ provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), dp::MakeStackRefPointer<void>(staticBuffer.data()));
+ provider.InitStream(1, gpu::TextDynamicVertex::GetBindingInfo(), dp::MakeStackRefPointer<void>(dynBuffer.data()));
+
+ dp::OverlayHandle * handle = new PathTextHandle(m_spline, layoutPtr, offset, m_params.m_depth);
+ batcher->InsertListOfStrip(state, dp::MakeStackRefPointer(&provider), dp::MovePointer(handle), 4);
+ }
}
}
diff --git a/drape_frontend/path_text_shape.hpp b/drape_frontend/path_text_shape.hpp
index 3468665cca..9612a9ea80 100644
--- a/drape_frontend/path_text_shape.hpp
+++ b/drape_frontend/path_text_shape.hpp
@@ -13,7 +13,7 @@ class PathTextShape : public MapShape
public:
PathTextShape(m2::SharedSpline const & spline,
PathTextViewParams const & params);
- virtual void Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const;
+ virtual void Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureManager> textures) const;
private:
m2::SharedSpline m_spline;
diff --git a/drape_frontend/text_layout.cpp b/drape_frontend/text_layout.cpp
index a477bbe30b..1b177b6f68 100644
--- a/drape_frontend/text_layout.cpp
+++ b/drape_frontend/text_layout.cpp
@@ -16,6 +16,7 @@ namespace
{
float const BASE_HEIGHT = 20.0f;
+float const VALID_SPLINE_TURN = 0.96f;
class TextGeometryGenerator
{
@@ -70,9 +71,7 @@ public:
void operator()(dp::TextureManager::GlyphRegion const & glyph)
{
- m2::PointU pixelSize(m2::PointU::Zero());
- glyph.GetPixelSize(pixelSize);
- pixelSize *= m_textRatio;
+ m2::PointF pixelSize = m2::PointF(glyph.GetPixelSize()) * m_textRatio;
float const xOffset = glyph.GetOffsetX() * m_textRatio;
float const yOffset = glyph.GetOffsetY() * m_textRatio;
@@ -251,11 +250,6 @@ void CalculateOffsets(dp::Anchor anchor,
} // namespace
-TextLayout::TextLayout(df::TextLayout::LayoutType type)
- : m_type(type)
-{
-}
-
void TextLayout::Init(strings::UniString const & text, float fontSize,
dp::RefPointer<dp::TextureManager> textures)
{
@@ -295,7 +289,6 @@ float TextLayout::GetPixelHeight() const
StraightTextLayout::StraightTextLayout(strings::UniString const & text, float fontSize,
dp::RefPointer<dp::TextureManager> textures, dp::Anchor anchor)
- : TBase(TextLayout::LayoutType::StraightLayout)
{
strings::UniString visibleText = fribidi::log2vis(text);
buffer_vector<size_t, 2> delimIndexes;
@@ -327,8 +320,84 @@ void StraightTextLayout::Cache(glm::vec3 const & pivot, glm::vec2 const & pixelO
}
}
+PathTextLayout::PathTextLayout(strings::UniString const & text, float fontSize,
+ dp::RefPointer<dp::TextureManager> textures)
+{
+ Init(fribidi::log2vis(text), fontSize, textures);
+}
+
+void PathTextLayout::CacheStaticGeometry(glm::vec3 const & pivot,
+ dp::TextureManager::ColorRegion const & colorRegion,
+ dp::TextureManager::ColorRegion const & outlineRegion,
+ gpu::TTextStaticVertexBuffer & staticBuffer) const
+{
+ TextGeometryGenerator gen(pivot, colorRegion, outlineRegion, staticBuffer);
+ for_each(m_metrics.begin(), m_metrics.end(), gen);
+}
+
+bool PathTextLayout::CacheDynamicGeometry(m2::Spline::iterator const & iter, ScreenBase const & screen,
+ gpu::TTextDynamicVertexBuffer & buffer) const
+{
+ float const scalePtoG = screen.GetScale();
+ float const glbHalfLength = 0.5 * GetPixelLength() * scalePtoG;
+
+ m2::Spline::iterator beginIter = iter;
+ beginIter.Advance(-glbHalfLength);
+ m2::Spline::iterator endIter = iter;
+ endIter.Advance(glbHalfLength);
+ if (beginIter.BeginAgain() || endIter.BeginAgain())
+ return false;
+
+ float const halfFontSize = 0.5 * GetPixelHeight();
+ float advanceSign = 1.0f;
+ m2::Spline::iterator penIter = beginIter;
+ if (screen.GtoP(beginIter.m_pos).x > screen.GtoP(endIter.m_pos).x)
+ {
+ advanceSign = -advanceSign;
+ penIter = endIter;
+ }
+
+ glsl::vec2 pxPivot = glsl::ToVec2(screen.GtoP(iter.m_pos));
+ buffer.resize(4 * m_metrics.size());
+ for (size_t i = 0; i < m_metrics.size(); ++i)
+ {
+ GlyphRegion const & g = m_metrics[i];
+ m2::PointF pxSize = m2::PointF(g.GetPixelSize()) * m_textSizeRatio;
+
+ m2::PointD const pxBase = screen.GtoP(penIter.m_pos);
+ m2::PointD const pxShiftBase = screen.GtoP(penIter.m_pos + penIter.m_dir);
+
+ glsl::vec2 tangent = advanceSign * glsl::normalize(glsl::ToVec2(pxShiftBase - pxBase));
+ glsl::vec2 normal = glsl::normalize(glsl::vec2(-tangent.y, tangent.x));
+ glsl::vec2 formingVector = (glsl::ToVec2(pxBase) - pxPivot) + (halfFontSize * normal);
+
+ float const xOffset = g.GetOffsetX() * m_textSizeRatio;
+ float const yOffset = g.GetOffsetY() * m_textSizeRatio;
+
+ float const upVector = - (pxSize.y + yOffset);
+ float const bottomVector = - yOffset;
+
+ size_t baseIndex = 4 * i;
+
+ buffer[baseIndex + 0] = gpu::TextDynamicVertex(formingVector + normal * upVector + tangent * xOffset);
+ buffer[baseIndex + 1] = gpu::TextDynamicVertex(formingVector + normal * bottomVector + tangent * xOffset);
+ buffer[baseIndex + 2] = gpu::TextDynamicVertex(formingVector + normal * upVector + tangent * (pxSize.x + xOffset));
+ buffer[baseIndex + 3] = gpu::TextDynamicVertex(formingVector + normal * bottomVector + tangent * (pxSize.x + xOffset));
+
+
+ float const xAdvance = g.GetAdvanceX() * m_textSizeRatio;
+ glsl::vec2 currentTangent = glsl::ToVec2(penIter.m_dir);
+ penIter.Advance(advanceSign * xAdvance * scalePtoG);
+ float const dotProduct = glsl::dot(currentTangent, glsl::ToVec2(penIter.m_dir));
+ if (dotProduct < VALID_SPLINE_TURN)
+ return false;
+ }
+
+ return true;
+}
+
///////////////////////////////////////////////////////////////
-SharedTextLayout::SharedTextLayout(TextLayout * layout)
+SharedTextLayout::SharedTextLayout(PathTextLayout * layout)
: m_layout(layout)
{
}
@@ -338,17 +407,22 @@ bool SharedTextLayout::IsNull() const
return m_layout == NULL;
}
-void SharedTextLayout::Reset(TextLayout * layout)
+void SharedTextLayout::Reset(PathTextLayout * layout)
{
m_layout.reset(layout);
}
-TextLayout * SharedTextLayout::operator->()
+PathTextLayout * SharedTextLayout::GetRaw()
+{
+ return m_layout.get();
+}
+
+PathTextLayout * SharedTextLayout::operator->()
{
return m_layout.get();
}
-TextLayout const * SharedTextLayout::operator->() const
+PathTextLayout const * SharedTextLayout::operator->() const
{
return m_layout.get();
}
diff --git a/drape_frontend/text_layout.hpp b/drape_frontend/text_layout.hpp
index ea98ac636f..e5e1e8410c 100644
--- a/drape_frontend/text_layout.hpp
+++ b/drape_frontend/text_layout.hpp
@@ -29,11 +29,7 @@ class TextLayout
{
public:
- enum class LayoutType
- {
- StraightLayout,
- PathLayout
- };
+ virtual ~TextLayout() {}
dp::RefPointer<dp::Texture> GetMaskTexture() const;
@@ -41,23 +37,17 @@ public:
float GetPixelLength() const;
float GetPixelHeight() const;
- LayoutType GetType() const { return m_type; }
protected:
- TextLayout(LayoutType type);
void Init(strings::UniString const & text,
float fontSize,
dp::RefPointer<dp::TextureManager> textures);
-
protected:
typedef dp::TextureManager::GlyphRegion GlyphRegion;
dp::TextureManager::TGlyphsBuffer m_metrics;
float m_textSizeRatio = 0.0;
-
-private:
- LayoutType m_type;
};
class StraightTextLayout : public TextLayout
@@ -69,11 +59,11 @@ public:
dp::RefPointer<dp::TextureManager> textures,
dp::Anchor anchor);
- void Cache(glm::vec3 const & pivot, glsl::vec2 const & pixelOffset,
- dp::TextureManager::ColorRegion const & colorRegion,
- dp::TextureManager::ColorRegion const & outlineRegion,
- gpu::TTextStaticVertexBuffer & staticBuffer,
- gpu::TTextDynamicVertexBuffer & dynamicBuffer) const;
+ void Cache(glsl::vec3 const & pivot, glsl::vec2 const & pixelOffset,
+ dp::TextureManager::ColorRegion const & colorRegion,
+ dp::TextureManager::ColorRegion const & outlineRegion,
+ gpu::TTextStaticVertexBuffer & staticBuffer,
+ gpu::TTextDynamicVertexBuffer & dynamicBuffer) const;
m2::PointU const & GetPixelSize() const { return m_pixelSize; }
@@ -82,19 +72,37 @@ private:
m2::PointU m_pixelSize;
};
+class PathTextLayout : public TextLayout
+{
+ typedef TextLayout TBase;
+public:
+ PathTextLayout(strings::UniString const & text,
+ float fontSize, dp::RefPointer<dp::TextureManager> textures);
+
+ void CacheStaticGeometry(glsl::vec3 const & pivot,
+ dp::TextureManager::ColorRegion const & colorRegion,
+ dp::TextureManager::ColorRegion const & outlineRegion,
+ gpu::TTextStaticVertexBuffer & staticBuffer) const;
+
+ bool CacheDynamicGeometry(m2::Spline::iterator const & iter,
+ ScreenBase const & screen,
+ gpu::TTextDynamicVertexBuffer & buffer) const;
+};
+
class SharedTextLayout
{
public:
- SharedTextLayout(TextLayout * layout);
+ SharedTextLayout(PathTextLayout * layout);
bool IsNull() const;
- void Reset(TextLayout * layout);
+ void Reset(PathTextLayout * layout);
+ PathTextLayout * GetRaw();
- TextLayout * operator->();
- TextLayout const * operator->() const;
+ PathTextLayout * operator->();
+ PathTextLayout const * operator->() const;
private:
- shared_ptr<TextLayout> m_layout;
+ shared_ptr<PathTextLayout> m_layout;
};
}
diff --git a/geometry/geometry_tests/spline_test.cpp b/geometry/geometry_tests/spline_test.cpp
index 6f70967732..d901340583 100644
--- a/geometry/geometry_tests/spline_test.cpp
+++ b/geometry/geometry_tests/spline_test.cpp
@@ -28,11 +28,11 @@ UNIT_TEST(SmoothedDirections)
PointD dir2(sqrt2 / 2.0, -sqrt2 / 2.0);
itr.Attach(spl);
TestPointDDir(itr.m_avrDir, dir1);
- itr.Step(sqrt2 * 30.0);
+ itr.Advance(sqrt2 * 30.0);
TestPointDDir(itr.m_avrDir, dir1);
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_avrDir, dir1 * 0.25 + dir2 * 0.75);
- itr.Step(sqrt2 * 10.0);
+ itr.Advance(sqrt2 * 10.0);
TestPointDDir(itr.m_avrDir, dir2);
path.clear();
@@ -46,12 +46,12 @@ UNIT_TEST(SmoothedDirections)
Spline spl2(path);
itr.Attach(spl2);
TestPointDDir(itr.m_avrDir, dir1);
- itr.Step(sqrt2 * 80.0 + 40.0);
+ itr.Advance(sqrt2 * 80.0 + 40.0);
TestPointDDir(itr.m_avrDir, dir12);
itr.Attach(spl2);
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_avrDir, dir1);
- itr.Step(80.0);
+ itr.Advance(80.0);
TestPointDDir(itr.m_avrDir, dir12 * 0.5 + dir2 * 0.5);
}
@@ -69,9 +69,9 @@ UNIT_TEST(UsualDirections)
PointD dir2(sqrt2 / 2.0, -sqrt2 / 2.0);
itr.Attach(spl);
TestPointDDir(itr.m_dir, dir1);
- itr.Step(sqrt2 * 30.0);
+ itr.Advance(sqrt2 * 30.0);
TestPointDDir(itr.m_dir, dir1);
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_dir, dir2);
path.clear();
@@ -85,12 +85,12 @@ UNIT_TEST(UsualDirections)
Spline spl2(path);
itr.Attach(spl2);
TestPointDDir(itr.m_dir, dir1);
- itr.Step(sqrt2 * 80.0 + 35.0);
+ itr.Advance(sqrt2 * 80.0 + 35.0);
TestPointDDir(itr.m_dir, dir2);
itr.Attach(spl2);
- itr.Step(sqrt2 * 45.0);
+ itr.Advance(sqrt2 * 45.0);
TestPointDDir(itr.m_dir, dir12);
- itr.Step(80.0);
+ itr.Advance(80.0);
TestPointDDir(itr.m_dir, dir2);
}
@@ -108,15 +108,15 @@ UNIT_TEST(Positions)
Spline::iterator itr;
itr.Attach(spl0);
TestPointDDir(itr.m_pos, PointD(0, 0));
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_pos, PointD(40, 40));
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_pos, PointD(80, 0));
itr.Attach(spl4);
TestPointDDir(itr.m_pos, PointD(0, 0));
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_pos, PointD(40, 40));
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_pos, PointD(80, 0));
path.clear();
@@ -130,16 +130,16 @@ UNIT_TEST(Positions)
Spline spl3 = spl2;
itr.Attach(spl3);
TestPointDDir(itr.m_pos, PointD(0, 0));
- itr.Step(sqrt2 * 80.0 + 40.0);
+ itr.Advance(sqrt2 * 80.0 + 40.0);
TestPointDDir(itr.m_pos, PointD(120, 0));
itr.Attach(spl2);
- itr.Step(sqrt2 * 40.0);
+ itr.Advance(sqrt2 * 40.0);
TestPointDDir(itr.m_pos, PointD(40, 40));
- itr.Step(2.0);
+ itr.Advance(2.0);
TestPointDDir(itr.m_pos, PointD(42, 40));
- itr.Step(20.0);
+ itr.Advance(20.0);
TestPointDDir(itr.m_pos, PointD(62, 40));
- itr.Step(18.0);
+ itr.Advance(18.0);
TestPointDDir(itr.m_pos, PointD(80, 40));
}
@@ -157,11 +157,11 @@ UNIT_TEST(BeginAgain)
PointD dir2(sqrt2 / 2.0, -sqrt2 / 2.0);
itr.Attach(spl);
TEST_EQUAL(itr.BeginAgain(), false, ());
- itr.Step(90.0);
+ itr.Advance(90.0);
TEST_EQUAL(itr.BeginAgain(), false, ());
- itr.Step(90.0);
+ itr.Advance(90.0);
TEST_EQUAL(itr.BeginAgain(), true, ());
- itr.Step(190.0);
+ itr.Advance(190.0);
TEST_EQUAL(itr.BeginAgain(), true, ());
path.clear();
@@ -174,11 +174,11 @@ UNIT_TEST(BeginAgain)
Spline spl2(path);
itr.Attach(spl2);
TEST_EQUAL(itr.BeginAgain(), false, ());
- itr.Step(90.0);
+ itr.Advance(90.0);
TEST_EQUAL(itr.BeginAgain(), false, ());
- itr.Step(90.0);
+ itr.Advance(90.0);
TEST_EQUAL(itr.BeginAgain(), true, ());
- itr.Step(190.0);
+ itr.Advance(190.0);
TEST_EQUAL(itr.BeginAgain(), true, ());
}
diff --git a/geometry/spline.cpp b/geometry/spline.cpp
index 1a2df1b5d3..1f2048f1a4 100644
--- a/geometry/spline.cpp
+++ b/geometry/spline.cpp
@@ -76,6 +76,34 @@ Spline::iterator::iterator()
, m_index(0)
, m_dist(0) {}
+Spline::iterator::iterator(Spline::iterator const & other)
+{
+ m_checker = other.m_checker;
+ m_spl = other.m_spl;
+ m_index = other.m_index;
+ m_dist = other.m_dist;
+
+ m_pos = other.m_pos;
+ m_dir = other.m_dir;
+ m_avrDir = other.m_avrDir;
+}
+
+Spline::iterator & Spline::iterator::operator=(Spline::iterator const & other)
+{
+ if (this == &other)
+ return *this;
+
+ m_checker = other.m_checker;
+ m_spl = other.m_spl;
+ m_index = other.m_index;
+ m_dist = other.m_dist;
+
+ m_pos = other.m_pos;
+ m_dir = other.m_dir;
+ m_avrDir = other.m_avrDir;
+ return *this;
+}
+
void Spline::iterator::Attach(Spline const & spl)
{
m_spl = &spl;
@@ -87,44 +115,12 @@ void Spline::iterator::Attach(Spline const & spl)
m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
}
-void Spline::iterator::Step(double speed)
-{
- m_dist += speed;
- if (m_checker)
- {
- m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
- return;
- }
- while (m_dist > m_spl->m_length[m_index])
- {
- m_dist -= m_spl->m_length[m_index];
- m_index++;
- if (m_index >= m_spl->m_direction.size())
- {
- m_index--;
- m_dist += m_spl->m_length[m_index];
- m_checker = true;
- break;
- }
- }
- m_dir = m_spl->m_direction[m_index];
- m_avrDir = -m_pos;
- m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
- m_avrDir += m_pos;
-}
-
-void Spline::iterator::StepBack(double speed)
+void Spline::iterator::Advance(double step)
{
- m_dist -= speed;
- while(m_dist < 0.0f)
- {
- m_index--;
- m_dist += m_spl->m_length[m_index];
- }
- m_dir = m_spl->m_direction[m_index];
- m_avrDir = -m_pos;
- m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
- m_avrDir += m_pos;
+ if (step < 0.0)
+ AdvanceBackward(step);
+ else
+ AdvanceForward(step);
}
double Spline::iterator::GetLength() const
@@ -152,6 +148,57 @@ int Spline::iterator::GetIndex() const
return m_index;
}
+void Spline::iterator::AdvanceBackward(double step)
+{
+ m_dist += step;
+ while(m_dist < 0.0f)
+ {
+ m_index--;
+ if (m_index < 0)
+ {
+ m_index = 0;
+ m_checker = true;
+ m_pos = m_spl->m_position[m_index];
+ m_dir = m_spl->m_direction[m_index];
+ m_avrDir = m2::PointD::Zero();
+ m_dist = 0.0;
+ return;
+ }
+
+ m_dist += m_spl->m_length[m_index];
+ }
+ m_dir = m_spl->m_direction[m_index];
+ m_avrDir = -m_pos;
+ m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
+ m_avrDir += m_pos;
+}
+
+void Spline::iterator::AdvanceForward(double step)
+{
+ m_dist += step;
+ if (m_checker)
+ {
+ m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
+ return;
+ }
+ while (m_dist > m_spl->m_length[m_index])
+ {
+ m_dist -= m_spl->m_length[m_index];
+ m_index++;
+ if (m_index >= m_spl->m_direction.size())
+ {
+ m_index--;
+ m_dist += m_spl->m_length[m_index];
+ m_checker = true;
+ break;
+ }
+ }
+ m_dir = m_spl->m_direction[m_index];
+ m_avrDir = -m_pos;
+ m_pos = m_spl->m_position[m_index] + m_dir * m_dist;
+ m_avrDir += m_pos;
+}
+
SharedSpline::SharedSpline(vector<PointD> const & path)
{
m_spline.reset(new Spline(path));
diff --git a/geometry/spline.hpp b/geometry/spline.hpp
index d313968ae3..12c5c77e79 100644
--- a/geometry/spline.hpp
+++ b/geometry/spline.hpp
@@ -17,10 +17,13 @@ public:
PointD m_pos;
PointD m_dir;
PointD m_avrDir;
+
iterator();
+ iterator(iterator const & other);
+ iterator & operator=(iterator const & other);
+
void Attach(Spline const & spl);
- void Step(double speed);
- void StepBack(double speed);
+ void Advance(double step);
bool BeginAgain() const;
double GetLength() const;
double GetFullLength() const;
@@ -30,6 +33,9 @@ public:
double GetDistance() const;
int GetIndex() const;
+ void AdvanceForward(double step);
+ void AdvanceBackward(double step);
+
private:
bool m_checker;
Spline const * m_spl;