Clean up recent gradients add, impl image shader
diff --git a/include/rive/renderer.hpp b/include/rive/renderer.hpp
index 18fbe99..bcbdaff 100644
--- a/include/rive/renderer.hpp
+++ b/include/rive/renderer.hpp
@@ -81,10 +81,8 @@
         int width() const { return m_Width; }
         int height() const { return m_Height; }
         
-        rcp<RenderShader> makeShader(RenderTileMode tx, RenderTileMode ty,
-                                     const Mat2D* localMatrix = nullptr) const {
-            return nullptr; // defaults to no shader
-        }
+        virtual rcp<RenderShader> makeShader(RenderTileMode tx, RenderTileMode ty,
+                                             const Mat2D* localMatrix = nullptr) const = 0;
     };
 
     class RenderPath : public CommandPath {
diff --git a/skia/renderer/include/skia_renderer.hpp b/skia/renderer/include/skia_renderer.hpp
index 1b47a87..d67333d 100644
--- a/skia/renderer/include/skia_renderer.hpp
+++ b/skia/renderer/include/skia_renderer.hpp
@@ -48,6 +48,8 @@
     public:
         sk_sp<SkImage> skImage() const { return m_SkImage; };
         bool decode(const uint8_t* bytes, std::size_t size) override;
+        rcp<RenderShader> makeShader(RenderTileMode tx, RenderTileMode ty,
+                                     const Mat2D* localMatrix) const override;
     };
 
     class SkiaRenderer : public Renderer {
diff --git a/skia/renderer/include/to_skia.hpp b/skia/renderer/include/to_skia.hpp
index 5eccd26..6420106 100644
--- a/skia/renderer/include/to_skia.hpp
+++ b/skia/renderer/include/to_skia.hpp
@@ -12,28 +12,26 @@
     class ToSkia {
     public:
         static SkMatrix convert(const rive::Mat2D& m) {
-            SkMatrix skMatrix;
-            skMatrix.set9((SkScalar[9])
-                          // Skia Matrix is row major
-                          {// Row 1
-                           m[0],
-                           m[2],
-                           m[4],
-                           // Row 2
-                           m[1],
-                           m[3],
-                           m[5],
-                           // Row 3
-                           0.0,
-                           0.0,
-                           1.0});
-            return skMatrix;
+            return SkMatrix::MakeAll(m[0], m[2], m[4],
+                                     m[1], m[3], m[5],
+                                     0,    0,    1);
         }
 
         static SkPoint convert(const rive::Vec2D& point) {
             return SkPoint::Make(point[0], point[1]);
         }
 
+        static SkTileMode convert(RenderTileMode rtm) {
+            switch (rtm) {
+                case RenderTileMode::clamp:  return SkTileMode::kClamp;
+                case RenderTileMode::repeat: return SkTileMode::kRepeat;
+                case RenderTileMode::mirror: return SkTileMode::kMirror;
+                case RenderTileMode::decal:  return SkTileMode::kDecal;
+            }
+            assert(false);
+            return SkTileMode::kClamp;
+        }
+
         static SkPaint::Cap convert(rive::StrokeCap cap) {
             switch (cap) {
                 case rive::StrokeCap::butt:
@@ -97,4 +95,4 @@
         }
     };
 } // namespace rive
-#endif
\ No newline at end of file
+#endif
diff --git a/skia/renderer/src/skia_renderer.cpp b/skia/renderer/src/skia_renderer.cpp
index de3c55b..14fc57f 100644
--- a/skia/renderer/src/skia_renderer.cpp
+++ b/skia/renderer/src/skia_renderer.cpp
@@ -7,23 +7,6 @@
 
 using namespace rive;
 
-static SkTileMode to_skia(RenderTileMode rtm) {
-    switch (rtm) {
-        case RenderTileMode::clamp:  return SkTileMode::kClamp;
-        case RenderTileMode::repeat: return SkTileMode::kRepeat;
-        case RenderTileMode::mirror: return SkTileMode::kMirror;
-        case RenderTileMode::decal:  return SkTileMode::kDecal;
-    }
-    assert(false);
-    return SkTileMode::kClamp;
-}
-
-static SkMatrix to_skia(const Mat2D& m) {
-    return SkMatrix::MakeAll(m[0], m[2], m[4],
-                             m[1], m[3], m[5],
-                             0,    0,    1);
-}
-
 class SkiaRenderShader : public RenderShader {
 public:
     SkiaRenderShader(sk_sp<SkShader> sh) : shader(std::move(sh)) {}
@@ -122,6 +105,14 @@
     return true;
 }
 
+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 {
     RenderPath* makeRenderPath() { return new SkiaRenderPath(); }
     RenderPaint* makeRenderPaint() { return new SkiaRenderPaint(); }
@@ -133,9 +124,9 @@
                                          const Mat2D* localm)
     {
         const SkPoint pts[] = { {sx, sy}, {ex, ey} };
-        const SkMatrix lm = localm ? to_skia(*localm) : SkMatrix();
+        const SkMatrix lm = localm ? ToSkia::convert(*localm) : SkMatrix();
         auto sh = SkGradientShader::MakeLinear(pts, (const SkColor*)colors, stops, count,
-                                               to_skia(mode), 0, &lm);
+                                               ToSkia::convert(mode), 0, &lm);
         return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
     }
 
@@ -144,10 +135,10 @@
                                          int count, RenderTileMode mode,
                                          const Mat2D* localm)
     {
-        const SkMatrix lm = localm ? to_skia(*localm) : SkMatrix();
+        const SkMatrix lm = localm ? ToSkia::convert(*localm) : SkMatrix();
         auto sh = SkGradientShader::MakeRadial({cx, cy}, radius,
                                                (const SkColor*)colors, stops, count,
-                                               to_skia(mode), 0, &lm);
+                                               ToSkia::convert(mode), 0, &lm);
         return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
     }
 
@@ -156,7 +147,7 @@
                                         int count, RenderTileMode mode,
                                         const Mat2D* localm)
    {
-       const SkMatrix lm = localm ? to_skia(*localm) : SkMatrix();
+       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)));