mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Lottie
This commit is contained in:
parent
41c88223b4
commit
814852d902
@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
|
||||
namespace lottieRendering {
|
||||
|
||||
@ -41,6 +42,20 @@ enum class BlendMode {
|
||||
DestinationOut
|
||||
};
|
||||
|
||||
enum class PathCommandType {
|
||||
MoveTo,
|
||||
LineTo,
|
||||
CurveTo,
|
||||
Close
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PathCommandType type;
|
||||
CGPoint points[4];
|
||||
} PathCommand;
|
||||
|
||||
typedef std::function<void(std::function<void(PathCommand const &)>)> CanvasPathEnumerator;
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
virtual ~Canvas() = default;
|
||||
@ -53,13 +68,13 @@ public:
|
||||
virtual void saveState() = 0;
|
||||
virtual void restoreState() = 0;
|
||||
|
||||
virtual void fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) = 0;
|
||||
virtual void linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) = 0;
|
||||
virtual void radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) = 0;
|
||||
virtual void fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) = 0;
|
||||
virtual void linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) = 0;
|
||||
virtual void radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) = 0;
|
||||
|
||||
virtual void strokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) = 0;
|
||||
virtual void linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) = 0;
|
||||
virtual void radialGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) = 0;
|
||||
virtual void strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) = 0;
|
||||
virtual void linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) = 0;
|
||||
virtual void radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) = 0;
|
||||
|
||||
virtual void fill(lottie::CGRect const &rect, lottie::Color const &fillColor) = 0;
|
||||
virtual void setBlendMode(BlendMode blendMode) = 0;
|
||||
@ -67,7 +82,6 @@ public:
|
||||
virtual void setAlpha(float alpha) = 0;
|
||||
|
||||
virtual void concatenate(lottie::CATransform3D const &transform) = 0;
|
||||
virtual lottie::CATransform3D currentTransform() = 0;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) = 0;
|
||||
};
|
||||
|
@ -29,19 +29,18 @@ public:
|
||||
virtual void saveState() override;
|
||||
virtual void restoreState() override;
|
||||
|
||||
virtual void fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
|
||||
virtual void strokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
|
||||
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::CATransform3D const &transform) override;
|
||||
virtual lottie::CATransform3D currentTransform() override;
|
||||
|
||||
virtual std::shared_ptr<Image> makeImage() const;
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
@ -11,6 +11,52 @@ int alignUp(int size, int align) {
|
||||
return (size + alignmentMask) & ~alignmentMask;
|
||||
}
|
||||
|
||||
bool addEnumeratedPath(CGContextRef context, CanvasPathEnumerator const &enumeratePath) {
|
||||
bool isEmpty = true;
|
||||
|
||||
enumeratePath([&](PathCommand const &command) {
|
||||
switch (command.type) {
|
||||
case PathCommandType::MoveTo: {
|
||||
if (isEmpty) {
|
||||
isEmpty = false;
|
||||
CGContextBeginPath(context);
|
||||
}
|
||||
CGContextMoveToPoint(context, command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::LineTo: {
|
||||
if (isEmpty) {
|
||||
isEmpty = false;
|
||||
CGContextBeginPath(context);
|
||||
}
|
||||
CGContextAddLineToPoint(context, command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::CurveTo: {
|
||||
if (isEmpty) {
|
||||
isEmpty = false;
|
||||
CGContextBeginPath(context);
|
||||
}
|
||||
CGContextAddCurveToPoint(context, command.points[0].x, command.points[0].y, command.points[1].x, command.points[1].y, command.points[2].x, command.points[2].y);
|
||||
break;
|
||||
}
|
||||
case PathCommandType::Close: {
|
||||
if (isEmpty) {
|
||||
isEmpty = false;
|
||||
CGContextBeginPath(context);
|
||||
}
|
||||
CGContextClosePath(context);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return !isEmpty;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ImageImpl::ImageImpl(::CGImageRef image) {
|
||||
@ -87,11 +133,10 @@ void CanvasImpl::restoreState() {
|
||||
CGContextRestoreGState(_context);
|
||||
}
|
||||
|
||||
void CanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
void CanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat components[4] = { color.r, color.g, color.b, color.a };
|
||||
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components);
|
||||
@ -110,12 +155,13 @@ void CanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::F
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
void CanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
CGContextSaveGState(_context);
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
CGContextRestoreGState(_context);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fillRule) {
|
||||
case lottie::FillRule::EvenOdd: {
|
||||
@ -155,12 +201,13 @@ void CanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &p
|
||||
CGContextRestoreGState(_context);
|
||||
}
|
||||
|
||||
void CanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
void CanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
CGContextSaveGState(_context);
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
CGContextRestoreGState(_context);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fillRule) {
|
||||
case lottie::FillRule::EvenOdd: {
|
||||
@ -200,11 +247,10 @@ void CanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &p
|
||||
CGContextRestoreGState(_context);
|
||||
}
|
||||
|
||||
void CanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
void CanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CGFloat components[4] = { color.r, color.g, color.b, color.a };
|
||||
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components);
|
||||
@ -261,12 +307,12 @@ void CanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, float l
|
||||
CGContextStrokePath(_context);
|
||||
}
|
||||
|
||||
void CanvasImpl::linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
void CanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
CGContextSaveGState(_context);
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
CGContextRestoreGState(_context);
|
||||
return;
|
||||
}
|
||||
|
||||
CGContextSetLineWidth(_context, lineWidth);
|
||||
|
||||
@ -346,12 +392,12 @@ void CanvasImpl::linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const
|
||||
CGContextRestoreGState(_context);
|
||||
}
|
||||
|
||||
void CanvasImpl::radialGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
void CanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
CGContextSaveGState(_context);
|
||||
CGContextBeginPath(_context);
|
||||
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) {
|
||||
CGContextAddPath(context, nativePath);
|
||||
});
|
||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
||||
CGContextRestoreGState(_context);
|
||||
return;
|
||||
}
|
||||
|
||||
CGContextSetLineWidth(_context, lineWidth);
|
||||
|
||||
@ -467,10 +513,6 @@ void CanvasImpl::concatenate(lottie::CATransform3D const &transform) {
|
||||
CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform)));
|
||||
}
|
||||
|
||||
lottie::CATransform3D CanvasImpl::currentTransform() {
|
||||
return lottie::fromNativeTransform(CATransform3DMakeAffineTransform(CGContextGetCTM(_context)));
|
||||
}
|
||||
|
||||
std::shared_ptr<Image> CanvasImpl::makeImage() const {
|
||||
::CGImageRef nativeImage = CGBitmapContextCreateImage(_context);
|
||||
if (nativeImage) {
|
||||
|
@ -0,0 +1,47 @@
|
||||
#ifndef NullCanvasImpl_h
|
||||
#define NullCanvasImpl_h
|
||||
|
||||
#include "Canvas.h"
|
||||
|
||||
namespace lottieRendering {
|
||||
|
||||
class NullCanvasImpl: public Canvas {
|
||||
public:
|
||||
NullCanvasImpl(int width, int height);
|
||||
virtual ~NullCanvasImpl();
|
||||
|
||||
virtual int width() const override;
|
||||
virtual int height() const override;
|
||||
|
||||
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
||||
|
||||
virtual void saveState() override;
|
||||
virtual void restoreState() override;
|
||||
|
||||
virtual void fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
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::CATransform3D const &transform) override;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
||||
void flush();
|
||||
|
||||
private:
|
||||
float _width = 0.0f;
|
||||
float _height = 0.0f;
|
||||
lottie::CATransform3D _transform;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,81 @@
|
||||
#include "NullCanvasImpl.h"
|
||||
|
||||
namespace lottieRendering {
|
||||
|
||||
namespace {
|
||||
|
||||
void addEnumeratedPath(CanvasPathEnumerator const &enumeratePath) {
|
||||
enumeratePath([&](PathCommand const &command) {
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NullCanvasImpl::NullCanvasImpl(int width, int height) :
|
||||
_width(width), _height(height), _transform(lottie::CATransform3D::identity()) {
|
||||
}
|
||||
|
||||
NullCanvasImpl::~NullCanvasImpl() {
|
||||
}
|
||||
|
||||
int NullCanvasImpl::width() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
int NullCanvasImpl::height() const {
|
||||
return _height;
|
||||
}
|
||||
|
||||
std::shared_ptr<Canvas> NullCanvasImpl::makeLayer(int width, int height) {
|
||||
return std::make_shared<NullCanvasImpl>(width, height);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::saveState() {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::restoreState() {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
addEnumeratedPath(enumeratePath);
|
||||
}
|
||||
|
||||
void NullCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::setBlendMode(BlendMode blendMode) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::setAlpha(float alpha) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::concatenate(lottie::CATransform3D const &transform) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
||||
}
|
||||
|
||||
void NullCanvasImpl::flush() {
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#import "Canvas.h"
|
||||
#import "CoreGraphicsCanvasImpl.h"
|
||||
#import "ThorVGCanvasImpl.h"
|
||||
#import "NullCanvasImpl.h"
|
||||
|
||||
#include <LottieCpp/RenderTreeNode.h>
|
||||
|
||||
@ -10,6 +11,8 @@ namespace {
|
||||
|
||||
static constexpr float minVisibleAlpha = 0.5f / 255.0f;
|
||||
|
||||
static constexpr float minGlobalRectCalculationSize = 200.0f;
|
||||
|
||||
struct TransformedPath {
|
||||
lottie::BezierPath path;
|
||||
lottie::CATransform3D transform;
|
||||
@ -53,9 +56,7 @@ static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTre
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
static std::vector<TransformedPath> collectPaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform) {
|
||||
std::vector<TransformedPath> mappedPaths;
|
||||
|
||||
static void enumeratePaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform, std::function<void(lottie::BezierPath const &path, lottie::CATransform3D const &transform)> const &onPath) {
|
||||
//TODO:remove skipApplyTransform
|
||||
lottie::CATransform3D effectiveTransform = parentTransform;
|
||||
if (!skipApplyTransform && item->isGroup) {
|
||||
@ -65,21 +66,14 @@ static std::vector<TransformedPath> collectPaths(std::shared_ptr<lottie::RenderT
|
||||
size_t maxSubitem = std::min(item->subItems.size(), subItemLimit);
|
||||
|
||||
if (item->path) {
|
||||
mappedPaths.emplace_back(item->path->path, effectiveTransform);
|
||||
onPath(item->path->path, effectiveTransform);
|
||||
}
|
||||
assert(!item->trimParams);
|
||||
|
||||
for (size_t i = 0; i < maxSubitem; i++) {
|
||||
auto &subItem = item->subItems[i];
|
||||
|
||||
auto subItemPaths = collectPaths(subItem, INT32_MAX, effectiveTransform, false);
|
||||
|
||||
for (auto &path : subItemPaths) {
|
||||
mappedPaths.emplace_back(path.path, path.transform);
|
||||
}
|
||||
enumeratePaths(subItem, INT32_MAX, effectiveTransform, false, onPath);
|
||||
}
|
||||
|
||||
return mappedPaths;
|
||||
}
|
||||
|
||||
}
|
||||
@ -187,7 +181,7 @@ static std::optional<CGRect> getRenderNodeGlobalRect(std::shared_ptr<RenderTreeN
|
||||
|
||||
namespace {
|
||||
|
||||
static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> parentContext, std::shared_ptr<lottie::RenderTreeNodeContentItem> item, float parentAlpha, lottie::Vector2D const &globalSize, lottie::CATransform3D 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::CATransform3D const &parentTransform, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
auto currentTransform = parentTransform;
|
||||
lottie::CATransform3D localTransform = item->transform;
|
||||
currentTransform = localTransform * currentTransform;
|
||||
@ -201,7 +195,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
|
||||
parentContext->saveState();
|
||||
|
||||
std::shared_ptr<lottieRendering::Canvas> currentContext;
|
||||
std::shared_ptr<lottieRendering::Canvas> const *currentContext;
|
||||
std::shared_ptr<lottieRendering::Canvas> tempContext;
|
||||
|
||||
bool needsTempContext = false;
|
||||
@ -209,7 +203,11 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
|
||||
std::optional<lottie::CGRect> globalRect;
|
||||
if (needsTempContext) {
|
||||
globalRect = lottie::getRenderContentItemGlobalRect(item, globalSize, parentTransform, bezierPathsBoundingBoxContext);
|
||||
if (globalSize.x <= minGlobalRectCalculationSize && globalSize.y <= minGlobalRectCalculationSize) {
|
||||
globalRect = lottie::CGRect(0.0, 0.0, globalSize.x, globalSize.y);
|
||||
} else {
|
||||
globalRect = lottie::getRenderContentItemGlobalRect(item, globalSize, parentTransform, bezierPathsBoundingBoxContext);
|
||||
}
|
||||
if (!globalRect || globalRect->width <= 0.0f || globalRect->height <= 0.0f) {
|
||||
parentContext->restoreState();
|
||||
return;
|
||||
@ -218,13 +216,13 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
auto tempContextValue = parentContext->makeLayer((int)(globalRect->width), (int)(globalRect->height));
|
||||
tempContext = tempContextValue;
|
||||
|
||||
currentContext = tempContextValue;
|
||||
currentContext->concatenate(lottie::CATransform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
currentContext = &tempContext;
|
||||
(*currentContext)->concatenate(lottie::CATransform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
|
||||
|
||||
currentContext->saveState();
|
||||
currentContext->concatenate(currentTransform);
|
||||
(*currentContext)->saveState();
|
||||
(*currentContext)->concatenate(currentTransform);
|
||||
} else {
|
||||
currentContext = parentContext;
|
||||
currentContext = &parentContext;
|
||||
}
|
||||
|
||||
parentContext->concatenate(item->transform);
|
||||
@ -237,75 +235,105 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
}
|
||||
|
||||
for (const auto &shading : item->shadings) {
|
||||
std::vector<lottie::BezierPath> itemPaths;
|
||||
lottieRendering::CanvasPathEnumerator iteratePaths;
|
||||
if (shading->explicitPath) {
|
||||
itemPaths = shading->explicitPath.value();
|
||||
} else {
|
||||
auto rawPaths = collectPaths(item, shading->subItemLimit, lottie::CATransform3D::identity(), true);
|
||||
for (const auto &rawPath : rawPaths) {
|
||||
itemPaths.push_back(rawPath.path.copyUsingTransform(rawPath.transform));
|
||||
}
|
||||
}
|
||||
|
||||
if (itemPaths.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 : itemPaths) {
|
||||
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);
|
||||
auto itemPaths = shading->explicitPath.value();
|
||||
iteratePaths = [itemPaths = itemPaths](std::function<void(lottieRendering::PathCommand const &)> iterate) -> void {
|
||||
lottieRendering::PathCommand pathCommand;
|
||||
for (const auto &path : itemPaths) {
|
||||
std::optional<lottie::PathElement> previousElement;
|
||||
for (const auto &element : path.elements()) {
|
||||
if (previousElement.has_value()) {
|
||||
if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::LineTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::CurveTo;
|
||||
pathCommand.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
pathCommand.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y);
|
||||
pathCommand.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::MoveTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
previousElement = element;
|
||||
}
|
||||
if (path.closed().value_or(true)) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::Close;
|
||||
iterate(pathCommand);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
iteratePaths = [&](std::function<void(lottieRendering::PathCommand const &)> iterate) {
|
||||
enumeratePaths(item, shading->subItemLimit, lottie::CATransform3D::identity(), true, [&](lottie::BezierPath const &sourcePath, lottie::CATransform3D const &transform) {
|
||||
auto path = sourcePath.copyUsingTransform(transform);
|
||||
|
||||
lottieRendering::PathCommand pathCommand;
|
||||
std::optional<lottie::PathElement> previousElement;
|
||||
for (const auto &element : path.elements()) {
|
||||
if (previousElement.has_value()) {
|
||||
if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::LineTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::CurveTo;
|
||||
pathCommand.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
pathCommand.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y);
|
||||
pathCommand.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::MoveTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
previousElement = element;
|
||||
}
|
||||
if (path.closed().value_or(true)) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::Close;
|
||||
iterate(pathCommand);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/*auto iteratePaths = [&](std::function<void(lottieRendering::PathCommand const &)> iterate) -> void {
|
||||
lottieRendering::PathCommand pathCommand;
|
||||
for (const auto &path : itemPaths) {
|
||||
std::optional<lottie::PathElement> previousElement;
|
||||
for (const auto &element : path.elements()) {
|
||||
if (previousElement.has_value()) {
|
||||
if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::LineTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::CurveTo;
|
||||
pathCommand.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
pathCommand.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y);
|
||||
pathCommand.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
} else {
|
||||
pathCommand.type = lottieRendering::PathCommandType::MoveTo;
|
||||
pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
|
||||
iterate(pathCommand);
|
||||
}
|
||||
previousElement = element;
|
||||
}
|
||||
if (path.closed().value_or(true)) {
|
||||
pathCommand.type = lottieRendering::PathCommandType::Close;
|
||||
iterate(pathCommand);
|
||||
}
|
||||
}
|
||||
};*/
|
||||
|
||||
if (shading->stroke) {
|
||||
if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) {
|
||||
lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->stroke->shading.get();
|
||||
@ -354,7 +382,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
dashPattern = shading->stroke->dashPattern;
|
||||
}
|
||||
|
||||
currentContext->strokePath(path, shading->stroke->lineWidth, lineJoin, lineCap, shading->stroke->dashPhase, dashPattern, lottie::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity * renderAlpha));
|
||||
(*currentContext)->strokePath(iteratePaths, shading->stroke->lineWidth, lineJoin, lineCap, shading->stroke->dashPhase, dashPattern, lottie::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity * renderAlpha));
|
||||
} else if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) {
|
||||
//TODO:gradient stroke
|
||||
}
|
||||
@ -378,7 +406,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) {
|
||||
lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->fill->shading.get();
|
||||
if (solidShading->opacity != 0.0) {
|
||||
currentContext->fillPath(path, rule, lottie::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity * renderAlpha));
|
||||
(*currentContext)->fillPath(iteratePaths, rule, lottie::Color(solidShading->color.r, solidShading->color.g, solidShading->color.b, solidShading->color.a * solidShading->opacity * renderAlpha));
|
||||
}
|
||||
} else if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) {
|
||||
lottie::RenderTreeNodeContentItem::GradientShading *gradientShading = (lottie::RenderTreeNodeContentItem::GradientShading *)shading->fill->shading.get();
|
||||
@ -397,11 +425,11 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
|
||||
switch (gradientShading->gradientType) {
|
||||
case lottie::GradientType::Linear: {
|
||||
currentContext->linearGradientFillPath(path, rule, gradient, start, end);
|
||||
(*currentContext)->linearGradientFillPath(iteratePaths, rule, gradient, start, end);
|
||||
break;
|
||||
}
|
||||
case lottie::GradientType::Radial: {
|
||||
currentContext->radialGradientFillPath(path, rule, gradient, start, 0.0, start, start.distanceTo(end));
|
||||
(*currentContext)->radialGradientFillPath(iteratePaths, rule, gradient, start, 0.0, start, start.distanceTo(end));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -415,7 +443,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
|
||||
for (auto it = item->subItems.rbegin(); it != item->subItems.rend(); it++) {
|
||||
const auto &subItem = *it;
|
||||
drawLottieContentItem(currentContext, subItem, renderAlpha, globalSize, currentTransform, bezierPathsBoundingBoxContext);
|
||||
drawLottieContentItem(*currentContext, subItem, renderAlpha, globalSize, currentTransform, bezierPathsBoundingBoxContext);
|
||||
}
|
||||
|
||||
if (tempContext) {
|
||||
@ -430,7 +458,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
|
||||
parentContext->restoreState();
|
||||
}
|
||||
|
||||
static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node, std::shared_ptr<lottieRendering::Canvas> parentContext, lottie::Vector2D const &globalSize, lottie::CATransform3D 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::CATransform3D const &parentTransform, float parentAlpha, bool isInvertedMatte, lottie::BezierPathsBoundingBoxContext &bezierPathsBoundingBoxContext) {
|
||||
float normalizedOpacity = node->alpha();
|
||||
float layerAlpha = ((float)normalizedOpacity) * parentAlpha;
|
||||
|
||||
@ -470,7 +498,11 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
|
||||
|
||||
std::optional<lottie::CGRect> globalRect;
|
||||
if (needsTempContext) {
|
||||
globalRect = lottie::getRenderNodeGlobalRect(node, globalSize, parentTransform, false, bezierPathsBoundingBoxContext);
|
||||
if (globalSize.x <= minGlobalRectCalculationSize && globalSize.y <= minGlobalRectCalculationSize) {
|
||||
globalRect = lottie::CGRect(0.0, 0.0, globalSize.x, globalSize.y);
|
||||
} else {
|
||||
globalRect = lottie::getRenderNodeGlobalRect(node, globalSize, parentTransform, false, bezierPathsBoundingBoxContext);
|
||||
}
|
||||
if (!globalRect || globalRect->width <= 0.0f || globalRect->height <= 0.0f) {
|
||||
parentContext->restoreState();
|
||||
return;
|
||||
@ -578,10 +610,6 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
|
||||
lottie::CATransform3D rootTransform = lottie::CATransform3D::identity().scaled(lottie::Vector2D(size.width / (float)animation.size.width, size.height / (float)animation.size.height));
|
||||
|
||||
if (!useReferenceRendering) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (useReferenceRendering) {
|
||||
auto context = std::make_shared<lottieRendering::CanvasImpl>((int)size.width, (int)size.height);
|
||||
|
||||
@ -594,12 +622,13 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
||||
|
||||
return [[UIImage alloc] initWithCGImage:std::static_pointer_cast<lottieRendering::ImageImpl>(image)->nativeImage()];
|
||||
} else {
|
||||
/*auto context = std::make_shared<lottieRendering::ThorVGCanvasImpl>((int)size.width, (int)size.height);
|
||||
//auto context = std::make_shared<lottieRendering::ThorVGCanvasImpl>((int)size.width, (int)size.height);
|
||||
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::CATransform3D::makeScale(scale.x, scale.y, 1.0));
|
||||
|
||||
renderLottieRenderNode(renderNode, context, lottie::Vector2D(context->width(), context->height()), 1.0);*/
|
||||
renderLottieRenderNode(renderNode, context, lottie::Vector2D(context->width(), context->height()), rootTransform, 1.0, false, *_bezierPathsBoundingBoxContext.get());
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
@ -20,12 +20,12 @@ public:
|
||||
virtual void saveState() override;
|
||||
virtual void restoreState() override;
|
||||
|
||||
virtual void fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void strokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) override;
|
||||
virtual void linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottieRendering::Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) override;
|
||||
virtual void linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) override;
|
||||
virtual void radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) override;
|
||||
virtual void fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override;
|
||||
|
||||
virtual void setBlendMode(BlendMode blendMode) override;
|
||||
@ -33,7 +33,6 @@ public:
|
||||
virtual void setAlpha(float alpha) override;
|
||||
|
||||
virtual void concatenate(lottie::CATransform3D const &transform) override;
|
||||
virtual lottie::CATransform3D currentTransform() override;
|
||||
|
||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
||||
|
||||
|
@ -4,22 +4,22 @@ namespace lottieRendering {
|
||||
|
||||
namespace {
|
||||
|
||||
void tvgPath(std::shared_ptr<lottie::CGPath> const &path, tvg::Shape *shape) {
|
||||
path->enumerate([shape](lottie::CGPathItem const &item) {
|
||||
switch (item.type) {
|
||||
case lottie::CGPathItem::Type::MoveTo: {
|
||||
shape->moveTo(item.points[0].x, item.points[0].y);
|
||||
void tvgPath(CanvasPathEnumerator const &enumeratePath, tvg::Shape *shape) {
|
||||
enumeratePath([&](PathCommand const &command) {
|
||||
switch (command.type) {
|
||||
case PathCommandType::MoveTo: {
|
||||
shape->moveTo(command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case lottie::CGPathItem::Type::LineTo: {
|
||||
shape->lineTo(item.points[0].x, item.points[0].y);
|
||||
case PathCommandType::LineTo: {
|
||||
shape->lineTo(command.points[0].x, command.points[0].y);
|
||||
break;
|
||||
}
|
||||
case lottie::CGPathItem::Type::CurveTo: {
|
||||
shape->cubicTo(item.points[0].x, item.points[0].y, item.points[1].x, item.points[1].y, item.points[2].x, item.points[2].y);
|
||||
case PathCommandType::CurveTo: {
|
||||
shape->cubicTo(command.points[0].x, command.points[0].y, command.points[1].x, command.points[1].y, command.points[2].x, command.points[2].y);
|
||||
break;
|
||||
}
|
||||
case lottie::CGPathItem::Type::Close: {
|
||||
case PathCommandType::Close: {
|
||||
shape->close();
|
||||
break;
|
||||
}
|
||||
@ -89,9 +89,9 @@ void ThorVGCanvasImpl::restoreState() {
|
||||
_stateStack.pop_back();
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
void ThorVGCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||
auto shape = tvg::Shape::gen();
|
||||
tvgPath(path, shape.get());
|
||||
tvgPath(enumeratePath, shape.get());
|
||||
|
||||
shape->transform(tvgTransform(_transform));
|
||||
|
||||
@ -101,9 +101,9 @@ void ThorVGCanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lot
|
||||
_canvas->push(std::move(shape));
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
void ThorVGCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
auto shape = tvg::Shape::gen();
|
||||
tvgPath(path, shape.get());
|
||||
tvgPath(enumeratePath, shape.get());
|
||||
|
||||
shape->transform(tvgTransform(_transform));
|
||||
|
||||
@ -129,9 +129,9 @@ void ThorVGCanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> co
|
||||
_canvas->push(std::move(shape));
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
void ThorVGCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
auto shape = tvg::Shape::gen();
|
||||
tvgPath(path, shape.get());
|
||||
tvgPath(enumeratePath, shape.get());
|
||||
|
||||
shape->transform(tvgTransform(_transform));
|
||||
|
||||
@ -157,9 +157,9 @@ void ThorVGCanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> co
|
||||
_canvas->push(std::move(shape));
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
void ThorVGCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, lottie::Color const &color) {
|
||||
auto shape = tvg::Shape::gen();
|
||||
tvgPath(path, shape.get());
|
||||
tvgPath(enumeratePath, shape.get());
|
||||
|
||||
shape->transform(tvgTransform(_transform));
|
||||
|
||||
@ -217,12 +217,10 @@ void ThorVGCanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, f
|
||||
_canvas->push(std::move(shape));
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
assert(false);
|
||||
void ThorVGCanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::radialGradientStrokePath(std::shared_ptr<lottie::CGPath> const &path, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
assert(false);
|
||||
void ThorVGCanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) {
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) {
|
||||
@ -271,10 +269,6 @@ void ThorVGCanvasImpl::concatenate(lottie::CATransform3D const &transform) {
|
||||
));*/
|
||||
}
|
||||
|
||||
lottie::CATransform3D ThorVGCanvasImpl::currentTransform() {
|
||||
return _transform;
|
||||
}
|
||||
|
||||
void ThorVGCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
||||
/*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get();
|
||||
auto image = impl->surface()->makeImageSnapshot();
|
||||
|
@ -78,7 +78,7 @@ private final class ReferenceCompareTest {
|
||||
}
|
||||
|
||||
var continueFromName: String?
|
||||
//continueFromName = "4986037051573928320.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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user