diff --git a/Example-iOS/Assets/sheep.riv b/Example-iOS/Assets/sheep.riv new file mode 100644 index 00000000..3b8f3594 Binary files /dev/null and b/Example-iOS/Assets/sheep.riv differ diff --git a/Example-iOS/RiveExample.xcodeproj/project.pbxproj b/Example-iOS/RiveExample.xcodeproj/project.pbxproj index d90ededb..648d0116 100644 --- a/Example-iOS/RiveExample.xcodeproj/project.pbxproj +++ b/Example-iOS/RiveExample.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ C99E2FE3251E8DB4009227CA /* van.riv in Resources */ = {isa = PBXBuildFile; fileRef = C99E2FE0251E8DB4009227CA /* van.riv */; }; C99E2FE8251E8E35009227CA /* bird.riv in Resources */ = {isa = PBXBuildFile; fileRef = C99E2FE6251E8E35009227CA /* bird.riv */; }; C99E2FE9251E8E35009227CA /* funtime.riv in Resources */ = {isa = PBXBuildFile; fileRef = C99E2FE7251E8E35009227CA /* funtime.riv */; }; + C9A7D7F52523C1D900AFB875 /* sheep.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9A7D7F22523C1D900AFB875 /* sheep.riv */; }; C9C73E9824FC471E00EF9516 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C73E9724FC471E00EF9516 /* AppDelegate.swift */; }; C9C73E9A24FC471E00EF9516 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C73E9924FC471E00EF9516 /* SceneDelegate.swift */; }; C9C73E9C24FC471E00EF9516 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C73E9B24FC471E00EF9516 /* ContentView.swift */; }; @@ -65,6 +66,7 @@ C99E2FE0251E8DB4009227CA /* van.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = van.riv; sourceTree = ""; }; C99E2FE6251E8E35009227CA /* bird.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = bird.riv; sourceTree = ""; }; C99E2FE7251E8E35009227CA /* funtime.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = funtime.riv; sourceTree = ""; }; + C9A7D7F22523C1D900AFB875 /* sheep.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = sheep.riv; sourceTree = ""; }; C9C73E9424FC471E00EF9516 /* RiveExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RiveExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; C9C73E9724FC471E00EF9516 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C9C73E9924FC471E00EF9516 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -91,6 +93,7 @@ C9696B0E24FC6FD10041502A /* Assets */ = { isa = PBXGroup; children = ( + C9A7D7F22523C1D900AFB875 /* sheep.riv */, C99E2FE6251E8E35009227CA /* bird.riv */, C99E2FE7251E8E35009227CA /* funtime.riv */, C99E2FE0251E8DB4009227CA /* van.riv */, @@ -260,6 +263,7 @@ C970484A250822F300CB3AB3 /* simple.riv in Resources */, C9C73E9E24FC471E00EF9516 /* Assets.xcassets in Resources */, C9927C1B250986BF009F17F5 /* truck.riv in Resources */, + C9A7D7F52523C1D900AFB875 /* sheep.riv in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example-iOS/Source/ContentView.swift b/Example-iOS/Source/ContentView.swift index e3570c5c..b364521e 100644 --- a/Example-iOS/Source/ContentView.swift +++ b/Example-iOS/Source/ContentView.swift @@ -11,7 +11,6 @@ import RiveRuntime struct ContentView: View { var body: some View { - // Text("Hello, World!") MyRive() } } diff --git a/RiveRuntime.xcodeproj/project.pbxproj b/RiveRuntime.xcodeproj/project.pbxproj index f249675c..b34629d9 100644 --- a/RiveRuntime.xcodeproj/project.pbxproj +++ b/RiveRuntime.xcodeproj/project.pbxproj @@ -523,21 +523,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - C9601F20250C13D40032AA07 /* RiveKit */ = { - isa = PBXGroup; - children = ( - C9C741F224FC510200EF9516 /* Rive.h */, - C9C741F324FC510200EF9516 /* Rive.mm */, - C9601F29250C25830032AA07 /* RiveRenderer.hpp */, - C9601F2A250C25930032AA07 /* RiveRenderer.mm */, - C9601F25250C14560032AA07 /* RiveView.h */, - C9601F26250C14560032AA07 /* RiveView.mm */, - C9601F21250C143A0032AA07 /* RiveViewController.h */, - C9601F22250C143A0032AA07 /* RiveViewController.mm */, - ); - path = RiveKit; - sourceTree = ""; - }; C9601F2C251004770032AA07 /* math */ = { isa = PBXGroup; children = ( @@ -661,7 +646,14 @@ C9C73ED324FC478800EF9516 /* Source */ = { isa = PBXGroup; children = ( - C9601F20250C13D40032AA07 /* RiveKit */, + C9C741F224FC510200EF9516 /* Rive.h */, + C9C741F324FC510200EF9516 /* Rive.mm */, + C9601F29250C25830032AA07 /* RiveRenderer.hpp */, + C9601F2A250C25930032AA07 /* RiveRenderer.mm */, + C9601F25250C14560032AA07 /* RiveView.h */, + C9601F26250C14560032AA07 /* RiveView.mm */, + C9601F21250C143A0032AA07 /* RiveViewController.h */, + C9601F22250C143A0032AA07 /* RiveViewController.mm */, C9C73ED424FC478800EF9516 /* RiveRuntime.h */, C9C73ED524FC478800EF9516 /* Info.plist */, ); diff --git a/Source/RiveKit/Rive.h b/Source/Rive.h similarity index 98% rename from Source/RiveKit/Rive.h rename to Source/Rive.h index 91e85064..55da524f 100644 --- a/Source/RiveKit/Rive.h +++ b/Source/Rive.h @@ -8,7 +8,6 @@ #import #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/Source/RiveKit/Rive.mm b/Source/Rive.mm similarity index 98% rename from Source/RiveKit/Rive.mm rename to Source/Rive.mm index e6a42fcd..437f9279 100644 --- a/Source/RiveKit/Rive.mm +++ b/Source/Rive.mm @@ -43,13 +43,17 @@ @implementation RiveRenderer -(instancetype) initWithContext:(CGContextRef) context { if (self = [super init]) { ctx = context; - _renderer = new rive::NewRiveRenderer(context); + _renderer = new rive::RiveRenderer(context); return self; } else { return nil; } } +-(void) dealloc { + delete _renderer; +} + -(void) alignWithRect:(CGRect)rect withContentRect:(CGRect)contentRect withAlignment:(Alignment)alignment withFit:(Fit)fit { // NSLog(@"Rect in align %@", NSStringFromCGRect(rect)); diff --git a/Source/RiveKit/RiveRenderer.hpp b/Source/RiveRenderer.hpp similarity index 87% rename from Source/RiveKit/RiveRenderer.hpp rename to Source/RiveRenderer.hpp index a10d96e6..03199bd5 100644 --- a/Source/RiveKit/RiveRenderer.hpp +++ b/Source/RiveRenderer.hpp @@ -9,15 +9,18 @@ #ifndef rive_renderer_hpp #define rive_renderer_hpp -#import - +#import +#import #import - #import "renderer.hpp" namespace rive { + /* + * RenderPaint + */ + enum class RiveGradient { None, @@ -69,7 +72,6 @@ namespace rive Luminosity = static_cast(BlendMode::luminosity) }; - class RiveRenderPaint : public RenderPaint { private: @@ -81,15 +83,16 @@ namespace rive RiveBlendMode currentBlendMode; float paintThickness; - // Gradient - RiveGradient gradient = RiveGradient::None; + // Gradient data + RiveGradient gradientType = RiveGradient::None; + CGGradientRef gradient = NULL; CGPoint gradientStart; CGPoint gradientEnd; std::vector colorStops; std::vector stops; - RiveRenderPaint(); + ~RiveRenderPaint(); void color(unsigned int value) override; void style(RenderPaintStyle value) override; @@ -103,6 +106,10 @@ namespace rive void completeGradient() override; }; + /* + * RenderPath + */ + enum class RivePathCommandType { MoveTo, @@ -126,12 +133,14 @@ namespace rive class RiveRenderPath : public RenderPath { private: - UIBezierPath *path; + CGMutablePathRef path; FillRule m_FillRule; public: RiveRenderPath(); - UIBezierPath *getBezierPath() { return path; } + ~RiveRenderPath(); + + CGMutablePathRef getPath() { return path; } FillRule getFillRule() { return m_FillRule; } void reset() override; @@ -143,14 +152,19 @@ namespace rive void close() override; }; - class NewRiveRenderer : public Renderer + /* + * Renderer + */ + + class RiveRenderer : public Renderer { private: CGContextRef ctx; public: - NewRiveRenderer(CGContextRef context) : ctx(context) {} - + RiveRenderer(CGContextRef context) : ctx(context) {} + ~RiveRenderer(); + void save() override; void restore() override; void transform(const Mat2D &transform) override; diff --git a/Source/RiveKit/RiveRenderer.mm b/Source/RiveRenderer.mm similarity index 80% rename from Source/RiveKit/RiveRenderer.mm rename to Source/RiveRenderer.mm index 8215bfed..551db2e3 100644 --- a/Source/RiveKit/RiveRenderer.mm +++ b/Source/RiveRenderer.mm @@ -10,18 +10,9 @@ #include "RiveRenderer.hpp" #include "renderer.hpp" -// Creates a UIColor from an RGBA int value -#define UIColorFromRGB(rgbValue) \ -[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/0xFF \ - green:((float)((rgbValue & 0xFF00) >> 8))/0xFF \ - blue:((float)(rgbValue & 0xFF))/0xFF \ - alpha:((float)((rgbValue & 0xFF000000) >> 24))/0xFF] - -#define opacityFromARGB(rgbValue) ((float)((rgbValue & 0xFF000000) >> 24))/0xFF - using namespace rive; -// Base color space used throughout the renderer +// Base color space used by the renderer const CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB(); /* @@ -32,6 +23,12 @@ // NSLog(@"INITIALIZING A NEW RENDER PAINT"); } +RiveRenderPaint::~RiveRenderPaint() { +// NSLog(@"Releasing paint resources"); + CGColorRelease(cgColor); + CGGradientRelease(gradient); +} + void RiveRenderPaint::style(RenderPaintStyle value) { // NSLog(@" --- RenderPaint::style"); switch(value) { @@ -39,20 +36,20 @@ paintStyle = RivePaintStyle::Fill; break; case RenderPaintStyle::stroke: -// NSLog(@"Ask for stroke"); paintStyle = RivePaintStyle::Stroke; break; } } void RiveRenderPaint::color(unsigned int value) { - // NSLog(@" --- RenderPaint::color -> %u", value); +// NSLog(@" --- RenderPaint::color -> %u", value); CGFloat color [] = { ((float)((value & 0xFF0000) >> 16))/0xFF, ((float)((value & 0xFF00) >> 8))/0xFF, ((float)(value & 0xFF))/0xFF, ((float)((value & 0xFF000000) >> 24))/0xFF }; + CGColorRelease(cgColor); cgColor = CGColorCreate(baseSpace, color); } @@ -155,24 +152,16 @@ void RiveRenderPaint::linearGradient(float sx, float sy, float ex, float ey) { // NSLog(@" --- RenderPaint::linearGradient (%.1f,%.1f), (%.1f,%.1f)", sx, sy, ex, ey); - gradient = RiveGradient::Linear; + gradientType = RiveGradient::Linear; gradientStart = CGPointMake(sx, sy); gradientEnd = CGPointMake(ex, ey); - - // clear out the stops - stops.clear(); - colorStops.clear(); - } + void RiveRenderPaint::radialGradient(float sx, float sy, float ex, float ey) { // NSLog(@" --- RenderPaint::radialGradient"); - gradient = RiveGradient::Radial; + gradientType = RiveGradient::Radial; gradientStart = CGPointMake(sx, sy); gradientEnd = CGPointMake(ex, ey); - - // clear out the stops - stops.clear(); - colorStops.clear(); } void RiveRenderPaint::addStop(unsigned int color, float stop) { @@ -185,6 +174,14 @@ } void RiveRenderPaint::completeGradient() { // NSLog(@" --- RenderPaint::completeGradient"); + // release the previously cached gradient, if any + if (gradient != NULL) { + CGGradientRelease(gradient); + } + gradient = CGGradientCreateWithColorComponents(baseSpace, &colorStops[0], &stops[0], stops.size()); + // clear out the stops + stops.clear(); + colorStops.clear(); } /* @@ -192,36 +189,36 @@ */ RiveRenderPath::RiveRenderPath() { - path = [[UIBezierPath alloc] init]; // NSLog(@"INITIALIZING A NEW RENDER PATH"); + path = CGPathCreateMutable(); +} + +RiveRenderPath::~RiveRenderPath() { +// NSLog(@"Releasing path resources"); + CGPathRelease(path); } void RiveRenderPath::close() { // NSLog(@" --- RenderPath::close"); - [path closePath]; + CGPathCloseSubpath(path); } void RiveRenderPath::reset() { // NSLog(@" --- RenderPath::reset"); - path = [[UIBezierPath alloc] init]; - // [path removeAllPoints]; + CGPathRelease(path); + path = CGPathCreateMutable(); } void RiveRenderPath::addPath(CommandPath* path, const Mat2D& transform) { // NSLog(@" --- RenderPath::addPath"); - UIBezierPath *addPath = reinterpret_cast(path)->getBezierPath(); - + CGMutablePathRef pathToAdd = reinterpret_cast(path)->getPath(); CGAffineTransform affineTransform = CGAffineTransformMake(transform.xx(), transform.xy(), transform.yx(), transform.yy(), transform.tx(), transform.ty()); - - UIBezierPath *clonePath = [addPath copy]; - - [clonePath applyTransform:affineTransform]; - [this->path appendPath:clonePath]; + CGPathAddPath(this->path, &affineTransform, pathToAdd); } void RiveRenderPath::fillRule(FillRule value) { @@ -231,48 +228,46 @@ void RiveRenderPath::moveTo(float x, float y) { // NSLog(@" --- RenderPath::moveTo x %.1f, y %.1f", x, y); - [path moveToPoint:CGPointMake(x, y)]; + CGPathMoveToPoint(path, NULL, x, y); } void RiveRenderPath::lineTo(float x, float y) { // NSLog(@" --- RenderPath::lineTo x %.1f, y %.1f", x, y); if (isnan(x) || isnan(y)) { - NSLog(@"Received NaN in lineTo!!!!"); +// NSLog(@"Received NaN in lineTo!!!!"); return; } - [path addLineToPoint:CGPointMake(x, y)]; + CGPathAddLineToPoint(path, NULL, x, y); } void RiveRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) { // NSLog(@" --- call to RenderPath::cubicTo %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, ", ox, oy, ix, iy, x, y); - [path addCurveToPoint:CGPointMake(x, y) - controlPoint1:CGPointMake(ox, oy) - controlPoint2:CGPointMake(ix, iy) - ]; + CGPathAddCurveToPoint(path, NULL, ox, oy, ix, iy, x, y); } -// Renderer +/* + * Renderer + */ + +RiveRenderer::~RiveRenderer() { + // NSLog(@"Releasing renderer c++"); +} -// Implement save by creating a sublayer -void NewRiveRenderer::save() { +void RiveRenderer::save() { // NSLog(@" --- Renderer::save"); CGContextSaveGState(ctx); } -// Implement restore by moving back up to the parent layer. If the parent -// layer is ctx, then there's been a restore without a save -void NewRiveRenderer::restore() { +void RiveRenderer::restore() { // NSLog(@" -- Renderer::restore"); CGContextRestoreGState(ctx); } -void NewRiveRenderer::drawPath(RenderPath* path, RenderPaint* paint) { - +void RiveRenderer::drawPath(RenderPath* path, RenderPaint* paint) { +// NSLog(@" --- Renderer::drawPath path for type %d", rivePaint->paintStyle); RiveRenderPaint *rivePaint = reinterpret_cast(paint); RiveRenderPath *rivePath = reinterpret_cast(path); -// NSLog(@" --- Renderer::drawPath path for type %d", rivePaint->paintStyle); - // Apply the stroke join if (rivePaint->strokeJoin != RiveStrokeJoin::None) { switch(rivePaint->strokeJoin) { @@ -363,57 +358,49 @@ } } - // Add the path and then paint it appropriately - CGPathRef cgPath = rivePath->getBezierPath().CGPath; + // Add the path and paint it + CGPathRef cgPath = rivePath->getPath(); CGContextAddPath(ctx, cgPath); // If fill or stroke set, draw appropriately if (rivePaint->cgColor != NULL) { switch (rivePaint->paintStyle) { case RivePaintStyle::Stroke: -// NSLog(@"Painting stroke"); CGContextSetStrokeColorWithColor(ctx, rivePaint->cgColor); CGContextSetLineWidth(ctx, rivePaint->paintThickness); CGContextDrawPath(ctx, kCGPathStroke); break; case RivePaintStyle::Fill: -// NSLog(@"Painting fill"); CGContextSetFillColorWithColor(ctx, rivePaint->cgColor); CGContextDrawPath(ctx, kCGPathFill); break; case RivePaintStyle::None: break; - default: - break; } - } else { -// NSLog(@"Color is null!!!"); } // Draw gradient - if (rivePaint->gradient != RiveGradient::None) { -// NSLog(@"Drawing a gradient"); - CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, &rivePaint->colorStops[0], &rivePaint->stops[0], rivePaint->stops.size()); - + if (rivePaint->gradientType != RiveGradient::None) { // If the path is a stroke, then convert the path to a stroked path to prevent the gradient from filling the path if (rivePaint->paintStyle == RivePaintStyle::Stroke) { CGContextSetLineWidth(ctx, rivePaint->paintThickness); CGContextReplacePathWithStrokedPath(ctx); } + + // Clip the gradient CGContextClip(ctx); - if (rivePaint->gradient == RiveGradient::Linear) { - CGContextDrawLinearGradient(ctx, gradient, rivePaint->gradientStart, rivePaint->gradientEnd, 0x3); - } else if (rivePaint->gradient == RiveGradient:: Radial) { + if (rivePaint->gradientType == RiveGradient::Linear) { + CGContextDrawLinearGradient(ctx, rivePaint->gradient, rivePaint->gradientStart, rivePaint->gradientEnd, 0x3); + } else if (rivePaint->gradientType == RiveGradient:: Radial) { // Calculate the end radius float dx = rivePaint->gradientEnd.x - rivePaint->gradientStart.x; float dy = rivePaint->gradientEnd.y - rivePaint->gradientStart.y; float endRadius = sqrt(dx*dx + dy*dy); - CGContextDrawRadialGradient(ctx, gradient, rivePaint->gradientStart, 0, rivePaint->gradientStart, endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + CGContextDrawRadialGradient(ctx, rivePaint->gradient, rivePaint->gradientStart, 0, rivePaint->gradientStart, endRadius, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); } - // Gradient is no longer needed - CGGradientRelease(gradient); gradient = NULL; - + + // Now draw the path, clipping the gradient if (rivePaint->paintStyle == RivePaintStyle::Fill) { CGContextDrawPath(ctx, kCGPathFill); } else if (rivePaint->paintStyle == RivePaintStyle::Stroke) { @@ -422,15 +409,14 @@ } } -void NewRiveRenderer::clipPath(RenderPath* path) { - const CGPath *clipPath = reinterpret_cast(path)->getBezierPath().CGPath; -// NSLog(@" --- Renderer::clipPath %@", clipPath); - +void RiveRenderer::clipPath(RenderPath* path) { +// NSLog(@" --- Renderer::clipPath %@", clipPath); + const CGPath *clipPath = reinterpret_cast(path)->getPath(); CGContextAddPath(ctx, clipPath); CGContextClip(ctx); } -void NewRiveRenderer::transform(const Mat2D& transform) { +void RiveRenderer::transform(const Mat2D& transform) { // NSLog(@" --- Renderer::transform %.1f, %.1f, %.1f, %.1f, %.1f, %.1f", // transform.xx(), // transform.xy(), @@ -453,6 +439,5 @@ namespace rive { RenderPaint* makeRenderPaint() { return new RiveRenderPaint(); } - RenderPath* makeRenderPath() { return new RiveRenderPath(); } } diff --git a/Source/RiveKit/RiveView.h b/Source/RiveView.h similarity index 92% rename from Source/RiveKit/RiveView.h rename to Source/RiveView.h index 3220c8e9..04e1aa53 100644 --- a/Source/RiveKit/RiveView.h +++ b/Source/RiveView.h @@ -7,6 +7,7 @@ // #import "Rive.h" +#import NS_ASSUME_NONNULL_BEGIN diff --git a/Source/RiveKit/RiveView.mm b/Source/RiveView.mm similarity index 100% rename from Source/RiveKit/RiveView.mm rename to Source/RiveView.mm diff --git a/Source/RiveKit/RiveViewController.h b/Source/RiveViewController.h similarity index 100% rename from Source/RiveKit/RiveViewController.h rename to Source/RiveViewController.h diff --git a/Source/RiveKit/RiveViewController.mm b/Source/RiveViewController.mm similarity index 100% rename from Source/RiveKit/RiveViewController.mm rename to Source/RiveViewController.mm diff --git a/submodules/rive-cpp b/submodules/rive-cpp index f0b47cf7..26ce6a33 160000 --- a/submodules/rive-cpp +++ b/submodules/rive-cpp @@ -1 +1 @@ -Subproject commit f0b47cf72bdb222a677d422be9388ed378762f1b +Subproject commit 26ce6a3396381c34258c7622f083d6a310056b35