From b4e54e27f0b2e5c9997faa40dbc78b23cc0eb13f Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Thu, 30 Jun 2022 07:15:31 -0400 Subject: [PATCH] Add copy of CGSkiaFactory --- RiveRuntime.xcodeproj/project.pbxproj | 8 ++ Source/Renderer/RiveFile.mm | 4 +- Source/Renderer/cg_skia_factory.cpp | 96 +++++++++++++++++++++ Source/Renderer/include/cg_skia_factory.hpp | 17 ++++ 4 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 Source/Renderer/cg_skia_factory.cpp create mode 100644 Source/Renderer/include/cg_skia_factory.hpp diff --git a/RiveRuntime.xcodeproj/project.pbxproj b/RiveRuntime.xcodeproj/project.pbxproj index 6515d7cb..272202ea 100644 --- a/RiveRuntime.xcodeproj/project.pbxproj +++ b/RiveRuntime.xcodeproj/project.pbxproj @@ -42,6 +42,8 @@ 04BE5430264D1F4100427B39 /* LayerState.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BE542F264D1F4100427B39 /* LayerState.h */; settings = {ATTRIBUTES = (Public, ); }; }; 04BE5434264D267900427B39 /* LayerState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 04BE5431264D243D00427B39 /* LayerState.mm */; }; 04BE5436264D2A7500427B39 /* RivePrivateHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */; }; + 274175FD286DB9CE000A60D1 /* cg_skia_factory.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 274175FB286DB9CE000A60D1 /* cg_skia_factory.hpp */; }; + 274175FE286DB9CE000A60D1 /* cg_skia_factory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 274175FC286DB9CE000A60D1 /* cg_skia_factory.cpp */; }; 2A7079352726277C00C035A1 /* rive_renderer_view.hh in Headers */ = {isa = PBXBuildFile; fileRef = 2A7079342726277C00C035A1 /* rive_renderer_view.hh */; settings = {ATTRIBUTES = (Public, ); }; }; 2A707937272628AD00C035A1 /* rive_renderer_view.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A707936272628AD00C035A1 /* rive_renderer_view.mm */; }; C34609FC27FF9114002DBCB7 /* RiveFile+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34609FB27FF9114002DBCB7 /* RiveFile+Extensions.swift */; }; @@ -105,6 +107,8 @@ 04BE542F264D1F4100427B39 /* LayerState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayerState.h; sourceTree = ""; }; 04BE5431264D243D00427B39 /* LayerState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LayerState.mm; sourceTree = ""; }; 04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RivePrivateHeaders.h; sourceTree = ""; }; + 274175FB286DB9CE000A60D1 /* cg_skia_factory.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cg_skia_factory.hpp; sourceTree = ""; }; + 274175FC286DB9CE000A60D1 /* cg_skia_factory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cg_skia_factory.cpp; sourceTree = ""; }; 2A7079342726277C00C035A1 /* rive_renderer_view.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rive_renderer_view.hh; sourceTree = ""; }; 2A707936272628AD00C035A1 /* rive_renderer_view.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = rive_renderer_view.mm; sourceTree = ""; }; C34609FB27FF9114002DBCB7 /* RiveFile+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RiveFile+Extensions.swift"; sourceTree = ""; }; @@ -147,6 +151,7 @@ 046FB801264EB632000129B1 /* include */ = { isa = PBXGroup; children = ( + 274175FB286DB9CE000A60D1 /* cg_skia_factory.hpp */, 046FB7EC264EAA60000129B1 /* RiveArtboard.h */, 046FB7E7264EAA5F000129B1 /* RiveFile.h */, 046FB7E1264EAA5E000129B1 /* RiveLinearAnimationInstance.h */, @@ -202,6 +207,7 @@ C9BD3927263B64B100696C37 /* Renderer */ = { isa = PBXGroup; children = ( + 274175FC286DB9CE000A60D1 /* cg_skia_factory.cpp */, 046FB801264EB632000129B1 /* include */, 046FB7E2264EAA5E000129B1 /* RiveArtboard.mm */, 046FB7EF264EAA60000129B1 /* RiveFile.mm */, @@ -293,6 +299,7 @@ 046FB7F7264EAA60000129B1 /* RiveFile.h in Headers */, 046FB7FC264EAA61000129B1 /* RiveArtboard.h in Headers */, 2A7079352726277C00C035A1 /* rive_renderer_view.hh in Headers */, + 274175FD286DB9CE000A60D1 /* cg_skia_factory.hpp in Headers */, 046FB800264EAA61000129B1 /* RiveStateMachineInstance.h in Headers */, 046FB7FB264EAA61000129B1 /* RiveSMIInput.h in Headers */, 046FB7F1264EAA60000129B1 /* RiveLinearAnimationInstance.h in Headers */, @@ -428,6 +435,7 @@ C9C741F524FC510200EF9516 /* Rive.mm in Sources */, 046FB7F8264EAA60000129B1 /* RiveStateMachineInstance.mm in Sources */, C3468E5C27ED4C41008652FD /* RiveModel.swift in Sources */, + 274175FE286DB9CE000A60D1 /* cg_skia_factory.cpp in Sources */, 046FB7FF264EAA61000129B1 /* RiveFile.mm in Sources */, 046FB7F2264EAA60000129B1 /* RiveArtboard.mm in Sources */, 046FB7F4264EAA60000129B1 /* RiveLinearAnimationInstance.mm in Sources */, diff --git a/Source/Renderer/RiveFile.mm b/Source/Renderer/RiveFile.mm index 40e23c6d..b129a740 100644 --- a/Source/Renderer/RiveFile.mm +++ b/Source/Renderer/RiveFile.mm @@ -8,9 +8,9 @@ #import #import -#include "skia_factory.hpp" +#import -static rive::SkiaFactory gFactory; +static rive::CGSkiaFactory gFactory; /* * RiveFile diff --git a/Source/Renderer/cg_skia_factory.cpp b/Source/Renderer/cg_skia_factory.cpp new file mode 100644 index 00000000..7ffad4de --- /dev/null +++ b/Source/Renderer/cg_skia_factory.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2022 Rive + */ + +#include "cg_skia_factory.hpp" +#include "rive/core/type_conversions.hpp" +#include + +#ifdef RIVE_BUILD_FOR_APPLE + +#if defined(RIVE_BUILD_FOR_OSX) + #include +#elif defined(RIVE_BUILD_FOR_IOS) + #include + #include +#endif + +// Helper that remembers to call CFRelease when an object goes out of scope. +template class AutoCF { + T m_Obj; +public: + AutoCF(T obj) : m_Obj(obj) {} + ~AutoCF() { if (m_Obj) CFRelease(m_Obj); } + + operator T() const { return m_Obj; } + operator bool() const { return m_Obj != nullptr; } + T get() const { return m_Obj; } +}; + +using namespace rive; + +std::vector CGSkiaFactory::platformDecode(Span span, + SkiaFactory::ImageInfo* info) { + std::vector pixels; + + AutoCF data = CFDataCreateWithBytesNoCopy(nullptr, span.data(), span.size(), nullptr); + if (!data) { + return pixels; + } + + AutoCF source = CGImageSourceCreateWithData(data, nullptr); + if (!source) { + return pixels; + } + + AutoCF image = CGImageSourceCreateImageAtIndex(source, 0, nullptr); + if (!image) { + return pixels; + } + + bool isOpaque = false; + switch (CGImageGetAlphaInfo(image.get())) { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipFirst: + case kCGImageAlphaNoneSkipLast: + isOpaque = true; + break; + default: + break; + } + + // Now create a drawing context to produce RGBA pixels + + const size_t bitsPerComponent = 8; + CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big; // rgba + if (isOpaque) { + cgInfo |= kCGImageAlphaNoneSkipLast; + } else { + cgInfo |= kCGImageAlphaPremultipliedLast; // premul + } + const size_t width = CGImageGetWidth(image); + const size_t height = CGImageGetHeight(image); + const size_t rowBytes = width * 4; // 4 bytes per pixel + const size_t size = rowBytes * height; + + pixels.resize(size); + + AutoCF cs = CGColorSpaceCreateDeviceRGB(); + AutoCF cg = CGBitmapContextCreate(pixels.data(), width, height, bitsPerComponent, rowBytes, cs, cgInfo); + if (!cg) { + pixels.clear(); + return pixels; + } + + CGContextSetBlendMode(cg, kCGBlendModeCopy); + CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); + + info->alphaType = isOpaque ? AlphaType::opaque : AlphaType::premul; + info->colorType = ColorType::rgba; + info->width = castTo(width); + info->height = castTo(height); + info->rowBytes = rowBytes; + return pixels; +}; + +#endif // RIVE_BUILD_FOR_APPLE diff --git a/Source/Renderer/include/cg_skia_factory.hpp b/Source/Renderer/include/cg_skia_factory.hpp new file mode 100644 index 00000000..050735f8 --- /dev/null +++ b/Source/Renderer/include/cg_skia_factory.hpp @@ -0,0 +1,17 @@ +/* + * Copyright 2022 Rive + */ + +#ifndef _RIVE_CGSkiaFactory_HPP_ +#define _RIVE_CGSkiaFactory_HPP_ + +#include "skia_factory.hpp" + +namespace rive { +struct CGSkiaFactory : public SkiaFactory { + std::vector platformDecode(Span, + SkiaFactory::ImageInfo*) override; +}; +} // namespace + +#endif // _RIVE_CGSkiaFactory_HPP_