This commit is contained in:
Isaac 2024-05-19 02:04:45 +04:00
parent 41c88223b4
commit 814852d902
9 changed files with 385 additions and 180 deletions

View File

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <cassert> #include <cassert>
#include <functional>
namespace lottieRendering { namespace lottieRendering {
@ -41,6 +42,20 @@ enum class BlendMode {
DestinationOut 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 { class Canvas {
public: public:
virtual ~Canvas() = default; virtual ~Canvas() = default;
@ -53,13 +68,13 @@ public:
virtual void saveState() = 0; virtual void saveState() = 0;
virtual void restoreState() = 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 fillPath(CanvasPathEnumerator const &enumeratePath, 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 linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, 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 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 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(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 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(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 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 fill(lottie::CGRect const &rect, lottie::Color const &fillColor) = 0;
virtual void setBlendMode(BlendMode blendMode) = 0; virtual void setBlendMode(BlendMode blendMode) = 0;
@ -67,7 +82,6 @@ public:
virtual void setAlpha(float alpha) = 0; virtual void setAlpha(float alpha) = 0;
virtual void concatenate(lottie::CATransform3D const &transform) = 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; virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) = 0;
}; };

View File

@ -29,19 +29,18 @@ public:
virtual void saveState() override; virtual void saveState() override;
virtual void restoreState() 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 fillPath(CanvasPathEnumerator const &enumeratePath, 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 linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, 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 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 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(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 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(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 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 fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override;
virtual void setBlendMode(BlendMode blendMode) override; virtual void setBlendMode(BlendMode blendMode) override;
virtual void setAlpha(float alpha) override; virtual void setAlpha(float alpha) override;
virtual void concatenate(lottie::CATransform3D const &transform) override; virtual void concatenate(lottie::CATransform3D const &transform) override;
virtual lottie::CATransform3D currentTransform() override;
virtual std::shared_ptr<Image> makeImage() const; virtual std::shared_ptr<Image> makeImage() const;
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override; virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;

View File

@ -11,6 +11,52 @@ int alignUp(int size, int align) {
return (size + alignmentMask) & ~alignmentMask; 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) { ImageImpl::ImageImpl(::CGImageRef image) {
@ -87,11 +133,10 @@ void CanvasImpl::restoreState() {
CGContextRestoreGState(_context); CGContextRestoreGState(_context);
} }
void CanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lottie::FillRule fillRule, lottie::Color const &color) { void CanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
CGContextBeginPath(_context); if (!addEnumeratedPath(_context, enumeratePath)) {
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { return;
CGContextAddPath(context, nativePath); }
});
CGFloat components[4] = { color.r, color.g, color.b, color.a }; CGFloat components[4] = { color.r, color.g, color.b, color.a };
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components); 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); CGContextSaveGState(_context);
CGContextBeginPath(_context);
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { if (!addEnumeratedPath(_context, enumeratePath)) {
CGContextAddPath(context, nativePath); CGContextRestoreGState(_context);
}); return;
}
switch (fillRule) { switch (fillRule) {
case lottie::FillRule::EvenOdd: { case lottie::FillRule::EvenOdd: {
@ -155,12 +201,13 @@ void CanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> const &p
CGContextRestoreGState(_context); 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); CGContextSaveGState(_context);
CGContextBeginPath(_context);
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { if (!addEnumeratedPath(_context, enumeratePath)) {
CGContextAddPath(context, nativePath); CGContextRestoreGState(_context);
}); return;
}
switch (fillRule) { switch (fillRule) {
case lottie::FillRule::EvenOdd: { case lottie::FillRule::EvenOdd: {
@ -200,11 +247,10 @@ void CanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> const &p
CGContextRestoreGState(_context); 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) { 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) {
CGContextBeginPath(_context); if (!addEnumeratedPath(_context, enumeratePath)) {
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { return;
CGContextAddPath(context, nativePath); }
});
CGFloat components[4] = { color.r, color.g, color.b, color.a }; CGFloat components[4] = { color.r, color.g, color.b, color.a };
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components); CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components);
@ -261,12 +307,12 @@ void CanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, float l
CGContextStrokePath(_context); 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); CGContextSaveGState(_context);
CGContextBeginPath(_context); if (!addEnumeratedPath(_context, enumeratePath)) {
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { CGContextRestoreGState(_context);
CGContextAddPath(context, nativePath); return;
}); }
CGContextSetLineWidth(_context, lineWidth); CGContextSetLineWidth(_context, lineWidth);
@ -346,12 +392,12 @@ void CanvasImpl::linearGradientStrokePath(std::shared_ptr<lottie::CGPath> const
CGContextRestoreGState(_context); 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); CGContextSaveGState(_context);
CGContextBeginPath(_context); if (!addEnumeratedPath(_context, enumeratePath)) {
lottie::CGPathCocoaImpl::withNativePath(path, [context = _context](CGPathRef nativePath) { CGContextRestoreGState(_context);
CGContextAddPath(context, nativePath); return;
}); }
CGContextSetLineWidth(_context, lineWidth); CGContextSetLineWidth(_context, lineWidth);
@ -467,10 +513,6 @@ void CanvasImpl::concatenate(lottie::CATransform3D const &transform) {
CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform))); CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform)));
} }
lottie::CATransform3D CanvasImpl::currentTransform() {
return lottie::fromNativeTransform(CATransform3DMakeAffineTransform(CGContextGetCTM(_context)));
}
std::shared_ptr<Image> CanvasImpl::makeImage() const { std::shared_ptr<Image> CanvasImpl::makeImage() const {
::CGImageRef nativeImage = CGBitmapContextCreateImage(_context); ::CGImageRef nativeImage = CGBitmapContextCreateImage(_context);
if (nativeImage) { if (nativeImage) {

View File

@ -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

View File

@ -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() {
}
}

View File

@ -3,6 +3,7 @@
#import "Canvas.h" #import "Canvas.h"
#import "CoreGraphicsCanvasImpl.h" #import "CoreGraphicsCanvasImpl.h"
#import "ThorVGCanvasImpl.h" #import "ThorVGCanvasImpl.h"
#import "NullCanvasImpl.h"
#include <LottieCpp/RenderTreeNode.h> #include <LottieCpp/RenderTreeNode.h>
@ -10,6 +11,8 @@ namespace {
static constexpr float minVisibleAlpha = 0.5f / 255.0f; static constexpr float minVisibleAlpha = 0.5f / 255.0f;
static constexpr float minGlobalRectCalculationSize = 200.0f;
struct TransformedPath { struct TransformedPath {
lottie::BezierPath path; lottie::BezierPath path;
lottie::CATransform3D transform; lottie::CATransform3D transform;
@ -53,9 +56,7 @@ static lottie::CGRect collectPathBoundingBoxes(std::shared_ptr<lottie::RenderTre
return boundingBox; return boundingBox;
} }
static std::vector<TransformedPath> collectPaths(std::shared_ptr<lottie::RenderTreeNodeContentItem> item, size_t subItemLimit, lottie::CATransform3D const &parentTransform, bool skipApplyTransform) { 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) {
std::vector<TransformedPath> mappedPaths;
//TODO:remove skipApplyTransform //TODO:remove skipApplyTransform
lottie::CATransform3D effectiveTransform = parentTransform; lottie::CATransform3D effectiveTransform = parentTransform;
if (!skipApplyTransform && item->isGroup) { 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); size_t maxSubitem = std::min(item->subItems.size(), subItemLimit);
if (item->path) { 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++) { for (size_t i = 0; i < maxSubitem; i++) {
auto &subItem = item->subItems[i]; auto &subItem = item->subItems[i];
auto subItemPaths = collectPaths(subItem, INT32_MAX, effectiveTransform, false); enumeratePaths(subItem, INT32_MAX, effectiveTransform, false, onPath);
for (auto &path : subItemPaths) {
mappedPaths.emplace_back(path.path, path.transform);
}
} }
return mappedPaths;
} }
} }
@ -187,7 +181,7 @@ static std::optional<CGRect> getRenderNodeGlobalRect(std::shared_ptr<RenderTreeN
namespace { 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; auto currentTransform = parentTransform;
lottie::CATransform3D localTransform = item->transform; lottie::CATransform3D localTransform = item->transform;
currentTransform = localTransform * currentTransform; currentTransform = localTransform * currentTransform;
@ -201,7 +195,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
parentContext->saveState(); parentContext->saveState();
std::shared_ptr<lottieRendering::Canvas> currentContext; std::shared_ptr<lottieRendering::Canvas> const *currentContext;
std::shared_ptr<lottieRendering::Canvas> tempContext; std::shared_ptr<lottieRendering::Canvas> tempContext;
bool needsTempContext = false; bool needsTempContext = false;
@ -209,7 +203,11 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
std::optional<lottie::CGRect> globalRect; std::optional<lottie::CGRect> globalRect;
if (needsTempContext) { 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) { if (!globalRect || globalRect->width <= 0.0f || globalRect->height <= 0.0f) {
parentContext->restoreState(); parentContext->restoreState();
return; return;
@ -218,13 +216,13 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
auto tempContextValue = parentContext->makeLayer((int)(globalRect->width), (int)(globalRect->height)); auto tempContextValue = parentContext->makeLayer((int)(globalRect->width), (int)(globalRect->height));
tempContext = tempContextValue; tempContext = tempContextValue;
currentContext = tempContextValue; currentContext = &tempContext;
currentContext->concatenate(lottie::CATransform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y))); (*currentContext)->concatenate(lottie::CATransform3D::identity().translated(lottie::Vector2D(-globalRect->x, -globalRect->y)));
currentContext->saveState(); (*currentContext)->saveState();
currentContext->concatenate(currentTransform); (*currentContext)->concatenate(currentTransform);
} else { } else {
currentContext = parentContext; currentContext = &parentContext;
} }
parentContext->concatenate(item->transform); parentContext->concatenate(item->transform);
@ -237,75 +235,105 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
} }
for (const auto &shading : item->shadings) { for (const auto &shading : item->shadings) {
std::vector<lottie::BezierPath> itemPaths; lottieRendering::CanvasPathEnumerator iteratePaths;
if (shading->explicitPath) { if (shading->explicitPath) {
itemPaths = shading->explicitPath.value(); auto itemPaths = shading->explicitPath.value();
} else { iteratePaths = [itemPaths = itemPaths](std::function<void(lottieRendering::PathCommand const &)> iterate) -> void {
auto rawPaths = collectPaths(item, shading->subItemLimit, lottie::CATransform3D::identity(), true); lottieRendering::PathCommand pathCommand;
for (const auto &rawPath : rawPaths) { for (const auto &path : itemPaths) {
itemPaths.push_back(rawPath.path.copyUsingTransform(rawPath.transform)); std::optional<lottie::PathElement> previousElement;
} for (const auto &element : path.elements()) {
} if (previousElement.has_value()) {
if (previousElement->vertex.outTangentRelative().isZero() && element.vertex.inTangentRelative().isZero()) {
if (itemPaths.empty()) { pathCommand.type = lottieRendering::PathCommandType::LineTo;
continue; pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
} iterate(pathCommand);
} else {
std::shared_ptr<lottie::CGPath> path = lottie::CGPath::makePath(); pathCommand.type = lottieRendering::PathCommandType::CurveTo;
pathCommand.points[2] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
const auto iterate = [&](LottiePathItem const *pathItem) { pathCommand.points[1] = CGPointMake(element.vertex.inTangent.x, element.vertex.inTangent.y);
switch (pathItem->type) { pathCommand.points[0] = CGPointMake(previousElement->vertex.outTangent.x, previousElement->vertex.outTangent.y);
case LottiePathItemTypeMoveTo: { iterate(pathCommand);
path->moveTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y)); }
break; } else {
} pathCommand.type = lottieRendering::PathCommandType::MoveTo;
case LottiePathItemTypeLineTo: { pathCommand.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
path->addLineTo(lottie::Vector2D(pathItem->points[0].x, pathItem->points[0].y)); iterate(pathCommand);
break; }
} previousElement = element;
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)); if (path.closed().value_or(true)) {
break; pathCommand.type = lottieRendering::PathCommandType::Close;
} iterate(pathCommand);
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);
} }
} else {
pathItem.type = LottiePathItemTypeMoveTo;
pathItem.points[0] = CGPointMake(element.vertex.point.x, element.vertex.point.y);
iterate(&pathItem);
} }
previousElement = element; };
} } else {
if (path.closed().value_or(true)) { iteratePaths = [&](std::function<void(lottieRendering::PathCommand const &)> iterate) {
pathItem.type = LottiePathItemTypeClose; enumeratePaths(item, shading->subItemLimit, lottie::CATransform3D::identity(), true, [&](lottie::BezierPath const &sourcePath, lottie::CATransform3D const &transform) {
iterate(&pathItem); 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) {
if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) { if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) {
lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->stroke->shading.get(); 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; 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) { } else if (shading->stroke->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) {
//TODO:gradient stroke //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) { if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Solid) {
lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->fill->shading.get(); lottie::RenderTreeNodeContentItem::SolidShading *solidShading = (lottie::RenderTreeNodeContentItem::SolidShading *)shading->fill->shading.get();
if (solidShading->opacity != 0.0) { 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) { } else if (shading->fill->shading->type() == lottie::RenderTreeNodeContentItem::ShadingType::Gradient) {
lottie::RenderTreeNodeContentItem::GradientShading *gradientShading = (lottie::RenderTreeNodeContentItem::GradientShading *)shading->fill->shading.get(); 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) { switch (gradientShading->gradientType) {
case lottie::GradientType::Linear: { case lottie::GradientType::Linear: {
currentContext->linearGradientFillPath(path, rule, gradient, start, end); (*currentContext)->linearGradientFillPath(iteratePaths, rule, gradient, start, end);
break; break;
} }
case lottie::GradientType::Radial: { 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; break;
} }
default: { 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++) { for (auto it = item->subItems.rbegin(); it != item->subItems.rend(); it++) {
const auto &subItem = *it; const auto &subItem = *it;
drawLottieContentItem(currentContext, subItem, renderAlpha, globalSize, currentTransform, bezierPathsBoundingBoxContext); drawLottieContentItem(*currentContext, subItem, renderAlpha, globalSize, currentTransform, bezierPathsBoundingBoxContext);
} }
if (tempContext) { if (tempContext) {
@ -430,7 +458,7 @@ static void drawLottieContentItem(std::shared_ptr<lottieRendering::Canvas> paren
parentContext->restoreState(); 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 normalizedOpacity = node->alpha();
float layerAlpha = ((float)normalizedOpacity) * parentAlpha; float layerAlpha = ((float)normalizedOpacity) * parentAlpha;
@ -470,7 +498,11 @@ static void renderLottieRenderNode(std::shared_ptr<lottie::RenderTreeNode> node,
std::optional<lottie::CGRect> globalRect; std::optional<lottie::CGRect> globalRect;
if (needsTempContext) { 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) { if (!globalRect || globalRect->width <= 0.0f || globalRect->height <= 0.0f) {
parentContext->restoreState(); parentContext->restoreState();
return; 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)); 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) { if (useReferenceRendering) {
auto context = std::make_shared<lottieRendering::CanvasImpl>((int)size.width, (int)size.height); 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()]; return [[UIImage alloc] initWithCGImage:std::static_pointer_cast<lottieRendering::ImageImpl>(image)->nativeImage()];
} else { } 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); 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)); 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; return nil;
} }

View File

@ -20,12 +20,12 @@ public:
virtual void saveState() override; virtual void saveState() override;
virtual void restoreState() 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 fillPath(CanvasPathEnumerator const &enumeratePath, 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 linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, 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 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(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 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(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 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(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 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 fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override;
virtual void setBlendMode(BlendMode blendMode) override; virtual void setBlendMode(BlendMode blendMode) override;
@ -33,7 +33,6 @@ public:
virtual void setAlpha(float alpha) override; virtual void setAlpha(float alpha) override;
virtual void concatenate(lottie::CATransform3D const &transform) 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; virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;

View File

@ -4,22 +4,22 @@ namespace lottieRendering {
namespace { namespace {
void tvgPath(std::shared_ptr<lottie::CGPath> const &path, tvg::Shape *shape) { void tvgPath(CanvasPathEnumerator const &enumeratePath, tvg::Shape *shape) {
path->enumerate([shape](lottie::CGPathItem const &item) { enumeratePath([&](PathCommand const &command) {
switch (item.type) { switch (command.type) {
case lottie::CGPathItem::Type::MoveTo: { case PathCommandType::MoveTo: {
shape->moveTo(item.points[0].x, item.points[0].y); shape->moveTo(command.points[0].x, command.points[0].y);
break; break;
} }
case lottie::CGPathItem::Type::LineTo: { case PathCommandType::LineTo: {
shape->lineTo(item.points[0].x, item.points[0].y); shape->lineTo(command.points[0].x, command.points[0].y);
break; break;
} }
case lottie::CGPathItem::Type::CurveTo: { case PathCommandType::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); 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; break;
} }
case lottie::CGPathItem::Type::Close: { case PathCommandType::Close: {
shape->close(); shape->close();
break; break;
} }
@ -89,9 +89,9 @@ void ThorVGCanvasImpl::restoreState() {
_stateStack.pop_back(); _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(); auto shape = tvg::Shape::gen();
tvgPath(path, shape.get()); tvgPath(enumeratePath, shape.get());
shape->transform(tvgTransform(_transform)); shape->transform(tvgTransform(_transform));
@ -101,9 +101,9 @@ void ThorVGCanvasImpl::fillPath(std::shared_ptr<lottie::CGPath> const &path, lot
_canvas->push(std::move(shape)); _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(); auto shape = tvg::Shape::gen();
tvgPath(path, shape.get()); tvgPath(enumeratePath, shape.get());
shape->transform(tvgTransform(_transform)); shape->transform(tvgTransform(_transform));
@ -129,9 +129,9 @@ void ThorVGCanvasImpl::linearGradientFillPath(std::shared_ptr<lottie::CGPath> co
_canvas->push(std::move(shape)); _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(); auto shape = tvg::Shape::gen();
tvgPath(path, shape.get()); tvgPath(enumeratePath, shape.get());
shape->transform(tvgTransform(_transform)); shape->transform(tvgTransform(_transform));
@ -157,9 +157,9 @@ void ThorVGCanvasImpl::radialGradientFillPath(std::shared_ptr<lottie::CGPath> co
_canvas->push(std::move(shape)); _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(); auto shape = tvg::Shape::gen();
tvgPath(path, shape.get()); tvgPath(enumeratePath, shape.get());
shape->transform(tvgTransform(_transform)); shape->transform(tvgTransform(_transform));
@ -217,12 +217,10 @@ void ThorVGCanvasImpl::strokePath(std::shared_ptr<lottie::CGPath> const &path, f
_canvas->push(std::move(shape)); _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) { 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) {
assert(false);
} }
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) { 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) {
assert(false);
} }
void ThorVGCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) { 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) { void ThorVGCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
/*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get(); /*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get();
auto image = impl->surface()->makeImageSnapshot(); auto image = impl->surface()->makeImageSnapshot();

View File

@ -78,7 +78,7 @@ private final class ReferenceCompareTest {
} }
var continueFromName: String? var continueFromName: String?
//continueFromName = "4986037051573928320.json" //continueFromName = "35707580709863498.json"
let _ = await processAnimationFolderAsync(basePath: bundlePath, path: "", stopOnFailure: true, process: { path, name, alwaysDraw in let _ = await processAnimationFolderAsync(basePath: bundlePath, path: "", stopOnFailure: true, process: { path, name, alwaysDraw in
if let continueFromNameValue = continueFromName { if let continueFromNameValue = continueFromName {
@ -119,7 +119,7 @@ public final class ViewController: UIViewController {
self.view.layer.addSublayer(MetalEngine.shared.rootLayer) self.view.layer.addSublayer(MetalEngine.shared.rootLayer)
if "".isEmpty { if !"".isEmpty {
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
self.test = ReferenceCompareTest(view: self.view) self.test = ReferenceCompareTest(view: self.view)
} }