mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Lottie: optimization
This commit is contained in:
parent
9fcef12d55
commit
58a1caf9df
@ -256,9 +256,10 @@ func processAnimationFolderAsync(basePath: String, path: String, stopOnFailure:
|
||||
return await processAnimationFolderItems(items: items, countPerBucket: 1, stopOnFailure: stopOnFailure, process: process)
|
||||
}
|
||||
|
||||
@available(iOS 13.0, *)
|
||||
func processAnimationFolderParallel(basePath: String, path: String, stopOnFailure: Bool, process: @escaping (String, String, Bool) async -> Bool) async -> Bool {
|
||||
let items = buildAnimationFolderItems(basePath: basePath, path: path)
|
||||
return await processAnimationFolderItems(items: items, countPerBucket: 16, stopOnFailure: stopOnFailure, process: process)
|
||||
return await processAnimationFolderItemsParallel(items: items, stopOnFailure: stopOnFailure, process: process)
|
||||
}
|
||||
|
||||
func cacheReferenceFolderPath(baseCachePath: String, width: Int, name: String) -> String {
|
||||
|
@ -79,7 +79,7 @@ private final class ReferenceCompareTest {
|
||||
|
||||
var continueFromName: String? = "5138957708585599529.json"
|
||||
|
||||
let _ = await processAnimationFolderParallel(basePath: bundlePath, path: "", stopOnFailure: true, process: { path, name, alwaysDraw in
|
||||
let _ = await processAnimationFolderAsync(basePath: bundlePath, path: "", stopOnFailure: true, process: { path, name, alwaysDraw in
|
||||
if let continueFromNameValue = continueFromName {
|
||||
if continueFromNameValue == name {
|
||||
continueFromName = nil
|
||||
|
@ -89,7 +89,13 @@ public:
|
||||
|
||||
void displayWithFrame(double frame, bool forceUpdates) {
|
||||
_transformNode->updateTree(frame, forceUpdates);
|
||||
|
||||
bool layerVisible = isInRangeOrEqual(frame, _inFrame, _outFrame);
|
||||
|
||||
_contentsLayer->setTransform(_transformNode->globalTransform());
|
||||
_contentsLayer->setOpacity(_transformNode->opacity());
|
||||
_contentsLayer->setIsHidden(!layerVisible);
|
||||
|
||||
/// Only update contents if current time is within the layers time bounds.
|
||||
if (layerVisible) {
|
||||
displayContentsWithFrame(frame, forceUpdates);
|
||||
@ -97,9 +103,6 @@ public:
|
||||
_maskLayer->updateWithFrame(frame, forceUpdates);
|
||||
}
|
||||
}
|
||||
_contentsLayer->setTransform(_transformNode->globalTransform());
|
||||
_contentsLayer->setOpacity(_transformNode->opacity());
|
||||
_contentsLayer->setIsHidden(!layerVisible);
|
||||
|
||||
if (const auto delegate = _layerDelegate.lock()) {
|
||||
delegate->frameUpdated(frame);
|
||||
@ -168,6 +171,9 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void updateRenderTree() {
|
||||
}
|
||||
|
||||
public:
|
||||
std::shared_ptr<LayerTransformNode> const transformNode() const {
|
||||
return _transformNode;
|
||||
@ -193,8 +199,6 @@ private:
|
||||
|
||||
std::string _keypathName;
|
||||
|
||||
//std::shared_ptr<RenderTreeNode> _renderTree;
|
||||
|
||||
public:
|
||||
virtual bool isImageCompositionLayer() const {
|
||||
return false;
|
||||
|
@ -101,6 +101,34 @@ public:
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<RenderTreeNode> renderTreeNode() override {
|
||||
if (!_renderTreeNode) {
|
||||
_renderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||
Vector2D(0.0, 0.0),
|
||||
CATransform3D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
nullptr,
|
||||
std::vector<std::shared_ptr<RenderTreeNode>>(),
|
||||
nullptr,
|
||||
false
|
||||
);
|
||||
|
||||
_contentsTreeNode = std::make_shared<RenderTreeNode>(
|
||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||
Vector2D(0.0, 0.0),
|
||||
CATransform3D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
nullptr,
|
||||
std::vector<std::shared_ptr<RenderTreeNode>>(),
|
||||
nullptr,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
if (_contentsLayer->isHidden()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -121,7 +149,17 @@ public:
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> subnodes;
|
||||
subnodes.push_back(std::make_shared<RenderTreeNode>(
|
||||
|
||||
_contentsTreeNode->_bounds = _contentsLayer->bounds();
|
||||
_contentsTreeNode->_position = _contentsLayer->position();
|
||||
_contentsTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentsTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
_contentsTreeNode->_subnodes = renderTreeValue;
|
||||
|
||||
subnodes.push_back(_contentsTreeNode);
|
||||
/*subnodes.push_back(std::make_shared<RenderTreeNode>(
|
||||
_contentsLayer->bounds(),
|
||||
_contentsLayer->position(),
|
||||
_contentsLayer->transform(),
|
||||
@ -132,7 +170,7 @@ public:
|
||||
renderTreeValue,
|
||||
nullptr,
|
||||
false
|
||||
));
|
||||
));*/
|
||||
|
||||
assert(opacity() == 1.0);
|
||||
assert(!isHidden());
|
||||
@ -140,18 +178,17 @@ public:
|
||||
assert(transform().isIdentity());
|
||||
assert(position() == Vector2D::Zero());
|
||||
|
||||
return std::make_shared<RenderTreeNode>(
|
||||
bounds(),
|
||||
position(),
|
||||
transform(),
|
||||
opacity(),
|
||||
masksToBounds(),
|
||||
isHidden(),
|
||||
nullptr,
|
||||
subnodes,
|
||||
maskNode,
|
||||
invertMask
|
||||
);
|
||||
_renderTreeNode->_bounds = bounds();
|
||||
_renderTreeNode->_position = position();
|
||||
_renderTreeNode->_transform = transform();
|
||||
_renderTreeNode->_alpha = opacity();
|
||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||
_renderTreeNode->_isHidden = isHidden();
|
||||
_renderTreeNode->_subnodes = subnodes;
|
||||
_renderTreeNode->_mask = maskNode;
|
||||
_renderTreeNode->_invertMask = invertMask;
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTreeNode> renderTree() {
|
||||
@ -188,11 +225,33 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
virtual void updateRenderTree() override {
|
||||
if (_matteLayer) {
|
||||
_matteLayer->updateRenderTree();
|
||||
}
|
||||
|
||||
for (const auto &animationLayer : _animationLayers) {
|
||||
bool found = false;
|
||||
for (const auto &sublayer : contentsLayer()->sublayers()) {
|
||||
if (animationLayer == sublayer) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
animationLayer->updateRenderTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
double _frameRate = 0.0;
|
||||
std::shared_ptr<NodeProperty<Vector1D>> _remappingNode;
|
||||
|
||||
std::vector<std::shared_ptr<CompositionLayer>> _animationLayers;
|
||||
|
||||
std::shared_ptr<RenderTreeNode> _renderTreeNode;
|
||||
std::shared_ptr<RenderTreeNode> _contentsTreeNode;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1284,16 +1284,46 @@ CompositionLayer(solidLayer, Vector2D::Zero()) {
|
||||
void ShapeCompositionLayer::displayContentsWithFrame(double frame, bool forceUpdates) {
|
||||
_frameTime = frame;
|
||||
_frameTimeInitialized = true;
|
||||
|
||||
_contentTree->itemTree->renderChildren(_frameTime, std::nullopt);
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode() {
|
||||
if (_contentsLayer->isHidden()) {
|
||||
return nullptr;
|
||||
if (!_frameTimeInitialized) {
|
||||
_frameTime = 0.0;
|
||||
_frameTimeInitialized = true;
|
||||
_contentTree->itemTree->renderChildren(_frameTime, std::nullopt);
|
||||
}
|
||||
|
||||
assert(_frameTimeInitialized);
|
||||
if (!_renderTreeNode) {
|
||||
_renderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||
Vector2D(0.0, 0.0),
|
||||
CATransform3D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
nullptr,
|
||||
std::vector<std::shared_ptr<RenderTreeNode>>(),
|
||||
nullptr,
|
||||
false
|
||||
);
|
||||
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> renderTreeValue;
|
||||
renderTreeValue.push_back(_contentTree->itemTree->renderTree());
|
||||
|
||||
_contentsTreeNode = std::make_shared<RenderTreeNode>(
|
||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||
Vector2D(0.0, 0.0),
|
||||
CATransform3D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
nullptr,
|
||||
renderTreeValue,
|
||||
nullptr,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTreeNode> maskNode;
|
||||
bool invertMask = false;
|
||||
@ -1304,45 +1334,39 @@ std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode() {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> renderTreeValue;
|
||||
renderTreeValue.push_back(_contentTree->itemTree->renderTree());
|
||||
_contentsTreeNode->_bounds = _contentsLayer->bounds();
|
||||
_contentsTreeNode->_position = _contentsLayer->position();
|
||||
_contentsTreeNode->_transform = _contentsLayer->transform();
|
||||
_contentsTreeNode->_alpha = _contentsLayer->opacity();
|
||||
_contentsTreeNode->_masksToBounds = _contentsLayer->masksToBounds();
|
||||
_contentsTreeNode->_isHidden = _contentsLayer->isHidden();
|
||||
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> subnodes;
|
||||
subnodes.push_back(std::make_shared<RenderTreeNode>(
|
||||
_contentsLayer->bounds(),
|
||||
_contentsLayer->position(),
|
||||
_contentsLayer->transform(),
|
||||
_contentsLayer->opacity(),
|
||||
_contentsLayer->masksToBounds(),
|
||||
_contentsLayer->isHidden(),
|
||||
nullptr,
|
||||
renderTreeValue,
|
||||
nullptr,
|
||||
false
|
||||
));
|
||||
subnodes.push_back(_contentsTreeNode);
|
||||
|
||||
assert(position() == Vector2D::Zero());
|
||||
assert(transform().isIdentity());
|
||||
assert(opacity() == 1.0);
|
||||
assert(!masksToBounds());
|
||||
assert(!isHidden());
|
||||
|
||||
assert(_contentsLayer->bounds() == CGRect(0.0, 0.0, 0.0, 0.0));
|
||||
assert(_contentsLayer->position() == Vector2D::Zero());
|
||||
assert(!_contentsLayer->masksToBounds());
|
||||
|
||||
return std::make_shared<RenderTreeNode>(
|
||||
bounds(),
|
||||
position(),
|
||||
transform(),
|
||||
opacity(),
|
||||
masksToBounds(),
|
||||
isHidden(),
|
||||
nullptr,
|
||||
subnodes,
|
||||
maskNode,
|
||||
invertMask
|
||||
);
|
||||
_renderTreeNode->_bounds = bounds();
|
||||
_renderTreeNode->_position = position();
|
||||
_renderTreeNode->_transform = transform();
|
||||
_renderTreeNode->_alpha = opacity();
|
||||
_renderTreeNode->_masksToBounds = masksToBounds();
|
||||
_renderTreeNode->_isHidden = isHidden();
|
||||
_renderTreeNode->_subnodes = subnodes;
|
||||
_renderTreeNode->_mask = maskNode;
|
||||
_renderTreeNode->_invertMask = invertMask;
|
||||
|
||||
return _renderTreeNode;
|
||||
}
|
||||
|
||||
void ShapeCompositionLayer::updateRenderTree() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,12 +18,16 @@ public:
|
||||
|
||||
virtual void displayContentsWithFrame(double frame, bool forceUpdates) override;
|
||||
virtual std::shared_ptr<RenderTreeNode> renderTreeNode() override;
|
||||
virtual void updateRenderTree() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ShapeLayerPresentationTree> _contentTree;
|
||||
|
||||
AnimationFrameTime _frameTime = 0.0;
|
||||
bool _frameTimeInitialized = false;
|
||||
|
||||
std::shared_ptr<RenderTreeNode> _renderTreeNode;
|
||||
std::shared_ptr<RenderTreeNode> _contentsTreeNode;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -23,12 +23,6 @@ public:
|
||||
_textProvider = textProvider;
|
||||
_fontProvider = fontProvider;
|
||||
|
||||
//_contentsLayer->addSublayer(_textLayer);
|
||||
|
||||
assert(false);
|
||||
//self.textLayer.masksToBounds = false
|
||||
//self.textLayer.isGeometryFlipped = true
|
||||
|
||||
if (_rootNode) {
|
||||
_childKeypaths.push_back(rootNode);
|
||||
}
|
||||
@ -67,42 +61,6 @@ public:
|
||||
if (_rootNode) {
|
||||
_rootNode->rebuildOutputs(frame);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
/*// Get Text Attributes
|
||||
let text = textDocument.value(frame: frame) as! TextDocument
|
||||
let strokeColor = rootNode?.textOutputNode.strokeColor ?? text.strokeColorData?.cgColorValue
|
||||
let strokeWidth = rootNode?.textOutputNode.strokeWidth ?? CGFloat(text.strokeWidth ?? 0)
|
||||
let tracking = (CGFloat(text.fontSize) * (rootNode?.textOutputNode.tracking ?? CGFloat(text.tracking))) / 1000.0
|
||||
let matrix = rootNode?.textOutputNode.xform ?? CATransform3DIdentity
|
||||
let textString = textProvider.textFor(keypathName: keypathName, sourceText: text.text)
|
||||
let ctFont = fontProvider.fontFor(family: text.fontFamily, size: CGFloat(text.fontSize))
|
||||
|
||||
// Set all of the text layer options
|
||||
textLayer.text = textString
|
||||
textLayer.font = ctFont
|
||||
textLayer.alignment = text.justification.textAlignment
|
||||
textLayer.lineHeight = CGFloat(text.lineHeight)
|
||||
textLayer.tracking = tracking
|
||||
|
||||
if let fillColor = rootNode?.textOutputNode.fillColor {
|
||||
textLayer.fillColor = fillColor
|
||||
} else if let fillColor = text.fillColorData?.cgColorValue {
|
||||
textLayer.fillColor = fillColor
|
||||
} else {
|
||||
textLayer.fillColor = nil
|
||||
}
|
||||
|
||||
textLayer.preferredSize = text.textFrameSize?.sizeValue
|
||||
textLayer.strokeOnTop = text.strokeOverFill ?? false
|
||||
textLayer.strokeWidth = strokeWidth
|
||||
textLayer.strokeColor = strokeColor
|
||||
textLayer.sizeToFit()
|
||||
|
||||
textLayer.opacity = Float(rootNode?.textOutputNode.opacity ?? 1)
|
||||
textLayer.transform = CATransform3DIdentity
|
||||
textLayer.position = text.textFramePosition?.pointValue ?? CGPoint.zero
|
||||
textLayer.transform = matrix*/
|
||||
}
|
||||
|
||||
public:
|
||||
@ -114,7 +72,6 @@ private:
|
||||
std::shared_ptr<TextAnimatorNode> _rootNode;
|
||||
std::shared_ptr<KeyframeInterpolator<TextDocument>> _textDocument;
|
||||
|
||||
//std::shared_ptr<CoreTextRenderLayer> _textLayer;
|
||||
std::shared_ptr<AnimationTextProvider> _textProvider;
|
||||
std::shared_ptr<AnimationFontProvider> _fontProvider;
|
||||
};
|
||||
|
@ -250,6 +250,21 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
virtual void updateRenderTree() {
|
||||
for (const auto &animationLayer : _animationLayers) {
|
||||
bool found = false;
|
||||
for (const auto &sublayer : sublayers()) {
|
||||
if (animationLayer == sublayer) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
animationLayer->updateRenderTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// MARK: Internal
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user