Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/skia/cpp/api/JsiSkAnimatedImageFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace jsi = facebook::jsi;
class JsiSkAnimatedImageFactory : public JsiSkHostObject {
public:
JSI_HOST_FUNCTION(MakeAnimatedImageFromEncoded) {
auto data = JsiSkData::fromValue(runtime, arguments[0]);
auto data = JsiSkData::fromValue(runtime, arguments[0])->getObject();
auto codec = SkAndroidCodec::MakeFromData(data);
auto image = SkAnimatedImage::Make(std::move(codec));
if (image == nullptr) {
Expand Down
2 changes: 1 addition & 1 deletion packages/skia/cpp/api/JsiSkCanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ class JsiSkCanvas : public JsiSkHostObject {
int xformsSize = static_cast<int>(transforms.size(runtime));
xforms.reserve(xformsSize);
for (int i = 0; i < xformsSize; i++) {
auto xform = JsiSkRSXform::fromValue(
auto xform = JsiSkRSXform::toRSXform(
runtime, transforms.getValueAtIndex(runtime, i).asObject(runtime));
xforms.push_back(*xform.get());
}
Expand Down
96 changes: 83 additions & 13 deletions packages/skia/cpp/api/JsiSkContourMeasure.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#pragma once

#include <atomic>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

#include <jsi/jsi.h>

#include "JsiSkHostObjects.h"
#include "jsi2/NativeObject.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
Expand All @@ -20,13 +24,29 @@ namespace RNSkia {

namespace jsi = facebook::jsi;

class JsiSkContourMeasure
: public JsiSkWrappingSkPtrHostObject<SkContourMeasure> {
/**
* Migrated from the deprecated jsi::HostObject API to the JSI NativeState
* pattern (rnwgpu::NativeObject, see cpp/jsi2/NativeObject.h).
*
* Instead of intercepting every property access through HostObject::get(),
* the methods/getters live on a shared prototype installed once per runtime,
* and the native data is attached to a plain JS object via setNativeState().
*/
class JsiSkContourMeasure : public rnwgpu::NativeObject<JsiSkContourMeasure> {
public:
// Used both for Symbol.toStringTag and (if ever installed) the global
// constructor name. The JS-facing type guard relies on __typename__ below.
static constexpr const char *CLASS_NAME = "ContourMeasure";

JsiSkContourMeasure(std::shared_ptr<RNSkPlatformContext> context,
const sk_sp<SkContourMeasure> contourMeasure)
: JsiSkWrappingSkPtrHostObject(std::move(context),
std::move(contourMeasure)) {}
sk_sp<SkContourMeasure> contourMeasure)
: rnwgpu::NativeObject<JsiSkContourMeasure>(CLASS_NAME),
_context(std::move(context)), _object(std::move(contourMeasure)) {}

// The method bodies below are unchanged from the HostObject implementation.
// They are installed on the prototype via installMethod(); because they
// return jsi::Value they take full control of argument handling (NativeObject
// forwards `arguments`/`count` and passes an undefined `thisValue`).

JSI_HOST_FUNCTION(getPosTan) {
auto dist = arguments[0].asNumber();
Expand Down Expand Up @@ -67,16 +87,66 @@ class JsiSkContourMeasure
return JsiSkPath::toValue(runtime, getContext(), builder.snapshot());
}

size_t getMemoryPressure() const override { return 1024; }
// Preserves the SkJSIInstance<"ContourMeasure"> contract on the JS side.
std::string getTypename() { return CLASS_NAME; }

size_t getMemoryPressure() override { return 1024; }

static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
installGetter(runtime, prototype, "__typename__",
&JsiSkContourMeasure::getTypename);
installMethod(runtime, prototype, "getPosTan",
&JsiSkContourMeasure::getPosTan);
installMethod(runtime, prototype, "length", &JsiSkContourMeasure::length);
installMethod(runtime, prototype, "isClosed",
&JsiSkContourMeasure::isClosed);
installMethod(runtime, prototype, "getSegment",
&JsiSkContourMeasure::getSegment);
// dispose() needs access to the JS object (`thisValue`) to lower the
// reported memory pressure, so it is installed as a raw host function
// rather than through installMethod() (which hides `thisValue`).
prototype.setProperty(
runtime, "dispose",
jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forUtf8(runtime, "dispose"), 0,
[](jsi::Runtime &rt, const jsi::Value &thisValue,
const jsi::Value * /*arguments*/,
size_t /*count*/) -> jsi::Value {
auto self = JsiSkContourMeasure::fromValue(rt, thisValue);
self->release();
if (thisValue.isObject()) {
thisValue.getObject(rt).setExternalMemoryPressure(
rt, rnwgpu::kMinMemoryPressure);
}
return jsi::Value::undefined();
}));
}

protected:
/**
* Returns the wrapped object, throwing if it has been disposed. Mirrors the
* behaviour of the former JsiSkWrapping* base classes.
*/
sk_sp<SkContourMeasure> getObject() const {
if (_disposed.load(std::memory_order_acquire)) {
throw std::runtime_error("Attempted to access a disposed object.");
}
return _object;
}

std::string getObjectType() const override { return "JsiSkContourMeasure"; }
std::shared_ptr<RNSkPlatformContext> getContext() const { return _context; }

EXPORT_JSI_API_TYPENAME(JsiSkContourMeasure, ContourMeasure)
private:
void release() {
bool expected = false;
if (_disposed.compare_exchange_strong(expected, true,
std::memory_order_acq_rel)) {
_object = nullptr;
}
}

JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkContourMeasure, getPosTan),
JSI_EXPORT_FUNC(JsiSkContourMeasure, length),
JSI_EXPORT_FUNC(JsiSkContourMeasure, isClosed),
JSI_EXPORT_FUNC(JsiSkContourMeasure, getSegment),
JSI_EXPORT_FUNC(JsiSkContourMeasure, dispose))
std::shared_ptr<RNSkPlatformContext> _context;
sk_sp<SkContourMeasure> _object;
std::atomic<bool> _disposed = {false};
};
} // namespace RNSkia
106 changes: 79 additions & 27 deletions packages/skia/cpp/api/JsiSkContourMeasureIter.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#pragma once

#include <algorithm>
#include <atomic>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <utility>

#include "JsiSkContourMeasure.h"
#include "JsiSkHostObjects.h"
#include "jsi2/NativeObject.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
Expand All @@ -19,47 +25,71 @@ namespace RNSkia {

namespace jsi = facebook::jsi;

/**
* Migrated from the deprecated jsi::HostObject API to the JSI NativeState
* pattern (rnwgpu::NativeObject, see cpp/jsi2/NativeObject.h).
*/
class JsiSkContourMeasureIter
: public JsiSkWrappingSharedPtrHostObject<SkContourMeasureIter> {
: public rnwgpu::NativeObject<JsiSkContourMeasureIter> {
public:
static constexpr const char *CLASS_NAME = "ContourMeasureIter";

JsiSkContourMeasureIter(std::shared_ptr<RNSkPlatformContext> context,
const SkPath &path, bool forceClosed,
SkScalar resScale = 1)
: JsiSkWrappingSharedPtrHostObject<SkContourMeasureIter>(
std::move(context), std::make_shared<SkContourMeasureIter>(
path, forceClosed, resScale)) {}
: rnwgpu::NativeObject<JsiSkContourMeasureIter>(CLASS_NAME),
_context(std::move(context)),
_object(std::make_shared<SkContourMeasureIter>(path, forceClosed,
resScale)) {}

JSI_HOST_FUNCTION(next) {
/**
* Returns the next contour measure, or undefined when iteration is complete.
*
* This is a typed method (not a raw jsi::Value host function): returning a
* std::shared_ptr<JsiSkContourMeasure> lets the JSIConverter / NativeObject
* pipeline wrap it automatically via JsiSkContourMeasure::create(), which
* attaches the native state and installs the shared prototype. The optional
* maps a null result to `undefined`.
*/
std::optional<std::shared_ptr<JsiSkContourMeasure>> next() {
auto next = getObject()->next();
if (next == nullptr) {
return jsi::Value::undefined();
return std::nullopt;
}
auto nextObject =
std::make_shared<JsiSkContourMeasure>(getContext(), std::move(next));

return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(runtime, nextObject,
getContext());
return std::make_shared<JsiSkContourMeasure>(getContext(),
std::move(next));
}

EXPORT_JSI_API_TYPENAME(JsiSkContourMeasureIter, ContourMeasureIter)
std::string getTypename() { return CLASS_NAME; }

JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkContourMeasureIter, next),
JSI_EXPORT_FUNC(JsiSkContourMeasureIter, dispose))

size_t getMemoryPressure() const override {
return std::max(sizeof(SkContourMeasureIter), kMinMemoryPressure);
size_t getMemoryPressure() override {
return std::max(sizeof(SkContourMeasureIter), rnwgpu::kMinMemoryPressure);
}

std::string getObjectType() const override {
return "JsiSkContourMeasureIter";
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
installGetter(runtime, prototype, "__typename__",
&JsiSkContourMeasureIter::getTypename);
installMethod(runtime, prototype, "next", &JsiSkContourMeasureIter::next);
prototype.setProperty(
runtime, "dispose",
jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forUtf8(runtime, "dispose"), 0,
[](jsi::Runtime &rt, const jsi::Value &thisValue,
const jsi::Value * /*arguments*/,
size_t /*count*/) -> jsi::Value {
auto self = JsiSkContourMeasureIter::fromValue(rt, thisValue);
self->release();
if (thisValue.isObject()) {
thisValue.getObject(rt).setExternalMemoryPressure(
rt, rnwgpu::kMinMemoryPressure);
}
return jsi::Value::undefined();
}));
}

/**
* Creates the function for construction a new instance of the
* SkContourMeasureIter wrapper
* @param context platform context
* @return A function for creating a new host object wrapper for the
* SkContourMeasureIter class
* Creates the function for constructing a new instance of the
* SkContourMeasureIter wrapper. Installed in JsiSkApi as "ContourMeasureIter".
*/
static const jsi::HostFunctionType
createCtor(std::shared_ptr<RNSkPlatformContext> context) {
Expand All @@ -69,10 +99,32 @@ class JsiSkContourMeasureIter
auto resScale = arguments[2].asNumber();
// Return the newly constructed object
auto iter = std::make_shared<JsiSkContourMeasureIter>(
std::move(context), path->snapshot(), forceClosed, resScale);
return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(runtime, iter,
context);
context, path->snapshot(), forceClosed, resScale);
return JsiSkContourMeasureIter::create(runtime, iter);
};
}

protected:
std::shared_ptr<SkContourMeasureIter> getObject() const {
if (_disposed.load(std::memory_order_acquire)) {
throw std::runtime_error("Attempted to access a disposed object.");
}
return _object;
}

std::shared_ptr<RNSkPlatformContext> getContext() const { return _context; }

private:
void release() {
bool expected = false;
if (_disposed.compare_exchange_strong(expected, true,
std::memory_order_acq_rel)) {
_object = nullptr;
}
}

std::shared_ptr<RNSkPlatformContext> _context;
std::shared_ptr<SkContourMeasureIter> _object;
std::atomic<bool> _disposed = {false};
};
} // namespace RNSkia
78 changes: 69 additions & 9 deletions packages/skia/cpp/api/JsiSkData.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
#pragma once

#include <algorithm>
#include <atomic>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

#include <jsi/jsi.h>

#include "JsiSkHostObjects.h"
#include "jsi2/NativeObject.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkStream.h"

Expand All @@ -19,19 +25,73 @@ namespace RNSkia {

namespace jsi = facebook::jsi;

class JsiSkData : public JsiSkWrappingSkPtrHostObject<SkData> {
/**
* Migrated from the deprecated jsi::HostObject API to the JSI NativeState
* pattern (rnwgpu::NativeObject, see cpp/jsi2/NativeObject.h).
*
* SkData is a leaf wrapper: it exposes only __typename__ and dispose() to JS.
* Consumers that need the wrapped sk_sp<SkData> read it back through
* JsiSkData::fromValue(rt, v)->getObject() (native object), or test for it with
* value.getObject(rt).hasNativeState<JsiSkData>(rt).
*/
class JsiSkData : public rnwgpu::NativeObject<JsiSkData> {
public:
JsiSkData(std::shared_ptr<RNSkPlatformContext> context, sk_sp<SkData> asset)
: JsiSkWrappingSkPtrHostObject(std::move(context), std::move(asset)) {}
static constexpr const char *CLASS_NAME = "Data";

size_t getMemoryPressure() const override {
auto data = getObject();
return data ? data->size() : 0;
JsiSkData(std::shared_ptr<RNSkPlatformContext> context, sk_sp<SkData> data)
: rnwgpu::NativeObject<JsiSkData>(CLASS_NAME), _context(std::move(context)),
_object(std::move(data)) {}

std::string getTypename() { return CLASS_NAME; }

size_t getMemoryPressure() override {
return _object ? std::max(_object->size(), rnwgpu::kMinMemoryPressure)
: rnwgpu::kMinMemoryPressure;
}

static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
installGetter(runtime, prototype, "__typename__", &JsiSkData::getTypename);
prototype.setProperty(
runtime, "dispose",
jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forUtf8(runtime, "dispose"), 0,
[](jsi::Runtime &rt, const jsi::Value &thisValue,
const jsi::Value * /*arguments*/,
size_t /*count*/) -> jsi::Value {
auto self = JsiSkData::fromValue(rt, thisValue);
self->release();
if (thisValue.isObject()) {
thisValue.getObject(rt).setExternalMemoryPressure(
rt, rnwgpu::kMinMemoryPressure);
}
return jsi::Value::undefined();
}));
}

std::string getObjectType() const override { return "JsiSkData"; }
/**
* Returns the wrapped object, throwing if it has been disposed. Mirrors the
* behaviour of the former JsiSkWrapping* base classes.
*/
sk_sp<SkData> getObject() const {
if (_disposed.load(std::memory_order_acquire)) {
throw std::runtime_error("Attempted to access a disposed object.");
}
return _object;
}

std::shared_ptr<RNSkPlatformContext> getContext() const { return _context; }

private:
void release() {
bool expected = false;
if (_disposed.compare_exchange_strong(expected, true,
std::memory_order_acq_rel)) {
_object = nullptr;
}
}

EXPORT_JSI_API_TYPENAME(JsiSkData, Data)
JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkData, dispose))
std::shared_ptr<RNSkPlatformContext> _context;
sk_sp<SkData> _object;
std::atomic<bool> _disposed = {false};
};
} // namespace RNSkia
Loading
Loading