mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
tvg_saver: optimize saving data.
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.
This commit is contained in:
parent
2337ea2b01
commit
abebdbe545
6 changed files with 93 additions and 31 deletions
Binary file not shown.
|
@ -32,6 +32,7 @@ namespace tvg
|
|||
virtual ~Iterator() {}
|
||||
virtual const Paint* next() = 0;
|
||||
virtual uint32_t count() = 0;
|
||||
virtual void begin() = 0;
|
||||
};
|
||||
|
||||
struct StrategyMethod
|
||||
|
|
|
@ -33,14 +33,15 @@
|
|||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,11 @@ struct SceneIterator : Iterator
|
|||
{
|
||||
return paints->count;
|
||||
}
|
||||
|
||||
void begin() override
|
||||
{
|
||||
idx = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Scene::Impl
|
||||
|
|
|
@ -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,17 +414,27 @@ 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;
|
||||
|
||||
//Bitmap Image
|
||||
uint32_t w, h;
|
||||
|
||||
if (auto pixels = picture->data(&w, &h)) {
|
||||
TvgBinCounter sizeCnt = SIZE(w);
|
||||
TvgBinCounter imgSize = w * h * SIZE(pixels[0]);
|
||||
|
||||
|
@ -389,12 +446,8 @@ TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* t
|
|||
cnt += writeData(pixels, imgSize);
|
||||
cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter);
|
||||
|
||||
//Only Bitmap picture needs the transform info.
|
||||
//Bitmap picture needs the transform info.
|
||||
cnt += writeTransform(transform);
|
||||
//Vector Image
|
||||
} else {
|
||||
cnt += serializeChildren(picture, 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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue