Move externs into Factory
diff --git a/include/rive/artboard.hpp b/include/rive/artboard.hpp
index 1e483d4..3dcf69c 100644
--- a/include/rive/artboard.hpp
+++ b/include/rive/artboard.hpp
@@ -17,6 +17,7 @@
namespace rive {
class File;
class Drawable;
+ class Factory;
class Node;
class DrawTarget;
class ArtboardImporter;
@@ -42,6 +43,7 @@
unsigned int m_DirtDepth = 0;
std::unique_ptr<CommandPath> m_BackgroundPath;
std::unique_ptr<CommandPath> m_ClipPath;
+ Factory* m_Factory = nullptr;
Drawable* m_FirstDrawable = nullptr;
bool m_IsInstance = false;
bool m_FrameOrigin = true;
@@ -51,8 +53,11 @@
void sortDependencies();
void sortDrawOrder();
+ Artboard* getArtboard() override { return this; }
+
#ifdef TESTING
public:
+ Artboard(Factory* factory) : m_Factory(factory) {}
#endif
void addObject(Core* object);
void addAnimation(LinearAnimation* object);
@@ -62,15 +67,19 @@
void testing_only_enque_message(const Message&);
public:
+ Artboard() {}
~Artboard();
StatusCode initialize();
Core* resolve(uint32_t id) const override;
+
/// Find the id of a component in the artboard the object in the artboard. The artboard
/// itself has id 0 so we use that as a flag for not found.
uint32_t idOf(Core* object) const;
+ Factory* factory() const { return m_Factory; }
+
// EXPERIMENTAL -- for internal testing only for now.
// DO NOT RELY ON THIS as it may change/disappear in the future.
Core* hitTest(HitInfo*, const Mat2D* = nullptr);
@@ -161,6 +170,8 @@
class ArtboardInstance : public Artboard {
public:
+ ArtboardInstance() {}
+
std::unique_ptr<LinearAnimationInstance> animationAt(size_t index);
std::unique_ptr<LinearAnimationInstance> animationNamed(std::string name);
diff --git a/include/rive/assets/file_asset.hpp b/include/rive/assets/file_asset.hpp
index e2bff1d..01ef88e 100644
--- a/include/rive/assets/file_asset.hpp
+++ b/include/rive/assets/file_asset.hpp
@@ -1,12 +1,14 @@
#ifndef _RIVE_FILE_ASSET_HPP_
#define _RIVE_FILE_ASSET_HPP_
#include "rive/generated/assets/file_asset_base.hpp"
+#include "rive/span.hpp"
#include <string>
namespace rive {
+ class Factory;
class FileAsset : public FileAssetBase {
public:
- virtual bool decode(const uint8_t* bytes, std::size_t size) = 0;
+ virtual bool decode(Span<const uint8_t>, Factory*) = 0;
virtual std::string fileExtension() = 0;
StatusCode import(ImportStack& importStack) override;
diff --git a/include/rive/assets/image_asset.hpp b/include/rive/assets/image_asset.hpp
index 76718b9..9386fcf 100644
--- a/include/rive/assets/image_asset.hpp
+++ b/include/rive/assets/image_asset.hpp
@@ -2,24 +2,24 @@
#define _RIVE_IMAGE_ASSET_HPP_
#include "rive/generated/assets/image_asset_base.hpp"
+#include "rive/renderer.hpp"
#include <string>
namespace rive {
- class RenderImage;
class ImageAsset : public ImageAssetBase {
private:
- RenderImage* m_RenderImage;
+ std::unique_ptr<RenderImage> m_RenderImage;
public:
- ImageAsset();
+ ImageAsset() {}
~ImageAsset();
#ifdef TESTING
std::size_t decodedByteSize = 0;
#endif
- bool decode(const uint8_t* bytes, std::size_t size) override;
+ bool decode(Span<const uint8_t>, Factory*) override;
std::string fileExtension() override;
- RenderImage* renderImage() const { return m_RenderImage; }
+ RenderImage* renderImage() const { return m_RenderImage.get(); }
};
} // namespace rive
diff --git a/include/rive/core_context.hpp b/include/rive/core_context.hpp
index d8d7a4d..76ed0b2 100644
--- a/include/rive/core_context.hpp
+++ b/include/rive/core_context.hpp
@@ -4,6 +4,7 @@
#include "rive/rive_types.hpp"
namespace rive {
+ class Artboard;
class Core;
class CoreContext {
public:
diff --git a/include/rive/factory.hpp b/include/rive/factory.hpp
new file mode 100644
index 0000000..1960faf
--- /dev/null
+++ b/include/rive/factory.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 Rive
+ */
+
+#ifndef _RIVE_FACTORY_HPP_
+#define _RIVE_FACTORY_HPP_
+
+#include "rive/renderer.hpp"
+#include "rive/refcnt.hpp"
+#include "rive/span.hpp"
+#include "rive/math/aabb.hpp"
+#include "rive/math/mat2d.hpp"
+
+#include <cmath>
+#include <stdio.h>
+#include <cstdint>
+
+namespace rive {
+
+ class Factory {
+ public:
+ Factory() {}
+ virtual ~Factory() {}
+
+ virtual rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) = 0;
+ virtual rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) = 0;
+ virtual rcp<RenderBuffer> makeBufferF32(Span<const float>) = 0;
+
+ virtual rcp<RenderShader> makeLinearGradient(float sx, float sy,
+ float ex, float ey,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) = 0;
+
+ virtual rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) = 0;
+
+ // Returns a full-formed RenderPath -- can be treated as immutable
+ virtual std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
+ Span<const uint8_t> verbs,
+ FillRule) = 0;
+
+ virtual std::unique_ptr<RenderPath> makeEmptyRenderPath() = 0;
+
+ virtual std::unique_ptr<RenderPaint> makeRenderPaint() = 0;
+
+ virtual std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) = 0;
+ };
+
+} // namespace rive
+#endif
diff --git a/include/rive/file.hpp b/include/rive/file.hpp
index 419634e..c7b4017 100644
--- a/include/rive/file.hpp
+++ b/include/rive/file.hpp
@@ -3,6 +3,7 @@
#include "rive/artboard.hpp"
#include "rive/backboard.hpp"
+#include "rive/factory.hpp"
#include "rive/file_asset_resolver.hpp"
#include <vector>
@@ -12,6 +13,7 @@
namespace rive {
class BinaryReader;
class RuntimeHeader;
+ class Factory;
///
/// Tracks the success/failure result when importing a Rive file.
@@ -44,11 +46,13 @@
/// Rive components and animations.
std::vector<std::unique_ptr<Artboard>> m_Artboards;
+ Factory* m_Factory;
+
/// The helper used to resolve assets when they're not provided in-band
/// with the file.
FileAssetResolver* m_AssetResolver;
- File(FileAssetResolver* assetResolver);
+ File(Factory*, FileAssetResolver*);
public:
~File();
@@ -61,8 +65,9 @@
/// cannot be found in-band.
/// @returns a pointer to the file, or null on failure.
static std::unique_ptr<File> import(Span<const uint8_t> data,
- ImportResult* result = nullptr,
- FileAssetResolver* assetResolver = nullptr);
+ Factory*,
+ ImportResult* result = nullptr,
+ FileAssetResolver* assetResolver = nullptr);
/// @returns the file's backboard. All files have exactly one backboard.
Backboard* backboard() const { return m_Backboard.get(); }
@@ -87,7 +92,7 @@
Artboard* artboard(size_t index) const;
private:
- ImportResult read(BinaryReader& reader, const RuntimeHeader& header);
+ ImportResult read(BinaryReader&, const RuntimeHeader&);
};
} // namespace rive
-#endif
\ No newline at end of file
+#endif
diff --git a/include/rive/importers/file_asset_importer.hpp b/include/rive/importers/file_asset_importer.hpp
index 6ad9d0c..170a440 100644
--- a/include/rive/importers/file_asset_importer.hpp
+++ b/include/rive/importers/file_asset_importer.hpp
@@ -9,14 +9,17 @@
class FileAsset;
class FileAssetContents;
class FileAssetResolver;
+ class Factory;
+
class FileAssetImporter : public ImportStackObject {
private:
bool m_LoadedContents = false;
FileAsset* m_FileAsset;
FileAssetResolver* m_FileAssetResolver;
+ Factory* m_Factory;
public:
- FileAssetImporter(FileAsset* fileAsset, FileAssetResolver* assetResolver);
+ FileAssetImporter(FileAsset*, FileAssetResolver*, Factory*);
void loadContents(const FileAssetContents& contents);
StatusCode resolve() override;
};
diff --git a/include/rive/relative_local_asset_resolver.hpp b/include/rive/relative_local_asset_resolver.hpp
index 63a7edb..5aa3f4c 100644
--- a/include/rive/relative_local_asset_resolver.hpp
+++ b/include/rive/relative_local_asset_resolver.hpp
@@ -8,14 +8,19 @@
namespace rive {
class FileAsset;
+ class Factory;
+
/// An implementation of FileAssetResolver which finds the assets in a local
/// path relative to the original .riv file looking for them.
class RelativeLocalAssetResolver : public FileAssetResolver {
private:
std::string m_Path;
+ Factory* m_Factory;
public:
- RelativeLocalAssetResolver(std::string filename) {
+ RelativeLocalAssetResolver(std::string filename, Factory* factory)
+ : m_Factory(factory)
+ {
std::size_t finalSlash = filename.rfind('/');
if (finalSlash != std::string::npos) {
@@ -32,7 +37,7 @@
fseek(fp, 0, SEEK_SET);
uint8_t* bytes = new uint8_t[length];
if (fread(bytes, 1, length, fp) == length) {
- asset.decode(bytes, length);
+ asset.decode(Span<const uint8_t>(bytes, length), m_Factory);
}
delete[] bytes;
}
diff --git a/include/rive/renderer.hpp b/include/rive/renderer.hpp
index affe81f..5d23576 100644
--- a/include/rive/renderer.hpp
+++ b/include/rive/renderer.hpp
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2022 Rive
+ */
+
#ifndef _RIVE_RENDERER_HPP_
#define _RIVE_RENDERER_HPP_
@@ -8,10 +12,10 @@
#include "rive/span.hpp"
#include "rive/math/aabb.hpp"
#include "rive/math/mat2d.hpp"
-#include "rive/math/raw_path.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/stroke_cap.hpp"
#include "rive/shapes/paint/stroke_join.hpp"
+
#include <cmath>
#include <stdio.h>
#include <cstdint>
@@ -32,10 +36,6 @@
size_t count() const { return m_Count; }
};
- extern rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>);
- extern rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>);
- extern rcp<RenderBuffer> makeBufferF32(Span<const float>);
-
enum class RenderPaintStyle { stroke, fill };
enum class RenderTileMode {
@@ -55,32 +55,6 @@
*/
class RenderShader : public RefCnt {};
- extern rcp<RenderShader> makeLinearGradient(float sx,
- float sy,
- float ex,
- float ey,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- int count,
- RenderTileMode,
- const Mat2D* localMatrix = nullptr);
-
- extern rcp<RenderShader> makeRadialGradient(float cx,
- float cy,
- float radius,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- int count,
- RenderTileMode,
- const Mat2D* localMatrix = nullptr);
-
- extern rcp<RenderShader> makeSweepGradient(float cx,
- float cy,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- int count,
- const Mat2D* localMatrix = nullptr);
-
class RenderPaint {
public:
virtual void style(RenderPaintStyle style) = 0;
@@ -101,7 +75,6 @@
public:
virtual ~RenderImage() {}
- virtual bool decode(Span<const uint8_t>) = 0;
int width() const { return m_Width; }
int height() const { return m_Height; }
@@ -146,13 +119,5 @@
transform(computeAlignment(fit, alignment, frame, content));
}
};
-
- // Returns a full-formed RenderPath -- can be treated as immutable
- extern RenderPath*
- makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule);
-
- extern RenderPath* makeRenderPath();
- extern RenderPaint* makeRenderPaint();
- extern RenderImage* makeRenderImage();
} // namespace rive
#endif
diff --git a/include/rive/shapes/clipping_shape.hpp b/include/rive/shapes/clipping_shape.hpp
index 4d01176..3ed3227 100644
--- a/include/rive/shapes/clipping_shape.hpp
+++ b/include/rive/shapes/clipping_shape.hpp
@@ -1,5 +1,6 @@
#ifndef _RIVE_CLIPPING_SHAPE_HPP_
#define _RIVE_CLIPPING_SHAPE_HPP_
+#include "rive/renderer.hpp"
#include "rive/generated/shapes/clipping_shape_base.hpp"
#include <stdio.h>
#include <vector>
@@ -12,10 +13,9 @@
private:
std::vector<Shape*> m_Shapes;
Node* m_Source = nullptr;
- RenderPath* m_RenderPath = nullptr;
+ std::unique_ptr<RenderPath> m_RenderPath;
public:
- ~ClippingShape();
Node* source() const { return m_Source; }
const std::vector<Shape*>& shapes() const { return m_Shapes; }
StatusCode onAddedClean(CoreContext* context) override;
@@ -23,7 +23,7 @@
void buildDependencies() override;
void update(ComponentDirt value) override;
- RenderPath* renderPath() const { return m_RenderPath; }
+ RenderPath* renderPath() const { return m_RenderPath.get(); }
};
} // namespace rive
diff --git a/include/rive/shapes/metrics_path.hpp b/include/rive/shapes/metrics_path.hpp
index c504c3a..daa694a 100644
--- a/include/rive/shapes/metrics_path.hpp
+++ b/include/rive/shapes/metrics_path.hpp
@@ -80,12 +80,11 @@
class RenderMetricsPath : public MetricsPath {
private:
- RenderPath* m_RenderPath;
+ std::unique_ptr<RenderPath> m_RenderPath;
public:
- RenderMetricsPath();
- ~RenderMetricsPath();
- RenderPath* renderPath() override { return m_RenderPath; }
+ RenderMetricsPath(std::unique_ptr<RenderPath>);
+ RenderPath* renderPath() override { return m_RenderPath.get(); }
void addPath(CommandPath* path, const Mat2D& transform) override;
void fillRule(FillRule value) override;
diff --git a/include/rive/shapes/paint/shape_paint.hpp b/include/rive/shapes/paint/shape_paint.hpp
index ed6b3b7..661adb7 100644
--- a/include/rive/shapes/paint/shape_paint.hpp
+++ b/include/rive/shapes/paint/shape_paint.hpp
@@ -10,11 +10,10 @@
class ShapePaintMutator;
class ShapePaint : public ShapePaintBase {
protected:
- RenderPaint* m_RenderPaint = nullptr;
+ std::unique_ptr<RenderPaint> m_RenderPaint;
ShapePaintMutator* m_PaintMutator = nullptr;
public:
- ~ShapePaint();
StatusCode onAddedClean(CoreContext* context) override;
float renderOpacity() const { return m_PaintMutator->renderOpacity(); }
@@ -31,6 +30,8 @@
virtual void draw(Renderer* renderer, CommandPath* path) = 0;
+ RenderPaint* renderPaint() { return m_RenderPaint.get(); }
+
/// Get the component that represents the ShapePaintMutator for this
/// ShapePaint. It'll be one of SolidColor, LinearGradient, or
/// RadialGradient.
diff --git a/include/rive/shapes/paint/stroke_effect.hpp b/include/rive/shapes/paint/stroke_effect.hpp
index bc40a4c..1db1423 100644
--- a/include/rive/shapes/paint/stroke_effect.hpp
+++ b/include/rive/shapes/paint/stroke_effect.hpp
@@ -1,12 +1,16 @@
#ifndef _RIVE_STROKE_EFFECT_HPP_
#define _RIVE_STROKE_EFFECT_HPP_
+
+#include "rive/rive_types.hpp"
+
namespace rive {
+ class Factory;
class RenderPath;
class MetricsPath;
class StrokeEffect {
public:
- virtual RenderPath* effectPath(MetricsPath* source) = 0;
+ virtual RenderPath* effectPath(MetricsPath* source, Factory*) = 0;
virtual void invalidateEffect() = 0;
};
} // namespace rive
diff --git a/include/rive/shapes/paint/trim_path.hpp b/include/rive/shapes/paint/trim_path.hpp
index 9806228..7289590 100644
--- a/include/rive/shapes/paint/trim_path.hpp
+++ b/include/rive/shapes/paint/trim_path.hpp
@@ -2,19 +2,18 @@
#define _RIVE_TRIM_PATH_HPP_
#include "rive/generated/shapes/paint/trim_path_base.hpp"
#include "rive/shapes/paint/stroke_effect.hpp"
+#include "rive/renderer.hpp"
#include <stdio.h>
namespace rive {
class TrimPath : public TrimPathBase, public StrokeEffect {
private:
- RenderPath* m_TrimmedPath;
+ std::unique_ptr<RenderPath> m_TrimmedPath;
RenderPath* m_RenderPath = nullptr;
public:
- TrimPath();
- ~TrimPath();
StatusCode onAddedClean(CoreContext* context) override;
- RenderPath* effectPath(MetricsPath* source) override;
+ RenderPath* effectPath(MetricsPath* source, Factory*) override;
void invalidateEffect() override;
void startChanged() override;
diff --git a/include/rive/shapes/shape.hpp b/include/rive/shapes/shape.hpp
index a4e6f37..8caf7f8 100644
--- a/include/rive/shapes/shape.hpp
+++ b/include/rive/shapes/shape.hpp
@@ -18,6 +18,8 @@
bool m_WantDifferencePath = false;
+ Artboard* getArtboard() override { return artboard(); }
+
public:
Shape();
void buildDependencies() override;
diff --git a/include/rive/shapes/shape_paint_container.hpp b/include/rive/shapes/shape_paint_container.hpp
index 1f1eede..89abf04 100644
--- a/include/rive/shapes/shape_paint_container.hpp
+++ b/include/rive/shapes/shape_paint_container.hpp
@@ -5,6 +5,7 @@
#include <vector>
namespace rive {
+ class Artboard;
class ShapePaint;
class Component;
@@ -14,6 +15,10 @@
friend class ShapePaint;
protected:
+ // Need this to access our artboard. We are treated as a mixin, either
+ // as a Shape or Artboard, so both of those will override this.
+ virtual Artboard* getArtboard() = 0;
+
PathSpace m_DefaultPathSpace = PathSpace::Neither;
std::vector<ShapePaint*> m_ShapePaints;
void addPaint(ShapePaint* paint);
diff --git a/skia/renderer/include/skia_factory.hpp b/skia/renderer/include/skia_factory.hpp
new file mode 100644
index 0000000..14abfa8
--- /dev/null
+++ b/skia/renderer/include/skia_factory.hpp
@@ -0,0 +1,40 @@
+#ifndef _RIVE_SKIA_FACTORY_HPP_
+#define _RIVE_SKIA_FACTORY_HPP_
+
+#include "rive/factory.hpp"
+
+namespace rive {
+
+class SkiaFactory : public Factory {
+ rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
+ rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
+ rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
+
+ rcp<RenderShader> makeLinearGradient(float sx, float sy,
+ float ex, float ey,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) override;
+
+ rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) override;
+
+ std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
+ Span<const uint8_t> verbs,
+ FillRule) override;
+
+ std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
+
+ std::unique_ptr<RenderPaint> makeRenderPaint() override;
+
+ std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override;
+};
+
+} // namespace rive
+#endif
diff --git a/skia/renderer/include/skia_renderer.hpp b/skia/renderer/include/skia_renderer.hpp
index b6ea76b..706e663 100644
--- a/skia/renderer/include/skia_renderer.hpp
+++ b/skia/renderer/include/skia_renderer.hpp
@@ -1,59 +1,11 @@
#ifndef _RIVE_SKIA_RENDERER_HPP_
#define _RIVE_SKIA_RENDERER_HPP_
-#include "SkCanvas.h"
-#include "SkPaint.h"
-#include "SkPath.h"
-#include "SkImage.h"
#include "rive/renderer.hpp"
-#include <vector>
+
+class SkCanvas;
namespace rive {
- class SkiaRenderPath : public RenderPath {
- private:
- SkPath m_Path;
-
- public:
- SkiaRenderPath() {}
- SkiaRenderPath(SkPath&& path) : m_Path(std::move(path)) {}
-
- const SkPath& path() const { return m_Path; }
- void reset() override;
- void addRenderPath(RenderPath* path, const Mat2D& transform) override;
- void fillRule(FillRule value) override;
- void moveTo(float x, float y) override;
- void lineTo(float x, float y) override;
- void cubicTo(float ox, float oy, float ix, float iy, float x, float y) override;
- virtual void close() override;
- };
-
- class SkiaRenderPaint : public RenderPaint {
- private:
- SkPaint m_Paint;
-
- public:
- const SkPaint& paint() const { return m_Paint; }
- SkiaRenderPaint();
- void style(RenderPaintStyle style) override;
- void color(unsigned int value) override;
- void thickness(float value) override;
- void join(StrokeJoin value) override;
- void cap(StrokeCap value) override;
- void blendMode(BlendMode value) override;
- void shader(rcp<RenderShader>) override;
- };
-
- class SkiaRenderImage : public RenderImage {
- private:
- sk_sp<SkImage> m_SkImage;
-
- public:
- sk_sp<SkImage> skImage() const { return m_SkImage; };
- bool decode(Span<const uint8_t>) override;
- rcp<RenderShader>
- makeShader(RenderTileMode tx, RenderTileMode ty, const Mat2D* localMatrix) const override;
- };
-
class SkiaRenderer : public Renderer {
protected:
SkCanvas* m_Canvas;
diff --git a/skia/renderer/include/to_skia.hpp b/skia/renderer/include/to_skia.hpp
index c19bf7e..365b4c0 100644
--- a/skia/renderer/include/to_skia.hpp
+++ b/skia/renderer/include/to_skia.hpp
@@ -4,6 +4,7 @@
#include "SkPaint.h"
#include "rive/math/mat2d.hpp"
#include "rive/math/vec2d.hpp"
+#include "rive/renderer.hpp"
#include "rive/shapes/paint/stroke_cap.hpp"
#include "rive/shapes/paint/stroke_join.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
diff --git a/skia/renderer/src/skia_factory.cpp b/skia/renderer/src/skia_factory.cpp
new file mode 100644
index 0000000..9f6b49b
--- /dev/null
+++ b/skia/renderer/src/skia_factory.cpp
@@ -0,0 +1,339 @@
+#include "skia_factory.hpp"
+
+#include "SkCanvas.h"
+#include "SkData.h"
+#include "SkGradientShader.h"
+#include "SkImage.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkVertices.h"
+#include "rive/math/vec2d.hpp"
+#include "rive/shapes/paint/color.hpp"
+#include "to_skia.hpp"
+
+using namespace rive;
+
+class SkiaRenderPath : public RenderPath {
+private:
+ SkPath m_Path;
+
+public:
+ SkiaRenderPath() {}
+ SkiaRenderPath(SkPath&& path) : m_Path(std::move(path)) {}
+
+ const SkPath& path() const { return m_Path; }
+
+ void reset() override;
+ void addRenderPath(RenderPath* path, const Mat2D& transform) override;
+ void fillRule(FillRule value) override;
+ void moveTo(float x, float y) override;
+ void lineTo(float x, float y) override;
+ void cubicTo(float ox, float oy, float ix, float iy, float x, float y) override;
+ virtual void close() override;
+};
+
+class SkiaRenderPaint : public RenderPaint {
+private:
+ SkPaint m_Paint;
+
+public:
+ SkiaRenderPaint();
+
+ const SkPaint& paint() const { return m_Paint; }
+
+ void style(RenderPaintStyle style) override;
+ void color(unsigned int value) override;
+ void thickness(float value) override;
+ void join(StrokeJoin value) override;
+ void cap(StrokeCap value) override;
+ void blendMode(BlendMode value) override;
+ void shader(rcp<RenderShader>) override;
+};
+
+class SkiaRenderImage : public RenderImage {
+private:
+ sk_sp<SkImage> m_SkImage;
+
+public:
+ SkiaRenderImage(sk_sp<SkImage> image);
+
+ sk_sp<SkImage> skImage() const { return m_SkImage; };
+
+ rcp<RenderShader>
+ makeShader(RenderTileMode tx, RenderTileMode ty, const Mat2D* localMatrix) const override;
+};
+
+class SkiaRenderer : public Renderer {
+protected:
+ SkCanvas* m_Canvas;
+
+public:
+ SkiaRenderer(SkCanvas* canvas) : m_Canvas(canvas) {}
+
+ void save() override;
+ void restore() override;
+ void transform(const Mat2D& transform) override;
+ void clipPath(RenderPath* path) override;
+ void drawPath(RenderPath* path, RenderPaint* paint) override;
+ void drawImage(const RenderImage*, BlendMode, float opacity) override;
+ void drawImageMesh(const RenderImage*,
+ rcp<RenderBuffer> vertices_f32,
+ rcp<RenderBuffer> uvCoords_f32,
+ rcp<RenderBuffer> indices_u16,
+ BlendMode,
+ float opacity) override;
+};
+
+class SkiaBuffer : public RenderBuffer {
+ const size_t m_ElemSize;
+ void* m_Buffer;
+
+public:
+ SkiaBuffer(const void* src, size_t count, size_t elemSize) :
+ RenderBuffer(count), m_ElemSize(elemSize) {
+ size_t bytes = count * elemSize;
+ m_Buffer = malloc(bytes);
+ memcpy(m_Buffer, src, bytes);
+ }
+
+ ~SkiaBuffer() { free(m_Buffer); }
+
+ const float* f32s() const {
+ assert(m_ElemSize == sizeof(float));
+ return static_cast<const float*>(m_Buffer);
+ }
+
+ const uint16_t* u16s() const {
+ assert(m_ElemSize == sizeof(uint16_t));
+ return static_cast<const uint16_t*>(m_Buffer);
+ }
+
+ const SkPoint* points() const { return reinterpret_cast<const SkPoint*>(this->f32s()); }
+
+ static const SkiaBuffer* Cast(const RenderBuffer* buffer) {
+ return reinterpret_cast<const SkiaBuffer*>(buffer);
+ }
+};
+
+template <typename T> rcp<RenderBuffer> make_buffer(Span<T> span) {
+ return rcp<RenderBuffer>(new SkiaBuffer(span.data(), span.size(), sizeof(T)));
+}
+
+class SkiaRenderShader : public RenderShader {
+public:
+ SkiaRenderShader(sk_sp<SkShader> sh) : shader(std::move(sh)) {}
+
+ sk_sp<SkShader> shader;
+};
+
+void SkiaRenderPath::fillRule(FillRule value) { m_Path.setFillType(ToSkia::convert(value)); }
+
+void SkiaRenderPath::reset() { m_Path.reset(); }
+void SkiaRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform) {
+ m_Path.addPath(reinterpret_cast<SkiaRenderPath*>(path)->m_Path, ToSkia::convert(transform));
+}
+
+void SkiaRenderPath::moveTo(float x, float y) { m_Path.moveTo(x, y); }
+void SkiaRenderPath::lineTo(float x, float y) { m_Path.lineTo(x, y); }
+void SkiaRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) {
+ m_Path.cubicTo(ox, oy, ix, iy, x, y);
+}
+void SkiaRenderPath::close() { m_Path.close(); }
+
+SkiaRenderPaint::SkiaRenderPaint() { m_Paint.setAntiAlias(true); }
+
+void SkiaRenderPaint::style(RenderPaintStyle style) {
+ switch (style) {
+ case RenderPaintStyle::fill:
+ m_Paint.setStyle(SkPaint::Style::kFill_Style);
+ break;
+ case RenderPaintStyle::stroke:
+ m_Paint.setStyle(SkPaint::Style::kStroke_Style);
+ break;
+ }
+}
+void SkiaRenderPaint::color(unsigned int value) { m_Paint.setColor(value); }
+void SkiaRenderPaint::thickness(float value) { m_Paint.setStrokeWidth(value); }
+void SkiaRenderPaint::join(StrokeJoin value) { m_Paint.setStrokeJoin(ToSkia::convert(value)); }
+void SkiaRenderPaint::cap(StrokeCap value) { m_Paint.setStrokeCap(ToSkia::convert(value)); }
+
+void SkiaRenderPaint::blendMode(BlendMode value) { m_Paint.setBlendMode(ToSkia::convert(value)); }
+
+void SkiaRenderPaint::shader(rcp<RenderShader> rsh) {
+ SkiaRenderShader* sksh = (SkiaRenderShader*)rsh.get();
+ m_Paint.setShader(sksh ? sksh->shader : nullptr);
+}
+
+void SkiaRenderer::save() { m_Canvas->save(); }
+void SkiaRenderer::restore() { m_Canvas->restore(); }
+void SkiaRenderer::transform(const Mat2D& transform) {
+ m_Canvas->concat(ToSkia::convert(transform));
+}
+void SkiaRenderer::drawPath(RenderPath* path, RenderPaint* paint) {
+ m_Canvas->drawPath(reinterpret_cast<SkiaRenderPath*>(path)->path(),
+ reinterpret_cast<SkiaRenderPaint*>(paint)->paint());
+}
+
+void SkiaRenderer::clipPath(RenderPath* path) {
+ m_Canvas->clipPath(reinterpret_cast<SkiaRenderPath*>(path)->path(), true);
+}
+
+void SkiaRenderer::drawImage(const RenderImage* image, BlendMode blendMode, float opacity) {
+ SkPaint paint;
+ paint.setAlphaf(opacity);
+ paint.setBlendMode(ToSkia::convert(blendMode));
+ auto skiaImage = reinterpret_cast<const SkiaRenderImage*>(image);
+ SkSamplingOptions sampling(SkFilterMode::kLinear);
+ m_Canvas->drawImage(skiaImage->skImage(), 0.0f, 0.0f, sampling, &paint);
+}
+
+#define SKIA_BUG_13047
+
+void SkiaRenderer::drawImageMesh(const RenderImage* image,
+ rcp<RenderBuffer> vertices,
+ rcp<RenderBuffer> uvCoords,
+ rcp<RenderBuffer> indices,
+ BlendMode blendMode,
+ float opacity) {
+ // need our vertices and uvs to agree
+ assert(vertices->count() == uvCoords->count());
+ // vertices and uvs are arrays of floats, so we need their counts to be
+ // even, since we treat them as arrays of points
+ assert((vertices->count() & 1) == 0);
+
+ const int vertexCount = vertices->count() >> 1;
+
+ SkMatrix scaleM;
+
+ const SkPoint* uvs = SkiaBuffer::Cast(uvCoords.get())->points();
+
+#ifdef SKIA_BUG_13047
+ // The local matrix is ignored for drawVertices, so we have to manually scale
+ // the UVs to match Skia's convention...
+ std::vector<SkPoint> scaledUVs(vertexCount);
+ for (int i = 0; i < vertexCount; ++i) {
+ scaledUVs[i] = {uvs[i].fX * image->width(), uvs[i].fY * image->height()};
+ }
+ uvs = scaledUVs.data();
+#else
+ // We do this because our UVs are normalized, but Skia expects them to be
+ // sized to the shader (i.e. 0..width, 0..height).
+ // To accomdate this, we effectively scaling the image down to 0..1 to
+ // match the scale of the UVs.
+ scaleM = SkMatrix::Scale(2.0f / image->width(), 2.0f / image->height());
+#endif
+
+ auto skiaImage = reinterpret_cast<const SkiaRenderImage*>(image)->skImage();
+ const SkSamplingOptions sampling(SkFilterMode::kLinear);
+ auto shader = skiaImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, &scaleM);
+
+ SkPaint paint;
+ paint.setAlphaf(opacity);
+ paint.setBlendMode(ToSkia::convert(blendMode));
+ paint.setShader(shader);
+
+ const SkColor* no_colors = nullptr;
+ auto vertexMode = SkVertices::kTriangles_VertexMode;
+ // clang-format off
+ auto vt = SkVertices::MakeCopy(vertexMode,
+ vertexCount,
+ SkiaBuffer::Cast(vertices.get())->points(),
+ uvs,
+ no_colors,
+ indices->count(),
+ SkiaBuffer::Cast(indices.get())->u16s());
+ // clang-format on
+
+ // The blend mode is ignored if we don't have colors && uvs
+ m_Canvas->drawVertices(vt, SkBlendMode::kModulate, paint);
+}
+
+SkiaRenderImage::SkiaRenderImage(sk_sp<SkImage> image) : m_SkImage(std::move(image)) {
+ m_Width = m_SkImage->width();
+ m_Height = m_SkImage->height();
+}
+
+rcp<RenderShader>
+SkiaRenderImage::makeShader(RenderTileMode tx, RenderTileMode ty, const Mat2D* localMatrix) const {
+ const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
+ const SkSamplingOptions options(SkFilterMode::kLinear);
+ auto sh = m_SkImage->makeShader(ToSkia::convert(tx), ToSkia::convert(ty), options, &lm);
+ return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
+}
+
+// Factory
+
+rcp<RenderBuffer> SkiaFactory::makeBufferU16(Span<const uint16_t> data) {
+ return make_buffer(data);
+}
+
+rcp<RenderBuffer> SkiaFactory::makeBufferU32(Span<const uint32_t> data) {
+ return make_buffer(data);
+}
+
+rcp<RenderBuffer> SkiaFactory::makeBufferF32(Span<const float> data) {
+ return make_buffer(data);
+}
+
+rcp<RenderShader> SkiaFactory::makeLinearGradient(float sx, float sy,
+ float ex, float ey,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode mode,
+ const Mat2D* localMatrix) {
+ const SkPoint pts[] = {{sx, sy}, {ex, ey}};
+ const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
+ auto sh = SkGradientShader::MakeLinear(
+ pts, (const SkColor*)colors, stops, count, ToSkia::convert(mode), 0, &lm);
+ return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
+}
+
+rcp<RenderShader> SkiaFactory::makeRadialGradient(float cx, float cy, float radius,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode mode,
+ const Mat2D* localMatrix) {
+ const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
+ auto sh = SkGradientShader::MakeRadial(
+ {cx, cy}, radius, (const SkColor*)colors, stops, count, ToSkia::convert(mode), 0, &lm);
+ return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
+}
+
+std::unique_ptr<RenderPath> SkiaFactory::makeRenderPath(Span<const Vec2D> points,
+ Span<const uint8_t> verbs,
+ FillRule fillRule) {
+ const bool isVolatile = false; // ???
+ const SkScalar* conicWeights = nullptr;
+ const int conicWeightCount = 0;
+ return std::make_unique<SkiaRenderPath>(SkPath::Make(reinterpret_cast<const SkPoint*>(points.data()),
+ points.count(),
+ verbs.data(),
+ verbs.count(),
+ conicWeights,
+ conicWeightCount,
+ ToSkia::convert(fillRule),
+ isVolatile));
+}
+
+std::unique_ptr<RenderPath> SkiaFactory::makeEmptyRenderPath() {
+ return std::make_unique<SkiaRenderPath>();
+}
+
+std::unique_ptr<RenderPaint> SkiaFactory::makeRenderPaint() {
+ return std::make_unique<SkiaRenderPaint>();
+}
+
+std::unique_ptr<RenderImage> SkiaFactory::decodeImage(Span<const uint8_t> encoded) {
+ sk_sp<SkData> data = SkData::MakeWithoutCopy(encoded.data(), encoded.size());
+ auto image = SkImage::MakeFromEncoded(data);
+
+ // Our optimized skia buld seems to have broken lazy-image decode.
+ // As a work-around for now, force the image to be decoded.
+ if (image) {
+ image = image->makeRasterImage();
+ }
+
+ return image ? std::make_unique<SkiaRenderImage>(std::move(image)) : nullptr;
+}
diff --git a/skia/renderer/src/skia_renderer.cpp b/skia/renderer/src/skia_renderer.cpp
deleted file mode 100644
index 8628a85..0000000
--- a/skia/renderer/src/skia_renderer.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-#include "skia_renderer.hpp"
-#include "SkData.h"
-#include "SkGradientShader.h"
-#include "SkPath.h"
-#include "SkVertices.h"
-#include "rive/math/vec2d.hpp"
-#include "rive/shapes/paint/color.hpp"
-#include "to_skia.hpp"
-
-using namespace rive;
-
-class SkiaBuffer : public RenderBuffer {
- const size_t m_ElemSize;
- void* m_Buffer;
-
-public:
- SkiaBuffer(const void* src, size_t count, size_t elemSize) :
- RenderBuffer(count), m_ElemSize(elemSize) {
- size_t bytes = count * elemSize;
- m_Buffer = malloc(bytes);
- memcpy(m_Buffer, src, bytes);
- }
-
- ~SkiaBuffer() { free(m_Buffer); }
-
- const float* f32s() const {
- assert(m_ElemSize == sizeof(float));
- return static_cast<const float*>(m_Buffer);
- }
-
- const uint16_t* u16s() const {
- assert(m_ElemSize == sizeof(uint16_t));
- return static_cast<const uint16_t*>(m_Buffer);
- }
-
- const SkPoint* points() const { return reinterpret_cast<const SkPoint*>(this->f32s()); }
-
- static const SkiaBuffer* Cast(const RenderBuffer* buffer) {
- return reinterpret_cast<const SkiaBuffer*>(buffer);
- }
-};
-
-template <typename T> rcp<RenderBuffer> make_buffer(Span<T> span) {
- return rcp<RenderBuffer>(new SkiaBuffer(span.data(), span.size(), sizeof(T)));
-}
-
-class SkiaRenderShader : public RenderShader {
-public:
- SkiaRenderShader(sk_sp<SkShader> sh) : shader(std::move(sh)) {}
-
- sk_sp<SkShader> shader;
-};
-
-void SkiaRenderPath::fillRule(FillRule value) { m_Path.setFillType(ToSkia::convert(value)); }
-
-void SkiaRenderPath::reset() { m_Path.reset(); }
-void SkiaRenderPath::addRenderPath(RenderPath* path, const Mat2D& transform) {
- m_Path.addPath(reinterpret_cast<SkiaRenderPath*>(path)->m_Path, ToSkia::convert(transform));
-}
-
-void SkiaRenderPath::moveTo(float x, float y) { m_Path.moveTo(x, y); }
-void SkiaRenderPath::lineTo(float x, float y) { m_Path.lineTo(x, y); }
-void SkiaRenderPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y) {
- m_Path.cubicTo(ox, oy, ix, iy, x, y);
-}
-void SkiaRenderPath::close() { m_Path.close(); }
-
-SkiaRenderPaint::SkiaRenderPaint() { m_Paint.setAntiAlias(true); }
-
-void SkiaRenderPaint::style(RenderPaintStyle style) {
- switch (style) {
- case RenderPaintStyle::fill:
- m_Paint.setStyle(SkPaint::Style::kFill_Style);
- break;
- case RenderPaintStyle::stroke:
- m_Paint.setStyle(SkPaint::Style::kStroke_Style);
- break;
- }
-}
-void SkiaRenderPaint::color(unsigned int value) { m_Paint.setColor(value); }
-void SkiaRenderPaint::thickness(float value) { m_Paint.setStrokeWidth(value); }
-void SkiaRenderPaint::join(StrokeJoin value) { m_Paint.setStrokeJoin(ToSkia::convert(value)); }
-void SkiaRenderPaint::cap(StrokeCap value) { m_Paint.setStrokeCap(ToSkia::convert(value)); }
-
-void SkiaRenderPaint::blendMode(BlendMode value) { m_Paint.setBlendMode(ToSkia::convert(value)); }
-
-void SkiaRenderPaint::shader(rcp<RenderShader> rsh) {
- SkiaRenderShader* sksh = (SkiaRenderShader*)rsh.get();
- m_Paint.setShader(sksh ? sksh->shader : nullptr);
-}
-
-void SkiaRenderer::save() { m_Canvas->save(); }
-void SkiaRenderer::restore() { m_Canvas->restore(); }
-void SkiaRenderer::transform(const Mat2D& transform) {
- m_Canvas->concat(ToSkia::convert(transform));
-}
-void SkiaRenderer::drawPath(RenderPath* path, RenderPaint* paint) {
- m_Canvas->drawPath(reinterpret_cast<SkiaRenderPath*>(path)->path(),
- reinterpret_cast<SkiaRenderPaint*>(paint)->paint());
-}
-
-void SkiaRenderer::clipPath(RenderPath* path) {
- m_Canvas->clipPath(reinterpret_cast<SkiaRenderPath*>(path)->path(), true);
-}
-
-void SkiaRenderer::drawImage(const RenderImage* image, BlendMode blendMode, float opacity) {
- SkPaint paint;
- paint.setAlphaf(opacity);
- paint.setBlendMode(ToSkia::convert(blendMode));
- auto skiaImage = reinterpret_cast<const SkiaRenderImage*>(image);
- SkSamplingOptions sampling(SkFilterMode::kLinear);
- m_Canvas->drawImage(skiaImage->skImage(), 0.0f, 0.0f, sampling, &paint);
-}
-
-#define SKIA_BUG_13047
-
-void SkiaRenderer::drawImageMesh(const RenderImage* image,
- rcp<RenderBuffer> vertices,
- rcp<RenderBuffer> uvCoords,
- rcp<RenderBuffer> indices,
- BlendMode blendMode,
- float opacity) {
- // need our vertices and uvs to agree
- assert(vertices->count() == uvCoords->count());
- // vertices and uvs are arrays of floats, so we need their counts to be
- // even, since we treat them as arrays of points
- assert((vertices->count() & 1) == 0);
-
- const int vertexCount = vertices->count() >> 1;
-
- SkMatrix scaleM;
-
- const SkPoint* uvs = SkiaBuffer::Cast(uvCoords.get())->points();
-
-#ifdef SKIA_BUG_13047
- // The local matrix is ignored for drawVertices, so we have to manually scale
- // the UVs to match Skia's convention...
- std::vector<SkPoint> scaledUVs(vertexCount);
- for (int i = 0; i < vertexCount; ++i) {
- scaledUVs[i] = {uvs[i].fX * image->width(), uvs[i].fY * image->height()};
- }
- uvs = scaledUVs.data();
-#else
- // We do this because our UVs are normalized, but Skia expects them to be
- // sized to the shader (i.e. 0..width, 0..height).
- // To accomdate this, we effectively scaling the image down to 0..1 to
- // match the scale of the UVs.
- scaleM = SkMatrix::Scale(2.0f / image->width(), 2.0f / image->height());
-#endif
-
- auto skiaImage = reinterpret_cast<const SkiaRenderImage*>(image)->skImage();
- const SkSamplingOptions sampling(SkFilterMode::kLinear);
- auto shader = skiaImage->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, sampling, &scaleM);
-
- SkPaint paint;
- paint.setAlphaf(opacity);
- paint.setBlendMode(ToSkia::convert(blendMode));
- paint.setShader(shader);
-
- const SkColor* no_colors = nullptr;
- auto vertexMode = SkVertices::kTriangles_VertexMode;
- // clang-format off
- auto vt = SkVertices::MakeCopy(vertexMode,
- vertexCount,
- SkiaBuffer::Cast(vertices.get())->points(),
- uvs,
- no_colors,
- indices->count(),
- SkiaBuffer::Cast(indices.get())->u16s());
- // clang-format on
-
- // The blend mode is ignored if we don't have colors && uvs
- m_Canvas->drawVertices(vt, SkBlendMode::kModulate, paint);
-}
-
-bool SkiaRenderImage::decode(Span<const uint8_t> encodedData) {
-
- sk_sp<SkData> data = SkData::MakeWithoutCopy(encodedData.data(), encodedData.size());
- m_SkImage = SkImage::MakeFromEncoded(data);
-
- // Our optimized skia buld seems to have broken lazy-image decode.
- // As a work-around for now, force the image to be decoded.
- if (m_SkImage) {
- m_SkImage = m_SkImage->makeRasterImage();
- }
-
- if (m_SkImage) {
- m_Width = m_SkImage->width();
- m_Height = m_SkImage->height();
- return true;
- }
- return false;
-}
-
-rcp<RenderShader>
-SkiaRenderImage::makeShader(RenderTileMode tx, RenderTileMode ty, const Mat2D* localMatrix) const {
- const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
- const SkSamplingOptions options(SkFilterMode::kLinear);
- auto sh = m_SkImage->makeShader(ToSkia::convert(tx), ToSkia::convert(ty), options, &lm);
- return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
-}
-
-namespace rive {
- rcp<RenderBuffer> makeBufferU16(Span<const uint16_t> data) { return make_buffer(data); }
- rcp<RenderBuffer> makeBufferU32(Span<const uint32_t> data) { return make_buffer(data); }
- rcp<RenderBuffer> makeBufferF32(Span<const float> data) { return make_buffer(data); }
-
- RenderPath*
- makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule fillrule) {
- return new SkiaRenderPath(SkPath::Make((const SkPoint*)points.data(),
- points.size(),
- verbs.data(),
- verbs.size(),
- nullptr,
- 0, // conics
- ToSkia::convert(fillrule),
- false));
- }
-
- RenderPath* makeRenderPath() { return new SkiaRenderPath(); }
- RenderPaint* makeRenderPaint() { return new SkiaRenderPaint(); }
- RenderImage* makeRenderImage() { return new SkiaRenderImage(); }
-
- rcp<RenderShader> makeLinearGradient(float sx,
- float sy,
- float ex,
- float ey,
- const ColorInt colors[],
- const float stops[],
- int count,
- RenderTileMode mode,
- const Mat2D* localm) {
- const SkPoint pts[] = {{sx, sy}, {ex, ey}};
- const SkMatrix lm = localm ? ToSkia::convert(*localm) : SkMatrix();
- auto sh = SkGradientShader::MakeLinear(
- pts, (const SkColor*)colors, stops, count, ToSkia::convert(mode), 0, &lm);
- return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
- }
-
- rcp<RenderShader> makeRadialGradient(float cx,
- float cy,
- float radius,
- const ColorInt colors[],
- const float stops[],
- int count,
- RenderTileMode mode,
- const Mat2D* localm) {
- const SkMatrix lm = localm ? ToSkia::convert(*localm) : SkMatrix();
- auto sh = SkGradientShader::MakeRadial(
- {cx, cy}, radius, (const SkColor*)colors, stops, count, ToSkia::convert(mode), 0, &lm);
- return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
- }
-
- rcp<RenderShader> makeSweepGradient(float cx,
- float cy,
- const ColorInt colors[],
- const float stops[],
- int count,
- RenderTileMode mode,
- const Mat2D* localm) {
- const SkMatrix lm = localm ? ToSkia::convert(*localm) : SkMatrix();
- auto sh = SkGradientShader::MakeSweep(cx, cy, (const SkColor*)colors, stops, count, 0, &lm);
- return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
- }
-} // namespace rive
diff --git a/skia/viewer/src/main.cpp b/skia/viewer/src/main.cpp
index eb2e6e2..0115a33 100644
--- a/skia/viewer/src/main.cpp
+++ b/skia/viewer/src/main.cpp
@@ -23,6 +23,7 @@
#include "rive/file.hpp"
#include "rive/layout.hpp"
#include "rive/math/aabb.hpp"
+#include "skia_factory.hpp"
#include "skia_renderer.hpp"
#include "imgui/backends/imgui_impl_glfw.h"
@@ -31,6 +32,8 @@
#include <cmath>
#include <stdio.h>
+rive::SkiaFactory skiaFactory;
+
std::string filename;
std::unique_ptr<rive::File> currentFile;
std::unique_ptr<rive::ArtboardInstance> artboardInstance;
@@ -68,7 +71,7 @@
stateMachineIndex = index;
animationIndex = -1;
assert(fileBytes.size() != 0);
- auto file = rive::File::import(rive::toSpan(fileBytes));
+ auto file = rive::File::import(rive::toSpan(fileBytes), &skiaFactory);
if (!file) {
fileBytes.clear();
fprintf(stderr, "failed to import file\n");
@@ -92,7 +95,7 @@
animationIndex = index;
stateMachineIndex = -1;
assert(fileBytes.size() != 0);
- auto file = rive::File::import(rive::toSpan(fileBytes));
+ auto file = rive::File::import(rive::toSpan(fileBytes), &skiaFactory);
if (!file) {
fileBytes.clear();
fprintf(stderr, "failed to import file\n");
diff --git a/src/artboard.cpp b/src/artboard.cpp
index 37a3745..91437b0 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -521,6 +521,7 @@
std::unique_ptr<ArtboardInstance> artboardClone(new ArtboardInstance);
artboardClone->copy(*this);
+ artboardClone->m_Factory = m_Factory;
artboardClone->m_FrameOrigin = m_FrameOrigin;
std::vector<Core*>& cloneObjects = artboardClone->m_Objects;
diff --git a/src/assets/image_asset.cpp b/src/assets/image_asset.cpp
index 6988c1b..7fe6304 100644
--- a/src/assets/image_asset.cpp
+++ b/src/assets/image_asset.cpp
@@ -1,16 +1,17 @@
#include "rive/assets/image_asset.hpp"
-#include "rive/renderer.hpp"
+#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
using namespace rive;
-ImageAsset::ImageAsset() : m_RenderImage(makeRenderImage()) {}
+ImageAsset::~ImageAsset() {}
-ImageAsset::~ImageAsset() { delete m_RenderImage; }
-bool ImageAsset::decode(const uint8_t* bytes, std::size_t size) {
+bool ImageAsset::decode(Span<const uint8_t> data, Factory* factory) {
#ifdef TESTING
- decodedByteSize = size;
+ decodedByteSize = data.size();
#endif
- return m_RenderImage->decode({bytes, size});
+ m_RenderImage = factory->decodeImage(data);
+ return m_RenderImage != nullptr;
}
std::string ImageAsset::fileExtension() { return "png"; }
diff --git a/src/file.cpp b/src/file.cpp
index 6a17dbb..b59eee0 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -108,12 +108,18 @@
return object;
}
-File::File(FileAssetResolver* assetResolver) : m_AssetResolver(assetResolver) {}
+File::File(Factory* factory, FileAssetResolver* assetResolver)
+ : m_Factory(factory)
+ , m_AssetResolver(assetResolver)
+{
+ assert(factory);
+}
File::~File() {}
std::unique_ptr<File>
-File::import(Span<const uint8_t> bytes, ImportResult* result, FileAssetResolver* assetResolver) {
+File::import(Span<const uint8_t> bytes, Factory* factory,
+ ImportResult* result, FileAssetResolver* assetResolver) {
BinaryReader reader(bytes);
RuntimeHeader header;
if (!RuntimeHeader::read(reader, header)) {
@@ -135,7 +141,7 @@
}
return nullptr;
}
- auto file = std::unique_ptr<File>(new File(assetResolver));
+ auto file = std::unique_ptr<File>(new File(factory, assetResolver));
auto readResult = file->read(reader, header);
if (readResult != ImportResult::success) {
file.reset(nullptr);
@@ -159,9 +165,11 @@
case Backboard::typeKey:
m_Backboard.reset(object->as<Backboard>());
break;
- case Artboard::typeKey:
- m_Artboards.push_back(std::unique_ptr<Artboard>(object->as<Artboard>()));
- break;
+ case Artboard::typeKey: {
+ Artboard* ab = object->as<Artboard>();
+ ab->m_Factory = m_Factory;
+ m_Artboards.push_back(std::unique_ptr<Artboard>(ab));
+ } break;
}
} else {
fprintf(stderr, "Failed to import object of type %d\n", object->coreType());
@@ -226,7 +234,7 @@
stackObject = new StateMachineEventImporter(object->as<StateMachineEvent>());
break;
case ImageAsset::typeKey:
- stackObject = new FileAssetImporter(object->as<FileAsset>(), m_AssetResolver);
+ stackObject = new FileAssetImporter(object->as<FileAsset>(), m_AssetResolver, m_Factory);
stackType = FileAsset::typeKey;
break;
}
diff --git a/src/importers/file_asset_importer.cpp b/src/importers/file_asset_importer.cpp
index 0357271..0d66c3c 100644
--- a/src/importers/file_asset_importer.cpp
+++ b/src/importers/file_asset_importer.cpp
@@ -7,12 +7,15 @@
using namespace rive;
-FileAssetImporter::FileAssetImporter(FileAsset* fileAsset, FileAssetResolver* assetResolver) :
- m_FileAsset(fileAsset), m_FileAssetResolver(assetResolver) {}
+FileAssetImporter::FileAssetImporter(FileAsset* fileAsset, FileAssetResolver* assetResolver, Factory* factory) :
+ m_FileAsset(fileAsset),
+ m_FileAssetResolver(assetResolver),
+ m_Factory(factory)
+{}
void FileAssetImporter::loadContents(const FileAssetContents& contents) {
auto data = contents.bytes();
- if (m_FileAsset->decode(data.begin(), data.size())) {
+ if (m_FileAsset->decode(data, m_Factory)) {
m_LoadedContents = true;
}
}
diff --git a/src/shapes/clipping_shape.cpp b/src/shapes/clipping_shape.cpp
index f9bbc7d..2889b4e 100644
--- a/src/shapes/clipping_shape.cpp
+++ b/src/shapes/clipping_shape.cpp
@@ -1,6 +1,7 @@
#include "rive/shapes/clipping_shape.hpp"
#include "rive/artboard.hpp"
#include "rive/core_context.hpp"
+#include "rive/factory.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/path_composer.hpp"
@@ -47,7 +48,7 @@
}
}
- m_RenderPath = rive::makeRenderPath();
+ m_RenderPath = artboard->factory()->makeEmptyRenderPath();
return StatusCode::Ok;
}
@@ -86,5 +87,3 @@
}
}
}
-
-ClippingShape::~ClippingShape() { delete m_RenderPath; }
\ No newline at end of file
diff --git a/src/shapes/mesh.cpp b/src/shapes/mesh.cpp
index 5f24336..fa8234f 100644
--- a/src/shapes/mesh.cpp
+++ b/src/shapes/mesh.cpp
@@ -3,6 +3,8 @@
#include "rive/shapes/vertex.hpp"
#include "rive/shapes/mesh_vertex.hpp"
#include "rive/bones/skin.hpp"
+#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
#include "rive/span.hpp"
#include <limits>
@@ -90,8 +92,10 @@
uv[index++] = vertex->u();
uv[index++] = vertex->v();
}
- m_UVRenderBuffer = makeBufferF32(toSpan(uv));
- m_IndexRenderBuffer = makeBufferU16(toSpan(*m_IndexBuffer));
+
+ auto factory = artboard()->factory();
+ m_UVRenderBuffer = factory->makeBufferF32(toSpan(uv));
+ m_IndexRenderBuffer = factory->makeBufferU16(toSpan(*m_IndexBuffer));
}
void Mesh::update(ComponentDirt value) {
@@ -114,7 +118,9 @@
vertices[index++] = translation[0];
vertices[index++] = translation[1];
}
- m_VertexRenderBuffer = makeBufferF32(toSpan(vertices));
+
+ auto factory = artboard()->factory();
+ m_VertexRenderBuffer = factory->makeBufferF32(toSpan(vertices));
}
if (skin() == nullptr) {
diff --git a/src/shapes/metrics_path.cpp b/src/shapes/metrics_path.cpp
index 6399d6c..3574eef 100644
--- a/src/shapes/metrics_path.cpp
+++ b/src/shapes/metrics_path.cpp
@@ -354,8 +354,9 @@
}
}
-RenderMetricsPath::RenderMetricsPath() : m_RenderPath(makeRenderPath()) {}
-RenderMetricsPath::~RenderMetricsPath() { delete m_RenderPath; }
+RenderMetricsPath::RenderMetricsPath(std::unique_ptr<RenderPath> path)
+ : m_RenderPath(std::move(path))
+{}
void RenderMetricsPath::addPath(CommandPath* path, const Mat2D& transform) {
MetricsPath::addPath(path, transform);
diff --git a/src/shapes/paint/fill.cpp b/src/shapes/paint/fill.cpp
index e39fb78..d451982 100644
--- a/src/shapes/paint/fill.cpp
+++ b/src/shapes/paint/fill.cpp
@@ -16,5 +16,5 @@
}
auto renderPath = path->renderPath();
renderPath->fillRule((FillRule)fillRule());
- renderer->drawPath(renderPath, m_RenderPaint);
+ renderer->drawPath(renderPath, renderPaint());
}
\ No newline at end of file
diff --git a/src/shapes/paint/linear_gradient.cpp b/src/shapes/paint/linear_gradient.cpp
index 0e5b978..24d0c6a 100644
--- a/src/shapes/paint/linear_gradient.cpp
+++ b/src/shapes/paint/linear_gradient.cpp
@@ -1,5 +1,7 @@
#include "rive/shapes/paint/linear_gradient.hpp"
#include "rive/math/vec2d.hpp"
+#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
#include "rive/node.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/paint/color.hpp"
@@ -92,8 +94,8 @@
void LinearGradient::makeGradient(
Vec2D start, Vec2D end, const ColorInt colors[], const float stops[], size_t count) {
- auto paint = renderPaint();
- paint->shader(makeLinearGradient(
+ auto factory = artboard()->factory();
+ renderPaint()->shader(factory->makeLinearGradient(
start[0], start[1], end[0], end[1], colors, stops, count, RenderTileMode::clamp));
}
diff --git a/src/shapes/paint/radial_gradient.cpp b/src/shapes/paint/radial_gradient.cpp
index d327d4e..6c6b481 100644
--- a/src/shapes/paint/radial_gradient.cpp
+++ b/src/shapes/paint/radial_gradient.cpp
@@ -1,16 +1,17 @@
#include "rive/shapes/paint/radial_gradient.hpp"
-#include "rive/renderer.hpp"
+#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
using namespace rive;
void RadialGradient::makeGradient(
Vec2D start, Vec2D end, const ColorInt colors[], const float stops[], size_t count) {
- auto paint = renderPaint();
- paint->shader(makeRadialGradient(start[0],
- start[1],
- Vec2D::distance(start, end),
- colors,
- stops,
- count,
- RenderTileMode::clamp));
+ auto factory = artboard()->factory();
+ renderPaint()->shader(factory->makeRadialGradient(start[0],
+ start[1],
+ Vec2D::distance(start, end),
+ colors,
+ stops,
+ count,
+ RenderTileMode::clamp));
}
diff --git a/src/shapes/paint/shape_paint.cpp b/src/shapes/paint/shape_paint.cpp
index 174d82a..b1d2890 100644
--- a/src/shapes/paint/shape_paint.cpp
+++ b/src/shapes/paint/shape_paint.cpp
@@ -1,12 +1,11 @@
#include "rive/shapes/paint/shape_paint.hpp"
#include "rive/shapes/shape_paint_container.hpp"
-#include "rive/renderer.hpp"
+#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
using namespace rive;
-ShapePaint::~ShapePaint() { delete m_RenderPaint; }
-
StatusCode ShapePaint::onAddedClean(CoreContext* context) {
auto container = ShapePaintContainer::from(parent());
if (container == nullptr) {
@@ -19,7 +18,10 @@
RenderPaint* ShapePaint::initRenderPaint(ShapePaintMutator* mutator) {
assert(m_RenderPaint == nullptr);
m_PaintMutator = mutator;
- return m_RenderPaint = makeRenderPaint();
+
+ auto factory = mutator->component()->artboard()->factory();
+ m_RenderPaint = factory->makeRenderPaint();
+ return m_RenderPaint.get();
}
void ShapePaint::blendMode(BlendMode value) {
diff --git a/src/shapes/paint/stroke.cpp b/src/shapes/paint/stroke.cpp
index ff48cf7..4588cc4 100644
--- a/src/shapes/paint/stroke.cpp
+++ b/src/shapes/paint/stroke.cpp
@@ -1,3 +1,4 @@
+#include "rive/artboard.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/shapes/paint/stroke_cap.hpp"
#include "rive/shapes/paint/stroke_effect.hpp"
@@ -27,10 +28,11 @@
if (m_Effect != nullptr) {
/// We're guaranteed to get a metrics path here if we have an effect.
- path = m_Effect->effectPath(reinterpret_cast<MetricsPath*>(path));
+ auto factory = artboard()->factory();
+ path = m_Effect->effectPath(reinterpret_cast<MetricsPath*>(path), factory);
}
- renderer->drawPath(path->renderPath(), m_RenderPaint);
+ renderer->drawPath(path->renderPath(), renderPaint());
}
void Stroke::thicknessChanged() {
diff --git a/src/shapes/paint/trim_path.cpp b/src/shapes/paint/trim_path.cpp
index 3d2e8d8..3087dde 100644
--- a/src/shapes/paint/trim_path.cpp
+++ b/src/shapes/paint/trim_path.cpp
@@ -1,12 +1,10 @@
#include "rive/shapes/paint/trim_path.hpp"
#include "rive/shapes/metrics_path.hpp"
#include "rive/shapes/paint/stroke.hpp"
+#include "rive/factory.hpp"
using namespace rive;
-TrimPath::TrimPath() : m_TrimmedPath(makeRenderPath()) {}
-TrimPath::~TrimPath() { delete m_TrimmedPath; }
-
StatusCode TrimPath::onAddedClean(CoreContext* context) {
if (!parent()->is<Stroke>()) {
return StatusCode::InvalidObject;
@@ -17,7 +15,7 @@
return StatusCode::Ok;
}
-RenderPath* TrimPath::effectPath(MetricsPath* source) {
+RenderPath* TrimPath::effectPath(MetricsPath* source, Factory* factory) {
if (m_RenderPath != nullptr) {
return m_RenderPath;
}
@@ -25,7 +23,12 @@
// Source is always a containing (shape) path.
const std::vector<MetricsPath*>& subPaths = source->paths();
- m_TrimmedPath->reset();
+ if (!m_TrimmedPath) {
+ m_TrimmedPath = factory->makeEmptyRenderPath();
+ } else {
+ m_TrimmedPath->reset();
+ }
+
auto renderOffset = std::fmod(std::fmod(offset(), 1.0f) + 1.0f, 1.0f);
switch (modeValue()) {
case 1: {
@@ -50,7 +53,7 @@
auto pathLength = path->length();
if (startLength < pathLength) {
- path->trim(startLength, endLength, true, m_TrimmedPath);
+ path->trim(startLength, endLength, true, m_TrimmedPath.get());
endLength -= pathLength;
startLength = 0;
} else {
@@ -76,17 +79,17 @@
startLength -= pathLength;
endLength -= pathLength;
}
- path->trim(startLength, endLength, true, m_TrimmedPath);
+ path->trim(startLength, endLength, true, m_TrimmedPath.get());
while (endLength > pathLength) {
startLength = 0;
endLength -= pathLength;
- path->trim(startLength, endLength, true, m_TrimmedPath);
+ path->trim(startLength, endLength, true, m_TrimmedPath.get());
}
}
} break;
}
- m_RenderPath = m_TrimmedPath;
+ m_RenderPath = m_TrimmedPath.get();
return m_RenderPath;
}
diff --git a/src/shapes/shape_paint_container.cpp b/src/shapes/shape_paint_container.cpp
index 044b40d..8dd83da 100644
--- a/src/shapes/shape_paint_container.cpp
+++ b/src/shapes/shape_paint_container.cpp
@@ -1,5 +1,6 @@
#include "rive/shapes/shape_paint_container.hpp"
#include "rive/artboard.hpp"
+#include "rive/factory.hpp"
#include "rive/component.hpp"
#include "rive/renderer.hpp"
#include "rive/shapes/metrics_path.hpp"
@@ -8,6 +9,7 @@
#include "rive/shapes/shape.hpp"
using namespace rive;
+
ShapePaintContainer* ShapePaintContainer::from(Component* component) {
switch (component->coreType()) {
case Artboard::typeKey:
@@ -58,11 +60,12 @@
}
}
+ auto factory = getArtboard()->factory();
if (needForEffects && needForRender) {
- return std::unique_ptr<CommandPath>(new RenderMetricsPath());
+ return std::unique_ptr<CommandPath>(new RenderMetricsPath(factory->makeEmptyRenderPath()));
} else if (needForEffects) {
return std::unique_ptr<CommandPath>(new OnlyMetricsPath());
} else {
- return std::unique_ptr<CommandPath>(rive::makeRenderPath());
+ return std::unique_ptr<CommandPath>(factory->makeEmptyRenderPath());
}
}
diff --git a/test/bound_bones_test.cpp b/test/bound_bones_test.cpp
index 4a92b48..d34b330 100644
--- a/test/bound_bones_test.cpp
+++ b/test/bound_bones_test.cpp
@@ -7,7 +7,7 @@
#include <rive/shapes/points_path.hpp>
#include <rive/shapes/rectangle.hpp>
#include <rive/shapes/shape.hpp>
-#include "no_op_renderer.hpp"
+#include "no_op_factory.hpp"
#include "rive_file_reader.hpp"
#include <catch.hpp>
#include <cstdio>
diff --git a/test/image_asset_test.cpp b/test/image_asset_test.cpp
index a681d9d..e65d25f 100644
--- a/test/image_asset_test.cpp
+++ b/test/image_asset_test.cpp
@@ -5,6 +5,7 @@
#include <rive/shapes/image.hpp>
#include <rive/assets/image_asset.hpp>
#include <rive/relative_local_asset_resolver.hpp>
+#include "no_op_factory.hpp"
#include "no_op_renderer.hpp"
#include "rive_file_reader.hpp"
#include <catch.hpp>
@@ -41,10 +42,12 @@
}
TEST_CASE("out of band image assets loads correctly", "[assets]") {
+ rive::NoOpFactory gEmptyFactory;
+
std::string filename = "../../test/assets/out_of_band/walle.riv";
- rive::RelativeLocalAssetResolver resolver(filename);
+ rive::RelativeLocalAssetResolver resolver(filename, &gEmptyFactory);
- auto file = ReadRiveFile(filename.c_str(), &resolver);
+ auto file = ReadRiveFile(filename.c_str(), &gEmptyFactory, &resolver);
auto node = file->artboard()->find("walle");
REQUIRE(node != nullptr);
diff --git a/test/instancing_test.cpp b/test/instancing_test.cpp
index 85d2e4f..93fe204 100644
--- a/test/instancing_test.cpp
+++ b/test/instancing_test.cpp
@@ -3,6 +3,7 @@
#include <rive/shapes/clipping_shape.hpp>
#include <rive/shapes/rectangle.hpp>
#include <rive/shapes/shape.hpp>
+#include "no_op_factory.hpp"
#include "no_op_renderer.hpp"
#include "rive_file_reader.hpp"
#include <catch.hpp>
diff --git a/test/linear_animation_instance_test.cpp b/test/linear_animation_instance_test.cpp
index f8a5b77..469b4ae 100644
--- a/test/linear_animation_instance_test.cpp
+++ b/test/linear_animation_instance_test.cpp
@@ -1,13 +1,15 @@
#include <rive/animation/loop.hpp>
#include <rive/animation/linear_animation.hpp>
#include <rive/animation/linear_animation_instance.hpp>
+#include "no_op_factory.hpp"
#include <catch.hpp>
#include <cstdio>
TEST_CASE("LinearAnimationInstance oneShot", "[animation]") {
+ rive::NoOpFactory emptyFactory;
// For each of these tests, we cons up a dummy artboard/instance
// just to make the animations happy.
- rive::Artboard ab;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -38,7 +40,8 @@
}
TEST_CASE("LinearAnimationInstance oneShot <-", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -85,7 +88,8 @@
}
TEST_CASE("LinearAnimationInstance loop ->", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -116,7 +120,8 @@
}
TEST_CASE("LinearAnimationInstance loop <-", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -157,7 +162,8 @@
}
TEST_CASE("LinearAnimationInstance loop <- work area", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -211,7 +217,8 @@
}
TEST_CASE("LinearAnimationInstance pingpong ->", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -243,7 +250,8 @@
}
TEST_CASE("LinearAnimationInstance pingpong <-", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
@@ -287,7 +295,8 @@
}
TEST_CASE("LinearAnimationInstance override loop", "[animation]") {
- rive::Artboard ab;
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard ab(&emptyFactory);
auto abi = ab.instance();
rive::LinearAnimation* linearAnimation = new rive::LinearAnimation();
diff --git a/test/no_op_factory.cpp b/test/no_op_factory.cpp
new file mode 100644
index 0000000..2f088f2
--- /dev/null
+++ b/test/no_op_factory.cpp
@@ -0,0 +1,43 @@
+#include "no_op_factory.hpp"
+#include "no_op_renderer.hpp"
+
+using namespace rive;
+
+NoOpFactory gNoOpFactory;
+
+rcp<RenderBuffer> NoOpFactory::makeBufferU16(Span<const uint16_t>) { return nullptr; }
+rcp<RenderBuffer> NoOpFactory::makeBufferU32(Span<const uint32_t>) { return nullptr; }
+rcp<RenderBuffer> NoOpFactory::makeBufferF32(Span<const float>) { return nullptr; }
+
+rcp<RenderShader> NoOpFactory::makeLinearGradient(float sx, float sy,
+ float ex, float ey,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix) { return nullptr; }
+
+rcp<RenderShader> NoOpFactory::makeRadialGradient(float cx, float cy, float radius,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix) { return nullptr; }
+
+std::unique_ptr<RenderPath> NoOpFactory::makeRenderPath(Span<const Vec2D> points,
+ Span<const uint8_t> verbs,
+ FillRule) {
+ return std::make_unique<NoOpRenderPath>();
+}
+
+std::unique_ptr<RenderPath> NoOpFactory::makeEmptyRenderPath() {
+ return std::make_unique<NoOpRenderPath>();
+}
+
+std::unique_ptr<RenderPaint> NoOpFactory::makeRenderPaint() {
+ return std::make_unique<NoOpRenderPaint>();
+}
+
+std::unique_ptr<RenderImage> NoOpFactory::decodeImage(Span<const uint8_t>) {
+ return std::make_unique<NoOpRenderImage>();
+}
diff --git a/test/no_op_factory.hpp b/test/no_op_factory.hpp
new file mode 100644
index 0000000..59095be
--- /dev/null
+++ b/test/no_op_factory.hpp
@@ -0,0 +1,43 @@
+#ifndef _RIVE_NOOP_FACTORY_HPP_
+#define _RIVE_NOOP_FACTORY_HPP_
+
+#include <rive/renderer.hpp>
+#include <rive/factory.hpp>
+
+namespace rive {
+
+ class NoOpFactory : public Factory {
+ rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
+ rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
+ rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
+
+ rcp<RenderShader> makeLinearGradient(float sx, float sy,
+ float ex, float ey,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) override;
+
+ rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
+ const ColorInt colors[], // [count]
+ const float stops[], // [count]
+ int count,
+ RenderTileMode,
+ const Mat2D* localMatrix = nullptr) override;
+
+ std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
+ Span<const uint8_t> verbs,
+ FillRule) override;
+
+ std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
+
+ std::unique_ptr<RenderPaint> makeRenderPaint() override;
+
+ std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override;
+ };
+
+ static NoOpFactory gNoOpFactory;
+
+} // namespace rive
+#endif
diff --git a/test/no_op_renderer.cpp b/test/no_op_renderer.cpp
deleted file mode 100644
index b6ec756..0000000
--- a/test/no_op_renderer.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "no_op_renderer.hpp"
-#include <rive/renderer.hpp>
-
-namespace rive {
- RenderPaint* makeRenderPaint() { return new NoOpRenderPaint(); }
- RenderPath* makeRenderPath() { return new NoOpRenderPath(); }
- RenderImage* makeRenderImage() { return new NoOpRenderImage(); }
-
- rcp<RenderShader> makeLinearGradient(float sx,
- float sy,
- float ex,
- float ey,
- const ColorInt colors[],
- const float stops[],
- int count,
- RenderTileMode,
- const Mat2D* localMatrix) {
- return nullptr;
- }
-
- rcp<RenderShader> makeRadialGradient(float cx,
- float cy,
- float radius,
- const ColorInt colors[],
- const float stops[],
- int count,
- RenderTileMode,
- const Mat2D* localMatrix) {
- return nullptr;
- }
-
- rcp<RenderShader> makeSweepGradient(float cx,
- float cy,
- const ColorInt colors[],
- const float stops[],
- int count,
- const Mat2D* localMatrix) {
- return nullptr;
- }
-
- rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) { return nullptr; }
- rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) { return nullptr; }
- rcp<RenderBuffer> makeBufferF32(Span<const float>) { return nullptr; }
-} // namespace rive
diff --git a/test/no_op_renderer.hpp b/test/no_op_renderer.hpp
index 9237c4c..b5e9bb5 100644
--- a/test/no_op_renderer.hpp
+++ b/test/no_op_renderer.hpp
@@ -1,12 +1,13 @@
#ifndef _RIVE_NOOP_RENDERER_HPP_
#define _RIVE_NOOP_RENDERER_HPP_
+
#include <rive/renderer.hpp>
+#include <rive/factory.hpp>
#include <vector>
namespace rive {
class NoOpRenderImage : public RenderImage {
public:
- bool decode(Span<const uint8_t>) override { return true; }
rcp<RenderShader> makeShader(RenderTileMode, RenderTileMode, const Mat2D*) const override {
return nullptr;
}
diff --git a/test/path_test.cpp b/test/path_test.cpp
index 15f9218..fb0e5fb 100644
--- a/test/path_test.cpp
+++ b/test/path_test.cpp
@@ -6,12 +6,14 @@
#include <rive/shapes/path_composer.hpp>
#include <rive/shapes/rectangle.hpp>
#include <rive/shapes/shape.hpp>
+#include "no_op_factory.hpp"
#include "no_op_renderer.hpp"
#include <catch.hpp>
#include <cstdio>
TEST_CASE("rectangle path builds expected commands", "[path]") {
- rive::Artboard* artboard = new rive::Artboard();
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard artboard(&emptyFactory);
rive::Shape* shape = new rive::Shape();
rive::Rectangle* rectangle = new rive::Rectangle();
@@ -21,14 +23,14 @@
rectangle->height(200.0f);
rectangle->cornerRadiusTL(0.0f);
- artboard->addObject(artboard);
- artboard->addObject(shape);
- artboard->addObject(rectangle);
+ artboard.addObject(&artboard);
+ artboard.addObject(shape);
+ artboard.addObject(rectangle);
rectangle->parentId(1);
- REQUIRE(artboard->initialize() == rive::StatusCode::Ok);
+ REQUIRE(artboard.initialize() == rive::StatusCode::Ok);
- artboard->advance(0.0f);
+ artboard.advance(0.0f);
REQUIRE(rectangle->commandPath() != nullptr);
@@ -42,12 +44,11 @@
REQUIRE(path->commands[4].command == rive::NoOpPathCommandType::LineTo);
REQUIRE(path->commands[5].command == rive::NoOpPathCommandType::LineTo);
REQUIRE(path->commands[6].command == rive::NoOpPathCommandType::Close);
-
- delete artboard;
}
TEST_CASE("rounded rectangle path builds expected commands", "[path]") {
- rive::Artboard* artboard = new rive::Artboard();
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard artboard(&emptyFactory);
rive::Shape* shape = new rive::Shape();
rive::Rectangle* rectangle = new rive::Rectangle();
@@ -58,14 +59,14 @@
rectangle->cornerRadiusTL(20.0f);
rectangle->linkCornerRadius(true);
- artboard->addObject(artboard);
- artboard->addObject(shape);
- artboard->addObject(rectangle);
+ artboard.addObject(&artboard);
+ artboard.addObject(shape);
+ artboard.addObject(rectangle);
rectangle->parentId(1);
- artboard->initialize();
+ artboard.initialize();
- artboard->advance(0.0f);
+ artboard.advance(0.0f);
REQUIRE(rectangle->commandPath() != nullptr);
@@ -105,12 +106,11 @@
REQUIRE(path->commands[9].command == rive::NoOpPathCommandType::LineTo);
REQUIRE(path->commands[10].command == rive::NoOpPathCommandType::Close);
-
- delete artboard;
}
TEST_CASE("ellipse path builds expected commands", "[path]") {
- rive::Artboard* artboard = new rive::Artboard();
+ rive::NoOpFactory emptyFactory;
+ rive::Artboard artboard(&emptyFactory);
rive::Ellipse* ellipse = new rive::Ellipse();
rive::Shape* shape = new rive::Shape();
@@ -119,14 +119,14 @@
ellipse->width(100.0f);
ellipse->height(200.0f);
- artboard->addObject(artboard);
- artboard->addObject(shape);
- artboard->addObject(ellipse);
+ artboard.addObject(&artboard);
+ artboard.addObject(shape);
+ artboard.addObject(ellipse);
ellipse->parentId(1);
- artboard->initialize();
+ artboard.initialize();
- artboard->advance(0.0f);
+ artboard.advance(0.0f);
REQUIRE(ellipse->commandPath() != nullptr);
@@ -187,6 +187,4 @@
REQUIRE(path->commands[5].y == -100.0f);
REQUIRE(path->commands[6].command == rive::NoOpPathCommandType::Close);
-
- delete artboard;
}
\ No newline at end of file
diff --git a/test/rive_file_reader.hpp b/test/rive_file_reader.hpp
index cec7a41..4294290 100644
--- a/test/rive_file_reader.hpp
+++ b/test/rive_file_reader.hpp
@@ -3,9 +3,16 @@
#include <rive/file.hpp>
#include "rive_testing.hpp"
+#include "no_op_factory.hpp"
static inline std::unique_ptr<rive::File>
-ReadRiveFile(const char path[], rive::FileAssetResolver* resolver = nullptr) {
+ReadRiveFile(const char path[],
+ rive::Factory* factory = nullptr,
+ rive::FileAssetResolver* resolver = nullptr) {
+ if (!factory) {
+ factory = &rive::gNoOpFactory;
+ }
+
FILE* fp = fopen(path, "rb");
REQUIRE(fp != nullptr);
@@ -17,7 +24,7 @@
fclose(fp);
rive::ImportResult result;
- auto file = rive::File::import(rive::toSpan(bytes), &result, resolver);
+ auto file = rive::File::import(rive::toSpan(bytes), factory, &result, resolver);
REQUIRE(result == rive::ImportResult::success);
REQUIRE(file.get() != nullptr);
REQUIRE(file->artboard() != nullptr);