mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 05:51:42 +00:00
vector: implement vpathmesure
Change-Id: I562df481e72b4e356821b1a44b7749c29ea0b1ca
This commit is contained in:
parent
f2bf8eabc9
commit
a411696b12
@ -1,10 +1,308 @@
|
||||
#include"vpathmesure.h"
|
||||
#include"vbezier.h"
|
||||
|
||||
V_BEGIN_NAMESPACE
|
||||
|
||||
class VPathMesureData
|
||||
struct VPathMesureData
|
||||
{
|
||||
VPath *path;
|
||||
void setPath(const VPath &path) { mPath = path; }
|
||||
VPath& getPath() { return mPath; }
|
||||
VPath mPath;
|
||||
};
|
||||
|
||||
V_END_NAMESPACE
|
||||
|
||||
static const struct VPathMesureData shared_empty = {VPath()};
|
||||
|
||||
VPathMesure::~VPathMesure()
|
||||
{
|
||||
}
|
||||
|
||||
VPathMesure::VPathMesure()
|
||||
: d(const_cast<VPathMesureData*>(&shared_empty))
|
||||
{
|
||||
}
|
||||
|
||||
VPathMesure::VPathMesure(const VPath *p, bool foceClose)
|
||||
{
|
||||
}
|
||||
|
||||
void VPathMesure::setStart(float pos)
|
||||
{
|
||||
VPath &path = d->getPath();
|
||||
const std::vector<VPath::Element> &elm = path.elements();
|
||||
const std::vector<VPointF> &pts = path.points();
|
||||
std::vector<float> len;
|
||||
|
||||
std::vector<VPath::Element> elm_copy;
|
||||
|
||||
int i = 0, idx = 0;
|
||||
float totlen = 0.0;
|
||||
float startlen = 0.0;
|
||||
bool cut = false;
|
||||
|
||||
for (auto e : elm) {
|
||||
elm_copy.push_back(e);
|
||||
switch(e) {
|
||||
case VPath::Element::MoveTo:
|
||||
break;
|
||||
case VPath::Element::LineTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
|
||||
VBezier b = VBezier::fromPoints(p0, p0, p, p);
|
||||
totlen += b.length();
|
||||
len.push_back(b.length());
|
||||
break;
|
||||
}
|
||||
case VPath::Element::CubicTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
VPointF p1 = pts[i++];
|
||||
VPointF p2 = pts[i++];
|
||||
|
||||
VBezier b = VBezier::fromPoints(p0, p, p1, p2);
|
||||
totlen += b.length();
|
||||
len.push_back(b.length());
|
||||
|
||||
break;
|
||||
}
|
||||
case VPath::Element::Close:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
startlen = totlen * (pos / 100);
|
||||
i = 0;
|
||||
path.reset();
|
||||
|
||||
for (auto e : elm_copy) {
|
||||
switch(e) {
|
||||
case VPath::Element::MoveTo:
|
||||
{
|
||||
VPointF p = pts[i++];
|
||||
path.moveTo(p.x(), p.y());
|
||||
break;
|
||||
}
|
||||
case VPath::Element::LineTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
if (len.at(idx) < startlen)
|
||||
{
|
||||
startlen -= len.at(idx);
|
||||
}
|
||||
else if (len.at(idx) == startlen)
|
||||
{
|
||||
path.moveTo(p.x(), p.y());
|
||||
cut = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VBezier b, bleft;
|
||||
float ratio = (startlen/len.at(idx));
|
||||
b = VBezier::fromPoints(p0, p0, p, p);
|
||||
b.parameterSplitLeft(ratio, &bleft);
|
||||
|
||||
path.moveTo(b.pt1().x(), b.pt1().y());
|
||||
path.lineTo(b.pt4().x(), b.pt4().y());
|
||||
cut = true;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.lineTo(p.x(), p.y());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VPath::Element::CubicTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
VPointF p1 = pts[i++];
|
||||
VPointF p2 = pts[i++];
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
if (len.at(idx) < startlen)
|
||||
{
|
||||
startlen -= len.at(idx);
|
||||
}
|
||||
else if (len.at(idx) == startlen)
|
||||
{
|
||||
path.moveTo(p2.x(), p2.y());
|
||||
cut = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VBezier b, bleft;
|
||||
float ratio = (startlen/len.at(idx));
|
||||
b = VBezier::fromPoints(p0, p, p1, p2);
|
||||
b.parameterSplitLeft(ratio, &bleft);
|
||||
|
||||
path.moveTo(b.pt1().x(), b.pt1().y());
|
||||
path.cubicTo(b.pt2().x(), b.pt2().y(),
|
||||
b.pt3().x(), b.pt3().y(),
|
||||
b.pt4().x(), b.pt4().y());
|
||||
cut = true;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VPath::Element::Close:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VPathMesure::setEnd(float pos)
|
||||
{
|
||||
VPath &path = d->getPath();
|
||||
const std::vector<VPath::Element> &elm = path.elements();
|
||||
const std::vector<VPointF> &pts = path.points();
|
||||
std::vector<float> len;
|
||||
|
||||
std::vector<VPath::Element> elm_copy;
|
||||
|
||||
int i = 0, idx = 0;
|
||||
float totlen = 0.0;
|
||||
float endlen = 0.0;
|
||||
bool cut = false;
|
||||
|
||||
for (auto e : elm) {
|
||||
elm_copy.push_back(e);
|
||||
switch(e) {
|
||||
case VPath::Element::MoveTo:
|
||||
break;
|
||||
case VPath::Element::LineTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
|
||||
VBezier b = VBezier::fromPoints(p0, p0, p, p);
|
||||
totlen += b.length();
|
||||
len.push_back(b.length());
|
||||
break;
|
||||
}
|
||||
case VPath::Element::CubicTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
VPointF p1 = pts[i++];
|
||||
VPointF p2 = pts[i++];
|
||||
|
||||
VBezier b = VBezier::fromPoints(p0, p, p1, p2);
|
||||
totlen += b.length();
|
||||
len.push_back(b.length());
|
||||
|
||||
break;
|
||||
}
|
||||
case VPath::Element::Close:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
endlen = totlen * (pos / 100);
|
||||
i = 0;
|
||||
path.reset();
|
||||
|
||||
for (auto e : elm_copy) {
|
||||
switch(e) {
|
||||
case VPath::Element::MoveTo:
|
||||
{
|
||||
VPointF p = pts[i++];
|
||||
path.moveTo(p.x(), p.y());
|
||||
break;
|
||||
}
|
||||
case VPath::Element::LineTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
if (len.at(idx) < endlen)
|
||||
{
|
||||
path.lineTo(p.x(), p.y());
|
||||
endlen -= len.at(idx);
|
||||
}
|
||||
else if (len.at(idx) == endlen)
|
||||
{
|
||||
path.lineTo(p.x(), p.y());
|
||||
cut = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VBezier b, bleft;
|
||||
float ratio = (endlen/len.at(idx));
|
||||
b = VBezier::fromPoints(p0, p0, p, p);
|
||||
b.parameterSplitLeft(ratio, &bleft);
|
||||
|
||||
path.lineTo(bleft.pt4().x(), bleft.pt4().y());
|
||||
cut = true;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VPath::Element::CubicTo:
|
||||
{
|
||||
VPointF p0 = pts[i - 1];
|
||||
VPointF p = pts[i++];
|
||||
VPointF p1 = pts[i++];
|
||||
VPointF p2 = pts[i++];
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
if (len.at(idx) < endlen)
|
||||
{
|
||||
path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
|
||||
endlen -= len.at(idx);
|
||||
}
|
||||
else if (len.at(idx) == endlen)
|
||||
{
|
||||
path.cubicTo(p.x(), p.y(), p1.x(), p1.y(), p2.x(), p2.y());
|
||||
cut = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
VBezier b, bleft;
|
||||
float ratio = (endlen/len.at(idx));
|
||||
b = VBezier::fromPoints(p0, p, p1, p2);
|
||||
b.parameterSplitLeft(ratio, &bleft);
|
||||
|
||||
path.cubicTo(bleft.pt2().x(), bleft.pt2().y(),
|
||||
bleft.pt3().x(), bleft.pt3().y(),
|
||||
bleft.pt4().x(), bleft.pt4().y());
|
||||
cut = true;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VPath::Element::Close:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VPathMesure::setPath(const VPath &path)
|
||||
{
|
||||
d->setPath(path);
|
||||
}
|
||||
|
||||
VPath VPathMesure::getPath()
|
||||
{
|
||||
return d->getPath();
|
||||
}
|
||||
|
||||
@ -13,6 +13,10 @@ public:
|
||||
VPathMesure();
|
||||
VPathMesure(const VPath *path, bool foceClose);
|
||||
int getLength() const;
|
||||
void setPath(const VPath &path);
|
||||
VPath getPath();
|
||||
void setStart(float pos);
|
||||
void setEnd(float pos);
|
||||
private:
|
||||
VPathMesureData *d;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user