mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-07 14:53:35 +00:00
lottie/vector: clean up vpathmesure and use vdasher in it
Change-Id: Id5367613f89487f4a764010ef155d19f78e2372a
This commit is contained in:
parent
86d179f9b1
commit
c607e87f97
@ -680,14 +680,11 @@ void LOTPathDataItem::update(int frameNo, const VMatrix &parentMatrix, float par
|
||||
{
|
||||
//TODO apply more than one trim path if necessary
|
||||
VPathMesure pm;
|
||||
float s = mTrimNodeRefs.front()->getStart(frameNo);
|
||||
float e = mTrimNodeRefs.front()->getEnd(frameNo);
|
||||
|
||||
pm.setPath(mLocalPath);
|
||||
pm.setStart(s);
|
||||
pm.setEnd(e);
|
||||
tempPath = pm.getPath();
|
||||
float s = mTrimNodeRefs.front()->getStart(frameNo) / 100.0f;
|
||||
float e = mTrimNodeRefs.front()->getEnd(frameNo) / 100.0f;
|
||||
|
||||
pm.setOffset(s, e);
|
||||
tempPath = pm.trim(tempPath);
|
||||
mPathChanged = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,364 +1,29 @@
|
||||
#include"vpathmesure.h"
|
||||
#include"vbezier.h"
|
||||
#include"vdasher.h"
|
||||
|
||||
V_BEGIN_NAMESPACE
|
||||
|
||||
struct VPathMesureData
|
||||
void VPathMesure::setOffset(float sp, float ep)
|
||||
{
|
||||
VPathMesureData():ref(-1){}
|
||||
void setPath(const VPath &path) { mPath = path; }
|
||||
VPath& getPath() { return mPath; }
|
||||
VPath mPath;
|
||||
RefCount ref;
|
||||
};
|
||||
|
||||
static const struct VPathMesureData shared_empty;
|
||||
|
||||
inline void VPathMesure::cleanUp(VPathMesureData *d)
|
||||
{
|
||||
delete d;
|
||||
startOffset = sp;
|
||||
endOffset = ep;
|
||||
}
|
||||
|
||||
void VPathMesure::detach()
|
||||
VPath VPathMesure::trim(const VPath &path)
|
||||
{
|
||||
if (d->ref.isShared())
|
||||
*this = copy();
|
||||
}
|
||||
if (vCompare(startOffset, 0.0f) && (vCompare(endOffset, 1.0f))) return path;
|
||||
|
||||
VPathMesure VPathMesure::copy() const
|
||||
{
|
||||
VPathMesure other;
|
||||
float len = path.length();
|
||||
float len1 = len;
|
||||
float sg = len * startOffset;
|
||||
float eg = len * (1.0f - endOffset);
|
||||
len = len - (sg + eg);
|
||||
|
||||
other.d = new VPathMesureData;
|
||||
other.d->mPath = d->mPath;
|
||||
other.d->ref.setOwned();
|
||||
return other;
|
||||
}
|
||||
float array[5] = { 0.0f, sg, len, 1000, 0.0f };
|
||||
VDasher dasher(array, 5);
|
||||
|
||||
VPathMesure::~VPathMesure()
|
||||
{
|
||||
if (!d->ref.deref())
|
||||
cleanUp(d);
|
||||
}
|
||||
|
||||
VPathMesure::VPathMesure()
|
||||
: d(const_cast<VPathMesureData*>(&shared_empty))
|
||||
{
|
||||
}
|
||||
|
||||
VPathMesure::VPathMesure(const VPathMesure &other)
|
||||
{
|
||||
d = other.d;
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
VPathMesure::VPathMesure(VPathMesure &&other): d(other.d)
|
||||
{
|
||||
other.d = const_cast<VPathMesureData*>(&shared_empty);
|
||||
}
|
||||
|
||||
VPathMesure &VPathMesure::operator=(const VPathMesure &other)
|
||||
{
|
||||
other.d->ref.ref();
|
||||
if (!d->ref.deref())
|
||||
cleanUp(d);
|
||||
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline VPathMesure &VPathMesure::operator=(VPathMesure &&other)
|
||||
{
|
||||
if (!d->ref.deref())
|
||||
cleanUp(d);
|
||||
d = other.d;
|
||||
other.d = const_cast<VPathMesureData*>(&shared_empty);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void VPathMesure::setStart(float pos)
|
||||
{
|
||||
detach();
|
||||
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:
|
||||
i++;
|
||||
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)
|
||||
{
|
||||
detach();
|
||||
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:
|
||||
i++;
|
||||
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)
|
||||
{
|
||||
detach();
|
||||
d->setPath(path);
|
||||
}
|
||||
|
||||
VPath VPathMesure::getPath()
|
||||
{
|
||||
return d->getPath();
|
||||
return dasher.dashed(path);
|
||||
}
|
||||
|
||||
V_END_NAMESPACE
|
||||
|
||||
@ -5,26 +5,14 @@
|
||||
|
||||
V_BEGIN_NAMESPACE
|
||||
|
||||
class VPathMesureData;
|
||||
class VPathMesure
|
||||
{
|
||||
public:
|
||||
~VPathMesure();
|
||||
VPathMesure();
|
||||
VPathMesure(const VPathMesure &other);
|
||||
VPathMesure(VPathMesure &&other);
|
||||
VPathMesure &operator=(const VPathMesure &);
|
||||
VPathMesure &operator=(VPathMesure &&other);
|
||||
int getLength() const;
|
||||
void setPath(const VPath &path);
|
||||
VPath getPath();
|
||||
void setStart(float pos);
|
||||
void setEnd(float pos);
|
||||
void setOffset(float sp, float ep);
|
||||
VPath trim(const VPath &path);
|
||||
private:
|
||||
VPathMesure copy() const;
|
||||
void detach();
|
||||
void cleanUp(VPathMesureData *x);
|
||||
VPathMesureData *d;
|
||||
float startOffset { 0.0f };
|
||||
float endOffset { 1.0f };
|
||||
};
|
||||
|
||||
V_END_NAMESPACE
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user