From d74e29d7905c9db760a2d64732a39266383dfb49 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Wed, 12 Jun 2024 23:04:22 +0400 Subject: [PATCH] Lottie tests --- .../Sources/CoreGraphicsCanvasImpl.h | 46 ++- .../Sources/CoreGraphicsCanvasImpl.mm | 297 +++++++++--------- .../Sources/SkiaCanvasImpl.cpp | 26 +- .../Sources/SkiaCanvasImpl.h | 10 +- .../Sources/SoftwareLottieRenderer.mm | 4 +- .../Sources/ThorVGCanvasImpl.cpp | 26 +- .../Sources/ThorVGCanvasImpl.h | 10 +- .../Sources/ViewController.swift | 4 +- 8 files changed, 187 insertions(+), 236 deletions(-) diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.h b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.h index 0f4a32be04..0c34cd3c97 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.h +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.h @@ -1,5 +1,5 @@ -#ifndef CoreGraphicsCanvasImpl_h -#define CoreGraphicsCanvasImpl_h +#ifndef CoreGraphicsCoreGraphicsCanvasImpl_h +#define CoreGraphicsCoreGraphicsCanvasImpl_h #include @@ -7,7 +7,9 @@ namespace lottie { -class CanvasImpl: public Canvas { +class CoreGraphicsCanvasImpl: public Canvas { +class Layer; + public: class Image { public: @@ -20,12 +22,9 @@ public: }; public: - CanvasImpl(int width, int height); - CanvasImpl(CGContextRef context, int width, int height); - virtual ~CanvasImpl(); - - virtual int width() const override; - virtual int height() const override; + CoreGraphicsCanvasImpl(int width, int height); + CoreGraphicsCanvasImpl(CGContextRef context, int width, int height); + virtual ~CoreGraphicsCanvasImpl(); std::shared_ptr makeLayer(int width, int height) override; @@ -42,32 +41,23 @@ public: virtual void fill(lottie::CGRect const &rect, lottie::Color const &fillColor) override; virtual void setBlendMode(BlendMode blendMode) override; - virtual void setAlpha(float alpha) override; virtual void concatenate(lottie::Transform2D const &transform) override; - virtual std::shared_ptr makeImage() const; - virtual void draw(std::shared_ptr const &other, lottie::CGRect const &rect) override; + virtual std::shared_ptr makeImage(); + virtual void draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) override; - CGContextRef nativeContext() const { - return _context; - } + virtual void pushLayer(CGRect const &rect) override; + virtual void popLayer() override; - std::vector &backingData() { - return _backingData; - } - - int bytesPerRow() { - return _bytesPerRow; - } + std::vector &backingData(); + int bytesPerRow(); + +private: + std::shared_ptr ¤tLayer(); private: - int _width = 0; - int _height = 0; - int _bytesPerRow = 0; - std::vector _backingData; - CGContextRef _context = nil; CGContextRef _topContext = nil; - CGLayerRef _layer = nil; + std::vector> _layerStack; }; } diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.mm b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.mm index 069155a98e..4ffa901d3c 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.mm +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/CoreGraphicsCanvasImpl.mm @@ -62,116 +62,117 @@ bool addEnumeratedPath(CGContextRef context, CanvasPathEnumerator const &enumera } -CanvasImpl::Image::Image(::CGImageRef image) { +class CoreGraphicsCanvasImpl::Layer { +public: + explicit Layer(int width, int height) { + _width = width; + _height = height; + _bytesPerRow = alignUp(width * 4, 16); + _backingData.resize(_bytesPerRow * _height); + memset(_backingData.data(), 0, _backingData.size()); + + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; + _context = CGBitmapContextCreate(_backingData.data(), _width, _height, 8, _bytesPerRow, colorSpace, bitmapInfo); + CFRelease(colorSpace); + + CGContextClearRect(_context, CGRectMake(0.0, 0.0, _width, _height)); + + } + + ~Layer() { + CGContextRelease(_context); + } + + CGContextRef context() const { + return _context; + } + +public: + CGContextRef _context = nil; + int _width = 0; + int _height = 0; + int _bytesPerRow = 0; + std::vector _backingData; +}; + +CoreGraphicsCanvasImpl::Image::Image(::CGImageRef image) { _image = CGImageRetain(image); } -CanvasImpl::Image::~Image() { +CoreGraphicsCanvasImpl::Image::~Image() { CFRelease(_image); } -::CGImageRef CanvasImpl::Image::nativeImage() const { +::CGImageRef CoreGraphicsCanvasImpl::Image::nativeImage() const { return _image; } -CanvasImpl::CanvasImpl(int width, int height) { - _width = width; - _height = height; - _bytesPerRow = alignUp(width * 4, 16); - _backingData.resize(_bytesPerRow * _height); - memset(_backingData.data(), 0, _backingData.size()); - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - - CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst; - _context = CGBitmapContextCreate(_backingData.data(), _width, _height, 8, _bytesPerRow, colorSpace, bitmapInfo); - - CGContextClearRect(_context, CGRectMake(0.0, 0.0, _width, _height)); - - //CGContextSetInterpolationQuality(_context, kCGInterpolationLow); - //CGContextSetAllowsAntialiasing(_context, true); - //CGContextSetShouldAntialias(_context, true); - - CFRelease(colorSpace); - - _topContext = CGContextRetain(_context); +CoreGraphicsCanvasImpl::CoreGraphicsCanvasImpl(int width, int height) { + _layerStack.push_back(std::make_shared(width, height)); + _topContext = CGContextRetain(currentLayer()->context()); } -CanvasImpl::CanvasImpl(CGContextRef context, int width, int height) { +CoreGraphicsCanvasImpl::CoreGraphicsCanvasImpl(CGContextRef context, int width, int height) { + _layerStack.push_back(std::make_shared(width, height)); _topContext = CGContextRetain(context); - _layer = CGLayerCreateWithContext(context, CGSizeMake(width, height), nil); - _context = CGContextRetain(CGLayerGetContext(_layer)); - _width = width; - _height = height; } -CanvasImpl::~CanvasImpl() { - CFRelease(_context); +CoreGraphicsCanvasImpl::~CoreGraphicsCanvasImpl() { if (_topContext) { CFRelease(_topContext); } - if (_layer) { - CFRelease(_layer); - } } -int CanvasImpl::width() const { - return _width; +std::shared_ptr CoreGraphicsCanvasImpl::makeLayer(int width, int height) { + return std::make_shared(_topContext, width, height); } -int CanvasImpl::height() const { - return _height; +void CoreGraphicsCanvasImpl::saveState() { + CGContextSaveGState(currentLayer()->context()); } -std::shared_ptr CanvasImpl::makeLayer(int width, int height) { - return std::make_shared(_topContext, width, height); +void CoreGraphicsCanvasImpl::restoreState() { + CGContextRestoreGState(currentLayer()->context()); } -void CanvasImpl::saveState() { - CGContextSaveGState(_context); -} - -void CanvasImpl::restoreState() { - CGContextRestoreGState(_context); -} - -void CanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) { - if (!addEnumeratedPath(_context, enumeratePath)) { +void CoreGraphicsCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) { + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { return; } CGFloat components[4] = { color.r, color.g, color.b, color.a }; CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components); - CGContextSetFillColorWithColor(_context, nativeColor); + CGContextSetFillColorWithColor(currentLayer()->context(), nativeColor); CFRelease(nativeColor); switch (fillRule) { case lottie::FillRule::EvenOdd: { - CGContextEOFillPath(_context); + CGContextEOFillPath(currentLayer()->context()); break; } default: { - CGContextFillPath(_context); + CGContextFillPath(currentLayer()->context()); break; } } } -void CanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) { - CGContextSaveGState(_context); +void CoreGraphicsCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) { + CGContextSaveGState(currentLayer()->context()); - if (!addEnumeratedPath(_context, enumeratePath)) { - CGContextRestoreGState(_context); + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { + CGContextRestoreGState(currentLayer()->context()); return; } switch (fillRule) { case lottie::FillRule::EvenOdd: { - CGContextEOClip(_context); + CGContextEOClip(currentLayer()->context()); break; } default: { - CGContextClip(_context); + CGContextClip(currentLayer()->context()); break; } } @@ -195,29 +196,29 @@ void CanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePat CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size()); if (nativeGradient) { - CGContextDrawLinearGradient(_context, nativeGradient, CGPointMake(start.x, start.y), CGPointMake(end.x, end.y), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + CGContextDrawLinearGradient(currentLayer()->context(), nativeGradient, CGPointMake(start.x, start.y), CGPointMake(end.x, end.y), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CFRelease(nativeGradient); } - CGContextResetClip(_context); - CGContextRestoreGState(_context); + CGContextResetClip(currentLayer()->context()); + CGContextRestoreGState(currentLayer()->context()); } -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); +void CoreGraphicsCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) { + CGContextSaveGState(currentLayer()->context()); - if (!addEnumeratedPath(_context, enumeratePath)) { - CGContextRestoreGState(_context); + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { + CGContextRestoreGState(currentLayer()->context()); return; } switch (fillRule) { case lottie::FillRule::EvenOdd: { - CGContextEOClip(_context); + CGContextEOClip(currentLayer()->context()); break; } default: { - CGContextClip(_context); + CGContextClip(currentLayer()->context()); break; } } @@ -241,60 +242,60 @@ void CanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePat CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size()); if (nativeGradient) { - CGContextDrawRadialGradient(_context, nativeGradient, CGPointMake(startCenter.x, startCenter.y), startRadius, CGPointMake(endCenter.x, endCenter.y), endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + CGContextDrawRadialGradient(currentLayer()->context(), nativeGradient, CGPointMake(startCenter.x, startCenter.y), startRadius, CGPointMake(endCenter.x, endCenter.y), endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CFRelease(nativeGradient); } - CGContextResetClip(_context); - CGContextRestoreGState(_context); + CGContextResetClip(currentLayer()->context()); + CGContextRestoreGState(currentLayer()->context()); } -void CanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, lottie::Color const &color) { - if (!addEnumeratedPath(_context, enumeratePath)) { +void CoreGraphicsCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, lottie::Color const &color) { + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { return; } CGFloat components[4] = { color.r, color.g, color.b, color.a }; CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components); - CGContextSetStrokeColorWithColor(_context, nativeColor); + CGContextSetStrokeColorWithColor(currentLayer()->context(), nativeColor); CFRelease(nativeColor); - CGContextSetLineWidth(_context, lineWidth); + CGContextSetLineWidth(currentLayer()->context(), lineWidth); switch (lineJoin) { case lottie::LineJoin::Miter: { - CGContextSetLineJoin(_context, kCGLineJoinMiter); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter); break; } case lottie::LineJoin::Round: { - CGContextSetLineJoin(_context, kCGLineJoinRound); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound); break; } case lottie::LineJoin::Bevel: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } default: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } } switch (lineCap) { case lottie::LineCap::Butt: { - CGContextSetLineCap(_context, kCGLineCapButt); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt); break; } case lottie::LineCap::Round: { - CGContextSetLineCap(_context, kCGLineCapRound); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound); break; } case lottie::LineCap::Square: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } default: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } } @@ -304,54 +305,54 @@ void CanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lin for (const auto value : dashPattern) { mappedDashPattern.push_back(value); } - CGContextSetLineDash(_context, dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); + CGContextSetLineDash(currentLayer()->context(), dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); } - CGContextStrokePath(_context); + CGContextStrokePath(currentLayer()->context()); } -void CanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) { - CGContextSaveGState(_context); - if (!addEnumeratedPath(_context, enumeratePath)) { - CGContextRestoreGState(_context); +void CoreGraphicsCanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) { + CGContextSaveGState(currentLayer()->context()); + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { + CGContextRestoreGState(currentLayer()->context()); return; } - CGContextSetLineWidth(_context, lineWidth); + CGContextSetLineWidth(currentLayer()->context(), lineWidth); switch (lineJoin) { case lottie::LineJoin::Miter: { - CGContextSetLineJoin(_context, kCGLineJoinMiter); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter); break; } case lottie::LineJoin::Round: { - CGContextSetLineJoin(_context, kCGLineJoinRound); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound); break; } case lottie::LineJoin::Bevel: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } default: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } } switch (lineCap) { case lottie::LineCap::Butt: { - CGContextSetLineCap(_context, kCGLineCapButt); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt); break; } case lottie::LineCap::Round: { - CGContextSetLineCap(_context, kCGLineCapRound); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound); break; } case lottie::LineCap::Square: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } default: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } } @@ -361,11 +362,11 @@ void CanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumerateP for (const auto value : dashPattern) { mappedDashPattern.push_back(value); } - CGContextSetLineDash(_context, dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); + CGContextSetLineDash(currentLayer()->context(), dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); } - CGContextReplacePathWithStrokedPath(_context); - CGContextClip(_context); + CGContextReplacePathWithStrokedPath(currentLayer()->context()); + CGContextClip(currentLayer()->context()); std::vector components; components.reserve(gradient.colors().size() + 4); @@ -386,57 +387,57 @@ void CanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumerateP CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size()); if (nativeGradient) { - CGContextDrawLinearGradient(_context, nativeGradient, CGPointMake(start.x, start.y), CGPointMake(end.x, end.y), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + CGContextDrawLinearGradient(currentLayer()->context(), nativeGradient, CGPointMake(start.x, start.y), CGPointMake(end.x, end.y), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CFRelease(nativeGradient); } - CGContextResetClip(_context); - CGContextRestoreGState(_context); + CGContextResetClip(currentLayer()->context()); + CGContextRestoreGState(currentLayer()->context()); } -void CanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) { - CGContextSaveGState(_context); - if (!addEnumeratedPath(_context, enumeratePath)) { - CGContextRestoreGState(_context); +void CoreGraphicsCanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumeratePath, float lineWidth, lottie::LineJoin lineJoin, lottie::LineCap lineCap, float dashPhase, std::vector const &dashPattern, Gradient const &gradient, lottie::Vector2D const &startCenter, float startRadius, lottie::Vector2D const &endCenter, float endRadius) { + CGContextSaveGState(currentLayer()->context()); + if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) { + CGContextRestoreGState(currentLayer()->context()); return; } - CGContextSetLineWidth(_context, lineWidth); + CGContextSetLineWidth(currentLayer()->context(), lineWidth); switch (lineJoin) { case lottie::LineJoin::Miter: { - CGContextSetLineJoin(_context, kCGLineJoinMiter); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter); break; } case lottie::LineJoin::Round: { - CGContextSetLineJoin(_context, kCGLineJoinRound); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound); break; } case lottie::LineJoin::Bevel: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } default: { - CGContextSetLineJoin(_context, kCGLineJoinBevel); + CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel); break; } } switch (lineCap) { case lottie::LineCap::Butt: { - CGContextSetLineCap(_context, kCGLineCapButt); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt); break; } case lottie::LineCap::Round: { - CGContextSetLineCap(_context, kCGLineCapRound); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound); break; } case lottie::LineCap::Square: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } default: { - CGContextSetLineCap(_context, kCGLineCapSquare); + CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare); break; } } @@ -446,11 +447,11 @@ void CanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumerateP for (const auto value : dashPattern) { mappedDashPattern.push_back(value); } - CGContextSetLineDash(_context, dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); + CGContextSetLineDash(currentLayer()->context(), dashPhase, mappedDashPattern.data(), mappedDashPattern.size()); } - CGContextReplacePathWithStrokedPath(_context); - CGContextClip(_context); + CGContextReplacePathWithStrokedPath(currentLayer()->context()); + CGContextClip(currentLayer()->context()); std::vector components; components.reserve(gradient.colors().size() + 4); @@ -471,24 +472,24 @@ void CanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumerateP CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size()); if (nativeGradient) { - CGContextDrawRadialGradient(_context, nativeGradient, CGPointMake(startCenter.x, startCenter.y), startRadius, CGPointMake(endCenter.x, endCenter.y), endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + CGContextDrawRadialGradient(currentLayer()->context(), nativeGradient, CGPointMake(startCenter.x, startCenter.y), startRadius, CGPointMake(endCenter.x, endCenter.y), endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); CFRelease(nativeGradient); } - CGContextResetClip(_context); - CGContextRestoreGState(_context); + CGContextResetClip(currentLayer()->context()); + CGContextRestoreGState(currentLayer()->context()); } -void CanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) { +void CoreGraphicsCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillColor) { CGFloat components[4] = { fillColor.r, fillColor.g, fillColor.b, fillColor.a }; CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components); - CGContextSetFillColorWithColor(_context, nativeColor); + CGContextSetFillColorWithColor(currentLayer()->context(), nativeColor); CFRelease(nativeColor); - CGContextFillRect(_context, CGRectMake(rect.x, rect.y, rect.width, rect.height)); + CGContextFillRect(currentLayer()->context(), CGRectMake(rect.x, rect.y, rect.width, rect.height)); } -void CanvasImpl::setBlendMode(BlendMode blendMode) { +void CoreGraphicsCanvasImpl::setBlendMode(BlendMode blendMode) { ::CGBlendMode nativeMode = kCGBlendModeNormal; switch (blendMode) { case BlendMode::Normal: { @@ -504,21 +505,17 @@ void CanvasImpl::setBlendMode(BlendMode blendMode) { break; } } - CGContextSetBlendMode(_context, nativeMode); + CGContextSetBlendMode(currentLayer()->context(), nativeMode); } -void CanvasImpl::setAlpha(float alpha) { - CGContextSetAlpha(_context, alpha); +void CoreGraphicsCanvasImpl::concatenate(lottie::Transform2D const &transform) { + CGContextConcatCTM(currentLayer()->context(), CATransform3DGetAffineTransform(nativeTransform(transform))); } -void CanvasImpl::concatenate(lottie::Transform2D const &transform) { - CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform))); -} - -std::shared_ptr CanvasImpl::makeImage() const { - ::CGImageRef nativeImage = CGBitmapContextCreateImage(_context); +std::shared_ptr CoreGraphicsCanvasImpl::makeImage() { + ::CGImageRef nativeImage = CGBitmapContextCreateImage(currentLayer()->context()); if (nativeImage) { - auto image = std::make_shared(nativeImage); + auto image = std::make_shared(nativeImage); CFRelease(nativeImage); return image; } else { @@ -526,15 +523,23 @@ std::shared_ptr CanvasImpl::makeImage() const { } } -void CanvasImpl::draw(std::shared_ptr const &other, lottie::CGRect const &rect) { - CanvasImpl *impl = (CanvasImpl *)other.get(); - if (impl->_layer) { - CGContextDrawLayerInRect(_context, CGRectMake(rect.x, rect.y, rect.width, rect.height), impl->_layer); - } else { - auto image = impl->makeImage(); - CGContextDrawImage(_context, CGRectMake(rect.x, rect.y, rect.width, rect.height), ((CanvasImpl::Image *)image.get())->nativeImage()); - } +void CoreGraphicsCanvasImpl::draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) { + CGContextSetAlpha(currentLayer()->context(), alpha); + CoreGraphicsCanvasImpl *impl = (CoreGraphicsCanvasImpl *)other.get(); + auto image = impl->makeImage(); + CGContextDrawImage(currentLayer()->context(), CGRectMake(rect.x, rect.y, rect.width, rect.height), ((CoreGraphicsCanvasImpl::Image *)image.get())->nativeImage()); + CGContextSetAlpha(currentLayer()->context(), 1.0); +} + +void CoreGraphicsCanvasImpl::pushLayer(CGRect const &rect) { +} + +void CoreGraphicsCanvasImpl::popLayer() { + +} + +std::shared_ptr &CoreGraphicsCanvasImpl::currentLayer() { + return _layerStack[_layerStack.size() - 1]; } } - diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.cpp b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.cpp index cb7bc72879..02816e411e 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.cpp +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.cpp @@ -50,8 +50,7 @@ void skPath(CanvasPathEnumerator const &enumeratePath, SkPath &nativePath) { } -SkiaCanvasImpl::SkiaCanvasImpl(int width, int height) : -_width(width), _height(height) { +SkiaCanvasImpl::SkiaCanvasImpl(int width, int height) { int bytesPerRow = width * 4; _pixelData = malloc(bytesPerRow * height); _ownsPixelData = true; @@ -90,14 +89,6 @@ SkiaCanvasImpl::~SkiaCanvasImpl() { } } -int SkiaCanvasImpl::width() const { - return _width; -} - -int SkiaCanvasImpl::height() const { - return _height; -} - std::shared_ptr SkiaCanvasImpl::makeLayer(int width, int height) { return std::make_shared(width, height); } @@ -113,7 +104,6 @@ void SkiaCanvasImpl::restoreState() { void SkiaCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) { SkPaint paint; paint.setColor(skColor(color)); - paint.setAlphaf(_alpha); paint.setAntiAlias(true); paint.setBlendMode(_blendMode); @@ -138,7 +128,7 @@ void SkiaCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumerat std::vector colors; for (const auto &color : gradient.colors()) { - colors.push_back(skColor(Color(color.r, color.g, color.b, color.a * _alpha))); + colors.push_back(skColor(Color(color.r, color.g, color.b, color.a))); } std::vector locations; @@ -164,7 +154,7 @@ void SkiaCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumerat std::vector colors; for (const auto &color : gradient.colors()) { - colors.push_back(skColor(Color(color.r, color.g, color.b, color.a * _alpha))); + colors.push_back(skColor(Color(color.r, color.g, color.b, color.a))); } std::vector locations; @@ -186,7 +176,6 @@ void SkiaCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float paint.setAntiAlias(true); paint.setBlendMode(_blendMode); paint.setColor(skColor(color)); - paint.setAlphaf(_alpha); paint.setStyle(SkPaint::Style::kStroke_Style); paint.setStrokeWidth(lineWidth); @@ -255,7 +244,6 @@ void SkiaCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillC SkPaint paint; paint.setAntiAlias(true); paint.setColor(skColor(fillColor)); - paint.setAlphaf(_alpha); paint.setBlendMode(_blendMode); _canvas->drawRect(SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), paint); @@ -282,10 +270,6 @@ void SkiaCanvasImpl::setBlendMode(BlendMode blendMode) { } } -void SkiaCanvasImpl::setAlpha(float alpha) { - _alpha = alpha; -} - void SkiaCanvasImpl::concatenate(lottie::Transform2D const &transform) { SkScalar m9[9] = { transform.rows().columns[0][0], transform.rows().columns[1][0], transform.rows().columns[2][0], @@ -297,12 +281,12 @@ void SkiaCanvasImpl::concatenate(lottie::Transform2D const &transform) { _canvas->concat(matrix); } -void SkiaCanvasImpl::draw(std::shared_ptr const &other, lottie::CGRect const &rect) { +void SkiaCanvasImpl::draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) { SkiaCanvasImpl *impl = (SkiaCanvasImpl *)other.get(); auto image = impl->surface()->makeImageSnapshot(); SkPaint paint; paint.setBlendMode(_blendMode); - paint.setAlphaf(_alpha); + paint.setAlphaf(alpha); _canvas->drawImageRect(image.get(), SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), SkSamplingOptions(SkFilterMode::kLinear), &paint); } diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.h b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.h index 6d7a2f35ef..cccf8b9075 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.h +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SkiaCanvasImpl.h @@ -14,9 +14,6 @@ public: SkiaCanvasImpl(int width, int height, int bytesPerRow, void *pixelData); virtual ~SkiaCanvasImpl(); - virtual int width() const override; - virtual int height() const override; - virtual std::shared_ptr makeLayer(int width, int height) override; virtual void saveState() override; @@ -32,11 +29,9 @@ public: virtual void setBlendMode(BlendMode blendMode) override; - virtual void setAlpha(float alpha) override; - virtual void concatenate(lottie::Transform2D const &transform) override; - virtual void draw(std::shared_ptr const &other, lottie::CGRect const &rect) override; + virtual void draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) override; void flush(); sk_sp surface() const; @@ -44,12 +39,9 @@ public: private: void *_pixelData = nullptr; bool _ownsPixelData = false; - int _width = 0; - int _height = 0; sk_sp _surface; SkCanvas *_canvas = nullptr; SkBlendMode _blendMode = SkBlendMode::kSrcOver; - double _alpha = 1.0; }; } diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm index 8476ccd457..e00ea55fa0 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/SoftwareLottieRenderer.mm @@ -64,13 +64,13 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) { } if (useReferenceRendering) { - auto context = std::make_shared((int)size.width, (int)size.height); + auto context = std::make_shared((int)size.width, (int)size.height); _canvasRenderer->render(_renderer, context, lottie::Vector2D(size.width, size.height)); auto image = context->makeImage(); - return [[UIImage alloc] initWithCGImage:std::static_pointer_cast(image)->nativeImage()]; + return [[UIImage alloc] initWithCGImage:std::static_pointer_cast(image)->nativeImage()]; } else { if ((int64_t)"" > 0) { /*auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul((int)size.width, (int)size.height)); diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.cpp b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.cpp index 1094b33ea6..6ff62ca987 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.cpp +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.cpp @@ -49,7 +49,7 @@ void ThorVGCanvasImpl::initializeOnce() { } ThorVGCanvasImpl::ThorVGCanvasImpl(int width, int height, int bytesPerRow) : -_width(width), _height(height), _transform(lottie::Transform2D::identity()) { +_transform(lottie::Transform2D::identity()) { _canvas = tvg::SwCanvas::gen(); _bytesPerRow = bytesPerRow; @@ -63,14 +63,6 @@ _width(width), _height(height), _transform(lottie::Transform2D::identity()) { ThorVGCanvasImpl::~ThorVGCanvasImpl() { } -int ThorVGCanvasImpl::width() const { - return _width; -} - -int ThorVGCanvasImpl::height() const { - return _height; -} - std::shared_ptr ThorVGCanvasImpl::makeLayer(int width, int height) { return std::make_shared(width, height, width * 4); } @@ -94,7 +86,7 @@ void ThorVGCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lotti shape->transform(tvgTransform(_transform)); - shape->fill((int)(color.r * 255.0), (int)(color.g * 255.0), (int)(color.b * 255.0), (int)(color.a * _alpha * 255.0)); + shape->fill((int)(color.r * 255.0), (int)(color.g * 255.0), (int)(color.b * 255.0), (int)(color.a * 255.0)); shape->fill(fillRule == lottie::FillRule::EvenOdd ? tvg::FillRule::EvenOdd : tvg::FillRule::Winding); _canvas->push(std::move(shape)); @@ -117,7 +109,7 @@ void ThorVGCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumer colorStop.r = (int)(color.r * 255.0); colorStop.g = (int)(color.g * 255.0); colorStop.b = (int)(color.b * 255.0); - colorStop.a = (int)(color.a * _alpha * 255.0); + colorStop.a = (int)(color.a * 255.0); colors.push_back(colorStop); } fill->colorStops(colors.data(), (uint32_t)colors.size()); @@ -145,7 +137,7 @@ void ThorVGCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumer colorStop.r = (int)(color.r * 255.0); colorStop.g = (int)(color.g * 255.0); colorStop.b = (int)(color.b * 255.0); - colorStop.a = (int)(color.a * _alpha * 255.0); + colorStop.a = (int)(color.a * 255.0); colors.push_back(colorStop); } fill->colorStops(colors.data(), (uint32_t)colors.size()); @@ -162,7 +154,7 @@ void ThorVGCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, flo shape->transform(tvgTransform(_transform)); - shape->strokeFill((int)(color.r * 255.0), (int)(color.g * 255.0), (int)(color.b * 255.0), (int)(color.a * _alpha * 255.0)); + shape->strokeFill((int)(color.r * 255.0), (int)(color.g * 255.0), (int)(color.b * 255.0), (int)(color.a * 255.0)); shape->strokeWidth(lineWidth); switch (lineJoin) { @@ -228,7 +220,7 @@ void ThorVGCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fil shape->transform(tvgTransform(_transform)); - shape->fill((int)(fillColor.r * 255.0), (int)(fillColor.g * 255.0), (int)(fillColor.b * 255.0), (int)(fillColor.a * _alpha * 255.0)); + shape->fill((int)(fillColor.r * 255.0), (int)(fillColor.g * 255.0), (int)(fillColor.b * 255.0), (int)(fillColor.a * 255.0)); _canvas->push(std::move(shape)); } @@ -254,10 +246,6 @@ void ThorVGCanvasImpl::setBlendMode(BlendMode blendMode) { }*/ } -void ThorVGCanvasImpl::setAlpha(float alpha) { - _alpha = alpha; -} - void ThorVGCanvasImpl::concatenate(lottie::Transform2D const &transform) { _transform = transform * _transform; /*_canvas->concat(SkM44( @@ -268,7 +256,7 @@ void ThorVGCanvasImpl::concatenate(lottie::Transform2D const &transform) { ));*/ } -void ThorVGCanvasImpl::draw(std::shared_ptr const &other, lottie::CGRect const &rect) { +void ThorVGCanvasImpl::draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) { /*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get(); auto image = impl->surface()->makeImageSnapshot(); SkPaint paint; diff --git a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.h b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.h index 10cc56489b..d1c83b6525 100644 --- a/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.h +++ b/Tests/LottieMetalTest/SoftwareLottieRenderer/Sources/ThorVGCanvasImpl.h @@ -14,9 +14,6 @@ public: ThorVGCanvasImpl(int width, int height, int bytesPerRow); virtual ~ThorVGCanvasImpl(); - virtual int width() const override; - virtual int height() const override; - virtual std::shared_ptr makeLayer(int width, int height) override; virtual void saveState() override; @@ -32,11 +29,9 @@ public: virtual void setBlendMode(BlendMode blendMode) override; - virtual void setAlpha(float alpha) override; - virtual void concatenate(lottie::Transform2D const &transform) override; - virtual void draw(std::shared_ptr const &other, lottie::CGRect const &rect) override; + virtual void draw(std::shared_ptr const &other, float alpha, lottie::CGRect const &rect) override; uint32_t *backingData() { return _backingData; @@ -49,11 +44,8 @@ public: void flush(); private: - int _width = 0; - int _height = 0; std::unique_ptr _canvas; - float _alpha = 1.0; lottie::Transform2D _transform; std::vector _stateStack; int _bytesPerRow = 0; diff --git a/Tests/LottieMetalTest/Sources/ViewController.swift b/Tests/LottieMetalTest/Sources/ViewController.swift index 0bd665e3a9..72550a1319 100644 --- a/Tests/LottieMetalTest/Sources/ViewController.swift +++ b/Tests/LottieMetalTest/Sources/ViewController.swift @@ -119,9 +119,9 @@ 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, testNonReference: true) + self.test = ReferenceCompareTest(view: self.view, testNonReference: false) } } else if !"".isEmpty { /*let cachedAnimation = cacheLottieMetalAnimation(path: filePath)!