}
/*
- * LOTPathDataItem uses 3 path objects for path object reuse.
+ * LOTPathDataItem uses 2 path objects for path object reuse.
* mLocalPath - keeps track of the local path of the item before
* applying path operation and transformation.
* mTemp - keeps a referece to the mLocalPath and can be updated by the
* path operation objects(trim, merge path),
- * mFinalPath - it takes a deep copy of the intermediate path(mTemp) each time
- * when the path is dirty(so if path changes every frame we don't realloc just
- * copy to the final path). NOTE: As path objects are COW objects we have to be
+ * We update the DirtyPath flag if the path needs to be updated again
+ * beacuse of local path or matrix or some path operation has changed which
+ * affects the final path.
+ * The PaintObject queries the dirty flag to check if it needs to compute the
+ * final path again and calls finalPath() api to do the same.
+ * finalPath() api passes a result Object so that we keep only one copy of
+ * the path object in the paintItem (for memory efficiency).
+ * NOTE: As path objects are COW objects we have to be
* carefull about the refcount so that we don't generate deep copy while
* modifying the path objects.
*/
void LOTPathDataItem::update(int frameNo, const VMatrix &, float,
const DirtyFlag &flag)
{
- mPathChanged = false;
+ mDirtyPath = false;
// 1. update the local path if needed
if (hasChanged(frameNo)) {
mTemp = VPath();
updatePath(mLocalPath, frameNo);
- mPathChanged = true;
- mNeedUpdate = true;
+ mDirtyPath = true;
}
// 2. keep a reference path in temp in case there is some
// path operation like trim which will update the path.
// we don't want to update the local path.
mTemp = mLocalPath;
- // 3. compute the final path with parentMatrix
- if ((flag & DirtyFlagBit::Matrix) || mPathChanged) {
- mPathChanged = true;
+ // 3. mark the path dirty if matrix has changed.
+ if (flag & DirtyFlagBit::Matrix) {
+ mDirtyPath = true;
}
}
-const VPath &LOTPathDataItem::finalPath()
+void LOTPathDataItem::finalPath(VPath& result)
{
- if (mPathChanged || mNeedUpdate) {
- mFinalPath.clone(mTemp);
- mFinalPath.transform(
- static_cast<LOTContentGroupItem *>(parent())->matrix());
- mNeedUpdate = false;
- }
- return mFinalPath;
+ result.addPath(mTemp, static_cast<LOTContentGroupItem *>(parent())->matrix());
}
+
LOTRectItem::LOTRectItem(LOTRectData *data)
: LOTPathDataItem(data->isStatic()), mData(data)
{
}
}
- if (dirty || mPath.empty()) {
+ if (dirty) {
mPath.reset();
-
- for (auto &i : mPathItems) {
- mPath.addPath(i->finalPath());
+ for (const auto &i : mPathItems) {
+ i->finalPath(mPath);
}
mDrawable.setPath(mPath);
} else {
LOTPathDataItem(bool staticPath): mStaticPath(staticPath){}
void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
ContentType type() const final {return ContentType::Path;}
- bool dirty() const {return mPathChanged;}
+ bool dirty() const {return mDirtyPath;}
const VPath &localPath() const {return mTemp;}
- const VPath &finalPath();
- void updatePath(const VPath &path) {mTemp = path; mPathChanged = true; mNeedUpdate = true;}
+ void finalPath(VPath& result);
+ void updatePath(const VPath &path) {mTemp = path; mDirtyPath = true;}
bool staticPath() const { return mStaticPath; }
void setParent(LOTContentGroupItem *parent) {mParent = parent;}
LOTContentGroupItem *parent() const {return mParent;}
LOTContentGroupItem *mParent{nullptr};
VPath mLocalPath;
VPath mTemp;
- VPath mFinalPath;
int mFrameNo{-1};
- bool mPathChanged{true};
- bool mNeedUpdate{true};
+ bool mDirtyPath{true};
bool mStaticPath;
};
close();
}
-void VPath::VPathData::addPath(const VPathData &path)
+void VPath::VPathData::addPath(const VPathData &path, const VMatrix *m)
{
size_t segment = path.segments();
if (m_elements.capacity() < m_elements.size() + path.m_elements.size())
m_elements.reserve(m_elements.size() + path.m_elements.size());
- std::copy(path.m_points.begin(), path.m_points.end(),
- back_inserter(m_points));
+ if (m) {
+ for (const auto &i : path.m_points) {
+ m_points.push_back(m->map(i));
+ }
+ } else {
+ std::copy(path.m_points.begin(), path.m_points.end(),
+ back_inserter(m_points));
+ }
+
std::copy(path.m_elements.begin(), path.m_elements.end(),
back_inserter(m_elements));
float startAngle, float cx, float cy,
VPath::Direction dir = Direction::CW);
void addPath(const VPath &path);
+ void addPath(const VPath &path, const VMatrix &m);
void transform(const VMatrix &m);
float length() const;
const std::vector<VPath::Element> &elements() const;
void addPolygon(float points, float radius, float roundness,
float startAngle, float cx, float cy,
VPath::Direction dir = Direction::CW);
- void addPath(const VPathData &path);
+ void addPath(const VPathData &path, const VMatrix *m = nullptr);
void clone(const VPath::VPathData &o) { *this = o;}
const std::vector<VPath::Element> &elements() const
{
}
}
+inline void VPath::addPath(const VPath &path, const VMatrix &m)
+{
+ if (path.empty()) return;
+
+ d.write().addPath(path.d.read(), &m);
+}
+
inline const std::vector<VPath::Element> &VPath::elements() const
{
return d->elements();