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:
authorRoman Sorokin <sorok-roma@yandex.ru>2014-09-10 11:04:54 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:27:00 +0300
commit452fde5f265e30cac0f2f24da3dafce0c48af613 (patch)
tree5af7dccd9e83bdd32707d2aa9d269edf6744b388 /drape_frontend
parentc1ef0f2d54a97d7e11a0078c522514871da3f9c0 (diff)
Splitting long text into small parts
Diffstat (limited to 'drape_frontend')
-rw-r--r--drape_frontend/text_shape.cpp225
-rw-r--r--drape_frontend/text_shape.hpp9
2 files changed, 159 insertions, 75 deletions
diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp
index 798ac7065c..74cb381dc1 100644
--- a/drape_frontend/text_shape.cpp
+++ b/drape_frontend/text_shape.cpp
@@ -113,105 +113,188 @@ TextShape::TextShape(m2::PointF const & basePoint, TextViewParams const & params
m_params(params)
{
}
+///Old code
+void TextShape::visSplit(strings::UniString const & visText,
+ buffer_vector<strings::UniString, 3> & res,
+ char const * delims,
+ bool splitAllFound) const
+{
+ if (!splitAllFound)
+ {
+ size_t count = visText.size();
+ if (count > 15)
+ {
+ // split on two parts
+ typedef strings::UniString::const_iterator IterT;
+ IterT const iMiddle = visText.begin() + count/2;
+
+ size_t const delimsSize = strlen(delims);
+
+ // find next delimeter after middle [m, e)
+ IterT iNext = find_first_of(iMiddle,
+ visText.end(),
+ delims, delims + delimsSize);
+
+ // find last delimeter before middle [b, m)
+ IterT iPrev = find_first_of(reverse_iterator<IterT>(iMiddle),
+ reverse_iterator<IterT>(visText.begin()),
+ delims, delims + delimsSize).base();
+ // don't do split like this:
+ // xxxx
+ // xxxxxxxxxxxx
+ if (4 * distance(visText.begin(), iPrev) <= count)
+ iPrev = visText.end();
+ else
+ --iPrev;
+
+ // get closest delimiter to the middle
+ if (iNext == visText.end() ||
+ (iPrev != visText.end() && distance(iPrev, iMiddle) < distance(iMiddle, iNext)))
+ {
+ iNext = iPrev;
+ }
+
+ // split string on 2 parts
+ if (iNext != visText.end())
+ {
+ ASSERT_NOT_EQUAL(iNext, visText.begin(), ());
+ res.push_back(strings::UniString(visText.begin(), iNext));
+
+ if (++iNext != visText.end())
+ res.push_back(strings::UniString(iNext, visText.end()));
+
+ return;
+ }
+ }
+
+ res.push_back(visText);
+ }
+ else
+ {
+ // split string using according to all delimiters
+ typedef strings::SimpleDelimiter DelimT;
+ for (strings::TokenizeIterator<DelimT> iter(visText, DelimT(delims)); iter; ++iter)
+ res.push_back(iter.GetUniString());
+ }
+}
void TextShape::Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const
{
ASSERT(!m_params.m_primaryText.empty(), ());
+ vector<TextLayout> layouts;
if (m_params.m_secondaryText.empty())
{
- TextLayout const primaryLayout(fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText)),
- m_params.m_primaryTextFont, textures);
- if (primaryLayout.GetGlyphCount() == 0)
+ strings::UniString text = fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText));
+ if (text.size() == 0)
return;
- DrawSingleLine(batcher, primaryLayout);
+ buffer_vector<strings::UniString, 3> res;
+ visSplit(text, res, " \n\t", false);
+ for (int i = 0; i < res.size(); ++i)
+ layouts.push_back(TextLayout(res[res.size() - i - 1], m_params.m_primaryTextFont, textures));
+
+ vector<bool> dels(layouts.size(), false);
+ dels[dels.size() - 1] = true;
+ DrawPolyLine(batcher, layouts, dels);
}
else
{
- TextLayout const primaryLayout(fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText)),
- m_params.m_primaryTextFont, textures);
- TextLayout const secondaryLayout(fribidi::log2vis(strings::MakeUniString(m_params.m_secondaryText)),
- m_params.m_secondaryTextFont, textures);
- uint32_t primGlyphCount = primaryLayout.GetGlyphCount();
- uint32_t secondGlyphCount = secondaryLayout.GetGlyphCount();
+ strings::UniString primaryText = fribidi::log2vis(strings::MakeUniString(m_params.m_primaryText));
+ strings::UniString secondaryText = fribidi::log2vis(strings::MakeUniString(m_params.m_secondaryText));
+ uint32_t primGlyphCount = primaryText.size();
+ uint32_t secondGlyphCount = secondaryText.size();
+ buffer_vector<strings::UniString, 3> primRes;
+ buffer_vector<strings::UniString, 3> secRes;
if (primGlyphCount == 0 && secondGlyphCount == 0)
return;
if (primGlyphCount == 0)
- DrawSingleLine(batcher, secondaryLayout);
+ {
+ visSplit(secondaryText, secRes, " \n\t", false);
+ for (int i = 0; i < secRes.size(); ++i)
+ layouts.push_back(TextLayout(secRes[secRes.size() - i - 1], m_params.m_secondaryTextFont, textures));
+ vector<bool> dels(layouts.size(), false);
+ dels[dels.size() - 1] = true;
+ DrawPolyLine(batcher, layouts, dels);
+ }
else if (secondGlyphCount == 0)
- DrawSingleLine(batcher, primaryLayout);
+ {
+ visSplit(primaryText, primRes, " \n\t", false);
+ for (int i = 0; i < primRes.size(); ++i)
+ layouts.push_back(TextLayout(primRes[primRes.size() - i - 1], m_params.m_primaryTextFont, textures));
+ vector<bool> dels(layouts.size(), false);
+ dels[dels.size() - 1] = true;
+ DrawPolyLine(batcher, layouts, dels);
+ }
else
- DrawDoubleLine(batcher, primaryLayout, secondaryLayout);
+ {
+ visSplit(primaryText, primRes, " \n\t", false);
+ visSplit(secondaryText, secRes, " \n\t", false);
+ for (int i = 0; i < secRes.size(); ++i)
+ layouts.push_back(TextLayout(secRes[secRes.size() - i - 1], m_params.m_secondaryTextFont, textures));
+ for (int i = 0; i < primRes.size(); ++i)
+ layouts.push_back(TextLayout(primRes[primRes.size() - i - 1], m_params.m_primaryTextFont, textures));
+ vector<bool> dels(layouts.size(), false);
+ dels[secRes.size()-1] = true;
+ dels[dels.size() - 1] = true;
+ DrawPolyLine(batcher, layouts, dels);
+ }
}
}
-void TextShape::DrawSingleLine(dp::RefPointer<dp::Batcher> batcher, TextLayout const & layout) const
-{
- size_t glyphCount = layout.GetGlyphCount();
- vector<glsl_types::Quad4> positions(glyphCount);
- vector<glsl_types::Quad4> texCoord(glyphCount);
- vector<glsl_types::Quad4> fontColor(glyphCount);
- vector<glsl_types::Quad4> outlineColor(glyphCount);
-
- PointF const pixelOffset = GetShift(m_params.m_anchor, layout.GetPixelLength(), m_params.m_primaryTextFont.m_size) + m_params.m_primaryOffset;
- dp::OverlayHandle * handle = layout.LayoutText(m_params.m_featureID, m_basePoint,
- pixelOffset, m_params.m_depth,
- positions, texCoord, fontColor, outlineColor);
- BatchText(batcher, layout.GetTextureSet(),
- positions, texCoord,
- fontColor, outlineColor,
- glyphCount, handle);
-}
-
-void TextShape::DrawDoubleLine(dp::RefPointer<dp::Batcher> batcher, TextLayout const & primaryLayout,
- TextLayout const & secondaryLayout) const
+void TextShape::DrawPolyLine(dp::RefPointer<dp::Batcher> batcher, vector<TextLayout> & layouts, vector<bool> & delims) const
{
- float const primaryTextLength = primaryLayout.GetPixelLength();
- float const secondaryTextLength = secondaryLayout.GetPixelLength();
- bool const isPrimaryLonger = primaryTextLength > secondaryTextLength;
- float const maxLength = max(primaryTextLength, secondaryTextLength);
- float const minLength = min(primaryTextLength, secondaryTextLength);
- float const halfLengthDiff = (maxLength - minLength) / 2.0;
-
- uint32_t primarySize = m_params.m_primaryTextFont.m_size;
- uint32_t secondarySize = m_params.m_secondaryTextFont.m_size;
-
- float const textHeight = TEXT_EXPAND_FACTOR * (primarySize + secondarySize);
- PointF const anchorOffset = GetShift(m_params.m_anchor, maxLength, textHeight);
+ uint32_t const count = layouts.size();
+ vector<float> lengths(count);
+ float maxLength = 0.0f;
+ float textHeight = 0.0f;
+ uint32_t maxCount = 0;
+ uint32_t symCount = 0;
+ vector<uint32_t> heights(count);
+ for (int i = 0; i < count; ++i)
+ {
+ lengths[i] = layouts[i].GetPixelLength();
+ heights[i] = layouts[i].GetPixelHeight();
+ textHeight += heights[i];
+ maxLength = max(maxLength, lengths[i]);
+ symCount += layouts[i].GetGlyphCount();
+ maxCount = max(maxCount, layouts[i].GetGlyphCount());
+ }
- float const primaryDx = isPrimaryLonger ? 0.0f : halfLengthDiff;
- float const primaryDy = (1.0f - TEXT_EXPAND_FACTOR) * primarySize - TEXT_EXPAND_FACTOR * secondarySize;
- PointF const primaryPixelOffset = PointF(primaryDx, primaryDy) + anchorOffset + m_params.m_primaryOffset;
+ PointF const anchorOffset = GetShift(m_params.m_anchor, maxLength, textHeight * TEXT_EXPAND_FACTOR);
- size_t glyphCount = max(primaryLayout.GetGlyphCount(), secondaryLayout.GetGlyphCount());
- vector<glsl_types::Quad4> positions(glyphCount);
- vector<glsl_types::Quad4> texCoord(glyphCount);
- vector<glsl_types::Quad4> fontColor(glyphCount);
- vector<glsl_types::Quad4> outlineColor(glyphCount);
+ vector<glsl_types::Quad4> positions(symCount);
+ vector<glsl_types::Quad4> texCoord(symCount);
+ vector<glsl_types::Quad4> fontColor(symCount);
+ vector<glsl_types::Quad4> outlineColor(symCount);
+ float dy = (1.0f - TEXT_EXPAND_FACTOR) * heights[0];
+ vector<PointF> pixelOffset;
+ uint32_t delSymCount = 0;
+ uint32_t lastIndex = 0;
+ ASSERT(delims.back(), ());
+ for (int i = 0; i < count; ++i)
{
- dp::OverlayHandle * handle = primaryLayout.LayoutText(m_params.m_featureID, m_basePoint,
- primaryPixelOffset, m_params.m_depth,
- positions, texCoord, fontColor, outlineColor);
- BatchText(batcher, primaryLayout.GetTextureSet(),
- positions, texCoord,
- fontColor, outlineColor,
- primaryLayout.GetGlyphCount(), handle);
- }
+ float const dx = (maxLength - lengths[i]) / 2.0f;
+ pixelOffset.push_back(PointF(dx, dy) + anchorOffset + m_params.m_primaryOffset);
+ dy -= heights[i] * TEXT_EXPAND_FACTOR;
+ delSymCount += layouts[i].GetGlyphCount();
+ if (delims[i])
+ {
+ dp::OverlayHandle * handle = LayoutText(m_params.m_featureID, m_basePoint,
+ pixelOffset, m_params.m_depth,
+ positions, texCoord, fontColor, outlineColor, &layouts[lastIndex]);
- float const secondaryDx = isPrimaryLonger ? halfLengthDiff : 0.0f;
- PointF const secondaryPixelOffset = PointF(secondaryDx, 0.0f) + anchorOffset + m_params.m_primaryOffset;
+ BatchText(batcher, layouts[0].GetTextureSet(),
+ positions, texCoord,
+ fontColor, outlineColor,
+ delSymCount, handle);
- {
- dp::OverlayHandle * handle = secondaryLayout.LayoutText(m_params.m_featureID, m_basePoint,
- secondaryPixelOffset, m_params.m_depth,
- positions, texCoord, fontColor, outlineColor);
- BatchText(batcher, secondaryLayout.GetTextureSet(),
- positions, texCoord,
- fontColor, outlineColor,
- secondaryLayout.GetGlyphCount(), handle);
+ pixelOffset.clear();
+ delSymCount = 0;
+ lastIndex = i + 1;
+ }
}
}
diff --git a/drape_frontend/text_shape.hpp b/drape_frontend/text_shape.hpp
index baa5a349ed..168a52688f 100644
--- a/drape_frontend/text_shape.hpp
+++ b/drape_frontend/text_shape.hpp
@@ -17,11 +17,12 @@ public:
TextShape(m2::PointF const & basePoint, TextViewParams const & params);
void Draw(dp::RefPointer<dp::Batcher> batcher, dp::RefPointer<dp::TextureSetHolder> textures) const;
-
+ void visSplit(strings::UniString const & visText,
+ buffer_vector<strings::UniString, 3> & res,
+ char const * delims,
+ bool splitAllFound) const;
private:
- void DrawSingleLine(dp::RefPointer<dp::Batcher> batcher, TextLayout const & layout) const;
- void DrawDoubleLine(dp::RefPointer<dp::Batcher> batcher, TextLayout const & primaryLayout,
- TextLayout const & secondaryLayout) const;
+ void DrawPolyLine(dp::RefPointer<dp::Batcher> batcher, vector<TextLayout> & layouts, vector<bool> & delims) const;
private:
m2::PointF m_basePoint;