mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Lottie tests
This commit is contained in:
parent
97996ee812
commit
d74e29d790
@ -1,5 +1,5 @@
|
|||||||
#ifndef CoreGraphicsCanvasImpl_h
|
#ifndef CoreGraphicsCoreGraphicsCanvasImpl_h
|
||||||
#define CoreGraphicsCanvasImpl_h
|
#define CoreGraphicsCoreGraphicsCanvasImpl_h
|
||||||
|
|
||||||
#include <LottieCpp/LottieCpp.h>
|
#include <LottieCpp/LottieCpp.h>
|
||||||
|
|
||||||
@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
namespace lottie {
|
namespace lottie {
|
||||||
|
|
||||||
class CanvasImpl: public Canvas {
|
class CoreGraphicsCanvasImpl: public Canvas {
|
||||||
|
class Layer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Image {
|
class Image {
|
||||||
public:
|
public:
|
||||||
@ -20,12 +22,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CanvasImpl(int width, int height);
|
CoreGraphicsCanvasImpl(int width, int height);
|
||||||
CanvasImpl(CGContextRef context, int width, int height);
|
CoreGraphicsCanvasImpl(CGContextRef context, int width, int height);
|
||||||
virtual ~CanvasImpl();
|
virtual ~CoreGraphicsCanvasImpl();
|
||||||
|
|
||||||
virtual int width() const override;
|
|
||||||
virtual int height() const override;
|
|
||||||
|
|
||||||
std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
std::shared_ptr<Canvas> 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 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 concatenate(lottie::Transform2D const &transform) override;
|
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||||
|
|
||||||
virtual std::shared_ptr<Image> makeImage() const;
|
virtual std::shared_ptr<Image> makeImage();
|
||||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
virtual void draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) override;
|
||||||
|
|
||||||
CGContextRef nativeContext() const {
|
virtual void pushLayer(CGRect const &rect) override;
|
||||||
return _context;
|
virtual void popLayer() override;
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> &backingData() {
|
std::vector<uint8_t> &backingData();
|
||||||
return _backingData;
|
int bytesPerRow();
|
||||||
}
|
|
||||||
|
private:
|
||||||
int bytesPerRow() {
|
std::shared_ptr<Layer> ¤tLayer();
|
||||||
return _bytesPerRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _width = 0;
|
|
||||||
int _height = 0;
|
|
||||||
int _bytesPerRow = 0;
|
|
||||||
std::vector<uint8_t> _backingData;
|
|
||||||
CGContextRef _context = nil;
|
|
||||||
CGContextRef _topContext = nil;
|
CGContextRef _topContext = nil;
|
||||||
CGLayerRef _layer = nil;
|
std::vector<std::shared_ptr<Layer>> _layerStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,19 +62,9 @@ bool addEnumeratedPath(CGContextRef context, CanvasPathEnumerator const &enumera
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasImpl::Image::Image(::CGImageRef image) {
|
class CoreGraphicsCanvasImpl::Layer {
|
||||||
_image = CGImageRetain(image);
|
public:
|
||||||
}
|
explicit Layer(int width, int height) {
|
||||||
|
|
||||||
CanvasImpl::Image::~Image() {
|
|
||||||
CFRelease(_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
::CGImageRef CanvasImpl::Image::nativeImage() const {
|
|
||||||
return _image;
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasImpl::CanvasImpl(int width, int height) {
|
|
||||||
_width = width;
|
_width = width;
|
||||||
_height = height;
|
_height = height;
|
||||||
_bytesPerRow = alignUp(width * 4, 16);
|
_bytesPerRow = alignUp(width * 4, 16);
|
||||||
@ -82,96 +72,107 @@ CanvasImpl::CanvasImpl(int width, int height) {
|
|||||||
memset(_backingData.data(), 0, _backingData.size());
|
memset(_backingData.data(), 0, _backingData.size());
|
||||||
|
|
||||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
|
||||||
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
|
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
|
||||||
_context = CGBitmapContextCreate(_backingData.data(), _width, _height, 8, _bytesPerRow, colorSpace, bitmapInfo);
|
_context = CGBitmapContextCreate(_backingData.data(), _width, _height, 8, _bytesPerRow, colorSpace, bitmapInfo);
|
||||||
|
CFRelease(colorSpace);
|
||||||
|
|
||||||
CGContextClearRect(_context, CGRectMake(0.0, 0.0, _width, _height));
|
CGContextClearRect(_context, CGRectMake(0.0, 0.0, _width, _height));
|
||||||
|
|
||||||
//CGContextSetInterpolationQuality(_context, kCGInterpolationLow);
|
|
||||||
//CGContextSetAllowsAntialiasing(_context, true);
|
|
||||||
//CGContextSetShouldAntialias(_context, true);
|
|
||||||
|
|
||||||
CFRelease(colorSpace);
|
|
||||||
|
|
||||||
_topContext = CGContextRetain(_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasImpl::CanvasImpl(CGContextRef context, int width, int height) {
|
~Layer() {
|
||||||
|
CGContextRelease(_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGContextRef context() const {
|
||||||
|
return _context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGContextRef _context = nil;
|
||||||
|
int _width = 0;
|
||||||
|
int _height = 0;
|
||||||
|
int _bytesPerRow = 0;
|
||||||
|
std::vector<uint8_t> _backingData;
|
||||||
|
};
|
||||||
|
|
||||||
|
CoreGraphicsCanvasImpl::Image::Image(::CGImageRef image) {
|
||||||
|
_image = CGImageRetain(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreGraphicsCanvasImpl::Image::~Image() {
|
||||||
|
CFRelease(_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
::CGImageRef CoreGraphicsCanvasImpl::Image::nativeImage() const {
|
||||||
|
return _image;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreGraphicsCanvasImpl::CoreGraphicsCanvasImpl(int width, int height) {
|
||||||
|
_layerStack.push_back(std::make_shared<Layer>(width, height));
|
||||||
|
_topContext = CGContextRetain(currentLayer()->context());
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreGraphicsCanvasImpl::CoreGraphicsCanvasImpl(CGContextRef context, int width, int height) {
|
||||||
|
_layerStack.push_back(std::make_shared<Layer>(width, height));
|
||||||
_topContext = CGContextRetain(context);
|
_topContext = CGContextRetain(context);
|
||||||
_layer = CGLayerCreateWithContext(context, CGSizeMake(width, height), nil);
|
|
||||||
_context = CGContextRetain(CGLayerGetContext(_layer));
|
|
||||||
_width = width;
|
|
||||||
_height = height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasImpl::~CanvasImpl() {
|
CoreGraphicsCanvasImpl::~CoreGraphicsCanvasImpl() {
|
||||||
CFRelease(_context);
|
|
||||||
if (_topContext) {
|
if (_topContext) {
|
||||||
CFRelease(_topContext);
|
CFRelease(_topContext);
|
||||||
}
|
}
|
||||||
if (_layer) {
|
|
||||||
CFRelease(_layer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CanvasImpl::width() const {
|
std::shared_ptr<Canvas> CoreGraphicsCanvasImpl::makeLayer(int width, int height) {
|
||||||
return _width;
|
return std::make_shared<CoreGraphicsCanvasImpl>(_topContext, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CanvasImpl::height() const {
|
void CoreGraphicsCanvasImpl::saveState() {
|
||||||
return _height;
|
CGContextSaveGState(currentLayer()->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Canvas> CanvasImpl::makeLayer(int width, int height) {
|
void CoreGraphicsCanvasImpl::restoreState() {
|
||||||
return std::make_shared<CanvasImpl>(_topContext, width, height);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasImpl::saveState() {
|
void CoreGraphicsCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||||
CGContextSaveGState(_context);
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
}
|
|
||||||
|
|
||||||
void CanvasImpl::restoreState() {
|
|
||||||
CGContextRestoreGState(_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
|
||||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
CGContextSetFillColorWithColor(_context, nativeColor);
|
CGContextSetFillColorWithColor(currentLayer()->context(), nativeColor);
|
||||||
CFRelease(nativeColor);
|
CFRelease(nativeColor);
|
||||||
|
|
||||||
switch (fillRule) {
|
switch (fillRule) {
|
||||||
case lottie::FillRule::EvenOdd: {
|
case lottie::FillRule::EvenOdd: {
|
||||||
CGContextEOFillPath(_context);
|
CGContextEOFillPath(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextFillPath(_context);
|
CGContextFillPath(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
void CoreGraphicsCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
||||||
CGContextSaveGState(_context);
|
CGContextSaveGState(currentLayer()->context());
|
||||||
|
|
||||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fillRule) {
|
switch (fillRule) {
|
||||||
case lottie::FillRule::EvenOdd: {
|
case lottie::FillRule::EvenOdd: {
|
||||||
CGContextEOClip(_context);
|
CGContextEOClip(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextClip(_context);
|
CGContextClip(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,29 +196,29 @@ void CanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumeratePat
|
|||||||
|
|
||||||
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
||||||
if (nativeGradient) {
|
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);
|
CFRelease(nativeGradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextResetClip(_context);
|
CGContextResetClip(currentLayer()->context());
|
||||||
CGContextRestoreGState(_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) {
|
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(_context);
|
CGContextSaveGState(currentLayer()->context());
|
||||||
|
|
||||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (fillRule) {
|
switch (fillRule) {
|
||||||
case lottie::FillRule::EvenOdd: {
|
case lottie::FillRule::EvenOdd: {
|
||||||
CGContextEOClip(_context);
|
CGContextEOClip(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextClip(_context);
|
CGContextClip(currentLayer()->context());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,60 +242,60 @@ void CanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumeratePat
|
|||||||
|
|
||||||
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
||||||
if (nativeGradient) {
|
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);
|
CFRelease(nativeGradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextResetClip(_context);
|
CGContextResetClip(currentLayer()->context());
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void CoreGraphicsCanvasImpl::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)) {
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
CGContextSetStrokeColorWithColor(_context, nativeColor);
|
CGContextSetStrokeColorWithColor(currentLayer()->context(), nativeColor);
|
||||||
CFRelease(nativeColor);
|
CFRelease(nativeColor);
|
||||||
|
|
||||||
CGContextSetLineWidth(_context, lineWidth);
|
CGContextSetLineWidth(currentLayer()->context(), lineWidth);
|
||||||
|
|
||||||
switch (lineJoin) {
|
switch (lineJoin) {
|
||||||
case lottie::LineJoin::Miter: {
|
case lottie::LineJoin::Miter: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinMiter);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Round: {
|
case lottie::LineJoin::Round: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinRound);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Bevel: {
|
case lottie::LineJoin::Bevel: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lineCap) {
|
switch (lineCap) {
|
||||||
case lottie::LineCap::Butt: {
|
case lottie::LineCap::Butt: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapButt);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Round: {
|
case lottie::LineCap::Round: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapRound);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Square: {
|
case lottie::LineCap::Square: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,54 +305,54 @@ void CanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float lin
|
|||||||
for (const auto value : dashPattern) {
|
for (const auto value : dashPattern) {
|
||||||
mappedDashPattern.push_back(value);
|
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<float> const &dashPattern, Gradient const &gradient, lottie::Vector2D const &start, lottie::Vector2D const &end) {
|
void CoreGraphicsCanvasImpl::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(currentLayer()->context());
|
||||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextSetLineWidth(_context, lineWidth);
|
CGContextSetLineWidth(currentLayer()->context(), lineWidth);
|
||||||
|
|
||||||
switch (lineJoin) {
|
switch (lineJoin) {
|
||||||
case lottie::LineJoin::Miter: {
|
case lottie::LineJoin::Miter: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinMiter);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Round: {
|
case lottie::LineJoin::Round: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinRound);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Bevel: {
|
case lottie::LineJoin::Bevel: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lineCap) {
|
switch (lineCap) {
|
||||||
case lottie::LineCap::Butt: {
|
case lottie::LineCap::Butt: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapButt);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Round: {
|
case lottie::LineCap::Round: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapRound);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Square: {
|
case lottie::LineCap::Square: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,11 +362,11 @@ void CanvasImpl::linearGradientStrokePath(CanvasPathEnumerator const &enumerateP
|
|||||||
for (const auto value : dashPattern) {
|
for (const auto value : dashPattern) {
|
||||||
mappedDashPattern.push_back(value);
|
mappedDashPattern.push_back(value);
|
||||||
}
|
}
|
||||||
CGContextSetLineDash(_context, dashPhase, mappedDashPattern.data(), mappedDashPattern.size());
|
CGContextSetLineDash(currentLayer()->context(), dashPhase, mappedDashPattern.data(), mappedDashPattern.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextReplacePathWithStrokedPath(_context);
|
CGContextReplacePathWithStrokedPath(currentLayer()->context());
|
||||||
CGContextClip(_context);
|
CGContextClip(currentLayer()->context());
|
||||||
|
|
||||||
std::vector<double> components;
|
std::vector<double> components;
|
||||||
components.reserve(gradient.colors().size() + 4);
|
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());
|
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
||||||
if (nativeGradient) {
|
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);
|
CFRelease(nativeGradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextResetClip(_context);
|
CGContextResetClip(currentLayer()->context());
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
void CoreGraphicsCanvasImpl::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(currentLayer()->context());
|
||||||
if (!addEnumeratedPath(_context, enumeratePath)) {
|
if (!addEnumeratedPath(currentLayer()->context(), enumeratePath)) {
|
||||||
CGContextRestoreGState(_context);
|
CGContextRestoreGState(currentLayer()->context());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextSetLineWidth(_context, lineWidth);
|
CGContextSetLineWidth(currentLayer()->context(), lineWidth);
|
||||||
|
|
||||||
switch (lineJoin) {
|
switch (lineJoin) {
|
||||||
case lottie::LineJoin::Miter: {
|
case lottie::LineJoin::Miter: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinMiter);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinMiter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Round: {
|
case lottie::LineJoin::Round: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinRound);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineJoin::Bevel: {
|
case lottie::LineJoin::Bevel: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineJoin(_context, kCGLineJoinBevel);
|
CGContextSetLineJoin(currentLayer()->context(), kCGLineJoinBevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lineCap) {
|
switch (lineCap) {
|
||||||
case lottie::LineCap::Butt: {
|
case lottie::LineCap::Butt: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapButt);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapButt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Round: {
|
case lottie::LineCap::Round: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapRound);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapRound);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lottie::LineCap::Square: {
|
case lottie::LineCap::Square: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
CGContextSetLineCap(_context, kCGLineCapSquare);
|
CGContextSetLineCap(currentLayer()->context(), kCGLineCapSquare);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -446,11 +447,11 @@ void CanvasImpl::radialGradientStrokePath(CanvasPathEnumerator const &enumerateP
|
|||||||
for (const auto value : dashPattern) {
|
for (const auto value : dashPattern) {
|
||||||
mappedDashPattern.push_back(value);
|
mappedDashPattern.push_back(value);
|
||||||
}
|
}
|
||||||
CGContextSetLineDash(_context, dashPhase, mappedDashPattern.data(), mappedDashPattern.size());
|
CGContextSetLineDash(currentLayer()->context(), dashPhase, mappedDashPattern.data(), mappedDashPattern.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextReplacePathWithStrokedPath(_context);
|
CGContextReplacePathWithStrokedPath(currentLayer()->context());
|
||||||
CGContextClip(_context);
|
CGContextClip(currentLayer()->context());
|
||||||
|
|
||||||
std::vector<double> components;
|
std::vector<double> components;
|
||||||
components.reserve(gradient.colors().size() + 4);
|
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());
|
CGGradientRef nativeGradient = CGGradientCreateWithColorComponents(CGBitmapContextGetColorSpace(_topContext), components.data(), locations.data(), locations.size());
|
||||||
if (nativeGradient) {
|
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);
|
CFRelease(nativeGradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGContextResetClip(_context);
|
CGContextResetClip(currentLayer()->context());
|
||||||
CGContextRestoreGState(_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 };
|
CGFloat components[4] = { fillColor.r, fillColor.g, fillColor.b, fillColor.a };
|
||||||
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components);
|
CGColorRef nativeColor = CGColorCreate(CGBitmapContextGetColorSpace(_topContext), components);
|
||||||
CGContextSetFillColorWithColor(_context, nativeColor);
|
CGContextSetFillColorWithColor(currentLayer()->context(), nativeColor);
|
||||||
CFRelease(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;
|
::CGBlendMode nativeMode = kCGBlendModeNormal;
|
||||||
switch (blendMode) {
|
switch (blendMode) {
|
||||||
case BlendMode::Normal: {
|
case BlendMode::Normal: {
|
||||||
@ -504,21 +505,17 @@ void CanvasImpl::setBlendMode(BlendMode blendMode) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CGContextSetBlendMode(_context, nativeMode);
|
CGContextSetBlendMode(currentLayer()->context(), nativeMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasImpl::setAlpha(float alpha) {
|
void CoreGraphicsCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||||
CGContextSetAlpha(_context, alpha);
|
CGContextConcatCTM(currentLayer()->context(), CATransform3DGetAffineTransform(nativeTransform(transform)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
std::shared_ptr<CoreGraphicsCanvasImpl::Image> CoreGraphicsCanvasImpl::makeImage() {
|
||||||
CGContextConcatCTM(_context, CATransform3DGetAffineTransform(nativeTransform(transform)));
|
::CGImageRef nativeImage = CGBitmapContextCreateImage(currentLayer()->context());
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CanvasImpl::Image> CanvasImpl::makeImage() const {
|
|
||||||
::CGImageRef nativeImage = CGBitmapContextCreateImage(_context);
|
|
||||||
if (nativeImage) {
|
if (nativeImage) {
|
||||||
auto image = std::make_shared<CanvasImpl::Image>(nativeImage);
|
auto image = std::make_shared<CoreGraphicsCanvasImpl::Image>(nativeImage);
|
||||||
CFRelease(nativeImage);
|
CFRelease(nativeImage);
|
||||||
return image;
|
return image;
|
||||||
} else {
|
} else {
|
||||||
@ -526,15 +523,23 @@ std::shared_ptr<CanvasImpl::Image> CanvasImpl::makeImage() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
void CoreGraphicsCanvasImpl::draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) {
|
||||||
CanvasImpl *impl = (CanvasImpl *)other.get();
|
CGContextSetAlpha(currentLayer()->context(), alpha);
|
||||||
if (impl->_layer) {
|
CoreGraphicsCanvasImpl *impl = (CoreGraphicsCanvasImpl *)other.get();
|
||||||
CGContextDrawLayerInRect(_context, CGRectMake(rect.x, rect.y, rect.width, rect.height), impl->_layer);
|
|
||||||
} else {
|
|
||||||
auto image = impl->makeImage();
|
auto image = impl->makeImage();
|
||||||
CGContextDrawImage(_context, CGRectMake(rect.x, rect.y, rect.width, rect.height), ((CanvasImpl::Image *)image.get())->nativeImage());
|
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::Layer> &CoreGraphicsCanvasImpl::currentLayer() {
|
||||||
|
return _layerStack[_layerStack.size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -50,8 +50,7 @@ void skPath(CanvasPathEnumerator const &enumeratePath, SkPath &nativePath) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkiaCanvasImpl::SkiaCanvasImpl(int width, int height) :
|
SkiaCanvasImpl::SkiaCanvasImpl(int width, int height) {
|
||||||
_width(width), _height(height) {
|
|
||||||
int bytesPerRow = width * 4;
|
int bytesPerRow = width * 4;
|
||||||
_pixelData = malloc(bytesPerRow * height);
|
_pixelData = malloc(bytesPerRow * height);
|
||||||
_ownsPixelData = true;
|
_ownsPixelData = true;
|
||||||
@ -90,14 +89,6 @@ SkiaCanvasImpl::~SkiaCanvasImpl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SkiaCanvasImpl::width() const {
|
|
||||||
return _width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SkiaCanvasImpl::height() const {
|
|
||||||
return _height;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Canvas> SkiaCanvasImpl::makeLayer(int width, int height) {
|
std::shared_ptr<Canvas> SkiaCanvasImpl::makeLayer(int width, int height) {
|
||||||
return std::make_shared<SkiaCanvasImpl>(width, height);
|
return std::make_shared<SkiaCanvasImpl>(width, height);
|
||||||
}
|
}
|
||||||
@ -113,7 +104,6 @@ void SkiaCanvasImpl::restoreState() {
|
|||||||
void SkiaCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
void SkiaCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lottie::FillRule fillRule, lottie::Color const &color) {
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setColor(skColor(color));
|
paint.setColor(skColor(color));
|
||||||
paint.setAlphaf(_alpha);
|
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setBlendMode(_blendMode);
|
paint.setBlendMode(_blendMode);
|
||||||
|
|
||||||
@ -138,7 +128,7 @@ void SkiaCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumerat
|
|||||||
|
|
||||||
std::vector<SkColor> colors;
|
std::vector<SkColor> colors;
|
||||||
for (const auto &color : gradient.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<SkScalar> locations;
|
std::vector<SkScalar> locations;
|
||||||
@ -164,7 +154,7 @@ void SkiaCanvasImpl::radialGradientFillPath(CanvasPathEnumerator const &enumerat
|
|||||||
|
|
||||||
std::vector<SkColor> colors;
|
std::vector<SkColor> colors;
|
||||||
for (const auto &color : gradient.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<SkScalar> locations;
|
std::vector<SkScalar> locations;
|
||||||
@ -186,7 +176,6 @@ void SkiaCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, float
|
|||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setBlendMode(_blendMode);
|
paint.setBlendMode(_blendMode);
|
||||||
paint.setColor(skColor(color));
|
paint.setColor(skColor(color));
|
||||||
paint.setAlphaf(_alpha);
|
|
||||||
paint.setStyle(SkPaint::Style::kStroke_Style);
|
paint.setStyle(SkPaint::Style::kStroke_Style);
|
||||||
|
|
||||||
paint.setStrokeWidth(lineWidth);
|
paint.setStrokeWidth(lineWidth);
|
||||||
@ -255,7 +244,6 @@ void SkiaCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fillC
|
|||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setColor(skColor(fillColor));
|
paint.setColor(skColor(fillColor));
|
||||||
paint.setAlphaf(_alpha);
|
|
||||||
paint.setBlendMode(_blendMode);
|
paint.setBlendMode(_blendMode);
|
||||||
|
|
||||||
_canvas->drawRect(SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), paint);
|
_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) {
|
void SkiaCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||||
SkScalar m9[9] = {
|
SkScalar m9[9] = {
|
||||||
transform.rows().columns[0][0], transform.rows().columns[1][0], transform.rows().columns[2][0],
|
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);
|
_canvas->concat(matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkiaCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
void SkiaCanvasImpl::draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) {
|
||||||
SkiaCanvasImpl *impl = (SkiaCanvasImpl *)other.get();
|
SkiaCanvasImpl *impl = (SkiaCanvasImpl *)other.get();
|
||||||
auto image = impl->surface()->makeImageSnapshot();
|
auto image = impl->surface()->makeImageSnapshot();
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
paint.setBlendMode(_blendMode);
|
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);
|
_canvas->drawImageRect(image.get(), SkRect::MakeXYWH(rect.x, rect.y, rect.width, rect.height), SkSamplingOptions(SkFilterMode::kLinear), &paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,9 +14,6 @@ public:
|
|||||||
SkiaCanvasImpl(int width, int height, int bytesPerRow, void *pixelData);
|
SkiaCanvasImpl(int width, int height, int bytesPerRow, void *pixelData);
|
||||||
virtual ~SkiaCanvasImpl();
|
virtual ~SkiaCanvasImpl();
|
||||||
|
|
||||||
virtual int width() const override;
|
|
||||||
virtual int height() const override;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
||||||
|
|
||||||
virtual void saveState() override;
|
virtual void saveState() override;
|
||||||
@ -32,11 +29,9 @@ public:
|
|||||||
|
|
||||||
virtual void setBlendMode(BlendMode blendMode) override;
|
virtual void setBlendMode(BlendMode blendMode) override;
|
||||||
|
|
||||||
virtual void setAlpha(float alpha) override;
|
|
||||||
|
|
||||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||||
|
|
||||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
virtual void draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) override;
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
sk_sp<SkSurface> surface() const;
|
sk_sp<SkSurface> surface() const;
|
||||||
@ -44,12 +39,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
void *_pixelData = nullptr;
|
void *_pixelData = nullptr;
|
||||||
bool _ownsPixelData = false;
|
bool _ownsPixelData = false;
|
||||||
int _width = 0;
|
|
||||||
int _height = 0;
|
|
||||||
sk_sp<SkSurface> _surface;
|
sk_sp<SkSurface> _surface;
|
||||||
SkCanvas *_canvas = nullptr;
|
SkCanvas *_canvas = nullptr;
|
||||||
SkBlendMode _blendMode = SkBlendMode::kSrcOver;
|
SkBlendMode _blendMode = SkBlendMode::kSrcOver;
|
||||||
double _alpha = 1.0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,13 +64,13 @@ CGRect getPathNativeBoundingBox(CGPathRef _Nonnull path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (useReferenceRendering) {
|
if (useReferenceRendering) {
|
||||||
auto context = std::make_shared<lottie::CanvasImpl>((int)size.width, (int)size.height);
|
auto context = std::make_shared<lottie::CoreGraphicsCanvasImpl>((int)size.width, (int)size.height);
|
||||||
|
|
||||||
_canvasRenderer->render(_renderer, context, lottie::Vector2D(size.width, size.height));
|
_canvasRenderer->render(_renderer, context, lottie::Vector2D(size.width, size.height));
|
||||||
|
|
||||||
auto image = context->makeImage();
|
auto image = context->makeImage();
|
||||||
|
|
||||||
return [[UIImage alloc] initWithCGImage:std::static_pointer_cast<lottie::CanvasImpl::Image>(image)->nativeImage()];
|
return [[UIImage alloc] initWithCGImage:std::static_pointer_cast<lottie::CoreGraphicsCanvasImpl::Image>(image)->nativeImage()];
|
||||||
} else {
|
} else {
|
||||||
if ((int64_t)"" > 0) {
|
if ((int64_t)"" > 0) {
|
||||||
/*auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul((int)size.width, (int)size.height));
|
/*auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul((int)size.width, (int)size.height));
|
||||||
|
@ -49,7 +49,7 @@ void ThorVGCanvasImpl::initializeOnce() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ThorVGCanvasImpl::ThorVGCanvasImpl(int width, int height, int bytesPerRow) :
|
ThorVGCanvasImpl::ThorVGCanvasImpl(int width, int height, int bytesPerRow) :
|
||||||
_width(width), _height(height), _transform(lottie::Transform2D::identity()) {
|
_transform(lottie::Transform2D::identity()) {
|
||||||
_canvas = tvg::SwCanvas::gen();
|
_canvas = tvg::SwCanvas::gen();
|
||||||
|
|
||||||
_bytesPerRow = bytesPerRow;
|
_bytesPerRow = bytesPerRow;
|
||||||
@ -63,14 +63,6 @@ _width(width), _height(height), _transform(lottie::Transform2D::identity()) {
|
|||||||
ThorVGCanvasImpl::~ThorVGCanvasImpl() {
|
ThorVGCanvasImpl::~ThorVGCanvasImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int ThorVGCanvasImpl::width() const {
|
|
||||||
return _width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ThorVGCanvasImpl::height() const {
|
|
||||||
return _height;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Canvas> ThorVGCanvasImpl::makeLayer(int width, int height) {
|
std::shared_ptr<Canvas> ThorVGCanvasImpl::makeLayer(int width, int height) {
|
||||||
return std::make_shared<ThorVGCanvasImpl>(width, height, width * 4);
|
return std::make_shared<ThorVGCanvasImpl>(width, height, width * 4);
|
||||||
}
|
}
|
||||||
@ -94,7 +86,7 @@ void ThorVGCanvasImpl::fillPath(CanvasPathEnumerator const &enumeratePath, lotti
|
|||||||
|
|
||||||
shape->transform(tvgTransform(_transform));
|
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);
|
shape->fill(fillRule == lottie::FillRule::EvenOdd ? tvg::FillRule::EvenOdd : tvg::FillRule::Winding);
|
||||||
|
|
||||||
_canvas->push(std::move(shape));
|
_canvas->push(std::move(shape));
|
||||||
@ -117,7 +109,7 @@ void ThorVGCanvasImpl::linearGradientFillPath(CanvasPathEnumerator const &enumer
|
|||||||
colorStop.r = (int)(color.r * 255.0);
|
colorStop.r = (int)(color.r * 255.0);
|
||||||
colorStop.g = (int)(color.g * 255.0);
|
colorStop.g = (int)(color.g * 255.0);
|
||||||
colorStop.b = (int)(color.b * 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);
|
colors.push_back(colorStop);
|
||||||
}
|
}
|
||||||
fill->colorStops(colors.data(), (uint32_t)colors.size());
|
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.r = (int)(color.r * 255.0);
|
||||||
colorStop.g = (int)(color.g * 255.0);
|
colorStop.g = (int)(color.g * 255.0);
|
||||||
colorStop.b = (int)(color.b * 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);
|
colors.push_back(colorStop);
|
||||||
}
|
}
|
||||||
fill->colorStops(colors.data(), (uint32_t)colors.size());
|
fill->colorStops(colors.data(), (uint32_t)colors.size());
|
||||||
@ -162,7 +154,7 @@ void ThorVGCanvasImpl::strokePath(CanvasPathEnumerator const &enumeratePath, flo
|
|||||||
|
|
||||||
shape->transform(tvgTransform(_transform));
|
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);
|
shape->strokeWidth(lineWidth);
|
||||||
|
|
||||||
switch (lineJoin) {
|
switch (lineJoin) {
|
||||||
@ -228,7 +220,7 @@ void ThorVGCanvasImpl::fill(lottie::CGRect const &rect, lottie::Color const &fil
|
|||||||
|
|
||||||
shape->transform(tvgTransform(_transform));
|
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));
|
_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) {
|
void ThorVGCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
||||||
_transform = transform * _transform;
|
_transform = transform * _transform;
|
||||||
/*_canvas->concat(SkM44(
|
/*_canvas->concat(SkM44(
|
||||||
@ -268,7 +256,7 @@ void ThorVGCanvasImpl::concatenate(lottie::Transform2D const &transform) {
|
|||||||
));*/
|
));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThorVGCanvasImpl::draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) {
|
void ThorVGCanvasImpl::draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) {
|
||||||
/*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get();
|
/*ThorVGCanvasImpl *impl = (ThorVGCanvasImpl *)other.get();
|
||||||
auto image = impl->surface()->makeImageSnapshot();
|
auto image = impl->surface()->makeImageSnapshot();
|
||||||
SkPaint paint;
|
SkPaint paint;
|
||||||
|
@ -14,9 +14,6 @@ public:
|
|||||||
ThorVGCanvasImpl(int width, int height, int bytesPerRow);
|
ThorVGCanvasImpl(int width, int height, int bytesPerRow);
|
||||||
virtual ~ThorVGCanvasImpl();
|
virtual ~ThorVGCanvasImpl();
|
||||||
|
|
||||||
virtual int width() const override;
|
|
||||||
virtual int height() const override;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
virtual std::shared_ptr<Canvas> makeLayer(int width, int height) override;
|
||||||
|
|
||||||
virtual void saveState() override;
|
virtual void saveState() override;
|
||||||
@ -32,11 +29,9 @@ public:
|
|||||||
|
|
||||||
virtual void setBlendMode(BlendMode blendMode) override;
|
virtual void setBlendMode(BlendMode blendMode) override;
|
||||||
|
|
||||||
virtual void setAlpha(float alpha) override;
|
|
||||||
|
|
||||||
virtual void concatenate(lottie::Transform2D const &transform) override;
|
virtual void concatenate(lottie::Transform2D const &transform) override;
|
||||||
|
|
||||||
virtual void draw(std::shared_ptr<Canvas> const &other, lottie::CGRect const &rect) override;
|
virtual void draw(std::shared_ptr<Canvas> const &other, float alpha, lottie::CGRect const &rect) override;
|
||||||
|
|
||||||
uint32_t *backingData() {
|
uint32_t *backingData() {
|
||||||
return _backingData;
|
return _backingData;
|
||||||
@ -49,11 +44,8 @@ public:
|
|||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _width = 0;
|
|
||||||
int _height = 0;
|
|
||||||
std::unique_ptr<tvg::SwCanvas> _canvas;
|
std::unique_ptr<tvg::SwCanvas> _canvas;
|
||||||
|
|
||||||
float _alpha = 1.0;
|
|
||||||
lottie::Transform2D _transform;
|
lottie::Transform2D _transform;
|
||||||
std::vector<lottie::Transform2D> _stateStack;
|
std::vector<lottie::Transform2D> _stateStack;
|
||||||
int _bytesPerRow = 0;
|
int _bytesPerRow = 0;
|
||||||
|
@ -119,9 +119,9 @@ 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, testNonReference: true)
|
self.test = ReferenceCompareTest(view: self.view, testNonReference: false)
|
||||||
}
|
}
|
||||||
} else if !"".isEmpty {
|
} else if !"".isEmpty {
|
||||||
/*let cachedAnimation = cacheLottieMetalAnimation(path: filePath)!
|
/*let cachedAnimation = cacheLottieMetalAnimation(path: filePath)!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user