lottie/vector: clean up vpathmesure and use vdasher in it

Change-Id: Id5367613f89487f4a764010ef155d19f78e2372a
This commit is contained in:
Jaeun Choi 2018-07-27 17:42:16 +09:00
parent 86d179f9b1
commit c607e87f97
3 changed files with 22 additions and 372 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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