mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Lottie optimization
This commit is contained in:
parent
2cf5bd724a
commit
920de21020
@ -38,6 +38,54 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
||||
|
||||
double alpha = node->alpha();
|
||||
|
||||
/*if (node->_contentItem) {
|
||||
RenderTreeNodeContentItem *contentItem = node->_contentItem.get();
|
||||
for (const auto &shadingVariant : contentItem->shadings) {
|
||||
if (shadingVariant->stroke) {
|
||||
CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shadingVariant->explicitPath.value());
|
||||
shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0);
|
||||
effectiveLocalBounds = shapeBounds;
|
||||
|
||||
switch (shadingVariant->stroke->shading->type()) {
|
||||
case RenderTreeNodeContent::ShadingType::Solid: {
|
||||
RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shadingVariant->stroke->shading.get();
|
||||
|
||||
alpha *= solidShading->opacity;
|
||||
|
||||
break;
|
||||
}
|
||||
case RenderTreeNodeContent::ShadingType::Gradient: {
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (shadingVariant->fill) {
|
||||
CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shadingVariant->explicitPath.value());
|
||||
effectiveLocalBounds = shapeBounds;
|
||||
|
||||
switch (shadingVariant->fill->shading->type()) {
|
||||
case RenderTreeNodeContent::ShadingType::Solid: {
|
||||
RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shadingVariant->fill->shading.get();
|
||||
|
||||
alpha *= solidShading->opacity;
|
||||
|
||||
break;
|
||||
}
|
||||
case RenderTreeNodeContent::ShadingType::Gradient: {
|
||||
RenderTreeNodeContent::GradientShading *gradientShading = (RenderTreeNodeContent::GradientShading *)shadingVariant->fill->shading.get();
|
||||
|
||||
alpha *= gradientShading->opacity;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (node->content()) {
|
||||
RenderTreeNodeContent *shapeContent = node->content().get();
|
||||
|
||||
@ -47,7 +95,7 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
||||
shapeBounds = shapeBounds.insetBy(-shapeContent->stroke->lineWidth / 2.0, -shapeContent->stroke->lineWidth / 2.0);
|
||||
effectiveLocalBounds = shapeBounds;
|
||||
|
||||
switch (shapeContent->stroke->shading->type()) {
|
||||
/*switch (shapeContent->stroke->shading->type()) {
|
||||
case RenderTreeNodeContent::ShadingType::Solid: {
|
||||
RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shapeContent->stroke->shading.get();
|
||||
|
||||
@ -61,11 +109,11 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
} else if (shapeContent->fill) {
|
||||
effectiveLocalBounds = shapeBounds;
|
||||
|
||||
switch (shapeContent->fill->shading->type()) {
|
||||
/*switch (shapeContent->fill->shading->type()) {
|
||||
case RenderTreeNodeContent::ShadingType::Solid: {
|
||||
RenderTreeNodeContent::SolidShading *solidShading = (RenderTreeNodeContent::SolidShading *)shapeContent->fill->shading.get();
|
||||
|
||||
@ -82,7 +130,7 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,7 +158,7 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
||||
if (item->renderData.isValid) {
|
||||
drawContentDescendants += item->renderData.drawContentDescendants;
|
||||
|
||||
if (item->content()) {
|
||||
if (item->content() || item->_contentItem) {
|
||||
drawContentDescendants += 1;
|
||||
}
|
||||
|
||||
@ -322,7 +370,7 @@ static void drawLottieRenderableItem(std::shared_ptr<lottieRendering::Canvas> co
|
||||
dashPattern = item->stroke->dashPattern;
|
||||
}
|
||||
|
||||
context->strokePath(path, item->stroke->lineWidth, lineJoin, lineCap, item->stroke->dashPhase, dashPattern, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a));
|
||||
context->strokePath(path, item->stroke->lineWidth, lineJoin, lineCap, item->stroke->dashPhase, dashPattern, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity));
|
||||
} else if (item->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) {
|
||||
//TODO:gradient stroke
|
||||
}
|
||||
@ -344,14 +392,14 @@ static void drawLottieRenderableItem(std::shared_ptr<lottieRendering::Canvas> co
|
||||
|
||||
if (item->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) {
|
||||
lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)item->fill->shading.get();
|
||||
context->fillPath(path, rule, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a));
|
||||
context->fillPath(path, rule, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity));
|
||||
} else if (item->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) {
|
||||
lottie::RenderTreeNodeContent::GradientShading *gradientShading = (lottie::RenderTreeNodeContent::GradientShading *)item->fill->shading.get();
|
||||
|
||||
std::vector<lottieRendering::Color> colors;
|
||||
std::vector<double> locations;
|
||||
for (const auto &color : gradientShading->colors) {
|
||||
colors.push_back(lottieRendering::Color(color.r, color.g, color.b, color.a));
|
||||
colors.push_back(lottieRendering::Color(color.r, color.g, color.b, color.a * gradientShading->opacity));
|
||||
}
|
||||
locations = gradientShading->locations;
|
||||
|
||||
@ -376,6 +424,179 @@ static void drawLottieRenderableItem(std::shared_ptr<lottieRendering::Canvas> co
|
||||
}
|
||||
}
|
||||
|
||||
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> context, std::shared_ptr<lottie::RenderTreeNodeContentItem> item) {
|
||||
if (item->shadings.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &shading : item->shadings) {
|
||||
if (shading->explicitPath->empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<lottie::CGPath> path = lottie::CGPath::makePath();
|
||||
|
||||
const auto iterate = [&](LottiePathItem const *pathItem) {
|
||||
switch (pathItem->type) {
|
||||
case LottiePathItemTypeMoveTo: {
|
||||
path->moveTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y));
|
||||
break;
|
||||
}
|
||||
case LottiePathItemTypeLineTo: {
|
||||
path->addLineTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y));
|
||||
break;
|
||||
}
|
||||
case LottiePathItemTypeCurveTo: {
|
||||
path->addCurveTo(lottie::Vector2D(pathItem->points[2].x, pathItem->points[2].y), lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y), lottie::Vector2D(pathItem->points[1].x, pathItem->points[1].y));
|
||||
break;
|
||||
}
|
||||
case LottiePathItemTypeClose: {
|
||||
path->closeSubpath();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LottiePathItem pathItem;
|
||||
for (const auto &path : shading->explicitPath.value()) {
|
||||
std::optional<lottie::PathElement> previousElement;
|
||||
for (const auto &element : path.elements()) {
|
||||
if (previousElement.has_value()) {
|
||||
if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) {
|
||||
pathItem.type = LottiePathItemTypeLineTo;
|
||||
pathItem.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(&pathItem);
|
||||
} else {
|
||||
pathItem.type = LottiePathItemTypeCurveTo;
|
||||
pathItem.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
pathItem.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y);
|
||||
pathItem.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y);
|
||||
iterate(&pathItem);
|
||||
}
|
||||
} else {
|
||||
pathItem.type = LottiePathItemTypeMoveTo;
|
||||
pathItem.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(&pathItem);
|
||||
}
|
||||
previousElement = element;
|
||||
}
|
||||
if (path.closed().value_or(true)) {
|
||||
pathItem.type = LottiePathItemTypeClose;
|
||||
iterate(&pathItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (shading->stroke) {
|
||||
if (shading->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) {
|
||||
lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)shading->stroke->shading.get();
|
||||
|
||||
if (solidShading->opacity != 0.0) {
|
||||
lottieRendering::LineJoin lineJoin = lottieRendering::LineJoin::Bevel;
|
||||
switch (shading->stroke->lineJoin) {
|
||||
case lottie::LineJoin::Bevel: {
|
||||
lineJoin = lottieRendering::LineJoin::Bevel;
|
||||
break;
|
||||
}
|
||||
case lottie::LineJoin::Round: {
|
||||
lineJoin = lottieRendering::LineJoin::Round;
|
||||
break;
|
||||
}
|
||||
case lottie::LineJoin::Miter: {
|
||||
lineJoin = lottieRendering::LineJoin::Miter;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lottieRendering::LineCap lineCap = lottieRendering::LineCap::Square;
|
||||
switch (shading->stroke->lineCap) {
|
||||
case lottie::LineCap::Butt: {
|
||||
lineCap = lottieRendering::LineCap::Butt;
|
||||
break;
|
||||
}
|
||||
case lottie::LineCap::Round: {
|
||||
lineCap = lottieRendering::LineCap::Round;
|
||||
break;
|
||||
}
|
||||
case lottie::LineCap::Square: {
|
||||
lineCap = lottieRendering::LineCap::Square;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> dashPattern;
|
||||
if (!shading->stroke->dashPattern.empty()) {
|
||||
dashPattern = shading->stroke->dashPattern;
|
||||
}
|
||||
|
||||
context->strokePath(path, shading->stroke->lineWidth, lineJoin, lineCap, shading->stroke->dashPhase, dashPattern, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity));
|
||||
} else if (shading->stroke->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) {
|
||||
//TODO:gradient stroke
|
||||
}
|
||||
}
|
||||
} else if (shading->fill) {
|
||||
lottieRendering::FillRule rule = lottieRendering::FillRule::NonZeroWinding;
|
||||
switch (shading->fill->rule) {
|
||||
case lottie::FillRule::EvenOdd: {
|
||||
rule = lottieRendering::FillRule::EvenOdd;
|
||||
break;
|
||||
}
|
||||
case lottie::FillRule::NonZeroWinding: {
|
||||
rule = lottieRendering::FillRule::NonZeroWinding;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shading->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Solid) {
|
||||
lottie::RenderTreeNodeContent::SolidShading *solidShading = (lottie::RenderTreeNodeContent::SolidShading *)shading->fill->shading.get();
|
||||
if (solidShading->opacity != 0.0) {
|
||||
context->fillPath(path, rule, lottieRendering::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity));
|
||||
}
|
||||
} else if (shading->fill->shading->type() == lottie::RenderTreeNodeContent::ShadingType::Gradient) {
|
||||
lottie::RenderTreeNodeContent::GradientShading *gradientShading = (lottie::RenderTreeNodeContent::GradientShading *)shading->fill->shading.get();
|
||||
|
||||
if (gradientShading->opacity != 0.0) {
|
||||
std::vector<lottieRendering::Color> colors;
|
||||
std::vector<double> locations;
|
||||
for (const auto &color : gradientShading->colors) {
|
||||
colors.push_back(lottieRendering::Color(color.r, color.g, color.b, color.a * gradientShading->opacity));
|
||||
}
|
||||
locations = gradientShading->locations;
|
||||
|
||||
lottieRendering::Gradient gradient(colors, locations);
|
||||
lottie::Vector2D start(gradientShading->start.x, gradientShading->start.y);
|
||||
lottie::Vector2D end(gradientShading->end.x, gradientShading->end.y);
|
||||
|
||||
switch (gradientShading->gradientType) {
|
||||
case lottie::GradientType::Linear: {
|
||||
context->linearGradientFillPath(path, rule, gradient, start, end);
|
||||
break;
|
||||
}
|
||||
case lottie::GradientType::Radial: {
|
||||
context->radialGradientFillPath(path, rule, gradient, start, 0.0, start, start.distanceTo(end));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> parentContext, lottie::Vector2D const &globalSize, double parentAlpha) {
|
||||
if (!node->renderData.isValid) {
|
||||
return;
|
||||
@ -442,9 +663,12 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
|
||||
|
||||
currentContext->setAlpha(renderAlpha);
|
||||
|
||||
if (node->content()) {
|
||||
if (node->content() && (int64_t)"" < 0) {
|
||||
drawLottieRenderableItem(currentContext, node->content());
|
||||
}
|
||||
if (node->_contentItem) {//} && (int64_t)"" < 0) {
|
||||
drawLottieContentItem(currentContext, node->_contentItem);
|
||||
}
|
||||
|
||||
if (node->renderData.isInvertedMatte) {
|
||||
currentContext->fill(lottie::CGRect(node->renderData.layer.bounds().x, node->renderData.layer.bounds().y, node->renderData.layer.bounds().width, node->renderData.layer.bounds().height), lottieRendering::Color(0.0, 0.0, 0.0, 1.0));
|
||||
|
@ -103,6 +103,11 @@ func processDrawAnimation(baseCachePath: String, path: String, name: String, siz
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/*if #available(iOS 16.0, *) {
|
||||
try? await Task.sleep(for: .seconds(0.1))
|
||||
}*/
|
||||
|
||||
if !frameResult {
|
||||
return false
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ private final class ReferenceCompareTest {
|
||||
}
|
||||
|
||||
var continueFromName: String?
|
||||
//continueFromName = "1258816259754282.json"
|
||||
//continueFromName = "35707580709863498.json"
|
||||
|
||||
let _ = await processAnimationFolderAsync(basePath: bundlePath, path: "", stopOnFailure: true, process: { path, name, alwaysDraw in
|
||||
if let continueFromNameValue = continueFromName {
|
||||
@ -119,7 +119,7 @@ public final class ViewController: UIViewController {
|
||||
|
||||
self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
|
||||
|
||||
if !"".isEmpty {
|
||||
if "".isEmpty {
|
||||
if #available(iOS 13.0, *) {
|
||||
self.test = ReferenceCompareTest(view: self.view)
|
||||
}
|
||||
|
@ -1072,6 +1072,8 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
|
||||
private var processedDidAppear: Bool = false
|
||||
private var processedDidDisappear: Bool = false
|
||||
|
||||
private var isActiveDisposable: Disposable?
|
||||
|
||||
override public var overlayWantsToBeBelowKeyboard: Bool {
|
||||
if let componentView = self.node.hostView.componentView as? ChatSendMessageContextScreenComponent.View {
|
||||
return componentView.wantsToBeBelowKeyboard()
|
||||
@ -1136,6 +1138,16 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
|
||||
|
||||
self.lockOrientation = true
|
||||
self.blocksBackgroundWhenInOverlay = true
|
||||
|
||||
self.isActiveDisposable = (context.sharedContext.applicationBindings.applicationInForeground
|
||||
|> filter { !$0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.dismiss()
|
||||
})
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
@ -1143,6 +1155,7 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.isActiveDisposable?.dispose()
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <LottieCpp/ShapeAttributes.h>
|
||||
#include <LottieCpp/BezierPath.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace lottie {
|
||||
|
||||
class RenderableItem {
|
||||
@ -229,14 +231,7 @@ public:
|
||||
CGRect bounds;
|
||||
};
|
||||
|
||||
class RenderTreeNodeContentItem {
|
||||
public:
|
||||
RenderTreeNodeContentItem() {
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<std::shared_ptr<RenderTreeNodeContentItem>> subItems;
|
||||
};
|
||||
class RenderTreeNodeContentItem;
|
||||
|
||||
class RenderTreeNodeContent {
|
||||
public:
|
||||
@ -360,6 +355,30 @@ public:
|
||||
std::shared_ptr<Fill> fill;
|
||||
};
|
||||
|
||||
class RenderTreeNodeContentShadingVariant {
|
||||
public:
|
||||
RenderTreeNodeContentShadingVariant() {
|
||||
}
|
||||
|
||||
public:
|
||||
std::shared_ptr<RenderTreeNodeContent::Stroke> stroke;
|
||||
std::shared_ptr<RenderTreeNodeContent::Fill> fill;
|
||||
std::optional<std::vector<BezierPath>> explicitPath;
|
||||
|
||||
size_t subItemLimit = 0;
|
||||
bool isGroup = false;
|
||||
};
|
||||
|
||||
class RenderTreeNodeContentItem {
|
||||
public:
|
||||
RenderTreeNodeContentItem() {
|
||||
}
|
||||
|
||||
public:
|
||||
bool isGroup = false;
|
||||
std::vector<std::shared_ptr<RenderTreeNodeContentShadingVariant>> shadings;
|
||||
};
|
||||
|
||||
class ProcessedRenderTreeNodeData {
|
||||
public:
|
||||
struct LayerParams {
|
||||
@ -518,6 +537,7 @@ public:
|
||||
bool _masksToBounds = false;
|
||||
bool _isHidden = false;
|
||||
std::shared_ptr<RenderTreeNodeContent> _content;
|
||||
std::shared_ptr<RenderTreeNodeContentItem> _contentItem;
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> _subnodes;
|
||||
std::shared_ptr<RenderTreeNode> _mask;
|
||||
bool _invertMask = false;
|
||||
|
@ -899,7 +899,7 @@ public:
|
||||
std::shared_ptr<RenderTreeNode> _renderTree;
|
||||
|
||||
private:
|
||||
std::vector<TransformedPath> collectPaths(AnimationFrameTime frameTime, size_t subItemLimit, CATransform3D parentTransform) {
|
||||
std::vector<TransformedPath> collectPaths(size_t subItemLimit, CATransform3D parentTransform) {
|
||||
std::vector<TransformedPath> mappedPaths;
|
||||
|
||||
CATransform3D effectiveTransform = parentTransform;
|
||||
@ -908,7 +908,6 @@ public:
|
||||
size_t maxSubitem = std::min(subItems.size(), subItemLimit);
|
||||
|
||||
if (path) {
|
||||
path->update(frameTime);
|
||||
mappedPaths.emplace_back(*(path->currentPath()), effectiveTransform);
|
||||
}
|
||||
|
||||
@ -917,17 +916,19 @@ public:
|
||||
CATransform3D subItemTransform = effectiveChildTransform;
|
||||
|
||||
if (subItem->isGroup && subItem->transform) {
|
||||
subItem->transform->update(frameTime);
|
||||
//update?
|
||||
//subItem->transform->update(frameTime);
|
||||
subItemTransform = subItem->transform->transform() * subItemTransform;
|
||||
}
|
||||
|
||||
std::optional<TrimParams> currentTrim;
|
||||
if (!trims.empty()) {
|
||||
trims[0]->update(frameTime);
|
||||
//update?
|
||||
//trims[0]->update(frameTime);
|
||||
currentTrim = trims[0]->trimParams();
|
||||
}
|
||||
|
||||
auto subItemPaths = subItem->collectPaths(frameTime, INT32_MAX, subItemTransform);
|
||||
auto subItemPaths = subItem->collectPaths(INT32_MAX, subItemTransform);
|
||||
|
||||
if (currentTrim) {
|
||||
CompoundBezierPath tempPath;
|
||||
@ -986,6 +987,9 @@ public:
|
||||
false
|
||||
);
|
||||
|
||||
_renderTree->_contentItem = std::make_shared<RenderTreeNodeContentItem>();
|
||||
_renderTree->_contentItem->isGroup = isGroup;
|
||||
|
||||
if (!shadings.empty()) {
|
||||
for (int i = 0; i < shadings.size(); i++) {
|
||||
auto &shadingVariant = shadings[i];
|
||||
@ -1008,6 +1012,28 @@ public:
|
||||
);
|
||||
shadingVariant.renderTree = shadingRenderTree;
|
||||
_renderTree->_subnodes.push_back(shadingRenderTree);
|
||||
|
||||
auto itemShadingVariant = std::make_shared<RenderTreeNodeContentShadingVariant>();
|
||||
if (shadingVariant.fill) {
|
||||
itemShadingVariant->fill = std::make_shared<RenderTreeNodeContent::Fill>(
|
||||
nullptr,
|
||||
FillRule::NonZeroWinding
|
||||
);
|
||||
}
|
||||
if (shadingVariant.stroke) {
|
||||
itemShadingVariant->stroke = std::make_shared<RenderTreeNodeContent::Stroke>(
|
||||
nullptr,
|
||||
0.0,
|
||||
LineJoin::Bevel,
|
||||
LineCap::Round,
|
||||
0.0,
|
||||
0.0,
|
||||
std::vector<double>()
|
||||
);
|
||||
}
|
||||
itemShadingVariant->subItemLimit = shadingVariant.subItemLimit;
|
||||
|
||||
_renderTree->_contentItem->shadings.push_back(itemShadingVariant);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1036,11 +1062,36 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
void updateChildren(AnimationFrameTime frameTime, std::optional<TrimParams> parentTrim) {
|
||||
void updateFrame(AnimationFrameTime frameTime) {
|
||||
if (transform) {
|
||||
transform->update(frameTime);
|
||||
}
|
||||
|
||||
if (path) {
|
||||
path->update(frameTime);
|
||||
}
|
||||
for (const auto &trim : trims) {
|
||||
trim->update(frameTime);
|
||||
}
|
||||
|
||||
for (const auto &shadingVariant : shadings) {
|
||||
if (shadingVariant.fill) {
|
||||
shadingVariant.fill->update(frameTime);
|
||||
}
|
||||
if (shadingVariant.stroke) {
|
||||
shadingVariant.stroke->update(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &subItem : subItems) {
|
||||
subItem->updateFrame(frameTime);
|
||||
}
|
||||
}
|
||||
|
||||
void updateChildren(std::optional<TrimParams> parentTrim) {
|
||||
CATransform3D containerTransform = CATransform3D::identity();
|
||||
double containerOpacity = 1.0;
|
||||
if (transform) {
|
||||
transform->update(frameTime);
|
||||
containerTransform = transform->transform();
|
||||
containerOpacity = transform->opacity();
|
||||
}
|
||||
@ -1055,7 +1106,7 @@ public:
|
||||
}
|
||||
|
||||
CompoundBezierPath compoundPath;
|
||||
auto paths = collectPaths(frameTime, shadingVariant.subItemLimit, CATransform3D::identity());
|
||||
auto paths = collectPaths(shadingVariant.subItemLimit, CATransform3D::identity());
|
||||
for (const auto &path : paths) {
|
||||
compoundPath.appendPath(path.path.copyUsingTransform(path.transform));
|
||||
}
|
||||
@ -1079,13 +1130,11 @@ public:
|
||||
|
||||
std::shared_ptr<RenderTreeNodeContent::Fill> fill;
|
||||
if (shadingVariant.fill) {
|
||||
shadingVariant.fill->update(frameTime);
|
||||
fill = shadingVariant.fill->fill();
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTreeNodeContent::Stroke> stroke;
|
||||
if (shadingVariant.stroke) {
|
||||
shadingVariant.stroke->update(frameTime);
|
||||
stroke = shadingVariant.stroke->stroke();
|
||||
}
|
||||
|
||||
@ -1096,14 +1145,16 @@ public:
|
||||
);
|
||||
|
||||
shadingVariant.renderTree->_content = content;
|
||||
|
||||
_renderTree->_contentItem->shadings[i]->stroke = stroke;
|
||||
_renderTree->_contentItem->shadings[i]->fill = fill;
|
||||
_renderTree->_contentItem->shadings[i]->explicitPath = resultPaths;
|
||||
}
|
||||
|
||||
if (isGroup && !subItems.empty()) {
|
||||
for (int i = (int)subItems.size() - 1; i >= 0; i--) {
|
||||
std::optional<TrimParams> childTrim = parentTrim;
|
||||
for (const auto &trim : trims) {
|
||||
trim->update(frameTime);
|
||||
|
||||
if (i < (int)trim->trimParams().subItemLimit) {
|
||||
//TODO:allow combination
|
||||
//assert(!parentTrim);
|
||||
@ -1111,7 +1162,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
subItems[i]->updateChildren(frameTime, childTrim);
|
||||
subItems[i]->updateChildren(childTrim);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1284,14 +1335,16 @@ CompositionLayer(solidLayer, Vector2D::Zero()) {
|
||||
void ShapeCompositionLayer::displayContentsWithFrame(double frame, bool forceUpdates) {
|
||||
_frameTime = frame;
|
||||
_frameTimeInitialized = true;
|
||||
_contentTree->itemTree->updateChildren(_frameTime, std::nullopt);
|
||||
_contentTree->itemTree->updateFrame(_frameTime);
|
||||
_contentTree->itemTree->updateChildren(std::nullopt);
|
||||
}
|
||||
|
||||
std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode() {
|
||||
if (!_frameTimeInitialized) {
|
||||
_frameTime = 0.0;
|
||||
_frameTimeInitialized = true;
|
||||
_contentTree->itemTree->updateChildren(_frameTime, std::nullopt);
|
||||
_contentTree->itemTree->updateFrame(_frameTime);
|
||||
_contentTree->itemTree->updateChildren(std::nullopt);
|
||||
}
|
||||
|
||||
if (!_renderTreeNode) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user