forked from organicmaps/organicmaps
Fix bug - recalculate text offset when path orientation changed. Minor code style fixes.
This commit is contained in:
parent
50f28e1197
commit
cf43af3886
1 changed files with 74 additions and 70 deletions
|
@ -79,15 +79,15 @@ namespace graphics
|
|||
m_textLength(0),
|
||||
m_textOffset(0)
|
||||
{
|
||||
if (!m_fontDesc.IsValid())
|
||||
return;
|
||||
|
||||
size_t const cnt = visText.size();
|
||||
ASSERT_GREATER(cnt, 0, ());
|
||||
|
||||
m_entries.resize(cnt);
|
||||
m_metrics.resize(cnt);
|
||||
|
||||
if (!m_fontDesc.IsValid())
|
||||
return;
|
||||
|
||||
m2::RectD boundRect;
|
||||
m2::PointD curPt(0, 0);
|
||||
|
||||
|
@ -134,7 +134,7 @@ namespace graphics
|
|||
m2::PointD ptOffs(-boundRect.SizeX() / 2 - boundRect.minX(),
|
||||
-boundRect.SizeY() / 2 - boundRect.minY());
|
||||
|
||||
/// adjusting according to position
|
||||
// adjusting according to position
|
||||
if (pos & EPosLeft)
|
||||
ptOffs += m2::PointD(-boundRect.SizeX() / 2, 0);
|
||||
|
||||
|
@ -167,15 +167,17 @@ namespace graphics
|
|||
m_offset(0, 0),
|
||||
m_textLength(src.m_textLength)
|
||||
{
|
||||
m_textOffset = (m2::PointD(0, src.m_textOffset) * m).Length(m2::PointD(0, 0) * m);
|
||||
|
||||
/// if isReverse flag is changed, recalculate m_textOffset
|
||||
if (src.m_path.isReverse() ^ m_path.isReverse())
|
||||
m_textOffset = m_path.fullLength() - m_textOffset - m_textLength;
|
||||
|
||||
if (!m_fontDesc.IsValid())
|
||||
return;
|
||||
|
||||
m_boundRects.push_back(m2::AnyRectD(m2::RectD(0, 0, 0, 0)));
|
||||
|
||||
m_textOffset = (m2::PointD(0, src.m_textOffset) * m).Length(m2::PointD(0, 0) * m);
|
||||
|
||||
// if isReverse flag is changed, recalculate m_textOffset
|
||||
if (src.m_path.isReverse() != m_path.isReverse())
|
||||
m_textOffset = m_path.fullLength() - m_textOffset - m_textLength;
|
||||
|
||||
recalcAlongPath();
|
||||
}
|
||||
|
||||
|
@ -199,85 +201,88 @@ namespace graphics
|
|||
{
|
||||
if (!m_fontDesc.IsValid())
|
||||
return;
|
||||
|
||||
m_boundRects.push_back(m2::AnyRectD(m2::RectD(0, 0, 0, 0)));
|
||||
|
||||
size_t cnt = m_visText.size();
|
||||
|
||||
size_t const cnt = m_visText.size();
|
||||
m_metrics.resize(cnt);
|
||||
|
||||
for (size_t i = 0; i < cnt; ++i)
|
||||
{
|
||||
GlyphKey key(visText[i],
|
||||
m_fontDesc.m_size,
|
||||
//m_fontDesc.m_isMasked,
|
||||
false, //< calculating glyph positions using the unmasked glyphs.
|
||||
false, // calculating glyph positions using the unmasked glyphs.
|
||||
graphics::Color(0, 0, 0, 0));
|
||||
m_metrics[i] = glyphCache->getGlyphMetrics(key);
|
||||
m_textLength += m_metrics[i].m_xAdvance;
|
||||
}
|
||||
|
||||
// if was reversed - recalculate m_textOffset
|
||||
if (m_path.isReverse())
|
||||
m_textOffset = m_path.fullLength() - m_textOffset - m_textLength;
|
||||
|
||||
recalcAlongPath();
|
||||
}
|
||||
|
||||
void GlyphLayout::recalcAlongPath()
|
||||
{
|
||||
// get vector of glyphs and calculate string length
|
||||
double strLength = 0.0;
|
||||
size_t count = m_visText.size();
|
||||
|
||||
if (count != 0)
|
||||
m_entries.resize(count);
|
||||
|
||||
for (size_t i = 0; i < m_entries.size(); ++i)
|
||||
{
|
||||
m_entries[i].m_sym = m_visText[i];
|
||||
strLength += m_metrics[i].m_xAdvance;
|
||||
}
|
||||
|
||||
if (m_path.fullLength() < strLength)
|
||||
size_t const count = m_visText.size();
|
||||
if (count == 0 || m_path.fullLength() < m_textLength)
|
||||
return;
|
||||
|
||||
m_entries.resize(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
m_entries[i].m_sym = m_visText[i];
|
||||
|
||||
PathPoint arrPathStart = m_path.front();
|
||||
|
||||
m_pivot = m_path.offsetPoint(arrPathStart, m_textOffset).m_pt;
|
||||
/// @todo Do we really need offset pivot somewhere?
|
||||
//m_path.offsetPoint(arrPathStart, m_textOffset).m_pt;
|
||||
m_pivot = arrPathStart.m_pt;
|
||||
|
||||
// offset of the text from path's start
|
||||
double offset = m_textOffset;
|
||||
double offset = m_textOffset - m_path.pathOffset();
|
||||
|
||||
// calculate base line offset
|
||||
double blOffset = 2 - m_fontDesc.m_size / 2;
|
||||
/// @todo The path text is always inside the path geometry now.
|
||||
//ASSERT_GREATER_OR_EQUAL(offset, 0.0, ());
|
||||
if (offset < 0.0) offset = 0.0;
|
||||
|
||||
offset -= m_path.pathOffset();
|
||||
if (-offset >= strLength)
|
||||
if (-offset >= m_textLength)
|
||||
return;
|
||||
|
||||
// find first visible glyph
|
||||
size_t symPos = 0;
|
||||
while (offset < 0 && symPos < count)
|
||||
offset += m_metrics[symPos++].m_xAdvance;
|
||||
//while (offset < 0 && symPos < count)
|
||||
// offset += m_metrics[symPos++].m_xAdvance;
|
||||
|
||||
PathPoint glyphStartPt = m_path.offsetPoint(arrPathStart, offset);
|
||||
|
||||
m_firstVisible = symPos;
|
||||
|
||||
GlyphLayoutElem prevElem; //< previous glyph, to compute kerning from
|
||||
GlyphLayoutElem prevElem; // previous glyph, to compute kerning from
|
||||
GlyphMetrics prevMetrics;
|
||||
bool hasPrevElem = false;
|
||||
|
||||
// calculate base line offset
|
||||
double const blOffset = 2 - m_fontDesc.m_size / 2;
|
||||
|
||||
for (; symPos < count; ++symPos)
|
||||
{
|
||||
/// full advance, including possible kerning.
|
||||
double fullGlyphAdvance = m_metrics[symPos].m_xAdvance;
|
||||
if (glyphStartPt.m_i == -1)
|
||||
{
|
||||
//LOG(LWARNING, ("Can't find glyph", symPos, count));
|
||||
return;
|
||||
}
|
||||
|
||||
GlyphMetrics const & metrics = m_metrics[symPos];
|
||||
GlyphLayoutElem & entry = m_entries[symPos];
|
||||
|
||||
if (glyphStartPt.m_i == -1)
|
||||
return;
|
||||
// full advance, including possible kerning.
|
||||
double fullGlyphAdvance = metrics.m_xAdvance;
|
||||
|
||||
if (metrics.m_width != 0)
|
||||
{
|
||||
double fullKern = 0;
|
||||
double kern = 0;
|
||||
|
||||
bool pathIsTooBended = false;
|
||||
|
||||
int i = 0;
|
||||
|
@ -286,55 +291,55 @@ namespace graphics
|
|||
PivotPoint pivotPt = m_path.findPivotPoint(glyphStartPt, metrics, fullKern);
|
||||
|
||||
if (pivotPt.m_pp.m_i == -1)
|
||||
{
|
||||
//LOG(LWARNING, ("Path text pivot error for glyph", symPos, count));
|
||||
return;
|
||||
}
|
||||
|
||||
m_entries[symPos].m_angle = pivotPt.m_angle;
|
||||
double centerOffset = metrics.m_xOffset + metrics.m_width / 2.0;
|
||||
m_entries[symPos].m_pt = pivotPt.m_pp.m_pt.Move(-centerOffset,
|
||||
m_entries[symPos].m_angle.sin(),
|
||||
m_entries[symPos].m_angle.cos());
|
||||
entry.m_angle = pivotPt.m_angle;
|
||||
double const centerOffset = metrics.m_xOffset + metrics.m_width / 2.0;
|
||||
entry.m_pt = pivotPt.m_pp.m_pt.Move(-centerOffset,
|
||||
entry.m_angle.sin(),
|
||||
entry.m_angle.cos());
|
||||
|
||||
m_entries[symPos].m_pt = m_entries[symPos].m_pt.Move(blOffset,
|
||||
-m_entries[symPos].m_angle.cos(),
|
||||
m_entries[symPos].m_angle.sin());
|
||||
entry.m_pt = entry.m_pt.Move(blOffset,
|
||||
-entry.m_angle.cos(),
|
||||
entry.m_angle.sin());
|
||||
|
||||
// check if angle between letters is too big
|
||||
if (hasPrevElem && (ang::GetShortestDistance(prevElem.m_angle.m_val, m_entries[symPos].m_angle.m_val) > 0.8)){
|
||||
if (hasPrevElem && (ang::GetShortestDistance(prevElem.m_angle.m_val, entry.m_angle.m_val) > 0.8))
|
||||
{
|
||||
pathIsTooBended = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// < check whether we should "kern"
|
||||
// check whether we should "kern"
|
||||
double kern = 0.0;
|
||||
if (hasPrevElem)
|
||||
{
|
||||
kern = getKerning(prevElem,
|
||||
prevMetrics,
|
||||
m_entries[symPos],
|
||||
m_metrics[symPos]);
|
||||
if (kern < 0.5)
|
||||
kern = 0;
|
||||
kern = getKerning(prevElem, prevMetrics, entry, metrics);
|
||||
if (kern < 0.5) kern = 0.0;
|
||||
|
||||
fullGlyphAdvance += kern;
|
||||
fullKern += kern;
|
||||
}
|
||||
|
||||
if (kern == 0)
|
||||
if (kern == 0.0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 100)
|
||||
{
|
||||
LOG(LINFO, ("100 iteration on computing kerning exceeded. possibly infinite loop occured"));
|
||||
}
|
||||
|
||||
if (pathIsTooBended)
|
||||
break;
|
||||
|
||||
/// kerning should be computed for baseline centered glyph
|
||||
prevElem = m_entries[symPos];
|
||||
prevMetrics = m_metrics[symPos];
|
||||
// kerning should be computed for baseline centered glyph
|
||||
prevElem = entry;
|
||||
prevMetrics = metrics;
|
||||
hasPrevElem = true;
|
||||
|
||||
// < align to baseline
|
||||
// m_entries[symPos].m_pt = m_entries[symPos].m_pt.Move(blOffset - kernOffset, m_entries[symPos].m_angle - math::pi / 2);
|
||||
// align to baseline
|
||||
//entry.m_pt = entry.m_pt.Move(blOffset - kernOffset, entry.m_angle - math::pi / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -350,12 +355,11 @@ namespace graphics
|
|||
}
|
||||
|
||||
glyphStartPt = m_path.offsetPoint(glyphStartPt, fullGlyphAdvance);
|
||||
offset += fullGlyphAdvance;
|
||||
|
||||
m_lastVisible = symPos + 1;
|
||||
}
|
||||
|
||||
/// storing glyph coordinates relative to pivot point.
|
||||
// storing glyph coordinates relative to pivot point.
|
||||
for (unsigned i = m_firstVisible; i < m_lastVisible; ++i)
|
||||
m_entries[i].m_pt -= m_pivot;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue