tvg_saver: optimize saving data.
authorHermet Park <chuneon.park@samsung.com>
Tue, 10 Aug 2021 02:54:24 +0000 (11:54 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 13 Aug 2021 05:21:50 +0000 (14:21 +0900)
This optimizes binary size by skipping the scene if it has the only child.

though the reduced size is too trivial size (avg 0.4% as far as I checked our example svgs),
we can reduce the loading job & runtime memory as well.

src/examples/images/test.tvg
src/lib/tvgPaint.h
src/lib/tvgPictureImpl.h
src/lib/tvgSceneImpl.h
src/savers/tvg/tvgTvgSaver.cpp
src/savers/tvg/tvgTvgSaver.h

index 56cc056..873daee 100644 (file)
Binary files a/src/examples/images/test.tvg and b/src/examples/images/test.tvg differ
index b15ab17..4700413 100644 (file)
@@ -32,6 +32,7 @@ namespace tvg
         virtual ~Iterator() {}
         virtual const Paint* next() = 0;
         virtual uint32_t count() = 0;
+        virtual void begin() = 0;
     };
 
     struct StrategyMethod
index 12352fd..dbb8916 100644 (file)
 struct PictureIterator : Iterator
 {
     Paint* paint = nullptr;
+    Paint* ptr = nullptr;
 
     PictureIterator(Paint* p) : paint(p) {}
 
     const Paint* next() override
     {
-        auto ret = paint;
-        paint = nullptr;
-        return ret;
+        if (!ptr) ptr = paint;
+        else ptr = nullptr;
+        return ptr;
     }
 
     uint32_t count() override
@@ -48,6 +49,11 @@ struct PictureIterator : Iterator
         if (paint) return 1;
         else return 0;
     }
+
+    void begin() override
+    {
+        ptr = nullptr;
+    }
 };
 
 
index 0a2292b..f935487 100644 (file)
@@ -48,6 +48,11 @@ struct SceneIterator : Iterator
     {
         return paints->count;
     }
+
+    void begin() override
+    {
+        idx = 0;
+    }
 };
 
 struct Scene::Impl
index 32ac23f..db9e09f 100644 (file)
@@ -200,12 +200,59 @@ TvgBinCounter TvgSaver::serializePaint(const Paint* paint)
 }
 
 
+/* Propagate parents properties to the child so that we can skip saving the parent. */
+TvgBinCounter TvgSaver::serializeChild(const Paint* parent, const Paint* child, const Matrix* transform)
+{
+    const Paint* compTarget = nullptr;
+    auto compMethod = parent->composite(&compTarget);
+
+    //If the parent & the only child have composition, we can't skip the parent....
+    if (compMethod != CompositeMethod::None && child->composite(nullptr) != CompositeMethod::None) return 0;
+
+    //propagate opacity
+    uint32_t opacity = parent->opacity();
+
+    if (opacity < 255) {
+        uint32_t tmp = (child->opacity() * opacity);
+        if (tmp > 0) tmp /= 255;
+        const_cast<Paint*>(child)->opacity(tmp);
+    }
+
+    //propagate composition
+    if (compTarget) const_cast<Paint*>(child)->composite(unique_ptr<Paint>(compTarget->duplicate()), compMethod);
+
+    return serialize(child, transform);
+}
+
+
 TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* transform)
 {
+    auto it = this->iterator(scene);
+    if (it->count() == 0) return 0;
+
+    //Case - Only Child: Skip saving this scene.
+    if (it->count() == 1) {
+        auto cnt = serializeChild(scene, it->next(), transform);
+        if (cnt > 0) {
+            delete(it);
+            return cnt;
+        }
+    }
+
+    it->begin();
+
+    //Case - Delegator Scene: This scene is just a delegator, we can skip this:
+    if (scene->composite(nullptr) == CompositeMethod::None && scene->opacity() == 255) {
+        return serializeChildren(it, transform);
+    }
+
+    //Case - Serialize Scene & its children
     writeTag(TVG_TAG_CLASS_SCENE);
     reserveCount();
 
-    auto cnt = serializeChildren(scene, transform) + serializePaint(scene);
+    auto cnt = serializeChildren(it, transform) + serializePaint(scene);
+
+    delete(it);
 
     writeReservedCount(cnt);
 
@@ -367,34 +414,40 @@ TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* transfo
 }
 
 
+/* Picture has either a vector scene or a bitmap. */
 TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* transform)
 {
+    //Case - Vector Scene: Only child, Skip to save Picture...
+    auto it = this->iterator(picture);
+    if (it->count() == 1) {
+        auto cnt = serializeChild(picture, it->next(), transform);
+        delete(it);
+        return cnt;
+    }
+    delete(it);
+
+    //Case - Bitmap Image:
+    uint32_t w, h;
+    auto pixels = picture->data(&w, &h);
+    if (!pixels) return 0;
+
     writeTag(TVG_TAG_CLASS_PICTURE);
     reserveCount();
 
     TvgBinCounter cnt = 0;
+    TvgBinCounter sizeCnt = SIZE(w);
+    TvgBinCounter imgSize = w * h * SIZE(pixels[0]);
 
-    //Bitmap Image
-    uint32_t w, h;
-
-    if (auto pixels = picture->data(&w, &h)) {
-        TvgBinCounter sizeCnt = SIZE(w);
-        TvgBinCounter imgSize = w * h * SIZE(pixels[0]);
+    writeTag(TVG_TAG_PICTURE_RAW_IMAGE);
+    writeCount(2 * sizeCnt + imgSize);
 
-        writeTag(TVG_TAG_PICTURE_RAW_IMAGE);
-        writeCount(2 * sizeCnt + imgSize);
+    cnt += writeData(&w, sizeCnt);
+    cnt += writeData(&h, sizeCnt);
+    cnt += writeData(pixels, imgSize);
+    cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
 
-        cnt += writeData(&w, sizeCnt);
-        cnt += writeData(&h, sizeCnt);
-        cnt += writeData(pixels, imgSize);
-        cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
-
-        //Only Bitmap picture needs the transform info.
-        cnt += writeTransform(transform);
-    //Vector Image
-    } else {
-        cnt += serializeChildren(picture, transform);
-    }
+    //Bitmap picture needs the transform info.
+    cnt += writeTransform(transform);
 
     cnt += serializePaint(picture);
 
@@ -420,17 +473,13 @@ TvgBinCounter TvgSaver::serializeComposite(const Paint* cmpTarget, CompositeMeth
 }
 
 
-TvgBinCounter TvgSaver::serializeChildren(const Paint* paint, const Matrix* transform)
+TvgBinCounter TvgSaver::serializeChildren(Iterator* it, const Matrix* transform)
 {
-    auto it = this->iterator(paint);
-    if (!it) return 0;
-
     TvgBinCounter cnt = 0;
 
-    while (auto p = it->next())
+    while (auto p = it->next()) {
         cnt += serialize(p, transform);
-
-    delete(it);
+    }
 
     return cnt;
 }
index b2ad4fa..9076173 100644 (file)
@@ -58,7 +58,8 @@ private:
     TvgBinCounter serializeStroke(const Shape* shape);
     TvgBinCounter serializePath(const Shape* shape, const Matrix* transform);
     TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod);
-    TvgBinCounter serializeChildren(const Paint* paint, const Matrix* transform);
+    TvgBinCounter serializeChildren(Iterator* it, const Matrix* transform);
+    TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* transform);
 
 public:
     ~TvgSaver();