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"vpathmesure.h"
|
||||||
|
#include"vbezier.h"
|
||||||
|
|
||||||
V_BEGIN_NAMESPACE
|
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
|
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();
|
||||||
VPathMesure(const VPath *path, bool foceClose);
|
VPathMesure(const VPath *path, bool foceClose);
|
||||||
int getLength() const;
|
int getLength() const;
|
||||||
|
void setPath(const VPath &path);
|
||||||
|
VPath getPath();
|
||||||
|
void setStart(float pos);
|
||||||
|
void setEnd(float pos);
|
||||||
private:
|
private:
|
||||||
VPathMesureData *d;
|
VPathMesureData *d;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user