"base class extraction" refactoring for TextPath.

This commit is contained in:
rachytski 2013-01-15 12:33:06 +03:00 committed by Alex Zolotarev
parent ee425ef178
commit 178f6fa4fa
6 changed files with 249 additions and 127 deletions

View file

@ -223,7 +223,7 @@ namespace graphics
if (m_path.fullLength() < strLength)
return;
PathPoint arrPathStart(0, ang::AngleD(ang::AngleTo(m_path.get(0), m_path.get(1))), m_path.get(0));
PathPoint arrPathStart = m_path.front();
m_pivot = m_path.offsetPoint(arrPathStart, m_path.fullLength() / 2.0).m_pt;

View file

@ -72,7 +72,8 @@ SOURCES += \
icon.cpp \
brush.cpp \
geometry_pipeline.cpp \
pipeline_manager.cpp
pipeline_manager.cpp \
path_view.cpp \
HEADERS += \
opengl/opengl.hpp \
@ -140,7 +141,8 @@ HEADERS += \
brush.hpp \
geometry_pipeline.hpp \
pipeline_manager.hpp \
vertex_stream.hpp
vertex_stream.hpp \
path_view.hpp \
win32* {
SOURCES += opengl/opengl_win32.cpp

144
graphics/path_view.cpp Normal file
View file

@ -0,0 +1,144 @@
#include "path_view.hpp"
namespace graphics
{
PathPoint::PathPoint(int i, ang::AngleD const & segAngle, m2::PointD const & pt)
: m_i(i),
m_segAngle(segAngle),
m_pt(pt)
{}
PivotPoint::PivotPoint(ang::AngleD const & angle, PathPoint const & pp)
: m_angle(angle), m_pp(pp)
{}
PathView::PathView()
: m_pts(0),
m_ptsCount(0),
m_isReverse(false)
{}
PathView::PathView(m2::PointD const * pts,
size_t ptsCount)
: m_pts(pts),
m_ptsCount(ptsCount),
m_isReverse(false)
{
}
size_t PathView::size() const
{
return m_ptsCount;
}
m2::PointD const & PathView::get(size_t i) const
{
ASSERT(i < m_ptsCount, ("index out of range"));
return m_pts[m_isReverse ? m_ptsCount - i - 1 : i];
}
void PathView::setIsReverse(bool flag)
{
m_isReverse = flag;
}
bool PathView::isReverse() const
{
return m_isReverse;
}
PathPoint const PathView::offsetPoint(PathPoint const & pp, double offset)
{
PathPoint res = pp;
if (res.m_i == -1)
return res;
if (offset == 0)
return pp;
bool found = false;
for (size_t i = res.m_i; i < size() - 1; ++i)
{
double l = res.m_pt.Length(get(i + 1));
if (offset <= l)
{
if (i != res.m_i)
res.m_segAngle = ang::AngleD(ang::AngleTo(get(i), get(i + 1)));
res.m_pt = res.m_pt.Move(offset, res.m_segAngle.sin(), res.m_segAngle.cos());
res.m_i = i;
found = true;
break;
}
else
{
offset -= l;
res.m_pt = get(i + 1);
}
}
if (!found)
res.m_i = -1;
return res;
}
PivotPoint PathView::findPivotPoint(PathPoint const & pp, double advance, double kern)
{
PathPoint startPt = offsetPoint(pp, kern);
PivotPoint res;
if (startPt.m_i == -1)
return res;
m2::PointD pt1 = startPt.m_pt;
double angle = 0;
int j = startPt.m_i;
while (advance > 0)
{
if (j + 1 == size())
return res;
double l = get(j + 1).Length(pt1);
double segAngle = j == startPt.m_i ? startPt.m_segAngle.val()
: ang::AngleTo(get(j), get(j + 1));
angle += segAngle;
if (l < advance)
{
advance -= l;
pt1 = get(j + 1);
++j;
}
else
{
ang::AngleD a(segAngle);
res.m_pp.m_i = j;
res.m_pp.m_pt = pt1.Move(advance, a.sin(), a.cos());
advance = 0;
angle /= (res.m_pp.m_i - startPt.m_i + 1);
res.m_angle = ang::AngleD(angle);
res.m_pp.m_segAngle = a;
break;
}
}
return res;
}
PathPoint const PathView::front() const
{
return PathPoint(0, ang::AngleD(ang::AngleTo(get(0), get(1))), get(0));
}
}

51
graphics/path_view.hpp Normal file
View file

@ -0,0 +1,51 @@
#pragma once
#include "../geometry/point2d.hpp"
#include "../geometry/angles.hpp"
namespace graphics
{
struct PathPoint
{
int m_i; //< segment number
ang::AngleD m_segAngle;
m2::PointD m_pt; //< point on segment
PathPoint(int i = -1,
ang::AngleD const & segAngle = ang::AngleD(),
m2::PointD const & pt = m2::PointD());
};
struct PivotPoint
{
ang::AngleD m_angle;
PathPoint m_pp;
PivotPoint(ang::AngleD const & angle = ang::AngleD(), PathPoint const & pp = PathPoint());
};
class PathView
{
private:
m2::PointD const * m_pts;
size_t m_ptsCount;
bool m_isReverse;
public:
PathView();
PathView(m2::PointD const * pts, size_t ptsCount);
size_t size() const;
m2::PointD const & get(size_t i) const;
void setIsReverse(bool flag);
bool isReverse() const;
PathPoint const offsetPoint(PathPoint const & pp, double offset);
PivotPoint findPivotPoint(PathPoint const & pp, double advance, double kern);
PathPoint const front() const;
};
}

View file

@ -6,17 +6,10 @@
namespace graphics
{
PathPoint::PathPoint(int i, ang::AngleD const & segAngle, m2::PointD const & pt)
: m_i(i),
m_segAngle(segAngle),
m_pt(pt)
{}
PivotPoint::PivotPoint(ang::AngleD const & angle, PathPoint const & pp)
: m_angle(angle), m_pp(pp)
{}
TextPath::TextPath() : m_reverse(false), m_fullLength(0), m_pathOffset(0)
TextPath::TextPath()
: m_pv(),
m_fullLength(0),
m_pathOffset(0)
{}
TextPath::TextPath(TextPath const & src, math::Matrix<double, 3, 3> const & m)
@ -28,21 +21,19 @@ namespace graphics
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)
{
m_reverse = false;
checkReverse();
}
else
m_reverse = src.m_reverse;
setIsReverse(src.isReverse());
}
TextPath::TextPath(m2::PointD const * arr, size_t sz, double fullLength, double pathOffset)
: m_reverse(false),
m_fullLength(fullLength),
: m_fullLength(fullLength),
m_pathOffset(pathOffset)
{
ASSERT ( sz > 1, () );
@ -50,9 +41,21 @@ namespace graphics
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):
@ -63,6 +66,7 @@ namespace graphics
*/
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
@ -75,8 +79,10 @@ namespace graphics
if (m_pathOffset < 0.0)
m_pathOffset = 0.0;
m_reverse = true;
setIsReverse(true);
}
else
setIsReverse(false);
}
double TextPath::fullLength() const
@ -89,104 +95,34 @@ namespace graphics
return m_pathOffset;
}
size_t TextPath::size() const { return m_arr.size(); }
size_t TextPath::size() const
{
return m_pv.size();
}
m2::PointD TextPath::get(size_t i) const
{
ASSERT ( i < m_arr.size(), ("Index out of range") );
return m_arr[m_reverse ? m_arr.size() - i - 1 : i];
return m_pv.get(i);
}
m2::PointD TextPath::operator[](size_t i) const { return get(i); }
m2::PointD TextPath::operator[](size_t i) const
{
return get(i);
}
PathPoint const TextPath::offsetPoint(PathPoint const & pp, double offset)
{
PathPoint res = pp;
if (res.m_i == -1)
return res;
if (offset == 0)
return pp;
bool found = false;
for (size_t i = res.m_i; i < size() - 1; ++i)
{
double l = res.m_pt.Length(get(i + 1));
if (offset <= l)
{
if (i != res.m_i)
res.m_segAngle = ang::AngleD(ang::AngleTo(get(i), get(i + 1)));
res.m_pt = res.m_pt.Move(offset, res.m_segAngle.sin(), res.m_segAngle.cos());
res.m_i = i;
found = true;
break;
}
else
{
offset -= l;
res.m_pt = get(i + 1);
}
}
if (!found)
res.m_i = -1;
return res;
return m_pv.offsetPoint(pp, offset);
}
PivotPoint TextPath::findPivotPoint(PathPoint const & pp, GlyphMetrics const & sym, double kern)
{
PathPoint startPt = offsetPoint(pp, kern);
return m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width / 2.0, kern);
}
PivotPoint res;
if (startPt.m_i == -1)
return res;
m2::PointD pt1 = startPt.m_pt;
double angle = 0;
double advance = sym.m_xOffset + sym.m_width / 2.0;
int j = startPt.m_i;
while (advance > 0)
{
if (j + 1 == size())
return res;
double l = get(j + 1).Length(pt1);
double segAngle = j == startPt.m_i ? startPt.m_segAngle.val() : ang::AngleTo(get(j), get(j + 1));
angle += segAngle;
if (l < advance)
{
advance -= l;
pt1 = get(j + 1);
++j;
}
else
{
ang::AngleD a(segAngle);
res.m_pp.m_i = j;
res.m_pp.m_pt = pt1.Move(advance, a.sin(), a.cos());
advance = 0;
angle /= (res.m_pp.m_i - startPt.m_i + 1);
res.m_angle = ang::AngleD(angle);
res.m_pp.m_segAngle = a;
break;
}
}
return res;
PathPoint const TextPath::front() const
{
return m_pv.front();
}
}

View file

@ -1,35 +1,20 @@
#pragma once
#include "../geometry/point2d.hpp"
#include "../geometry/angles.hpp"
#include "../base/matrix.hpp"
#include "../base/buffer_vector.hpp"
#include "glyph_cache.hpp"
#include "path_view.hpp"
namespace graphics
{
struct PathPoint
{
int m_i; //< segment number
ang::AngleD m_segAngle;
m2::PointD m_pt; //< point on segment
PathPoint(int i = -1,
ang::AngleD const & segAngle = ang::AngleD(),
m2::PointD const & pt = m2::PointD());
};
struct PivotPoint
{
ang::AngleD m_angle;
PathPoint m_pp;
PivotPoint(ang::AngleD const & angle = ang::AngleD(), PathPoint const & pp = PathPoint());
};
class TextPath
{
private:
buffer_vector<m2::PointD, 8> m_arr;
bool m_reverse;
PathView m_pv;
double m_fullLength;
double m_pathOffset;
@ -49,8 +34,12 @@ namespace graphics
double fullLength() const;
double pathOffset() const;
PathPoint const offsetPoint(PathPoint const & pp, double offset);
void setIsReverse(bool flag);
bool isReverse() const;
PathPoint const offsetPoint(PathPoint const & pp, double offset);
PivotPoint findPivotPoint(PathPoint const & pp, GlyphMetrics const & sym, double kern);
PathPoint const front() const;
};
}