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:
authorrachytski <siarhei.rachytski@gmail.com>2012-11-09 17:40:13 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:46:45 +0300
commitbcc94857d7b9f092148dea4a2a9b90c592f43a75 (patch)
tree7bf4c63e9b28fd0b00dfdcffcada9bb2c637b935 /graphics/straight_text_element.cpp
parent771f47410fa67f271cf425a2b1a9a0ed6119b4ea (diff)
renamed yg into graphics.
Diffstat (limited to 'graphics/straight_text_element.cpp')
-rw-r--r--graphics/straight_text_element.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/graphics/straight_text_element.cpp b/graphics/straight_text_element.cpp
new file mode 100644
index 0000000000..1826258b2a
--- /dev/null
+++ b/graphics/straight_text_element.cpp
@@ -0,0 +1,310 @@
+#include "../base/SRC_FIRST.hpp"
+#include "straight_text_element.hpp"
+#include "overlay_renderer.hpp"
+
+namespace graphics
+{
+ void visSplit(strings::UniString const & visText,
+ buffer_vector<strings::UniString, 3> & res,
+ char const * delimiters,
+ size_t delimSize,
+ bool splitAllFound)
+ {
+ if (!splitAllFound)
+ {
+ if (visText.size() > 15)
+ {
+ /// split into two
+ size_t rs = visText.size() / 2;
+ size_t ls = visText.size() / 2;
+
+ size_t s;
+
+ while (true)
+ {
+ if (rs == visText.size() - 1)
+ break;
+
+ bool foundDelim = false;
+
+ for (int i = 0; i < delimSize; ++i)
+ if (visText[rs] == strings::UniChar(delimiters[i]))
+ {
+ foundDelim = true;
+ break;
+ }
+
+ if (foundDelim)
+ break;
+
+ ++rs;
+ }
+
+ if (rs == visText.size() - 1)
+ {
+ while (true)
+ {
+ if (ls == 0)
+ break;
+
+ bool foundDelim = false;
+
+ for (int i = 0; i < delimSize; ++i)
+ if (visText[ls] == strings::UniChar(delimiters[i]))
+ {
+ foundDelim = true;
+ break;
+ }
+
+ if (foundDelim)
+ break;
+
+ --ls;
+ }
+
+ if (ls < 5)
+ s = visText.size() - 1;
+ else
+ s = ls;
+ }
+ else
+ s = rs;
+
+ res.push_back(strings::UniString());
+ res.back().resize(s + 1);
+ for (unsigned i = 0; i < s + 1; ++i)
+ res.back()[i] = visText[i];
+
+ if (s != visText.size() - 1)
+ {
+ res.push_back(strings::UniString());
+ res.back().resize(visText.size() - s - 1);
+ for (unsigned i = s + 1; i < visText.size(); ++i)
+ res.back()[i - s - 1] = visText[i];
+ }
+ }
+ else
+ res.push_back(visText);
+ }
+ else
+ {
+ size_t beg = 0;
+ size_t i = 0;
+ for (;i < visText.size(); ++i)
+ {
+ for (int j = 0; j < delimSize; ++j)
+ if (visText[i] == strings::UniChar(delimiters[j]))
+ {
+ strings::UniString s;
+ s.resize(i - beg);
+ for (unsigned k = beg; k < i; ++k)
+ s[k - beg] = visText[k];
+ res.push_back(s);
+ beg = i + 1;
+ }
+ }
+
+ strings::UniString s;
+
+ s.resize(i - beg);
+ for (unsigned k = beg; k < i; ++k)
+ s[k - beg] = visText[k];
+
+ res.push_back(s);
+ }
+ }
+
+ StraightTextElement::StraightTextElement(Params const & p)
+ : TextElement(p)
+ {
+ ASSERT(p.m_fontDesc.IsValid(), ());
+
+ buffer_vector<strings::UniString, 3> res;
+ if (p.m_doSplit && !isBidi())
+ {
+ res.clear();
+ if (!p.m_delimiters.empty())
+ visSplit(visText(), res, p.m_delimiters.c_str(), p.m_delimiters.size(), p.m_useAllParts);
+ else
+ visSplit(visText(), res, " \n\t", 3, p.m_useAllParts);
+ }
+ else
+ res.push_back(visText());
+
+ double allElemWidth = 0;
+ double allElemHeight = 0;
+
+ for (unsigned i = 0; i < res.size(); ++i)
+ {
+ m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_fontDesc, m2::PointD(0, 0), res[i], graphics::EPosCenter));
+ m2::RectD r = m_glyphLayouts.back().boundRects().back().GetGlobalRect();
+ allElemWidth = max(r.SizeX(), allElemWidth);
+ allElemHeight += r.SizeY();
+ }
+
+ buffer_vector<strings::UniString, 3> auxRes;
+
+ if (p.m_auxFontDesc.IsValid() && (!auxVisText().empty()))
+ {
+ GlyphLayout l(p.m_glyphCache, p.m_auxFontDesc, m2::PointD(0, 0), auxVisText(), graphics::EPosCenter);
+ if (l.boundRects().back().GetGlobalRect().SizeX() > allElemWidth)
+ {
+ // should split
+ if (p.m_doSplit && !isAuxBidi())
+ {
+ if (!p.m_delimiters.empty())
+ visSplit(auxVisText(), auxRes, p.m_delimiters.c_str(), p.m_delimiters.size(), p.m_useAllParts);
+ else
+ visSplit(auxVisText(), auxRes, " \n\t", 3, p.m_useAllParts);
+ }
+ else
+ auxRes.push_back(auxVisText());
+ }
+ else
+ auxRes.push_back(auxVisText());
+
+ for (int i = 0; i < auxRes.size(); ++i)
+ {
+ m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_auxFontDesc, m2::PointD(0, 0), auxRes[i], graphics::EPosCenter));
+ m2::RectD r = m_glyphLayouts.back().boundRects().back().GetGlobalRect();
+ allElemWidth = max(r.SizeX(), allElemWidth);
+ allElemHeight += r.SizeY();
+ }
+ }
+
+
+ double curShift = allElemHeight / 2;
+
+ /// performing aligning of glyphLayouts as for the center position
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ {
+ double elemSize = m_glyphLayouts[i].boundRects().back().GetGlobalRect().SizeY();
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, -curShift + elemSize / 2));
+ curShift -= elemSize;
+ }
+
+ if (position() & graphics::EPosLeft)
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(-allElemWidth / 2, 0));
+
+ if (position() & graphics::EPosRight)
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(allElemWidth / 2, 0));
+
+ if (position() & graphics::EPosAbove)
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, -allElemHeight / 2));
+
+ if (position() & graphics::EPosUnder)
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + m2::PointD(0, allElemHeight / 2));
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ {
+ m_offsets.push_back(m_glyphLayouts[i].pivot());
+ m_glyphLayouts[i].setPivot(m_offsets[i] + pivot());
+ }
+ }
+
+ StraightTextElement::Params::Params()
+ : m_minWordsInRow(2),
+ m_maxWordsInRow(4),
+ m_minSymInRow(10),
+ m_maxSymInRow(20),
+ m_doSplit(false)
+ {}
+
+ StraightTextElement::StraightTextElement(StraightTextElement const & src,
+ math::Matrix<double, 3, 3> const & m)
+ : TextElement(src),
+ m_glyphLayouts(src.m_glyphLayouts)
+ {
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_offsets = src.m_offsets;
+
+ setPivot(pivot() * m);
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ {
+ m_glyphLayouts[i].setPivot(pivot());
+ m_glyphLayouts[i].setOffset(m_offsets[i]);
+ }
+ }
+
+ vector<m2::AnyRectD> const & StraightTextElement::boundRects() const
+ {
+ if (isDirtyRect())
+ {
+ m_boundRects.clear();
+
+ for (size_t i = 0; i < m_glyphLayouts.size(); ++i)
+ copy(m_glyphLayouts[i].boundRects().begin(),
+ m_glyphLayouts[i].boundRects().end(),
+ back_inserter(m_boundRects));
+
+ setIsDirtyRect(false);
+ }
+ return m_boundRects;
+ }
+
+ void StraightTextElement::draw(gl::OverlayRenderer * screen, math::Matrix<double, 3, 3> const & m) const
+ {
+ if (screen->isDebugging())
+ {
+ graphics::Color c(255, 255, 255, 32);
+
+ if (isFrozen())
+ c = graphics::Color(0, 0, 255, 64);
+ if (isNeedRedraw())
+ c = graphics::Color(255, 0, 0, 64);
+
+ screen->drawRectangle(roughBoundRect(), graphics::Color(255, 255, 0, 64), graphics::maxDepth - 3);
+
+ for (unsigned i = 0 ; i < boundRects().size(); ++i)
+ screen->drawRectangle(boundRects()[i], c, graphics::maxDepth - 3);
+ }
+
+ if (!isNeedRedraw())
+ return;
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ {
+ if (m_glyphLayouts[i].fontDesc().m_isMasked)
+ drawTextImpl(m_glyphLayouts[i], screen, m, true, true, m_glyphLayouts[i].fontDesc(), graphics::maxDepth - 2);
+ }
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ {
+ graphics::FontDesc fontDesc = m_glyphLayouts[i].fontDesc();
+ fontDesc.m_isMasked = false;
+ drawTextImpl(m_glyphLayouts[i], screen, m, true, true, fontDesc, graphics::maxDepth - 1);
+ }
+ }
+
+ void StraightTextElement::setPivot(m2::PointD const & pv)
+ {
+ m2::PointD oldPv = pivot();
+ m2::PointD offs = pv - oldPv;
+
+ TextElement::setPivot(pv);
+
+ for (unsigned i = 0; i < m_glyphLayouts.size(); ++i)
+ m_glyphLayouts[i].setPivot(m_glyphLayouts[i].pivot() + offs);
+ }
+
+ int StraightTextElement::visualRank() const
+ {
+ return 1000 + m_fontDesc.m_size;
+ }
+
+ OverlayElement * StraightTextElement::clone(math::Matrix<double, 3, 3> const & m) const
+ {
+ return new StraightTextElement(*this, m);
+ }
+
+ bool StraightTextElement::hasSharpGeometry() const
+ {
+ return true;
+ }
+}