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 <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;
};

View File

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

View File

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

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 "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;
}

View File

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

View File

@ -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();

View File

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