}
-static void _multiply(Point* pt, const Matrix* transform)
+static void _multiply(Point* pt, const Matrix& transform)
{
- auto tx = pt->x * transform->e11 + pt->y * transform->e12 + transform->e13;
- auto ty = pt->x * transform->e21 + pt->y * transform->e22 + transform->e23;
+ auto tx = pt->x * transform.e11 + pt->y * transform.e12 + transform.e13;
+ auto ty = pt->x * transform.e21 + pt->y * transform.e22 + transform.e23;
pt->x = tx;
pt->y = ty;
}
}
-TvgBinCounter TvgSaver::writeTransform(const Matrix* transform)
+TvgBinCounter TvgSaver::writeTransform(const Matrix& transform)
{
- if (!transform) return 0;
-
- if (fabs(transform->e11 - 1) > FLT_EPSILON || fabs(transform->e12) > FLT_EPSILON || fabs(transform->e13) > FLT_EPSILON ||
- fabs(transform->e21) > FLT_EPSILON || fabs(transform->e22 - 1) > FLT_EPSILON || fabs(transform->e23) > FLT_EPSILON ||
- fabs(transform->e31) > FLT_EPSILON || fabs(transform->e32) > FLT_EPSILON || fabs(transform->e33 - 1) > FLT_EPSILON) {
- return writeTagProperty(TVG_TAG_PAINT_TRANSFORM, SIZE(Matrix), transform);
+ if (fabs(transform.e11 - 1) > FLT_EPSILON || fabs(transform.e12) > FLT_EPSILON || fabs(transform.e13) > FLT_EPSILON ||
+ fabs(transform.e21) > FLT_EPSILON || fabs(transform.e22 - 1) > FLT_EPSILON || fabs(transform.e23) > FLT_EPSILON ||
+ fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) {
+ return writeTagProperty(TVG_TAG_PAINT_TRANSFORM, SIZE(Matrix), &transform);
}
return 0;
}
-TvgBinCounter TvgSaver::serializePaint(const Paint* paint)
+TvgBinCounter TvgSaver::serializePaint(const Paint* paint, const Matrix* pTransform)
{
TvgBinCounter cnt = 0;
const Paint* cmpTarget = nullptr;
auto cmpMethod = paint->composite(&cmpTarget);
if (cmpMethod != CompositeMethod::None && cmpTarget) {
- cnt += serializeComposite(cmpTarget, cmpMethod);
+ cnt += serializeComposite(cmpTarget, cmpMethod, pTransform);
}
return cnt;
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;
+ /* If the parent & the only child have composition, we can't skip the parent...
+ Or if the parent has the transform and composition, we can't skip the parent... */
+ if (compMethod != CompositeMethod::None) {
+ if (transform || child->composite(nullptr) != CompositeMethod::None) return 0;
+ }
//propagate opacity
uint32_t opacity = parent->opacity();
}
-TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* transform)
+TvgBinCounter TvgSaver::serializeScene(const Scene* scene, const Matrix* pTransform)
{
auto it = this->iterator(scene);
if (it->count() == 0) return 0;
+ auto transform = const_cast<Scene*>(scene)->transform();
+ if (pTransform) transform = _multiply(pTransform, &transform);
+
//Case - Only Child: Skip saving this scene.
if (it->count() == 1) {
- auto cnt = serializeChild(scene, it->next(), transform);
+ auto cnt = serializeChild(scene, it->next(), &transform);
if (cnt > 0) {
delete(it);
return cnt;
//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);
+ return serializeChildren(it, &transform);
}
//Case - Serialize Scene & its children
writeTag(TVG_TAG_CLASS_SCENE);
reserveCount();
- auto cnt = serializeChildren(it, transform) + serializePaint(scene);
+ auto cnt = serializeChildren(it, &transform) + serializePaint(scene, pTransform);
delete(it);
}
-TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* transform)
+TvgBinCounter TvgSaver::serializePath(const Shape* shape, const Matrix* pTransform)
{
const PathCommand* cmds = nullptr;
auto cmdCnt = shape->pathCommands(&cmds);
cnt += writeData(outCmds, SIZE(outCmds));
//transform?
- if (fabs(transform->e11 - 1) > FLT_EPSILON || fabs(transform->e12) > FLT_EPSILON || fabs(transform->e13) > FLT_EPSILON ||
- fabs(transform->e21) > FLT_EPSILON || fabs(transform->e22 - 1) > FLT_EPSILON || fabs(transform->e23) > FLT_EPSILON ||
- fabs(transform->e31) > FLT_EPSILON || fabs(transform->e32) > FLT_EPSILON || fabs(transform->e33 - 1) > FLT_EPSILON) {
+ auto transform = const_cast<Shape*>(shape)->transform();
+ if (pTransform) transform = _multiply(pTransform, &transform);
+
+ if (fabs(transform.e11 - 1) > FLT_EPSILON || fabs(transform.e12) > FLT_EPSILON || fabs(transform.e13) > FLT_EPSILON ||
+ fabs(transform.e21) > FLT_EPSILON || fabs(transform.e22 - 1) > FLT_EPSILON || fabs(transform.e23) > FLT_EPSILON ||
+ fabs(transform.e31) > FLT_EPSILON || fabs(transform.e32) > FLT_EPSILON || fabs(transform.e33 - 1) > FLT_EPSILON) {
auto p = const_cast<Point*>(pts);
for (uint32_t i = 0; i < ptsCnt; ++i) _multiply(p++, transform);
}
}
-TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* transform)
+TvgBinCounter TvgSaver::serializeShape(const Shape* shape, const Matrix* pTransform)
{
writeTag(TVG_TAG_CLASS_SHAPE);
reserveCount();
if (color[3] > 0) cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, SIZE(color), color);
}
- cnt += serializePath(shape, transform);
- cnt += serializePaint(shape);
+ cnt += serializePath(shape, pTransform);
+ cnt += serializePaint(shape, pTransform);
writeReservedCount(cnt);
/* Picture has either a vector scene or a bitmap. */
-TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* transform)
+TvgBinCounter TvgSaver::serializePicture(const Picture* picture, const Matrix* pTransform)
{
- //Case - Vector Scene: Only child, Skip to save Picture...
+ //transform
+ auto transform = const_cast<Picture*>(picture)->transform();
+ if (pTransform) transform = _multiply(pTransform, &transform);
+
auto it = this->iterator(picture);
+
+ //Case - Vector Scene:
if (it->count() == 1) {
- auto cnt = serializeChild(picture, it->next(), transform);
+ auto cnt = serializeChild(picture, it->next(), &transform);
+ //Only child, Skip to save Picture...
+ if (cnt > 0) {
+ delete(it);
+ return cnt;
+ /* Unfortunately, we can't skip the Picture because it might have a compositor,
+ Serialize Scene(instead of the Picture) & its scene. */
+ } else {
+ writeTag(TVG_TAG_CLASS_SCENE);
+ reserveCount();
+ auto cnt = serializeChildren(it, &transform) + serializePaint(picture, pTransform);
+ writeReservedCount(cnt);
+ }
delete(it);
- return cnt;
+ return SERIAL_DONE(cnt);
}
delete(it);
//Bitmap picture needs the transform info.
cnt += writeTransform(transform);
- cnt += serializePaint(picture);
+ cnt += serializePaint(picture, pTransform);
writeReservedCount(cnt);
}
-TvgBinCounter TvgSaver::serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod)
+TvgBinCounter TvgSaver::serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod, const Matrix* pTransform)
{
writeTag(TVG_TAG_PAINT_CMP_TARGET);
reserveCount();
auto flag = static_cast<TvgBinFlag>(cmpMethod);
auto cnt = writeTagProperty(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &flag);
- cnt += serialize(cmpTarget, nullptr, true);
+ cnt += serialize(cmpTarget, pTransform, true);
writeReservedCount(cnt);
}
-TvgBinCounter TvgSaver::serializeChildren(Iterator* it, const Matrix* transform)
+TvgBinCounter TvgSaver::serializeChildren(Iterator* it, const Matrix* pTransform)
{
TvgBinCounter cnt = 0;
//Serialize merged children.
auto child = children.data;
for (uint32_t i = 0; i < children.count; ++i, ++child) {
- cnt += serialize(*child, transform);
+ cnt += serialize(*child, pTransform);
}
return cnt;
}
-TvgBinCounter TvgSaver::serialize(const Paint* paint, const Matrix* transform, bool compTarget)
+TvgBinCounter TvgSaver::serialize(const Paint* paint, const Matrix* pTransform, bool compTarget)
{
if (!paint) return 0;
//Invisible paint, no point to save it if the paint is not the composition target...
if (!compTarget && paint->opacity() == 0) return 0;
- auto m = const_cast<Paint*>(paint)->transform();
- if (transform) m = _multiply(transform, &m);
-
switch (paint->id()) {
- case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast<const Shape*>(paint), &m);
- case TVG_CLASS_ID_SCENE: return serializeScene(static_cast<const Scene*>(paint), &m);
- case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast<const Picture*>(paint), &m);
+ case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast<const Shape*>(paint), pTransform);
+ case TVG_CLASS_ID_SCENE: return serializeScene(static_cast<const Scene*>(paint), pTransform);
+ case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast<const Picture*>(paint), pTransform);
}
return 0;
void writeReservedCount(TvgBinCounter cnt);
TvgBinCounter writeData(const void* data, TvgBinCounter cnt);
TvgBinCounter writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data);
- TvgBinCounter writeTransform(const Matrix* transform);
+ TvgBinCounter writeTransform(const Matrix& transform);
- TvgBinCounter serialize(const Paint* paint, const Matrix* transform, bool compTarget = false);
- TvgBinCounter serializeScene(const Scene* scene, const Matrix* transform);
- TvgBinCounter serializeShape(const Shape* shape, const Matrix* transform);
- TvgBinCounter serializePicture(const Picture* picture, const Matrix* transform);
- TvgBinCounter serializePaint(const Paint* paint);
+ TvgBinCounter serialize(const Paint* paint, const Matrix* pTransform, bool compTarget = false);
+ TvgBinCounter serializeScene(const Scene* scene, const Matrix* pTransform);
+ TvgBinCounter serializeShape(const Shape* shape, const Matrix* pTransform);
+ TvgBinCounter serializePicture(const Picture* picture, const Matrix* pTransform);
+ TvgBinCounter serializePaint(const Paint* paint, const Matrix* pTransform);
TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag);
TvgBinCounter serializeStroke(const Shape* shape);
- TvgBinCounter serializePath(const Shape* shape, const Matrix* transform);
- TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod);
+ TvgBinCounter serializePath(const Shape* shape, const Matrix* pTransform);
+ TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod, const Matrix* pTransform);
TvgBinCounter serializeChildren(Iterator* it, const Matrix* transform);
- TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* transform);
+ TvgBinCounter serializeChild(const Paint* parent, const Paint* child, const Matrix* pTransform);
public:
~TvgSaver();