mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Refactoring
This commit is contained in:
parent
62d58b3bdd
commit
1f1509a64c
@ -81,7 +81,7 @@ public:
|
||||
|
||||
virtual void setAlpha(float alpha) = 0;
|
||||
|
||||
virtual void concatenate(lottie::Transform3D const &transform) = 0;
|
||||
virtual void concatenate(lottie::Transform2D const &transform) = 0;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) = 0;
|
||||
};
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
virtual void fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override;
|
||||
virtual void setBlendMode(BlendMode blendMode) override;
|
||||
virtual void setAlpha(float alpha) override;
|
||||
virtual void concatenate(lottie::Transform3D const &transform) override;
|
||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||
|
||||
virtual std::shared_ptr<Image> makeImage() const;
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
@ -509,7 +509,7 @@ void CanvasImpl::setAlpha(float alpha) {
|
||||
CGContextSetAlpha(_context, alpha);
|
||||
}
|
||||
|
||||
void CanvasImpl::concatenate(lottie::Transform3D const &transform) {
|
||||
void CanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||
CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform)));
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
|
||||
virtual void setAlpha(float alpha) override;
|
||||
|
||||
virtual void concatenate(lottie::Transform3D const &transform) override;
|
||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
||||
@ -39,7 +39,7 @@ public:
|
||||
private:
|
||||
float _width = 0.0f;
|
||||
float _height = 0.0f;
|
||||
lottie::Transform3D _transform;
|
||||
lottie::Transform2D _transform;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ void addEnumeratedPath(CanvasPathEnumerator const &enumeratePath) {
|
||||
}
|
||||
|
||||
NullCanvasImpl::NullCanvasImpl(int width, int height) :
|
||||
_width(width), _height(height), _transform(lottie::Transform3D::identity()) {
|
||||
_width(width), _height(height), _transform(lottie::Transform2D::identity()) {
|
||||
}
|
||||
|
||||
NullCanvasImpl::~NullCanvasImpl() {
|
||||
@ -69,7 +69,7 @@ void NullCanvasImpl::setBlendMode(BlendMode blendMode) {
|
||||
void NullCanvasImpl::setAlpha(float alpha) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::concatenate(lottie::Transform3D const &transform) {
|
||||
void NullCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
||||
|
@ -15,17 +15,17 @@ static constexpr float minGlobalRectCalculationSize = 200.0f;
|
||||
|
||||
struct TransformedPath {
|
||||
lottie::BezierPath path;
|
||||
lottie::Transform3D transform;
|
||||
lottie::Transform2D transform;
|
||||
|
||||
TransformedPath(lottie::BezierPath const &path_, lottie::Transform3D const &transform_) :
|
||||
TransformedPath(lottie::BezierPath const &path_, lottie::Transform2D const &transform_) :
|
||||
path(path_),
|
||||
transform(transform_) {
|
||||
}
|
||||
};
|
||||
|
||||
static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::Transform3D const &parentTransform, bool skipApplyTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::Transform2D const &parentTransform, bool skipApplyTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
//TODO:remove skipApplyTransform
|
||||
lottie::Transform3D effectiveTransform = parentTransform;
|
||||
lottie::Transform2D effectiveTransform = parentTransform;
|
||||
if (!skipApplyTransform && item->isGroup) {
|
||||
effectiveTransform = item->transform * effectiveTransform;
|
||||
}
|
||||
@ -56,9 +56,9 @@ static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTre
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
static void enumeratePaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::Transform3D const &parentTransform, bool skipApplyTransform, std::function<void(lottie::BezierPath const &path, lottie::Transform3D const &transform)> const &onPath) {
|
||||
static void enumeratePaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::Transform2D const &parentTransform, bool skipApplyTransform, std::function<void(lottie::BezierPath const &path, lottie::Transform2D const &transform)> const &onPath) {
|
||||
//TODO:remove skipApplyTransform
|
||||
lottie::Transform3D effectiveTransform = parentTransform;
|
||||
lottie::Transform2D effectiveTransform = parentTransform;
|
||||
if (!skipApplyTransform && item->isGroup) {
|
||||
effectiveTransform = item->transform * effectiveTransform;
|
||||
}
|
||||
@ -80,14 +80,14 @@ static void enumeratePaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> it
|
||||
|
||||
namespace lottie {
|
||||
|
||||
static std::optional<CGRect> getRenderContentItemGlobalRect(std::shared_ptr<RenderTreeNodeContentItem> const &contentItem, lottie::Vector2D const &globalSize, lottie::Transform3D const &parentTransform, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
static std::optional<CGRect> getRenderContentItemGlobalRect(std::shared_ptr<RenderTreeNodeContentItem> const &contentItem, lottie::Vector2D const &globalSize, lottie::Transform2D const &parentTransform, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
auto currentTransform = parentTransform;
|
||||
Transform3D localTransform = contentItem->transform;
|
||||
Transform2D localTransform = contentItem->transform;
|
||||
currentTransform = localTransform * currentTransform;
|
||||
|
||||
std::optional<CGRect> globalRect;
|
||||
for (const auto &shadingVariant : contentItem->shadings) {
|
||||
lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::Transform3D::identity(), true, bezierPathsBoundingBoxContext);
|
||||
lottie::CGRect shapeBounds = collectPathBoundingBoxes(contentItem, shadingVariant->subItemLimit, lottie::Transform2D::identity(), true, bezierPathsBoundingBoxContext);
|
||||
|
||||
if (shadingVariant->stroke) {
|
||||
shapeBounds = shapeBounds.insetBy(-shadingVariant->stroke->lineWidth / 2.0, -shadingVariant->stroke->lineWidth / 2.0);
|
||||
@ -128,13 +128,13 @@ static std::optional<CGRect> getRenderContentItemGlobalRect(std::shared_ptr<Rend
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<CGRect> getRenderNodeGlobalRect(std::shared_ptr<RenderTreeNode> const &node, lottie::Vector2D const &globalSize, lottie::Transform3D const &parentTransform, bool isInvertedMatte, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
static std::optional<CGRect> getRenderNodeGlobalRect(std::shared_ptr<RenderTreeNode> const &node, lottie::Vector2D const &globalSize, lottie::Transform2D const &parentTransform, bool isInvertedMatte, BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
if (node->isHidden() || node->alpha() < minVisibleAlpha) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto currentTransform = parentTransform;
|
||||
Transform3D localTransform = node->transform();
|
||||
Transform2D localTransform = node->transform();
|
||||
currentTransform = localTransform * currentTransform;
|
||||
|
||||
std::optional<CGRect> globalRect;
|
||||
@ -179,9 +179,9 @@ static std::optional<CGRect> getRenderNodeGlobalRect(std::shared_ptr<RenderTreeN
|
||||
|
||||
namespace {
|
||||
|
||||
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> const &parentContext, std::shared_ptr<lottie::RenderTreeNodeContentItem> item, float parentAlpha, lottie::Vector2D const &globalSize, lottie::Transform3D const &parentTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> const &parentContext, std::shared_ptr<lottie::RenderTreeNodeContentItem> item, float parentAlpha, lottie::Vector2D const &globalSize, lottie::Transform2D const &parentTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
auto currentTransform = parentTransform;
|
||||
lottie::Transform3D localTransform = item->transform;
|
||||
lottie::Transform2D localTransform = item->transform;
|
||||
currentTransform = localTransform * currentTransform;
|
||||
|
||||
float normalizedOpacity = item->alpha;
|
||||
@ -215,7 +215,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> const
|
||||
tempContext = tempContextValue;
|
||||
|
||||
currentContext = &tempContext;
|
||||
(*currentContext)->concatenate(lottie::Transform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
(*currentContext)->concatenate(lottie::Transform2D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
|
||||
(*currentContext)->saveState();
|
||||
(*currentContext)->concatenate(currentTransform);
|
||||
@ -268,7 +268,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> const
|
||||
};
|
||||
} else {
|
||||
iteratePaths = [&](std::function<void(lottieRendering::PathCommand const &)> iterate) {
|
||||
enumeratePaths(item, shading->subItemLimit, lottie::Transform3D::identity(), true, [&](lottie::BezierPath const &sourcePath, lottie::Transform3D const &transform) {
|
||||
enumeratePaths(item, shading->subItemLimit, lottie::Transform2D::identity(), true, [&](lottie::BezierPath const &sourcePath, lottie::Transform2D const &transform) {
|
||||
auto path = sourcePath.copyUsingTransform(transform);
|
||||
|
||||
lottieRendering::PathCommand pathCommand;
|
||||
@ -456,7 +456,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> const
|
||||
parentContext->restoreState();
|
||||
}
|
||||
|
||||
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> const &parentContext, lottie::Vector2D const &globalSize, lottie::Transform3D const &parentTransform, float parentAlpha, bool isInvertedMatte, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> const &parentContext, lottie::Vector2D const &globalSize, lottie::Transform2D const &parentTransform, float parentAlpha, bool isInvertedMatte, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
float normalizedOpacity = node->alpha();
|
||||
float layerAlpha = ((float)normalizedOpacity) * parentAlpha;
|
||||
|
||||
@ -465,7 +465,7 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
|
||||
}
|
||||
|
||||
auto currentTransform = parentTransform;
|
||||
lottie::Transform3D localTransform = node->transform();
|
||||
lottie::Transform2D localTransform = node->transform();
|
||||
currentTransform = localTransform * currentTransform;
|
||||
|
||||
std::shared_ptr<lottieRendering::Canvas> maskContext;
|
||||
@ -507,7 +507,7 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
|
||||
if ((node->mask() && !node->mask()->isHidden() && node->mask()->alpha() >= minVisibleAlpha) || masksToBounds) {
|
||||
auto maskBackingStorage = parentContext->makeLayer((int)(globalRect->width), (int)(globalRect->height));
|
||||
|
||||
maskBackingStorage->concatenate(lottie::Transform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
maskBackingStorage->concatenate(lottie::Transform2D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
maskBackingStorage->concatenate(currentTransform);
|
||||
|
||||
if (masksToBounds) {
|
||||
@ -524,7 +524,7 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
|
||||
tempContext = tempContextValue;
|
||||
|
||||
currentContext = tempContextValue;
|
||||
currentContext->concatenate(lottie::Transform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
currentContext->concatenate(lottie::Transform2D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
|
||||
currentContext->saveState();
|
||||
currentContext->concatenate(currentTransform);
|
||||
@ -602,13 +602,13 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
lottie::Transform3D rootTransform = lottie::Transform3D::identity().scaled(lottie::Vector2D(size.width / (float)animation.size.width, size.height / (float)animation.size.height));
|
||||
lottie::Transform2D rootTransform = lottie::Transform2D::identity().scaled(lottie::Vector2D(size.width / (float)animation.size.width, size.height / (float)animation.size.height));
|
||||
|
||||
if (useReferenceRendering) {
|
||||
auto context = std::make_shared<lottieRendering::CanvasImpl>((int)size.width, (int)size.height);
|
||||
|
||||
CGPoint scale = CGPointMake(size.width / (CGFloat)animation.size.width, size.height / (CGFloat)animation.size.height);
|
||||
context->concatenate(lottie::Transform3D::makeScale(scale.x, scale.y, 1.0));
|
||||
context->concatenate(lottie::Transform2D::makeScale(scale.x, scale.y));
|
||||
|
||||
renderLottieRenderNode(renderNode, context, lottie::Vector2D(context->width(), context->height()), rootTransform, 1.0, false, *_bezierPathsBoundingBoxContext.get());
|
||||
|
||||
@ -620,7 +620,7 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
auto context = std::make_shared<lottieRendering::NullCanvasImpl>((int)size.width, (int)size.height);
|
||||
|
||||
CGPoint scale = CGPointMake(size.width / (CGFloat)animation.size.width, size.height / (CGFloat)animation.size.height);
|
||||
context->concatenate(lottie::Transform3D::makeScale(scale.x, scale.y, 1.0));
|
||||
context->concatenate(lottie::Transform2D::makeScale(scale.x, scale.y));
|
||||
|
||||
renderLottieRenderNode(renderNode, context, lottie::Vector2D(context->width(), context->height()), rootTransform, 1.0, false, *_bezierPathsBoundingBoxContext.get());
|
||||
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
|
||||
virtual void setAlpha(float alpha) override;
|
||||
|
||||
virtual void concatenate(lottie::Transform3D const &transform) override;
|
||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
||||
@ -52,8 +52,8 @@ private:
|
||||
std::unique_ptr<tvg::SwCanvas> _canvas;
|
||||
|
||||
float _alpha = 1.0;
|
||||
lottie::Transform3D _transform;
|
||||
std::vector<lottie::Transform3D> _stateStack;
|
||||
lottie::Transform2D _transform;
|
||||
std::vector<lottie::Transform2D> _stateStack;
|
||||
int _bytesPerRow = 0;
|
||||
uint32_t *_backingData = nullptr;
|
||||
int _statsNumStrokes = 0;
|
||||
|
@ -27,7 +27,7 @@ void tvgPath(CanvasPathEnumerator const &enumeratePath, tvg::Shape *shape) {
|
||||
});
|
||||
}
|
||||
|
||||
tvg::Matrix tvgTransform(lottie::Transform3D const &transform) {
|
||||
tvg::Matrix tvgTransform(lottie::Transform2D const &transform) {
|
||||
CGAffineTransform affineTransform = CATransform3DGetAffineTransform(lottie::nativeTransform(transform));
|
||||
tvg::Matrix result;
|
||||
result.e11 = affineTransform.a;
|
||||
@ -45,7 +45,7 @@ tvg::Matrix tvgTransform(lottie::Transform3D const &transform) {
|
||||
}
|
||||
|
||||
ThorVGCanvasImpl::ThorVGCanvasImpl(int width, int height) :
|
||||
_width(width), _height(height), _transform(lottie::Transform3D::identity()) {
|
||||
_width(width), _height(height), _transform(lottie::Transform2D::identity()) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
tvg::Initializer::init(0);
|
||||
@ -259,7 +259,7 @@ void ThorVGCanvasImpl::setAlpha(float alpha) {
|
||||
_alpha = alpha;
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::concatenate(lottie::Transform3D const &transform) {
|
||||
void ThorVGCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||
_transform = transform * _transform;
|
||||
/*_canvas->concat(SkM44(
|
||||
transform.m11, transform.m21, transform.m31, transform.m41,
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
std::optional<bool> const &closed() const;
|
||||
void setClosed(std::optional<bool> const &closed);
|
||||
std::shared_ptr<CGPath> cgPath() const;
|
||||
BezierPath copyUsingTransform(Transform3D const &transform) const;
|
||||
BezierPath copyUsingTransform(Transform2D const &transform) const;
|
||||
|
||||
public:
|
||||
BezierPath(std::shared_ptr<BezierPathContents> contents);
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
|
||||
virtual bool empty() const = 0;
|
||||
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform3D const &transform) const = 0;
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform2D const &transform) const = 0;
|
||||
|
||||
virtual void addLineTo(Vector2D const &point) = 0;
|
||||
virtual void addCurveTo(Vector2D const &point, Vector2D const &control1, Vector2D const &control2) = 0;
|
||||
@ -71,7 +71,7 @@ public:
|
||||
virtual bool isEqual(CGPath *other) const = 0;
|
||||
};
|
||||
|
||||
Vector2D transformVector(Vector2D const &v, Transform3D const &m);
|
||||
Vector2D transformVector(Vector2D const &v, Transform2D const &m);
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
|
||||
virtual bool empty() const override;
|
||||
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform3D const &transform) const override;
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform2D const &transform) const override;
|
||||
|
||||
virtual void addLineTo(Vector2D const &point) override;
|
||||
virtual void addCurveTo(Vector2D const &point, Vector2D const &control1, Vector2D const &control2) override;
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
return CurveVertex(point + translation, inTangent + translation, outTangent + translation, false);
|
||||
}
|
||||
|
||||
CurveVertex transformed(Transform3D const &transform) const {
|
||||
CurveVertex transformed(Transform2D const &transform) const {
|
||||
return CurveVertex(transformVector(point, transform), transformVector(inTangent, transform), transformVector(outTangent, transform), false);
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ public:
|
||||
|
||||
public:
|
||||
bool isGroup = false;
|
||||
Transform3D transform = Transform3D::identity();
|
||||
Transform2D transform = Transform2D::identity();
|
||||
float alpha = 0.0;
|
||||
std::optional<TrimParams> trimParams;
|
||||
std::shared_ptr<RenderTreeNodeContentPath> path;
|
||||
@ -392,7 +392,7 @@ class RenderTreeNode {
|
||||
public:
|
||||
RenderTreeNode(
|
||||
Vector2D size_,
|
||||
Transform3D transform_,
|
||||
Transform2D transform_,
|
||||
float alpha_,
|
||||
bool masksToBounds_,
|
||||
bool isHidden_,
|
||||
@ -421,7 +421,7 @@ public:
|
||||
return _size;
|
||||
}
|
||||
|
||||
Transform3D const &transform() const {
|
||||
Transform2D const &transform() const {
|
||||
return _transform;
|
||||
}
|
||||
|
||||
@ -451,7 +451,7 @@ public:
|
||||
|
||||
public:
|
||||
Vector2D _size;
|
||||
Transform3D _transform = Transform3D::identity();
|
||||
Transform2D _transform = Transform2D::identity();
|
||||
float _alpha = 1.0f;
|
||||
bool _masksToBounds = false;
|
||||
bool _isHidden = false;
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <LottieCpp/lottiejson11.hpp>
|
||||
|
||||
#import <simd/simd.h>
|
||||
|
||||
namespace lottie {
|
||||
|
||||
struct Vector1D {
|
||||
@ -148,167 +150,64 @@ inline float radiansToDegrees(float value) {
|
||||
return value * 180.0f / M_PI;
|
||||
}
|
||||
|
||||
struct Transform3D {
|
||||
float m11, m12, m13, m14;
|
||||
float m21, m22, m23, m24;
|
||||
float m31, m32, m33, m34;
|
||||
float m41, m42, m43, m44;
|
||||
|
||||
Transform3D(
|
||||
float m11_, float m12_, float m13_, float m14_,
|
||||
float m21_, float m22_, float m23_, float m24_,
|
||||
float m31_, float m32_, float m33_, float m34_,
|
||||
float m41_, float m42_, float m43_, float m44_
|
||||
) :
|
||||
m11(m11_), m12(m12_), m13(m13_), m14(m14_),
|
||||
m21(m21_), m22(m22_), m23(m23_), m24(m24_),
|
||||
m31(m31_), m32(m32_), m33(m33_), m34(m34_),
|
||||
m41(m41_), m42(m42_), m43(m43_), m44(m44_) {
|
||||
struct Transform2D {
|
||||
static Transform2D const &identity() {
|
||||
return _identity;
|
||||
}
|
||||
|
||||
bool operator==(Transform3D const &rhs) const {
|
||||
return m11 == rhs.m11 && m12 == rhs.m12 && m13 == rhs.m13 && m14 == rhs.m14 &&
|
||||
m21 == rhs.m21 && m22 == rhs.m22 && m23 == rhs.m23 && m24 == rhs.m24 &&
|
||||
m31 == rhs.m31 && m32 == rhs.m32 && m33 == rhs.m33 && m34 == rhs.m34 &&
|
||||
m41 == rhs.m41 && m42 == rhs.m42 && m43 == rhs.m43 && m44 == rhs.m44;
|
||||
explicit Transform2D(simd_float3x3 const &rows_) :
|
||||
_rows(rows_) {
|
||||
}
|
||||
|
||||
bool operator!=(Transform3D const &rhs) const {
|
||||
return !(*this == rhs);
|
||||
Transform2D operator*(Transform2D const &other) const {
|
||||
return Transform2D(simd_mul(other._rows, _rows));
|
||||
}
|
||||
|
||||
inline bool isIdentity() const {
|
||||
return m11 == 1.0 && m12 == 0.0 && m13 == 0.0 && m14 == 0.0 &&
|
||||
m21 == 0.0 && m22 == 1.0 && m23 == 0.0 && m24 == 0.0 &&
|
||||
m31 == 0.0 && m32 == 0.0 && m33 == 1.0 && m34 == 0.0 &&
|
||||
m41 == 0.0 && m42 == 0.0 && m43 == 0.0 && m44 == 1.0;
|
||||
bool isInvertible() const {
|
||||
return simd_determinant(_rows) > 0.00000001;
|
||||
}
|
||||
|
||||
static Transform3D makeTranslation(float tx, float ty, float tz) {
|
||||
return Transform3D(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
tx, ty, tz, 1
|
||||
);
|
||||
Transform2D inverted() const {
|
||||
return Transform2D(simd_inverse(_rows));
|
||||
}
|
||||
|
||||
static Transform3D makeScale(float sx, float sy, float sz) {
|
||||
return Transform3D(
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
bool isIdentity() const {
|
||||
return (*this) == identity();
|
||||
}
|
||||
|
||||
static Transform3D makeRotation(float radians, float x, float y, float z);
|
||||
|
||||
static Transform3D makeSkew(float skew, float skewAxis) {
|
||||
float mCos = cos(degreesToRadians(skewAxis));
|
||||
float mSin = sin(degreesToRadians(skewAxis));
|
||||
float aTan = tan(degreesToRadians(skew));
|
||||
|
||||
Transform3D transform1(
|
||||
mCos,
|
||||
mSin,
|
||||
0.0,
|
||||
0.0,
|
||||
-mSin,
|
||||
mCos,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
Transform3D transform2(
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
aTan,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
Transform3D transform3(
|
||||
mCos,
|
||||
-mSin,
|
||||
0.0,
|
||||
0.0,
|
||||
mSin,
|
||||
mCos,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
return transform3 * transform2 * transform1;
|
||||
}
|
||||
|
||||
static Transform3D makeTransform(
|
||||
static Transform2D makeTranslation(float tx, float ty);
|
||||
static Transform2D makeScale(float sx, float sy);
|
||||
static Transform2D makeRotation(float radians);
|
||||
static Transform2D makeSkew(float skew, float skewAxis);
|
||||
static Transform2D makeTransform(
|
||||
Vector2D const &anchor,
|
||||
Vector2D const &position,
|
||||
Vector2D const &scale,
|
||||
float rotation,
|
||||
std::optional<float> skew,
|
||||
std::optional<float> skewAxis
|
||||
) {
|
||||
Transform3D result = Transform3D::identity();
|
||||
if (skew.has_value() && skewAxis.has_value()) {
|
||||
result = Transform3D::identity().translated(position).rotated(rotation).skewed(-skew.value(), skewAxis.value()).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
} else {
|
||||
result = Transform3D::identity().translated(position).rotated(rotation).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
);
|
||||
|
||||
Transform2D rotated(float degrees) const;
|
||||
Transform2D translated(Vector2D const &translation) const;
|
||||
Transform2D scaled(Vector2D const &scale) const;
|
||||
Transform2D skewed(float skew, float skewAxis) const;
|
||||
|
||||
bool operator==(Transform2D const &rhs) const {
|
||||
return simd_equal(_rows, rhs._rows);
|
||||
}
|
||||
|
||||
return result;
|
||||
bool operator!=(Transform2D const &rhs) const {
|
||||
return !((*this) == rhs);
|
||||
}
|
||||
|
||||
Transform3D rotated(float degrees) const;
|
||||
|
||||
Transform3D translated(Vector2D const &translation) const;
|
||||
|
||||
Transform3D scaled(Vector2D const &scale) const;
|
||||
|
||||
Transform3D skewed(float skew, float skewAxis) const {
|
||||
return Transform3D::makeSkew(skew, skewAxis) * (*this);
|
||||
simd_float3x3 const &rows() const {
|
||||
return _rows;
|
||||
}
|
||||
|
||||
static Transform3D const &identity() {
|
||||
return _identity;
|
||||
}
|
||||
|
||||
Transform3D operator*(Transform3D const &b) const;
|
||||
|
||||
bool isInvertible() const;
|
||||
|
||||
Transform3D inverted() const;
|
||||
|
||||
private:
|
||||
static Transform3D _identity;
|
||||
static Transform2D _identity;
|
||||
|
||||
simd_float3x3 _rows;
|
||||
};
|
||||
|
||||
struct CGRect {
|
||||
@ -359,7 +258,7 @@ struct CGRect {
|
||||
CGRect intersection(CGRect const &other) const;
|
||||
CGRect unionWith(CGRect const &other) const;
|
||||
|
||||
CGRect applyingTransform(Transform3D const &transform) const;
|
||||
CGRect applyingTransform(Transform2D const &transform) const;
|
||||
};
|
||||
|
||||
inline bool isInRangeOrEqual(float value, float from, float to) {
|
||||
|
@ -7,8 +7,8 @@
|
||||
|
||||
namespace lottie {
|
||||
|
||||
::CATransform3D nativeTransform(Transform3D const &value);
|
||||
Transform3D fromNativeTransform(::CATransform3D const &value);
|
||||
::CATransform3D nativeTransform(Transform2D const &value);
|
||||
Transform2D fromNativeTransform(::CATransform3D const &value);
|
||||
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
std::vector<std::shared_ptr<RenderTreeNode>> renderTreeValue;
|
||||
auto renderTreeContentItem = std::make_shared<RenderTreeNode>(
|
||||
Vector2D(0.0, 0.0),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
@ -136,7 +136,7 @@ public:
|
||||
|
||||
_contentsTreeNode = std::make_shared<RenderTreeNode>(
|
||||
Vector2D(0.0, 0.0),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
@ -159,7 +159,7 @@ public:
|
||||
|
||||
_renderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
Vector2D(0.0, 0.0),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
|
@ -492,9 +492,9 @@ public:
|
||||
|
||||
struct TransformedPath {
|
||||
BezierPath path;
|
||||
Transform3D transform;
|
||||
Transform2D transform;
|
||||
|
||||
TransformedPath(BezierPath const &path_, Transform3D const &transform_) :
|
||||
TransformedPath(BezierPath const &path_, Transform2D const &transform_) :
|
||||
path(path_),
|
||||
transform(transform_) {
|
||||
}
|
||||
@ -853,13 +853,13 @@ public:
|
||||
_opacityValue = 1.0;
|
||||
}
|
||||
|
||||
_transformValue = Transform3D::identity().translated(Vector2D(positionValue.x, positionValue.y)).rotated(rotationValue).skewed(-skewValue, skewAxisValue).scaled(Vector2D(scaleValue.x * 0.01, scaleValue.y * 0.01)).translated(Vector2D(-anchorValue.x, -anchorValue.y));
|
||||
_transformValue = Transform2D::identity().translated(Vector2D(positionValue.x, positionValue.y)).rotated(rotationValue).skewed(-skewValue, skewAxisValue).scaled(Vector2D(scaleValue.x * 0.01, scaleValue.y * 0.01)).translated(Vector2D(-anchorValue.x, -anchorValue.y));
|
||||
|
||||
hasValidData = true;
|
||||
}
|
||||
}
|
||||
|
||||
Transform3D const &transform() {
|
||||
Transform2D const &transform() {
|
||||
return _transformValue;
|
||||
}
|
||||
|
||||
@ -878,7 +878,7 @@ public:
|
||||
std::unique_ptr<KeyframeInterpolator<Vector1D>> _skewAxis;
|
||||
std::unique_ptr<KeyframeInterpolator<Vector1D>> _opacity;
|
||||
|
||||
Transform3D _transformValue = Transform3D::identity();
|
||||
Transform2D _transformValue = Transform2D::identity();
|
||||
float _opacityValue = 1.0;
|
||||
};
|
||||
|
||||
@ -910,11 +910,11 @@ public:
|
||||
std::shared_ptr<RenderTreeNodeContentItem> _contentItem;
|
||||
|
||||
private:
|
||||
std::vector<TransformedPath> collectPaths(size_t subItemLimit, Transform3D const &parentTransform, bool skipApplyTransform) {
|
||||
std::vector<TransformedPath> collectPaths(size_t subItemLimit, Transform2D const &parentTransform, bool skipApplyTransform) {
|
||||
std::vector<TransformedPath> mappedPaths;
|
||||
|
||||
//TODO:remove skipApplyTransform
|
||||
Transform3D effectiveTransform = parentTransform;
|
||||
Transform2D effectiveTransform = parentTransform;
|
||||
if (!skipApplyTransform && isGroup && transform) {
|
||||
effectiveTransform = transform->transform() * effectiveTransform;
|
||||
}
|
||||
@ -942,7 +942,7 @@ public:
|
||||
}
|
||||
CompoundBezierPath trimmedPath = trimCompoundPath(tempPath, currentTrim->start, currentTrim->end, currentTrim->offset, currentTrim->type);
|
||||
for (auto &path : trimmedPath.paths) {
|
||||
mappedPaths.emplace_back(path, Transform3D::identity());
|
||||
mappedPaths.emplace_back(path, Transform2D::identity());
|
||||
}
|
||||
} else {
|
||||
for (auto &path : subItemPaths) {
|
||||
@ -1061,7 +1061,7 @@ public:
|
||||
}
|
||||
|
||||
void updateContents(std::optional<TrimParams> parentTrim) {
|
||||
Transform3D containerTransform = Transform3D::identity();
|
||||
Transform2D containerTransform = Transform2D::identity();
|
||||
float containerOpacity = 1.0;
|
||||
if (transform) {
|
||||
containerTransform = transform->transform();
|
||||
@ -1089,7 +1089,7 @@ public:
|
||||
|
||||
if (parentTrim) {
|
||||
CompoundBezierPath compoundPath;
|
||||
auto paths = collectPaths(shadingVariant.subItemLimit, Transform3D::identity(), true);
|
||||
auto paths = collectPaths(shadingVariant.subItemLimit, Transform2D::identity(), true);
|
||||
for (const auto &path : paths) {
|
||||
compoundPath.appendPath(path.path.copyUsingTransform(path.transform));
|
||||
}
|
||||
@ -1104,7 +1104,7 @@ public:
|
||||
} else {
|
||||
if (hasTrims()) {
|
||||
CompoundBezierPath compoundPath;
|
||||
auto paths = collectPaths(shadingVariant.subItemLimit, Transform3D::identity(), true);
|
||||
auto paths = collectPaths(shadingVariant.subItemLimit, Transform2D::identity(), true);
|
||||
for (const auto &path : paths) {
|
||||
compoundPath.appendPath(path.path.copyUsingTransform(path.transform));
|
||||
}
|
||||
@ -1324,7 +1324,7 @@ std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode(BezierPath
|
||||
if (!_renderTreeNode) {
|
||||
_contentRenderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
Vector2D(0.0, 0.0),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
@ -1349,7 +1349,7 @@ std::shared_ptr<RenderTreeNode> ShapeCompositionLayer::renderTreeNode(BezierPath
|
||||
|
||||
_renderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
Vector2D(0.0, 0.0),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
|
@ -238,7 +238,7 @@ public:
|
||||
}
|
||||
_renderTreeNode = std::make_shared<RenderTreeNode>(
|
||||
size(),
|
||||
Transform3D::identity(),
|
||||
Transform2D::identity(),
|
||||
1.0,
|
||||
false,
|
||||
false,
|
||||
|
@ -157,7 +157,7 @@ public:
|
||||
|
||||
Vector3D anchor = _transformProperties->anchor()->value();
|
||||
Vector3D scale = _transformProperties->scale()->value();
|
||||
_localTransform = Transform3D::makeTransform(
|
||||
_localTransform = Transform2D::makeTransform(
|
||||
Vector2D(anchor.x, anchor.y),
|
||||
position,
|
||||
Vector2D(scale.x, scale.y),
|
||||
@ -181,7 +181,7 @@ public:
|
||||
return _opacity;
|
||||
}
|
||||
|
||||
Transform3D const &globalTransform() {
|
||||
Transform2D const &globalTransform() {
|
||||
return _globalTransform;
|
||||
}
|
||||
|
||||
@ -191,8 +191,8 @@ private:
|
||||
std::shared_ptr<LayerTransformProperties> _transformProperties;
|
||||
|
||||
float _opacity = 1.0;
|
||||
Transform3D _localTransform = Transform3D::identity();
|
||||
Transform3D _globalTransform = Transform3D::identity();
|
||||
Transform2D _localTransform = Transform2D::identity();
|
||||
Transform2D _globalTransform = Transform2D::identity();
|
||||
|
||||
public:
|
||||
virtual LayerTransformNode *asLayerTransformNode() override {
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
return _childKeypaths;
|
||||
}
|
||||
|
||||
Transform3D caTransform() {
|
||||
Transform2D caTransform() {
|
||||
Vector2D anchor = Vector2D::Zero();
|
||||
if (_anchor) {
|
||||
auto anchor3d = _anchor->value();
|
||||
@ -126,7 +126,7 @@ public:
|
||||
skewAxis = _skewAxis->value().value;
|
||||
}
|
||||
|
||||
return Transform3D::makeTransform(
|
||||
return Transform2D::makeTransform(
|
||||
anchor,
|
||||
position,
|
||||
scale,
|
||||
@ -212,16 +212,16 @@ public:
|
||||
return _parentTextNode;
|
||||
}
|
||||
|
||||
Transform3D xform() {
|
||||
Transform2D xform() {
|
||||
if (_xform.has_value()) {
|
||||
return _xform.value();
|
||||
} else if (_parentTextNode) {
|
||||
return _parentTextNode->xform();
|
||||
} else {
|
||||
return Transform3D::identity();
|
||||
return Transform2D::identity();
|
||||
}
|
||||
}
|
||||
void setXform(Transform3D const &xform) {
|
||||
void setXform(Transform2D const &xform) {
|
||||
_xform = xform;
|
||||
}
|
||||
|
||||
@ -312,7 +312,7 @@ private:
|
||||
|
||||
std::shared_ptr<CGPath> _outputPath;
|
||||
|
||||
std::optional<Transform3D> _xform;
|
||||
std::optional<Transform2D> _xform;
|
||||
std::optional<float> _opacity;
|
||||
std::optional<Color> _strokeColor;
|
||||
std::optional<Color> _fillColor;
|
||||
|
@ -486,8 +486,8 @@ std::shared_ptr<CGPath> BezierPath::cgPath() const {
|
||||
return _contents->cgPath();
|
||||
}
|
||||
|
||||
BezierPath BezierPath::copyUsingTransform(Transform3D const &transform) const {
|
||||
if (transform == Transform3D::identity()) {
|
||||
BezierPath BezierPath::copyUsingTransform(Transform2D const &transform) const {
|
||||
if (transform == Transform2D::identity()) {
|
||||
return (*this);
|
||||
}
|
||||
BezierPath result;
|
||||
|
@ -64,10 +64,10 @@ public:
|
||||
_size = size;
|
||||
}
|
||||
|
||||
Transform3D const &transform() const {
|
||||
Transform2D const &transform() const {
|
||||
return _transform;
|
||||
}
|
||||
void setTransform(Transform3D const &transform) {
|
||||
void setTransform(Transform2D const &transform) {
|
||||
_transform = transform;
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ private:
|
||||
bool _isHidden = false;
|
||||
float _opacity = 1.0;
|
||||
Vector2D _size = Vector2D(0.0, 0.0);
|
||||
Transform3D _transform = Transform3D::identity();
|
||||
Transform2D _transform = Transform2D::identity();
|
||||
std::shared_ptr<CALayer> _mask;
|
||||
bool _masksToBounds = false;
|
||||
std::optional<BlendMode> _compositingFilter;
|
||||
|
@ -35,11 +35,10 @@ void addPointToBoundingRect(bool *isFirst, CGRect *rect, Vector2D const *point)
|
||||
|
||||
}
|
||||
|
||||
Vector2D transformVector(Vector2D const &v, Transform3D const &m) {
|
||||
return Vector2D(
|
||||
m.m11 * v.x + m.m21 * v.y + m.m41 * 1.0,
|
||||
m.m12 * v.x + m.m22 * v.y + m.m42 * 1.0
|
||||
);
|
||||
Vector2D transformVector(Vector2D const &v, Transform2D const &m) {
|
||||
float transformedX = m.rows().columns[0][0] * v.x + m.rows().columns[1][0] * v.y + m.rows().columns[2][0] * 1.0f;
|
||||
float transformedY = m.rows().columns[0][1] * v.x + m.rows().columns[1][1] * v.y + m.rows().columns[2][1] * 1.0f;
|
||||
return Vector2D(transformedX, transformedY);
|
||||
}
|
||||
|
||||
class CGPathImpl: public CGPath {
|
||||
@ -51,7 +50,7 @@ public:
|
||||
|
||||
virtual bool empty() const override;
|
||||
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform3D const &transform) const override;
|
||||
virtual std::shared_ptr<CGPath> copyUsingTransform(Transform2D const &transform) const override;
|
||||
|
||||
virtual void addLineTo(Vector2D const &point) override;
|
||||
virtual void addCurveTo(Vector2D const &point, Vector2D const &control1, Vector2D const &control2) override;
|
||||
@ -108,10 +107,10 @@ bool CGPathImpl::empty() const {
|
||||
return _items.empty();
|
||||
}
|
||||
|
||||
std::shared_ptr<CGPath> CGPathImpl::copyUsingTransform(Transform3D const &transform) const {
|
||||
std::shared_ptr<CGPath> CGPathImpl::copyUsingTransform(Transform2D const &transform) const {
|
||||
auto result = std::make_shared<CGPathImpl>();
|
||||
|
||||
if (transform == Transform3D::identity()) {
|
||||
if (transform == Transform2D::identity()) {
|
||||
result->_items = _items;
|
||||
return result;
|
||||
}
|
||||
|
@ -92,29 +92,12 @@ bool CGPathCocoaImpl::empty() const {
|
||||
return CGPathIsEmpty(_path);
|
||||
}
|
||||
|
||||
std::shared_ptr<CGPath> CGPathCocoaImpl::copyUsingTransform(Transform3D const &transform) const {
|
||||
::CATransform3D nativeTransform;
|
||||
nativeTransform.m11 = transform.m11;
|
||||
nativeTransform.m12 = transform.m12;
|
||||
nativeTransform.m13 = transform.m13;
|
||||
nativeTransform.m14 = transform.m14;
|
||||
|
||||
nativeTransform.m21 = transform.m21;
|
||||
nativeTransform.m22 = transform.m22;
|
||||
nativeTransform.m23 = transform.m23;
|
||||
nativeTransform.m24 = transform.m24;
|
||||
|
||||
nativeTransform.m31 = transform.m31;
|
||||
nativeTransform.m32 = transform.m32;
|
||||
nativeTransform.m33 = transform.m33;
|
||||
nativeTransform.m34 = transform.m34;
|
||||
|
||||
nativeTransform.m41 = transform.m41;
|
||||
nativeTransform.m42 = transform.m42;
|
||||
nativeTransform.m43 = transform.m43;
|
||||
nativeTransform.m44 = transform.m44;
|
||||
|
||||
auto affineTransform = CATransform3DGetAffineTransform(nativeTransform);
|
||||
std::shared_ptr<CGPath> CGPathCocoaImpl::copyUsingTransform(Transform2D const &transform) const {
|
||||
CGAffineTransform affineTransform = CGAffineTransformMake(
|
||||
transform.rows().columns[0][0], transform.rows().columns[0][1],
|
||||
transform.rows().columns[1][0], transform.rows().columns[1][1],
|
||||
transform.rows().columns[2][0], transform.rows().columns[2][1]
|
||||
);
|
||||
|
||||
CGPathRef resultPath = CGPathCreateCopyByTransformingPath(_path, &affineTransform);
|
||||
if (resultPath == nil) {
|
||||
|
@ -8,10 +8,261 @@
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
#import <simd/simd.h>
|
||||
|
||||
namespace lottie {
|
||||
|
||||
/*explicit Transform2D(Transform3D const &t) {
|
||||
CGAffineTransform at = CATransform3DGetAffineTransform(nativeTransform(t));
|
||||
_rows.columns[0] = simd_make_float3(at.a, at.b, 0.0);
|
||||
_rows.columns[1] = simd_make_float3(at.c, at.d, 0.0);
|
||||
_rows.columns[2] = simd_make_float3(at.tx, at.ty, 1.0);
|
||||
}
|
||||
|
||||
Transform3D transform3D() {
|
||||
CGAffineTransform at = CGAffineTransformMake(
|
||||
_rows.columns[0][0], _rows.columns[0][1],
|
||||
_rows.columns[1][0], _rows.columns[1][1],
|
||||
_rows.columns[2][0], _rows.columns[2][1]
|
||||
);
|
||||
return fromNativeTransform(CATransform3DMakeAffineTransform(at));
|
||||
}*/
|
||||
|
||||
/*struct Transform3D {
|
||||
float m11, m12, m13, m14;
|
||||
float m21, m22, m23, m24;
|
||||
float m31, m32, m33, m34;
|
||||
float m41, m42, m43, m44;
|
||||
|
||||
Transform3D(
|
||||
float m11_, float m12_, float m13_, float m14_,
|
||||
float m21_, float m22_, float m23_, float m24_,
|
||||
float m31_, float m32_, float m33_, float m34_,
|
||||
float m41_, float m42_, float m43_, float m44_
|
||||
) :
|
||||
m11(m11_), m12(m12_), m13(m13_), m14(m14_),
|
||||
m21(m21_), m22(m22_), m23(m23_), m24(m24_),
|
||||
m31(m31_), m32(m32_), m33(m33_), m34(m34_),
|
||||
m41(m41_), m42(m42_), m43(m43_), m44(m44_) {
|
||||
}
|
||||
|
||||
bool operator==(Transform3D const &rhs) const {
|
||||
return m11 == rhs.m11 && m12 == rhs.m12 && m13 == rhs.m13 && m14 == rhs.m14 &&
|
||||
m21 == rhs.m21 && m22 == rhs.m22 && m23 == rhs.m23 && m24 == rhs.m24 &&
|
||||
m31 == rhs.m31 && m32 == rhs.m32 && m33 == rhs.m33 && m34 == rhs.m34 &&
|
||||
m41 == rhs.m41 && m42 == rhs.m42 && m43 == rhs.m43 && m44 == rhs.m44;
|
||||
}
|
||||
|
||||
bool operator!=(Transform3D const &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
inline bool isIdentity() const {
|
||||
return m11 == 1.0 && m12 == 0.0 && m13 == 0.0 && m14 == 0.0 &&
|
||||
m21 == 0.0 && m22 == 1.0 && m23 == 0.0 && m24 == 0.0 &&
|
||||
m31 == 0.0 && m32 == 0.0 && m33 == 1.0 && m34 == 0.0 &&
|
||||
m41 == 0.0 && m42 == 0.0 && m43 == 0.0 && m44 == 1.0;
|
||||
}
|
||||
|
||||
static Transform3D makeTranslation(float tx, float ty, float tz) {
|
||||
return Transform3D(
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
tx, ty, tz, 1
|
||||
);
|
||||
}
|
||||
|
||||
static Transform3D makeScale(float sx, float sy, float sz) {
|
||||
return Transform3D(
|
||||
sx, 0, 0, 0,
|
||||
0, sy, 0, 0,
|
||||
0, 0, sz, 0,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
}
|
||||
|
||||
static Transform3D makeRotation(float radians);
|
||||
|
||||
static Transform3D makeSkew(float skew, float skewAxis) {
|
||||
float mCos = cos(degreesToRadians(skewAxis));
|
||||
float mSin = sin(degreesToRadians(skewAxis));
|
||||
float aTan = tan(degreesToRadians(skew));
|
||||
|
||||
Transform3D transform1(
|
||||
mCos,
|
||||
mSin,
|
||||
0.0,
|
||||
0.0,
|
||||
-mSin,
|
||||
mCos,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
Transform3D transform2(
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
aTan,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
Transform3D transform3(
|
||||
mCos,
|
||||
-mSin,
|
||||
0.0,
|
||||
0.0,
|
||||
mSin,
|
||||
mCos,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
|
||||
return transform3 * transform2 * transform1;
|
||||
}
|
||||
|
||||
static Transform3D makeTransform(
|
||||
Vector2D const &anchor,
|
||||
Vector2D const &position,
|
||||
Vector2D const &scale,
|
||||
float rotation,
|
||||
std::optional<float> skew,
|
||||
std::optional<float> skewAxis
|
||||
) {
|
||||
Transform3D result = Transform3D::identity();
|
||||
if (skew.has_value() && skewAxis.has_value()) {
|
||||
result = Transform3D::identity().translated(position).rotated(rotation).skewed(-skew.value(), skewAxis.value()).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
} else {
|
||||
result = Transform3D::identity().translated(position).rotated(rotation).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform3D rotated(float degrees) const;
|
||||
|
||||
Transform3D translated(Vector2D const &translation) const;
|
||||
|
||||
Transform3D scaled(Vector2D const &scale) const;
|
||||
|
||||
Transform3D skewed(float skew, float skewAxis) const {
|
||||
return Transform3D::makeSkew(skew, skewAxis) * (*this);
|
||||
}
|
||||
|
||||
static Transform3D identity() {
|
||||
return Transform3D(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
}
|
||||
|
||||
Transform3D operator*(Transform3D const &b) const;
|
||||
};*/
|
||||
|
||||
/*Transform2D t2d(Transform3D const &testMatrix) {
|
||||
::CATransform3D nativeTest;
|
||||
|
||||
nativeTest.m11 = testMatrix.m11;
|
||||
nativeTest.m12 = testMatrix.m12;
|
||||
nativeTest.m13 = testMatrix.m13;
|
||||
nativeTest.m14 = testMatrix.m14;
|
||||
|
||||
nativeTest.m21 = testMatrix.m21;
|
||||
nativeTest.m22 = testMatrix.m22;
|
||||
nativeTest.m23 = testMatrix.m23;
|
||||
nativeTest.m24 = testMatrix.m24;
|
||||
|
||||
nativeTest.m31 = testMatrix.m31;
|
||||
nativeTest.m32 = testMatrix.m32;
|
||||
nativeTest.m33 = testMatrix.m33;
|
||||
nativeTest.m34 = testMatrix.m34;
|
||||
|
||||
nativeTest.m41 = testMatrix.m41;
|
||||
nativeTest.m42 = testMatrix.m42;
|
||||
nativeTest.m43 = testMatrix.m43;
|
||||
nativeTest.m44 = testMatrix.m44;
|
||||
|
||||
CGAffineTransform at = CATransform3DGetAffineTransform(nativeTest);
|
||||
Transform2D result = Transform2D::identity();
|
||||
simd_float3x3 *rows = (simd_float3x3 *)&result.rows();
|
||||
rows->columns[0] = simd_make_float3(at.a, at.b, 0.0);
|
||||
rows->columns[1] = simd_make_float3(at.c, at.d, 0.0);
|
||||
rows->columns[2] = simd_make_float3(at.tx, at.ty, 1.0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform3D t3d(Transform2D const &t) {
|
||||
CGAffineTransform at = CGAffineTransformMake(
|
||||
t.rows().columns[0][0], t.rows().columns[0][1],
|
||||
t.rows().columns[1][0], t.rows().columns[1][1],
|
||||
t.rows().columns[2][0], t.rows().columns[2][1]
|
||||
);
|
||||
::CATransform3D value = CATransform3DMakeAffineTransform(at);
|
||||
|
||||
Transform3D result = Transform3D::identity();
|
||||
result.m11 = value.m11;
|
||||
result.m12 = value.m12;
|
||||
result.m13 = value.m13;
|
||||
result.m14 = value.m14;
|
||||
|
||||
result.m21 = value.m21;
|
||||
result.m22 = value.m22;
|
||||
result.m23 = value.m23;
|
||||
result.m24 = value.m24;
|
||||
|
||||
result.m31 = value.m31;
|
||||
result.m32 = value.m32;
|
||||
result.m33 = value.m33;
|
||||
result.m34 = value.m34;
|
||||
|
||||
result.m41 = value.m41;
|
||||
result.m42 = value.m42;
|
||||
result.m43 = value.m43;
|
||||
result.m44 = value.m44;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::operator*(Transform3D const &b) const {
|
||||
if (isIdentity()) {
|
||||
return b;
|
||||
}
|
||||
if (b.isIdentity()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
return t3d((t2d(*this) * t2d(b)));
|
||||
}*/
|
||||
|
||||
Vector1D::Vector1D(lottiejson11::Json const &json) noexcept(false) {
|
||||
if (json.is_number()) {
|
||||
value = json.number_value();
|
||||
@ -140,13 +391,108 @@ lottiejson11::Json Vector3D::toJson() const {
|
||||
return lottiejson11::Json(result);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::_identity = Transform3D(
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0
|
||||
Transform2D Transform2D::_identity = Transform2D(
|
||||
simd_float3x3({
|
||||
simd_make_float3(1.0f, 0.0f, 0.0f),
|
||||
simd_make_float3(0.0f, 1.0f, 0.0f),
|
||||
simd_make_float3(0.0f, 0.0f, 1.0f)
|
||||
})
|
||||
);
|
||||
|
||||
Transform2D Transform2D::makeTranslation(float tx, float ty) {
|
||||
return Transform2D(simd_float3x3({
|
||||
simd_make_float3(1.0f, 0.0f, 0.0f),
|
||||
simd_make_float3(0.0f, 1.0f, 0.0f),
|
||||
simd_make_float3(tx, ty, 1.0f)
|
||||
}));
|
||||
}
|
||||
|
||||
Transform2D Transform2D::makeScale(float sx, float sy) {
|
||||
return Transform2D(simd_float3x3({
|
||||
simd_make_float3(sx, 0.0f, 0.0f),
|
||||
simd_make_float3(0.0f, sy, 0.0f),
|
||||
simd_make_float3(0.0f, 0.0f, 1.0f)
|
||||
}));
|
||||
}
|
||||
|
||||
Transform2D Transform2D::makeRotation(float radians) {
|
||||
float c = cos(radians);
|
||||
float s = sin(radians);
|
||||
|
||||
return Transform2D(simd_float3x3({
|
||||
simd_make_float3(c, s, 0.0f),
|
||||
simd_make_float3(-s, c, 0.0f),
|
||||
simd_make_float3(0.0f, 0.0f, 1.0f)
|
||||
}));
|
||||
}
|
||||
|
||||
Transform2D Transform2D::makeSkew(float skew, float skewAxis) {
|
||||
if (std::abs(skew) <= FLT_EPSILON && std::abs(skewAxis) <= FLT_EPSILON) {
|
||||
return Transform2D::identity();
|
||||
}
|
||||
|
||||
float mCos = cos(degreesToRadians(skewAxis));
|
||||
float mSin = sin(degreesToRadians(skewAxis));
|
||||
float aTan = tan(degreesToRadians(skew));
|
||||
|
||||
simd_float3x3 simd1 = simd_float3x3({
|
||||
simd_make_float3(mCos, -mSin, 0.0),
|
||||
simd_make_float3(mSin, mCos, 0.0),
|
||||
simd_make_float3(0.0, 0.0, 1.0)
|
||||
});
|
||||
|
||||
simd_float3x3 simd2 = simd_float3x3({
|
||||
simd_make_float3(1.0, 0.0, 0.0),
|
||||
simd_make_float3(aTan, 1.0, 0.0),
|
||||
simd_make_float3(0.0, 0.0, 1.0)
|
||||
});
|
||||
|
||||
simd_float3x3 simd3 = simd_float3x3({
|
||||
simd_make_float3(mCos, mSin, 0.0),
|
||||
simd_make_float3(-mSin, mCos, 0.0),
|
||||
simd_make_float3(0.0, 0.0, 1.0)
|
||||
});
|
||||
|
||||
simd_float3x3 result = simd_mul(simd_mul(simd3, simd2), simd1);
|
||||
Transform2D resultTransform(result);
|
||||
|
||||
return resultTransform;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::makeTransform(
|
||||
Vector2D const &anchor,
|
||||
Vector2D const &position,
|
||||
Vector2D const &scale,
|
||||
float rotation,
|
||||
std::optional<float> skew,
|
||||
std::optional<float> skewAxis
|
||||
) {
|
||||
Transform2D result = Transform2D::identity();
|
||||
if (skew.has_value() && skewAxis.has_value()) {
|
||||
result = Transform2D::identity().translated(position).rotated(rotation).skewed(-skew.value(), skewAxis.value()).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
} else {
|
||||
result = Transform2D::identity().translated(position).rotated(rotation).scaled(Vector2D(scale.x * 0.01, scale.y * 0.01)).translated(Vector2D(-anchor.x, -anchor.y));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Transform2D Transform2D::rotated(float degrees) const {
|
||||
return Transform2D::makeRotation(degreesToRadians(degrees)) * (*this);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::translated(Vector2D const &translation) const {
|
||||
return Transform2D::makeTranslation(translation.x, translation.y) * (*this);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::scaled(Vector2D const &scale) const {
|
||||
return Transform2D::makeScale(scale.x, scale.y) * (*this);
|
||||
}
|
||||
|
||||
Transform2D Transform2D::skewed(float skew, float skewAxis) const {
|
||||
return Transform2D::makeSkew(skew, skewAxis) * (*this);
|
||||
}
|
||||
|
||||
float interpolate(float value, float to, float amount) {
|
||||
return value + ((to - value) * amount);
|
||||
}
|
||||
@ -415,8 +761,15 @@ Vector2D Vector2D::interpolate(
|
||||
return point.point;
|
||||
}
|
||||
|
||||
::CATransform3D nativeTransform(Transform3D const &value) {
|
||||
::CATransform3D result;
|
||||
::CATransform3D nativeTransform(Transform2D const &value) {
|
||||
CGAffineTransform at = CGAffineTransformMake(
|
||||
value.rows().columns[0][0], value.rows().columns[0][1],
|
||||
value.rows().columns[1][0], value.rows().columns[1][1],
|
||||
value.rows().columns[2][0], value.rows().columns[2][1]
|
||||
);
|
||||
return CATransform3DMakeAffineTransform(at);
|
||||
|
||||
/*::CATransform3D result;
|
||||
|
||||
result.m11 = value.m11;
|
||||
result.m12 = value.m12;
|
||||
@ -438,11 +791,20 @@ Vector2D Vector2D::interpolate(
|
||||
result.m43 = value.m43;
|
||||
result.m44 = value.m44;
|
||||
|
||||
return result;
|
||||
return result;*/
|
||||
}
|
||||
|
||||
Transform3D fromNativeTransform(::CATransform3D const &value) {
|
||||
Transform3D result = Transform3D::identity();
|
||||
Transform2D fromNativeTransform(::CATransform3D const &value) {
|
||||
CGAffineTransform at = CATransform3DGetAffineTransform(value);
|
||||
return Transform2D(
|
||||
simd_float3x3({
|
||||
simd_make_float3(at.a, at.b, 0.0),
|
||||
simd_make_float3(at.c, at.d, 0.0),
|
||||
simd_make_float3(at.tx, at.ty, 1.0)
|
||||
})
|
||||
);
|
||||
|
||||
/*Transform2D result = Transform2D::identity();
|
||||
|
||||
result.m11 = value.m11;
|
||||
result.m12 = value.m12;
|
||||
@ -464,47 +826,23 @@ Transform3D fromNativeTransform(::CATransform3D const &value) {
|
||||
result.m43 = value.m43;
|
||||
result.m44 = value.m44;
|
||||
|
||||
return result;
|
||||
return result;*/
|
||||
}
|
||||
|
||||
Transform3D Transform3D::makeRotation(float radians, float x, float y, float z) {
|
||||
if (std::abs(radians) <= FLT_EPSILON || (x == 0.0 && y == 0.0 && z == 0.0)) {
|
||||
/*Transform3D Transform3D::makeRotation(float radians) {
|
||||
if (std::abs(radians) <= FLT_EPSILON) {
|
||||
return Transform3D::identity();
|
||||
}
|
||||
|
||||
float s = sin(radians);
|
||||
float c = cos(radians);
|
||||
|
||||
float len = sqrt(x*x + y*y + z*z);
|
||||
x /= len; y /= len; z /= len;
|
||||
|
||||
Transform3D returnValue = Transform3D::identity();
|
||||
|
||||
returnValue.m11 = c + (1.0f - c) * x * x;
|
||||
returnValue.m12 = (1.0f - c) * x*y + s * z;
|
||||
returnValue.m13 = (1.0f - c) * x*z - s * y;
|
||||
returnValue.m14 = 0.0f;
|
||||
|
||||
returnValue.m21 = (1.0f - c) * y * x - s * z;
|
||||
returnValue.m22 = c + (1.0f - c) * y * y;
|
||||
returnValue.m23 = (1.0f - c) * y * z + s * x;
|
||||
returnValue.m24 = 0.0f;
|
||||
|
||||
returnValue.m31 = (1.0f - c) * z * x + s * y;
|
||||
returnValue.m32 = (1.0f - c) * y * z - s * x;
|
||||
returnValue.m33 = c + (1.0f - c) * z * z;
|
||||
returnValue.m34 = 0.0f;
|
||||
|
||||
returnValue.m41 = 0.0f;
|
||||
returnValue.m42 = 0.0f;
|
||||
returnValue.m43 = 0.0f;
|
||||
returnValue.m44 = 1.0f;
|
||||
|
||||
return returnValue;
|
||||
::CGAffineTransform t = CGAffineTransformMake(c, s, -s, c, 0.0f, 0.0f);
|
||||
return fromNativeTransform(CATransform3DMakeAffineTransform(t));
|
||||
}
|
||||
|
||||
Transform3D Transform3D::rotated(float degrees) const {
|
||||
return Transform3D::makeRotation(degreesToRadians(degrees), 0.0, 0.0, 1.0) * (*this);
|
||||
return Transform3D::makeRotation(degreesToRadians(degrees)) * (*this);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::translated(Vector2D const &translation) const {
|
||||
@ -515,57 +853,14 @@ Transform3D Transform3D::scaled(Vector2D const &scale) const {
|
||||
return Transform3D::makeScale(scale.x, scale.y, 1.0) * (*this);
|
||||
}
|
||||
|
||||
Transform3D Transform3D::operator*(Transform3D const &b) const {
|
||||
if (isIdentity()) {
|
||||
return b;
|
||||
}
|
||||
if (b.isIdentity()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
simd_float4x4 simdLhs = {
|
||||
simd_make_float4(b.m11, b.m21, b.m31, b.m41),
|
||||
simd_make_float4(b.m12, b.m22, b.m32, b.m42),
|
||||
simd_make_float4(b.m13, b.m23, b.m33, b.m43),
|
||||
simd_make_float4(b.m14, b.m24, b.m34, b.m44)
|
||||
};
|
||||
simd_float4x4 simdRhs = {
|
||||
simd_make_float4(m11, m21, m31, m41),
|
||||
simd_make_float4(m12, m22, m32, m42),
|
||||
simd_make_float4(m13, m23, m33, m43),
|
||||
simd_make_float4(m14, m24, m34, m44)
|
||||
};
|
||||
|
||||
simd_float4x4 simdResult = simd_mul(simdRhs, simdLhs);
|
||||
return Transform3D(
|
||||
simdResult.columns[0][0], simdResult.columns[1][0], simdResult.columns[2][0], simdResult.columns[3][0],
|
||||
simdResult.columns[0][1], simdResult.columns[1][1], simdResult.columns[2][1], simdResult.columns[3][1],
|
||||
simdResult.columns[0][2], simdResult.columns[1][2], simdResult.columns[2][2], simdResult.columns[3][2],
|
||||
simdResult.columns[0][3], simdResult.columns[1][3], simdResult.columns[2][3], simdResult.columns[3][3]
|
||||
);
|
||||
}
|
||||
|
||||
bool Transform3D::isInvertible() const {
|
||||
return std::abs(m11 * m22 - m12 * m21) >= 0.00000001;
|
||||
return Transform2D(*this).isInvertible();
|
||||
//return std::abs(m11 * m22 - m12 * m21) >= 0.00000001;
|
||||
}
|
||||
|
||||
Transform3D Transform3D::inverted() const {
|
||||
simd_float4x4 matrix = {
|
||||
simd_make_float4(m11, m21, m31, m41),
|
||||
simd_make_float4(m12, m22, m32, m42),
|
||||
simd_make_float4(m13, m23, m33, m43),
|
||||
simd_make_float4(m14, m24, m34, m44)
|
||||
};
|
||||
simd_float4x4 result = simd_inverse(matrix);
|
||||
Transform3D nativeResult = Transform3D(
|
||||
result.columns[0][0], result.columns[1][0], result.columns[2][0], result.columns[3][0],
|
||||
result.columns[0][1], result.columns[1][1], result.columns[2][1], result.columns[3][1],
|
||||
result.columns[0][2], result.columns[1][2], result.columns[2][2], result.columns[3][2],
|
||||
result.columns[0][3], result.columns[1][3], result.columns[2][3], result.columns[3][3]
|
||||
);
|
||||
|
||||
return nativeResult;
|
||||
}
|
||||
return Transform2D(*this).inverted().transform3D();
|
||||
}*/
|
||||
|
||||
bool CGRect::intersects(CGRect const &other) const {
|
||||
return CGRectIntersectsRect(CGRectMake(x, y, width, height), CGRectMake(other.x, other.y, other.width, other.height));
|
||||
@ -585,29 +880,26 @@ CGRect CGRect::unionWith(CGRect const &other) const {
|
||||
return CGRect(result.origin.x, result.origin.y, result.size.width, result.size.height);
|
||||
}
|
||||
|
||||
CGRect CGRect::applyingTransform(Transform3D const &transform) const {
|
||||
CGRect CGRect::applyingTransform(Transform2D const &transform) const {
|
||||
if (transform.isIdentity()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
simd_float3 simdRow1 = simd_make_float3(transform.m11, transform.m12, transform.m14);
|
||||
simd_float3 simdRow2 = simd_make_float3(transform.m21, transform.m22, transform.m24);
|
||||
simd_float3 simdRow3 = simd_make_float3(transform.m41, transform.m42, transform.m44);
|
||||
|
||||
Vector2D sourceTopLeft = Vector2D(x, y);
|
||||
Vector2D sourceTopRight = Vector2D(x + width, y);
|
||||
Vector2D sourceBottomLeft = Vector2D(x, y + height);
|
||||
Vector2D sourceBottomRight = Vector2D(x + width, y + height);
|
||||
|
||||
simd_float3 simdTopLeft = sourceTopLeft.x * simdRow1 + sourceTopLeft.y * simdRow2 + simdRow3;
|
||||
simd_float3 simdTopRight = sourceTopRight.x * simdRow1 + sourceTopRight.y * simdRow2 + simdRow3;
|
||||
simd_float3 simdBottomLeft = sourceBottomLeft.x * simdRow1 + sourceBottomLeft.y * simdRow2 + simdRow3;
|
||||
simd_float3 simdBottomRight = sourceBottomRight.x * simdRow1 + sourceBottomRight.y * simdRow2 + simdRow3;
|
||||
simd_float4 xs = simd_make_float4(sourceTopLeft.x, sourceTopRight.x, sourceBottomLeft.x, sourceBottomRight.x);
|
||||
simd_float4 ys = simd_make_float4(sourceTopLeft.y, sourceTopRight.y, sourceBottomLeft.y, sourceBottomRight.y);
|
||||
|
||||
Vector2D topLeft = Vector2D(simdTopLeft[0] / simdTopLeft[2], simdTopLeft[1] / simdTopLeft[2]);
|
||||
Vector2D topRight = Vector2D(simdTopRight[0] / simdTopRight[2], simdTopRight[1] / simdTopRight[2]);
|
||||
Vector2D bottomLeft = Vector2D(simdBottomLeft[0] / simdBottomLeft[2], simdBottomLeft[1] / simdBottomLeft[2]);
|
||||
Vector2D bottomRight = Vector2D(simdBottomRight[0] / simdBottomRight[2], simdBottomRight[1] / simdBottomRight[2]);
|
||||
simd_float4 rx = xs * transform.rows().columns[0][0] + ys * transform.rows().columns[1][0] + transform.rows().columns[2][0];
|
||||
simd_float4 ry = xs * transform.rows().columns[0][1] + ys * transform.rows().columns[1][1] + transform.rows().columns[2][1];
|
||||
|
||||
Vector2D topLeft = Vector2D(rx[0], ry[0]);
|
||||
Vector2D topRight = Vector2D(rx[1], ry[1]);
|
||||
Vector2D bottomLeft = Vector2D(rx[2], ry[2]);
|
||||
Vector2D bottomRight = Vector2D(rx[3], ry[3]);
|
||||
|
||||
float minX = simd_reduce_min(simd_make_float4(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x));
|
||||
float minY = simd_reduce_min(simd_make_float4(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y));
|
||||
|
Loading…
x
Reference in New Issue
Block a user