Skip to content

Commit

Permalink
Integrate the Rive renderer into iOS
Browse files Browse the repository at this point in the history
Diffs=
afc961233 Integrate the Rive renderer into iOS (#5952)

Co-authored-by: Chris Dalton <[email protected]>
Co-authored-by: Luigi Rosso <[email protected]>
  • Loading branch information
3 people committed Sep 8, 2023
1 parent cc236e3 commit b1f11bf
Show file tree
Hide file tree
Showing 18 changed files with 639 additions and 213 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
matrix:
arch: ["x86", "x64", "arm", "arm64", "iossim_arm64"]

runs-on: macos-latest
runs-on: [self-hosted, macOS, ARM64]
permissions:
id-token: write
contents: read
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
run_tests:
name: Run Rive tests
needs: build-skia
runs-on: macos-latest
runs-on: [self-hosted, macOS, ARM64]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f96c86fcc800a1fa2bec3e97be00cab395ea838d
afc961233ea9dd22bf654d277b27de4d35b6a01f
2 changes: 2 additions & 0 deletions Example-iOS/Source/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
//

import UIKit
import RiveRuntime

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
RenderContextManager.shared().defaultRenderer = RendererType.skiaRenderer
return true
}

Expand Down
36 changes: 28 additions & 8 deletions RiveRuntime.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@
04BE5436264D2A7500427B39 /* RivePrivateHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */; };
04ED72F1299C114000E8DE53 /* RiveViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ED72F0299C114000E8DE53 /* RiveViewModelTest.swift */; };
04ED72F3299C115100E8DE53 /* empty_animation_state.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04ED72F2299C115100E8DE53 /* empty_animation_state.riv */; };
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 */; };
83DE4C912AA8DD7B00B88B72 /* RenderContextManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83DE4C902AA8DD7B00B88B72 /* RenderContextManager.mm */; };
83DE4C932AA8DD9F00B88B72 /* RenderContextManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE4C922AA8DD9F00B88B72 /* RenderContextManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
83DE4CA02AAA072B00B88B72 /* PlatformCGImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83DE4C9F2AAA072B00B88B72 /* PlatformCGImage.mm */; };
83DE4CA22AAA077200B88B72 /* PlatformCGImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DE4CA12AAA077200B88B72 /* PlatformCGImage.h */; };
83DE4CA72AAAE72100B88B72 /* RenderContext.hh in Headers */ = {isa = PBXBuildFile; fileRef = 83DE4CA62AAAE72000B88B72 /* RenderContext.hh */; };
C34609FC27FF9114002DBCB7 /* RiveFile+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34609FB27FF9114002DBCB7 /* RiveFile+Extensions.swift */; };
C3468E5827EB9887008652FD /* RiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3468E5727EB9887008652FD /* RiveView.swift */; };
C3468E5A27ECC7C6008652FD /* RiveViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3468E5927ECC7C6008652FD /* RiveViewModel.swift */; };
Expand Down Expand Up @@ -116,10 +119,13 @@
04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RivePrivateHeaders.h; sourceTree = "<group>"; };
04ED72F0299C114000E8DE53 /* RiveViewModelTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiveViewModelTest.swift; sourceTree = "<group>"; };
04ED72F2299C115100E8DE53 /* empty_animation_state.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = empty_animation_state.riv; sourceTree = "<group>"; };
274175FB286DB9CE000A60D1 /* cg_skia_factory.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cg_skia_factory.hpp; sourceTree = "<group>"; };
274175FC286DB9CE000A60D1 /* cg_skia_factory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cg_skia_factory.cpp; sourceTree = "<group>"; };
2A7079342726277C00C035A1 /* rive_renderer_view.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = rive_renderer_view.hh; sourceTree = "<group>"; };
2A707936272628AD00C035A1 /* rive_renderer_view.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = rive_renderer_view.mm; sourceTree = "<group>"; };
83DE4C902AA8DD7B00B88B72 /* RenderContextManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RenderContextManager.mm; path = Source/Renderer/RenderContextManager.mm; sourceTree = SOURCE_ROOT; };
83DE4C922AA8DD9F00B88B72 /* RenderContextManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderContextManager.h; sourceTree = "<group>"; };
83DE4C9F2AAA072B00B88B72 /* PlatformCGImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformCGImage.mm; sourceTree = "<group>"; };
83DE4CA12AAA077200B88B72 /* PlatformCGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformCGImage.h; sourceTree = "<group>"; };
83DE4CA62AAAE72000B88B72 /* RenderContext.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RenderContext.hh; sourceTree = "<group>"; };
C34609FB27FF9114002DBCB7 /* RiveFile+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RiveFile+Extensions.swift"; sourceTree = "<group>"; };
C3468E5727EB9887008652FD /* RiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiveView.swift; sourceTree = "<group>"; };
C3468E5927ECC7C6008652FD /* RiveViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiveViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -165,6 +171,7 @@
046FB801264EB632000129B1 /* include */ = {
isa = PBXGroup;
children = (
83DE4CA12AAA077200B88B72 /* PlatformCGImage.h */,
C9C741F224FC510200EF9516 /* Rive.h */,
046FB7E7264EAA5F000129B1 /* RiveFile.h */,
046FB7EC264EAA60000129B1 /* RiveArtboard.h */,
Expand All @@ -175,8 +182,9 @@
C9601F29250C25830032AA07 /* RiveRenderer.hpp */,
04BE542F264D1F4100427B39 /* LayerState.h */,
04BE5435264D2A7500427B39 /* RivePrivateHeaders.h */,
274175FB286DB9CE000A60D1 /* cg_skia_factory.hpp */,
E57798A12A72C81F00FF25C3 /* RiveTextValueRun.h */,
83DE4CA62AAAE72000B88B72 /* RenderContext.hh */,
83DE4C922AA8DD9F00B88B72 /* RenderContextManager.h */,
);
path = include;
sourceTree = "<group>";
Expand Down Expand Up @@ -219,6 +227,7 @@
isa = PBXGroup;
children = (
046FB801264EB632000129B1 /* include */,
83DE4C9F2AAA072B00B88B72 /* PlatformCGImage.mm */,
C9C741F324FC510200EF9516 /* Rive.mm */,
046FB7EF264EAA60000129B1 /* RiveFile.mm */,
046FB7E2264EAA5E000129B1 /* RiveArtboard.mm */,
Expand All @@ -229,7 +238,7 @@
C9601F2A250C25930032AA07 /* RiveRenderer.mm */,
E57798A52A72C9C500FF25C3 /* RiveTextValueRun.mm */,
04BE5431264D243D00427B39 /* LayerState.mm */,
274175FC286DB9CE000A60D1 /* cg_skia_factory.cpp */,
83DE4C902AA8DD7B00B88B72 /* RenderContextManager.mm */,
);
path = Renderer;
sourceTree = "<group>";
Expand Down Expand Up @@ -304,7 +313,8 @@
046FB7F7264EAA60000129B1 /* RiveFile.h in Headers */,
046FB7FC264EAA61000129B1 /* RiveArtboard.h in Headers */,
2A7079352726277C00C035A1 /* rive_renderer_view.hh in Headers */,
274175FD286DB9CE000A60D1 /* cg_skia_factory.hpp in Headers */,
83DE4CA22AAA077200B88B72 /* PlatformCGImage.h in Headers */,
83DE4C932AA8DD9F00B88B72 /* RenderContextManager.h in Headers */,
046FB800264EAA61000129B1 /* RiveStateMachineInstance.h in Headers */,
046FB7FB264EAA61000129B1 /* RiveSMIInput.h in Headers */,
E57798A72A72EEAD00FF25C3 /* RiveTextValueRun.h in Headers */,
Expand All @@ -313,6 +323,7 @@
C9C741F424FC510200EF9516 /* Rive.h in Headers */,
04BE5436264D2A7500427B39 /* RivePrivateHeaders.h in Headers */,
C9C73EE224FC478900EF9516 /* RiveRuntime.h in Headers */,
83DE4CA72AAAE72100B88B72 /* RenderContext.hh in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -432,19 +443,20 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
83DE4CA02AAA072B00B88B72 /* PlatformCGImage.mm in Sources */,
2A707937272628AD00C035A1 /* rive_renderer_view.mm in Sources */,
C34609FC27FF9114002DBCB7 /* RiveFile+Extensions.swift in Sources */,
C3468E5827EB9887008652FD /* RiveView.swift in Sources */,
04BE5434264D267900427B39 /* LayerState.mm in Sources */,
C9601F2B250C25930032AA07 /* RiveRenderer.mm in Sources */,
83DE4C912AA8DD7B00B88B72 /* RenderContextManager.mm in Sources */,
C3E2B580282F242400A8651B /* RiveStateMachineInstance+Extensions.swift in Sources */,
046FB7F5264EAA60000129B1 /* RiveSMIInput.mm in Sources */,
C3468E5A27ECC7C6008652FD /* RiveViewModel.swift in Sources */,
C3745FD3282BFAB90087F4AF /* FPSCounterView.swift in Sources */,
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 */,
Expand Down Expand Up @@ -639,6 +651,7 @@
dependencies/includes/skia/include/config,
dependencies/includes/rive/include,
dependencies/includes/renderer/include,
dependencies/includes/pls/include,
);
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
Expand All @@ -663,19 +676,22 @@
"-lrive_harfbuzz",
"-lrive_sheenbidi",
"-lrive_skia_renderer",
"-lrive_pls_renderer",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"-lskia_ios_sim",
"-lrive_sim",
"-lrive_harfbuzz_sim",
"-lrive_sheenbidi_sim",
"-lrive_skia_renderer_sim",
"-lrive_pls_renderer_sim",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-lskia_macos",
"-lrive_harfbuzz_macos",
"-lrive_sheenbidi_macos",
"-lrive_skia_renderer_macos",
"-lrive_pls_renderer_macos",
);
PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntime;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
Expand Down Expand Up @@ -716,6 +732,7 @@
dependencies/includes/skia/include/config,
dependencies/includes/rive/include,
dependencies/includes/renderer/include,
dependencies/includes/pls/include,
);
INFOPLIST_FILE = Source/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
Expand All @@ -742,20 +759,23 @@
"-lrive_harfbuzz",
"-lrive_sheenbidi",
"-lrive_skia_renderer",
"-lrive_pls_renderer",
);
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = (
"-lskia_ios_sim",
"-lrive_sim",
"-lrive_harfbuzz_sim",
"-lrive_sheenbidi_sim",
"-lrive_skia_renderer_sim",
"-lrive_pls_renderer_sim",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-lskia_macos",
"-lrive_macos",
"-lrive_harfbuzz_macos",
"-lrive_sheenbidi_macos",
"-lrive_skia_renderer_macos",
"-lrive_pls_renderer_macos",
);
PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntime;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
Expand Down
1 change: 1 addition & 0 deletions Source/Renderer/NullPLS/include/rive/pls/pls.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#define RIVE_NO_PLS
63 changes: 63 additions & 0 deletions Source/Renderer/NullPLS/out/premake5_pls_renderer.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
workspace 'rive'
configurations {'debug', 'release'}

require 'setup_compiler'

newoption {
trigger = 'no-rive-decoders',
description = ''
}

-- Build a no-op librive_pls_renderer.a so xcode still sees a static library to link with when the
-- module isn't available.
project 'rive_pls_renderer'
do
kind 'StaticLib'
language 'C++'
cppdialect 'C++17'
exceptionhandling 'Off'
rtti 'Off'
targetdir '%{cfg.buildcfg}'
objdir 'obj/%{cfg.buildcfg}'
files {'../pls.cpp'}

if os.host() == 'macosx' then
iphoneos_sysroot = os.outputof('xcrun --sdk iphoneos --show-sdk-path')
iphonesimulator_sysroot = os.outputof('xcrun --sdk iphonesimulator --show-sdk-path')

filter {'system:ios', 'options:variant=system'}
do
targetdir 'iphoneos_%{cfg.buildcfg}'
objdir 'obj/iphoneos_%{cfg.buildcfg}'
buildoptions {
'--target=arm64-apple-ios13.0.0',
'-mios-version-min=13.0.0',
'-isysroot ' .. iphoneos_sysroot
}
end

filter {'system:ios', 'options:variant=simulator'}
do
targetdir 'iphonesimulator_%{cfg.buildcfg}'
objdir 'obj/iphonesimulator_%{cfg.buildcfg}'
buildoptions {
'--target=arm64-apple-ios13.0.0-simulator',
'-mios-version-min=13.0.0',
'-arch x86_64',
'-arch arm64',
'-isysroot ' .. iphonesimulator_sysroot
}
end
end
end

newoption {
trigger = 'variant',
value = 'type',
description = 'Choose a particular variant to build',
allowed = {
{'system', 'Builds the static library for the provided system'},
{'simulator', 'Builds for an emulator/simulator for the provided system'}
},
default = 'system'
}
3 changes: 3 additions & 0 deletions Source/Renderer/NullPLS/pls.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Build a no-op librive_pls_renderer.a so xcode still sees a static library to link with when the
// module isn't available.
void NullPLS() {}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
/*
* Copyright 2022 Rive
* Copyright 2023 Rive
*/

#include "cg_skia_factory.hpp"
#import <PlatformCGImage.h>
#include "rive/core/type_conversions.hpp"
#include <vector>

#ifdef RIVE_BUILD_FOR_APPLE

#if defined(RIVE_BUILD_FOR_OSX)
#include <ApplicationServices/ApplicationServices.h>
Expand All @@ -33,29 +30,26 @@ template <typename T> class AutoCF
T get() const { return m_Obj; }
};

using namespace rive;

std::vector<uint8_t> CGSkiaFactory::platformDecode(Span<const uint8_t> span,
SkiaFactory::ImageInfo* info)
bool PlatformCGImageDecode(const uint8_t* encodedBytes,
size_t encodedSizeInBytes,
PlatformCGImage* platformImage)
{
std::vector<uint8_t> pixels;

AutoCF data = CFDataCreateWithBytesNoCopy(nullptr, span.data(), span.size(), nullptr);
AutoCF data = CFDataCreate(kCFAllocatorDefault, encodedBytes, encodedSizeInBytes);
if (!data)
{
return pixels;
return false;
}

AutoCF source = CGImageSourceCreateWithData(data, nullptr);
if (!source)
{
return pixels;
return false;
}

AutoCF image = CGImageSourceCreateImageAtIndex(source, 0, nullptr);
if (!image)
{
return pixels;
return false;
}

bool isOpaque = false;
Expand Down Expand Up @@ -87,26 +81,23 @@ std::vector<uint8_t> CGSkiaFactory::platformDecode(Span<const uint8_t> span,
const size_t rowBytes = width * 4; // 4 bytes per pixel
const size_t size = rowBytes * height;

std::vector<uint8_t> pixels;
pixels.resize(size);

AutoCF cs = CGColorSpaceCreateDeviceRGB();
AutoCF cg =
CGBitmapContextCreate(pixels.data(), width, height, bitsPerComponent, rowBytes, cs, cgInfo);
if (!cg)
{
pixels.clear();
return pixels;
return false;
}

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<uint32_t>(width);
info->height = castTo<uint32_t>(height);
info->rowBytes = rowBytes;
return pixels;
};

#endif // RIVE_BUILD_FOR_APPLE
platformImage->width = rive::castTo<uint32_t>(width);
platformImage->height = rive::castTo<uint32_t>(height);
platformImage->opaque = isOpaque;
platformImage->pixels = std::move(pixels);
return true;
}
Loading

0 comments on commit b1f11bf

Please sign in to comment.