optimization: move rare propery field to extra structure to minimize memory footprint of LOTTransformData.

- only layer transform object can have position property as separate X and Y
  by keeping them in the main structure incurs an overhead of 32 bytes to the user of the structure.
  as well as 8 byte on the book keeping (mSeparate) by moving those rarely used field along with 3D
  data to ExtraData we could trim the object size by 40bytes.

- with this patch now the object size is reduced from 128 bytes to 88bytes.
This commit is contained in:
subhransu mohanty 2019-08-01 10:52:12 +09:00 committed by Subhransu
parent e7f0790e06
commit 2034f0ee0c
3 changed files with 53 additions and 41 deletions

View File

@ -111,19 +111,19 @@ VMatrix TransformData::matrix(int frameNo, bool autoOrient) const
{ {
VMatrix m; VMatrix m;
VPointF position; VPointF position;
if (mSeparate) { if (mExtra && mExtra->mSeparate) {
position.setX(mX.value(frameNo)); position.setX(mExtra->mSeparateX.value(frameNo));
position.setY(mY.value(frameNo)); position.setY(mExtra->mSeparateY.value(frameNo));
} else { } else {
position = mPosition.value(frameNo); position = mPosition.value(frameNo);
} }
float angle = autoOrient ? mPosition.angle(frameNo) : 0; float angle = autoOrient ? mPosition.angle(frameNo) : 0;
if (m3D) { if (mExtra && mExtra->m3DData) {
m.translate(position) m.translate(position)
.rotate(m3D->mRz.value(frameNo) + angle) .rotate(mExtra->m3DRz.value(frameNo) + angle)
.rotate(m3D->mRy.value(frameNo), VMatrix::Axis::Y) .rotate(mExtra->m3DRy.value(frameNo), VMatrix::Axis::Y)
.rotate(m3D->mRx.value(frameNo), VMatrix::Axis::X) .rotate(mExtra->m3DRx.value(frameNo), VMatrix::Axis::X)
.scale(mScale.value(frameNo) / 100.f) .scale(mScale.value(frameNo) / 100.f)
.translate(-mAnchor.value(frameNo)); .translate(-mAnchor.value(frameNo));
} else { } else {

View File

@ -423,37 +423,40 @@ struct LOTAsset
VBitmap mBitmap; VBitmap mBitmap;
}; };
struct LOT3DData struct TransformDataExtra
{ {
LOTAnimatable<float> mRx{0}; LOTAnimatable<float> m3DRx{0};
LOTAnimatable<float> mRy{0}; LOTAnimatable<float> m3DRy{0};
LOTAnimatable<float> mRz{0}; LOTAnimatable<float> m3DRz{0};
LOTAnimatable<float> mSeparateX{0};
LOTAnimatable<float> mSeparateY{0};
bool mSeparate{false};
bool m3DData{false};
}; };
struct TransformData struct TransformData
{ {
VMatrix matrix(int frameNo, bool autoOrient = false) const; VMatrix matrix(int frameNo, bool autoOrient = false) const;
float opacity(int frameNo) const { return mOpacity.value(frameNo)/100.0f; } float opacity(int frameNo) const { return mOpacity.value(frameNo)/100.0f; }
bool isStatic() const { return mStatic;} void createExtraData()
std::unique_ptr<LOT3DData> m3D; {
LOTAnimatable<float> mRotation{0}; /* "r" */ if (!mExtra) mExtra = std::make_unique<TransformDataExtra>();
LOTAnimatable<VPointF> mScale{{100, 100}}; /* "s" */ }
LOTAnimatable<VPointF> mPosition; /* "p" */ LOTAnimatable<float> mRotation{0}; /* "r" */
LOTAnimatable<float> mX{0}; LOTAnimatable<VPointF> mScale{{100, 100}}; /* "s" */
LOTAnimatable<float> mY{0}; LOTAnimatable<VPointF> mPosition; /* "p" */
LOTAnimatable<VPointF> mAnchor; /* "a" */ LOTAnimatable<VPointF> mAnchor; /* "a" */
LOTAnimatable<float> mOpacity{100}; /* "o" */ LOTAnimatable<float> mOpacity{100}; /* "o" */
bool mSeparate{false}; std::unique_ptr<TransformDataExtra> mExtra;
bool mStatic{false};
}; };
class LOTTransformData : public LOTData class LOTTransformData : public LOTData
{ {
public: public:
LOTTransformData():LOTData(LOTData::Type::Transform){} LOTTransformData():LOTData(LOTData::Type::Transform){}
void set(std::unique_ptr<TransformData> data) void set(std::unique_ptr<TransformData> data, bool staticFlag)
{ {
setStatic(data->isStatic()); setStatic(staticFlag);
if (isStatic()) { if (isStatic()) {
new (&impl.mStaticData) static_data(data->matrix(0), data->opacity(0)); new (&impl.mStaticData) static_data(data->matrix(0), data->opacity(0));
} else { } else {

View File

@ -1387,7 +1387,10 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(
std::make_shared<LOTTransformData>(); std::make_shared<LOTTransformData>();
auto obj = std::make_unique<TransformData>(); auto obj = std::make_unique<TransformData>();
if (ddd) obj->m3D = std::make_unique<LOT3DData>(); if (ddd) {
obj->createExtraData();
obj->mExtra->m3DData = true;
}
while (const char *key = NextObjectKey()) { while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "nm")) { if (0 == strcmp(key, "nm")) {
@ -1396,15 +1399,18 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(
parseProperty(obj->mAnchor); parseProperty(obj->mAnchor);
} else if (0 == strcmp(key, "p")) { } else if (0 == strcmp(key, "p")) {
EnterObject(); EnterObject();
bool separate = false;
while (const char *key = NextObjectKey()) { while (const char *key = NextObjectKey()) {
if (0 == strcmp(key, "k")) { if (0 == strcmp(key, "k")) {
parsePropertyHelper(obj->mPosition); parsePropertyHelper(obj->mPosition);
} else if (0 == strcmp(key, "s")) { } else if (0 == strcmp(key, "s")) {
obj->mSeparate = GetBool(); obj->createExtraData();
} else if (obj->mSeparate && (0 == strcmp(key, "x"))) { obj->mExtra->mSeparate = GetBool();
parseProperty(obj->mX); separate = true;
} else if (obj->mSeparate && (0 == strcmp(key, "y"))) { } else if (separate && (0 == strcmp(key, "x"))) {
parseProperty(obj->mY); parseProperty(obj->mExtra->mSeparateX);
} else if (separate && (0 == strcmp(key, "y"))) {
parseProperty(obj->mExtra->mSeparateY);
} else { } else {
Skip(key); Skip(key);
} }
@ -1418,25 +1424,28 @@ std::shared_ptr<LOTTransformData> LottieParserImpl::parseTransformObject(
} else if (0 == strcmp(key, "hd")) { } else if (0 == strcmp(key, "hd")) {
sharedTransform->mHidden = GetBool(); sharedTransform->mHidden = GetBool();
} else if (0 == strcmp(key, "rx")) { } else if (0 == strcmp(key, "rx")) {
parseProperty(obj->m3D->mRx); parseProperty(obj->mExtra->m3DRx);
} else if (0 == strcmp(key, "ry")) { } else if (0 == strcmp(key, "ry")) {
parseProperty(obj->m3D->mRy); parseProperty(obj->mExtra->m3DRy);
} else if (0 == strcmp(key, "rz")) { } else if (0 == strcmp(key, "rz")) {
parseProperty(obj->m3D->mRz); parseProperty(obj->mExtra->m3DRz);
} else { } else {
Skip(key); Skip(key);
} }
} }
obj->mStatic = obj->mAnchor.isStatic() && obj->mPosition.isStatic() && bool isStatic = obj->mAnchor.isStatic() && obj->mPosition.isStatic() &&
obj->mRotation.isStatic() && obj->mScale.isStatic() && obj->mRotation.isStatic() && obj->mScale.isStatic() &&
obj->mX.isStatic() && obj->mY.isStatic() && obj->mOpacity.isStatic();
obj->mOpacity.isStatic(); if (obj->mExtra) {
if (obj->m3D) { isStatic = isStatic &&
obj->mStatic = obj->mStatic && obj->m3D->mRx.isStatic() && obj->mExtra->m3DRx.isStatic() &&
obj->m3D->mRy.isStatic() && obj->m3D->mRz.isStatic(); obj->mExtra->m3DRy.isStatic() &&
obj->mExtra->m3DRz.isStatic() &&
obj->mExtra->mSeparateX.isStatic() &&
obj->mExtra->mSeparateY.isStatic();
} }
sharedTransform->set(std::move(obj)); sharedTransform->set(std::move(obj), isStatic);
return sharedTransform; return sharedTransform;
} }