support a max width property for drawable texts

This commit is contained in:
ExMix 2013-05-23 15:31:39 +03:00 committed by Alex Zolotarev
parent 76605ec17b
commit 6cc0074db7
6 changed files with 160 additions and 75 deletions

View file

@ -79,80 +79,24 @@ namespace graphics
m_textLength(0),
m_textOffset(0)
{
if (!m_fontDesc.IsValid())
return;
initStraigthText(glyphCache, fontDesc, pt, visText, pos, numeric_limits<unsigned>::max());
}
size_t const cnt = visText.size();
ASSERT_GREATER(cnt, 0, ());
m_entries.resize(cnt);
m_metrics.resize(cnt);
m2::RectD boundRect;
m2::PointD curPt(0, 0);
bool isFirst = true;
for (size_t i = 0; i < visText.size(); ++i)
{
GlyphKey glyphKey(visText[i],
fontDesc.m_size,
//fontDesc.m_isMasked,
false, //< calculating glyph positions using unmasked glyphs.
fontDesc.m_color);
GlyphMetrics const m = glyphCache->getGlyphMetrics(glyphKey);
m_textLength += m.m_xAdvance;
if (isFirst)
{
boundRect = m2::RectD(m.m_xOffset,
-m.m_yOffset,
m.m_xOffset,
-m.m_yOffset);
isFirst = false;
}
else
boundRect.Add(m2::PointD(m.m_xOffset + curPt.x, -m.m_yOffset + curPt.y));
boundRect.Add(m2::PointD(m.m_xOffset + m.m_width,
-(m.m_yOffset + m.m_height)) + curPt);
GlyphLayoutElem elem;
elem.m_sym = visText[i];
elem.m_angle = 0;
elem.m_pt = curPt;
m_entries[i] = elem;
m_metrics[i] = m;
curPt += m2::PointD(m.m_xAdvance, m.m_yAdvance);
}
boundRect.Inflate(2, 2);
m2::PointD ptOffs(-boundRect.SizeX() / 2 - boundRect.minX(),
-boundRect.SizeY() / 2 - boundRect.minY());
// adjusting according to position
if (pos & EPosLeft)
ptOffs += m2::PointD(-boundRect.SizeX() / 2, 0);
if (pos & EPosRight)
ptOffs += m2::PointD(boundRect.SizeX() / 2, 0);
if (pos & EPosAbove)
ptOffs += m2::PointD(0, -boundRect.SizeY() / 2);
if (pos & EPosUnder)
ptOffs += m2::PointD(0, boundRect.SizeY() / 2);
for (unsigned i = 0; i < m_entries.size(); ++i)
m_entries[i].m_pt += ptOffs;
boundRect.Offset(ptOffs);
m_boundRects.push_back(m2::AnyRectD(boundRect));
GlyphLayout::GlyphLayout(GlyphCache * glyphCache,
FontDesc const & fontDesc,
m2::PointD const & pt,
strings::UniString const & visText,
graphics::EPosition pos,
unsigned maxWidth)
: m_firstVisible(0),
m_lastVisible(visText.size()),
m_fontDesc(fontDesc),
m_pivot(pt),
m_offset(0, 0),
m_textLength(0),
m_textOffset(0)
{
initStraigthText(glyphCache, fontDesc, pt, visText, pos, maxWidth);
}
GlyphLayout::GlyphLayout(GlyphLayout const & src,
@ -224,6 +168,115 @@ namespace graphics
recalcAlongPath();
}
void GlyphLayout::addGlyph(GlyphCache * glyphCache,
GlyphKey const & key,
bool isFirst,
strings::UniChar symbol,
m2::RectD & boundRect,
m2::PointD & curPt)
{
GlyphMetrics const m = glyphCache->getGlyphMetrics(key);
m_textLength += m.m_xAdvance;
if (isFirst)
{
boundRect = m2::RectD(m.m_xOffset,
-m.m_yOffset,
m.m_xOffset,
-m.m_yOffset);
}
else
boundRect.Add(m2::PointD(m.m_xOffset + curPt.x, -m.m_yOffset + curPt.y));
boundRect.Add(m2::PointD(m.m_xOffset + m.m_width,
-(m.m_yOffset + m.m_height)) + curPt);
GlyphLayoutElem elem;
elem.m_sym = symbol;
elem.m_angle = 0;
elem.m_pt = curPt;
m_entries.push_back(elem);
m_metrics.push_back(m);
curPt += m2::PointD(m.m_xAdvance, m.m_yAdvance);
}
void GlyphLayout::initStraigthText(GlyphCache * glyphCache,
FontDesc const & fontDesc,
m2::PointD const & pt,
strings::UniString const & visText,
graphics::EPosition pos,
unsigned maxWidth)
{
if (!m_fontDesc.IsValid())
return;
size_t const cnt = visText.size();
ASSERT_GREATER(cnt, 0, ());
m_entries.reserve(cnt + 2);
m_metrics.reserve(cnt + 2);
m2::RectD boundRect;
m2::PointD curPt(0, 0);
bool isFirst = true;
strings::UniChar dotSymbol = strings::MakeUniString(".")[0];
GlyphKey dotKey(dotSymbol,
fontDesc.m_size,
false,
fontDesc.m_color);
maxWidth -= glyphCache->getGlyphMetrics(dotKey).m_xAdvance;
for (size_t i = 0; i < visText.size(); ++i)
{
if (m_textLength >= maxWidth)
{
addGlyph(glyphCache, dotKey, isFirst, dotSymbol, boundRect, curPt);
addGlyph(glyphCache, dotKey, isFirst, dotSymbol, boundRect, curPt);
addGlyph(glyphCache, dotKey, isFirst, dotSymbol, boundRect, curPt);
m_lastVisible = i + 3;
break;
}
GlyphKey glyphKey(visText[i],
fontDesc.m_size,
false, //< calculating glyph positions using unmasked glyphs.
fontDesc.m_color);
addGlyph(glyphCache, glyphKey, isFirst, visText[i], boundRect, curPt);
isFirst = false;
}
boundRect.Inflate(2, 2);
m2::PointD ptOffs(-boundRect.SizeX() / 2 - boundRect.minX(),
-boundRect.SizeY() / 2 - boundRect.minY());
// adjusting according to position
if (pos & EPosLeft)
ptOffs += m2::PointD(-boundRect.SizeX() / 2, 0);
if (pos & EPosRight)
ptOffs += m2::PointD(boundRect.SizeX() / 2, 0);
if (pos & EPosAbove)
ptOffs += m2::PointD(0, -boundRect.SizeY() / 2);
if (pos & EPosUnder)
ptOffs += m2::PointD(0, boundRect.SizeY() / 2);
for (unsigned i = 0; i < m_entries.size(); ++i)
m_entries[i].m_pt += ptOffs;
boundRect.Offset(ptOffs);
m_boundRects.push_back(m2::AnyRectD(boundRect));
}
void GlyphLayout::recalcAlongPath()
{
size_t const count = m_visText.size();

View file

@ -64,6 +64,20 @@ namespace graphics
void recalcPivot();
void recalcAlongPath();
inline void addGlyph(GlyphCache * glyphCache,
GlyphKey const & key,
bool isFirst,
strings::UniChar symbol,
m2::RectD & boundRect,
m2::PointD & curPt);
void initStraigthText(GlyphCache * glyphCache,
FontDesc const & font,
m2::PointD const & pt,
strings::UniString const & visText,
graphics::EPosition pos,
unsigned maxWidth);
public:
GlyphLayout();
@ -77,6 +91,13 @@ namespace graphics
strings::UniString const & visText,
graphics::EPosition pos);
GlyphLayout(GlyphCache * glyphCache,
FontDesc const & font,
m2::PointD const & pt,
strings::UniString const & visText,
graphics::EPosition pos,
unsigned maxWidth);
GlyphLayout(GlyphCache * glyphCache,
FontDesc const & font,
m2::PointD const * pts,

View file

@ -97,7 +97,7 @@ namespace graphics
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));
m_glyphLayouts.push_back(GlyphLayout(p.m_glyphCache, p.m_fontDesc, m2::PointD(0, 0), res[i], graphics::EPosCenter, p.m_maxPixelWidth));
m2::RectD r = m_glyphLayouts.back().boundRects().back().GetGlobalRect();
allElemWidth = max(r.SizeX(), allElemWidth);
allElemHeight += r.SizeY();
@ -168,6 +168,7 @@ namespace graphics
m_maxWordsInRow(4),
m_minSymInRow(10),
m_maxSymInRow(20),
m_maxPixelWidth(numeric_limits<unsigned>::max()),
m_doSplit(false),
m_useAllParts(true),
m_offset(0, 0)

View file

@ -20,6 +20,7 @@ namespace graphics
unsigned m_maxWordsInRow;
unsigned m_minSymInRow;
unsigned m_maxSymInRow;
unsigned m_maxPixelWidth;
bool m_doSplit;
bool m_useAllParts;
m2::PointD m_offset;

View file

@ -8,7 +8,7 @@
namespace gui
{
TextView::TextView(Params const & p)
: Element(p)
: Element(p), m_maxWidth(numeric_limits<unsigned>::max())
{
setText(p.m_text);
@ -50,6 +50,7 @@ namespace gui
params.m_doSplit = true;
params.m_delimiters = "\n";
params.m_useAllParts = true;
params.m_maxPixelWidth = m_maxWidth;
elem.reset(new graphics::StraightTextElement(params));
}
@ -136,6 +137,12 @@ namespace gui
return m_boundRects;
}
void TextView::setMaxWidth(unsigned width)
{
m_maxWidth = width;
setIsDirtyLayout(true);
}
bool TextView::onTapStarted(m2::PointD const & pt)
{
return false;

View file

@ -20,6 +20,7 @@ namespace gui
map<EState, shared_ptr<graphics::StraightTextElement> > m_elems;
string m_text;
unsigned m_maxWidth;
mutable vector<m2::AnyRectD> m_boundRects;
@ -41,6 +42,7 @@ namespace gui
void setText(string const & text);
string const & text() const;
void setMaxWidth(unsigned width);
vector<m2::AnyRectD> const & boundRects() const;
void draw(graphics::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;