mRoot->addChildren(layerData);
std::vector<LOTPathDataItem *> list;
- mRoot->processPathItems(list);
+ mRoot->processPaintItems(list);
- if (layerData->hasPathOperator()) mRoot->processTrimOperation();
+ if (layerData->hasPathOperator()) {
+ list.clear();
+ mRoot->processTrimItems(list);
+ }
}
std::unique_ptr<LOTContentItem>
void LOTShapeLayerItem::updateContent()
{
mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag());
+
+ if (mLayerData->hasPathOperator()) {
+ mRoot->applyTrim();
+ }
}
void LOTShapeLayerItem::renderList(std::vector<VDrawable *> &list)
}
}
+void LOTContentGroupItem::applyTrim()
+{
+ for (auto &i : mContents) {
+ if (auto trim = dynamic_cast<LOTTrimItem *>(i.get())) {
+ trim->update();
+ } else if (auto group = dynamic_cast<LOTContentGroupItem *>(i.get())) {
+ group->applyTrim();
+ }
+ }
+}
+
void LOTContentGroupItem::renderList(std::vector<VDrawable *> &list)
{
for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
}
}
-void LOTContentGroupItem::processPathItems(
+void LOTContentGroupItem::processPaintItems(
std::vector<LOTPathDataItem *> &list)
{
int curOpCount = list.size();
} else if (auto groupNode =
dynamic_cast<LOTContentGroupItem *>(i.get())) {
// update the groups node with current list
- groupNode->processPathItems(list);
+ groupNode->processPaintItems(list);
}
}
}
-void LOTContentGroupItem::processTrimOperation()
-{
- std::vector<LOTTrimItem *> list;
- trimOperationHelper(list);
-}
-
-void LOTContentGroupItem::trimOperationHelper(std::vector<LOTTrimItem *> &list)
+void LOTContentGroupItem::processTrimItems(
+ std::vector<LOTPathDataItem *> &list)
{
int curOpCount = list.size();
- for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
- auto child = (*i).get();
- if (auto pathNode = dynamic_cast<LOTPathDataItem *>(child)) {
- // the node is a path data node add the trim operation list to it.
- pathNode->addTrimOperation(list);
- } else if (auto trimNode = dynamic_cast<LOTTrimItem *>(child)) {
- // add it to the trim operation list
- list.push_back(trimNode);
+ for (auto &i : mContents) {
+ if (auto pathNode = dynamic_cast<LOTPathDataItem *>(i.get())) {
+ // add it to the list
+ list.push_back(pathNode);
+ } else if (auto trimNode = dynamic_cast<LOTTrimItem *>(i.get())) {
+ // the node is a paint data node update the path list of the paint item.
+ trimNode->addPathItems(list, curOpCount);
} else if (auto groupNode =
- dynamic_cast<LOTContentGroupItem *>(child)) {
+ dynamic_cast<LOTContentGroupItem *>(i.get())) {
// update the groups node with current list
- groupNode->trimOperationHelper(list);
+ groupNode->processTrimItems(list);
}
}
- list.erase(list.begin() + curOpCount, list.end());
-}
-
-void LOTPathDataItem::addTrimOperation(std::vector<LOTTrimItem *> &list)
-{
- for (auto trimItem : list) {
- mTrimNodeRefs.push_back(trimItem);
- }
}
void LOTPathDataItem::update(int frameNo, const VMatrix &parentMatrix,
float, const DirtyFlag &flag)
{
- VPath tempPath;
-
mPathChanged = false;
// 1. update the local path if needed
mPathChanged = true;
}
- tempPath = mLocalPath;
-
- // 2. apply path operation if needed
- if (mTrimNodeRefs.size() > 0) {
- // TODO apply more than one trim path if necessary
- VPathMesure pm;
- 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;
- }
+ mTemp = mLocalPath;
// 3. compute the final path with parentMatrix
if ((flag & DirtyFlagBit::Matrix) || mPathChanged) {
- mFinalPath.clone(tempPath);
- mFinalPath.transform(parentMatrix);
+ mMatrix = parentMatrix;
mPathChanged = true;
}
}
+const VPath & LOTPathDataItem::finalPath()
+{
+ if (mPathChanged) {
+ mFinalPath.clone(mTemp);
+ mFinalPath.transform(mMatrix);
+ mPathChanged = false;
+ }
+ return mFinalPath;
+}
LOTRectItem::LOTRectItem(LOTRectData *data)
: LOTPathDataItem(data->isStatic()), mData(data)
{
mPath.reset();
for (auto &i : mPathItems) {
- mPath.addPath(i->path());
+ mPath.addPath(i->finalPath());
}
mDrawable->setPath(mPath);
} else {
LOTTrimItem::LOTTrimItem(LOTTrimData *data) : mData(data) {}
-void LOTTrimItem::update(int /*frameNo*/, const VMatrix &/*parentMatrix*/,
+void LOTTrimItem::update(int frameNo, const VMatrix &/*parentMatrix*/,
float /*parentAlpha*/, const DirtyFlag &/*flag*/)
{
+ mDirty = false;
+
+ if (mCache.mFrameNo == frameNo) return;
+
+ float start = mData->start(frameNo);
+ float end = mData->end(frameNo);
+ float offset = mData->offset(frameNo);
+
+ if (!(vCompare(mCache.mStart, start) && vCompare(mCache.mEnd, end) &&
+ vCompare(mCache.mOffset, offset))) {
+ mDirty = true;
+ mCache.mStart = start;
+ mCache.mEnd = end;
+ mCache.mOffset = offset;
+ }
+ mCache.mFrameNo = frameNo;
}
+void LOTTrimItem::update()
+{
+ // when both path and trim are not dirty
+ if (!(mDirty || pathDirty())) return;
+
+ //@TODO take the offset and trim type into account.
+ for (auto &i : mPathItems) {
+ VPathMesure pm;
+ pm.setOffset(mCache.mStart, mCache.mEnd);
+ i->updatePath(pm.trim(i->localPath()));
+ }
+}
+
+
+void LOTTrimItem::addPathItems(std::vector<LOTPathDataItem *> &list, int startOffset)
+{
+ std::copy(list.begin() + startOffset, list.end(), back_inserter(mPathItems));
+}
+
+
LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mData(data) {}
void LOTRepeaterItem::update(int /*frameNo*/, const VMatrix &/*parentMatrix*/,
LOTContentGroupItem(LOTShapeGroupData *data);
void addChildren(LOTGroupData *data);
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- void processTrimOperation();
- void processPathItems(std::vector<LOTPathDataItem *> &list);
+ void applyTrim();
+ void processTrimItems(std::vector<LOTPathDataItem *> &list);
+ void processPaintItems(std::vector<LOTPathDataItem *> &list);
void renderList(std::vector<VDrawable *> &list) final;
private:
- void trimOperationHelper(std::vector<LOTTrimItem *> &list);
LOTShapeGroupData *mData;
std::vector<std::unique_ptr<LOTContentItem>> mContents;
};
public:
LOTPathDataItem(bool staticPath):mInit(false), mStaticPath(staticPath){}
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- void addTrimOperation(std::vector<LOTTrimItem *> &list);
bool dirty() const {return mPathChanged;}
- const VPath &path()const {return mFinalPath;}
+ const VPath &localPath() const {return mTemp;}
+ const VPath &finalPath();
+ void updatePath(const VPath &path) {mTemp.clone(path); mPathChanged = true;}
private:
- std::vector<LOTTrimItem *> mTrimNodeRefs;
bool mInit;
bool mStaticPath;
VPath mLocalPath;
+ VPath mTemp;
VPath mFinalPath;
+ VMatrix mMatrix;
bool mPathChanged{true};
protected:
virtual void updatePath(VPath& path, int frameNo) = 0;
public:
LOTTrimItem(LOTTrimData *data);
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
- float getStart(int frameNo) {return mData->mStart.value(frameNo);}
- float getEnd(int frameNo) {return mData->mEnd.value(frameNo);}
+ void update();
+ void addPathItems(std::vector<LOTPathDataItem *> &list, int startOffset);
private:
- LOTTrimData *mData;
+ bool pathDirty() const {
+ for (auto &i : mPathItems) {
+ if (i->dirty())
+ return true;
+ }
+ return false;
+ }
+ struct Cache {
+ int mFrameNo{-1};
+ float mStart{0};
+ float mEnd{0};
+ float mOffset{0};
+ };
+ Cache mCache;
+ std::vector<LOTPathDataItem *> mPathItems;
+ LOTTrimData *mData;
+ bool mDirty{true};
};
class LOTRepeaterItem : public LOTContentItem