mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP]
This commit is contained in:
parent
2d06c977ed
commit
624a3d0c6d
@ -8,8 +8,24 @@
|
|||||||
|
|
||||||
namespace lottie {
|
namespace lottie {
|
||||||
|
|
||||||
static void processRenderContentItem(std::shared_ptr<RenderTreeNodeContentItem> const &contentItem, std::optional<CGRect> &effectiveLocalBounds, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
static void processRenderContentItem(std::shared_ptr<RenderTreeNodeContentItem> const &contentItem, Vector2D const &globalSize, CATransform3D const &parentTransform, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||||
|
auto currentTransform = parentTransform;
|
||||||
|
|
||||||
|
CATransform3D localTransform = contentItem->transform;
|
||||||
|
currentTransform = localTransform * currentTransform;
|
||||||
|
|
||||||
|
if (!currentTransform.isInvertible()) {
|
||||||
|
contentItem->renderData.isValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CGRect> effectiveLocalBounds;
|
||||||
|
|
||||||
|
int drawContentDescendants = 0;
|
||||||
|
|
||||||
for (const auto &shadingVariant : contentItem->shadings) {
|
for (const auto &shadingVariant : contentItem->shadings) {
|
||||||
|
drawContentDescendants += 1;
|
||||||
|
|
||||||
CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shadingVariant->explicitPath.value());
|
CGRect shapeBounds = bezierPathsBoundingBoxParallel(bezierPathsBoundingBoxContext, shadingVariant->explicitPath.value());
|
||||||
if (shadingVariant->stroke) {
|
if (shadingVariant->stroke) {
|
||||||
shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0);
|
shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0);
|
||||||
@ -27,9 +43,86 @@ static void processRenderContentItem(std::shared_ptr<RenderTreeNodeContentItem>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &subItem : contentItem->subItems) {
|
std::optional<CGRect> effectiveLocalRect;
|
||||||
processRenderContentItem(subItem, effectiveLocalBounds, bezierPathsBoundingBoxContext);
|
if (effectiveLocalBounds.has_value()) {
|
||||||
|
effectiveLocalRect = effectiveLocalBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<CGRect> subnodesGlobalRect;
|
||||||
|
|
||||||
|
for (const auto &subItem : contentItem->subItems) {
|
||||||
|
processRenderContentItem(subItem, globalSize, currentTransform, bezierPathsBoundingBoxContext);
|
||||||
|
|
||||||
|
drawContentDescendants += subItem->renderData.drawContentDescendants;
|
||||||
|
|
||||||
|
if (!subItem->renderData.localRect.empty()) {
|
||||||
|
if (effectiveLocalRect.has_value()) {
|
||||||
|
effectiveLocalRect = effectiveLocalRect->unionWith(subItem->renderData.localRect);
|
||||||
|
} else {
|
||||||
|
effectiveLocalRect = subItem->renderData.localRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subnodesGlobalRect) {
|
||||||
|
subnodesGlobalRect = subnodesGlobalRect->unionWith(subItem->renderData.globalRect);
|
||||||
|
} else {
|
||||||
|
subnodesGlobalRect = subItem->renderData.globalRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CGRect> fuzzyGlobalRect;
|
||||||
|
|
||||||
|
if (effectiveLocalBounds) {
|
||||||
|
CGRect effectiveGlobalBounds = effectiveLocalBounds->applyingTransform(currentTransform);
|
||||||
|
if (fuzzyGlobalRect) {
|
||||||
|
fuzzyGlobalRect = fuzzyGlobalRect->unionWith(effectiveGlobalBounds);
|
||||||
|
} else {
|
||||||
|
fuzzyGlobalRect = effectiveGlobalBounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subnodesGlobalRect) {
|
||||||
|
if (fuzzyGlobalRect) {
|
||||||
|
fuzzyGlobalRect = fuzzyGlobalRect->unionWith(subnodesGlobalRect.value());
|
||||||
|
} else {
|
||||||
|
fuzzyGlobalRect = subnodesGlobalRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fuzzyGlobalRect) {
|
||||||
|
contentItem->renderData.isValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect globalRect(
|
||||||
|
std::floor(fuzzyGlobalRect->x),
|
||||||
|
std::floor(fuzzyGlobalRect->y),
|
||||||
|
std::ceil(fuzzyGlobalRect->width + fuzzyGlobalRect->x - floor(fuzzyGlobalRect->x)),
|
||||||
|
std::ceil(fuzzyGlobalRect->height + fuzzyGlobalRect->y - floor(fuzzyGlobalRect->y))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!CGRect(0.0, 0.0, globalSize.x, globalSize.y).intersects(globalRect)) {
|
||||||
|
contentItem->renderData.isValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect localRect = effectiveLocalRect.value_or(CGRect(0.0, 0.0, 0.0, 0.0)).applyingTransform(localTransform);
|
||||||
|
|
||||||
|
contentItem->renderData.isValid = true;
|
||||||
|
|
||||||
|
contentItem->renderData.layer._bounds = CGRect(0.0, 0.0, 0.0, 0.0);
|
||||||
|
contentItem->renderData.layer._position = Vector2D(0.0, 0.0);
|
||||||
|
contentItem->renderData.layer._transform = contentItem->transform;
|
||||||
|
contentItem->renderData.layer._opacity = contentItem->alpha;
|
||||||
|
contentItem->renderData.layer._masksToBounds = false;
|
||||||
|
contentItem->renderData.layer._isHidden = false;
|
||||||
|
|
||||||
|
contentItem->renderData.globalRect = globalRect;
|
||||||
|
contentItem->renderData.localRect = localRect;
|
||||||
|
contentItem->renderData.globalTransform = currentTransform;
|
||||||
|
contentItem->renderData.drawsContent = effectiveLocalBounds.has_value();
|
||||||
|
contentItem->renderData.drawContentDescendants = drawContentDescendants;
|
||||||
|
contentItem->renderData.isInvertedMatte = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vector2D const &globalSize, CATransform3D const &parentTransform, bool isInvertedMask, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vector2D const &globalSize, CATransform3D const &parentTransform, bool isInvertedMask, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||||
@ -58,14 +151,12 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<CGRect> effectiveLocalBounds;
|
|
||||||
|
|
||||||
double alpha = node->alpha();
|
|
||||||
|
|
||||||
if (node->_contentItem) {
|
if (node->_contentItem) {
|
||||||
processRenderContentItem(node->_contentItem, effectiveLocalBounds, bezierPathsBoundingBoxContext);
|
processRenderContentItem(node->_contentItem, globalSize, currentTransform, bezierPathsBoundingBoxContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<CGRect> effectiveLocalBounds;
|
||||||
|
|
||||||
bool isInvertedMatte = isInvertedMask;
|
bool isInvertedMatte = isInvertedMask;
|
||||||
if (isInvertedMatte) {
|
if (isInvertedMatte) {
|
||||||
effectiveLocalBounds = node->bounds();
|
effectiveLocalBounds = node->bounds();
|
||||||
@ -179,7 +270,7 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
|||||||
node->renderData.layer._bounds = node->bounds();
|
node->renderData.layer._bounds = node->bounds();
|
||||||
node->renderData.layer._position = node->position();
|
node->renderData.layer._position = node->position();
|
||||||
node->renderData.layer._transform = node->transform();
|
node->renderData.layer._transform = node->transform();
|
||||||
node->renderData.layer._opacity = alpha;
|
node->renderData.layer._opacity = node->alpha();
|
||||||
node->renderData.layer._masksToBounds = masksToBounds;
|
node->renderData.layer._masksToBounds = masksToBounds;
|
||||||
node->renderData.layer._isHidden = node->isHidden();
|
node->renderData.layer._isHidden = node->isHidden();
|
||||||
|
|
||||||
@ -196,6 +287,9 @@ static void processRenderTree(std::shared_ptr<RenderTreeNode> const &node, Vecto
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> context, std::shared_ptr<lottie::RenderTreeNodeContentItem> item) {
|
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> context, std::shared_ptr<lottie::RenderTreeNodeContentItem> item) {
|
||||||
|
context->saveState();
|
||||||
|
context->concatenate(item->transform);
|
||||||
|
|
||||||
for (const auto &shading : item->shadings) {
|
for (const auto &shading : item->shadings) {
|
||||||
if (shading->explicitPath->empty()) {
|
if (shading->explicitPath->empty()) {
|
||||||
continue;
|
continue;
|
||||||
@ -366,6 +460,8 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> conte
|
|||||||
for (const auto &subItem : item->subItems) {
|
for (const auto &subItem : item->subItems) {
|
||||||
drawLottieContentItem(context, subItem);
|
drawLottieContentItem(context, subItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context->restoreState();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> parentContext, lottie::Vector2D const &globalSize, double parentAlpha) {
|
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> parentContext, lottie::Vector2D const &globalSize, double parentAlpha) {
|
||||||
|
@ -13,6 +13,86 @@
|
|||||||
|
|
||||||
namespace lottie {
|
namespace lottie {
|
||||||
|
|
||||||
|
class ProcessedRenderTreeNodeData {
|
||||||
|
public:
|
||||||
|
struct LayerParams {
|
||||||
|
CGRect _bounds;
|
||||||
|
Vector2D _position;
|
||||||
|
CATransform3D _transform;
|
||||||
|
double _opacity;
|
||||||
|
bool _masksToBounds;
|
||||||
|
bool _isHidden;
|
||||||
|
|
||||||
|
LayerParams(
|
||||||
|
CGRect bounds_,
|
||||||
|
Vector2D position_,
|
||||||
|
CATransform3D transform_,
|
||||||
|
double opacity_,
|
||||||
|
bool masksToBounds_,
|
||||||
|
bool isHidden_
|
||||||
|
) :
|
||||||
|
_bounds(bounds_),
|
||||||
|
_position(position_),
|
||||||
|
_transform(transform_),
|
||||||
|
_opacity(opacity_),
|
||||||
|
_masksToBounds(masksToBounds_),
|
||||||
|
_isHidden(isHidden_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect bounds() const {
|
||||||
|
return _bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D position() const {
|
||||||
|
return _position;
|
||||||
|
}
|
||||||
|
|
||||||
|
CATransform3D transform() const {
|
||||||
|
return _transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
double opacity() const {
|
||||||
|
return _opacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool masksToBounds() const {
|
||||||
|
return _masksToBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHidden() const {
|
||||||
|
return _isHidden;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ProcessedRenderTreeNodeData() :
|
||||||
|
isValid(false),
|
||||||
|
layer(
|
||||||
|
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||||
|
Vector2D(0.0, 0.0),
|
||||||
|
CATransform3D::identity(),
|
||||||
|
1.0,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
globalRect(CGRect(0.0, 0.0, 0.0, 0.0)),
|
||||||
|
localRect(CGRect(0.0, 0.0, 0.0, 0.0)),
|
||||||
|
globalTransform(CATransform3D::identity()),
|
||||||
|
drawsContent(false),
|
||||||
|
drawContentDescendants(false),
|
||||||
|
isInvertedMatte(false) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid = false;
|
||||||
|
LayerParams layer;
|
||||||
|
CGRect globalRect;
|
||||||
|
CGRect localRect;
|
||||||
|
CATransform3D globalTransform;
|
||||||
|
bool drawsContent;
|
||||||
|
int drawContentDescendants;
|
||||||
|
bool isInvertedMatte;
|
||||||
|
};
|
||||||
|
|
||||||
class RenderableItem {
|
class RenderableItem {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
@ -345,8 +425,11 @@ public:
|
|||||||
public:
|
public:
|
||||||
bool isGroup = false;
|
bool isGroup = false;
|
||||||
CATransform3D transform = CATransform3D::identity();
|
CATransform3D transform = CATransform3D::identity();
|
||||||
|
double alpha = 0.0;
|
||||||
std::vector<std::shared_ptr<RenderTreeNodeContentShadingVariant>> shadings;
|
std::vector<std::shared_ptr<RenderTreeNodeContentShadingVariant>> shadings;
|
||||||
std::vector<std::shared_ptr<RenderTreeNodeContentItem>> subItems;
|
std::vector<std::shared_ptr<RenderTreeNodeContentItem>> subItems;
|
||||||
|
|
||||||
|
ProcessedRenderTreeNodeData renderData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderTreeNodeContentShadingVariant {
|
class RenderTreeNodeContentShadingVariant {
|
||||||
@ -362,86 +445,6 @@ public:
|
|||||||
size_t subItemLimit = 0;
|
size_t subItemLimit = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProcessedRenderTreeNodeData {
|
|
||||||
public:
|
|
||||||
struct LayerParams {
|
|
||||||
CGRect _bounds;
|
|
||||||
Vector2D _position;
|
|
||||||
CATransform3D _transform;
|
|
||||||
double _opacity;
|
|
||||||
bool _masksToBounds;
|
|
||||||
bool _isHidden;
|
|
||||||
|
|
||||||
LayerParams(
|
|
||||||
CGRect bounds_,
|
|
||||||
Vector2D position_,
|
|
||||||
CATransform3D transform_,
|
|
||||||
double opacity_,
|
|
||||||
bool masksToBounds_,
|
|
||||||
bool isHidden_
|
|
||||||
) :
|
|
||||||
_bounds(bounds_),
|
|
||||||
_position(position_),
|
|
||||||
_transform(transform_),
|
|
||||||
_opacity(opacity_),
|
|
||||||
_masksToBounds(masksToBounds_),
|
|
||||||
_isHidden(isHidden_) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CGRect bounds() const {
|
|
||||||
return _bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D position() const {
|
|
||||||
return _position;
|
|
||||||
}
|
|
||||||
|
|
||||||
CATransform3D transform() const {
|
|
||||||
return _transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
double opacity() const {
|
|
||||||
return _opacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool masksToBounds() const {
|
|
||||||
return _masksToBounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isHidden() const {
|
|
||||||
return _isHidden;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ProcessedRenderTreeNodeData() :
|
|
||||||
isValid(false),
|
|
||||||
layer(
|
|
||||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
|
||||||
Vector2D(0.0, 0.0),
|
|
||||||
CATransform3D::identity(),
|
|
||||||
1.0,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
globalRect(CGRect(0.0, 0.0, 0.0, 0.0)),
|
|
||||||
localRect(CGRect(0.0, 0.0, 0.0, 0.0)),
|
|
||||||
globalTransform(CATransform3D::identity()),
|
|
||||||
drawsContent(false),
|
|
||||||
drawContentDescendants(false),
|
|
||||||
isInvertedMatte(false) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValid = false;
|
|
||||||
LayerParams layer;
|
|
||||||
CGRect globalRect;
|
|
||||||
CGRect localRect;
|
|
||||||
CATransform3D globalTransform;
|
|
||||||
bool drawsContent;
|
|
||||||
int drawContentDescendants;
|
|
||||||
bool isInvertedMatte;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RenderTreeNode {
|
class RenderTreeNode {
|
||||||
public:
|
public:
|
||||||
RenderTreeNode(
|
RenderTreeNode(
|
||||||
|
@ -1034,10 +1034,10 @@ public:
|
|||||||
for (int i = (int)subItems.size() - 1; i >= 0; i--) {
|
for (int i = (int)subItems.size() - 1; i >= 0; i--) {
|
||||||
subItems[i]->initializeRenderChildren();
|
subItems[i]->initializeRenderChildren();
|
||||||
subItemNodes.push_back(subItems[i]->_renderTree);
|
subItemNodes.push_back(subItems[i]->_renderTree);
|
||||||
//_renderTree->_contentItem->subItems.push_back(subItems[i]->_renderTree->_contentItem);
|
_renderTree->_contentItem->subItems.push_back(subItems[i]->_renderTree->_contentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subItemNodes.empty()) {
|
/*if (!subItemNodes.empty()) {
|
||||||
_renderTree->_subnodes.push_back(std::make_shared<RenderTreeNode>(
|
_renderTree->_subnodes.push_back(std::make_shared<RenderTreeNode>(
|
||||||
CGRect(0.0, 0.0, 0.0, 0.0),
|
CGRect(0.0, 0.0, 0.0, 0.0),
|
||||||
Vector2D(0.0, 0.0),
|
Vector2D(0.0, 0.0),
|
||||||
@ -1049,7 +1049,7 @@ public:
|
|||||||
nullptr,
|
nullptr,
|
||||||
false
|
false
|
||||||
));
|
));
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1087,6 +1087,9 @@ public:
|
|||||||
containerTransform = transform->transform();
|
containerTransform = transform->transform();
|
||||||
containerOpacity = transform->opacity();
|
containerOpacity = transform->opacity();
|
||||||
}
|
}
|
||||||
|
_renderTree->_contentItem->transform = containerTransform;
|
||||||
|
_renderTree->_contentItem->alpha = containerOpacity;
|
||||||
|
|
||||||
_renderTree->_transform = containerTransform;
|
_renderTree->_transform = containerTransform;
|
||||||
_renderTree->_alpha = containerOpacity;
|
_renderTree->_alpha = containerOpacity;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user