Inline trivial Vec2D methods (for readability and efficiency)
diff --git a/include/rive/math/vec2d.hpp b/include/rive/math/vec2d.hpp
index f90f465..1289f26 100644
--- a/include/rive/math/vec2d.hpp
+++ b/include/rive/math/vec2d.hpp
@@ -10,49 +10,65 @@
         float m_Buffer[2];
 
     public:
-        Vec2D();
-        Vec2D(const Vec2D& copy);
-        Vec2D(float x, float y);
+        Vec2D() : m_Buffer{0.0f, 0.0f} {}
+        Vec2D(const Vec2D& copy) : m_Buffer{copy.m_Buffer[0], copy.m_Buffer[1]} {}
+        Vec2D(float x, float y) : m_Buffer{x, y} {}
 
+        float x() const { return m_Buffer[0]; }
+        float y() const { return m_Buffer[1]; }
         inline const float* values() const { return m_Buffer; }
 
         float& operator[](std::size_t idx) { return m_Buffer[idx]; }
         const float& operator[](std::size_t idx) const { return m_Buffer[idx]; }
 
-        static void transform(Vec2D& result, const Vec2D& a, const Mat2D& m);
-        static void transformDir(Vec2D& result, const Vec2D& a, const Mat2D& m);
-        static void subtract(Vec2D& result, const Vec2D& a, const Vec2D& b);
-        static void add(Vec2D& result, const Vec2D& a, const Vec2D& b);
-        static float length(const Vec2D& a);
-        static float lengthSquared(const Vec2D& a);
+        float lengthSquared() const {
+            return x() * x() + y() * y();
+        }
+        float length() const;
+        Vec2D normalized() const;
+
+        Vec2D operator-() const { return { -x(), -y() }; }
+
+        void operator*=(float s) {
+            m_Buffer[0] *= s;
+            m_Buffer[1] *= s;
+        }
+    
+        static Vec2D transform(const Vec2D& a, const Mat2D& m);
+        static Vec2D transformDir(const Vec2D& a, const Mat2D& m);
         static float distance(const Vec2D& a, const Vec2D& b);
         static float distanceSquared(const Vec2D& a, const Vec2D& b);
         static void copy(Vec2D& result, const Vec2D& a);
-        static void normalize(Vec2D& result, const Vec2D& a);
         static float dot(const Vec2D& a, const Vec2D& b);
-        static void lerp(Vec2D& o, const Vec2D& a, const Vec2D& b, float f);
-        static void scale(Vec2D& o, const Vec2D& a, float scale);
-        static void
-        scaleAndAdd(Vec2D& o, const Vec2D& a, const Vec2D& b, float scale);
-        static void negate(Vec2D& o, const Vec2D& a);
+        static Vec2D lerp(const Vec2D& a, const Vec2D& b, float f);
+        static Vec2D scaleAndAdd(Vec2D a, Vec2D b, float scale) {
+            return {
+                a[0] + b[0] * scale,
+                a[1] + b[1] * scale,
+            };
+        }
     };
 
+    inline Vec2D operator*(const Vec2D& v, float s) {
+        return { v[0] * s, v[1] * s };
+    }
+    inline Vec2D operator*(float s, const Vec2D& v) {
+        return { v[0] * s, v[1] * s };
+    }
+    inline Vec2D operator/(const Vec2D& v, float s) {
+        return { v[0] / s, v[1] / s };
+    }
+
     inline Vec2D operator*(const Mat2D& a, const Vec2D& b) {
-        Vec2D result;
-        Vec2D::transform(result, b, a);
-        return result;
+        return Vec2D::transform(b, a);
     }
 
     inline Vec2D operator-(const Vec2D& a, const Vec2D& b) {
-        Vec2D result;
-        Vec2D::subtract(result, a, b);
-        return result;
+        return {a[0] - b[0], a[1] - b[1]};
     }
 
     inline Vec2D operator+(const Vec2D& a, const Vec2D& b) {
-        Vec2D result;
-        Vec2D::add(result, a, b);
-        return result;
+        return {a[0] + b[0], a[1] + b[1]};
     }
 
     inline bool operator==(const Vec2D& a, const Vec2D& b) {
@@ -62,4 +78,4 @@
         return a[0] != b[0] || a[1] != b[1];
     }
 } // namespace rive
-#endif
\ No newline at end of file
+#endif
diff --git a/src/bones/bone.cpp b/src/bones/bone.cpp
index 217738c..2759e84 100644
--- a/src/bones/bone.cpp
+++ b/src/bones/bone.cpp
@@ -26,9 +26,7 @@
 float Bone::y() const { return 0.0f; }
 
 void Bone::tipWorldTranslation(Vec2D& result) {
-    result[0] = length();
-    result[1] = 0.0f;
-    Vec2D::transform(result, result, worldTransform());
+    result = Vec2D::transform({length(), 0}, worldTransform());
 }
 
 void Bone::addPeerConstraint(Constraint* peer) {
@@ -36,4 +34,4 @@
                      m_PeerConstraints.end(),
                      peer) == m_PeerConstraints.end());
     m_PeerConstraints.push_back(peer);
-}
\ No newline at end of file
+}
diff --git a/src/constraints/distance_constraint.cpp b/src/constraints/distance_constraint.cpp
index 186a523..0df5022 100644
--- a/src/constraints/distance_constraint.cpp
+++ b/src/constraints/distance_constraint.cpp
@@ -18,9 +18,8 @@
     Vec2D ourTranslation;
     component->worldTranslation(ourTranslation);
 
-    Vec2D toTarget;
-    Vec2D::subtract(toTarget, ourTranslation, targetTranslation);
-    float currentDistance = Vec2D::length(toTarget);
+    Vec2D toTarget = ourTranslation - targetTranslation;
+    float currentDistance = toTarget.length();
     switch (static_cast<Mode>(modeValue())) {
         case Mode::Closer:
             if (currentDistance < distance()) {
@@ -39,13 +38,11 @@
         return;
     }
 
-    Vec2D::scale(toTarget, toTarget, 1.0f / currentDistance);
-    Vec2D::scale(toTarget, toTarget, distance());
+    toTarget *= (distance() / currentDistance);
 
     Mat2D& world = component->mutableWorldTransform();
-    Vec2D position;
-    Vec2D::add(position, targetTranslation, toTarget);
-    Vec2D::lerp(position, ourTranslation, position, strength());
+    Vec2D position = targetTranslation + toTarget;
+    position = Vec2D::lerp(ourTranslation, position, strength());
     world[4] = position[0];
     world[5] = position[1];
-}
\ No newline at end of file
+}
diff --git a/src/constraints/ik_constraint.cpp b/src/constraints/ik_constraint.cpp
index be80b26..964110e 100644
--- a/src/constraints/ik_constraint.cpp
+++ b/src/constraints/ik_constraint.cpp
@@ -79,12 +79,10 @@
     Vec2D pBT(worldTargetTranslation);
 
     // To target in worldspace
-    Vec2D toTarget;
-    Vec2D::subtract(toTarget, pBT, pA);
+    const Vec2D toTarget = pBT - pA;
 
     // Note this is directional, hence not transformMat2d
-    Vec2D toTargetLocal;
-    Vec2D::transformDir(toTargetLocal, toTarget, iworld);
+    Vec2D toTargetLocal = Vec2D::transformDir(toTarget, iworld);
     float r = std::atan2(toTargetLocal[1], toTargetLocal[0]);
 
     constrainRotation(*fk1, r);
@@ -106,21 +104,18 @@
     b2->tipWorldTranslation(pB);
     Vec2D pBT(worldTargetTranslation);
 
-    Vec2D::transform(pA, pA, iworld);
-    Vec2D::transform(pC, pC, iworld);
-    Vec2D::transform(pB, pB, iworld);
-    Vec2D::transform(pBT, pBT, iworld);
+    pA  = Vec2D::transform(pA, iworld);
+    pC  = Vec2D::transform(pC, iworld);
+    pB  = Vec2D::transform(pB, iworld);
+    pBT = Vec2D::transform(pBT, iworld);
 
     // http://mathworld.wolfram.com/LawofCosines.html
-    Vec2D av, bv, cv;
-    Vec2D::subtract(av, pB, pC);
-    float a = Vec2D::length(av);
-
-    Vec2D::subtract(bv, pC, pA);
-    float b = Vec2D::length(bv);
-
-    Vec2D::subtract(cv, pBT, pA);
-    float c = Vec2D::length(cv);
+    Vec2D av = pB  - pC,
+          bv = pC  - pA,
+          cv = pBT - pA;
+    float a = av.length(),
+          b = bv.length(),
+          c = cv.length();
 
     float A = std::acos(std::max(
         -1.0f, std::min(1.0f, (-a * a + b * b + c * c) / (2.0f * b * c))));
@@ -136,10 +131,7 @@
         firstChild->bone->worldTranslation(pC);
         b2->tipWorldTranslation(pB);
 
-        Vec2D avec;
-        Vec2D::subtract(avec, pB, pC);
-        Vec2D avLocal;
-        Vec2D::transformDir(avLocal, avec, secondChildWorldInverse);
+        Vec2D avLocal = Vec2D::transformDir(pB - pC, secondChildWorldInverse);
         float angleCorrection = -std::atan2(avLocal[1], avLocal[0]);
 
         if (invertDirection()) {
diff --git a/src/constraints/translation_constraint.cpp b/src/constraints/translation_constraint.cpp
index db2db8a..de5d976 100644
--- a/src/constraints/translation_constraint.cpp
+++ b/src/constraints/translation_constraint.cpp
@@ -49,8 +49,7 @@
 
         if (destSpace() == TransformSpace::local) {
             // Destination space is in parent transform coordinates.
-            Vec2D::transform(
-                translationB, translationB, getParentWorld(*component));
+            translationB = Vec2D::transform(translationB, getParentWorld(*component));
         }
     }
 
@@ -63,7 +62,7 @@
             return;
         }
         // Get our target world coordinates in parent local.
-        Vec2D::transform(translationB, translationB, invert);
+        translationB = Vec2D::transform(translationB, invert);
     }
     if (max() && translationB[0] > maxValue()) {
         translationB[0] = maxValue();
@@ -79,8 +78,7 @@
     }
     if (clampLocal) {
         // Transform back to world.
-        Vec2D::transform(
-            translationB, translationB, getParentWorld(*component));
+        translationB = Vec2D::transform(translationB, getParentWorld(*component));
     }
 
     float t = strength();
diff --git a/src/math/aabb.cpp b/src/math/aabb.cpp
index ce363a2..be7bc31 100644
--- a/src/math/aabb.cpp
+++ b/src/math/aabb.cpp
@@ -76,15 +76,10 @@
 }
 
 void AABB::transform(AABB& out, const AABB& a, const Mat2D& matrix) {
-    Vec2D p1(a[0], a[1]);
-    Vec2D p2(a[2], a[1]);
-    Vec2D p3(a[2], a[3]);
-    Vec2D p4(a[0], a[3]);
-
-    Vec2D::transform(p1, p1, matrix);
-    Vec2D::transform(p2, p2, matrix);
-    Vec2D::transform(p3, p3, matrix);
-    Vec2D::transform(p4, p4, matrix);
+    const auto p1 = Vec2D::transform({a[0], a[1]}, matrix);
+    const auto p2 = Vec2D::transform({a[2], a[1]}, matrix);
+    const auto p3 = Vec2D::transform({a[2], a[3]}, matrix);
+    const auto p4 = Vec2D::transform({a[0], a[3]}, matrix);
 
     out[0] = std::fmin(p1[0], std::fmin(p2[0], std::fmin(p3[0], p4[0])));
     out[1] = std::fmin(p1[1], std::fmin(p2[1], std::fmin(p3[1], p4[1])));
diff --git a/src/math/vec2d.cpp b/src/math/vec2d.cpp
index f74eff8..f0b8ebb 100644
--- a/src/math/vec2d.cpp
+++ b/src/math/vec2d.cpp
@@ -4,43 +4,18 @@
 
 using namespace rive;
 
-Vec2D::Vec2D() : m_Buffer{0.0f, 0.0f} {}
-
-Vec2D::Vec2D(float x, float y) : m_Buffer{x, y} {}
-
-Vec2D::Vec2D(const Vec2D& copy) :
-    m_Buffer{copy.m_Buffer[0], copy.m_Buffer[1]} {}
-
-void Vec2D::transform(Vec2D& result, const Vec2D& a, const Mat2D& m) {
-    float x = a[0];
-    float y = a[1];
-    result[0] = m[0] * x + m[2] * y + m[4];
-    result[1] = m[1] * x + m[3] * y + m[5];
+Vec2D Vec2D::transform(const Vec2D& a, const Mat2D& m) {
+    return {
+        m[0] * a.x() + m[2] * a.y() + m[4],
+        m[1] * a.x() + m[3] * a.y() + m[5],
+    };
 }
 
-void Vec2D::transformDir(Vec2D& result, const Vec2D& a, const Mat2D& m) {
-    float x = a[0];
-    float y = a[1];
-    result[0] = m[0] * x + m[2] * y;
-    result[1] = m[1] * x + m[3] * y;
-}
-
-void Vec2D::add(Vec2D& result, const Vec2D& a, const Vec2D& b) {
-    result[0] = a[0] + b[0];
-    result[1] = a[1] + b[1];
-}
-
-void Vec2D::subtract(Vec2D& result, const Vec2D& a, const Vec2D& b) {
-    result[0] = a[0] - b[0];
-    result[1] = a[1] - b[1];
-}
-
-float Vec2D::length(const Vec2D& a) { return std::sqrt(lengthSquared(a)); }
-
-float Vec2D::lengthSquared(const Vec2D& a) {
-    float x = a[0];
-    float y = a[1];
-    return x * x + y * y;
+Vec2D Vec2D::transformDir(const Vec2D& a, const Mat2D& m) {
+    return {
+        m[0] * a.x() + m[2] * a.y(),
+        m[1] * a.x() + m[3] * a.y(),
+    };
 }
 
 float Vec2D::distance(const Vec2D& a, const Vec2D& b) {
@@ -58,39 +33,23 @@
     result[1] = a[1];
 }
 
-void Vec2D::normalize(Vec2D& result, const Vec2D& a) {
-    float x = a[0];
-    float y = a[1];
-    float len = x * x + y * y;
-    if (len > 0.0f) {
-        len = 1.0f / std::sqrt(len);
-        result[0] = a[0] * len;
-        result[1] = a[1] * len;
-    }
+float Vec2D::length() const {
+    return std::sqrt(lengthSquared());
+}
+
+Vec2D Vec2D::normalized() const {
+    auto len2 = lengthSquared();
+    auto scale = len2 > 0 ? (1 / std::sqrt(len2)) : 1;
+    return *this * scale;
 }
 
 float Vec2D::dot(const Vec2D& a, const Vec2D& b) {
     return a[0] * b[0] + a[1] * b[1];
 }
 
-void Vec2D::lerp(Vec2D& o, const Vec2D& a, const Vec2D& b, float f) {
-    float ax = a[0];
-    float ay = a[1];
-    o[0] = ax + f * (b[0] - ax);
-    o[1] = ay + f * (b[1] - ay);
+Vec2D Vec2D::lerp(const Vec2D& a, const Vec2D& b, float f) {
+    return {
+        a.x() + f * (b[0] - a.x()),
+        a.y() + f * (b[1] - a.y()),
+    };
 }
-
-void Vec2D::scale(Vec2D& o, const Vec2D& a, float scale) {
-    o[0] = a[0] * scale;
-    o[1] = a[1] * scale;
-}
-
-void Vec2D::scaleAndAdd(Vec2D& o, const Vec2D& a, const Vec2D& b, float scale) {
-    o[0] = a[0] + b[0] * scale;
-    o[1] = a[1] + b[1] * scale;
-}
-
-void Vec2D::negate(Vec2D& o, const Vec2D& a) {
-    o[0] = -a[0];
-    o[1] = -a[1];
-}
\ No newline at end of file
diff --git a/src/shapes/cubic_asymmetric_vertex.cpp b/src/shapes/cubic_asymmetric_vertex.cpp
index 3e7c5ee..8ba1ab0 100644
--- a/src/shapes/cubic_asymmetric_vertex.cpp
+++ b/src/shapes/cubic_asymmetric_vertex.cpp
@@ -4,18 +4,26 @@
 
 using namespace rive;
 
+static Vec2D get_point(const CubicAsymmetricVertex& v) {
+    return Vec2D(v.x(), v.y());
+}
+
+static Vec2D in_vector(const CubicAsymmetricVertex& v) {
+    return Vec2D(cos(v.rotation()) * v.inDistance(),
+                 sin(v.rotation()) * v.inDistance());
+}
+
+static Vec2D out_vector(const CubicAsymmetricVertex& v) {
+    return Vec2D(cos(v.rotation()) * v.outDistance(),
+                 sin(v.rotation()) * v.outDistance());
+}
+
 void CubicAsymmetricVertex::computeIn() {
-    Vec2D::add(m_InPoint,
-               Vec2D(x(), y()),
-               Vec2D(cos(rotation()) * -inDistance(),
-                     sin(rotation()) * -inDistance()));
+    m_InPoint = get_point(*this) - in_vector(*this);
 }
 
 void CubicAsymmetricVertex::computeOut() {
-    Vec2D::add(m_OutPoint,
-               Vec2D(x(), y()),
-               Vec2D(cos(rotation()) * outDistance(),
-                     sin(rotation()) * outDistance()));
+    m_OutPoint = get_point(*this) + out_vector(*this);
 }
 
 void CubicAsymmetricVertex::rotationChanged() {
@@ -30,4 +38,4 @@
 void CubicAsymmetricVertex::outDistanceChanged() {
     m_OutValid = false;
     markPathDirty();
-}
\ No newline at end of file
+}
diff --git a/src/shapes/cubic_detached_vertex.cpp b/src/shapes/cubic_detached_vertex.cpp
index 83960c1..3a76fb9 100644
--- a/src/shapes/cubic_detached_vertex.cpp
+++ b/src/shapes/cubic_detached_vertex.cpp
@@ -4,18 +4,26 @@
 
 using namespace rive;
 
+static Vec2D get_point(const CubicDetachedVertex& v) {
+    return Vec2D(v.x(), v.y());
+}
+
+static Vec2D in_vector(const CubicDetachedVertex& v) {
+    return Vec2D(cos(v.inRotation()) * v.inDistance(),
+                 sin(v.inRotation()) * v.inDistance());
+}
+
+static Vec2D out_vector(const CubicDetachedVertex& v) {
+    return Vec2D(cos(v.outRotation()) * v.outDistance(),
+                 sin(v.outRotation()) * v.outDistance());
+}
+
 void CubicDetachedVertex::computeIn() {
-    Vec2D::add(m_InPoint,
-               Vec2D(x(), y()),
-               Vec2D(cos(inRotation()) * inDistance(),
-                     sin(inRotation()) * inDistance()));
+    m_InPoint = get_point(*this) + in_vector(*this);
 }
 
 void CubicDetachedVertex::computeOut() {
-    Vec2D::add(m_OutPoint,
-               Vec2D(x(), y()),
-               Vec2D(cos(outRotation()) * outDistance(),
-                     sin(outRotation()) * outDistance()));
+    m_OutPoint = get_point(*this) + out_vector(*this);
 }
 
 void CubicDetachedVertex::inRotationChanged() {
@@ -33,4 +41,4 @@
 void CubicDetachedVertex::outDistanceChanged() {
     m_OutValid = false;
     markPathDirty();
-}
\ No newline at end of file
+}
diff --git a/src/shapes/cubic_mirrored_vertex.cpp b/src/shapes/cubic_mirrored_vertex.cpp
index 340934f..068887c 100644
--- a/src/shapes/cubic_mirrored_vertex.cpp
+++ b/src/shapes/cubic_mirrored_vertex.cpp
@@ -4,18 +4,21 @@
 
 using namespace rive;
 
+static Vec2D get_point(const CubicMirroredVertex& v) {
+    return Vec2D(v.x(), v.y());
+}
+
+static Vec2D get_vector(const CubicMirroredVertex& v) {
+    return Vec2D(cos(v.rotation()) * v.distance(),
+                 sin(v.rotation()) * v.distance());
+}
+
 void CubicMirroredVertex::computeIn() {
-    Vec2D::add(
-        m_InPoint,
-        Vec2D(x(), y()),
-        Vec2D(cos(rotation()) * -distance(), sin(rotation()) * -distance()));
+    m_InPoint = get_point(*this) - get_vector(*this);
 }
 
 void CubicMirroredVertex::computeOut() {
-    Vec2D::add(
-        m_OutPoint,
-        Vec2D(x(), y()),
-        Vec2D(cos(rotation()) * distance(), sin(rotation()) * distance()));
+    m_OutPoint = get_point(*this) + get_vector(*this);
 }
 
 void CubicMirroredVertex::rotationChanged() {
@@ -25,4 +28,4 @@
 void CubicMirroredVertex::distanceChanged() {
     m_InValid = m_OutValid = false;
     markPathDirty();
-}
\ No newline at end of file
+}
diff --git a/src/shapes/metrics_path.cpp b/src/shapes/metrics_path.cpp
index e4c1800..e24df3d 100644
--- a/src/shapes/metrics_path.cpp
+++ b/src/shapes/metrics_path.cpp
@@ -54,14 +54,14 @@
                         const Vec2D& to,
                         float t,
                         Vec2D* hull) {
-    Vec2D::lerp(hull[0], from, fromOut, t);
-    Vec2D::lerp(hull[1], fromOut, toIn, t);
-    Vec2D::lerp(hull[2], toIn, to, t);
+    hull[0] = Vec2D::lerp(from, fromOut, t);
+    hull[1] = Vec2D::lerp(fromOut, toIn, t);
+    hull[2] = Vec2D::lerp(toIn, to, t);
 
-    Vec2D::lerp(hull[3], hull[0], hull[1], t);
-    Vec2D::lerp(hull[4], hull[1], hull[2], t);
+    hull[3] = Vec2D::lerp(hull[0], hull[1], t);
+    hull[4] = Vec2D::lerp(hull[1], hull[2], t);
 
-    Vec2D::lerp(hull[5], hull[3], hull[4], t);
+    hull[5] = Vec2D::lerp(hull[3], hull[4], t);
 }
 
 static const float minSegmentLength = 0.05f;
@@ -75,9 +75,8 @@
                              const Vec2D& fromOut,
                              const Vec2D& toIn,
                              const Vec2D& to) {
-    Vec2D oneThird, twoThird;
-    Vec2D::lerp(oneThird, from, to, 1.0f / 3.0f);
-    Vec2D::lerp(twoThird, from, to, 2.0f / 3.0f);
+    const Vec2D oneThird = Vec2D::lerp(from, to, 1.0f / 3.0f),
+                twoThird = Vec2D::lerp(from, to, 2.0f / 3.0f);
     return tooFar(fromOut, oneThird) || tooFar(toIn, twoThird);
 }
 
@@ -131,7 +130,7 @@
     // another transform).
     m_TransformedPoints.resize(m_Points.size());
     for (size_t i = 0, l = m_Points.size(); i < l; i++) {
-        Vec2D::transform(m_TransformedPoints[i], m_Points[i], transform);
+        m_TransformedPoints[i] = Vec2D::transform(m_Points[i], transform);
     }
 
     // Should never have subPaths with more subPaths (Skia allows this but for
@@ -271,14 +270,12 @@
         case PathPart::line: {
             const Vec2D& from = m_TransformedPoints[part.offset - 1];
             const Vec2D& to = m_TransformedPoints[part.offset];
-            Vec2D dir;
-            Vec2D::subtract(dir, to, from);
+            Vec2D dir = to - from;
             if (moveTo) {
-                Vec2D point;
-                Vec2D::scaleAndAdd(point, from, dir, startT);
+                Vec2D point = from + dir * startT;
                 result->moveTo(point[0], point[1]);
             }
-            Vec2D::scaleAndAdd(dir, from, dir, endT);
+            dir = from + dir * endT;
             result->lineTo(dir[0], dir[1]);
 
             break;
diff --git a/src/shapes/paint/linear_gradient.cpp b/src/shapes/paint/linear_gradient.cpp
index 273a39e..2ab64f4 100644
--- a/src/shapes/paint/linear_gradient.cpp
+++ b/src/shapes/paint/linear_gradient.cpp
@@ -75,11 +75,8 @@
             // Get the start and end of the gradient in world coordinates (world
             // transform of the shape).
             const Mat2D& world = m_ShapePaintContainer->worldTransform();
-            Vec2D worldStart;
-            Vec2D::transform(worldStart, start, world);
-
-            Vec2D worldEnd;
-            Vec2D::transform(worldEnd, end, world);
+            Vec2D worldStart = Vec2D::transform(start, world);
+            Vec2D worldEnd = Vec2D::transform(end, world);
             makeGradient(worldStart, worldEnd);
         } else {
             makeGradient(start, end);
diff --git a/src/shapes/path.cpp b/src/shapes/path.cpp
index 2b503ea..fb7a3bd 100644
--- a/src/shapes/path.cpp
+++ b/src/shapes/path.cpp
@@ -91,45 +91,35 @@
 
             Vec2D pos = point.renderTranslation();
 
-            Vec2D toPrev;
-            Vec2D::subtract(toPrev,
-                            prev->is<CubicVertex>()
+            Vec2D toPrev = (prev->is<CubicVertex>()
                                 ? prev->as<CubicVertex>()->renderOut()
-                                : prev->renderTranslation(),
-                            pos);
-            auto toPrevLength = Vec2D::length(toPrev);
+                                : prev->renderTranslation())
+                         - pos;
+
+            auto toPrevLength = toPrev.length();
             toPrev[0] /= toPrevLength;
             toPrev[1] /= toPrevLength;
 
             auto next = vertices[1];
 
-            Vec2D toNext;
-            Vec2D::subtract(toNext,
-                            next->is<CubicVertex>()
+            Vec2D toNext = (next->is<CubicVertex>()
                                 ? next->as<CubicVertex>()->renderIn()
-                                : next->renderTranslation(),
-                            pos);
-            auto toNextLength = Vec2D::length(toNext);
+                                : next->renderTranslation())
+                         - pos;
+            auto toNextLength = toNext.length();
             toNext[0] /= toNextLength;
             toNext[1] /= toNextLength;
 
             float renderRadius =
                 std::min(toPrevLength, std::min(toNextLength, radius));
 
-            Vec2D translation;
-            Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);
+            Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
             commandPath.moveTo(startInX = startX = translation[0],
                                startInY = startY = translation[1]);
-            Vec2D outPoint;
-            Vec2D::scaleAndAdd(
-                outPoint, pos, toPrev, icircleConstant * renderRadius);
 
-            Vec2D inPoint;
-            Vec2D::scaleAndAdd(
-                inPoint, pos, toNext, icircleConstant * renderRadius);
-
-            Vec2D posNext;
-            Vec2D::scaleAndAdd(posNext, pos, toNext, renderRadius);
+            Vec2D outPoint = Vec2D::scaleAndAdd(pos, toPrev, icircleConstant * renderRadius);
+            Vec2D inPoint = Vec2D::scaleAndAdd(pos, toNext, icircleConstant * renderRadius);
+            Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
             commandPath.cubicTo(outPoint[0],
                                 outPoint[1],
                                 inPoint[0],
@@ -168,29 +158,25 @@
             Vec2D pos = point.renderTranslation();
 
             if (auto radius = point.radius(); radius > 0.0f) {
-                Vec2D toPrev;
-                Vec2D::subtract(toPrev, Vec2D(outX, outY), pos);
-                auto toPrevLength = Vec2D::length(toPrev);
+                Vec2D toPrev = Vec2D(outX, outY) - pos;
+                auto toPrevLength = toPrev.length();
                 toPrev[0] /= toPrevLength;
                 toPrev[1] /= toPrevLength;
 
                 auto next = vertices[(i + 1) % length];
 
-                Vec2D toNext;
-                Vec2D::subtract(toNext,
-                                next->is<CubicVertex>()
+                Vec2D toNext = (next->is<CubicVertex>()
                                     ? next->as<CubicVertex>()->renderIn()
-                                    : next->renderTranslation(),
-                                pos);
-                auto toNextLength = Vec2D::length(toNext);
+                                    : next->renderTranslation())
+                             - pos;
+                auto toNextLength = toNext.length();
                 toNext[0] /= toNextLength;
                 toNext[1] /= toNextLength;
 
                 float renderRadius =
                     std::min(toPrevLength, std::min(toNextLength, radius));
 
-                Vec2D translation;
-                Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);
+                Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
                 if (prevIsCubic) {
                     commandPath.cubicTo(outX,
                                         outY,
@@ -202,16 +188,9 @@
                     commandPath.lineTo(translation[0], translation[1]);
                 }
 
-                Vec2D outPoint;
-                Vec2D::scaleAndAdd(
-                    outPoint, pos, toPrev, icircleConstant * renderRadius);
-
-                Vec2D inPoint;
-                Vec2D::scaleAndAdd(
-                    inPoint, pos, toNext, icircleConstant * renderRadius);
-
-                Vec2D posNext;
-                Vec2D::scaleAndAdd(posNext, pos, toNext, renderRadius);
+                Vec2D outPoint = Vec2D::scaleAndAdd(pos, toPrev, icircleConstant * renderRadius);
+                Vec2D inPoint = Vec2D::scaleAndAdd(pos, toNext, icircleConstant * renderRadius);
+                Vec2D posNext = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
                 commandPath.cubicTo(outPoint[0],
                                     outPoint[1],
                                     inPoint[0],
@@ -334,26 +313,21 @@
 
                     Vec2D pos = point.renderTranslation();
 
-                    Vec2D toPrev;
-                    Vec2D::subtract(toPrev, prevPoint, pos);
-                    auto toPrevLength = Vec2D::length(toPrev);
+                    Vec2D toPrev = prevPoint - pos;
+                    auto toPrevLength = toPrev.length();
                     toPrev[0] /= toPrevLength;
                     toPrev[1] /= toPrevLength;
 
-                    Vec2D toNext;
-                    Vec2D::subtract(toNext, nextPoint, pos);
-                    auto toNextLength = Vec2D::length(toNext);
+                    Vec2D toNext = nextPoint - pos;
+                    auto toNextLength = toNext.length();
                     toNext[0] /= toNextLength;
                     toNext[1] /= toNextLength;
 
                     auto renderRadius = std::min(
                         toPrevLength, std::min(toNextLength, point.radius()));
-                    Vec2D translation;
-                    Vec2D::scaleAndAdd(translation, pos, toPrev, renderRadius);
+                    Vec2D translation = Vec2D::scaleAndAdd(pos, toPrev, renderRadius);
 
-                    Vec2D out;
-                    Vec2D::scaleAndAdd(
-                        out, pos, toPrev, icircleConstant * renderRadius);
+                    Vec2D out = Vec2D::scaleAndAdd(pos, toPrev, icircleConstant * renderRadius);
                     {
                         auto v1 = new DisplayCubicVertex(
                             translation, out, translation);
@@ -361,11 +335,9 @@
                         delete v1;
                     }
 
-                    Vec2D::scaleAndAdd(translation, pos, toNext, renderRadius);
+                    translation = Vec2D::scaleAndAdd(pos, toNext, renderRadius);
 
-                    Vec2D in;
-                    Vec2D::scaleAndAdd(
-                        in, pos, toNext, icircleConstant * renderRadius);
+                    Vec2D in = Vec2D::scaleAndAdd(pos, toNext, icircleConstant * renderRadius);
                     auto v2 =
                         new DisplayCubicVertex(in, translation, translation);
 
@@ -402,17 +374,15 @@
 
         // Cubics need to be transformed so we create a Display version which
         // has set in/out values.
-        Vec2D in, out, translation;
-        Vec2D::transform(in, cubic->renderIn(), transform);
-        Vec2D::transform(out, cubic->renderOut(), transform);
-        Vec2D::transform(translation, cubic->renderTranslation(), transform);
+        const auto in = Vec2D::transform(cubic->renderIn(), transform);
+        const auto out = Vec2D::transform(cubic->renderOut(), transform);
+        const auto translation = Vec2D::transform(cubic->renderTranslation(), transform);
 
         auto displayCubic = new DisplayCubicVertex(in, out, translation);
         m_Vertices.push_back(displayCubic);
     } else {
         auto point = new PathVertex();
-        Vec2D translation;
-        Vec2D::transform(translation, vertex->renderTranslation(), transform);
+        Vec2D translation = Vec2D::transform(vertex->renderTranslation(), transform);
         point->x(translation[0]);
         point->y(translation[1]);
         m_Vertices.push_back(point);