Drop the runtime to C++11 This is necessary in order for us to be able to run on more platforms. Diffs= 312a6c778 Drop the runtime to C++11
diff --git a/.rive_head b/.rive_head index 100b2c9..18868aa 100644 --- a/.rive_head +++ b/.rive_head
@@ -1 +1 @@ -de4fe4d71a1eeef8e135991ca395c3159b42dc0d +312a6c77883aaf469214e1dffc6953d4e82ace8c
diff --git a/build/premake5.lua b/build/premake5.lua index 507d7c2..52390b9 100644 --- a/build/premake5.lua +++ b/build/premake5.lua
@@ -40,7 +40,7 @@ do kind 'StaticLib' language 'C++' - cppdialect 'C++17' + cppdialect 'C++11' toolset 'clang' targetdir '%{cfg.system}/bin/%{cfg.buildcfg}' objdir '%{cfg.system}/obj/%{cfg.buildcfg}'
diff --git a/dev/test/premake5.lua b/dev/test/premake5.lua index aa95378..7e73360 100644 --- a/dev/test/premake5.lua +++ b/dev/test/premake5.lua
@@ -23,7 +23,7 @@ do kind 'ConsoleApp' language 'C++' - cppdialect 'C++17' + cppdialect 'C++11' toolset (_OPTIONS["toolset"] or "clang") targetdir 'build/bin/%{cfg.buildcfg}' objdir 'build/obj/%{cfg.buildcfg}'
diff --git a/include/rive/math/math_types.hpp b/include/rive/math/math_types.hpp index 00b2bf0..1b6db5f 100644 --- a/include/rive/math/math_types.hpp +++ b/include/rive/math/math_types.hpp
@@ -7,6 +7,7 @@ #include "rive/rive_types.hpp" #include <cmath> +#include <limits> #include <string.h> namespace rive @@ -17,13 +18,13 @@ constexpr float PI = 3.14159265f; constexpr float EPSILON = 1.f / (1 << 12); // Common threshold for detecting values near zero. -[[maybe_unused]] inline bool nearly_zero(float a, float tolerance = EPSILON) +RIVE_MAYBE_UNUSED inline bool nearly_zero(float a, float tolerance = EPSILON) { assert(tolerance >= 0); return fabsf(a) <= tolerance; } -[[maybe_unused]] inline bool nearly_equal(float a, float b, float tolerance = EPSILON) +RIVE_MAYBE_UNUSED inline bool nearly_equal(float a, float b, float tolerance = EPSILON) { return nearly_zero(b - a, tolerance); } @@ -38,7 +39,7 @@ // // Reference: // https://stackoverflow.com/questions/42926763/the-behaviour-of-floating-point-division-by-zero -[[maybe_unused]] +RIVE_MAYBE_UNUSED #if defined(__clang__) || defined(__GNUC__) __attribute__((no_sanitize("float-divide-by-zero"), always_inline)) #endif @@ -46,16 +47,16 @@ ieee_float_divide(float a, float b) { static_assert(std::numeric_limits<float>::is_iec559, - "Conformant IEEE 754 behavior for NaN and Inf is required."); + "conformant IEEE 754 behavior for NaN and Inf is required"); return a / b; } // Reinterprets the underlying bits of src as the given type. template <typename Dst, typename Src> Dst bit_cast(const Src& src) { - static_assert(sizeof(Dst) == sizeof(Src)); + static_assert(sizeof(Dst) == sizeof(Src), "sizes of both types must match"); Dst dst; - memcpy(&dst, &src, sizeof(Dst)); + RIVE_INLINE_MEMCPY(&dst, &src, sizeof(Dst)); return dst; } } // namespace math
diff --git a/include/rive/math/raw_path.hpp b/include/rive/math/raw_path.hpp index ee6affc..f441917 100644 --- a/include/rive/math/raw_path.hpp +++ b/include/rive/math/raw_path.hpp
@@ -14,6 +14,7 @@ #include <cmath> #include <stdio.h> #include <cstdint> +#include <tuple> #include <vector> namespace rive @@ -108,7 +109,7 @@ private: // How much should we advance pts after encountering this verb? - constexpr static int PtsAdvanceAfterVerb(PathVerb verb) + inline static int PtsAdvanceAfterVerb(PathVerb verb) { switch (verb) { @@ -123,14 +124,14 @@ case PathVerb::close: return 0; } - RIVE_UNREACHABLE; + RIVE_UNREACHABLE(); } // Where is p0 relative to our m_pts pointer? We find the start point of segments by // peeking backwards from the current point, which works as long as there is always a // PathVerb::move before any geometry. (injectImplicitMoveToIfNeeded() guarantees this // to be the case.) - constexpr static int PtsBacksetForVerb(PathVerb verb) + inline static int PtsBacksetForVerb(PathVerb verb) { switch (verb) { @@ -145,7 +146,7 @@ case PathVerb::close: return -1; } - RIVE_UNREACHABLE; + RIVE_UNREACHABLE(); } const PathVerb* m_verbs; @@ -158,8 +159,10 @@ { RawPath dst; // todo: dst.reserve(src.ptCount, src.verbCount); - for (auto [verb, pts] : *this) + for (auto iter : *this) { + PathVerb verb = std::get<0>(iter); + const Vec2D* pts = std::get<1>(iter); switch (verb) { case PathVerb::move:
diff --git a/include/rive/math/simd.hpp b/include/rive/math/simd.hpp index 7ef17e0..9cb90aa 100644 --- a/include/rive/math/simd.hpp +++ b/include/rive/math/simd.hpp
@@ -14,6 +14,7 @@ #ifndef _RIVE_SIMD_HPP_ #define _RIVE_SIMD_HPP_ +#include "rive/rive_types.hpp" #include <cassert> #include <limits> #include <stdint.h> @@ -35,13 +36,6 @@ #if defined(__clang__) || defined(__GNUC__) -#define SIMD_ALWAYS_INLINE inline __attribute__((always_inline)) - -// Recommended in https://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - namespace rive { namespace simd @@ -55,21 +49,12 @@ #else -#define SIMD_ALWAYS_INLINE inline -#define __has_builtin(x) 0 - // gvec needs to be polyfilled with templates. #pragma message("performance: ext_vector_type not supported. Consider using clang.") #include "simd_gvec_polyfill.hpp" #endif -#if __has_builtin(__builtin_memcpy) -#define SIMD_INLINE_MEMCPY __builtin_memcpy -#else -#define SIMD_INLINE_MEMCPY memcpy -#endif - namespace rive { namespace simd @@ -81,7 +66,7 @@ // // Returns true if all elements in x are equal to 0. -template <int N> SIMD_ALWAYS_INLINE bool any(gvec<int32_t, N> x) +template <int N> RIVE_ALWAYS_INLINE bool any(gvec<int32_t, N> x) { #if __has_builtin(__builtin_reduce_or) return __builtin_reduce_or(x); @@ -98,7 +83,7 @@ } // Returns true if all elements in x are equal to ~0. -template <int N> SIMD_ALWAYS_INLINE bool all(gvec<int32_t, N> x) +template <int N> RIVE_ALWAYS_INLINE bool all(gvec<int32_t, N> x) { #if __has_builtin(__builtin_reduce_and) return __builtin_reduce_and(x); @@ -112,7 +97,7 @@ template <typename T, int N, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> -SIMD_ALWAYS_INLINE gvec<int32_t, N> isnan(gvec<T, N> x) +RIVE_ALWAYS_INLINE gvec<int32_t, N> isnan(gvec<T, N> x) { return ~(x == x); } @@ -127,7 +112,7 @@ // Elementwise ternary expression: "_if ? _then : _else" for each component. template <typename T, int N> -SIMD_ALWAYS_INLINE gvec<T, N> if_then_else(gvec<int32_t, N> _if, gvec<T, N> _then, gvec<T, N> _else) +RIVE_ALWAYS_INLINE gvec<T, N> if_then_else(gvec<int32_t, N> _if, gvec<T, N> _then, gvec<T, N> _else) { #if defined(__clang_major__) && __clang_major__ >= 13 // The '?:' operator supports a vector condition beginning in clang 13. @@ -143,7 +128,7 @@ // Similar to std::min(), with a noteworthy difference: // If a[i] or b[i] is NaN and the other is not, returns whichever is _not_ NaN. -template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> min(gvec<T, N> a, gvec<T, N> b) +template <typename T, int N> RIVE_ALWAYS_INLINE gvec<T, N> min(gvec<T, N> a, gvec<T, N> b) { #if __has_builtin(__builtin_elementwise_min) return __builtin_elementwise_min(a, b); @@ -156,7 +141,7 @@ // Similar to std::max(), with a noteworthy difference: // If a[i] or b[i] is NaN and the other is not, returns whichever is _not_ NaN. -template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> max(gvec<T, N> a, gvec<T, N> b) +template <typename T, int N> RIVE_ALWAYS_INLINE gvec<T, N> max(gvec<T, N> a, gvec<T, N> b) { #if __has_builtin(__builtin_elementwise_max) return __builtin_elementwise_max(a, b); @@ -174,14 +159,14 @@ // Ignores hi and/or lo if they are NaN. // template <typename T, int N> -SIMD_ALWAYS_INLINE gvec<T, N> clamp(gvec<T, N> x, gvec<T, N> lo, gvec<T, N> hi) +RIVE_ALWAYS_INLINE gvec<T, N> clamp(gvec<T, N> x, gvec<T, N> lo, gvec<T, N> hi) { return min(max(lo, x), hi); } // Returns the absolute value of x per element, with one exception: // If x[i] is an integer type and equal to the minimum representable value, returns x[i]. -template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> abs(gvec<T, N> x) +template <typename T, int N> RIVE_ALWAYS_INLINE gvec<T, N> abs(gvec<T, N> x) { #if __has_builtin(__builtin_elementwise_abs) return __builtin_elementwise_abs(x); @@ -193,7 +178,7 @@ ////// Floating Point Functions ////// -template <int N> SIMD_ALWAYS_INLINE gvec<float, N> floor(gvec<float, N> x) +template <int N> RIVE_ALWAYS_INLINE gvec<float, N> floor(gvec<float, N> x) { #if __has_builtin(__builtin_elementwise_floor) return __builtin_elementwise_floor(x); @@ -206,7 +191,7 @@ #endif } -template <int N> SIMD_ALWAYS_INLINE gvec<float, N> ceil(gvec<float, N> x) +template <int N> RIVE_ALWAYS_INLINE gvec<float, N> ceil(gvec<float, N> x) { #if __has_builtin(__builtin_elementwise_ceil) return __builtin_elementwise_ceil(x); @@ -219,7 +204,7 @@ } // IEEE compliant sqrt. -template <int N> SIMD_ALWAYS_INLINE gvec<float, N> sqrt(gvec<float, N> x) +template <int N> RIVE_ALWAYS_INLINE gvec<float, N> sqrt(gvec<float, N> x) { // There isn't an elementwise builtin for sqrt. We define architecture-specific specializations // of this function later. @@ -229,42 +214,42 @@ } #ifdef __SSE__ -template <> SIMD_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) { __m128 _x; - SIMD_INLINE_MEMCPY(&_x, &x, sizeof(float) * 4); + RIVE_INLINE_MEMCPY(&_x, &x, sizeof(float) * 4); _x = _mm_sqrt_ps(_x); - SIMD_INLINE_MEMCPY(&x, &_x, sizeof(float) * 4); + RIVE_INLINE_MEMCPY(&x, &_x, sizeof(float) * 4); return x; } -template <> SIMD_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) { __m128 _x; - SIMD_INLINE_MEMCPY(&_x, &x, sizeof(float) * 2); + RIVE_INLINE_MEMCPY(&_x, &x, sizeof(float) * 2); _x = _mm_sqrt_ps(_x); - SIMD_INLINE_MEMCPY(&x, &_x, sizeof(float) * 2); + RIVE_INLINE_MEMCPY(&x, &_x, sizeof(float) * 2); return x; } #endif #ifdef __ARM_NEON__ #ifdef __aarch64__ -template <> SIMD_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) { float32x4_t _x; - SIMD_INLINE_MEMCPY(&_x, &x, sizeof(float) * 4); + RIVE_INLINE_MEMCPY(&_x, &x, sizeof(float) * 4); _x = vsqrtq_f32(_x); - SIMD_INLINE_MEMCPY(&x, &_x, sizeof(float) * 4); + RIVE_INLINE_MEMCPY(&x, &_x, sizeof(float) * 4); return x; } -template <> SIMD_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) { float32x2_t _x; - SIMD_INLINE_MEMCPY(&_x, &x, sizeof(float) * 2); + RIVE_INLINE_MEMCPY(&_x, &x, sizeof(float) * 2); _x = vsqrt_f32(_x); - SIMD_INLINE_MEMCPY(&x, &_x, sizeof(float) * 2); + RIVE_INLINE_MEMCPY(&x, &_x, sizeof(float) * 2); return x; } #endif @@ -272,12 +257,12 @@ // This will only be present when building with Emscripten and "-msimd128". #if __has_builtin(__builtin_wasm_sqrt_f32x4) -template <> SIMD_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 4> sqrt(gvec<float, 4> x) { return __builtin_wasm_sqrt_f32x4(x); } -template <> SIMD_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) +template <> RIVE_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x) { gvec<float, 4> _x{x.x, x.y}; _x = __builtin_wasm_sqrt_f32x4(_x); @@ -291,7 +276,7 @@ // // See: https://stackoverflow.com/a/36387954 #define SIMD_FAST_ACOS_MAX_ERROR 0.0167552f // .96 degrees -template <int N> SIMD_ALWAYS_INLINE gvec<float, N> fast_acos(gvec<float, N> x) +template <int N> RIVE_ALWAYS_INLINE gvec<float, N> fast_acos(gvec<float, N> x) { constexpr static float a = -0.939115566365855f; constexpr static float b = 0.9217841528914573f; @@ -306,36 +291,36 @@ ////// Loading and storing ////// -template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> load(const void* ptr) +template <typename T, int N> RIVE_ALWAYS_INLINE gvec<T, N> load(const void* ptr) { gvec<T, N> ret; - SIMD_INLINE_MEMCPY(&ret, ptr, sizeof(T) * N); + RIVE_INLINE_MEMCPY(&ret, ptr, sizeof(T) * N); return ret; } -SIMD_ALWAYS_INLINE gvec<float, 2> load2f(const void* ptr) { return load<float, 2>(ptr); } -SIMD_ALWAYS_INLINE gvec<float, 4> load4f(const void* ptr) { return load<float, 4>(ptr); } -SIMD_ALWAYS_INLINE gvec<int32_t, 2> load2i(const void* ptr) { return load<int32_t, 2>(ptr); } -SIMD_ALWAYS_INLINE gvec<int32_t, 4> load4i(const void* ptr) { return load<int32_t, 4>(ptr); } -SIMD_ALWAYS_INLINE gvec<uint32_t, 2> load2ui(const void* ptr) { return load<uint32_t, 2>(ptr); } -SIMD_ALWAYS_INLINE gvec<uint32_t, 4> load4ui(const void* ptr) { return load<uint32_t, 4>(ptr); } +RIVE_ALWAYS_INLINE gvec<float, 2> load2f(const void* ptr) { return load<float, 2>(ptr); } +RIVE_ALWAYS_INLINE gvec<float, 4> load4f(const void* ptr) { return load<float, 4>(ptr); } +RIVE_ALWAYS_INLINE gvec<int32_t, 2> load2i(const void* ptr) { return load<int32_t, 2>(ptr); } +RIVE_ALWAYS_INLINE gvec<int32_t, 4> load4i(const void* ptr) { return load<int32_t, 4>(ptr); } +RIVE_ALWAYS_INLINE gvec<uint32_t, 2> load2ui(const void* ptr) { return load<uint32_t, 2>(ptr); } +RIVE_ALWAYS_INLINE gvec<uint32_t, 4> load4ui(const void* ptr) { return load<uint32_t, 4>(ptr); } -template <typename T, int N> SIMD_ALWAYS_INLINE void store(void* dst, gvec<T, N> vec) +template <typename T, int N> RIVE_ALWAYS_INLINE void store(void* dst, gvec<T, N> vec) { - SIMD_INLINE_MEMCPY(dst, &vec, sizeof(T) * N); + RIVE_INLINE_MEMCPY(dst, &vec, sizeof(T) * N); } template <typename T, int M, int N> -SIMD_ALWAYS_INLINE gvec<T, M + N> join(gvec<T, M> a, gvec<T, N> b) +RIVE_ALWAYS_INLINE gvec<T, M + N> join(gvec<T, M> a, gvec<T, N> b) { T data[M + N]; - SIMD_INLINE_MEMCPY(data, &a, sizeof(T) * M); - SIMD_INLINE_MEMCPY(data + M, &b, sizeof(T) * N); + RIVE_INLINE_MEMCPY(data, &a, sizeof(T) * M); + RIVE_INLINE_MEMCPY(data + M, &b, sizeof(T) * N); return load<T, M + N>(data); } ////// Basic linear algebra ////// -template <typename T, int N> SIMD_ALWAYS_INLINE T dot(gvec<T, N> a, gvec<T, N> b) +template <typename T, int N> RIVE_ALWAYS_INLINE T dot(gvec<T, N> a, gvec<T, N> b) { auto d = a * b; T s = d[0]; @@ -346,20 +331,20 @@ // We can use __builtin_reduce_add for integer types. #if __has_builtin(__builtin_reduce_add) -template <int N> SIMD_ALWAYS_INLINE int32_t dot(gvec<int32_t, N> a, gvec<int32_t, N> b) +template <int N> RIVE_ALWAYS_INLINE int32_t dot(gvec<int32_t, N> a, gvec<int32_t, N> b) { auto d = a * b; return __builtin_reduce_add(d); } -template <int N> SIMD_ALWAYS_INLINE uint32_t dot(gvec<uint32_t, N> a, gvec<uint32_t, N> b) +template <int N> RIVE_ALWAYS_INLINE uint32_t dot(gvec<uint32_t, N> a, gvec<uint32_t, N> b) { auto d = a * b; return __builtin_reduce_add(d); } #endif -SIMD_ALWAYS_INLINE float cross(gvec<float, 2> a, gvec<float, 2> b) +RIVE_ALWAYS_INLINE float cross(gvec<float, 2> a, gvec<float, 2> b) { auto c = a * b.yx; return c.x - c.y; @@ -373,7 +358,7 @@ // structure seems to get better precision for things like chopping cubics on exact cusp points than // "a*(1 - t) + b*t" (which would return exactly b when t == 1). template <int N> -SIMD_ALWAYS_INLINE gvec<float, N> mix(gvec<float, N> a, gvec<float, N> b, gvec<float, N> t) +RIVE_ALWAYS_INLINE gvec<float, N> mix(gvec<float, N> a, gvec<float, N> b, gvec<float, N> t) { assert(simd::all(0.f <= t && t < 1.f)); return (b - a) * t + a; @@ -381,8 +366,7 @@ } // namespace simd } // namespace rive -#undef SIMD_ALWAYS_INLINE -#undef SIMD_INLINE_MEMCPY +#undef RIVE_INLINE_MEMCPY namespace rive {
diff --git a/include/rive/math/simd_gvec_polyfill.hpp b/include/rive/math/simd_gvec_polyfill.hpp index f1ab72b..a590aab 100644 --- a/include/rive/math/simd_gvec_polyfill.hpp +++ b/include/rive/math/simd_gvec_polyfill.hpp
@@ -143,10 +143,9 @@ T& operator[](size_t i) { return gvec_data<T, N>::data[i]; } }; -static_assert(sizeof(gvec<float, 1>) == 4); -static_assert(sizeof(gvec<float, 2>) == 8); -static_assert(sizeof(gvec<float, 3>) == 12); -static_assert(sizeof(gvec<float, 4>) == 16); +static_assert(sizeof(gvec<float, 1>) == 4, "gvec<1> is expected to be tightly packed"); +static_assert(sizeof(gvec<float, 2>) == 8, "gvec<2> is expected to be tightly packed"); +static_assert(sizeof(gvec<float, 4>) == 16, "gvec<4> is expected to be tightly packed"); #define DECL_UNARY_OP(_OP_) \ template <typename T, int N, Swizzle Z> gvec<T, N> operator _OP_(gvec<T, N, Z> x) \
diff --git a/include/rive/rive_types.hpp b/include/rive/rive_types.hpp index 13fb53b..3450d76 100644 --- a/include/rive/rive_types.hpp +++ b/include/rive/rive_types.hpp
@@ -9,44 +9,45 @@ #ifndef _RIVE_TYPES_HPP_ #define _RIVE_TYPES_HPP_ -// clang-format off +#include <memory> // For unique_ptr. +#include <string.h> // For memcpy. #if defined(DEBUG) && defined(NDEBUG) - #error "can't determine if we're debug or release" +#error "can't determine if we're debug or release" #endif #if !defined(DEBUG) && !defined(NDEBUG) - // we have to make a decision what mode we're in - // historically this has been to look for NDEBUG, and in its - // absence assume we're DEBUG. - #define DEBUG 1 - // fyi - Xcode seems to set DEBUG (or not), so the above guess - // doesn't work for them - so our projects may need to explicitly - // set NDEBUG in our 'release' builds. +// we have to make a decision what mode we're in +// historically this has been to look for NDEBUG, and in its +// absence assume we're DEBUG. +#define DEBUG 1 +// fyi - Xcode seems to set DEBUG (or not), so the above guess +// doesn't work for them - so our projects may need to explicitly +// set NDEBUG in our 'release' builds. #endif #ifdef NDEBUG - #ifndef RELEASE - #define RELEASE 1 - #endif -#else // debug mode - #ifndef DEBUG - #define DEBUG 1 - #endif +#ifndef RELEASE +#define RELEASE 1 +#endif +#else // debug mode +#ifndef DEBUG +#define DEBUG 1 +#endif #endif // Some checks to guess what platform we're building for #ifdef __APPLE__ - #define RIVE_BUILD_FOR_APPLE - #include <TargetConditionals.h> +#define RIVE_BUILD_FOR_APPLE +#include <TargetConditionals.h> - #if TARGET_OS_IPHONE - #define RIVE_BUILD_FOR_IOS - #elif TARGET_OS_MAC - #define RIVE_BUILD_FOR_OSX - #endif +#if TARGET_OS_IPHONE +#define RIVE_BUILD_FOR_IOS +#elif TARGET_OS_MAC +#define RIVE_BUILD_FOR_OSX +#endif #endif @@ -60,14 +61,59 @@ #include <type_traits> // Annotations to assert unreachable control flow. -#ifdef __GNUC__ // GCC 4.8+, Clang, Intel and others compatible with GCC (-std=c++0x or above) - #define RIVE_UNREACHABLE __builtin_unreachable() +#if defined(__GNUC__) || defined(__clang__) +#define RIVE_UNREACHABLE __builtin_unreachable #elif _MSC_VER - #define RIVE_UNREACHABLE __assume(0) +#define RIVE_UNREACHABLE() __assume(0) #else - #define RIVE_UNREACHABLE do {} while(0) +#define RIVE_UNREACHABLE() \ + do \ + { \ + } while (0) #endif -// clang-format on +#if __cplusplus >= 201703L +#define RIVE_MAYBE_UNUSED [[maybe_unused]] +#else +#define RIVE_MAYBE_UNUSED +#endif + +#if __cplusplus >= 201703L +#define RIVE_FALLTHROUGH [[fallthrough]] +#elif defined(__clang__) +#define RIVE_FALLTHROUGH [[clang::fallthrough]] +#else +#define RIVE_FALLTHROUGH +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define RIVE_ALWAYS_INLINE inline __attribute__((always_inline)) +#else +#define RIVE_ALWAYS_INLINE inline +#endif + +#if defined(__GNUC__) || defined(__clang__) +// Recommended in https://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif +#else +#define __has_builtin(x) 0 +#endif + +#if __has_builtin(__builtin_memcpy) +#define RIVE_INLINE_MEMCPY __builtin_memcpy +#else +#define RIVE_INLINE_MEMCPY memcpy +#endif + +// Backports of later stl functions. +namespace rivestd +{ +template <class T, class... Args> std::unique_ptr<T> make_unique(Args&&... args) +{ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} +} // namespace rivestd #endif // rive_types
diff --git a/include/rive/simple_array.hpp b/include/rive/simple_array.hpp index db2ccaf..c295abe 100644 --- a/include/rive/simple_array.hpp +++ b/include/rive/simple_array.hpp
@@ -27,6 +27,41 @@ } // namespace SimpleArrayTesting #endif +// Helper for constructing and destructing arrays of objects. +template <typename T, bool IsPOD = std::is_pod<T>()> class SimpleArrayHelper +{ +public: + static_assert(!std::is_pod<T>(), "This helper is for non-POD types."); + static void DefaultConstructArray(T* ptr, T* end) + { + for (; ptr < end; ++ptr) + new (ptr) T(); + } + static void CopyConstructArray(const T* first, const T* end, T* ptr) + { + for (; first < end; ++first, ++ptr) + new (ptr) T(*first); + } + static void DestructArray(T* ptr, T* end) + { + for (; ptr < end; ++ptr) + ptr->~T(); + } +}; + +// Specialized helper for constructing and destructing arrays of POD objects. +template <typename T> class SimpleArrayHelper<T, true> +{ +public: + static_assert(std::is_pod<T>(), "This helper is only for POD types."); + static void DefaultConstructArray(T* ptr, T* end) {} + static void CopyConstructArray(const T* first, const T* end, T* ptr) + { + memcpy(ptr, first, reinterpret_cast<uintptr_t>(end) - reinterpret_cast<uintptr_t>(first)); + } + static void DestructArray(T* ptr, T* end) {} +}; + /// Lightweight heap array meant to be used when knowing the exact memory layout /// of the simple array is necessary, like marshaling the data to Dart/C#/Wasm. /// Note that it intentionally doesn't have push/add/resize functionality as @@ -41,14 +76,7 @@ SimpleArray() : m_ptr(nullptr), m_size(0) {} SimpleArray(size_t size) : m_ptr(static_cast<T*>(malloc(size * sizeof(T)))), m_size(size) { - if constexpr (!std::is_pod<T>()) - { - for (T *element = m_ptr, *end = m_ptr + m_size; element < end; element++) - { - new (element) T(); - } - } - + SimpleArrayHelper<T>::DefaultConstructArray(m_ptr, m_ptr + m_size); #ifdef TESTING SimpleArrayTesting::mallocCount++; #endif @@ -56,28 +84,18 @@ SimpleArray(const T* ptr, size_t size) : SimpleArray(size) { assert(ptr <= ptr + size); - if constexpr (std::is_pod<T>()) - { - memcpy(m_ptr, ptr, size * sizeof(T)); - } - else - { - for (T *element = m_ptr, *end = m_ptr + m_size; element < end; element++) - { - new (element) T(ptr++); - } - } + SimpleArrayHelper<T>::CopyConstructArray(ptr, ptr + size, m_ptr); } constexpr SimpleArray(const SimpleArray<T>& other) : SimpleArray(other.m_ptr, other.m_size) {} - constexpr SimpleArray(SimpleArray<T>&& other) : m_ptr(other.m_ptr), m_size(other.m_size) + SimpleArray(SimpleArray<T>&& other) : m_ptr(other.m_ptr), m_size(other.m_size) { other.m_ptr = nullptr; other.m_size = 0; } - constexpr SimpleArray(SimpleArrayBuilder<T>&& other); + SimpleArray(SimpleArrayBuilder<T>&& other); SimpleArray<T>& operator=(const SimpleArray<T>& other) = delete; @@ -93,30 +111,20 @@ SimpleArray<T>& operator=(SimpleArrayBuilder<T>&& other); template <typename Container> - constexpr SimpleArray(Container& c) : SimpleArray(std::data(c), std::size(c)) + constexpr SimpleArray(Container& c) : SimpleArray(c.data(), c.size()) {} - constexpr SimpleArray(std::initializer_list<T> il) : SimpleArray(std::data(il), std::size(il)) + constexpr SimpleArray(const std::initializer_list<T>& il) : SimpleArray(il.begin(), il.size()) {} ~SimpleArray() { - if constexpr (!std::is_pod<T>()) - { - for (T *element = m_ptr, *end = m_ptr + m_size; element < end; element++) - { - element->~T(); - } - } + SimpleArrayHelper<T>::DestructArray(m_ptr, m_ptr + m_size); free(m_ptr); #ifdef TESTING SimpleArrayTesting::freeCount++; #endif } - constexpr T& operator[](size_t index) const - { - assert(index < m_size); - return m_ptr[index]; - } + T& operator[](size_t index) const { return m_ptr[index]; } constexpr T* data() const { return m_ptr; } constexpr size_t size() const { return m_size; } @@ -203,25 +211,11 @@ #ifdef TESTING SimpleArrayTesting::reallocCount++; #endif - if constexpr (!std::is_pod<T>()) - { - // Call destructor for elements when sizing down. - for (T *element = this->m_ptr + size, *end = this->m_ptr + this->m_size; element < end; - element++) - { - element->~T(); - } - } + // Call destructor for elements when sizing down. + SimpleArrayHelper<T>::DestructArray(this->m_ptr + size, this->m_ptr + this->m_size); this->m_ptr = static_cast<T*>(realloc(this->m_ptr, size * sizeof(T))); - if constexpr (!std::is_pod<T>()) - { - // Call constructor for elements when sizing up. - for (T *element = this->m_ptr + this->m_size, *end = this->m_ptr + size; element < end; - element++) - { - new (element) T(); - } - } + // Call constructor for elements when sizing up. + SimpleArrayHelper<T>::DefaultConstructArray(this->m_ptr + this->m_size, this->m_ptr + size); this->m_size = size; } @@ -229,7 +223,7 @@ }; template <typename T> -constexpr SimpleArray<T>::SimpleArray(SimpleArrayBuilder<T>&& other) : m_size(other.size()) +SimpleArray<T>::SimpleArray(SimpleArrayBuilder<T>&& other) : m_size(other.size()) { // Bring the capacity down to the actual size (this should keep the same // ptr, but that's not guaranteed, so we copy the ptr after the realloc).
diff --git a/include/rive/span.hpp b/include/rive/span.hpp index 5dac1b5..3dd8ea1 100644 --- a/include/rive/span.hpp +++ b/include/rive/span.hpp
@@ -34,11 +34,9 @@ constexpr Span(const Span<U>& that) : Span(that.data(), that.size()) {} constexpr Span(const Span&) = default; - template <typename Container> constexpr Span(Container& c) : Span{std::data(c), std::size(c)} {} - constexpr Span(std::initializer_list<T> il) : Span(std::data(il), std::size(il)) {} - template <size_t N> constexpr Span(T (&a)[N]) : Span(a, N) {} + template <typename Container> constexpr Span(Container& c) : Span(c.data(), c.size()) {} - constexpr T& operator[](size_t index) const + T& operator[](size_t index) const { assert(index < m_Size); return m_Ptr[index]; @@ -57,14 +55,9 @@ // returns byte-size of the entire span constexpr size_t size_bytes() const { return m_Size * sizeof(T); } - constexpr int count() const - { - const int n = static_cast<int>(m_Size); - assert(n >= 0); - return n; - } + constexpr size_t count() const { return m_Size; } - constexpr Span<T> subset(size_t offset, size_t size) const + Span<T> subset(size_t offset, size_t size) const { assert(offset <= m_Size); assert(size <= m_Size - offset); @@ -82,6 +75,8 @@ typedef size_t size_type; }; +template <typename T> Span<T> make_span(T* ptr, size_t size) { return Span<T>(ptr, size); } + } // namespace rive #endif
diff --git a/src/animation/animation_state.cpp b/src/animation/animation_state.cpp index 342ed42..4e4dcf9 100644 --- a/src/animation/animation_state.cpp +++ b/src/animation/animation_state.cpp
@@ -8,5 +8,5 @@ std::unique_ptr<StateInstance> AnimationState::makeInstance(ArtboardInstance* instance) const { - return std::make_unique<AnimationStateInstance>(this, instance); + return rivestd::make_unique<AnimationStateInstance>(this, instance); }
diff --git a/src/animation/blend_state_1d.cpp b/src/animation/blend_state_1d.cpp index b77422d..ec95728 100644 --- a/src/animation/blend_state_1d.cpp +++ b/src/animation/blend_state_1d.cpp
@@ -8,7 +8,7 @@ std::unique_ptr<StateInstance> BlendState1D::makeInstance(ArtboardInstance* instance) const { - return std::make_unique<BlendState1DInstance>(this, instance); + return rivestd::make_unique<BlendState1DInstance>(this, instance); } StatusCode BlendState1D::import(ImportStack& importStack)
diff --git a/src/animation/blend_state_direct.cpp b/src/animation/blend_state_direct.cpp index 92e96d4..c9b4597 100644 --- a/src/animation/blend_state_direct.cpp +++ b/src/animation/blend_state_direct.cpp
@@ -8,5 +8,5 @@ std::unique_ptr<StateInstance> BlendStateDirect::makeInstance(ArtboardInstance* instance) const { - return std::make_unique<BlendStateDirectInstance>(this, instance); + return rivestd::make_unique<BlendStateDirectInstance>(this, instance); } \ No newline at end of file
diff --git a/src/animation/layer_state.cpp b/src/animation/layer_state.cpp index ffce4ab..173267a 100644 --- a/src/animation/layer_state.cpp +++ b/src/animation/layer_state.cpp
@@ -58,5 +58,5 @@ std::unique_ptr<StateInstance> LayerState::makeInstance(ArtboardInstance* instance) const { - return std::make_unique<SystemStateInstance>(this, instance); + return rivestd::make_unique<SystemStateInstance>(this, instance); } \ No newline at end of file
diff --git a/src/animation/linear_animation.cpp b/src/animation/linear_animation.cpp index f643c7a..9ddfd0a 100644 --- a/src/animation/linear_animation.cpp +++ b/src/animation/linear_animation.cpp
@@ -92,5 +92,5 @@ int direction = ((int)(seconds / (endSeconds() - startSeconds()))) % 2; return direction == 0 ? localTime + startSeconds() : endSeconds() - localTime; } - RIVE_UNREACHABLE; + RIVE_UNREACHABLE(); } \ No newline at end of file
diff --git a/src/animation/nested_linear_animation.cpp b/src/animation/nested_linear_animation.cpp index 069d276..2d53dee 100644 --- a/src/animation/nested_linear_animation.cpp +++ b/src/animation/nested_linear_animation.cpp
@@ -9,5 +9,5 @@ void NestedLinearAnimation::initializeAnimation(ArtboardInstance* artboard) { m_AnimationInstance = - std::make_unique<LinearAnimationInstance>(artboard->animation(animationId()), artboard); + rivestd::make_unique<LinearAnimationInstance>(artboard->animation(animationId()), artboard); } \ No newline at end of file
diff --git a/src/animation/state_machine_instance.cpp b/src/animation/state_machine_instance.cpp index 6ae9f34..e0a7132 100644 --- a/src/animation/state_machine_instance.cpp +++ b/src/animation/state_machine_instance.cpp
@@ -434,7 +434,7 @@ auto shape = m_ArtboardInstance->resolve(id); if (shape != nullptr && shape->is<Shape>()) { - auto hs = std::make_unique<HitShape>(shape->as<Shape>()); + auto hs = rivestd::make_unique<HitShape>(shape->as<Shape>()); hitShapeLookup[id] = hitShape = hs.get(); m_HitShapes.push_back(std::move(hs)); }
diff --git a/src/artboard.cpp b/src/artboard.cpp index 53dbe47..14fd0ea 100644 --- a/src/artboard.cpp +++ b/src/artboard.cpp
@@ -735,25 +735,25 @@ std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationAt(size_t index) { auto la = this->animation(index); - return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr; + return la ? rivestd::make_unique<LinearAnimationInstance>(la, this) : nullptr; } std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationNamed(const std::string& name) { auto la = this->animation(name); - return la ? std::make_unique<LinearAnimationInstance>(la, this) : nullptr; + return la ? rivestd::make_unique<LinearAnimationInstance>(la, this) : nullptr; } std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineAt(size_t index) { auto sm = this->stateMachine(index); - return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr; + return sm ? rivestd::make_unique<StateMachineInstance>(sm, this) : nullptr; } std::unique_ptr<StateMachineInstance> ArtboardInstance::stateMachineNamed(const std::string& name) { auto sm = this->stateMachine(name); - return sm ? std::make_unique<StateMachineInstance>(sm, this) : nullptr; + return sm ? rivestd::make_unique<StateMachineInstance>(sm, this) : nullptr; } std::unique_ptr<StateMachineInstance> ArtboardInstance::defaultStateMachine()
diff --git a/src/math/contour_measure.cpp b/src/math/contour_measure.cpp index 5971a2d..49b5be2 100644 --- a/src/math/contour_measure.cpp +++ b/src/math/contour_measure.cpp
@@ -385,7 +385,8 @@ for (; m_iter != m_end; ++m_iter) { - auto [verb, iterPts] = *m_iter; + PathVerb verb = std::get<0>(*m_iter); + const Vec2D* iterPts = std::get<1>(*m_iter); if (verb == PathVerb::move) { if (!pts.empty()) @@ -439,7 +440,7 @@ } break; case PathVerb::move: - RIVE_UNREACHABLE; // Handled above. + RIVE_UNREACHABLE(); // Handled above. } }
diff --git a/src/math/raw_path.cpp b/src/math/raw_path.cpp index 0cc01a2..1529900 100644 --- a/src/math/raw_path.cpp +++ b/src/math/raw_path.cpp
@@ -270,8 +270,10 @@ void RawPath::addTo(CommandPath* result) const { - for (auto [verb, pts] : *this) + for (auto iter : *this) { + PathVerb verb = std::get<0>(iter); + const Vec2D* pts = std::get<1>(iter); switch (verb) { case PathVerb::move: @@ -287,7 +289,7 @@ result->close(); break; case PathVerb::quad: - RIVE_UNREACHABLE; + RIVE_UNREACHABLE(); } } }
diff --git a/src/shapes/path.cpp b/src/shapes/path.cpp index bcb4aca..902980a 100644 --- a/src/shapes/path.cpp +++ b/src/shapes/path.cpp
@@ -351,7 +351,7 @@ deletePrevious = true; break; } - [[fallthrough]]; + RIVE_FALLTHROUGH; } default: if (deletePrevious)
diff --git a/tess/src/sokol/sokol_tess_renderer.cpp b/tess/src/sokol/sokol_tess_renderer.cpp index c01de67..5078ec1 100644 --- a/tess/src/sokol/sokol_tess_renderer.cpp +++ b/tess/src/sokol/sokol_tess_renderer.cpp
@@ -141,12 +141,12 @@ // Returns a full-formed RenderPath -- can be treated as immutable std::unique_ptr<RenderPath> SokolFactory::makeRenderPath(RawPath& rawPath, FillRule rule) { - return std::make_unique<SokolRenderPath>(rawPath, rule); + return rivestd::make_unique<SokolRenderPath>(rawPath, rule); } std::unique_ptr<RenderPath> SokolFactory::makeEmptyRenderPath() { - return std::make_unique<SokolRenderPath>(); + return rivestd::make_unique<SokolRenderPath>(); } class SokolBuffer : public RenderBuffer @@ -740,7 +740,7 @@ m_strokeDirty = false; break; case RenderPaintStyle::stroke: - m_stroke = std::make_unique<ContourStroke>(); + m_stroke = rivestd::make_unique<ContourStroke>(); m_strokeDirty = true; break; } @@ -897,7 +897,7 @@ std::unique_ptr<RenderPaint> SokolFactory::makeRenderPaint() { - return std::make_unique<SokolRenderPaint>(); + return rivestd::make_unique<SokolRenderPaint>(); } void SokolTessRenderer::restore()
diff --git a/test/binary_reader_test.cpp b/test/binary_reader_test.cpp index bb43a84..da924fb 100644 --- a/test/binary_reader_test.cpp +++ b/test/binary_reader_test.cpp
@@ -40,7 +40,7 @@ uint8_t* p = storage; p = packvarint(storage, value); - rive::BinaryReader reader(rive::Span(storage, p - storage)); + rive::BinaryReader reader(rive::make_span(storage, p - storage)); auto newValue = reader.readVarUintAs<T>();
diff --git a/test/clip_test.cpp b/test/clip_test.cpp index e040633..9185294 100644 --- a/test/clip_test.cpp +++ b/test/clip_test.cpp
@@ -50,7 +50,7 @@ std::unique_ptr<rive::RenderPath> makeRenderPath(rive::RawPath& rawPath, rive::FillRule) override { - return std::make_unique<ClipTestRenderPath>(rawPath); + return rivestd::make_unique<ClipTestRenderPath>(rawPath); } };
diff --git a/test/contour_measure_test.cpp b/test/contour_measure_test.cpp index aa6c77c..abf0635 100644 --- a/test/contour_measure_test.cpp +++ b/test/contour_measure_test.cpp
@@ -87,7 +87,7 @@ {3, 0}, {3, 4}, }; - auto span = Span(pts, sizeof(pts) / sizeof(pts[0])); + auto span = make_span(pts, sizeof(pts) / sizeof(pts[0])); // We expect 3 measurable contours out of this: 7, 16, 7 // the others should be skipped since they are empty (len == 0)
diff --git a/test/hittest_test.cpp b/test/hittest_test.cpp index 46e461e..fa87032 100644 --- a/test/hittest_test.cpp +++ b/test/hittest_test.cpp
@@ -55,5 +55,5 @@ 1, 2, }; - REQUIRE(HitTester::testMesh(area, Span(verts, 3), Span(indices, 3))); + REQUIRE(HitTester::testMesh(area, make_span(verts, 3), make_span(indices, 3))); }
diff --git a/test/mat2d_test.cpp b/test/mat2d_test.cpp index 1d68cd8..c21df78 100644 --- a/test/mat2d_test.cpp +++ b/test/mat2d_test.cpp
@@ -107,12 +107,14 @@ // success = givingNegativeNearlyZeros.getMinMaxScales(scales); // CHECK(success && 0 == scales[0]); - Mat2D baseMats[] = {scale, rot90Scale, rotate, translate}; - Mat2D mats[2 * std::size(baseMats)]; - for (size_t i = 0; i < std::size(baseMats); ++i) + constexpr int kNumBaseMats = 4; + Mat2D baseMats[kNumBaseMats] = {scale, rot90Scale, rotate, translate}; + constexpr int kNumMats = 2 * kNumBaseMats; + Mat2D mats[kNumMats]; + for (size_t i = 0; i < kNumBaseMats; ++i) { mats[i] = baseMats[i]; - bool invertible = mats[i].invert(&mats[i + std::size(baseMats)]); + bool invertible = mats[i].invert(&mats[i + kNumBaseMats]); REQUIRE(invertible); } srand(0); @@ -121,7 +123,7 @@ Mat2D mat; for (int i = 0; i < 4; ++i) { - int x = rand() % std::size(mats); + int x = rand() % kNumMats; mat = mats[x] * mat; } @@ -135,8 +137,9 @@ static const float gVectorScaleTol = (105 * 1.f) / 100; static const float gCloseScaleTol = (97 * 1.f) / 100; float max = 0, min = std::numeric_limits<float>::max(); - Vec2D vectors[1000]; - for (size_t i = 0; i < std::size(vectors); ++i) + constexpr int kNumVectors = 1000; + Vec2D vectors[kNumVectors]; + for (size_t i = 0; i < kNumVectors; ++i) { vectors[i].x = rand() * 2.f / static_cast<float>(RAND_MAX) - 1; vectors[i].y = rand() * 2.f / static_cast<float>(RAND_MAX) - 1; @@ -144,7 +147,7 @@ vectors[i] = {mat[0] * vectors[i].x + mat[2] * vectors[i].y, mat[1] * vectors[i].x + mat[3] * vectors[i].y}; } - for (size_t i = 0; i < std::size(vectors); ++i) + for (size_t i = 0; i < kNumVectors; ++i) { float d = vectors[i].length(); REQUIRE(d / maxScale < gVectorScaleTol);
diff --git a/test/path_test.cpp b/test/path_test.cpp index 673c54d..bfc6a33 100644 --- a/test/path_test.cpp +++ b/test/path_test.cpp
@@ -75,7 +75,7 @@ public: std::unique_ptr<rive::RenderPath> makeEmptyRenderPath() override { - return std::make_unique<TestRenderPath>(); + return rivestd::make_unique<TestRenderPath>(); } }; } // namespace
diff --git a/test/raw_path_test.cpp b/test/raw_path_test.cpp index 0eca6c3..815ba2e 100644 --- a/test/raw_path_test.cpp +++ b/test/raw_path_test.cpp
@@ -91,7 +91,8 @@ std::vector<Vec2D> expectedPts) { REQUIRE(iter != end); - auto [verb, pts] = *iter; + PathVerb verb = std::get<0>(*iter); + const Vec2D* pts = std::get<1>(*iter); REQUIRE(verb == expectedVerb); for (size_t i = 0; i < expectedPts.size(); ++i) { @@ -113,7 +114,8 @@ rp.quadTo(5, 6, 7, 8); rp.cubicTo(9, 10, 11, 12, 13, 14); rp.close(); - auto [iter, end] = std::make_tuple(rp.begin(), rp.end()); + auto iter = rp.begin(); + auto end = rp.end(); check_iter(iter, end, PathVerb::move, {{1, 2}}); check_iter(iter, end, PathVerb::line, {{1, 2}, {3, 4}}); check_iter(iter, end, PathVerb::quad, {{3, 4}, {5, 6}, {7, 8}});
diff --git a/test/simd_test.cpp b/test/simd_test.cpp index 0ac8a64..2fff755 100644 --- a/test/simd_test.cpp +++ b/test/simd_test.cpp
@@ -289,8 +289,6 @@ // Returns lo if x == NaN, but std::clamp() returns NaN. CHECK(simd::clamp<float, 1>(kNaN, 1, 2).x == 1); - CHECK(std::clamp<float>(kNaN, 1, 2) != 1); - CHECK(std::isnan(std::clamp<float>(kNaN, 1, 2))); // Returns hi if hi <= lo. CHECK(simd::clamp<float, 1>(3, 2, 1).x == 1);
diff --git a/test/simple_array_test.cpp b/test/simple_array_test.cpp index 9b4e206..82b5fc2 100644 --- a/test/simple_array_test.cpp +++ b/test/simple_array_test.cpp
@@ -19,7 +19,8 @@ TEST_CASE("simple array can be created", "[simple array]") { - SimpleArray<int> array({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + SimpleArray<int> array(v); REQUIRE(!array.empty()); REQUIRE(array.size() == 10); @@ -40,7 +41,7 @@ TEST_CASE("can iterate simple array", "[simple array]") { const int carray[] = {2, 4, 8, 16}; - SimpleArray<int> array(carray); + SimpleArray<int> array(carray, 4); int expect = 2; for (auto value : array) { @@ -89,7 +90,8 @@ { SimpleArrayTesting::resetCounters(); - SimpleArray<uint32_t> numbersA({33, 22, 44, 66}); + std::vector<uint32_t> vA{33, 22, 44, 66}; + SimpleArray<uint32_t> numbersA(vA); StructA dataA = {std::move(numbersA)}; // We moved the data so expect only one alloc and 0 reallocs. @@ -98,7 +100,8 @@ REQUIRE(dataA.numbers.size() == 4); REQUIRE(numbersA.size() == 0); - SimpleArray<uint32_t> numbersB({1, 2, 3}); + std::vector<uint32_t> vB{1, 2, 3}; + SimpleArray<uint32_t> numbersB(vB); StructA dataB = {std::move(numbersB)}; REQUIRE(SimpleArrayTesting::mallocCount == 2);
diff --git a/test/span_test.cpp b/test/span_test.cpp index a2ddfb6..874b766 100644 --- a/test/span_test.cpp +++ b/test/span_test.cpp
@@ -55,9 +55,7 @@ funcb({carray, 4}); int array[] = {1, 2, 3, 4}; - funca(array); funca({array, 4}); - funcb(array); funcb({array, 4}); std::vector<int> v; @@ -69,7 +67,7 @@ { const int carray[] = {2, 4, 8, 16}; - auto span = Span(carray); + auto span = make_span(carray, 4); int expect = 2; for (auto value : span) {
diff --git a/utils/no_op_factory.cpp b/utils/no_op_factory.cpp index 9058301..2178aba 100644 --- a/utils/no_op_factory.cpp +++ b/utils/no_op_factory.cpp
@@ -66,17 +66,17 @@ std::unique_ptr<RenderPath> NoOpFactory::makeRenderPath(RawPath&, FillRule) { - return std::make_unique<NoOpRenderPath>(); + return rivestd::make_unique<NoOpRenderPath>(); } std::unique_ptr<RenderPath> NoOpFactory::makeEmptyRenderPath() { - return std::make_unique<NoOpRenderPath>(); + return rivestd::make_unique<NoOpRenderPath>(); } std::unique_ptr<RenderPaint> NoOpFactory::makeRenderPaint() { - return std::make_unique<NoOpRenderPaint>(); + return rivestd::make_unique<NoOpRenderPaint>(); } std::unique_ptr<RenderImage> NoOpFactory::decodeImage(Span<const uint8_t>)
diff --git a/viewer/src/sample_tools/sample_atlas_packer.cpp b/viewer/src/sample_tools/sample_atlas_packer.cpp index b9a6f88..5848ef7 100644 --- a/viewer/src/sample_tools/sample_atlas_packer.cpp +++ b/viewer/src/sample_tools/sample_atlas_packer.cpp
@@ -40,9 +40,9 @@ bitmap->pixelFormat(Bitmap::PixelFormat::RGBA); } - return std::make_unique<AtlasRenderImage>(bitmap->bytes(), - bitmap->width(), - bitmap->height()); + return rivestd::make_unique<AtlasRenderImage>(bitmap->bytes(), + bitmap->width(), + bitmap->height()); } return nullptr; } @@ -236,10 +236,10 @@ // renderer (and hence will know which RenderImage they need to // make). - imageAsset->renderImage(std::make_unique<SokolRenderImage>(imageResource, - location.width, - location.height, - location.transform)); + imageAsset->renderImage(rivestd::make_unique<SokolRenderImage>(imageResource, + location.width, + location.height, + location.transform)); } } }
diff --git a/viewer/src/skia/skia_host.cpp b/viewer/src/skia/skia_host.cpp index 2c44b6b..a24e4d8 100644 --- a/viewer/src/skia/skia_host.cpp +++ b/viewer/src/skia/skia_host.cpp
@@ -121,7 +121,7 @@ } }; -std::unique_ptr<ViewerHost> ViewerHost::Make() { return std::make_unique<SkiaViewerHost>(); } +std::unique_ptr<ViewerHost> ViewerHost::Make() { return rivestd::make_unique<SkiaViewerHost>(); } rive::Factory* ViewerHost::Factory() {
diff --git a/viewer/src/tess/bitmap_decoder.cpp b/viewer/src/tess/bitmap_decoder.cpp index 112f9d1..cd4a286 100644 --- a/viewer/src/tess/bitmap_decoder.cpp +++ b/viewer/src/tess/bitmap_decoder.cpp
@@ -100,7 +100,7 @@ return; } auto nextByteSize = byteSize(format); - auto nextBytes = std::make_unique<uint8_t[]>(nextByteSize); + auto nextBytes = rivestd::make_unique<uint8_t[]>(nextByteSize); auto fromBytesPerPixel = bytesPerPixel(m_PixelFormat); auto toBytesPerPixel = bytesPerPixel(format);
diff --git a/viewer/src/tess/decode_png.cpp b/viewer/src/tess/decode_png.cpp index 1a7a6b0..63998f4 100644 --- a/viewer/src/tess/decode_png.cpp +++ b/viewer/src/tess/decode_png.cpp
@@ -135,6 +135,6 @@ pixelFormat = Bitmap::PixelFormat::R; break; } - return std::make_unique<Bitmap>(width, height, pixelFormat, pixelBuffer); + return rivestd::make_unique<Bitmap>(width, height, pixelFormat, pixelBuffer); } #endif \ No newline at end of file
diff --git a/viewer/src/tess/tess_host.cpp b/viewer/src/tess/tess_host.cpp index b25a345..416f910 100644 --- a/viewer/src/tess/tess_host.cpp +++ b/viewer/src/tess/tess_host.cpp
@@ -17,7 +17,7 @@ bool init(sg_pass_action*, int width, int height) override { - m_renderer = std::make_unique<rive::SokolTessRenderer>(); + m_renderer = rivestd::make_unique<rive::SokolTessRenderer>(); m_renderer->orthographicProjection(0.0f, width, height, 0.0f, 0.0f, 1.0f); return true; } @@ -37,7 +37,7 @@ } }; -std::unique_ptr<ViewerHost> ViewerHost::Make() { return std::make_unique<TessViewerHost>(); } +std::unique_ptr<ViewerHost> ViewerHost::Make() { return rivestd::make_unique<TessViewerHost>(); } rive::Factory* ViewerHost::Factory() {
diff --git a/viewer/src/tess/viewer_sokol_factory.cpp b/viewer/src/tess/viewer_sokol_factory.cpp index bc0b6fb..a403693 100644 --- a/viewer/src/tess/viewer_sokol_factory.cpp +++ b/viewer/src/tess/viewer_sokol_factory.cpp
@@ -26,10 +26,10 @@ new rive::SokolRenderImageResource(bitmap->bytes(), bitmap->width(), bitmap->height())); static rive::Mat2D identity; - return std::make_unique<rive::SokolRenderImage>(imageGpuResource, - bitmap->width(), - bitmap->height(), - identity); + return rivestd::make_unique<rive::SokolRenderImage>(imageGpuResource, + bitmap->width(), + bitmap->height(), + identity); } return nullptr; }
diff --git a/viewer/src/viewer_content/image_content.cpp b/viewer/src/viewer_content/image_content.cpp index 055c038..ab24415 100644 --- a/viewer/src/viewer_content/image_content.cpp +++ b/viewer/src/viewer_content/image_content.cpp
@@ -28,7 +28,7 @@ auto image = RiveFactory()->decodeImage(bytes); if (image) { - return std::make_unique<ImageContent>(std::move(image)); + return rivestd::make_unique<ImageContent>(std::move(image)); } return nullptr; }
diff --git a/viewer/src/viewer_content/scene_content.cpp b/viewer/src/viewer_content/scene_content.cpp index 6bd1129..196000f 100644 --- a/viewer/src/viewer_content/scene_content.cpp +++ b/viewer/src/viewer_content/scene_content.cpp
@@ -386,7 +386,7 @@ auto bytes = LoadFile(filename); if (auto file = rive::File::import(bytes, RiveFactory())) { - return std::make_unique<SceneContent>(filename, std::move(file)); + return rivestd::make_unique<SceneContent>(filename, std::move(file)); } return nullptr; } \ No newline at end of file
diff --git a/viewer/src/viewer_content/text_content.cpp b/viewer/src/viewer_content/text_content.cpp index fecc4b1..a84612f 100644 --- a/viewer/src/viewer_content/text_content.cpp +++ b/viewer/src/viewer_content/text_content.cpp
@@ -392,7 +392,7 @@ { if (ends_width(filename, ".svg")) { - return std::make_unique<TextContent>(); + return rivestd::make_unique<TextContent>(); } return nullptr; }
diff --git a/viewer/src/viewer_content/textpath_content.cpp b/viewer/src/viewer_content/textpath_content.cpp index 0b78ae6..4f90389 100644 --- a/viewer/src/viewer_content/textpath_content.cpp +++ b/viewer/src/viewer_content/textpath_content.cpp
@@ -402,7 +402,7 @@ std::unique_ptr<ViewerContent> ViewerContent::TextPath(const char filename[]) { - return std::make_unique<TextPathContent>(); + return rivestd::make_unique<TextPathContent>(); } #else std::unique_ptr<ViewerContent> ViewerContent::TextPath(const char filename[]) { return nullptr; }
diff --git a/viewer/src/viewer_content/trimpath_content.cpp b/viewer/src/viewer_content/trimpath_content.cpp index f72bd4a..2f4dac2 100644 --- a/viewer/src/viewer_content/trimpath_content.cpp +++ b/viewer/src/viewer_content/trimpath_content.cpp
@@ -170,5 +170,5 @@ std::unique_ptr<ViewerContent> ViewerContent::TrimPath(const char[]) { - return std::make_unique<TrimPathContent>(); + return rivestd::make_unique<TrimPathContent>(); }