1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "../base/SRC_FIRST.hpp"
#include "text_path.hpp"
#include "../geometry/angles.hpp"
namespace graphics
{
TextPath::TextPath()
: m_pv(),
m_fullLength(0),
m_pathOffset(0)
{}
TextPath::TextPath(TextPath const & src, math::Matrix<double, 3, 3> const & m)
{
m_arr.resize(src.m_arr.size());
for (unsigned i = 0; i < m_arr.size(); ++i)
m_arr[i] = src.m_arr[i] * m;
m_fullLength = (m2::PointD(src.m_fullLength, 0) * m).Length(m2::PointD(0, 0) * m);
m_pathOffset = (m2::PointD(src.m_pathOffset, 0) * m).Length(m2::PointD(0, 0) * m);
m_pv = PathView(&m_arr[0], m_arr.size());
/// Fix: Check for reversing only when rotation is active,
/// otherwise we have some flicker-blit issues for street names on zooming.
/// @todo Should investigate this stuff.
if (m(0, 1) != 0.0 && m(1, 0) != 0.0)
checkReverse();
else
setIsReverse(src.isReverse());
}
TextPath::TextPath(m2::PointD const * arr, size_t sz, double fullLength, double pathOffset)
: m_fullLength(fullLength),
m_pathOffset(pathOffset)
{
ASSERT ( sz > 1, () );
m_arr.resize(sz);
copy(arr, arr + sz, m_arr.begin());
m_pv = PathView(&m_arr[0], m_arr.size());
checkReverse();
}
bool TextPath::isReverse() const
{
return m_pv.isReverse();
}
void TextPath::setIsReverse(bool flag)
{
m_pv.setIsReverse(flag);
}
void TextPath::checkReverse()
{
/* assume, that readable text in path should be ('o' - start draw point):
* / o
* / \
* / or \
* o \
*/
double const a = ang::AngleTo(m_arr[0], m_arr[m_arr.size() - 1]);
if (fabs(a) > math::pi / 2.0)
{
// if we swap direction, we need to recalculate path offset from the end
double len = 0.0;
for (size_t i = 1; i < m_arr.size(); ++i)
len += m_arr[i-1].Length(m_arr[i]);
m_pathOffset = m_fullLength - m_pathOffset - len;
ASSERT ( m_pathOffset >= -1.0E-6, () );
if (m_pathOffset < 0.0)
m_pathOffset = 0.0;
setIsReverse(true);
}
else
setIsReverse(false);
}
double TextPath::fullLength() const
{
return m_fullLength;
}
double TextPath::pathOffset() const
{
return m_pathOffset;
}
size_t TextPath::size() const
{
return m_pv.size();
}
m2::PointD TextPath::get(size_t i) const
{
return m_pv.get(i);
}
m2::PointD TextPath::operator[](size_t i) const
{
return get(i);
}
PathPoint const TextPath::offsetPoint(PathPoint const & pp, double offset) const
{
return m_pv.offsetPoint(pp, offset);
}
PivotPoint TextPath::findPivotPoint(PathPoint const & pp, GlyphMetrics const & sym, double kern) const
{
return m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width / 2.0, kern);
}
PathPoint const TextPath::front() const
{
return m_pv.front();
}
}
|