mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
clang-format the universe
find . -name '*.c' -o -name '*.cpp' -o -name '*.cc'-o \
-name '*.h' -o -name '*.hpp' \
| xargs clang-format --style=file -i
Diffs=
c885b0ffd clang-format the universe
This commit is contained in:
@@ -1 +1 @@
|
||||
3f2972fe3f004c4afe35960517d701d100a6a406
|
||||
c885b0ffdf19f2d4b90ed6538ac8463842d24e0d
|
||||
|
||||
@@ -25,8 +25,7 @@ namespace rive {
|
||||
|
||||
BlendStateAnimationInstance(const T* blendAnimation, ArtboardInstance* instance) :
|
||||
m_BlendAnimation(blendAnimation),
|
||||
m_AnimationInstance(blendAnimation->animation(), instance)
|
||||
{}
|
||||
m_AnimationInstance(blendAnimation->animation(), instance) {}
|
||||
|
||||
void mix(float value) { m_Mix = value; }
|
||||
};
|
||||
@@ -37,9 +36,10 @@ namespace rive {
|
||||
bool m_KeepGoing = true;
|
||||
|
||||
public:
|
||||
BlendStateInstance(const K* blendState, ArtboardInstance* instance) : StateInstance(blendState) {
|
||||
BlendStateInstance(const K* blendState, ArtboardInstance* instance) :
|
||||
StateInstance(blendState) {
|
||||
m_AnimationInstances.reserve(blendState->animations().size());
|
||||
|
||||
|
||||
for (auto blendAnimation : blendState->animations()) {
|
||||
m_AnimationInstances.emplace_back(
|
||||
BlendStateAnimationInstance<T>(static_cast<T*>(blendAnimation), instance));
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace rive {
|
||||
|
||||
class LinearAnimation : public LinearAnimationBase {
|
||||
private:
|
||||
std::vector< std::unique_ptr<KeyedObject> > m_KeyedObjects;
|
||||
std::vector<std::unique_ptr<KeyedObject>> m_KeyedObjects;
|
||||
|
||||
friend class Artboard;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace rive {
|
||||
// Advance the animation by the specified time. Returns true if the
|
||||
// animation will continue to animate after this advance.
|
||||
bool advance(float seconds);
|
||||
|
||||
|
||||
// Returns a pointer to the instance's animation
|
||||
const LinearAnimation* animation() const { return m_Animation; }
|
||||
|
||||
@@ -53,9 +53,7 @@ namespace rive {
|
||||
// Applies the animation instance to its artboard instance. The mix (a value
|
||||
// between 0 and 1) is the strength at which the animation is mixed with
|
||||
// other animations applied to the artboard.
|
||||
void apply(float mix = 1.0f) const {
|
||||
m_Animation->apply(m_ArtboardInstance, m_Time, mix);
|
||||
}
|
||||
void apply(float mix = 1.0f) const { m_Animation->apply(m_ArtboardInstance, m_Time, mix); }
|
||||
|
||||
// Set when the animation is advanced, true if the animation has stopped
|
||||
// (oneShot), reached the end (loop), or changed direction (pingPong)
|
||||
@@ -71,7 +69,7 @@ namespace rive {
|
||||
uint32_t duration() const;
|
||||
float speed() const;
|
||||
float startSeconds() const;
|
||||
|
||||
|
||||
// Returns either the animation's default or overridden loop values
|
||||
Loop loop() const override { return (Loop)loopValue(); }
|
||||
int loopValue() const;
|
||||
|
||||
@@ -34,9 +34,7 @@ namespace rive {
|
||||
|
||||
void move(Vec2D v) { this->moveTo(v.x, v.y); }
|
||||
void line(Vec2D v) { this->lineTo(v.x, v.y); }
|
||||
void cubic(Vec2D a, Vec2D b, Vec2D c) {
|
||||
this->cubicTo(a.x, a.y, b.x, b.y, c.x, c.y);
|
||||
}
|
||||
void cubic(Vec2D a, Vec2D b, Vec2D c) { this->cubicTo(a.x, a.y, b.x, b.y, c.x, c.y); }
|
||||
};
|
||||
} // namespace rive
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace rive {
|
||||
uint8_t readByte();
|
||||
uint32_t readUint32();
|
||||
uint64_t readVarUint64(); // Reads a LEB128 encoded uint64_t
|
||||
|
||||
|
||||
// This will cast the uint read to the requested size, but if the
|
||||
// raw value was out-of-range, instead returns 0 and sets the IntRangeError.
|
||||
template <typename T> T readVarUintAs() {
|
||||
|
||||
@@ -10,17 +10,16 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
template <typename T> bool fitsIn(intmax_t x) {
|
||||
return x >= std::numeric_limits<T>::min() &&
|
||||
x <= std::numeric_limits<T>::max();
|
||||
}
|
||||
template <typename T> bool fitsIn(intmax_t x) {
|
||||
return x >= std::numeric_limits<T>::min() && x <= std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <typename T> T castTo(intmax_t x) {
|
||||
assert(sizeof(T) <= 4); // don't cast to 64bit types
|
||||
assert(fitsIn<T>(x));
|
||||
return static_cast<T>(x);
|
||||
}
|
||||
template <typename T> T castTo(intmax_t x) {
|
||||
assert(sizeof(T) <= 4); // don't cast to 64bit types
|
||||
assert(fitsIn<T>(x));
|
||||
return static_cast<T>(x);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,25 +27,28 @@ namespace rive {
|
||||
virtual rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) = 0;
|
||||
virtual rcp<RenderBuffer> makeBufferF32(Span<const float>) = 0;
|
||||
|
||||
virtual rcp<RenderShader> makeLinearGradient(float sx, float sy,
|
||||
float ex, float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
virtual rcp<RenderShader> makeLinearGradient(float sx,
|
||||
float sy,
|
||||
float ex,
|
||||
float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) = 0;
|
||||
|
||||
virtual rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
virtual rcp<RenderShader> makeRadialGradient(float cx,
|
||||
float cy,
|
||||
float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) = 0;
|
||||
|
||||
// Returns a full-formed RenderPath -- can be treated as immutable
|
||||
virtual std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
|
||||
Span<const uint8_t> verbs,
|
||||
FillRule) = 0;
|
||||
virtual std::unique_ptr<RenderPath>
|
||||
makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule) = 0;
|
||||
|
||||
virtual std::unique_ptr<RenderPath> makeEmptyRenderPath() = 0;
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace rive {
|
||||
/// @returns a pointer to the file, or null on failure.
|
||||
static std::unique_ptr<File> import(Span<const uint8_t> data,
|
||||
Factory*,
|
||||
ImportResult* result = nullptr,
|
||||
ImportResult* result = nullptr,
|
||||
FileAssetResolver* assetResolver = nullptr);
|
||||
|
||||
/// @returns the file's backboard. All files have exactly one backboard.
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace rive {
|
||||
(void)invert(&inverse); // inverse is unchanged if invert() fails
|
||||
return inverse;
|
||||
}
|
||||
|
||||
|
||||
TransformComponents decompose() const;
|
||||
static Mat2D compose(const TransformComponents&);
|
||||
Mat2D scale(Vec2D) const;
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
namespace math {
|
||||
constexpr float PI = 3.14159265f;
|
||||
}
|
||||
namespace math {
|
||||
constexpr float PI = 3.14159265f;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,12 +24,12 @@ namespace rive {
|
||||
|
||||
enum class PathVerb : uint8_t {
|
||||
// These deliberately match Skia's values
|
||||
move = 0,
|
||||
line = 1,
|
||||
quad = 2,
|
||||
move = 0,
|
||||
line = 1,
|
||||
quad = 2,
|
||||
// conic
|
||||
cubic = 4,
|
||||
close = 5,
|
||||
cubic = 4,
|
||||
close = 5,
|
||||
};
|
||||
|
||||
int path_verb_to_point_count(PathVerb);
|
||||
|
||||
@@ -37,9 +37,7 @@ namespace rive {
|
||||
|
||||
RawPath transform(const Mat2D&) const;
|
||||
void transformInPlace(const Mat2D&);
|
||||
RawPath operator*(const Mat2D& mat) const {
|
||||
return this->transform(mat);
|
||||
}
|
||||
RawPath operator*(const Mat2D& mat) const { return this->transform(mat); }
|
||||
|
||||
Span<const Vec2D> points() const { return toSpan(m_Points); }
|
||||
Span<Vec2D> points() { return toSpan(m_Points); }
|
||||
@@ -73,21 +71,21 @@ namespace rive {
|
||||
const PathVerb* m_stopVerb; // 1 past last verb
|
||||
public:
|
||||
Iter(const RawPath& path) {
|
||||
m_currPts = path.m_Points.data();
|
||||
m_currPts = path.m_Points.data();
|
||||
m_currVerb = path.m_Verbs.data();
|
||||
m_stopVerb = path.m_Verbs.data() + path.m_Verbs.size();
|
||||
}
|
||||
|
||||
|
||||
struct Rec {
|
||||
const Vec2D* pts;
|
||||
int count;
|
||||
PathVerb verb;
|
||||
|
||||
|
||||
operator bool() const { return pts != nullptr; }
|
||||
};
|
||||
Rec next();
|
||||
};
|
||||
|
||||
|
||||
template <typename Handler> RawPath morph(Handler proc) const {
|
||||
RawPath dst;
|
||||
// todo: dst.reserve(src.ptCount, src.verbCount);
|
||||
@@ -98,16 +96,25 @@ namespace rive {
|
||||
pts[i] = proc(rec.pts[i]);
|
||||
}
|
||||
switch (rec.verb) {
|
||||
case PathVerb::move: dst.move(pts[0]); break;
|
||||
case PathVerb::line: dst.line(pts[0]); break;
|
||||
case PathVerb::quad: dst.quad(pts[0], pts[1]); break;
|
||||
case PathVerb::cubic: dst.cubic(pts[0], pts[1], pts[2]); break;
|
||||
case PathVerb::close: dst.close(); break;
|
||||
case PathVerb::move:
|
||||
dst.move(pts[0]);
|
||||
break;
|
||||
case PathVerb::line:
|
||||
dst.line(pts[0]);
|
||||
break;
|
||||
case PathVerb::quad:
|
||||
dst.quad(pts[0], pts[1]);
|
||||
break;
|
||||
case PathVerb::cubic:
|
||||
dst.cubic(pts[0], pts[1], pts[2]);
|
||||
break;
|
||||
case PathVerb::close:
|
||||
dst.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
|
||||
@@ -79,9 +79,7 @@ namespace rive {
|
||||
inline bool operator==(const Vec2D& a, const Vec2D& b) { return a.x == b.x && a.y == b.y; }
|
||||
inline bool operator!=(const Vec2D& a, const Vec2D& b) { return a.x != b.x || a.y != b.y; }
|
||||
|
||||
Vec2D Vec2D::lerp(Vec2D a, Vec2D b, float t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
Vec2D Vec2D::lerp(Vec2D a, Vec2D b, float t) { return a + (b - a) * t; }
|
||||
|
||||
} // namespace rive
|
||||
#endif
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
enum class PointerEventType {
|
||||
down, // The button has gone from up to down
|
||||
move, // The pointer's position has changed
|
||||
up, // The button has gone from down to up
|
||||
};
|
||||
enum class PointerEventType {
|
||||
down, // The button has gone from up to down
|
||||
move, // The pointer's position has changed
|
||||
up, // The button has gone from down to up
|
||||
};
|
||||
|
||||
struct PointerEvent {
|
||||
PointerEventType m_Type;
|
||||
Vec2D m_Position;
|
||||
int m_PointerIndex;
|
||||
struct PointerEvent {
|
||||
PointerEventType m_Type;
|
||||
Vec2D m_Position;
|
||||
int m_PointerIndex;
|
||||
|
||||
// add more fields as needed
|
||||
};
|
||||
|
||||
// add more fields as needed
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,9 +18,7 @@ namespace rive {
|
||||
Factory* m_Factory;
|
||||
|
||||
public:
|
||||
RelativeLocalAssetResolver(std::string filename, Factory* factory)
|
||||
: m_Factory(factory)
|
||||
{
|
||||
RelativeLocalAssetResolver(std::string filename, Factory* factory) : m_Factory(factory) {
|
||||
std::size_t finalSlash = filename.rfind('/');
|
||||
|
||||
if (finalSlash != std::string::npos) {
|
||||
|
||||
@@ -11,88 +11,88 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
using Unichar = int32_t;
|
||||
using GlyphID = uint16_t;
|
||||
using Unichar = int32_t;
|
||||
using GlyphID = uint16_t;
|
||||
|
||||
struct RenderTextRun;
|
||||
struct RenderGlyphRun;
|
||||
struct RenderTextRun;
|
||||
struct RenderGlyphRun;
|
||||
|
||||
class RenderFont : public RefCnt {
|
||||
public:
|
||||
struct LineMetrics {
|
||||
float ascent,
|
||||
descent;
|
||||
class RenderFont : public RefCnt {
|
||||
public:
|
||||
struct LineMetrics {
|
||||
float ascent, descent;
|
||||
};
|
||||
|
||||
const LineMetrics& lineMetrics() const { return m_LineMetrics; }
|
||||
|
||||
// This is experimental
|
||||
// -- may only be needed by Editor
|
||||
// -- so it may be removed from here later
|
||||
//
|
||||
struct Axis {
|
||||
uint32_t tag;
|
||||
float min;
|
||||
float def; // default value
|
||||
float max;
|
||||
};
|
||||
|
||||
// Returns the canonical set of Axes for this font. Use this to know
|
||||
// what variations are possible. If you want to know the specific
|
||||
// coordinate within that variations space for *this* font, call
|
||||
// getCoords().
|
||||
//
|
||||
virtual std::vector<Axis> getAxes() const = 0;
|
||||
|
||||
struct Coord {
|
||||
uint32_t axis;
|
||||
float value;
|
||||
};
|
||||
|
||||
// Returns the specific coords in variation space for this font.
|
||||
// If you want to have a description of the entire variation space,
|
||||
// call getAxes().
|
||||
//
|
||||
virtual std::vector<Coord> getCoords() const = 0;
|
||||
|
||||
virtual rcp<RenderFont> makeAtCoords(Span<const Coord>) const = 0;
|
||||
|
||||
rcp<RenderFont> makeAtCoord(Coord c) {
|
||||
return this->makeAtCoords(Span<const Coord>(&c, 1));
|
||||
}
|
||||
|
||||
// Returns a 1-point path for this glyph. It will be positioned
|
||||
// relative to (0,0) with the typographic baseline at y = 0.
|
||||
//
|
||||
virtual RawPath getPath(GlyphID) const = 0;
|
||||
|
||||
std::vector<RenderGlyphRun> shapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const;
|
||||
|
||||
protected:
|
||||
RenderFont(const LineMetrics& lm) : m_LineMetrics(lm) {}
|
||||
|
||||
virtual std::vector<RenderGlyphRun>
|
||||
onShapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const = 0;
|
||||
|
||||
private:
|
||||
const LineMetrics m_LineMetrics;
|
||||
};
|
||||
|
||||
const LineMetrics& lineMetrics() const { return m_LineMetrics; }
|
||||
|
||||
// This is experimental
|
||||
// -- may only be needed by Editor
|
||||
// -- so it may be removed from here later
|
||||
//
|
||||
struct Axis {
|
||||
uint32_t tag;
|
||||
float min;
|
||||
float def; // default value
|
||||
float max;
|
||||
struct RenderTextRun {
|
||||
rcp<RenderFont> font;
|
||||
float size;
|
||||
uint32_t unicharCount;
|
||||
};
|
||||
|
||||
// Returns the canonical set of Axes for this font. Use this to know
|
||||
// what variations are possible. If you want to know the specific
|
||||
// coordinate within that variations space for *this* font, call
|
||||
// getCoords().
|
||||
//
|
||||
virtual std::vector<Axis> getAxes() const = 0;
|
||||
struct RenderGlyphRun {
|
||||
rcp<RenderFont> font;
|
||||
float size;
|
||||
|
||||
struct Coord {
|
||||
uint32_t axis;
|
||||
float value;
|
||||
std::vector<GlyphID> glyphs; // [#glyphs]
|
||||
std::vector<uint32_t> textOffsets; // [#glyphs]
|
||||
std::vector<float> xpos; // [#glyphs + 1]
|
||||
};
|
||||
|
||||
// Returns the specific coords in variation space for this font.
|
||||
// If you want to have a description of the entire variation space,
|
||||
// call getAxes().
|
||||
//
|
||||
virtual std::vector<Coord> getCoords() const = 0;
|
||||
|
||||
virtual rcp<RenderFont> makeAtCoords(Span<const Coord>) const = 0;
|
||||
|
||||
rcp<RenderFont> makeAtCoord(Coord c) {
|
||||
return this->makeAtCoords(Span<const Coord>(&c, 1));
|
||||
}
|
||||
|
||||
// Returns a 1-point path for this glyph. It will be positioned
|
||||
// relative to (0,0) with the typographic baseline at y = 0.
|
||||
//
|
||||
virtual RawPath getPath(GlyphID) const = 0;
|
||||
|
||||
std::vector<RenderGlyphRun> shapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const;
|
||||
|
||||
protected:
|
||||
RenderFont(const LineMetrics& lm) : m_LineMetrics(lm) {}
|
||||
|
||||
virtual std::vector<RenderGlyphRun> onShapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const = 0;
|
||||
|
||||
private:
|
||||
const LineMetrics m_LineMetrics;
|
||||
};
|
||||
|
||||
struct RenderTextRun {
|
||||
rcp<RenderFont> font;
|
||||
float size;
|
||||
uint32_t unicharCount;
|
||||
};
|
||||
|
||||
struct RenderGlyphRun {
|
||||
rcp<RenderFont> font;
|
||||
float size;
|
||||
|
||||
std::vector<GlyphID> glyphs; // [#glyphs]
|
||||
std::vector<uint32_t> textOffsets; // [#glyphs]
|
||||
std::vector<float> xpos; // [#glyphs + 1]
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace rive {
|
||||
public:
|
||||
RenderPaint();
|
||||
virtual ~RenderPaint();
|
||||
|
||||
|
||||
virtual void style(RenderPaintStyle style) = 0;
|
||||
virtual void color(ColorInt value) = 0;
|
||||
virtual void thickness(float value) = 0;
|
||||
|
||||
@@ -9,32 +9,32 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
struct Counter {
|
||||
enum Type {
|
||||
kFile,
|
||||
kArtboardInstance,
|
||||
kLinearAnimationInstance,
|
||||
kStateMachineInstance,
|
||||
struct Counter {
|
||||
enum Type {
|
||||
kFile,
|
||||
kArtboardInstance,
|
||||
kLinearAnimationInstance,
|
||||
kStateMachineInstance,
|
||||
|
||||
kBuffer,
|
||||
kPath,
|
||||
kPaint,
|
||||
kShader,
|
||||
kImage,
|
||||
kBuffer,
|
||||
kPath,
|
||||
kPaint,
|
||||
kShader,
|
||||
kImage,
|
||||
|
||||
kLastType = kImage,
|
||||
kLastType = kImage,
|
||||
};
|
||||
|
||||
static constexpr int kNumTypes = Type::kLastType + 1;
|
||||
static int counts[kNumTypes];
|
||||
|
||||
static void update(Type ct, int delta) {
|
||||
assert(delta == 1 || delta == -1);
|
||||
counts[ct] += delta;
|
||||
assert(counts[ct] >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr int kNumTypes = Type::kLastType + 1;
|
||||
static int counts[kNumTypes];
|
||||
|
||||
static void update(Type ct, int delta) {
|
||||
assert(delta == 1 || delta == -1);
|
||||
counts[ct] += delta;
|
||||
assert(counts[ct] >= 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,14 +36,14 @@
|
||||
|
||||
#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
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace rive {
|
||||
class SMINumber;
|
||||
class SMITrigger;
|
||||
|
||||
class Scene {
|
||||
class Scene {
|
||||
protected:
|
||||
ArtboardInstance* m_ArtboardInstance;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace rive {
|
||||
|
||||
public:
|
||||
virtual ~Scene() {}
|
||||
|
||||
|
||||
Scene(Scene const& lhs) : m_ArtboardInstance(lhs.m_ArtboardInstance) {}
|
||||
|
||||
float width() const;
|
||||
@@ -38,7 +38,7 @@ namespace rive {
|
||||
virtual bool isTranslucent() const = 0;
|
||||
// returns -1 for continuous
|
||||
virtual float durationSeconds() const = 0;
|
||||
|
||||
|
||||
// returns true if draw() should be called
|
||||
virtual bool advanceAndApply(float elapsedSeconds) = 0;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace rive {
|
||||
virtual void draw(Renderer* renderer, CommandPath* path) = 0;
|
||||
|
||||
RenderPaint* renderPaint() { return m_RenderPaint.get(); }
|
||||
|
||||
|
||||
/// Get the component that represents the ShapePaintMutator for this
|
||||
/// ShapePaint. It'll be one of SolidColor, LinearGradient, or
|
||||
/// RadialGradient.
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace rive {
|
||||
// Need this to access our artboard. We are treated as a mixin, either
|
||||
// as a Shape or Artboard, so both of those will override this.
|
||||
virtual Artboard* getArtboard() = 0;
|
||||
|
||||
|
||||
PathSpace m_DefaultPathSpace = PathSpace::Neither;
|
||||
std::vector<ShapePaint*> m_ShapePaints;
|
||||
void addPaint(ShapePaint* paint);
|
||||
|
||||
@@ -55,9 +55,7 @@ public:
|
||||
printf("%c\n", c);
|
||||
}
|
||||
|
||||
void add(const char key[], int value) {
|
||||
this->add(key, std::to_string(value).c_str());
|
||||
}
|
||||
void add(const char key[], int value) { this->add(key, std::to_string(value).c_str()); }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
#include "skia_factory.hpp"
|
||||
|
||||
namespace rive {
|
||||
struct CGSkiaFactory : public SkiaFactory {
|
||||
std::vector<uint8_t> platformDecode(Span<const uint8_t>,
|
||||
SkiaFactory::ImageInfo*) override;
|
||||
};
|
||||
} // namespace
|
||||
struct CGSkiaFactory : public SkiaFactory {
|
||||
std::vector<uint8_t> platformDecode(Span<const uint8_t>, SkiaFactory::ImageInfo*) override;
|
||||
};
|
||||
} // namespace rive
|
||||
|
||||
#endif // _RIVE_CGSkiaFactory_HPP_
|
||||
|
||||
@@ -9,40 +9,38 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
struct RenderGlyphLine {
|
||||
int startRun;
|
||||
int startIndex;
|
||||
int endRun;
|
||||
int endIndex;
|
||||
int wsRun;
|
||||
int wsIndex;
|
||||
float startX;
|
||||
float top = 0, baseline = 0, bottom = 0;
|
||||
struct RenderGlyphLine {
|
||||
int startRun;
|
||||
int startIndex;
|
||||
int endRun;
|
||||
int endIndex;
|
||||
int wsRun;
|
||||
int wsIndex;
|
||||
float startX;
|
||||
float top = 0, baseline = 0, bottom = 0;
|
||||
|
||||
RenderGlyphLine(int startRun,
|
||||
int startIndex,
|
||||
int endRun,
|
||||
int endIndex,
|
||||
int wsRun,
|
||||
int wsIndex,
|
||||
float startX) :
|
||||
startRun(startRun),
|
||||
startIndex(startIndex),
|
||||
endRun(endRun),
|
||||
endIndex(endIndex),
|
||||
wsRun(wsRun),
|
||||
wsIndex(wsIndex),
|
||||
startX(startX)
|
||||
{}
|
||||
RenderGlyphLine(int startRun,
|
||||
int startIndex,
|
||||
int endRun,
|
||||
int endIndex,
|
||||
int wsRun,
|
||||
int wsIndex,
|
||||
float startX) :
|
||||
startRun(startRun),
|
||||
startIndex(startIndex),
|
||||
endRun(endRun),
|
||||
endIndex(endIndex),
|
||||
wsRun(wsRun),
|
||||
wsIndex(wsIndex),
|
||||
startX(startX) {}
|
||||
|
||||
static std::vector<RenderGlyphLine> BreakLines(Span<const RenderGlyphRun> runs,
|
||||
Span<const int> breaks,
|
||||
float width);
|
||||
// Compute vaues for top/baseline/bottom per line
|
||||
static void ComputeLineSpacing(rive::Span<RenderGlyphLine>,
|
||||
rive::Span<const RenderGlyphRun>);
|
||||
};
|
||||
static std::vector<RenderGlyphLine>
|
||||
BreakLines(Span<const RenderGlyphRun> runs, Span<const int> breaks, float width);
|
||||
// Compute vaues for top/baseline/bottom per line
|
||||
static void ComputeLineSpacing(rive::Span<RenderGlyphLine>,
|
||||
rive::Span<const RenderGlyphRun>);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include <string>
|
||||
|
||||
#if defined(RIVE_BUILD_FOR_OSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(RIVE_BUILD_FOR_IOS)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
template <size_t N, typename T> class AutoSTArray {
|
||||
@@ -44,16 +44,20 @@ static inline std::string tag2str(uint32_t tag) {
|
||||
std::string str = "abcd";
|
||||
str[0] = (tag >> 24) & 0xFF;
|
||||
str[1] = (tag >> 16) & 0xFF;
|
||||
str[2] = (tag >> 8) & 0xFF;
|
||||
str[3] = (tag >> 0) & 0xFF;
|
||||
str[2] = (tag >> 8) & 0xFF;
|
||||
str[3] = (tag >> 0) & 0xFF;
|
||||
return str;
|
||||
}
|
||||
|
||||
template <typename T> class AutoCF {
|
||||
T m_Obj;
|
||||
|
||||
public:
|
||||
AutoCF(T obj) : m_Obj(obj) {}
|
||||
~AutoCF() { if (m_Obj) CFRelease(m_Obj); }
|
||||
~AutoCF() {
|
||||
if (m_Obj)
|
||||
CFRelease(m_Obj);
|
||||
}
|
||||
|
||||
operator T() const { return m_Obj; }
|
||||
operator bool() const { return m_Obj != nullptr; }
|
||||
|
||||
@@ -46,8 +46,8 @@ static inline std::string tag2str(uint32_t tag) {
|
||||
std::string str = "abcd";
|
||||
str[0] = (tag >> 24) & 0xFF;
|
||||
str[1] = (tag >> 16) & 0xFF;
|
||||
str[2] = (tag >> 8) & 0xFF;
|
||||
str[3] = (tag >> 0) & 0xFF;
|
||||
str[2] = (tag >> 8) & 0xFF;
|
||||
str[3] = (tag >> 0) & 0xFF;
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#include "rive/render_text.hpp"
|
||||
|
||||
#if defined(RIVE_BUILD_FOR_OSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(RIVE_BUILD_FOR_IOS)
|
||||
#include <CoreText/CoreText.h>
|
||||
#include <CoreText/CoreText.h>
|
||||
#endif
|
||||
|
||||
class CoreTextRenderFont : public rive::RenderFont {
|
||||
@@ -28,8 +28,9 @@ public:
|
||||
std::vector<Coord> getCoords() const override { return m_coords; }
|
||||
rive::rcp<rive::RenderFont> makeAtCoords(rive::Span<const Coord>) const override;
|
||||
rive::RawPath getPath(rive::GlyphID) const override;
|
||||
std::vector<rive::RenderGlyphRun> onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
std::vector<rive::RenderGlyphRun>
|
||||
onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
|
||||
static rive::rcp<rive::RenderFont> Decode(rive::Span<const uint8_t>);
|
||||
};
|
||||
|
||||
@@ -25,8 +25,9 @@ public:
|
||||
std::vector<Coord> getCoords() const override;
|
||||
rive::rcp<rive::RenderFont> makeAtCoords(rive::Span<const Coord>) const override;
|
||||
rive::RawPath getPath(rive::GlyphID) const override;
|
||||
std::vector<rive::RenderGlyphRun> onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
std::vector<rive::RenderGlyphRun>
|
||||
onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
|
||||
static rive::rcp<rive::RenderFont> Decode(rive::Span<const uint8_t>);
|
||||
};
|
||||
|
||||
@@ -18,8 +18,9 @@ public:
|
||||
std::vector<Coord> getCoords() const override;
|
||||
rive::rcp<rive::RenderFont> makeAtCoords(rive::Span<const Coord>) const override;
|
||||
rive::RawPath getPath(rive::GlyphID) const override;
|
||||
std::vector<rive::RenderGlyphRun> onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
std::vector<rive::RenderGlyphRun>
|
||||
onShapeText(rive::Span<const rive::Unichar>,
|
||||
rive::Span<const rive::RenderTextRun>) const override;
|
||||
|
||||
static rive::rcp<rive::RenderFont> Decode(rive::Span<const uint8_t>);
|
||||
};
|
||||
|
||||
@@ -10,64 +10,67 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
class SkiaFactory : public Factory {
|
||||
public:
|
||||
rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
|
||||
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
|
||||
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
|
||||
class SkiaFactory : public Factory {
|
||||
public:
|
||||
rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
|
||||
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
|
||||
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
|
||||
|
||||
rcp<RenderShader> makeLinearGradient(float sx, float sy,
|
||||
float ex, float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
rcp<RenderShader> makeLinearGradient(float sx,
|
||||
float sy,
|
||||
float ex,
|
||||
float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
|
||||
rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
rcp<RenderShader> makeRadialGradient(float cx,
|
||||
float cy,
|
||||
float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
|
||||
std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
|
||||
Span<const uint8_t> verbs,
|
||||
FillRule) override;
|
||||
std::unique_ptr<RenderPath>
|
||||
makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule) override;
|
||||
|
||||
std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
|
||||
std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
|
||||
|
||||
std::unique_ptr<RenderPaint> makeRenderPaint() override;
|
||||
std::unique_ptr<RenderPaint> makeRenderPaint() override;
|
||||
|
||||
std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override;
|
||||
std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override;
|
||||
|
||||
//
|
||||
// New virtual for access the platform's codecs
|
||||
//
|
||||
//
|
||||
// New virtual for access the platform's codecs
|
||||
//
|
||||
|
||||
enum class ColorType {
|
||||
rgba,
|
||||
bgra,
|
||||
enum class ColorType {
|
||||
rgba,
|
||||
bgra,
|
||||
};
|
||||
enum class AlphaType {
|
||||
premul,
|
||||
opaque,
|
||||
};
|
||||
struct ImageInfo {
|
||||
size_t rowBytes; // number of bytes between rows
|
||||
uint32_t width; // logical width in pixels
|
||||
uint32_t height; // logical height in pixels
|
||||
ColorType colorType;
|
||||
AlphaType alphaType;
|
||||
};
|
||||
|
||||
// Clients can override this to provide access to the platform's decoders, rather
|
||||
// than solely relying on the codecs built into Skia. This allows for the Skia impl
|
||||
// to not have to duplicate the code for codecs that the platform may already have.
|
||||
virtual std::vector<uint8_t> platformDecode(Span<const uint8_t>, ImageInfo* info) {
|
||||
return std::vector<uint8_t>(); // empty vector means decode failed
|
||||
}
|
||||
};
|
||||
enum class AlphaType {
|
||||
premul,
|
||||
opaque,
|
||||
};
|
||||
struct ImageInfo {
|
||||
size_t rowBytes; // number of bytes between rows
|
||||
uint32_t width; // logical width in pixels
|
||||
uint32_t height; // logical height in pixels
|
||||
ColorType colorType;
|
||||
AlphaType alphaType;
|
||||
};
|
||||
|
||||
// Clients can override this to provide access to the platform's decoders, rather
|
||||
// than solely relying on the codecs built into Skia. This allows for the Skia impl
|
||||
// to not have to duplicate the code for codecs that the platform may already have.
|
||||
virtual std::vector<uint8_t> platformDecode(Span<const uint8_t>, ImageInfo* info) {
|
||||
return std::vector<uint8_t>(); // empty vector means decode failed
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace rive
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,7 @@ namespace rive {
|
||||
return SkMatrix::MakeAll(m[0], m[2], m[4], m[1], m[3], m[5], 0, 0, 1);
|
||||
}
|
||||
|
||||
static SkPoint convert(rive::Vec2D point) {
|
||||
return SkPoint::Make(point.x, point.y);
|
||||
}
|
||||
static SkPoint convert(rive::Vec2D point) { return SkPoint::Make(point.x, point.y); }
|
||||
|
||||
// clang-format off
|
||||
static SkTileMode convert(RenderTileMode rtm) {
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
#include "mac_utils.hpp"
|
||||
|
||||
#if defined(RIVE_BUILD_FOR_OSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(RIVE_BUILD_FOR_IOS)
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <ImageIO/ImageIO.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <ImageIO/ImageIO.h>
|
||||
#endif
|
||||
|
||||
using namespace rive;
|
||||
@@ -52,7 +52,7 @@ std::vector<uint8_t> CGSkiaFactory::platformDecode(Span<const uint8_t> span,
|
||||
// Now create a drawing context to produce RGBA pixels
|
||||
|
||||
const size_t bitsPerComponent = 8;
|
||||
CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big; // rgba
|
||||
CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big; // rgba
|
||||
if (isOpaque) {
|
||||
cgInfo |= kCGImageAlphaNoneSkipLast;
|
||||
} else {
|
||||
@@ -60,13 +60,14 @@ std::vector<uint8_t> CGSkiaFactory::platformDecode(Span<const uint8_t> span,
|
||||
}
|
||||
const size_t width = CGImageGetWidth(image);
|
||||
const size_t height = CGImageGetHeight(image);
|
||||
const size_t rowBytes = width * 4; // 4 bytes per pixel
|
||||
const size_t rowBytes = width * 4; // 4 bytes per pixel
|
||||
const size_t size = rowBytes * height;
|
||||
|
||||
pixels.resize(size);
|
||||
|
||||
AutoCF cs = CGColorSpaceCreateDeviceRGB();
|
||||
AutoCF cg = CGBitmapContextCreate(pixels.data(), width, height, bitsPerComponent, rowBytes, cs, cgInfo);
|
||||
AutoCF cg =
|
||||
CGBitmapContextCreate(pixels.data(), width, height, bitsPerComponent, rowBytes, cs, cgInfo);
|
||||
if (!cg) {
|
||||
pixels.clear();
|
||||
return pixels;
|
||||
@@ -83,4 +84,4 @@ std::vector<uint8_t> CGSkiaFactory::platformDecode(Span<const uint8_t> span,
|
||||
return pixels;
|
||||
};
|
||||
|
||||
#endif // RIVE_BUILD_FOR_APPLE
|
||||
#endif // RIVE_BUILD_FOR_APPLE
|
||||
|
||||
@@ -19,21 +19,20 @@ static int _offsetToRunIndex(Span<const RenderGlyphRun> runs, size_t textOffset)
|
||||
|
||||
static int textOffsetToGlyphIndex(const RenderGlyphRun& run, size_t textOffset) {
|
||||
assert(textOffset >= run.textOffsets.front());
|
||||
// assert(textOffset <= run.textOffsets.back()); // not true for last run
|
||||
// assert(textOffset <= run.textOffsets.back()); // not true for last run
|
||||
|
||||
// todo: bsearch?
|
||||
auto begin = run.textOffsets.begin();
|
||||
auto end = run.textOffsets.end();
|
||||
auto iter = std::find(begin, end, textOffset);
|
||||
if (iter == end) { // end of run
|
||||
return run.glyphs.size() - 1;
|
||||
if (iter == end) { // end of run
|
||||
return run.glyphs.size() - 1;
|
||||
}
|
||||
return iter - begin;
|
||||
}
|
||||
|
||||
std::vector<RenderGlyphLine> RenderGlyphLine::BreakLines(Span<const RenderGlyphRun> runs,
|
||||
Span<const int> breaks,
|
||||
float width) {
|
||||
std::vector<RenderGlyphLine>
|
||||
RenderGlyphLine::BreakLines(Span<const RenderGlyphRun> runs, Span<const int> breaks, float width) {
|
||||
assert(breaks.size() >= 2);
|
||||
|
||||
std::vector<RenderGlyphLine> lines;
|
||||
@@ -50,99 +49,96 @@ std::vector<RenderGlyphLine> RenderGlyphLine::BreakLines(Span<const RenderGlyphR
|
||||
int lineStartTextOffset = wordStart;
|
||||
|
||||
for (;;) {
|
||||
assert(wordStart <= wordEnd); // == means trailing spaces?
|
||||
assert(wordStart <= wordEnd); // == means trailing spaces?
|
||||
|
||||
int endRun = _offsetToRunIndex(runs, wordEnd);
|
||||
int endIndex = textOffsetToGlyphIndex(runs[endRun], wordEnd);
|
||||
float pos = runs[endRun].xpos[endIndex];
|
||||
bool bumpBreakIndex = true;
|
||||
if (pos > xlimit) {
|
||||
int wsRun = _offsetToRunIndex(runs, wordStart);
|
||||
int wsIndex = textOffsetToGlyphIndex(runs[wsRun], wordStart);
|
||||
int endRun = _offsetToRunIndex(runs, wordEnd);
|
||||
int endIndex = textOffsetToGlyphIndex(runs[endRun], wordEnd);
|
||||
float pos = runs[endRun].xpos[endIndex];
|
||||
bool bumpBreakIndex = true;
|
||||
if (pos > xlimit) {
|
||||
int wsRun = _offsetToRunIndex(runs, wordStart);
|
||||
int wsIndex = textOffsetToGlyphIndex(runs[wsRun], wordStart);
|
||||
|
||||
bumpBreakIndex = false;
|
||||
// does just one word not fit?
|
||||
if (lineStartTextOffset == wordStart) {
|
||||
// walk backwards a letter at a time until we fit, stopping at
|
||||
// 1 letter.
|
||||
int wend = wordEnd;
|
||||
while (pos > xlimit && wend - 1 > wordStart) {
|
||||
wend -= 1;
|
||||
prevRun = _offsetToRunIndex(runs, wend);
|
||||
prevIndex = textOffsetToGlyphIndex(runs[prevRun], wend);
|
||||
pos = runs[prevRun].xpos[prevIndex];
|
||||
}
|
||||
assert(wend < wordEnd || wend == wordEnd && wordStart + 1 == wordEnd);
|
||||
if (wend == wordEnd) {
|
||||
bumpBreakIndex = true;
|
||||
}
|
||||
bumpBreakIndex = false;
|
||||
// does just one word not fit?
|
||||
if (lineStartTextOffset == wordStart) {
|
||||
// walk backwards a letter at a time until we fit, stopping at
|
||||
// 1 letter.
|
||||
int wend = wordEnd;
|
||||
while (pos > xlimit && wend - 1 > wordStart) {
|
||||
wend -= 1;
|
||||
prevRun = _offsetToRunIndex(runs, wend);
|
||||
prevIndex = textOffsetToGlyphIndex(runs[prevRun], wend);
|
||||
pos = runs[prevRun].xpos[prevIndex];
|
||||
}
|
||||
assert(wend < wordEnd || wend == wordEnd && wordStart + 1 == wordEnd);
|
||||
if (wend == wordEnd) {
|
||||
bumpBreakIndex = true;
|
||||
}
|
||||
|
||||
// now reset our "whitespace" marker to just be prev, since
|
||||
// by defintion we have no extra whitespace on this line
|
||||
wsRun = prevRun;
|
||||
wsIndex = prevIndex;
|
||||
wordStart = wend;
|
||||
}
|
||||
// now reset our "whitespace" marker to just be prev, since
|
||||
// by defintion we have no extra whitespace on this line
|
||||
wsRun = prevRun;
|
||||
wsIndex = prevIndex;
|
||||
wordStart = wend;
|
||||
}
|
||||
|
||||
// bulid the line
|
||||
const auto lineStartX = runs[startRun].xpos[startIndex];
|
||||
lines.push_back(RenderGlyphLine(
|
||||
startRun, startIndex, prevRun, prevIndex, wsRun, wsIndex, lineStartX
|
||||
));
|
||||
// bulid the line
|
||||
const auto lineStartX = runs[startRun].xpos[startIndex];
|
||||
lines.push_back(RenderGlyphLine(
|
||||
startRun, startIndex, prevRun, prevIndex, wsRun, wsIndex, lineStartX));
|
||||
|
||||
// update for the next line
|
||||
xlimit = runs[wsRun].xpos[wsIndex] + width;
|
||||
startRun = prevRun = wsRun;
|
||||
startIndex = prevIndex = wsIndex;
|
||||
lineStartTextOffset = wordStart;
|
||||
} else {
|
||||
// we didn't go too far, so remember this word-end boundary
|
||||
prevRun = endRun;
|
||||
prevIndex = endIndex;
|
||||
}
|
||||
|
||||
if (bumpBreakIndex) {
|
||||
if (nextBreakIndex < breaks.size()) {
|
||||
wordStart = breaks[nextBreakIndex++];
|
||||
wordEnd = breaks[nextBreakIndex++];
|
||||
// update for the next line
|
||||
xlimit = runs[wsRun].xpos[wsIndex] + width;
|
||||
startRun = prevRun = wsRun;
|
||||
startIndex = prevIndex = wsIndex;
|
||||
lineStartTextOffset = wordStart;
|
||||
} else {
|
||||
break; // bust out of the loop
|
||||
// we didn't go too far, so remember this word-end boundary
|
||||
prevRun = endRun;
|
||||
prevIndex = endIndex;
|
||||
}
|
||||
|
||||
if (bumpBreakIndex) {
|
||||
if (nextBreakIndex < breaks.size()) {
|
||||
wordStart = breaks[nextBreakIndex++];
|
||||
wordEnd = breaks[nextBreakIndex++];
|
||||
} else {
|
||||
break; // bust out of the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// scoop up the last line (if present)
|
||||
const int tailRun = runs.size() - 1;
|
||||
const int tailIndex = runs[tailRun].glyphs.size();
|
||||
if (startRun != tailRun || startIndex != tailIndex) {
|
||||
const auto startX = runs[startRun].xpos[startIndex];
|
||||
lines.push_back(RenderGlyphLine(
|
||||
startRun, startIndex, tailRun, tailIndex, tailRun, tailIndex, startX
|
||||
));
|
||||
const auto startX = runs[startRun].xpos[startIndex];
|
||||
lines.push_back(
|
||||
RenderGlyphLine(startRun, startIndex, tailRun, tailIndex, tailRun, tailIndex, startX));
|
||||
}
|
||||
|
||||
ComputeLineSpacing(toSpan(lines), runs);
|
||||
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderGlyphLine::ComputeLineSpacing(Span<RenderGlyphLine> lines,
|
||||
Span<const RenderGlyphRun> runs) {
|
||||
float Y = 0; // top of our frame
|
||||
float Y = 0; // top of our frame
|
||||
for (auto& line : lines) {
|
||||
float asc = 0;
|
||||
float des = 0;
|
||||
for (int i = line.startRun; i <= line.wsRun; ++i) {
|
||||
const auto& run = runs[i];
|
||||
float asc = 0;
|
||||
float des = 0;
|
||||
for (int i = line.startRun; i <= line.wsRun; ++i) {
|
||||
const auto& run = runs[i];
|
||||
|
||||
asc = std::min(asc, run.font->lineMetrics().ascent * run.size);
|
||||
des = std::max(des, run.font->lineMetrics().descent * run.size);
|
||||
}
|
||||
line.top = Y;
|
||||
Y -= asc;
|
||||
line.baseline = Y;
|
||||
Y += des;
|
||||
line.bottom = Y;
|
||||
asc = std::min(asc, run.font->lineMetrics().ascent * run.size);
|
||||
des = std::max(des, run.font->lineMetrics().descent * run.size);
|
||||
}
|
||||
line.top = Y;
|
||||
Y -= asc;
|
||||
line.baseline = Y;
|
||||
Y += des;
|
||||
line.bottom = Y;
|
||||
}
|
||||
// TODO: good place to perform left/center/right alignment
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
#ifdef RIVE_BUILD_FOR_APPLE
|
||||
|
||||
#if defined(RIVE_BUILD_FOR_OSX)
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(RIVE_BUILD_FOR_IOS)
|
||||
#include <CoreText/CoreText.h>
|
||||
#include <CoreText/CTFontManager.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreText/CoreText.h>
|
||||
#include <CoreText/CTFontManager.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
constexpr int kStdScale = 2048;
|
||||
@@ -37,7 +37,7 @@ static std::vector<rive::RenderFont::Axis> compute_axes(CTFontRef font) {
|
||||
auto min = find_float(axis, kCTFontVariationAxisMinimumValueKey);
|
||||
auto def = find_float(axis, kCTFontVariationAxisDefaultValueKey);
|
||||
auto max = find_float(axis, kCTFontVariationAxisMaximumValueKey);
|
||||
// printf("%08X %g %g %g\n", tag, min, def, max);
|
||||
// printf("%08X %g %g %g\n", tag, min, def, max);
|
||||
|
||||
axes.push_back({tag, min, def, max});
|
||||
}
|
||||
@@ -60,7 +60,7 @@ static std::vector<rive::RenderFont::Coord> compute_coords(CTFontRef font) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
uint32_t tag = number_as_u32((CFNumberRef)keys[i]);
|
||||
float value = number_as_float((CFNumberRef)values[i]);
|
||||
// printf("[%d] %08X %s %g\n", i, tag, tag2str(tag).c_str(), value);
|
||||
// printf("[%d] %08X %s %g\n", i, tag, tag2str(tag).c_str(), value);
|
||||
coords[i] = {tag, value};
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ static std::vector<rive::RenderFont::Coord> compute_coords(CTFontRef font) {
|
||||
}
|
||||
|
||||
rive::rcp<rive::RenderFont> CoreTextRenderFont::Decode(rive::Span<const uint8_t> span) {
|
||||
AutoCF data = CFDataCreate(nullptr, span.data(), span.size()); // makes a copy
|
||||
AutoCF data = CFDataCreate(nullptr, span.data(), span.size()); // makes a copy
|
||||
if (!data) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
@@ -111,26 +111,23 @@ rive::rcp<rive::RenderFont> CoreTextRenderFont::Decode(rive::Span<const uint8_t>
|
||||
|
||||
static rive::RenderFont::LineMetrics make_lmx(CTFontRef font) {
|
||||
return {
|
||||
(float) -CTFontGetAscent(font) * gInvScale,
|
||||
(float) CTFontGetDescent(font) * gInvScale,
|
||||
(float)-CTFontGetAscent(font) * gInvScale,
|
||||
(float)CTFontGetDescent(font) * gInvScale,
|
||||
};
|
||||
}
|
||||
|
||||
CoreTextRenderFont::CoreTextRenderFont(CTFontRef font,
|
||||
std::vector<rive::RenderFont::Axis> axes) :
|
||||
CoreTextRenderFont::CoreTextRenderFont(CTFontRef font, std::vector<rive::RenderFont::Axis> axes) :
|
||||
rive::RenderFont(make_lmx(font)),
|
||||
m_font(font), // we take ownership of font
|
||||
m_font(font), // we take ownership of font
|
||||
m_axes(std::move(axes)),
|
||||
m_coords(compute_coords(font))
|
||||
{}
|
||||
m_coords(compute_coords(font)) {}
|
||||
|
||||
CoreTextRenderFont::~CoreTextRenderFont() {
|
||||
CFRelease(m_font);
|
||||
}
|
||||
CoreTextRenderFont::~CoreTextRenderFont() { CFRelease(m_font); }
|
||||
|
||||
rive::rcp<rive::RenderFont> CoreTextRenderFont::makeAtCoords(rive::Span<const Coord> coords) const {
|
||||
AutoCF vars = CFDictionaryCreateMutable(kCFAllocatorDefault, coords.size(),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
AutoCF vars = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
coords.size(),
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
for (const auto& c : coords) {
|
||||
AutoCF tagNum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &c.axis);
|
||||
@@ -138,11 +135,10 @@ rive::rcp<rive::RenderFont> CoreTextRenderFont::makeAtCoords(rive::Span<const Co
|
||||
CFDictionaryAddValue(vars.get(), tagNum.get(), valueNum.get());
|
||||
}
|
||||
|
||||
AutoCF attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
AutoCF attrs = CFDictionaryCreateMutable(
|
||||
kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
CFDictionarySetValue(attrs.get(), kCTFontVariationAttribute, vars.get());
|
||||
|
||||
|
||||
AutoCF desc = (CTFontDescriptorRef)CTFontDescriptorCreateWithAttributes(attrs.get());
|
||||
|
||||
auto font = CTFontCreateCopyWithAttributes(m_font, 0, nullptr, desc.get());
|
||||
@@ -150,7 +146,7 @@ rive::rcp<rive::RenderFont> CoreTextRenderFont::makeAtCoords(rive::Span<const Co
|
||||
return rive::rcp<rive::RenderFont>(new CoreTextRenderFont(font, compute_axes(font)));
|
||||
}
|
||||
|
||||
static void apply_element(void *ctx, const CGPathElement *element) {
|
||||
static void apply_element(void* ctx, const CGPathElement* element) {
|
||||
auto path = (rive::RawPath*)ctx;
|
||||
const CGPoint* points = element->points;
|
||||
|
||||
@@ -164,14 +160,12 @@ static void apply_element(void *ctx, const CGPathElement *element) {
|
||||
break;
|
||||
|
||||
case kCGPathElementAddQuadCurveToPoint:
|
||||
path->quadTo(points[0].x, points[0].y,
|
||||
points[1].x, points[1].y);
|
||||
path->quadTo(points[0].x, points[0].y, points[1].x, points[1].y);
|
||||
break;
|
||||
|
||||
case kCGPathElementAddCurveToPoint:
|
||||
path->cubicTo(points[0].x, points[0].y,
|
||||
points[1].x, points[1].y,
|
||||
points[2].x, points[2].y);
|
||||
path->cubicTo(
|
||||
points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y);
|
||||
break;
|
||||
|
||||
case kCGPathElementCloseSubpath:
|
||||
@@ -209,8 +203,8 @@ struct AutoUTF16 {
|
||||
}
|
||||
};
|
||||
|
||||
static float add_run(rive::RenderGlyphRun* gr, CTRunRef run,
|
||||
uint32_t textStart, float textSize, float startX) {
|
||||
static float
|
||||
add_run(rive::RenderGlyphRun* gr, CTRunRef run, uint32_t textStart, float textSize, float startX) {
|
||||
if (auto count = CTRunGetGlyphCount(run)) {
|
||||
const float scale = textSize * gInvScale;
|
||||
|
||||
@@ -250,12 +244,13 @@ CoreTextRenderFont::onShapeText(rive::Span<const rive::Unichar> text,
|
||||
CTFontRef font = ((CoreTextRenderFont*)tr.font.get())->m_font;
|
||||
|
||||
AutoUTF16 utf16(&text[unicharIndex], tr.unicharCount);
|
||||
AutoCF string = CFStringCreateWithCharactersNoCopy(nullptr, utf16.array.data(),
|
||||
tr.unicharCount, kCFAllocatorNull);
|
||||
AutoCF string = CFStringCreateWithCharactersNoCopy(
|
||||
nullptr, utf16.array.data(), tr.unicharCount, kCFAllocatorNull);
|
||||
|
||||
AutoCF attr = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
AutoCF attr = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFDictionaryAddValue(attr.get(), kCTFontAttributeName, font);
|
||||
|
||||
AutoCF attrString = CFAttributedStringCreate(kCFAllocatorDefault, string.get(), attr.get());
|
||||
@@ -268,8 +263,11 @@ CoreTextRenderFont::onShapeText(rive::Span<const rive::Unichar> text,
|
||||
CFIndex runCount = CFArrayGetCount(run_array);
|
||||
for (CFIndex i = 0; i < runCount; ++i) {
|
||||
rive::RenderGlyphRun grun;
|
||||
startX = add_run(&grun, (CTRunRef)CFArrayGetValueAtIndex(run_array, i),
|
||||
unicharIndex, tr.size, startX);
|
||||
startX = add_run(&grun,
|
||||
(CTRunRef)CFArrayGetValueAtIndex(run_array, i),
|
||||
unicharIndex,
|
||||
tr.size,
|
||||
startX);
|
||||
if (grun.glyphs.size() > 0) {
|
||||
grun.font = tr.font;
|
||||
grun.size = tr.size;
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
#include "hb-ot.h"
|
||||
|
||||
rive::rcp<rive::RenderFont> HBRenderFont::Decode(rive::Span<const uint8_t> span) {
|
||||
auto blob = hb_blob_create_or_fail((const char*)span.data(), (unsigned)span.size(),
|
||||
HB_MEMORY_MODE_DUPLICATE, nullptr, nullptr);
|
||||
auto blob = hb_blob_create_or_fail((const char*)span.data(),
|
||||
(unsigned)span.size(),
|
||||
HB_MEMORY_MODE_DUPLICATE,
|
||||
nullptr,
|
||||
nullptr);
|
||||
if (blob) {
|
||||
auto face = hb_face_create(blob, 0);
|
||||
auto face = hb_face_create(blob, 0);
|
||||
hb_blob_destroy(blob);
|
||||
if (face) {
|
||||
auto font = hb_font_create(face);
|
||||
@@ -40,15 +43,34 @@ void rpath_move_to(hb_draw_funcs_t*, void* rpath, hb_draw_state_t*, float x, flo
|
||||
void rpath_line_to(hb_draw_funcs_t*, void* rpath, hb_draw_state_t*, float x1, float y1, void*) {
|
||||
((rive::RawPath*)rpath)->lineTo(x1 * gInvScale, -y1 * gInvScale);
|
||||
}
|
||||
void rpath_quad_to(hb_draw_funcs_t*, void* rpath, hb_draw_state_t*, float x1, float y1, float x2, float y2, void*) {
|
||||
((rive::RawPath*)rpath)->quadTo(x1 * gInvScale, -y1 * gInvScale,
|
||||
x2 * gInvScale, -y2 * gInvScale);
|
||||
void rpath_quad_to(hb_draw_funcs_t*,
|
||||
void* rpath,
|
||||
hb_draw_state_t*,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
void*) {
|
||||
((rive::RawPath*)rpath)
|
||||
->quadTo(x1 * gInvScale, -y1 * gInvScale, x2 * gInvScale, -y2 * gInvScale);
|
||||
}
|
||||
void rpath_cubic_to(hb_draw_funcs_t*, void* rpath, hb_draw_state_t*,
|
||||
float x1, float y1, float x2, float y2, float x3, float y3, void*) {
|
||||
((rive::RawPath*)rpath)->cubicTo(x1 * gInvScale, -y1 * gInvScale,
|
||||
x2 * gInvScale, -y2 * gInvScale,
|
||||
x3 * gInvScale, -y3 * gInvScale);
|
||||
void rpath_cubic_to(hb_draw_funcs_t*,
|
||||
void* rpath,
|
||||
hb_draw_state_t*,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
void*) {
|
||||
((rive::RawPath*)rpath)
|
||||
->cubicTo(x1 * gInvScale,
|
||||
-y1 * gInvScale,
|
||||
x2 * gInvScale,
|
||||
-y2 * gInvScale,
|
||||
x3 * gInvScale,
|
||||
-y3 * gInvScale);
|
||||
}
|
||||
void rpath_close(hb_draw_funcs_t*, void* rpath, hb_draw_state_t*, void*) {
|
||||
((rive::RawPath*)rpath)->close();
|
||||
@@ -67,7 +89,7 @@ static rive::RenderFont::LineMetrics make_lmx(hb_font_t* font) {
|
||||
|
||||
HBRenderFont::HBRenderFont(hb_font_t* font) :
|
||||
RenderFont(make_lmx(font)),
|
||||
m_Font(font) // we just take ownership, no need to call reference()
|
||||
m_Font(font) // we just take ownership, no need to call reference()
|
||||
{
|
||||
m_DrawFuncs = hb_draw_funcs_create();
|
||||
hb_draw_funcs_set_move_to_func(m_DrawFuncs, rpath_move_to, nullptr, nullptr);
|
||||
@@ -96,8 +118,9 @@ std::vector<rive::RenderFont::Axis> HBRenderFont::getAxes() const {
|
||||
unsigned n = 1;
|
||||
hb_ot_var_get_axis_infos(face, i, &n, &info);
|
||||
assert(n == 1);
|
||||
axes[i] = { info.tag, info.min_value, info.default_value, info.max_value };
|
||||
// printf("[%d] %08X %g %g %g\n", i, info.tag, info.min_value, info.default_value, info.max_value);
|
||||
axes[i] = {info.tag, info.min_value, info.default_value, info.max_value};
|
||||
// printf("[%d] %08X %g %g %g\n", i, info.tag, info.min_value, info.default_value,
|
||||
// info.max_value);
|
||||
}
|
||||
}
|
||||
return axes;
|
||||
@@ -105,14 +128,14 @@ std::vector<rive::RenderFont::Axis> HBRenderFont::getAxes() const {
|
||||
|
||||
std::vector<rive::RenderFont::Coord> HBRenderFont::getCoords() const {
|
||||
auto axes = this->getAxes();
|
||||
// const int count = (int)axes.size();
|
||||
// const int count = (int)axes.size();
|
||||
|
||||
unsigned length;
|
||||
const float* values = hb_font_get_var_coords_design(m_Font, &length);
|
||||
|
||||
std::vector<rive::RenderFont::Coord> coords(length);
|
||||
for (unsigned i = 0; i < length; ++i) {
|
||||
coords[i] = { axes[i].tag, values[i] };
|
||||
coords[i] = {axes[i].tag, values[i]};
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
@@ -144,28 +167,29 @@ HBRenderFont::onShapeText(rive::Span<const rive::Unichar> text,
|
||||
/////////////////
|
||||
|
||||
const hb_feature_t features[] = {
|
||||
{ 'liga', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
|
||||
{ 'dlig', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
|
||||
{ 'kern', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
|
||||
{'liga', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END},
|
||||
{'dlig', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END},
|
||||
{'kern', 1, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END},
|
||||
};
|
||||
constexpr int numFeatures = sizeof(features) / sizeof(features[0]);
|
||||
|
||||
uint32_t unicharIndex = 0;
|
||||
rive::Vec2D origin = {0, 0};
|
||||
for (const auto& tr : truns) {
|
||||
hb_buffer_t *buf = hb_buffer_create();
|
||||
hb_buffer_add_utf32(buf, (const uint32_t*)&text[unicharIndex], tr.unicharCount, 0, tr.unicharCount);
|
||||
hb_buffer_t* buf = hb_buffer_create();
|
||||
hb_buffer_add_utf32(
|
||||
buf, (const uint32_t*)&text[unicharIndex], tr.unicharCount, 0, tr.unicharCount);
|
||||
|
||||
hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
|
||||
hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
|
||||
hb_buffer_set_language(buf, hb_language_from_string("en", -1));
|
||||
|
||||
|
||||
auto hbfont = (HBRenderFont*)tr.font.get();
|
||||
hb_shape(hbfont->m_Font, buf, features, numFeatures);
|
||||
|
||||
|
||||
unsigned int glyph_count;
|
||||
hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
|
||||
hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
|
||||
hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
|
||||
hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
|
||||
|
||||
// todo: check for missing glyphs, and perform font-substitution
|
||||
|
||||
@@ -179,8 +203,8 @@ HBRenderFont::onShapeText(rive::Span<const rive::Unichar> text,
|
||||
const float scale = tr.size / kStdScale;
|
||||
|
||||
for (unsigned int i = 0; i < glyph_count; i++) {
|
||||
// hb_position_t x_offset = glyph_pos[i].x_offset;
|
||||
// hb_position_t y_offset = glyph_pos[i].y_offset;
|
||||
// hb_position_t x_offset = glyph_pos[i].x_offset;
|
||||
// hb_position_t y_offset = glyph_pos[i].y_offset;
|
||||
|
||||
gr.glyphs[i] = (uint16_t)glyph_info[i].codepoint;
|
||||
gr.textOffsets[i] = unicharIndex + glyph_info[i].cluster;
|
||||
|
||||
@@ -27,13 +27,10 @@ static rive::RenderFont::LineMetrics make_lmx(sk_sp<SkTypeface> tf) {
|
||||
}
|
||||
|
||||
SkiaRenderFont::SkiaRenderFont(sk_sp<SkTypeface> tf) :
|
||||
RenderFont(make_lmx(tf)),
|
||||
m_Typeface(std::move(tf))
|
||||
{}
|
||||
RenderFont(make_lmx(tf)), m_Typeface(std::move(tf)) {}
|
||||
|
||||
rive::rcp<rive::RenderFont> SkiaRenderFont::Decode(rive::Span<const uint8_t> span) {
|
||||
auto tf = SkTypeface::MakeFromData(SkData::MakeWithCopy(span.data(),
|
||||
span.size()));
|
||||
auto tf = SkTypeface::MakeFromData(SkData::MakeWithCopy(span.data(), span.size()));
|
||||
return tf ? rive::rcp<rive::RenderFont>(new SkiaRenderFont(std::move(tf))) : nullptr;
|
||||
}
|
||||
|
||||
@@ -45,7 +42,7 @@ std::vector<rive::RenderFont::Axis> SkiaRenderFont::getAxes() const {
|
||||
(void)m_Typeface->getVariationDesignParameters(src.data(), count);
|
||||
axes.resize(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
axes[i] = { src[i].tag, src[i].min, src[i].def, src[i].max };
|
||||
axes[i] = {src[i].tag, src[i].min, src[i].def, src[i].max};
|
||||
}
|
||||
}
|
||||
return axes;
|
||||
@@ -58,7 +55,7 @@ std::vector<rive::RenderFont::Coord> SkiaRenderFont::getCoords() const {
|
||||
|
||||
std::vector<rive::RenderFont::Coord> coords(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
coords[i] = { skcoord[i].axis, skcoord[i].value };
|
||||
coords[i] = {skcoord[i].axis, skcoord[i].value};
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
@@ -98,13 +95,27 @@ rive::RawPath SkiaRenderFont::getPath(rive::GlyphID glyph) const {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
switch (iter.next(pts)) {
|
||||
case SkPath::kMove_Verb: rpath.move (rv(pts[0])); break;
|
||||
case SkPath::kLine_Verb: rpath.line (rv(pts[1])); break;
|
||||
case SkPath::kQuad_Verb: rpath.quad (rv(pts[1]), rv(pts[2])); break;
|
||||
case SkPath::kConic_Verb: rpath.quad (rv(pts[1]), rv(pts[2])); break; // TODO: convert
|
||||
case SkPath::kCubic_Verb: rpath.cubic(rv(pts[1]), rv(pts[2]), rv(pts[3])); break;
|
||||
case SkPath::kClose_Verb: rpath.close(); break;
|
||||
case SkPath::kDone_Verb: done = true; break;
|
||||
case SkPath::kMove_Verb:
|
||||
rpath.move(rv(pts[0]));
|
||||
break;
|
||||
case SkPath::kLine_Verb:
|
||||
rpath.line(rv(pts[1]));
|
||||
break;
|
||||
case SkPath::kQuad_Verb:
|
||||
rpath.quad(rv(pts[1]), rv(pts[2]));
|
||||
break;
|
||||
case SkPath::kConic_Verb:
|
||||
rpath.quad(rv(pts[1]), rv(pts[2]));
|
||||
break; // TODO: convert
|
||||
case SkPath::kCubic_Verb:
|
||||
rpath.cubic(rv(pts[1]), rv(pts[2]), rv(pts[3]));
|
||||
break;
|
||||
case SkPath::kClose_Verb:
|
||||
rpath.close();
|
||||
break;
|
||||
case SkPath::kDone_Verb:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rpath;
|
||||
@@ -112,9 +123,12 @@ rive::RawPath SkiaRenderFont::getPath(rive::GlyphID glyph) const {
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
static float shapeRun(rive::RenderGlyphRun* grun, const rive::RenderTextRun& trun,
|
||||
const rive::Unichar text[], size_t textOffset, float origin) {
|
||||
const int glyphCount = SkToInt(trun.unicharCount); // simple shaper, no ligatures
|
||||
static float shapeRun(rive::RenderGlyphRun* grun,
|
||||
const rive::RenderTextRun& trun,
|
||||
const rive::Unichar text[],
|
||||
size_t textOffset,
|
||||
float origin) {
|
||||
const int glyphCount = SkToInt(trun.unicharCount); // simple shaper, no ligatures
|
||||
|
||||
grun->font = trun.font;
|
||||
grun->size = trun.size;
|
||||
|
||||
@@ -256,17 +256,17 @@ rcp<RenderBuffer> SkiaFactory::makeBufferU32(Span<const uint32_t> data) {
|
||||
return make_buffer(data);
|
||||
}
|
||||
|
||||
rcp<RenderBuffer> SkiaFactory::makeBufferF32(Span<const float> data) {
|
||||
return make_buffer(data);
|
||||
}
|
||||
rcp<RenderBuffer> SkiaFactory::makeBufferF32(Span<const float> data) { return make_buffer(data); }
|
||||
|
||||
rcp<RenderShader> SkiaFactory::makeLinearGradient(float sx, float sy,
|
||||
float ex, float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode mode,
|
||||
const Mat2D* localMatrix) {
|
||||
rcp<RenderShader> SkiaFactory::makeLinearGradient(float sx,
|
||||
float sy,
|
||||
float ex,
|
||||
float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode mode,
|
||||
const Mat2D* localMatrix) {
|
||||
const SkPoint pts[] = {{sx, sy}, {ex, ey}};
|
||||
const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
|
||||
auto sh = SkGradientShader::MakeLinear(
|
||||
@@ -274,12 +274,14 @@ rcp<RenderShader> SkiaFactory::makeLinearGradient(float sx, float sy,
|
||||
return rcp<RenderShader>(new SkiaRenderShader(std::move(sh)));
|
||||
}
|
||||
|
||||
rcp<RenderShader> SkiaFactory::makeRadialGradient(float cx, float cy, float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode mode,
|
||||
const Mat2D* localMatrix) {
|
||||
rcp<RenderShader> SkiaFactory::makeRadialGradient(float cx,
|
||||
float cy,
|
||||
float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode mode,
|
||||
const Mat2D* localMatrix) {
|
||||
const SkMatrix lm = localMatrix ? ToSkia::convert(*localMatrix) : SkMatrix();
|
||||
auto sh = SkGradientShader::MakeRadial(
|
||||
{cx, cy}, radius, (const SkColor*)colors, stops, count, ToSkia::convert(mode), 0, &lm);
|
||||
@@ -289,17 +291,18 @@ rcp<RenderShader> SkiaFactory::makeRadialGradient(float cx, float cy, float radi
|
||||
std::unique_ptr<RenderPath> SkiaFactory::makeRenderPath(Span<const Vec2D> points,
|
||||
Span<const uint8_t> verbs,
|
||||
FillRule fillRule) {
|
||||
const bool isVolatile = false; // ???
|
||||
const bool isVolatile = false; // ???
|
||||
const SkScalar* conicWeights = nullptr;
|
||||
const int conicWeightCount = 0;
|
||||
return std::make_unique<SkiaRenderPath>(SkPath::Make(reinterpret_cast<const SkPoint*>(points.data()),
|
||||
points.count(),
|
||||
verbs.data(),
|
||||
verbs.count(),
|
||||
conicWeights,
|
||||
conicWeightCount,
|
||||
ToSkia::convert(fillRule),
|
||||
isVolatile));
|
||||
return std::make_unique<SkiaRenderPath>(
|
||||
SkPath::Make(reinterpret_cast<const SkPoint*>(points.data()),
|
||||
points.count(),
|
||||
verbs.data(),
|
||||
verbs.count(),
|
||||
conicWeights,
|
||||
conicWeightCount,
|
||||
ToSkia::convert(fillRule),
|
||||
isVolatile));
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPath> SkiaFactory::makeEmptyRenderPath() {
|
||||
@@ -323,10 +326,10 @@ std::unique_ptr<RenderImage> SkiaFactory::decodeImage(Span<const uint8_t> encode
|
||||
ImageInfo info;
|
||||
auto pixels = this->platformDecode(encoded, &info);
|
||||
if (pixels.size() > 0) {
|
||||
auto ct = info.colorType == ColorType::rgba ? kRGBA_8888_SkColorType
|
||||
: kBGRA_8888_SkColorType;
|
||||
auto at = info.alphaType == AlphaType::premul ? kPremul_SkAlphaType
|
||||
: kOpaque_SkAlphaType;
|
||||
auto ct =
|
||||
info.colorType == ColorType::rgba ? kRGBA_8888_SkColorType : kBGRA_8888_SkColorType;
|
||||
auto at =
|
||||
info.alphaType == AlphaType::premul ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
|
||||
auto skinfo = SkImageInfo::Make(info.width, info.height, ct, at);
|
||||
image = SkImage::MakeRasterCopy({skinfo, pixels.data(), info.rowBytes});
|
||||
}
|
||||
|
||||
@@ -7,45 +7,44 @@
|
||||
|
||||
namespace rive {
|
||||
|
||||
ContourMeasure::ContourMeasure(const RawPath& path) {
|
||||
auto skpath = ToSkia::convert(path);
|
||||
m_meas = SkContourMeasureIter(skpath, false).next().release();
|
||||
}
|
||||
|
||||
ContourMeasure::~ContourMeasure() {
|
||||
m_meas->unref();
|
||||
}
|
||||
|
||||
float ContourMeasure::length() const { return m_meas->length(); }
|
||||
|
||||
bool ContourMeasure::computePosTan(float distance, Vec2D* pos, Vec2D* tan) const {
|
||||
return m_meas->getPosTan(distance, (SkPoint*)pos, (SkPoint*)tan);
|
||||
}
|
||||
|
||||
RawPath ContourMeasure::warp(const RawPath& src) const {
|
||||
RawPath dst;
|
||||
|
||||
RawPath::Iter iter(src);
|
||||
while (auto rec = iter.next()) {
|
||||
switch (rec.verb) {
|
||||
case PathVerb::move:
|
||||
dst.move(this->warp(rec.pts[0]));
|
||||
break;
|
||||
case PathVerb::line:
|
||||
dst.line(this->warp(rec.pts[0]));
|
||||
break;
|
||||
case PathVerb::quad:
|
||||
dst.quad(this->warp(rec.pts[0]), this->warp(rec.pts[1]));
|
||||
break;
|
||||
case PathVerb::cubic:
|
||||
dst.cubic(this->warp(rec.pts[0]), this->warp(rec.pts[1]), this->warp(rec.pts[2]));
|
||||
break;
|
||||
case PathVerb::close:
|
||||
dst.close();
|
||||
break;
|
||||
}
|
||||
ContourMeasure::ContourMeasure(const RawPath& path) {
|
||||
auto skpath = ToSkia::convert(path);
|
||||
m_meas = SkContourMeasureIter(skpath, false).next().release();
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
}
|
||||
ContourMeasure::~ContourMeasure() { m_meas->unref(); }
|
||||
|
||||
float ContourMeasure::length() const { return m_meas->length(); }
|
||||
|
||||
bool ContourMeasure::computePosTan(float distance, Vec2D* pos, Vec2D* tan) const {
|
||||
return m_meas->getPosTan(distance, (SkPoint*)pos, (SkPoint*)tan);
|
||||
}
|
||||
|
||||
RawPath ContourMeasure::warp(const RawPath& src) const {
|
||||
RawPath dst;
|
||||
|
||||
RawPath::Iter iter(src);
|
||||
while (auto rec = iter.next()) {
|
||||
switch (rec.verb) {
|
||||
case PathVerb::move:
|
||||
dst.move(this->warp(rec.pts[0]));
|
||||
break;
|
||||
case PathVerb::line:
|
||||
dst.line(this->warp(rec.pts[0]));
|
||||
break;
|
||||
case PathVerb::quad:
|
||||
dst.quad(this->warp(rec.pts[0]), this->warp(rec.pts[1]));
|
||||
break;
|
||||
case PathVerb::cubic:
|
||||
dst.cubic(
|
||||
this->warp(rec.pts[0]), this->warp(rec.pts[1]), this->warp(rec.pts[2]));
|
||||
break;
|
||||
case PathVerb::close:
|
||||
dst.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
} // namespace rive
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace rive {
|
||||
|
||||
class ContourMeasure {
|
||||
SkContourMeasure* m_meas;
|
||||
|
||||
public:
|
||||
ContourMeasure(const RawPath& path);
|
||||
~ContourMeasure();
|
||||
@@ -38,6 +39,6 @@ namespace rive {
|
||||
|
||||
RawPath warp(const RawPath&) const;
|
||||
};
|
||||
}
|
||||
} // namespace rive
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,12 +9,11 @@
|
||||
|
||||
class ImageContent : public ViewerContent {
|
||||
sk_sp<SkImage> m_image;
|
||||
|
||||
public:
|
||||
ImageContent(sk_sp<SkImage> image) : m_image(std::move(image)) {}
|
||||
|
||||
void handleDraw(SkCanvas* canvas, double) override {
|
||||
canvas->drawImage(m_image, 0, 0);
|
||||
}
|
||||
void handleDraw(SkCanvas* canvas, double) override { canvas->drawImage(m_image, 0, 0); }
|
||||
|
||||
void handleResize(int width, int height) override {}
|
||||
void handleImgui() override {}
|
||||
|
||||
@@ -178,7 +178,7 @@ int main() {
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (gContent) {
|
||||
gContent->handleImgui();
|
||||
gContent->handleImgui();
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
@@ -188,7 +188,7 @@ int main() {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
gContent = nullptr; // force delete now, so we can clean up
|
||||
gContent = nullptr; // force delete now, so we can clean up
|
||||
|
||||
// Cleanup Skia.
|
||||
surface = nullptr;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "skia_renderer.hpp"
|
||||
#include "viewer_content.hpp"
|
||||
|
||||
|
||||
// ImGui wants raw pointers to names, but our public API returns
|
||||
// names as strings (by value), so we cache these names each time we
|
||||
// load a file
|
||||
@@ -40,11 +39,9 @@ double GetSecondsToday() {
|
||||
hours -= 12;
|
||||
}
|
||||
|
||||
auto secs = (double)hours * 60 * 60 +
|
||||
(double)tstruct.tm_min * 60 +
|
||||
(double)tstruct.tm_sec;
|
||||
// printf("%d %d %d\n", tstruct.tm_sec, tstruct.tm_min, hours);
|
||||
// printf("%g %g %g\n", secs, secs/60, secs/60/60);
|
||||
auto secs = (double)hours * 60 * 60 + (double)tstruct.tm_min * 60 + (double)tstruct.tm_sec;
|
||||
// printf("%d %d %d\n", tstruct.tm_sec, tstruct.tm_min, hours);
|
||||
// printf("%g %g %g\n", secs, secs/60, secs/60/60);
|
||||
return secs;
|
||||
}
|
||||
|
||||
@@ -53,7 +50,6 @@ double GetSecondsToday() {
|
||||
// it.
|
||||
std::vector<uint8_t> fileBytes;
|
||||
|
||||
|
||||
static void loadNames(const rive::Artboard* ab) {
|
||||
animationNames.clear();
|
||||
stateMachineNames.clear();
|
||||
@@ -70,12 +66,12 @@ static void loadNames(const rive::Artboard* ab) {
|
||||
class SceneContent : public ViewerContent {
|
||||
std::string m_filename;
|
||||
std::unique_ptr<rive::File> m_file;
|
||||
|
||||
|
||||
std::unique_ptr<rive::ArtboardInstance> m_artboardInstance;
|
||||
std::unique_ptr<rive::Scene> m_currentScene;
|
||||
int m_animationIndex = 0;
|
||||
int m_stateMachineIndex = -1;
|
||||
|
||||
|
||||
int m_width = 0, m_height = 0;
|
||||
rive::Vec2D m_lastPointer;
|
||||
rive::Mat2D m_inverseViewTransform;
|
||||
@@ -135,9 +131,7 @@ class SceneContent : public ViewerContent {
|
||||
|
||||
public:
|
||||
SceneContent(const char filename[], std::unique_ptr<rive::File> file) :
|
||||
m_filename(filename),
|
||||
m_file(std::move(file))
|
||||
{
|
||||
m_filename(filename), m_file(std::move(file)) {
|
||||
initStateMachine(REQUEST_DEFAULT_SCENE);
|
||||
}
|
||||
|
||||
@@ -168,7 +162,7 @@ public:
|
||||
if (m_currentScene) {
|
||||
// See if we can "set the time" e.g. clock statemachine
|
||||
if (auto num = m_currentScene->getNumber("isTime")) {
|
||||
num->value(GetSecondsToday()/60/60);
|
||||
num->value(GetSecondsToday() / 60 / 60);
|
||||
}
|
||||
|
||||
m_currentScene->advanceAndApply(elapsed);
|
||||
|
||||
@@ -15,32 +15,34 @@ using RenderFontTextRuns = std::vector<rive::RenderTextRun>;
|
||||
using RenderFontGlyphRuns = std::vector<rive::RenderGlyphRun>;
|
||||
using RenderFontFactory = rive::rcp<rive::RenderFont> (*)(const rive::Span<const uint8_t>);
|
||||
|
||||
static bool ws(rive::Unichar c) {
|
||||
return c <= ' ';
|
||||
}
|
||||
static bool ws(rive::Unichar c) { return c <= ' '; }
|
||||
|
||||
std::vector<int> compute_word_breaks(rive::Span<rive::Unichar> chars) {
|
||||
std::vector<int> breaks;
|
||||
|
||||
const unsigned len = chars.size();
|
||||
for (unsigned i = 0; i < len;) {
|
||||
// skip ws
|
||||
while (i < len && ws(chars[i])) {
|
||||
++i;
|
||||
}
|
||||
breaks.push_back(i); // word start
|
||||
// skip non-ws
|
||||
while (i < len && !ws(chars[i])) {
|
||||
++i;
|
||||
}
|
||||
breaks.push_back(i); // word end
|
||||
// skip ws
|
||||
while (i < len && ws(chars[i])) {
|
||||
++i;
|
||||
}
|
||||
breaks.push_back(i); // word start
|
||||
// skip non-ws
|
||||
while (i < len && !ws(chars[i])) {
|
||||
++i;
|
||||
}
|
||||
breaks.push_back(i); // word end
|
||||
}
|
||||
assert(breaks[breaks.size()-1] == len);
|
||||
assert(breaks[breaks.size() - 1] == len);
|
||||
return breaks;
|
||||
}
|
||||
|
||||
static void drawrun(rive::Factory* factory, rive::Renderer* renderer,
|
||||
const rive::RenderGlyphRun& run, unsigned startIndex, unsigned endIndex, rive::Vec2D origin) {
|
||||
static void drawrun(rive::Factory* factory,
|
||||
rive::Renderer* renderer,
|
||||
const rive::RenderGlyphRun& run,
|
||||
unsigned startIndex,
|
||||
unsigned endIndex,
|
||||
rive::Vec2D origin) {
|
||||
auto font = run.font.get();
|
||||
const auto scale = rive::Mat2D::fromScale(run.size, run.size);
|
||||
auto paint = factory->makeRenderPaint();
|
||||
@@ -51,12 +53,14 @@ static void drawrun(rive::Factory* factory, rive::Renderer* renderer,
|
||||
auto trans = rive::Mat2D::fromTranslate(origin.x + run.xpos[i], origin.y);
|
||||
auto rawpath = font->getPath(run.glyphs[i]);
|
||||
rawpath.transformInPlace(trans * scale);
|
||||
auto path = factory->makeRenderPath(rawpath.points(), rawpath.verbsU8(), rive::FillRule::nonZero);
|
||||
auto path =
|
||||
factory->makeRenderPath(rawpath.points(), rawpath.verbsU8(), rive::FillRule::nonZero);
|
||||
renderer->drawPath(path.get(), paint.get());
|
||||
}
|
||||
}
|
||||
|
||||
static void drawpara(rive::Factory* factory, rive::Renderer* renderer,
|
||||
static void drawpara(rive::Factory* factory,
|
||||
rive::Renderer* renderer,
|
||||
rive::Span<const rive::RenderGlyphLine> lines,
|
||||
rive::Span<const rive::RenderGlyphRun> runs,
|
||||
rive::Vec2D origin) {
|
||||
@@ -66,7 +70,11 @@ static void drawpara(rive::Factory* factory, rive::Renderer* renderer,
|
||||
for (int runIndex = line.startRun; runIndex <= line.endRun; ++runIndex) {
|
||||
const auto& run = runs[runIndex];
|
||||
int endGIndex = runIndex == line.endRun ? line.endIndex : run.glyphs.size();
|
||||
drawrun(factory, renderer, run, startGIndex, endGIndex,
|
||||
drawrun(factory,
|
||||
renderer,
|
||||
run,
|
||||
startGIndex,
|
||||
endGIndex,
|
||||
{origin.x - x0, origin.y + line.baseline});
|
||||
startGIndex = 0;
|
||||
}
|
||||
@@ -96,13 +104,14 @@ static rive::SkiaFactory skiaFactory;
|
||||
|
||||
static rive::RenderTextRun append(std::vector<rive::Unichar>* unichars,
|
||||
rive::rcp<rive::RenderFont> font,
|
||||
float size, const char text[]) {
|
||||
float size,
|
||||
const char text[]) {
|
||||
uint32_t n = 0;
|
||||
while (text[n]) {
|
||||
unichars->push_back(text[n]); // todo: utf8 -> unichar
|
||||
unichars->push_back(text[n]); // todo: utf8 -> unichar
|
||||
n += 1;
|
||||
}
|
||||
return { std::move(font), size, n };
|
||||
return {std::move(font), size, n};
|
||||
}
|
||||
|
||||
class TextContent : public ViewerContent {
|
||||
@@ -133,8 +142,7 @@ class TextContent : public ViewerContent {
|
||||
assert(font0);
|
||||
assert(font1);
|
||||
|
||||
rive::RenderFont::Coord c1 = {'wght', 100.f},
|
||||
c2 = {'wght', 800.f};
|
||||
rive::RenderFont::Coord c1 = {'wght', 100.f}, c2 = {'wght', 800.f};
|
||||
|
||||
RenderFontTextRuns truns;
|
||||
|
||||
@@ -157,19 +165,19 @@ public:
|
||||
};
|
||||
for (auto f : factory) {
|
||||
auto truns = this->make_truns(f);
|
||||
m_gruns.push_back(truns[0].font->shapeText(rive::toSpan(m_unichars),
|
||||
rive::toSpan(truns)));
|
||||
m_gruns.push_back(
|
||||
truns[0].font->shapeText(rive::toSpan(m_unichars), rive::toSpan(truns)));
|
||||
}
|
||||
|
||||
m_xform = rive::Mat2D::fromTranslate(10, 0)
|
||||
* rive::Mat2D::fromScale(3, 3);
|
||||
m_xform = rive::Mat2D::fromTranslate(10, 0) * rive::Mat2D::fromScale(3, 3);
|
||||
}
|
||||
|
||||
void draw(rive::Renderer* renderer, float width, const RenderFontGlyphRuns& gruns) {
|
||||
renderer->save();
|
||||
renderer->transform(m_xform);
|
||||
|
||||
auto lines = rive::RenderGlyphLine::BreakLines(rive::toSpan(gruns), rive::toSpan(m_breaks), width);
|
||||
auto lines =
|
||||
rive::RenderGlyphLine::BreakLines(rive::toSpan(gruns), rive::toSpan(m_breaks), width);
|
||||
|
||||
drawpara(&skiaFactory, renderer, rive::toSpan(lines), rive::toSpan(gruns), {0, 0});
|
||||
draw_line(&skiaFactory, renderer, width);
|
||||
@@ -184,13 +192,12 @@ public:
|
||||
this->draw(&renderer, m_width, grun);
|
||||
renderer.translate(1200, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void handleResize(int width, int height) override {}
|
||||
void handleImgui() override {
|
||||
ImGui::Begin("text", nullptr);
|
||||
ImGui::SliderFloat("Alignment", &m_width, 10, 400);
|
||||
ImGui::SliderFloat("Alignment", &m_width, 10, 400);
|
||||
ImGui::End();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,17 +24,15 @@ void visit(const std::vector<RenderGlyphRun>& gruns, Vec2D origin, Handler proc)
|
||||
for (const auto& gr : gruns) {
|
||||
for (size_t i = 0; i < gr.glyphs.size(); ++i) {
|
||||
auto path = gr.font->getPath(gr.glyphs[i]);
|
||||
auto mx = Mat2D::fromTranslate(origin.x + gr.xpos[i], origin.y)
|
||||
* Mat2D::fromScale(gr.size, gr.size);
|
||||
auto mx = Mat2D::fromTranslate(origin.x + gr.xpos[i], origin.y) *
|
||||
Mat2D::fromScale(gr.size, gr.size);
|
||||
path.transformInPlace(mx);
|
||||
proc(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Vec2D ave(Vec2D a, Vec2D b) {
|
||||
return (a + b) * 0.5f;
|
||||
}
|
||||
static Vec2D ave(Vec2D a, Vec2D b) { return (a + b) * 0.5f; }
|
||||
|
||||
static RawPath make_quad_path(Span<const Vec2D> pts) {
|
||||
const int N = pts.size();
|
||||
@@ -47,9 +45,9 @@ static RawPath make_quad_path(Span<const Vec2D> pts) {
|
||||
path.quad(pts[1], pts[2]);
|
||||
} else {
|
||||
for (int i = 1; i < N - 2; ++i) {
|
||||
path.quad(pts[i], ave(pts[i], pts[i+1]));
|
||||
path.quad(pts[i], ave(pts[i], pts[i + 1]));
|
||||
}
|
||||
path.quad(pts[N-2], pts[N-1]);
|
||||
path.quad(pts[N - 2], pts[N - 1]);
|
||||
}
|
||||
}
|
||||
return path;
|
||||
@@ -96,14 +94,14 @@ static void fill_point(Renderer* renderer, Vec2D p, float r, RenderPaint* paint)
|
||||
|
||||
typedef rcp<RenderFont> (*RenderFontFactory)(Span<const uint8_t>);
|
||||
|
||||
static RenderTextRun append(std::vector<Unichar>* unichars, rcp<RenderFont> font,
|
||||
float size, const char text[]) {
|
||||
static RenderTextRun
|
||||
append(std::vector<Unichar>* unichars, rcp<RenderFont> font, float size, const char text[]) {
|
||||
uint32_t n = 0;
|
||||
while (text[n]) {
|
||||
unichars->push_back(text[n]); // todo: utf8 -> unichar
|
||||
unichars->push_back(text[n]); // todo: utf8 -> unichar
|
||||
n += 1;
|
||||
}
|
||||
return { std::move(font), size, n };
|
||||
return {std::move(font), size, n};
|
||||
}
|
||||
|
||||
class TextPathContent : public ViewerContent {
|
||||
@@ -113,7 +111,7 @@ class TextPathContent : public ViewerContent {
|
||||
AABB m_gbounds;
|
||||
|
||||
std::vector<Vec2D> m_pathpts;
|
||||
Vec2D m_lastPt = {0,0};
|
||||
Vec2D m_lastPt = {0, 0};
|
||||
int m_trackingIndex = -1;
|
||||
Mat2D m_trans;
|
||||
|
||||
@@ -121,11 +119,9 @@ class TextPathContent : public ViewerContent {
|
||||
bool m_trackingOneLine = false;
|
||||
float m_oneLineX = 0;
|
||||
|
||||
float m_alignment = 0,
|
||||
m_scaleY = 1,
|
||||
m_offsetY = 0,
|
||||
m_windowWidth = 1, // %
|
||||
m_windowOffset = 0; // %
|
||||
float m_alignment = 0, m_scaleY = 1, m_offsetY = 0,
|
||||
m_windowWidth = 1, // %
|
||||
m_windowOffset = 0; // %
|
||||
|
||||
RenderFontTextRuns make_truns(RenderFontFactory fact) {
|
||||
auto loader = [fact](const char filename[]) -> rcp<RenderFont> {
|
||||
@@ -147,8 +143,7 @@ class TextPathContent : public ViewerContent {
|
||||
assert(font0);
|
||||
assert(font1);
|
||||
|
||||
RenderFont::Coord c1 = {'wght', 100.f},
|
||||
c2 = {'wght', 800.f};
|
||||
RenderFont::Coord c1 = {'wght', 100.f}, c2 = {'wght', 800.f};
|
||||
|
||||
RenderFontTextRuns truns;
|
||||
|
||||
@@ -185,7 +180,7 @@ public:
|
||||
m_paint = skiaFactory.makeRenderPaint();
|
||||
m_paint->color(0xFFFFFFFF);
|
||||
|
||||
m_pathpts.push_back({ 20, 300});
|
||||
m_pathpts.push_back({20, 300});
|
||||
m_pathpts.push_back({220, 100});
|
||||
m_pathpts.push_back({420, 500});
|
||||
m_pathpts.push_back({620, 100});
|
||||
@@ -213,15 +208,13 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
void modify(float amount) {
|
||||
m_paint->color(0xFFFFFFFF);
|
||||
}
|
||||
void modify(float amount) { m_paint->color(0xFFFFFFFF); }
|
||||
|
||||
void draw(Renderer* renderer, const RenderFontGlyphRuns& gruns) {
|
||||
auto get_path = [this](const RenderGlyphRun& run, int index, float dx) {
|
||||
auto path = run.font->getPath(run.glyphs[index]);
|
||||
path.transformInPlace(Mat2D::fromTranslate(run.xpos[index] + dx, m_offsetY)
|
||||
* Mat2D::fromScale(run.size, run.size * m_scaleY));
|
||||
path.transformInPlace(Mat2D::fromTranslate(run.xpos[index] + dx, m_offsetY) *
|
||||
Mat2D::fromScale(run.size, run.size * m_scaleY));
|
||||
return path;
|
||||
};
|
||||
|
||||
@@ -268,10 +261,16 @@ public:
|
||||
const float radius = 50;
|
||||
if (m_trackingOneLine) {
|
||||
float mx = m_oneLineX / m_gbounds.width();
|
||||
const ColorInt colors[] = { 0xFF88FFFF, 0xFF88FFFF, 0xFFFFFFFF, 0xFF88FFFF, 0xFF88FFFF };
|
||||
const float stops[] = { 0, mx / 2, mx, (1 + mx) / 2, 1 };
|
||||
paint->shader(skiaFactory.makeLinearGradient(m_gbounds.left(), 0, m_gbounds.right(), 0,
|
||||
colors, stops, 5, RenderTileMode::clamp));
|
||||
const ColorInt colors[] = {0xFF88FFFF, 0xFF88FFFF, 0xFFFFFFFF, 0xFF88FFFF, 0xFF88FFFF};
|
||||
const float stops[] = {0, mx / 2, mx, (1 + mx) / 2, 1};
|
||||
paint->shader(skiaFactory.makeLinearGradient(m_gbounds.left(),
|
||||
0,
|
||||
m_gbounds.right(),
|
||||
0,
|
||||
colors,
|
||||
stops,
|
||||
5,
|
||||
RenderTileMode::clamp));
|
||||
}
|
||||
|
||||
auto wrap_path = [](const RawPath& src, float x, float rad) {
|
||||
@@ -333,9 +332,7 @@ public:
|
||||
}
|
||||
}
|
||||
void handlePointerDown() override {
|
||||
auto close_to = [](Vec2D a, Vec2D b) {
|
||||
return Vec2D::distance(a, b) <= 10;
|
||||
};
|
||||
auto close_to = [](Vec2D a, Vec2D b) { return Vec2D::distance(a, b) <= 10; };
|
||||
for (size_t i = 0; i < m_pathpts.size(); ++i) {
|
||||
if (close_to(m_lastPt, m_pathpts[i])) {
|
||||
m_trackingIndex = i;
|
||||
@@ -344,19 +341,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void handlePointerUp() override {
|
||||
m_trackingIndex = -1;
|
||||
}
|
||||
void handlePointerUp() override { m_trackingIndex = -1; }
|
||||
|
||||
void handleResize(int width, int height) override {}
|
||||
|
||||
|
||||
void handleImgui() override {
|
||||
ImGui::Begin("path", nullptr);
|
||||
ImGui::SliderFloat("Alignment", &m_alignment, -3, 4);
|
||||
ImGui::SliderFloat("Scale Y", &m_scaleY, 0.25f, 3.0f);
|
||||
ImGui::SliderFloat("Offset Y", &m_offsetY, -100, 100);
|
||||
ImGui::SliderFloat("Window Offset", &m_windowOffset, -1.1f, 1.1f);
|
||||
ImGui::SliderFloat("Window Width", &m_windowWidth, 0, 1.2f);
|
||||
ImGui::SliderFloat("Alignment", &m_alignment, -3, 4);
|
||||
ImGui::SliderFloat("Scale Y", &m_scaleY, 0.25f, 3.0f);
|
||||
ImGui::SliderFloat("Offset Y", &m_offsetY, -100, 100);
|
||||
ImGui::SliderFloat("Window Offset", &m_windowOffset, -1.1f, 1.1f);
|
||||
ImGui::SliderFloat("Window Width", &m_windowWidth, 0, 1.2f);
|
||||
ImGui::End();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,17 +5,22 @@
|
||||
#include "viewer_content.hpp"
|
||||
#include "rive/rive_counter.hpp"
|
||||
|
||||
ViewerContent::~ViewerContent() {
|
||||
DumpCounters("After deleting content");
|
||||
}
|
||||
ViewerContent::~ViewerContent() { DumpCounters("After deleting content"); }
|
||||
|
||||
const char* gCounterNames[] = {
|
||||
"file", "artboard", "animation", "machine",
|
||||
"buffer", "path", "paint", "shader", "image",
|
||||
"file",
|
||||
"artboard",
|
||||
"animation",
|
||||
"machine",
|
||||
"buffer",
|
||||
"path",
|
||||
"paint",
|
||||
"shader",
|
||||
"image",
|
||||
};
|
||||
|
||||
void ViewerContent::DumpCounters(const char label[]) {
|
||||
assert(sizeof(gCounterNames)/sizeof(gCounterNames[0]) == rive::Counter::kLastType + 1);
|
||||
assert(sizeof(gCounterNames) / sizeof(gCounterNames[0]) == rive::Counter::kLastType + 1);
|
||||
|
||||
if (label == nullptr) {
|
||||
label = "Counters";
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
|
||||
// Searches all handlers and returns a content if it is found.
|
||||
static std::unique_ptr<ViewerContent> FindHandler(const char filename[]) {
|
||||
Factory factories[] = { Scene, Image, Text, TextPath };
|
||||
Factory factories[] = {Scene, Image, Text, TextPath};
|
||||
for (auto f : factories) {
|
||||
if (auto content = f(filename)) {
|
||||
return content;
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
using namespace rive;
|
||||
|
||||
BlendState1DInstance::BlendState1DInstance(const BlendState1D* blendState, ArtboardInstance* instance) :
|
||||
BlendState1DInstance::BlendState1DInstance(const BlendState1D* blendState,
|
||||
ArtboardInstance* instance) :
|
||||
BlendStateInstance<BlendState1D, BlendAnimation1D>(blendState, instance) {}
|
||||
|
||||
int BlendState1DInstance::animationIndex(float value) {
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
using namespace rive;
|
||||
|
||||
BlendStateDirectInstance::BlendStateDirectInstance(const BlendStateDirect* blendState, ArtboardInstance* instance) :
|
||||
BlendStateDirectInstance::BlendStateDirectInstance(const BlendStateDirect* blendState,
|
||||
ArtboardInstance* instance) :
|
||||
BlendStateInstance<BlendStateDirect, BlendAnimationDirect>(blendState, instance) {}
|
||||
|
||||
void BlendStateDirectInstance::advance(float seconds, Span<SMIInput*> inputs) {
|
||||
|
||||
@@ -14,8 +14,7 @@ LinearAnimationInstance::LinearAnimationInstance(const LinearAnimation* animatio
|
||||
m_TotalTime(0.0f),
|
||||
m_LastTotalTime(0.0f),
|
||||
m_SpilledTime(0.0f),
|
||||
m_Direction(1)
|
||||
{
|
||||
m_Direction(1) {
|
||||
Counter::update(Counter::kLinearAnimationInstance, +1);
|
||||
}
|
||||
|
||||
@@ -28,8 +27,7 @@ LinearAnimationInstance::LinearAnimationInstance(LinearAnimationInstance const&
|
||||
m_SpilledTime(lhs.m_SpilledTime),
|
||||
m_Direction(lhs.m_Direction),
|
||||
m_DidLoop(lhs.m_DidLoop),
|
||||
m_LoopValue(lhs.m_LoopValue)
|
||||
{
|
||||
m_LoopValue(lhs.m_LoopValue) {
|
||||
Counter::update(Counter::kLinearAnimationInstance, +1);
|
||||
}
|
||||
|
||||
@@ -151,9 +149,7 @@ float LinearAnimationInstance::speed() const { return m_Animation->speed(); }
|
||||
|
||||
float LinearAnimationInstance::startSeconds() const { return m_Animation->startSeconds(); }
|
||||
|
||||
std::string LinearAnimationInstance::name() const {
|
||||
return m_Animation->name();
|
||||
}
|
||||
std::string LinearAnimationInstance::name() const { return m_Animation->name(); }
|
||||
|
||||
bool LinearAnimationInstance::isTranslucent() const {
|
||||
return m_ArtboardInstance->isTranslucent(this);
|
||||
|
||||
@@ -7,6 +7,6 @@ NestedLinearAnimation::NestedLinearAnimation() {}
|
||||
NestedLinearAnimation::~NestedLinearAnimation() {}
|
||||
|
||||
void NestedLinearAnimation::initializeAnimation(ArtboardInstance* artboard) {
|
||||
m_AnimationInstance = std::make_unique<LinearAnimationInstance>(artboard->animation(animationId()),
|
||||
artboard);
|
||||
m_AnimationInstance =
|
||||
std::make_unique<LinearAnimationInstance>(artboard->animation(animationId()), artboard);
|
||||
}
|
||||
@@ -326,8 +326,7 @@ void StateMachineInstance::pointerUp(Vec2D position) {
|
||||
|
||||
StateMachineInstance::StateMachineInstance(const StateMachine* machine,
|
||||
ArtboardInstance* instance) :
|
||||
Scene(instance), m_Machine(machine)
|
||||
{
|
||||
Scene(instance), m_Machine(machine) {
|
||||
Counter::update(Counter::kStateMachineInstance, +1);
|
||||
|
||||
const auto count = machine->inputCount();
|
||||
|
||||
@@ -101,8 +101,9 @@ const LinearAnimation* StateTransition::exitTimeAnimation(const LayerState* from
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
AllowTransition
|
||||
StateTransition::allowed(StateInstance* stateFrom, Span<SMIInput*> inputs, bool ignoreTriggers) const {
|
||||
AllowTransition StateTransition::allowed(StateInstance* stateFrom,
|
||||
Span<SMIInput*> inputs,
|
||||
bool ignoreTriggers) const {
|
||||
if (isDisabled()) {
|
||||
return AllowTransition::no;
|
||||
}
|
||||
|
||||
@@ -585,13 +585,9 @@ StatusCode Artboard::import(ImportStack& importStack) {
|
||||
#include "rive/animation/linear_animation_instance.hpp"
|
||||
#include "rive/animation/state_machine_instance.hpp"
|
||||
|
||||
ArtboardInstance::ArtboardInstance() {
|
||||
Counter::update(Counter::kArtboardInstance, +1);
|
||||
}
|
||||
ArtboardInstance::ArtboardInstance() { Counter::update(Counter::kArtboardInstance, +1); }
|
||||
|
||||
ArtboardInstance::~ArtboardInstance() {
|
||||
Counter::update(Counter::kArtboardInstance, -1);
|
||||
}
|
||||
ArtboardInstance::~ArtboardInstance() { Counter::update(Counter::kArtboardInstance, -1); }
|
||||
|
||||
std::unique_ptr<LinearAnimationInstance> ArtboardInstance::animationAt(size_t index) {
|
||||
auto la = this->animation(index);
|
||||
|
||||
@@ -25,9 +25,7 @@ float Bone::x() const { return parent()->as<Bone>()->length(); }
|
||||
|
||||
float Bone::y() const { return 0.0f; }
|
||||
|
||||
Vec2D Bone::tipWorldTranslation() const {
|
||||
return worldTransform() * Vec2D(length(), 0);
|
||||
}
|
||||
Vec2D Bone::tipWorldTranslation() const { return worldTransform() * Vec2D(length(), 0); }
|
||||
|
||||
void Bone::addPeerConstraint(Constraint* peer) {
|
||||
assert(std::find(m_PeerConstraints.begin(), m_PeerConstraints.end(), peer) ==
|
||||
|
||||
@@ -23,10 +23,10 @@ static int encodedWeightValue(unsigned int index, unsigned int data) {
|
||||
}
|
||||
|
||||
Vec2D Weight::deform(Vec2D inPoint,
|
||||
unsigned int indices,
|
||||
unsigned int weights,
|
||||
const Mat2D& world,
|
||||
const float* boneTransforms) {
|
||||
unsigned int indices,
|
||||
unsigned int weights,
|
||||
const Mat2D& world,
|
||||
const float* boneTransforms) {
|
||||
float xx = 0, xy = 0, yx = 0, yy = 0, tx = 0, ty = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int weight = encodedWeightValue(i, weights);
|
||||
|
||||
@@ -14,7 +14,7 @@ void DistanceConstraint::constrain(TransformComponent* component) {
|
||||
|
||||
const Vec2D targetTranslation = m_Target->worldTranslation();
|
||||
const Vec2D ourTranslation = component->worldTranslation();
|
||||
|
||||
|
||||
Vec2D toTarget = ourTranslation - targetTranslation;
|
||||
float currentDistance = toTarget.length();
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
|
||||
using namespace rive;
|
||||
|
||||
static float atan2(Vec2D v) {
|
||||
return std::atan2(v.y, v.x);
|
||||
}
|
||||
static float atan2(Vec2D v) { return std::atan2(v.y, v.x); }
|
||||
|
||||
void IKConstraint::buildDependencies() {
|
||||
Super::buildDependencies();
|
||||
|
||||
@@ -109,16 +109,13 @@ static Core* readRuntimeObject(BinaryReader& reader, const RuntimeHeader& header
|
||||
}
|
||||
|
||||
File::File(Factory* factory, FileAssetResolver* assetResolver) :
|
||||
m_Factory(factory), m_AssetResolver(assetResolver)
|
||||
{
|
||||
m_Factory(factory), m_AssetResolver(assetResolver) {
|
||||
Counter::update(Counter::kFile, +1);
|
||||
|
||||
assert(factory);
|
||||
}
|
||||
|
||||
File::~File() {
|
||||
Counter::update(Counter::kFile, -1);
|
||||
}
|
||||
File::~File() { Counter::update(Counter::kFile, -1); }
|
||||
|
||||
std::unique_ptr<File> File::import(Span<const uint8_t> bytes,
|
||||
Factory* factory,
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
|
||||
using namespace rive;
|
||||
|
||||
FileAssetImporter::FileAssetImporter(FileAsset* fileAsset, FileAssetResolver* assetResolver, Factory* factory) :
|
||||
m_FileAsset(fileAsset),
|
||||
m_FileAssetResolver(assetResolver),
|
||||
m_Factory(factory)
|
||||
{}
|
||||
FileAssetImporter::FileAssetImporter(FileAsset* fileAsset,
|
||||
FileAssetResolver* assetResolver,
|
||||
Factory* factory) :
|
||||
m_FileAsset(fileAsset), m_FileAssetResolver(assetResolver), m_Factory(factory) {}
|
||||
|
||||
void FileAssetImporter::loadContents(const FileAssetContents& contents) {
|
||||
auto data = contents.bytes();
|
||||
|
||||
@@ -316,9 +316,7 @@ bool HitTester::test(FillRule rule) {
|
||||
|
||||
/////////////////////////
|
||||
|
||||
static bool cross_lt(Vec2D a, Vec2D b) {
|
||||
return a.x * b.y < a.y * b.x;
|
||||
}
|
||||
static bool cross_lt(Vec2D a, Vec2D b) { return a.x * b.y < a.y * b.x; }
|
||||
|
||||
bool HitTester::testMesh(Vec2D pt, Span<Vec2D> verts, Span<uint16_t> indices) {
|
||||
if (verts.size() < 3) {
|
||||
@@ -330,8 +328,8 @@ bool HitTester::testMesh(Vec2D pt, Span<Vec2D> verts, Span<uint16_t> indices) {
|
||||
if (CULL_BOUNDS) {
|
||||
const auto bounds = AABB(verts);
|
||||
|
||||
if (bounds.bottom() < pt.y || pt.y < bounds.top() ||
|
||||
bounds.right() < pt.x || pt.x < bounds.left()) {
|
||||
if (bounds.bottom() < pt.y || pt.y < bounds.top() || bounds.right() < pt.x ||
|
||||
pt.x < bounds.left()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -344,7 +342,7 @@ bool HitTester::testMesh(Vec2D pt, Span<Vec2D> verts, Span<uint16_t> indices) {
|
||||
auto pa = a - pt;
|
||||
auto pb = b - pt;
|
||||
auto pc = c - pt;
|
||||
|
||||
|
||||
auto ab = cross_lt(pa, pb);
|
||||
auto bc = cross_lt(pb, pc);
|
||||
auto ca = cross_lt(pc, pa);
|
||||
@@ -382,12 +380,12 @@ bool HitTester::testMesh(const IAABB& area, Span<Vec2D> verts, Span<uint16_t> in
|
||||
std::vector<int> windings(area.width() * area.height());
|
||||
const auto offset = Vec2D((float)area.left, (float)area.top);
|
||||
int* deltas = windings.data();
|
||||
|
||||
|
||||
for (size_t i = 0; i < indices.size(); i += 3) {
|
||||
const auto a = verts[indices[i + 0]] - offset;
|
||||
const auto b = verts[indices[i + 1]] - offset;
|
||||
const auto c = verts[indices[i + 2]] - offset;
|
||||
|
||||
|
||||
clip_line(area.height(), a, b, deltas, area.width());
|
||||
clip_line(area.height(), b, c, deltas, area.width());
|
||||
clip_line(area.height(), c, a, deltas, area.width());
|
||||
|
||||
@@ -26,8 +26,8 @@ Mat2D Mat2D::scale(Vec2D vec) const {
|
||||
}
|
||||
|
||||
Mat2D Mat2D::multiply(const Mat2D& a, const Mat2D& b) {
|
||||
float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5],
|
||||
b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
|
||||
float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], b0 = b[0], b1 = b[1],
|
||||
b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5];
|
||||
return {
|
||||
a0 * b0 + a2 * b1,
|
||||
a1 * b0 + a3 * b1,
|
||||
@@ -39,8 +39,8 @@ Mat2D Mat2D::multiply(const Mat2D& a, const Mat2D& b) {
|
||||
}
|
||||
|
||||
bool Mat2D::invert(Mat2D* result) const {
|
||||
float aa = m_Buffer[0], ab = m_Buffer[1], ac = m_Buffer[2],
|
||||
ad = m_Buffer[3], atx = m_Buffer[4], aty = m_Buffer[5];
|
||||
float aa = m_Buffer[0], ab = m_Buffer[1], ac = m_Buffer[2], ad = m_Buffer[3], atx = m_Buffer[4],
|
||||
aty = m_Buffer[5];
|
||||
|
||||
float det = aa * ad - ab * ac;
|
||||
if (det == 0.0f) {
|
||||
@@ -49,10 +49,10 @@ bool Mat2D::invert(Mat2D* result) const {
|
||||
det = 1.0f / det;
|
||||
|
||||
*result = {
|
||||
ad * det,
|
||||
ad * det,
|
||||
-ab * det,
|
||||
-ac * det,
|
||||
aa * det,
|
||||
aa * det,
|
||||
(ac * aty - ad * atx) * det,
|
||||
(ab * atx - aa * aty) * det,
|
||||
};
|
||||
@@ -60,8 +60,7 @@ bool Mat2D::invert(Mat2D* result) const {
|
||||
}
|
||||
|
||||
TransformComponents Mat2D::decompose() const {
|
||||
float m0 = m_Buffer[0], m1 = m_Buffer[1],
|
||||
m2 = m_Buffer[2], m3 = m_Buffer[3];
|
||||
float m0 = m_Buffer[0], m1 = m_Buffer[1], m2 = m_Buffer[2], m3 = m_Buffer[3];
|
||||
|
||||
float rotation = (float)std::atan2(m1, m0);
|
||||
float denom = m0 * m0 + m1 * m1;
|
||||
|
||||
@@ -169,20 +169,20 @@ void RawPath::addPoly(Span<const Vec2D> span, bool isClosed) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace rive {
|
||||
int path_verb_to_point_count(PathVerb v) {
|
||||
static uint8_t ptCounts[] = {
|
||||
1, // move
|
||||
1, // line
|
||||
2, // quad
|
||||
2, // conic (unused)
|
||||
3, // cubic
|
||||
0, // close
|
||||
};
|
||||
size_t index = (size_t)v;
|
||||
assert(index < sizeof(ptCounts));
|
||||
return ptCounts[index];
|
||||
}
|
||||
}
|
||||
int path_verb_to_point_count(PathVerb v) {
|
||||
static uint8_t ptCounts[] = {
|
||||
1, // move
|
||||
1, // line
|
||||
2, // quad
|
||||
2, // conic (unused)
|
||||
3, // cubic
|
||||
0, // close
|
||||
};
|
||||
size_t index = (size_t)v;
|
||||
assert(index < sizeof(ptCounts));
|
||||
return ptCounts[index];
|
||||
}
|
||||
} // namespace rive
|
||||
|
||||
RawPath::Iter::Rec RawPath::Iter::next() {
|
||||
// initialize with "false"
|
||||
|
||||
@@ -69,13 +69,9 @@ void Renderer::rotate(float radians) {
|
||||
this->transform(Mat2D(c, s, -s, c, 0, 0));
|
||||
}
|
||||
|
||||
RenderBuffer::RenderBuffer(size_t count) : m_Count(count) {
|
||||
Counter::update(Counter::kBuffer, 1);
|
||||
}
|
||||
RenderBuffer::RenderBuffer(size_t count) : m_Count(count) { Counter::update(Counter::kBuffer, 1); }
|
||||
|
||||
RenderBuffer::~RenderBuffer() {
|
||||
Counter::update(Counter::kBuffer, -1);
|
||||
}
|
||||
RenderBuffer::~RenderBuffer() { Counter::update(Counter::kBuffer, -1); }
|
||||
|
||||
RenderShader::RenderShader() { Counter::update(Counter::kShader, 1); }
|
||||
RenderShader::~RenderShader() { Counter::update(Counter::kShader, -1); }
|
||||
@@ -91,8 +87,9 @@ RenderPath::~RenderPath() { Counter::update(Counter::kPath, -1); }
|
||||
|
||||
#include "rive/render_text.hpp"
|
||||
|
||||
std::vector<RenderGlyphRun> RenderFont::shapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const {
|
||||
std::vector<RenderGlyphRun>
|
||||
RenderFont::shapeText(rive::Span<const rive::Unichar> text,
|
||||
rive::Span<const rive::RenderTextRun> runs) const {
|
||||
#ifdef DEBUG
|
||||
size_t count = 0;
|
||||
for (const auto& tr : runs) {
|
||||
|
||||
@@ -7,17 +7,11 @@ Scene::Scene(ArtboardInstance* abi) : m_ArtboardInstance(abi) {
|
||||
assert(m_ArtboardInstance->isInstance());
|
||||
}
|
||||
|
||||
float Scene::width() const {
|
||||
return m_ArtboardInstance->width();
|
||||
}
|
||||
float Scene::width() const { return m_ArtboardInstance->width(); }
|
||||
|
||||
float Scene::height() const {
|
||||
return m_ArtboardInstance->height();
|
||||
}
|
||||
float Scene::height() const { return m_ArtboardInstance->height(); }
|
||||
|
||||
void Scene::draw(Renderer* renderer) {
|
||||
m_ArtboardInstance->draw(renderer);
|
||||
}
|
||||
void Scene::draw(Renderer* renderer) { m_ArtboardInstance->draw(renderer); }
|
||||
|
||||
void Scene::pointerDown(Vec2D) {}
|
||||
void Scene::pointerMove(Vec2D) {}
|
||||
|
||||
@@ -4,14 +4,10 @@
|
||||
|
||||
using namespace rive;
|
||||
|
||||
static float clamp(float v, float lo, float hi) {
|
||||
return std::min(std::max(v, lo), hi);
|
||||
}
|
||||
static float clamp(float v, float lo, float hi) { return std::min(std::max(v, lo), hi); }
|
||||
|
||||
// Less exact, but faster, than std::lerp
|
||||
static float lerp(float from, float to, float f) {
|
||||
return from + f * (to - from);
|
||||
}
|
||||
static float lerp(float from, float to, float f) { return from + f * (to - from); }
|
||||
|
||||
void MetricsPath::reset() {
|
||||
m_ComputedLength = 0.0f;
|
||||
@@ -349,9 +345,8 @@ void MetricsPath::extractSubPart(
|
||||
}
|
||||
}
|
||||
|
||||
RenderMetricsPath::RenderMetricsPath(std::unique_ptr<RenderPath> path)
|
||||
: m_RenderPath(std::move(path))
|
||||
{}
|
||||
RenderMetricsPath::RenderMetricsPath(std::unique_ptr<RenderPath> path) :
|
||||
m_RenderPath(std::move(path)) {}
|
||||
|
||||
void RenderMetricsPath::addPath(CommandPath* path, const Mat2D& transform) {
|
||||
MetricsPath::addPath(path, transform);
|
||||
|
||||
@@ -13,9 +13,6 @@ void Vertex::xChanged() { markGeometryDirty(); }
|
||||
void Vertex::yChanged() { markGeometryDirty(); }
|
||||
|
||||
void Vertex::deform(const Mat2D& worldTransform, const float* boneTransforms) {
|
||||
m_Weight->translation() = Weight::deform(Vec2D(x(), y()),
|
||||
m_Weight->indices(),
|
||||
m_Weight->values(),
|
||||
worldTransform,
|
||||
boneTransforms);
|
||||
m_Weight->translation() = Weight::deform(
|
||||
Vec2D(x(), y()), m_Weight->indices(), m_Weight->values(), worldTransform, boneTransforms);
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
template <typename T> void checkFits() {
|
||||
int64_t min = std::numeric_limits<T>::min();
|
||||
int64_t max = std::numeric_limits<T>::max();
|
||||
REQUIRE( rive::fitsIn<T>(max+0));
|
||||
REQUIRE( rive::fitsIn<T>(min-0));
|
||||
REQUIRE(!rive::fitsIn<T>(max+1));
|
||||
REQUIRE(!rive::fitsIn<T>(min-1));
|
||||
REQUIRE(rive::fitsIn<T>(max + 0));
|
||||
REQUIRE(rive::fitsIn<T>(min - 0));
|
||||
REQUIRE(!rive::fitsIn<T>(max + 1));
|
||||
REQUIRE(!rive::fitsIn<T>(min - 1));
|
||||
}
|
||||
|
||||
TEST_CASE("fitsIn checks", "[type_conversions]") {
|
||||
@@ -36,9 +36,9 @@ template <typename T> bool checkAs(uint64_t value) {
|
||||
|
||||
p = packvarint(storage, value);
|
||||
rive::BinaryReader reader(rive::Span(storage, p - storage));
|
||||
|
||||
|
||||
auto newValue = reader.readVarUintAs<T>();
|
||||
|
||||
|
||||
if (reader.hasError()) {
|
||||
REQUIRE(newValue == 0);
|
||||
}
|
||||
@@ -47,15 +47,15 @@ template <typename T> bool checkAs(uint64_t value) {
|
||||
}
|
||||
|
||||
TEST_CASE("range checks", "[binary_reader]") {
|
||||
REQUIRE( checkAs<uint8_t>(100));
|
||||
REQUIRE( checkAs<uint16_t>(100));
|
||||
REQUIRE( checkAs<uint32_t>(100));
|
||||
REQUIRE(checkAs<uint8_t>(100));
|
||||
REQUIRE(checkAs<uint16_t>(100));
|
||||
REQUIRE(checkAs<uint32_t>(100));
|
||||
|
||||
REQUIRE(!checkAs<uint8_t>(1000));
|
||||
REQUIRE( checkAs<uint16_t>(1000));
|
||||
REQUIRE( checkAs<uint32_t>(1000));
|
||||
REQUIRE(checkAs<uint16_t>(1000));
|
||||
REQUIRE(checkAs<uint32_t>(1000));
|
||||
|
||||
REQUIRE(!checkAs<uint8_t>(100000));
|
||||
REQUIRE(!checkAs<uint16_t>(100000));
|
||||
REQUIRE( checkAs<uint32_t>(100000));
|
||||
REQUIRE(checkAs<uint32_t>(100000));
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ TEST_CASE("image assets loads correctly", "[assets]") {
|
||||
TEST_CASE("out of band image assets loads correctly", "[assets]") {
|
||||
RenderObjectLeakChecker checker;
|
||||
rive::NoOpFactory gEmptyFactory;
|
||||
|
||||
|
||||
std::string filename = "../../test/assets/out_of_band/walle.riv";
|
||||
rive::RelativeLocalAssetResolver resolver(filename, &gEmptyFactory);
|
||||
|
||||
|
||||
@@ -9,24 +9,31 @@ rcp<RenderBuffer> NoOpFactory::makeBufferU16(Span<const uint16_t>) { return null
|
||||
rcp<RenderBuffer> NoOpFactory::makeBufferU32(Span<const uint32_t>) { return nullptr; }
|
||||
rcp<RenderBuffer> NoOpFactory::makeBufferF32(Span<const float>) { return nullptr; }
|
||||
|
||||
rcp<RenderShader> NoOpFactory::makeLinearGradient(float sx, float sy,
|
||||
float ex, float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix) { return nullptr; }
|
||||
rcp<RenderShader> NoOpFactory::makeLinearGradient(float sx,
|
||||
float sy,
|
||||
float ex,
|
||||
float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rcp<RenderShader> NoOpFactory::makeRadialGradient(float cx, float cy, float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix) { return nullptr; }
|
||||
rcp<RenderShader> NoOpFactory::makeRadialGradient(float cx,
|
||||
float cy,
|
||||
float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPath> NoOpFactory::makeRenderPath(Span<const Vec2D> points,
|
||||
Span<const uint8_t> verbs,
|
||||
FillRule) {
|
||||
std::unique_ptr<RenderPath>
|
||||
NoOpFactory::makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule) {
|
||||
return std::make_unique<NoOpRenderPath>();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,24 +11,27 @@ namespace rive {
|
||||
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
|
||||
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
|
||||
|
||||
rcp<RenderShader> makeLinearGradient(float sx, float sy,
|
||||
float ex, float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
rcp<RenderShader> makeLinearGradient(float sx,
|
||||
float sy,
|
||||
float ex,
|
||||
float ey,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
|
||||
rcp<RenderShader> makeRadialGradient(float cx, float cy, float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
rcp<RenderShader> makeRadialGradient(float cx,
|
||||
float cy,
|
||||
float radius,
|
||||
const ColorInt colors[], // [count]
|
||||
const float stops[], // [count]
|
||||
size_t count,
|
||||
RenderTileMode,
|
||||
const Mat2D* localMatrix = nullptr) override;
|
||||
|
||||
std::unique_ptr<RenderPath> makeRenderPath(Span<const Vec2D> points,
|
||||
Span<const uint8_t> verbs,
|
||||
FillRule) override;
|
||||
std::unique_ptr<RenderPath>
|
||||
makeRenderPath(Span<const Vec2D> points, Span<const uint8_t> verbs, FillRule) override;
|
||||
|
||||
std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ TEST_CASE("rawpath-iter", "[rawpath]") {
|
||||
RawPath rp;
|
||||
RawPath::Iter iter(rp);
|
||||
REQUIRE(iter.next() == false);
|
||||
REQUIRE(iter.next() == false); // should be safe to call again
|
||||
REQUIRE(iter.next() == false); // should be safe to call again
|
||||
}
|
||||
{
|
||||
RawPath rp;
|
||||
@@ -136,20 +136,18 @@ TEST_CASE("rawpath-iter", "[rawpath]") {
|
||||
rp.close();
|
||||
RawPath::Iter iter(rp);
|
||||
auto rec = iter.next();
|
||||
REQUIRE((rec && is_move(rec) && eq(rec.pts[0], 1,2)));
|
||||
REQUIRE((rec && is_move(rec) && eq(rec.pts[0], 1, 2)));
|
||||
rec = iter.next();
|
||||
REQUIRE((rec && is_line(rec) && eq(rec.pts[0], 3,4)));
|
||||
REQUIRE((rec && is_line(rec) && eq(rec.pts[0], 3, 4)));
|
||||
rec = iter.next();
|
||||
REQUIRE((rec && is_quad(rec) && eq(rec.pts[0], 5,6)
|
||||
&& eq(rec.pts[1], 7,8)));
|
||||
REQUIRE((rec && is_quad(rec) && eq(rec.pts[0], 5, 6) && eq(rec.pts[1], 7, 8)));
|
||||
rec = iter.next();
|
||||
REQUIRE((rec && is_cubic(rec) && eq(rec.pts[0], 9,10)
|
||||
&& eq(rec.pts[1], 11,12)
|
||||
&& eq(rec.pts[2], 13,14)));
|
||||
REQUIRE((rec && is_cubic(rec) && eq(rec.pts[0], 9, 10) && eq(rec.pts[1], 11, 12) &&
|
||||
eq(rec.pts[2], 13, 14)));
|
||||
rec = iter.next();
|
||||
REQUIRE((rec && is_close(rec)));
|
||||
rec = iter.next();
|
||||
REQUIRE(rec == false);
|
||||
REQUIRE(iter.next() == false); // should be safe to call again
|
||||
REQUIRE(iter.next() == false); // should be safe to call again
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,9 +39,8 @@ class RenderObjectLeakChecker {
|
||||
|
||||
public:
|
||||
RenderObjectLeakChecker() {
|
||||
std::copy(rive::Counter::counts,
|
||||
rive::Counter::counts + rive::Counter::kNumTypes,
|
||||
m_before);
|
||||
std::copy(
|
||||
rive::Counter::counts, rive::Counter::counts + rive::Counter::kNumTypes, m_before);
|
||||
}
|
||||
~RenderObjectLeakChecker() {
|
||||
const int* after = rive::Counter::counts;
|
||||
|
||||
Reference in New Issue
Block a user