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;
VPointF position;
if (mSeparate) {
position.setX(mX.value(frameNo));
position.setY(mY.value(frameNo));
if (mExtra && mExtra->mSeparate) {
position.setX(mExtra->mSeparateX.value(frameNo));
position.setY(mExtra->mSeparateY.value(frameNo));
} else {
position = mPosition.value(frameNo);
}
float angle = autoOrient ? mPosition.angle(frameNo) : 0;
if (m3D) {
if (mExtra && mExtra->m3DData) {
m.translate(position)
.rotate(m3D->mRz.value(frameNo) + angle)
.rotate(m3D->mRy.value(frameNo), VMatrix::Axis::Y)
.rotate(m3D->mRx.value(frameNo), VMatrix::Axis::X)
.rotate(mExtra->m3DRz.value(frameNo) + angle)
.rotate(mExtra->m3DRy.value(frameNo), VMatrix::Axis::Y)
.rotate(mExtra->m3DRx.value(frameNo), VMatrix::Axis::X)
.scale(mScale.value(frameNo) / 100.f)
.translate(-mAnchor.value(frameNo));
} else {

View File

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

View File

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