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
This commit is contained in:
csmartdalton
2022-12-06 17:32:09 +00:00
parent 1a4db8761b
commit 28ffb1b138
44 changed files with 270 additions and 241 deletions

View File

@@ -1 +1 @@
de4fe4d71a1eeef8e135991ca395c3159b42dc0d
312a6c77883aaf469214e1dffc6953d4e82ace8c

View File

@@ -40,7 +40,7 @@ project 'rive'
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}'

View File

@@ -23,7 +23,7 @@ project('tests')
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}'

View File

@@ -7,6 +7,7 @@
#include "rive/rive_types.hpp"
#include <cmath>
#include <limits>
#include <string.h>
namespace rive
@@ -17,13 +18,13 @@ namespace math
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 @@ constexpr float EPSILON = 1.f / (1 << 12); // Common threshold for detecting val
//
// 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 @@ inline static float
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

View File

@@ -14,6 +14,7 @@
#include <cmath>
#include <stdio.h>
#include <cstdint>
#include <tuple>
#include <vector>
namespace rive
@@ -108,7 +109,7 @@ public:
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 @@ public:
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 @@ public:
case PathVerb::close:
return -1;
}
RIVE_UNREACHABLE;
RIVE_UNREACHABLE();
}
const PathVerb* m_verbs;
@@ -158,8 +159,10 @@ public:
{
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:

View File

@@ -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 @@ static_assert(std::numeric_limits<float>::is_iec559,
#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 @@ using gvec = T __attribute__((ext_vector_type(N))) __attribute__((aligned(sizeof
#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 @@ namespace simd
//
// 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 @@ template <int N> SIMD_ALWAYS_INLINE bool any(gvec<int32_t, N> x)
}
// 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 <int N> SIMD_ALWAYS_INLINE bool all(gvec<int32_t, N> x)
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 @@ constexpr gvec<int32_t, N> isnan(gvec<T, N>)
// 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 @@ SIMD_ALWAYS_INLINE gvec<T, N> if_then_else(gvec<int32_t, N> _if, gvec<T, N> _the
// 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 @@ template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> min(gvec<T, N> a, gve
// 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 @@ template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> max(gvec<T, N> a, gve
// 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 @@ template <typename T, int N> SIMD_ALWAYS_INLINE gvec<T, N> abs(gvec<T, N> x)
////// 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 @@ template <int N> SIMD_ALWAYS_INLINE gvec<float, N> floor(gvec<float, N> x)
#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 @@ template <int N> SIMD_ALWAYS_INLINE gvec<float, N> ceil(gvec<float, N> x)
}
// 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 @@ template <int N> SIMD_ALWAYS_INLINE gvec<float, N> sqrt(gvec<float, N> x)
}
#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 @@ template <> SIMD_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x)
// 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 @@ template <> SIMD_ALWAYS_INLINE gvec<float, 2> sqrt(gvec<float, 2> x)
//
// 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 @@ template <int N> SIMD_ALWAYS_INLINE gvec<float, N> fast_acos(gvec<float, N> x)
////// 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 @@ template <typename T, int N> SIMD_ALWAYS_INLINE T dot(gvec<T, N> a, gvec<T, N> b
// 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 @@ SIMD_ALWAYS_INLINE float cross(gvec<float, 2> a, gvec<float, 2> b)
// 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 @@ SIMD_ALWAYS_INLINE gvec<float, N> mix(gvec<float, N> a, gvec<float, N> b, gvec<f
} // namespace simd
} // namespace rive
#undef SIMD_ALWAYS_INLINE
#undef SIMD_INLINE_MEMCPY
#undef RIVE_INLINE_MEMCPY
namespace rive
{

View File

@@ -143,10 +143,9 @@ template <typename T, int N> struct gvec<T, N, 0> : public gvec_data<T, N>
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) \

View File

@@ -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

View File

@@ -27,6 +27,41 @@ void resetCounters();
} // 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 @@ public:
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 @@ public:
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 @@ public:
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 @@ private:
#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 @@ private:
};
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).

View File

@@ -34,11 +34,9 @@ public:
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 @@ public:
// 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 @@ public:
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

View File

@@ -8,5 +8,5 @@ using namespace rive;
std::unique_ptr<StateInstance> AnimationState::makeInstance(ArtboardInstance* instance) const
{
return std::make_unique<AnimationStateInstance>(this, instance);
return rivestd::make_unique<AnimationStateInstance>(this, instance);
}

View File

@@ -8,7 +8,7 @@ using namespace rive;
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)

View File

@@ -8,5 +8,5 @@ using namespace rive;
std::unique_ptr<StateInstance> BlendStateDirect::makeInstance(ArtboardInstance* instance) const
{
return std::make_unique<BlendStateDirectInstance>(this, instance);
return rivestd::make_unique<BlendStateDirectInstance>(this, instance);
}

View File

@@ -58,5 +58,5 @@ void LayerState::addTransition(StateTransition* transition) { m_Transitions.push
std::unique_ptr<StateInstance> LayerState::makeInstance(ArtboardInstance* instance) const
{
return std::make_unique<SystemStateInstance>(this, instance);
return rivestd::make_unique<SystemStateInstance>(this, instance);
}

View File

@@ -92,5 +92,5 @@ float LinearAnimation::globalToLocalSeconds(float seconds) const
int direction = ((int)(seconds / (endSeconds() - startSeconds()))) % 2;
return direction == 0 ? localTime + startSeconds() : endSeconds() - localTime;
}
RIVE_UNREACHABLE;
RIVE_UNREACHABLE();
}

View File

@@ -9,5 +9,5 @@ NestedLinearAnimation::~NestedLinearAnimation() {}
void NestedLinearAnimation::initializeAnimation(ArtboardInstance* artboard)
{
m_AnimationInstance =
std::make_unique<LinearAnimationInstance>(artboard->animation(animationId()), artboard);
rivestd::make_unique<LinearAnimationInstance>(artboard->animation(animationId()), artboard);
}

View File

@@ -434,7 +434,7 @@ StateMachineInstance::StateMachineInstance(const StateMachine* machine,
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));
}

View File

@@ -735,25 +735,25 @@ ArtboardInstance::~ArtboardInstance() { Counter::update(Counter::kArtboardInstan
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()

View File

@@ -385,7 +385,8 @@ rcp<ContourMeasure> ContourMeasureIter::tryNext()
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 @@ rcp<ContourMeasure> ContourMeasureIter::tryNext()
}
break;
case PathVerb::move:
RIVE_UNREACHABLE; // Handled above.
RIVE_UNREACHABLE(); // Handled above.
}
}

View File

@@ -270,8 +270,10 @@ void RawPath::rewind()
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 @@ void RawPath::addTo(CommandPath* result) const
result->close();
break;
case PathVerb::quad:
RIVE_UNREACHABLE;
RIVE_UNREACHABLE();
}
}
}

View File

@@ -351,7 +351,7 @@ FlattenedPath* Path::makeFlat(bool transformToParent)
deletePrevious = true;
break;
}
[[fallthrough]];
RIVE_FALLTHROUGH;
}
default:
if (deletePrevious)

View File

@@ -141,12 +141,12 @@ public:
// 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 @@ public:
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 @@ public:
std::unique_ptr<RenderPaint> SokolFactory::makeRenderPaint()
{
return std::make_unique<SokolRenderPaint>();
return rivestd::make_unique<SokolRenderPaint>();
}
void SokolTessRenderer::restore()

View File

@@ -40,7 +40,7 @@ template <typename T> bool checkAs(uint64_t value)
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>();

View File

@@ -50,7 +50,7 @@ class ClippingFactory : public rive::NoOpFactory
std::unique_ptr<rive::RenderPath> makeRenderPath(rive::RawPath& rawPath,
rive::FillRule) override
{
return std::make_unique<ClipTestRenderPath>(rawPath);
return rivestd::make_unique<ClipTestRenderPath>(rawPath);
}
};

View File

@@ -87,7 +87,7 @@ TEST_CASE("multi-contours", "[contourmeasure]")
{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)

View File

@@ -55,5 +55,5 @@ TEST_CASE("hittest-mesh", "[hittest]")
1,
2,
};
REQUIRE(HitTester::testMesh(area, Span(verts, 3), Span(indices, 3)));
REQUIRE(HitTester::testMesh(area, make_span(verts, 3), make_span(indices, 3)));
}

View File

@@ -107,12 +107,14 @@ TEST_CASE("findMaxScale", "[Mat2D]")
// 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 @@ TEST_CASE("findMaxScale", "[Mat2D]")
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 @@ TEST_CASE("findMaxScale", "[Mat2D]")
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 @@ TEST_CASE("findMaxScale", "[Mat2D]")
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);

View File

@@ -75,7 +75,7 @@ class TestNoOpFactory : public rive::NoOpFactory
public:
std::unique_ptr<rive::RenderPath> makeEmptyRenderPath() override
{
return std::make_unique<TestRenderPath>();
return rivestd::make_unique<TestRenderPath>();
}
};
} // namespace

View File

@@ -91,7 +91,8 @@ static void check_iter(RawPath::Iter& iter,
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 @@ TEST_CASE("rawpath-iter", "[rawpath]")
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}});

View File

@@ -289,8 +289,6 @@ TEST_CASE("clamp", "[simd]")
// 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);

View File

@@ -19,7 +19,8 @@ TEST_CASE("array initializes as expected", "[simple array]")
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("simple array can be created", "[simple array]")
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 @@ static SimpleArray<StructA> buildStructs()
{
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 @@ static SimpleArray<StructA> buildStructs()
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);

View File

@@ -55,9 +55,7 @@ TEST_CASE("const-and-containers", "[span]")
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 @@ TEST_CASE("can iterate span", "[span]")
{
const int carray[] = {2, 4, 8, 16};
auto span = Span(carray);
auto span = make_span(carray, 4);
int expect = 2;
for (auto value : span)
{

View File

@@ -66,17 +66,17 @@ rcp<RenderShader> NoOpFactory::makeRadialGradient(float cx,
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>)

View File

@@ -40,9 +40,9 @@ class AtlasPackerFactory : public NoOpFactory
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 @@ void SampleAtlasResolver::loadContents(FileAsset& asset)
// 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));
}
}
}

View File

@@ -121,7 +121,7 @@ public:
}
};
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()
{

View File

@@ -100,7 +100,7 @@ void Bitmap::pixelFormat(PixelFormat format)
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);

View File

@@ -135,6 +135,6 @@ std::unique_ptr<Bitmap> DecodePng(rive::Span<const uint8_t> bytes)
pixelFormat = Bitmap::PixelFormat::R;
break;
}
return std::make_unique<Bitmap>(width, height, pixelFormat, pixelBuffer);
return rivestd::make_unique<Bitmap>(width, height, pixelFormat, pixelBuffer);
}
#endif

View File

@@ -17,7 +17,7 @@ public:
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 @@ public:
}
};
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()
{

View File

@@ -26,10 +26,10 @@ std::unique_ptr<rive::RenderImage> ViewerSokolFactory::decodeImage(rive::Span<co
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;
}

View File

@@ -28,7 +28,7 @@ std::unique_ptr<ViewerContent> ViewerContent::Image(const char filename[])
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;
}

View File

@@ -386,7 +386,7 @@ std::unique_ptr<ViewerContent> ViewerContent::Scene(const char filename[])
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;
}

View File

@@ -392,7 +392,7 @@ std::unique_ptr<ViewerContent> ViewerContent::Text(const char filename[])
{
if (ends_width(filename, ".svg"))
{
return std::make_unique<TextContent>();
return rivestd::make_unique<TextContent>();
}
return nullptr;
}

View File

@@ -402,7 +402,7 @@ public:
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; }

View File

@@ -170,5 +170,5 @@ public:
std::unique_ptr<ViewerContent> ViewerContent::TrimPath(const char[])
{
return std::make_unique<TrimPathContent>();
return rivestd::make_unique<TrimPathContent>();
}