mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Refactoring
This commit is contained in:
parent
b6ba0d8f99
commit
7f88fb6ffa
@ -18,7 +18,7 @@ struct TransformedPath {
|
||||
}
|
||||
};
|
||||
|
||||
static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform) {
|
||||
static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
//TODO:remove skipApplyTransform
|
||||
lottie::CATransform3D effectiveTransform = parentTransform;
|
||||
if (!skipApplyTransform && item->isGroup) {
|
||||
@ -29,13 +29,17 @@ static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTre
|
||||
|
||||
lottie::CGRect boundingBox(0.0, 0.0, 0.0, 0.0);
|
||||
if (item->path) {
|
||||
boundingBox = item->pathBoundingBox.applyingTransform(effectiveTransform);
|
||||
if (item->path->needsBoundsRecalculation) {
|
||||
item->path->bounds = lottie::bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, item->path->path);
|
||||
item->path->needsBoundsRecalculation = false;
|
||||
}
|
||||
boundingBox = item->path->bounds.applyingTransform(effectiveTransform);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < maxSubitem; i++) {
|
||||
auto &subItem = item->subItems[i];
|
||||
|
||||
lottie::CGRect subItemBoundingBox = collectPathBoundingBoxes(subItem, INT32_MAX, effectiveTransform, false);
|
||||
lottie::CGRect subItemBoundingBox = collectPathBoundingBoxes(subItem, INT32_MAX, effectiveTransform, false, bezierPathsBoundingBoxContext);
|
||||
|
||||
if (boundingBox.empty()) {
|
||||
boundingBox = subItemBoundingBox;
|
||||
@ -59,7 +63,7 @@ static std::vector<TransformedPath> collectPaths(std::shared_ptr<lottie::RenderT
|
||||
size_t maxSubitem = std::min(item->subItems.size(), subItemLimit);
|
||||
|
||||
if (item->path) {
|
||||
mappedPaths.emplace_back(item->path.value(), effectiveTransform);
|
||||
mappedPaths.emplace_back(item->path->path, effectiveTransform);
|
||||
}
|
||||
assert(!item->trimParams);
|
||||
|
||||
@ -96,7 +100,7 @@ static void processRenderContentItem(std::shared_ptr<RenderTreeNodeContentItem>
|
||||
int drawContentDescendants = 0;
|
||||
|
||||
for (const auto &shadingVariant : contentItem->shadings) {
|
||||
lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::CATransform3D::identity(), true);
|
||||
lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::CATransform3D::identity(), true, bezierPathsBoundingBoxContext);
|
||||
|
||||
if (shadingVariant->stroke) {
|
||||
shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0);
|
||||
|
@ -309,6 +309,17 @@ public:
|
||||
|
||||
class RenderTreeNodeContentShadingVariant;
|
||||
|
||||
struct RenderTreeNodeContentPath {
|
||||
public:
|
||||
explicit RenderTreeNodeContentPath(BezierPath path_) :
|
||||
path(path_) {
|
||||
}
|
||||
|
||||
BezierPath path;
|
||||
CGRect bounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
bool needsBoundsRecalculation = true;
|
||||
};
|
||||
|
||||
class RenderTreeNodeContentItem {
|
||||
public:
|
||||
enum class ShadingType {
|
||||
@ -423,8 +434,7 @@ public:
|
||||
CATransform3D transform = CATransform3D::identity();
|
||||
float alpha = 0.0;
|
||||
std::optional<TrimParams> trimParams;
|
||||
std::optional<BezierPath> path;
|
||||
CGRect pathBoundingBox = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> path;
|
||||
std::vector<std::shared_ptr<RenderTreeNodeContentShadingVariant>> shadings;
|
||||
std::vector<std::shared_ptr<RenderTreeNodeContentItem>> subItems;
|
||||
|
||||
|
@ -506,60 +506,44 @@ public:
|
||||
}
|
||||
virtual ~PathOutput() = default;
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) = 0;
|
||||
virtual BezierPath const *currentPath() = 0;
|
||||
virtual CGRect const ¤tPathBounds() = 0;
|
||||
virtual void update(AnimationFrameTime frameTime) = 0;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() = 0;
|
||||
};
|
||||
|
||||
class StaticPathOutput : public PathOutput {
|
||||
public:
|
||||
explicit StaticPathOutput(BezierPath const &path) :
|
||||
resolvedPath(path) {
|
||||
resolvedPath(std::make_shared<RenderTreeNodeContentPath>(path)) {
|
||||
}
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
if (!isPathBoundsResolved) {
|
||||
resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath);
|
||||
isPathBoundsResolved = true;
|
||||
}
|
||||
virtual void update(AnimationFrameTime frameTime) override {
|
||||
}
|
||||
|
||||
virtual BezierPath const *currentPath() override {
|
||||
return &resolvedPath;
|
||||
}
|
||||
|
||||
virtual CGRect const ¤tPathBounds() override {
|
||||
return resolvedPathBounds;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() override {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
private:
|
||||
BezierPath resolvedPath;
|
||||
|
||||
bool isPathBoundsResolved = false;
|
||||
CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> resolvedPath;
|
||||
};
|
||||
|
||||
class ShapePathOutput : public PathOutput {
|
||||
public:
|
||||
explicit ShapePathOutput(Shape const &shape) :
|
||||
path(shape.path.keyframes) {
|
||||
path(shape.path.keyframes),
|
||||
resolvedPath(std::make_shared<RenderTreeNodeContentPath>(BezierPath())) {
|
||||
}
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
virtual void update(AnimationFrameTime frameTime) override {
|
||||
if (!hasValidData || path.hasUpdate(frameTime)) {
|
||||
path.update(frameTime, resolvedPath);
|
||||
resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath);
|
||||
path.update(frameTime, resolvedPath->path);
|
||||
resolvedPath->needsBoundsRecalculation = true;
|
||||
}
|
||||
|
||||
hasValidData = true;
|
||||
}
|
||||
|
||||
virtual BezierPath const *currentPath() override {
|
||||
return &resolvedPath;
|
||||
}
|
||||
|
||||
virtual CGRect const ¤tPathBounds() override {
|
||||
return resolvedPathBounds;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() override {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -567,8 +551,7 @@ public:
|
||||
|
||||
BezierPathKeyframeInterpolator path;
|
||||
|
||||
BezierPath resolvedPath;
|
||||
CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> resolvedPath;
|
||||
};
|
||||
|
||||
class RectanglePathOutput : public PathOutput {
|
||||
@ -577,10 +560,11 @@ public:
|
||||
direction(rectangle.direction.value_or(PathDirection::Clockwise)),
|
||||
position(rectangle.position.keyframes),
|
||||
size(rectangle.size.keyframes),
|
||||
cornerRadius(rectangle.cornerRadius.keyframes) {
|
||||
cornerRadius(rectangle.cornerRadius.keyframes),
|
||||
resolvedPath(std::make_shared<RenderTreeNodeContentPath>(BezierPath())) {
|
||||
}
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
virtual void update(AnimationFrameTime frameTime) override {
|
||||
bool hasUpdates = false;
|
||||
|
||||
if (!hasValidData || position.hasUpdate(frameTime)) {
|
||||
@ -597,19 +581,15 @@ public:
|
||||
}
|
||||
|
||||
if (hasUpdates) {
|
||||
ValueInterpolator<BezierPath>::setInplace(makeRectangleBezierPath(Vector2D(positionValue.x, positionValue.y), Vector2D(sizeValue.x, sizeValue.y), cornerRadiusValue, direction), resolvedPath);
|
||||
resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath);
|
||||
ValueInterpolator<BezierPath>::setInplace(makeRectangleBezierPath(Vector2D(positionValue.x, positionValue.y), Vector2D(sizeValue.x, sizeValue.y), cornerRadiusValue, direction), resolvedPath->path);
|
||||
resolvedPath->needsBoundsRecalculation = true;
|
||||
}
|
||||
|
||||
hasValidData = true;
|
||||
}
|
||||
|
||||
virtual BezierPath const *currentPath() override {
|
||||
return &resolvedPath;
|
||||
}
|
||||
|
||||
virtual CGRect const ¤tPathBounds() override {
|
||||
return resolvedPathBounds;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() override {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -626,8 +606,7 @@ public:
|
||||
KeyframeInterpolator<Vector1D> cornerRadius;
|
||||
float cornerRadiusValue = 0.0;
|
||||
|
||||
BezierPath resolvedPath;
|
||||
CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> resolvedPath;
|
||||
};
|
||||
|
||||
class EllipsePathOutput : public PathOutput {
|
||||
@ -635,10 +614,11 @@ public:
|
||||
explicit EllipsePathOutput(Ellipse const &ellipse) :
|
||||
direction(ellipse.direction.value_or(PathDirection::Clockwise)),
|
||||
position(ellipse.position.keyframes),
|
||||
size(ellipse.size.keyframes) {
|
||||
size(ellipse.size.keyframes),
|
||||
resolvedPath(std::make_shared<RenderTreeNodeContentPath>(BezierPath())) {
|
||||
}
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
virtual void update(AnimationFrameTime frameTime) override {
|
||||
bool hasUpdates = false;
|
||||
|
||||
if (!hasValidData || position.hasUpdate(frameTime)) {
|
||||
@ -651,19 +631,15 @@ public:
|
||||
}
|
||||
|
||||
if (hasUpdates) {
|
||||
ValueInterpolator<BezierPath>::setInplace(makeEllipseBezierPath(Vector2D(sizeValue.x, sizeValue.y), Vector2D(positionValue.x, positionValue.y), direction), resolvedPath);
|
||||
resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath);
|
||||
ValueInterpolator<BezierPath>::setInplace(makeEllipseBezierPath(Vector2D(sizeValue.x, sizeValue.y), Vector2D(positionValue.x, positionValue.y), direction), resolvedPath->path);
|
||||
resolvedPath->needsBoundsRecalculation = true;
|
||||
}
|
||||
|
||||
hasValidData = true;
|
||||
}
|
||||
|
||||
virtual BezierPath const *currentPath() override {
|
||||
return &resolvedPath;
|
||||
}
|
||||
|
||||
virtual CGRect const ¤tPathBounds() override {
|
||||
return resolvedPathBounds;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() override {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -677,8 +653,7 @@ public:
|
||||
KeyframeInterpolator<Vector3D> size;
|
||||
Vector3D sizeValue = Vector3D(0.0, 0.0, 0.0);
|
||||
|
||||
BezierPath resolvedPath;
|
||||
CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> resolvedPath;
|
||||
};
|
||||
|
||||
class StarPathOutput : public PathOutput {
|
||||
@ -689,7 +664,8 @@ public:
|
||||
outerRadius(star.outerRadius.keyframes),
|
||||
outerRoundedness(star.outerRoundness.keyframes),
|
||||
rotation(star.rotation.keyframes),
|
||||
points(star.points.keyframes) {
|
||||
points(star.points.keyframes),
|
||||
resolvedPath(std::make_shared<RenderTreeNodeContentPath>(BezierPath())) {
|
||||
if (star.innerRadius.has_value()) {
|
||||
innerRadius = std::make_unique<NodeProperty<Vector1D>>(std::make_shared<KeyframeInterpolator<Vector1D>>(star.innerRadius->keyframes));
|
||||
} else {
|
||||
@ -703,7 +679,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void update(AnimationFrameTime frameTime, BezierPathsBoundingBoxContext &boundingBoxContext) override {
|
||||
virtual void update(AnimationFrameTime frameTime) override {
|
||||
bool hasUpdates = false;
|
||||
|
||||
if (!hasValidData || position.hasUpdate(frameTime)) {
|
||||
@ -744,19 +720,15 @@ public:
|
||||
}
|
||||
|
||||
if (hasUpdates) {
|
||||
ValueInterpolator<BezierPath>::setInplace(makeStarBezierPath(Vector2D(positionValue.x, positionValue.y), outerRadiusValue, innerRadiusValue, outerRoundednessValue, innerRoundednessValue, pointsValue, rotationValue, direction), resolvedPath);
|
||||
resolvedPathBounds = bezierPathsBoundingBoxParallel(boundingBoxContext, resolvedPath);
|
||||
ValueInterpolator<BezierPath>::setInplace(makeStarBezierPath(Vector2D(positionValue.x, positionValue.y), outerRadiusValue, innerRadiusValue, outerRoundednessValue, innerRoundednessValue, pointsValue, rotationValue, direction), resolvedPath->path);
|
||||
resolvedPath->needsBoundsRecalculation = true;
|
||||
}
|
||||
|
||||
hasValidData = true;
|
||||
}
|
||||
|
||||
virtual BezierPath const *currentPath() override {
|
||||
return &resolvedPath;
|
||||
}
|
||||
|
||||
virtual CGRect const ¤tPathBounds() override {
|
||||
return resolvedPathBounds;
|
||||
virtual std::shared_ptr<RenderTreeNodeContentPath> ¤tPath() override {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -785,8 +757,7 @@ public:
|
||||
KeyframeInterpolator<Vector1D> points;
|
||||
float pointsValue = 0.0;
|
||||
|
||||
BezierPath resolvedPath;
|
||||
CGRect resolvedPathBounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||
std::shared_ptr<RenderTreeNodeContentPath> resolvedPath;
|
||||
};
|
||||
|
||||
class TransformOutput {
|
||||
@ -951,7 +922,7 @@ public:
|
||||
size_t maxSubitem = std::min(subItems.size(), subItemLimit);
|
||||
|
||||
if (_contentItem->path) {
|
||||
mappedPaths.emplace_back(_contentItem->path.value(), effectiveTransform);
|
||||
mappedPaths.emplace_back(_contentItem->path->path, effectiveTransform);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < maxSubitem; i++) {
|
||||
@ -1012,7 +983,7 @@ public:
|
||||
_contentItem->isGroup = isGroup;
|
||||
|
||||
if (path) {
|
||||
_contentItem->path = *path->currentPath();
|
||||
_contentItem->path = path->currentPath();
|
||||
}
|
||||
|
||||
if (!shadings.empty()) {
|
||||
@ -1052,8 +1023,7 @@ public:
|
||||
}
|
||||
|
||||
if (path) {
|
||||
path->update(frameTime, boundingBoxContext);
|
||||
_contentItem->pathBoundingBox = path->currentPathBounds();
|
||||
path->update(frameTime);
|
||||
}
|
||||
for (const auto &trim : trims) {
|
||||
trim->update(frameTime);
|
||||
|
Loading…
x
Reference in New Issue
Block a user