We only read/use floats, not doubles
diff --git a/build/premake5.lua b/build/premake5.lua
index 2d8c587..c592111 100644
--- a/build/premake5.lua
+++ b/build/premake5.lua
@@ -75,7 +75,11 @@
     }
 
     filter {"system:macosx" }
-        buildoptions {"-flto=full"}
+        buildoptions {
+            "-flto=full",
+            -- this triggers too much on linux, so just enable here for now
+            "-Wimplicit-float-conversion",
+        }
 
     filter {"system:ios" }
         buildoptions {"-flto=full"}
diff --git a/include/rive/core/binary_reader.hpp b/include/rive/core/binary_reader.hpp
index eb45f15..eca5ce7 100644
--- a/include/rive/core/binary_reader.hpp
+++ b/include/rive/core/binary_reader.hpp
@@ -29,7 +29,6 @@
 
         std::string readString();
         Span<const uint8_t> readBytes();
-        double readFloat64();
         float readFloat32();
         uint8_t readByte();
         uint32_t readUint32();
diff --git a/include/rive/core/field_types/core_double_type.hpp b/include/rive/core/field_types/core_double_type.hpp
index e13be51..351c9b2 100644
--- a/include/rive/core/field_types/core_double_type.hpp
+++ b/include/rive/core/field_types/core_double_type.hpp
@@ -6,7 +6,7 @@
     class CoreDoubleType {
     public:
         static const int id = 2;
-        static double deserialize(BinaryReader& reader);
+        static float deserialize(BinaryReader& reader);
     };
 } // namespace rive
 #endif
\ No newline at end of file
diff --git a/include/rive/core/reader.h b/include/rive/core/reader.h
index 1779cc0..572ef24 100644
--- a/include/rive/core/reader.h
+++ b/include/rive/core/reader.h
@@ -47,22 +47,6 @@
     return str_len;
 }
 
-/* Decodes a double (8 bytes)
- */
-inline size_t decode_double(const uint8_t* buf, const uint8_t* buf_end, double* r) {
-    // Return zero bytes read on buffer overflow
-    if (buf_end - buf < ((unsigned)sizeof(double))) {
-        return 0;
-    }
-    if (is_big_endian()) {
-        uint8_t inverted[8] = {buf[7], buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]};
-        memcpy(r, inverted, sizeof(double));
-    } else {
-        memcpy(r, buf, sizeof(double));
-    }
-    return sizeof(double);
-}
-
 /* Decodes a float (4 bytes)
  */
 inline size_t decode_float(const uint8_t* buf, const uint8_t* buf_end, float* r) {
diff --git a/include/rive/math/circle_constant.hpp b/include/rive/math/circle_constant.hpp
index da7c9c5..d3d7ed1 100644
--- a/include/rive/math/circle_constant.hpp
+++ b/include/rive/math/circle_constant.hpp
@@ -4,8 +4,8 @@
 #include "rive/rive_types.hpp"
 
 namespace rive {
-    constexpr float circleConstant = 0.552284749831;
-    constexpr float icircleConstant = 1.0 - circleConstant;
+    constexpr float circleConstant = 0.552284749831f;
+    constexpr float icircleConstant = 1.0f - circleConstant;
 } // namespace rive
 
 #endif
diff --git a/src/animation/keyframe_double.cpp b/src/animation/keyframe_double.cpp
index b059062..887ade1 100644
--- a/src/animation/keyframe_double.cpp
+++ b/src/animation/keyframe_double.cpp
@@ -12,7 +12,7 @@
     if (mix == 1.0f) {
         CoreRegistry::setDouble(object, propertyKey, value);
     } else {
-        float mixi = 1.0 - mix;
+        float mixi = 1.0f - mix;
         CoreRegistry::setDouble(
             object, propertyKey, CoreRegistry::getDouble(object, propertyKey) * mixi + value * mix);
     }
diff --git a/src/animation/linear_animation_instance.cpp b/src/animation/linear_animation_instance.cpp
index 9819657..46d7349 100644
--- a/src/animation/linear_animation_instance.cpp
+++ b/src/animation/linear_animation_instance.cpp
@@ -60,7 +60,7 @@
             if (m_Direction == 1 && frames >= end) {
                 m_SpilledTime = (frames - end) / fps;
                 frames = m_Time * fps;
-                frames = start + std::fmod(frames - start, range);
+                frames = start + std::fmod(frames - start, (float)range);
 
                 m_Time = frames / fps;
                 didLoop = true;
@@ -68,7 +68,7 @@
 
                 m_SpilledTime = (start - frames) / fps;
                 frames = m_Time * fps;
-                frames = end - std::abs(std::fmod(start - frames, range));
+                frames = end - std::abs(std::fmod(start - frames, (float)range));
                 m_Time = frames / fps;
                 didLoop = true;
             }
diff --git a/src/artboard.cpp b/src/artboard.cpp
index 5a865ea..58e9cae 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -375,7 +375,7 @@
 
 bool Artboard::advance(double elapsedSeconds) {
     for (auto nestedArtboard : m_NestedArtboards) {
-        nestedArtboard->advance(elapsedSeconds);
+        nestedArtboard->advance((float)elapsedSeconds);
     }
     return updateComponents();
 }
diff --git a/src/core/binary_reader.cpp b/src/core/binary_reader.cpp
index 153ec46..b87475e 100644
--- a/src/core/binary_reader.cpp
+++ b/src/core/binary_reader.cpp
@@ -66,17 +66,6 @@
     return {start, (size_t)length};
 }
 
-double BinaryReader::readFloat64() {
-    double value;
-    auto readBytes = decode_double(m_Position, m_Bytes.end(), &value);
-    if (readBytes == 0) {
-        overflow();
-        return 0.0;
-    }
-    m_Position += readBytes;
-    return value;
-}
-
 float BinaryReader::readFloat32() {
     float value;
     auto readBytes = decode_float(m_Position, m_Bytes.end(), &value);
diff --git a/src/core/field_types/core_double_type.cpp b/src/core/field_types/core_double_type.cpp
index a0c26e7..cbd3a0d 100644
--- a/src/core/field_types/core_double_type.cpp
+++ b/src/core/field_types/core_double_type.cpp
@@ -3,4 +3,4 @@
 
 using namespace rive;
 
-double CoreDoubleType::deserialize(BinaryReader& reader) { return reader.readFloat32(); }
\ No newline at end of file
+float CoreDoubleType::deserialize(BinaryReader& reader) { return reader.readFloat32(); }
\ No newline at end of file
diff --git a/src/renderer.cpp b/src/renderer.cpp
index d56657b..37c3a89 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -6,10 +6,10 @@
 Mat2D rive::computeAlignment(Fit fit, Alignment alignment, const AABB& frame, const AABB& content) {
     float contentWidth = content.width();
     float contentHeight = content.height();
-    float x = -content.left() - contentWidth / 2.0 - (alignment.x() * contentWidth / 2.0);
-    float y = -content.top() - contentHeight / 2.0 - (alignment.y() * contentHeight / 2.0);
+    float x = -content.left() - contentWidth * 0.5f - (alignment.x() * contentWidth * 0.5f);
+    float y = -content.top() - contentHeight * 0.5f - (alignment.y() * contentHeight * 0.5f);
 
-    float scaleX = 1.0, scaleY = 1.0;
+    float scaleX = 1.0f, scaleY = 1.0f;
 
     switch (fit) {
         case Fit::fill: {
@@ -40,20 +40,20 @@
             break;
         }
         case Fit::none: {
-            scaleX = scaleY = 1.0;
+            scaleX = scaleY = 1.0f;
             break;
         }
         case Fit::scaleDown: {
             float minScale =
                 std::fmin(frame.width() / contentWidth, frame.height() / contentHeight);
-            scaleX = scaleY = minScale < 1.0 ? minScale : 1.0;
+            scaleX = scaleY = minScale < 1.0f ? minScale : 1.0f;
             break;
         }
     }
 
     Mat2D translation;
-    translation[4] = frame.left() + frame.width() / 2.0 + (alignment.x() * frame.width() / 2.0);
-    translation[5] = frame.top() + frame.height() / 2.0 + (alignment.y() * frame.height() / 2.0);
+    translation[4] = frame.left() + frame.width() * 0.5f + (alignment.x() * frame.width() * 0.5f);
+    translation[5] = frame.top() + frame.height() * 0.5f + (alignment.y() * frame.height() * 0.5f);
 
     return translation * Mat2D::fromScale(scaleX, scaleY) * Mat2D::fromTranslate(x, y);
 }
diff --git a/src/shapes/paint/linear_gradient.cpp b/src/shapes/paint/linear_gradient.cpp
index 92fb7a6..06a7a3b 100644
--- a/src/shapes/paint/linear_gradient.cpp
+++ b/src/shapes/paint/linear_gradient.cpp
@@ -78,7 +78,7 @@
         }
 
         // build up the color and positions lists
-        const double ro = opacity() * renderOpacity();
+        const auto ro = opacity() * renderOpacity();
         const auto count = m_Stops.size();
 
         // need some temporary storage. Allocate enough for both arrays
diff --git a/test/reader_test.cpp b/test/reader_test.cpp
index 5ad83ab..9178cd3 100644
--- a/test/reader_test.cpp
+++ b/test/reader_test.cpp
@@ -32,29 +32,6 @@
     delete decoded_str;
 }
 
-TEST_CASE("double decoder", "[reader]") {
-    double decoded_num;
-    uint64_t bytes_read;
-
-    uint8_t num_bytes_100[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x40};
-    bytes_read = decode_double(num_bytes_100, num_bytes_100 + 8, &decoded_num);
-    REQUIRE(decoded_num == 100);
-    REQUIRE(bytes_read == 8);
-
-    uint8_t num_bytes_pi[] = {0x6E, 0x86, 0x1B, 0xF0, 0xF9, 0x21, 0x09, 0x40};
-    bytes_read = decode_double(num_bytes_pi, num_bytes_pi + 8, &decoded_num);
-    REQUIRE(decoded_num == 3.14159);
-    REQUIRE(bytes_read == 8);
-
-    uint8_t num_bytes_neg_euler[] = {0x96, 0xB4, 0xE2, 0x1B, 0x0A, 0xBF, 0x05, 0xC0};
-    bytes_read = decode_double(num_bytes_neg_euler, num_bytes_neg_euler + 8, &decoded_num);
-    REQUIRE(decoded_num == -2.718281);
-    REQUIRE(bytes_read == 8);
-
-    bytes_read = decode_double(num_bytes_neg_euler, num_bytes_neg_euler + 7, &decoded_num);
-    REQUIRE(bytes_read == 0);
-}
-
 TEST_CASE("float decoder", "[reader]") {
     float decoded_num;
     uint64_t bytes_read;