diff --git a/packages/skia/cpp/api/JsiSkAnimatedImage.h b/packages/skia/cpp/api/JsiSkAnimatedImage.h index eb181ccd3b..38667f1af5 100644 --- a/packages/skia/cpp/api/JsiSkAnimatedImage.h +++ b/packages/skia/cpp/api/JsiSkAnimatedImage.h @@ -35,34 +35,31 @@ class JsiSkAnimatedImage static constexpr const char *CLASS_NAME = "AnimatedImage"; // TODO-API: Properties? - JSI_HOST_FUNCTION(getCurrentFrame) { + std::shared_ptr getCurrentFrame() { auto image = getObject()->getCurrentFrame(); - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(image))); + return std::make_shared(getContext(), std::move(image)); } - JSI_HOST_FUNCTION(getFrameCount) { - return static_cast(getObject()->getFrameCount()); - } + int getFrameCount() { return static_cast(getObject()->getFrameCount()); } - JSI_HOST_FUNCTION(currentFrameDuration) { + int currentFrameDuration() { return static_cast(getObject()->currentFrameDuration()); } - JSI_HOST_FUNCTION(decodeNextFrame) { + int decodeNextFrame() { return static_cast(getObject()->decodeNextFrame()); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "getFrameCount", - &JsiSkAnimatedImage::getFrameCount); - installHostMethod(runtime, prototype, "getCurrentFrame", - &JsiSkAnimatedImage::getCurrentFrame); - installHostMethod(runtime, prototype, "currentFrameDuration", - &JsiSkAnimatedImage::currentFrameDuration); - installHostMethod(runtime, prototype, "decodeNextFrame", - &JsiSkAnimatedImage::decodeNextFrame); + installMethod(runtime, prototype, "getFrameCount", + &JsiSkAnimatedImage::getFrameCount); + installMethod(runtime, prototype, "getCurrentFrame", + &JsiSkAnimatedImage::getCurrentFrame); + installMethod(runtime, prototype, "currentFrameDuration", + &JsiSkAnimatedImage::currentFrameDuration); + installMethod(runtime, prototype, "decodeNextFrame", + &JsiSkAnimatedImage::decodeNextFrame); } JsiSkAnimatedImage(std::shared_ptr context, diff --git a/packages/skia/cpp/api/JsiSkAnimatedImageFactory.h b/packages/skia/cpp/api/JsiSkAnimatedImageFactory.h index d6ecff500b..5c981c1455 100644 --- a/packages/skia/cpp/api/JsiSkAnimatedImageFactory.h +++ b/packages/skia/cpp/api/JsiSkAnimatedImageFactory.h @@ -2,10 +2,12 @@ #include #include +#include #include #include "JsiSkAnimatedImage.h" +#include "JsiSkConverters.h" #include "JsiSkData.h" #include "JsiSkNativeObjects.h" #include "jsi/JsiPromises.h" @@ -19,22 +21,22 @@ class JsiSkAnimatedImageFactory public: static constexpr const char *CLASS_NAME = "AnimatedImageFactory"; - JSI_HOST_FUNCTION(MakeAnimatedImageFromEncoded) { - auto data = JsiSkData::fromValue(runtime, arguments[0]); + std::variant> + MakeAnimatedImageFromEncoded(sk_sp data) { auto codec = SkAndroidCodec::MakeFromData(data); auto image = SkAnimatedImage::Make(std::move(codec)); if (image == nullptr) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(image))); + return std::make_shared(getContext(), + std::move(image)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeAnimatedImageFromEncoded", - &JsiSkAnimatedImageFactory::MakeAnimatedImageFromEncoded); + installMethod(runtime, prototype, "MakeAnimatedImageFromEncoded", + &JsiSkAnimatedImageFactory::MakeAnimatedImageFromEncoded); } explicit JsiSkAnimatedImageFactory( diff --git a/packages/skia/cpp/api/JsiSkColorFilterFactory.h b/packages/skia/cpp/api/JsiSkColorFilterFactory.h index 70e2a64d00..4776f914a2 100644 --- a/packages/skia/cpp/api/JsiSkColorFilterFactory.h +++ b/packages/skia/cpp/api/JsiSkColorFilterFactory.h @@ -2,10 +2,12 @@ #include "JsiSkColor.h" #include "JsiSkColorFilter.h" +#include "JsiSkConverters.h" #include "JsiSkNativeObjects.h" #include #include #include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -24,87 +26,67 @@ class JsiSkColorFilterFactory public: static constexpr const char *CLASS_NAME = "ColorFilterFactory"; - JSI_HOST_FUNCTION(MakeMatrix) { - auto jsiMatrix = arguments[0].asObject(runtime).asArray(runtime); - float matrix[20]; - for (int i = 0; i < 20; i++) { - if (jsiMatrix.size(runtime) > i) { - matrix[i] = jsiMatrix.getValueAtIndex(runtime, i).asNumber(); - } + std::shared_ptr MakeMatrix(std::vector values) { + float matrix[20] = {0}; + for (size_t i = 0; i < 20 && i < values.size(); i++) { + matrix[i] = values[i]; } - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), SkColorFilters::Matrix(std::move(matrix)))); + return std::make_shared(getContext(), + SkColorFilters::Matrix(matrix)); } - JSI_HOST_FUNCTION(MakeBlend) { - auto color = JsiSkColor::fromValue(runtime, arguments[0]); - SkBlendMode blend = (SkBlendMode)arguments[1].asNumber(); - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), SkColorFilters::Blend(color, blend))); + std::shared_ptr MakeBlend(JsiColor color, double blend) { + return std::make_shared( + getContext(), + SkColorFilters::Blend(color, static_cast(blend))); } - JSI_HOST_FUNCTION(MakeCompose) { - auto outer = JsiSkColorFilter::fromValue(runtime, arguments[0]); - auto inner = JsiSkColorFilter::fromValue(runtime, arguments[1]); - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), SkColorFilters::Compose(std::move(outer), - std::move(inner)))); + std::shared_ptr MakeCompose(sk_sp outer, + sk_sp inner) { + return std::make_shared( + getContext(), + SkColorFilters::Compose(std::move(outer), std::move(inner))); } - JSI_HOST_FUNCTION(MakeLerp) { - auto t = arguments[0].asNumber(); - auto dst = JsiSkColorFilter::fromValue(runtime, arguments[1]); - auto src = JsiSkColorFilter::fromValue(runtime, arguments[2]); - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), - SkColorFilters::Lerp(t, std::move(dst), std::move(src)))); + std::shared_ptr MakeLerp(double t, + sk_sp dst, + sk_sp src) { + return std::make_shared( + getContext(), SkColorFilters::Lerp(t, std::move(dst), std::move(src))); } - JSI_HOST_FUNCTION(MakeSRGBToLinearGamma) { - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), SkColorFilters::SRGBToLinearGamma())); + std::shared_ptr MakeSRGBToLinearGamma() { + return std::make_shared( + getContext(), SkColorFilters::SRGBToLinearGamma()); } - JSI_HOST_FUNCTION(MakeLinearToSRGBGamma) { - // Return the newly constructed object - return makeJsiObject( - runtime, std::make_shared( - getContext(), SkColorFilters::LinearToSRGBGamma())); + std::shared_ptr MakeLinearToSRGBGamma() { + return std::make_shared( + getContext(), SkColorFilters::LinearToSRGBGamma()); } - JSI_HOST_FUNCTION(MakeLumaColorFilter) { - // Return the newly constructed object - return makeJsiObject(runtime, std::make_shared( - getContext(), SkLumaColorFilter::Make())); + std::shared_ptr MakeLumaColorFilter() { + return std::make_shared(getContext(), + SkLumaColorFilter::Make()); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeMatrix", - &JsiSkColorFilterFactory::MakeMatrix); - installHostMethod(runtime, prototype, "MakeBlend", - &JsiSkColorFilterFactory::MakeBlend); - installHostMethod(runtime, prototype, "MakeCompose", - &JsiSkColorFilterFactory::MakeCompose); - installHostMethod(runtime, prototype, "MakeLerp", - &JsiSkColorFilterFactory::MakeLerp); - installHostMethod(runtime, prototype, "MakeSRGBToLinearGamma", - &JsiSkColorFilterFactory::MakeSRGBToLinearGamma); - installHostMethod(runtime, prototype, "MakeLinearToSRGBGamma", - &JsiSkColorFilterFactory::MakeLinearToSRGBGamma); - installHostMethod(runtime, prototype, "MakeLumaColorFilter", - &JsiSkColorFilterFactory::MakeLumaColorFilter); + installMethod(runtime, prototype, "MakeMatrix", + &JsiSkColorFilterFactory::MakeMatrix); + installMethod(runtime, prototype, "MakeBlend", + &JsiSkColorFilterFactory::MakeBlend); + installMethod(runtime, prototype, "MakeCompose", + &JsiSkColorFilterFactory::MakeCompose); + installMethod(runtime, prototype, "MakeLerp", + &JsiSkColorFilterFactory::MakeLerp); + installMethod(runtime, prototype, "MakeSRGBToLinearGamma", + &JsiSkColorFilterFactory::MakeSRGBToLinearGamma); + installMethod(runtime, prototype, "MakeLinearToSRGBGamma", + &JsiSkColorFilterFactory::MakeLinearToSRGBGamma); + installMethod(runtime, prototype, "MakeLumaColorFilter", + &JsiSkColorFilterFactory::MakeLumaColorFilter); } explicit JsiSkColorFilterFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkContourMeasure.h b/packages/skia/cpp/api/JsiSkContourMeasure.h index a0f137ddb6..c3d50a4821 100644 --- a/packages/skia/cpp/api/JsiSkContourMeasure.h +++ b/packages/skia/cpp/api/JsiSkContourMeasure.h @@ -2,10 +2,12 @@ #include #include +#include #include #include "JsiSkNativeObjects.h" +#include "JsiSkPoint.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -31,55 +33,43 @@ class JsiSkContourMeasure : JsiSkWrappingSkPtrNativeObject( std::move(context), std::move(contourMeasure)) {} - JSI_HOST_FUNCTION(getPosTan) { - auto dist = arguments[0].asNumber(); + std::vector> getPosTan(double dist) { SkPoint position; SkPoint tangent; auto result = getObject()->getPosTan(dist, &position, &tangent); if (!result) { - throw jsi::JSError(runtime, "getPosTan() failed"); + throw std::runtime_error("getPosTan() failed"); } - auto posTan = jsi::Array(runtime, 2); - auto pos = makeJsiObject( - runtime, std::make_shared(getContext(), position)); - auto tan = makeJsiObject( - runtime, std::make_shared(getContext(), tangent)); - posTan.setValueAtIndex(runtime, 0, pos); - posTan.setValueAtIndex(runtime, 1, tan); - return posTan; + return {std::make_shared(getContext(), position), + std::make_shared(getContext(), tangent)}; } - JSI_HOST_FUNCTION(length) { - return jsi::Value(SkScalarToDouble(getObject()->length())); - } + double length() { return SkScalarToDouble(getObject()->length()); } - JSI_HOST_FUNCTION(isClosed) { return jsi::Value(getObject()->isClosed()); } + bool isClosed() { return getObject()->isClosed(); } - JSI_HOST_FUNCTION(getSegment) { - auto start = arguments[0].asNumber(); - auto end = arguments[1].asNumber(); - auto startWithMoveTo = arguments[2].getBool(); + std::shared_ptr getSegment(double start, double end, + bool startWithMoveTo) { SkPathBuilder builder; auto result = getObject()->getSegment(start, end, &builder, startWithMoveTo); if (!result) { - throw jsi::JSError(runtime, "getSegment() failed"); + throw std::runtime_error("getSegment() failed"); } - return JsiSkPath::toValue(runtime, getContext(), builder.snapshot()); + return std::make_shared(getContext(), builder.snapshot()); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "getPosTan", - &JsiSkContourMeasure::getPosTan); - installHostMethod(runtime, prototype, "length", - &JsiSkContourMeasure::length); - installHostMethod(runtime, prototype, "isClosed", - &JsiSkContourMeasure::isClosed); - installHostMethod(runtime, prototype, "getSegment", - &JsiSkContourMeasure::getSegment); + installMethod(runtime, prototype, "getPosTan", + &JsiSkContourMeasure::getPosTan); + installMethod(runtime, prototype, "length", &JsiSkContourMeasure::length); + installMethod(runtime, prototype, "isClosed", + &JsiSkContourMeasure::isClosed); + installMethod(runtime, prototype, "getSegment", + &JsiSkContourMeasure::getSegment); } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkContourMeasureIter.h b/packages/skia/cpp/api/JsiSkContourMeasureIter.h index 7102cf2678..867e82068a 100644 --- a/packages/skia/cpp/api/JsiSkContourMeasureIter.h +++ b/packages/skia/cpp/api/JsiSkContourMeasureIter.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "JsiSkContourMeasure.h" @@ -33,19 +34,18 @@ class JsiSkContourMeasureIter std::move(context), std::make_shared( path, forceClosed, resScale)) {} - JSI_HOST_FUNCTION(next) { + std::optional> next() { auto next = getObject()->next(); if (next == nullptr) { - return jsi::Value::undefined(); + return std::nullopt; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(next))); + return std::make_shared(getContext(), + std::move(next)); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "next", - &JsiSkContourMeasureIter::next); + installMethod(runtime, prototype, "next", &JsiSkContourMeasureIter::next); } size_t getMemoryPressure() override { diff --git a/packages/skia/cpp/api/JsiSkConverters.h b/packages/skia/cpp/api/JsiSkConverters.h new file mode 100644 index 0000000000..39ac425f77 --- /dev/null +++ b/packages/skia/cpp/api/JsiSkConverters.h @@ -0,0 +1,378 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "jsi/JSIConverter.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include "include/core/SkColor.h" +#include "include/core/SkPoint3.h" +#include "include/core/SkRefCnt.h" +#include "include/core/SkSize.h" + +#pragma clang diagnostic pop + +// Forward declarations of the wrapped Skia types. Only the trait below needs +// them; the converter bodies are templates and are instantiated lazily, at +// which point the classes are complete. +class SkImage; +class SkShader; +class SkTypeface; +class SkColorFilter; +class SkImageFilter; +class SkMaskFilter; +class SkPathEffect; +class SkData; +class SkPicture; +class SkTextBlob; +class SkRuntimeEffect; +class SkRuntimeEffectBuilder; +class SkVertices; +class SkFontMgr; +class SkSVGDOM; +class SkPaint; +class SkFont; +class SkMatrix; +class SkPathBuilder; +struct SkRect; +struct SkPoint; +class SkRRect; +class SkFontStyle; +struct SkImageInfo; +struct SkRSXform; + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiSkImage; +class JsiSkShader; +class JsiSkTypeface; +class JsiSkColorFilter; +class JsiSkImageFilter; +class JsiSkMaskFilter; +class JsiSkPathEffect; +class JsiSkData; +class JsiSkPicture; +class JsiSkTextBlob; +class JsiSkRuntimeEffect; +class JsiSkRuntimeShaderBuilder; +class JsiSkVertices; +class JsiSkFontMgr; +class JsiSkSVG; +class JsiSkPaint; +class JsiSkFont; +class JsiSkMatrix; +class JsiSkPath; +class JsiSkRect; +class JsiSkPoint; +class JsiSkRRect; +class JsiSkFontStyle; +class JsiSkImageInfo; +class JsiSkRSXform; + +/** + * Maps a wrapped Skia type to the JsiSk* class whose `fromValue` knows how to + * read it from a JS value (including the plain-object fallbacks, e.g. SkRect + * from {x, y, width, height}). The JSIConverter specializations below are + * enabled for exactly the types listed here. + */ +template struct JsiSkWrapperFor; + +template <> struct JsiSkWrapperFor { + using type = JsiSkImage; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkShader; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkTypeface; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkColorFilter; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkImageFilter; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkMaskFilter; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkPathEffect; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkData; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkPicture; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkTextBlob; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkRuntimeEffect; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkRuntimeShaderBuilder; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkVertices; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkFontMgr; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkSVG; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkPaint; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkFont; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkMatrix; +}; +// Note: JsiSkPath wraps an SkPathBuilder (not an SkPath). +template <> struct JsiSkWrapperFor { + using type = JsiSkPath; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkRect; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkPoint; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkRRect; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkFontStyle; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkImageInfo; +}; +template <> struct JsiSkWrapperFor { + using type = JsiSkRSXform; +}; + +template +using JsiSkWrapperFor_t = typename JsiSkWrapperFor::type; + +class JsiSkColor; + +/** + * SkColor is a typedef of uint32_t, which already has a JSIConverter, so + * color arguments use this strong typedef to route through + * JsiSkColor::fromValue (array | Float32Array) instead. + */ +struct JsiColor { + SkColor color; + operator SkColor() const { return color; } +}; + +template <> struct JsiSkWrapperFor { + using type = JsiSkColor; +}; + +/** + * An argument the JS API treats as absent when it is omitted, undefined, or + * null. This matches the pervasive `hasOptionalArgument` pattern of the raw + * bindings. Use std::optional instead when null must be distinguished from + * undefined (it treats only omitted/undefined as absent). + */ +template struct JsiOptional : std::optional { + using std::optional::optional; +}; + +} // namespace RNSkia + +namespace rnwgpu { + +/** + * sk_sp arguments (SkImage, SkShader, ...). Delegates to the wrapper + * class's fromValue, so wrapper objects and any legacy fallback shapes keep + * working. Conversion is strict: null/undefined throw, matching the previous + * raw JSI_HOST_FUNCTION bodies. Arguments that explicitly accept null use + * std::variant> (see below); arguments that may be + * omitted use std::optional. + * + * There is intentionally no toJSI: building a wrapper requires the platform + * context, so methods return std::shared_ptr built with + * getContext() instead (handled by the NativeObject converter). + */ +template +struct JSIConverter, + std::void_t::type>> { + static sk_sp fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + return RNSkia::JsiSkWrapperFor_t::fromValue(runtime, arg); + } +}; + +/** + * std::shared_ptr arguments for the wrapped non-refcounted Skia types + * (SkPaint, SkFont, SkMatrix, SkRect, ...). Same rules as sk_sp above. + */ +template +struct JSIConverter, + std::void_t::type>> { + static std::shared_ptr fromJSI(jsi::Runtime &runtime, + const jsi::Value &arg, bool outOfBound) { + return RNSkia::JsiSkWrapperFor_t::fromValue(runtime, arg); + } +}; + +/** + * Nullable sk_sp arguments: JS null maps to the std::nullptr_t + * alternative, anything else goes through the strict converter above. + */ +template +struct JSIConverter>, + std::void_t::type>> { + using Target = std::variant>; + + static Target fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + if (arg.isNull()) { + return Target(nullptr); + } + return Target(JSIConverter>::fromJSI(runtime, arg, outOfBound)); + } +}; + +/** + * SkRect / SkPoint / SkMatrix / SkRSXform by value — the wrapper's fromValue + * provides the plain-object/array fallbacks. fromJSI only; returning these + * types is done through std::shared_ptr etc. (see above). + * + * All bodies below reach the wrapper through JsiSkWrapperFor_t so the + * name stays dependent on T and is only looked up at instantiation, when the + * wrapper class is complete (two-phase lookup would otherwise bind — and + * reject — the incomplete forward declaration at definition time). + */ +template +struct JSIConverter || + std::is_same_v || + std::is_same_v>> { + static T fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + return *RNSkia::JsiSkWrapperFor_t::fromValue(runtime, arg); + } +}; + +// SkPoint additionally converts back to a plain {x, y} object — this is what +// the raw bindings returned for point results (e.g. getLastPt), NOT a Point +// wrapper. Methods that should return a wrapper use +// std::shared_ptr instead. +template +struct JSIConverter>> { + static T fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + return *RNSkia::JsiSkWrapperFor_t::fromValue(runtime, arg); + } + static jsi::Value toJSI(jsi::Runtime &runtime, const T &point) { + jsi::Object result(runtime); + result.setProperty(runtime, "x", static_cast(point.x())); + result.setProperty(runtime, "y", static_cast(point.y())); + return result; + } +}; + +// Colors via the JsiColor strong typedef (see above). +template +struct JSIConverter>> { + static T fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + return {RNSkia::JsiSkWrapperFor_t::fromValue(runtime, arg)}; + } + static jsi::Value toJSI(jsi::Runtime &runtime, const T &arg) { + return RNSkia::JsiSkWrapperFor_t::toValue(runtime, arg.color); + } +}; + +// JsiOptional: omitted | undefined | null -> absent +template struct JSIConverter> { + static RNSkia::JsiOptional fromJSI(jsi::Runtime &runtime, + const jsi::Value &arg, + bool outOfBound) { + if (outOfBound || arg.isUndefined() || arg.isNull()) { + return {}; + } + return {JSIConverter::fromJSI(runtime, arg, outOfBound)}; + } + static jsi::Value toJSI(jsi::Runtime &runtime, + const RNSkia::JsiOptional &arg) { + if (!arg.has_value()) { + return jsi::Value::null(); + } + return JSIConverter::toJSI(runtime, arg.value()); + } +}; + +// SkPoint3 <- {x, y, z} +template <> struct JSIConverter { + static SkPoint3 fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + auto object = arg.asObject(runtime); + auto x = object.getProperty(runtime, "x").asNumber(); + auto y = object.getProperty(runtime, "y").asNumber(); + auto z = object.getProperty(runtime, "z").asNumber(); + return SkPoint3::Make(x, y, z); + } +}; + +// std::string | null (nullable string results) +template <> struct JSIConverter> { + using Target = std::variant; + static Target fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + if (arg.isNull()) { + return Target(nullptr); + } + return Target(JSIConverter::fromJSI(runtime, arg, outOfBound)); + } + static jsi::Value toJSI(jsi::Runtime &runtime, const Target &arg) { + if (std::holds_alternative(arg)) { + return jsi::Value::null(); + } + return JSIConverter::toJSI(runtime, std::get(arg)); + } +}; + +// SkSize -> {width, height} (fractional) +template <> struct JSIConverter { + static jsi::Value toJSI(jsi::Runtime &runtime, const SkSize &size) { + jsi::Object result(runtime); + result.setProperty(runtime, "width", static_cast(size.width())); + result.setProperty(runtime, "height", static_cast(size.height())); + return result; + } +}; + +// SkISize <> {width, height} +template <> struct JSIConverter { + static SkISize fromJSI(jsi::Runtime &runtime, const jsi::Value &arg, + bool outOfBound) { + auto object = arg.asObject(runtime); + auto width = object.getProperty(runtime, "width").asNumber(); + auto height = object.getProperty(runtime, "height").asNumber(); + return SkISize::Make(static_cast(width), + static_cast(height)); + } + static jsi::Value toJSI(jsi::Runtime &runtime, const SkISize &size) { + jsi::Object result(runtime); + result.setProperty(runtime, "width", static_cast(size.width())); + result.setProperty(runtime, "height", static_cast(size.height())); + return result; + } +}; + +} // namespace rnwgpu diff --git a/packages/skia/cpp/api/JsiSkDataFactory.h b/packages/skia/cpp/api/JsiSkDataFactory.h index 0b9cc868ab..5952700f90 100644 --- a/packages/skia/cpp/api/JsiSkDataFactory.h +++ b/packages/skia/cpp/api/JsiSkDataFactory.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -62,31 +63,24 @@ class JsiSkDataFactory : public JsiSkNativeObject { runtime, std::make_shared(getContext(), std::move(data))); } - JSI_HOST_FUNCTION(fromBase64) { - auto base64 = arguments[0].asString(runtime); - auto base64Str = base64.utf8(runtime); + std::shared_ptr fromBase64(std::string base64Str) { auto size = base64Str.size(); // Calculate length size_t len; - auto err = - Base64::Decode(&base64.utf8(runtime).c_str()[0], size, nullptr, &len); + auto err = Base64::Decode(base64Str.c_str(), size, nullptr, &len); if (err != Base64::Error::kNone) { - throw jsi::JSError(runtime, "Error decoding base64 string"); - return jsi::Value::undefined(); + throw std::runtime_error("Error decoding base64 string"); } // Create data object and decode auto data = SkData::MakeUninitialized(len); - err = Base64::Decode(&base64.utf8(runtime).c_str()[0], size, - data->writable_data(), &len); + err = Base64::Decode(base64Str.c_str(), size, data->writable_data(), &len); if (err != Base64::Error::kNone) { - throw jsi::JSError(runtime, "Error decoding base64 string"); - return jsi::Value::undefined(); + throw std::runtime_error("Error decoding base64 string"); } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(data))); + return std::make_shared(getContext(), std::move(data)); } size_t getMemoryPressure() override { return 1024; } @@ -96,8 +90,8 @@ class JsiSkDataFactory : public JsiSkNativeObject { &JsiSkDataFactory::fromURI); installHostMethod(runtime, prototype, "fromBytes", &JsiSkDataFactory::fromBytes); - installHostMethod(runtime, prototype, "fromBase64", - &JsiSkDataFactory::fromBase64); + installMethod(runtime, prototype, "fromBase64", + &JsiSkDataFactory::fromBase64); } explicit JsiSkDataFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkFont.h b/packages/skia/cpp/api/JsiSkFont.h index 0b85c4fbdf..59a0e12938 100644 --- a/packages/skia/cpp/api/JsiSkFont.h +++ b/packages/skia/cpp/api/JsiSkFont.h @@ -2,13 +2,17 @@ #include #include +#include +#include #include +#include #include #include "JsiSkNativeObjects.h" #include "utils/RNSkLog.h" #include +#include "JsiSkConverters.h" #include "JsiSkPaint.h" #include "JsiSkPoint.h" #include "JsiSkRect.h" @@ -30,39 +34,26 @@ class JsiSkFont : public JsiSkWrappingSharedPtrNativeObject { public: static constexpr const char *CLASS_NAME = "Font"; - JSI_HOST_FUNCTION(getGlyphWidths) { - auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); - std::vector glyphs; - int glyphsSize = static_cast(jsiGlyphs.size(runtime)); - - std::vector widthPtrs; - widthPtrs.resize(glyphsSize); - - glyphs.reserve(glyphsSize); - for (int i = 0; i < glyphsSize; i++) { - glyphs.push_back(jsiGlyphs.getValueAtIndex(runtime, i).asNumber()); - } - auto widths = SkSpan(static_cast(widthPtrs.data()), glyphsSize); - auto g = SkSpan(glyphs.data(), glyphs.size()); - if (count > 1) { - auto paint = JsiSkPaint::fromValue(runtime, arguments[1]); - getObject()->getWidthsBounds(g, widths, {}, paint.get()); - } else { - getObject()->getWidthsBounds(g, widths, {}, nullptr); - } - auto jsiWidths = jsi::Array(runtime, glyphsSize); - for (int i = 0; i < glyphsSize; i++) { - jsiWidths.setValueAtIndex( - runtime, i, - jsi::Value( - SkScalarToDouble(static_cast(widthPtrs.data())[i]))); + std::vector + getGlyphWidths(std::vector glyphs, + std::optional> paint) { + std::vector glyphIds; + glyphIds.reserve(glyphs.size()); + for (auto glyph : glyphs) { + glyphIds.push_back(static_cast(glyph)); } - return jsiWidths; + std::vector widths; + widths.resize(glyphIds.size()); + auto g = SkSpan(glyphIds.data(), glyphIds.size()); + auto w = SkSpan(widths.data(), widths.size()); + getObject()->getWidthsBounds( + g, w, {}, paint.has_value() ? paint.value().get() : nullptr); + return std::vector(widths.begin(), widths.end()); } // TODO: deprecate - JSI_HOST_FUNCTION(getTextWidth) { - auto str = arguments[0].asString(runtime).utf8(runtime); + int getTextWidth(std::string str, + std::optional> paint) { auto numGlyphIDs = getObject()->countText(str.c_str(), str.length(), SkTextEncoding::kUTF8); std::vector glyphs; @@ -70,33 +61,25 @@ class JsiSkFont : public JsiSkWrappingSharedPtrNativeObject { auto g = SkSpan(glyphs.data(), glyphs.size()); getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8, g); - std::vector widthPtrs; - widthPtrs.resize(numGlyphIDs); - auto widths = SkSpan(widthPtrs.data(), widthPtrs.size()); - if (count > 1) { - auto paint = JsiSkPaint::fromValue(runtime, arguments[1]); - getObject()->getWidthsBounds(g, widths, {}, paint.get()); - } else { - getObject()->getWidthsBounds(g, widths, {}, nullptr); - } - return jsi::Value(std::accumulate(widthPtrs.begin(), widthPtrs.end(), 0)); + std::vector widths; + widths.resize(numGlyphIDs); + auto w = SkSpan(widths.data(), widths.size()); + getObject()->getWidthsBounds( + g, w, {}, paint.has_value() ? paint.value().get() : nullptr); + return std::accumulate(widths.begin(), widths.end(), 0); } - JSI_HOST_FUNCTION(measureText) { - auto str = arguments[0].asString(runtime).utf8(runtime); + std::shared_ptr + measureText(std::string str, std::optional> paint) { SkRect bounds; - if (count > 1) { - auto paint = JsiSkPaint::fromValue(runtime, arguments[1]); - getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8, - &bounds, paint.get()); - } else { - getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8, - &bounds); - } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(bounds))); + getObject()->measureText(str.c_str(), str.length(), SkTextEncoding::kUTF8, + &bounds, + paint.has_value() ? paint.value().get() : nullptr); + return std::make_shared(getContext(), bounds); } + // Stays raw: the result object has a conditionally present `bounds` + // property, which a typed return value cannot express. JSI_HOST_FUNCTION(getMetrics) { SkFontMetrics fm; getObject()->getMetrics(&fm); @@ -113,178 +96,114 @@ class JsiSkFont : public JsiSkWrappingSharedPtrNativeObject { return metrics; } - JSI_HOST_FUNCTION(getGlyphIDs) { - auto str = arguments[0].asString(runtime).utf8(runtime); - int numGlyphIDs = - count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() - ? static_cast(arguments[1].asNumber()) - : getObject()->countText(str.c_str(), str.length(), - SkTextEncoding::kUTF8); + std::vector getGlyphIDs(std::string str, JsiOptional numGlyphs) { + int numGlyphIDs = numGlyphs.has_value() + ? *numGlyphs + : getObject()->countText(str.c_str(), str.length(), + SkTextEncoding::kUTF8); std::vector glyphIDs; glyphIDs.resize(numGlyphIDs); auto g = SkSpan(static_cast(glyphIDs.data()), glyphIDs.size()); getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8, g); - auto jsiGlyphIDs = jsi::Array(runtime, numGlyphIDs); - for (int i = 0; i < numGlyphIDs; i++) { - jsiGlyphIDs.setValueAtIndex(runtime, i, - jsi::Value(static_cast(glyphIDs[i]))); - } - return jsiGlyphIDs; + return std::vector(glyphIDs.begin(), glyphIDs.end()); } - JSI_HOST_FUNCTION(getGlyphIntercepts) { - auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); - auto jsiPositions = arguments[1].asObject(runtime).asArray(runtime); - auto top = arguments[2].asNumber(); - auto bottom = arguments[3].asNumber(); - std::vector positions; - int pointsSize = static_cast(jsiPositions.size(runtime)); - positions.reserve(pointsSize); - for (int i = 0; i < pointsSize; i++) { - std::shared_ptr point = JsiSkPoint::fromValue( - runtime, jsiPositions.getValueAtIndex(runtime, i).asObject(runtime)); - positions.push_back(*point.get()); - } - - std::vector glyphs; - int glyphsSize = static_cast(jsiGlyphs.size(runtime)); - glyphs.reserve(glyphsSize); - for (int i = 0; i < glyphsSize; i++) { - glyphs.push_back(jsiGlyphs.getValueAtIndex(runtime, i).asNumber()); + std::vector getGlyphIntercepts(std::vector glyphs, + std::vector positions, + double top, double bottom) { + std::vector glyphIds; + glyphIds.reserve(glyphs.size()); + for (auto glyph : glyphs) { + glyphIds.push_back(static_cast(glyph)); } - - if (glyphs.size() > positions.size()) { - throw jsi::JSError(runtime, "Not enough x,y position pairs for glyphs"); - return jsi::Value::null(); + if (glyphIds.size() > positions.size()) { + throw std::runtime_error("Not enough x,y position pairs for glyphs"); } - auto g = SkSpan(glyphs.data(), glyphs.size()); + auto g = SkSpan(glyphIds.data(), glyphIds.size()); auto p = SkSpan(positions.data(), positions.size()); auto sects = getObject()->getIntercepts(g, p, top, bottom); - auto jsiSects = jsi::Array(runtime, sects.size()); - for (int i = 0; i < sects.size(); i++) { - jsiSects.setValueAtIndex(runtime, i, - jsi::Value(static_cast(sects.at(i)))); - } - return jsiSects; + return std::vector(sects.begin(), sects.end()); } - JSI_HOST_FUNCTION(getScaleX) { - return jsi::Value(SkScalarToDouble(getObject()->getScaleX())); - } + double getScaleX() { return SkScalarToDouble(getObject()->getScaleX()); } - JSI_HOST_FUNCTION(getSize) { - return jsi::Value(SkScalarToDouble(getObject()->getSize())); - } + double getSize() { return SkScalarToDouble(getObject()->getSize()); } - JSI_HOST_FUNCTION(getSkewX) { - return jsi::Value(SkScalarToDouble(getObject()->getSkewX())); - } + double getSkewX() { return SkScalarToDouble(getObject()->getSkewX()); } - JSI_HOST_FUNCTION(isEmbolden) { - return jsi::Value(getObject()->isEmbolden()); - } + bool isEmbolden() { return getObject()->isEmbolden(); } - JSI_HOST_FUNCTION(getTypeface) { - return JsiSkTypeface::toValue( - runtime, getContext(), sk_sp(getObject()->getTypeface())); + std::shared_ptr getTypeface() { + return std::make_shared( + getContext(), sk_sp(getObject()->getTypeface())); } - JSI_HOST_FUNCTION(setEdging) { - auto edging = arguments[0].asNumber(); + void setEdging(double edging) { getObject()->setEdging(static_cast(edging)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(embeddedBitmaps) { - auto embeddedBitmaps = arguments[0].getBool(); + void setEmbeddedBitmaps(bool embeddedBitmaps) { getObject()->setEmbeddedBitmaps(embeddedBitmaps); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setHinting) { - auto hinting = arguments[0].asNumber(); + void setHinting(double hinting) { getObject()->setHinting(static_cast(hinting)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setLinearMetrics) { - auto linearMetrics = arguments[0].getBool(); + void setLinearMetrics(bool linearMetrics) { getObject()->setLinearMetrics(linearMetrics); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setScaleX) { - auto scaleX = arguments[0].asNumber(); - getObject()->setScaleX(scaleX); - return jsi::Value::undefined(); - } + void setScaleX(double scaleX) { getObject()->setScaleX(scaleX); } - JSI_HOST_FUNCTION(setSkewX) { - auto skewX = arguments[0].asNumber(); - getObject()->setSkewX(skewX); - return jsi::Value::undefined(); - } + void setSkewX(double skewX) { getObject()->setSkewX(skewX); } - JSI_HOST_FUNCTION(setSize) { - auto size = arguments[0].asNumber(); - getObject()->setSize(size); - return jsi::Value::undefined(); - } + void setSize(double size) { getObject()->setSize(size); } - JSI_HOST_FUNCTION(setEmbolden) { - auto embolden = arguments[0].asNumber(); - getObject()->setEmbolden(embolden); - return jsi::Value::undefined(); + // The JS API declares booleans here, but the previous implementation read + // the arguments with asNumber() — keep accepting numbers. + void setEmbolden(double embolden) { + getObject()->setEmbolden(static_cast(embolden)); } - JSI_HOST_FUNCTION(setSubpixel) { - auto subpixel = arguments[0].asNumber(); - getObject()->setSubpixel(subpixel); - return jsi::Value::undefined(); + void setSubpixel(double subpixel) { + getObject()->setSubpixel(static_cast(subpixel)); } - JSI_HOST_FUNCTION(setTypeface) { - auto typeface = arguments[0].isNull() - ? nullptr - : JsiSkTypeface::fromValue(runtime, arguments[0]); - getObject()->setTypeface(typeface); - return jsi::Value::undefined(); + void setTypeface(std::variant> typeface) { + getObject()->setTypeface( + std::holds_alternative(typeface) + ? nullptr + : std::get>(std::move(typeface))); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "getSize", &JsiSkFont::getSize); + installMethod(runtime, prototype, "getSize", &JsiSkFont::getSize); installHostMethod(runtime, prototype, "getMetrics", &JsiSkFont::getMetrics); - installHostMethod(runtime, prototype, "getGlyphIDs", - &JsiSkFont::getGlyphIDs); - installHostMethod(runtime, prototype, "getGlyphIntercepts", - &JsiSkFont::getGlyphIntercepts); - installHostMethod(runtime, prototype, "getScaleX", &JsiSkFont::getScaleX); - installHostMethod(runtime, prototype, "getSkewX", &JsiSkFont::getSkewX); - installHostMethod(runtime, prototype, "getTypeface", - &JsiSkFont::getTypeface); - installHostMethod(runtime, prototype, "setEdging", &JsiSkFont::setEdging); - installHostMethod(runtime, prototype, "embeddedBitmaps", - &JsiSkFont::embeddedBitmaps); - installHostMethod(runtime, prototype, "setHinting", &JsiSkFont::setHinting); - installHostMethod(runtime, prototype, "setLinearMetrics", - &JsiSkFont::setLinearMetrics); - installHostMethod(runtime, prototype, "setScaleX", &JsiSkFont::setScaleX); - installHostMethod(runtime, prototype, "setSkewX", &JsiSkFont::setSkewX); - installHostMethod(runtime, prototype, "setSize", &JsiSkFont::setSize); - installHostMethod(runtime, prototype, "setEmbolden", - &JsiSkFont::setEmbolden); - installHostMethod(runtime, prototype, "setSubpixel", - &JsiSkFont::setSubpixel); - installHostMethod(runtime, prototype, "setTypeface", - &JsiSkFont::setTypeface); - installHostMethod(runtime, prototype, "getGlyphWidths", - &JsiSkFont::getGlyphWidths); - installHostMethod(runtime, prototype, "getTextWidth", - &JsiSkFont::getTextWidth); - installHostMethod(runtime, prototype, "measureText", - &JsiSkFont::measureText); + installMethod(runtime, prototype, "getGlyphIDs", &JsiSkFont::getGlyphIDs); + installMethod(runtime, prototype, "getGlyphIntercepts", + &JsiSkFont::getGlyphIntercepts); + installMethod(runtime, prototype, "getScaleX", &JsiSkFont::getScaleX); + installMethod(runtime, prototype, "getSkewX", &JsiSkFont::getSkewX); + installMethod(runtime, prototype, "getTypeface", &JsiSkFont::getTypeface); + installMethod(runtime, prototype, "setEdging", &JsiSkFont::setEdging); + installMethod(runtime, prototype, "embeddedBitmaps", + &JsiSkFont::setEmbeddedBitmaps); + installMethod(runtime, prototype, "setHinting", &JsiSkFont::setHinting); + installMethod(runtime, prototype, "setLinearMetrics", + &JsiSkFont::setLinearMetrics); + installMethod(runtime, prototype, "setScaleX", &JsiSkFont::setScaleX); + installMethod(runtime, prototype, "setSkewX", &JsiSkFont::setSkewX); + installMethod(runtime, prototype, "setSize", &JsiSkFont::setSize); + installMethod(runtime, prototype, "setEmbolden", &JsiSkFont::setEmbolden); + installMethod(runtime, prototype, "setSubpixel", &JsiSkFont::setSubpixel); + installMethod(runtime, prototype, "setTypeface", &JsiSkFont::setTypeface); + installMethod(runtime, prototype, "getGlyphWidths", + &JsiSkFont::getGlyphWidths); + installMethod(runtime, prototype, "getTextWidth", &JsiSkFont::getTextWidth); + installMethod(runtime, prototype, "measureText", &JsiSkFont::measureText); } JsiSkFont(std::shared_ptr context, const SkFont &font) diff --git a/packages/skia/cpp/api/JsiSkFontMgr.h b/packages/skia/cpp/api/JsiSkFontMgr.h index c4f1936d57..33eb9ef649 100644 --- a/packages/skia/cpp/api/JsiSkFontMgr.h +++ b/packages/skia/cpp/api/JsiSkFontMgr.h @@ -2,11 +2,14 @@ #include #include +#include #include #include +#include "JsiSkConverters.h" #include "JsiSkFontStyle.h" #include "JsiSkNativeObjects.h" +#include "JsiSkTypeface.h" #include "utils/RNSkLog.h" #include @@ -32,41 +35,36 @@ class JsiSkFontMgr fontMgr), _systemFontFamilies(context->getSystemFontFamilies()) {} - JSI_HOST_FUNCTION(countFamilies) { + int countFamilies() { return static_cast(getObject()->countFamilies() + _systemFontFamilies.size()); } - JSI_HOST_FUNCTION(getFamilyName) { - auto i = static_cast(arguments[0].asNumber()); + std::string getFamilyName(int i) { auto baseFamilyCount = getObject()->countFamilies(); if (i < baseFamilyCount) { SkString name; getObject()->getFamilyName(i, &name); - return jsi::String::createFromUtf8(runtime, name.c_str()); + return std::string(name.c_str()); } auto systemIndex = i - baseFamilyCount; if (systemIndex < static_cast(_systemFontFamilies.size())) { - return jsi::String::createFromUtf8(runtime, - _systemFontFamilies[systemIndex]); + return _systemFontFamilies[systemIndex]; } - throw jsi::JSError( - runtime, + throw std::runtime_error( "Font family index out of bounds: " + std::to_string(i) + - " (total families: " + - std::to_string(baseFamilyCount + _systemFontFamilies.size()) + ")"); + " (total families: " + + std::to_string(baseFamilyCount + _systemFontFamilies.size()) + ")"); } - JSI_HOST_FUNCTION(matchFamilyStyle) { - auto name = arguments[0].asString(runtime).utf8(runtime); + std::shared_ptr + matchFamilyStyle(std::string name, std::shared_ptr fontStyle) { // Resolve font family aliases (e.g., "System" -> ".AppleSystemUIFont" on // iOS) auto resolvedName = getContext()->resolveFontFamily(name); - auto fontStyle = JsiSkFontStyle::fromValue(runtime, arguments[1]); auto typeface = getObject()->matchFamilyStyle(resolvedName.c_str(), *fontStyle); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(typeface))); + return std::make_shared(getContext(), std::move(typeface)); } size_t getMemoryPressure() override { return 2048; } @@ -78,12 +76,12 @@ class JsiSkFontMgr static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "countFamilies", - &JsiSkFontMgr::countFamilies); - installHostMethod(runtime, prototype, "getFamilyName", - &JsiSkFontMgr::getFamilyName); - installHostMethod(runtime, prototype, "matchFamilyStyle", - &JsiSkFontMgr::matchFamilyStyle); + installMethod(runtime, prototype, "countFamilies", + &JsiSkFontMgr::countFamilies); + installMethod(runtime, prototype, "getFamilyName", + &JsiSkFontMgr::getFamilyName); + installMethod(runtime, prototype, "matchFamilyStyle", + &JsiSkFontMgr::matchFamilyStyle); } private: diff --git a/packages/skia/cpp/api/JsiSkFontMgrFactory.h b/packages/skia/cpp/api/JsiSkFontMgrFactory.h index 879a4d4149..d57343732a 100644 --- a/packages/skia/cpp/api/JsiSkFontMgrFactory.h +++ b/packages/skia/cpp/api/JsiSkFontMgrFactory.h @@ -6,6 +6,7 @@ #include +#include "JsiSkFontMgr.h" #include "JsiSkNativeObjects.h" #pragma clang diagnostic push @@ -32,17 +33,15 @@ class JsiSkFontMgrFactory : public JsiSkNativeObject { return fontMgr; } - JSI_HOST_FUNCTION(System) { + std::shared_ptr System() { auto fontMgr = JsiSkFontMgrFactory::getFontMgr(getContext()); - return makeJsiObject(runtime, - std::make_shared(getContext(), fontMgr)); + return std::make_shared(getContext(), fontMgr); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "System", - &JsiSkFontMgrFactory::System); + installMethod(runtime, prototype, "System", &JsiSkFontMgrFactory::System); } explicit JsiSkFontMgrFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkImage.h b/packages/skia/cpp/api/JsiSkImage.h index 8551a58371..bfd9cf8ee3 100644 --- a/packages/skia/cpp/api/JsiSkImage.h +++ b/packages/skia/cpp/api/JsiSkImage.h @@ -1,9 +1,12 @@ #pragma once #include +#include #include #include +#include +#include "JsiSkConverters.h" #include "JsiSkDispatcher.h" #include "JsiSkImageInfo.h" #include "JsiSkMatrix.h" @@ -148,53 +151,42 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { static constexpr const char *CLASS_NAME = "Image"; // TODO-API: Properties? - JSI_HOST_FUNCTION(width) { return static_cast(getObject()->width()); } - JSI_HOST_FUNCTION(height) { - return static_cast(getObject()->height()); - } + double width() { return static_cast(getObject()->width()); } + double height() { return static_cast(getObject()->height()); } - JSI_HOST_FUNCTION(getImageInfo) { - return JsiSkImageInfo::toValue(runtime, getContext(), - getObject()->imageInfo()); + std::shared_ptr getImageInfo() { + return std::make_shared(getContext(), + getObject()->imageInfo()); } - JSI_HOST_FUNCTION(makeShaderOptions) { - auto tmx = (SkTileMode)arguments[0].asNumber(); - auto tmy = (SkTileMode)arguments[1].asNumber(); - auto fm = (SkFilterMode)arguments[2].asNumber(); - auto mm = (SkMipmapMode)arguments[3].asNumber(); - auto m = count > 4 && !arguments[4].isUndefined() - ? JsiSkMatrix::fromValue(runtime, arguments[4]).get() - : nullptr; - auto shader = - getObject()->makeShader(tmx, tmy, SkSamplingOptions(fm, mm), m); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(shader))); + std::shared_ptr + makeShaderOptions(double tmx, double tmy, double fm, double mm, + std::optional> m) { + auto shader = getObject()->makeShader( + static_cast(tmx), static_cast(tmy), + SkSamplingOptions(static_cast(fm), + static_cast(mm)), + m.has_value() ? m->get() : nullptr); + return std::make_shared(getContext(), std::move(shader)); } - JSI_HOST_FUNCTION(makeShaderCubic) { - auto tmx = (SkTileMode)arguments[0].asNumber(); - auto tmy = (SkTileMode)arguments[1].asNumber(); - auto B = SkDoubleToScalar(arguments[2].asNumber()); - auto C = SkDoubleToScalar(arguments[3].asNumber()); - auto m = count > 4 && !arguments[4].isUndefined() - ? JsiSkMatrix::fromValue(runtime, arguments[4]).get() - : nullptr; - auto shader = - getObject()->makeShader(tmx, tmy, SkSamplingOptions({B, C}), m); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(shader))); + std::shared_ptr + makeShaderCubic(double tmx, double tmy, double B, double C, + std::optional> m) { + auto shader = getObject()->makeShader( + static_cast(tmx), static_cast(tmy), + SkSamplingOptions({SkDoubleToScalar(B), SkDoubleToScalar(C)}), + m.has_value() ? m->get() : nullptr); + return std::make_shared(getContext(), std::move(shader)); } - sk_sp encodeImageData(const jsi::Value *arguments, size_t count) { + sk_sp encodeImageData(JsiOptional formatParam, + JsiOptional qualityParam) { // Get optional parameters - auto format = - count >= 1 ? static_cast(arguments[0].asNumber()) - : SkEncodedImageFormat::kPNG; - - auto quality = (count >= 2 && arguments[1].isNumber()) - ? arguments[1].asNumber() - : 100.0; + auto format = formatParam.has_value() + ? static_cast(*formatParam) + : SkEncodedImageFormat::kPNG; + auto quality = qualityParam.has_value() ? *qualityParam : 100.0; auto image = getObject(); #if defined(SK_GRAPHITE) image = DawnContext::getInstance().MakeRasterImage(image); @@ -238,8 +230,17 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { return data; } + // Stays raw: constructs a Uint8Array result. JSI_HOST_FUNCTION(encodeToBytes) { - auto data = encodeImageData(arguments, count); + JsiOptional format = + count >= 1 && !arguments[0].isUndefined() && !arguments[0].isNull() + ? JsiOptional(arguments[0].asNumber()) + : JsiOptional(); + JsiOptional quality = count >= 2 && arguments[1].isNumber() + ? JsiOptional( + arguments[1].asNumber()) + : JsiOptional(); + auto data = encodeImageData(format, quality); if (!data) { return jsi::Value::null(); } @@ -261,17 +262,18 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { return array; } - JSI_HOST_FUNCTION(encodeToBase64) { - auto data = encodeImageData(arguments, count); + std::variant + encodeToBase64(JsiOptional format, JsiOptional quality) { + auto data = encodeImageData(format, quality); if (!data) { - return jsi::Value::null(); + return nullptr; } auto len = Base64::Encode(data->bytes(), data->size(), nullptr); auto buffer = std::string(len, 0); Base64::Encode(data->bytes(), data->size(), reinterpret_cast(&buffer[0])); - return jsi::String::createFromAscii(runtime, buffer); + return buffer; } JSI_HOST_FUNCTION(readPixels) { @@ -328,22 +330,22 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { return dest; } - JSI_HOST_FUNCTION(makeNonTextureImage) { + std::variant> + makeNonTextureImage() { #if defined(SK_GRAPHITE) auto rasterImage = DawnContext::getInstance().MakeRasterImage(getObject()); #else auto grContext = getContext()->getDirectContext(); auto image = getObject(); if (!grContext) { - throw jsi::JSError(runtime, "No GPU context available."); + throw std::runtime_error("No GPU context available."); } auto rasterImage = image->makeRasterImage(grContext); #endif if (!rasterImage) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(rasterImage))); + return std::make_shared(getContext(), std::move(rasterImage)); } JSI_HOST_FUNCTION(getNativeTextureUnstable) { @@ -355,9 +357,7 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { return JsiTextureInfo::toValue(runtime, texInfo); } - JSI_HOST_FUNCTION(isTextureBacked) { - return jsi::Value(getObject()->isTextureBacked()); - } + bool isTextureBacked() { return getObject()->isTextureBacked(); } /** Returns the underlying object from a host object of this type @@ -369,26 +369,26 @@ class JsiSkImage : public JsiSkWrappingSkPtrNativeObject { static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "width", &JsiSkImage::width); - installHostMethod(runtime, prototype, "height", &JsiSkImage::height); - installHostMethod(runtime, prototype, "getImageInfo", - &JsiSkImage::getImageInfo); - installHostMethod(runtime, prototype, "makeShaderOptions", - &JsiSkImage::makeShaderOptions); - installHostMethod(runtime, prototype, "makeShaderCubic", - &JsiSkImage::makeShaderCubic); + installMethod(runtime, prototype, "width", &JsiSkImage::width); + installMethod(runtime, prototype, "height", &JsiSkImage::height); + installMethod(runtime, prototype, "getImageInfo", + &JsiSkImage::getImageInfo); + installMethod(runtime, prototype, "makeShaderOptions", + &JsiSkImage::makeShaderOptions); + installMethod(runtime, prototype, "makeShaderCubic", + &JsiSkImage::makeShaderCubic); installHostMethod(runtime, prototype, "encodeToBytes", &JsiSkImage::encodeToBytes); - installHostMethod(runtime, prototype, "encodeToBase64", - &JsiSkImage::encodeToBase64); + installMethod(runtime, prototype, "encodeToBase64", + &JsiSkImage::encodeToBase64); installHostMethod(runtime, prototype, "readPixels", &JsiSkImage::readPixels); - installHostMethod(runtime, prototype, "makeNonTextureImage", - &JsiSkImage::makeNonTextureImage); + installMethod(runtime, prototype, "makeNonTextureImage", + &JsiSkImage::makeNonTextureImage); installHostMethod(runtime, prototype, "getNativeTextureUnstable", &JsiSkImage::getNativeTextureUnstable); - installHostMethod(runtime, prototype, "isTextureBacked", - &JsiSkImage::isTextureBacked); + installMethod(runtime, prototype, "isTextureBacked", + &JsiSkImage::isTextureBacked); } JsiSkImage(std::shared_ptr context, diff --git a/packages/skia/cpp/api/JsiSkImageFactory.h b/packages/skia/cpp/api/JsiSkImageFactory.h index 4ad5d400a6..67198e55e8 100644 --- a/packages/skia/cpp/api/JsiSkImageFactory.h +++ b/packages/skia/cpp/api/JsiSkImageFactory.h @@ -2,9 +2,11 @@ #include #include +#include #include +#include "JsiSkConverters.h" #include "JsiSkData.h" #include "JsiSkImage.h" #include "JsiSkImageInfo.h" @@ -24,43 +26,35 @@ class JsiSkImageFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "ImageFactory"; - JSI_HOST_FUNCTION(MakeNull) { - return makeJsiObject(runtime, - std::make_shared(getContext(), nullptr)); + std::shared_ptr MakeNull() { + return std::make_shared(getContext(), nullptr); } - JSI_HOST_FUNCTION(MakeImageFromEncoded) { - auto data = JsiSkData::fromValue(runtime, arguments[0]); + std::variant> + MakeImageFromEncoded(sk_sp data) { auto image = SkImages::DeferredFromEncodedData(data); if (image == nullptr) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(image))); + return std::make_shared(getContext(), std::move(image)); } - JSI_HOST_FUNCTION(MakeImageFromNativeBuffer) { - jsi::BigInt pointer = arguments[0].asBigInt(runtime); - const uintptr_t nativeBufferPointer = pointer.asUint64(runtime); - void *rawPointer = reinterpret_cast(nativeBufferPointer); + std::shared_ptr MakeImageFromNativeBuffer(void *rawPointer) { auto image = getContext()->makeImageFromNativeBuffer(rawPointer); if (image == nullptr) { throw std::runtime_error("Failed to convert NativeBuffer to SkImage!"); } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(image))); + return std::make_shared(getContext(), std::move(image)); } - JSI_HOST_FUNCTION(MakeImage) { - auto imageInfo = JsiSkImageInfo::fromValue(runtime, arguments[0]); - auto pixelData = JsiSkData::fromValue(runtime, arguments[1]); - auto bytesPerRow = arguments[2].asNumber(); + std::variant> + MakeImage(std::shared_ptr imageInfo, sk_sp pixelData, + double bytesPerRow) { auto image = SkImages::RasterFromData(*imageInfo, pixelData, bytesPerRow); if (image == nullptr) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(image))); + return std::make_shared(getContext(), std::move(image)); } JSI_HOST_FUNCTION(MakeImageFromViewTag) { @@ -171,18 +165,17 @@ class JsiSkImageFactory : public JsiSkNativeObject { size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeImageFromEncoded", - &JsiSkImageFactory::MakeImageFromEncoded); + installMethod(runtime, prototype, "MakeImageFromEncoded", + &JsiSkImageFactory::MakeImageFromEncoded); installHostMethod(runtime, prototype, "MakeImageFromViewTag", &JsiSkImageFactory::MakeImageFromViewTag); - installHostMethod(runtime, prototype, "MakeImageFromNativeBuffer", - &JsiSkImageFactory::MakeImageFromNativeBuffer); + installMethod(runtime, prototype, "MakeImageFromNativeBuffer", + &JsiSkImageFactory::MakeImageFromNativeBuffer); installHostMethod(runtime, prototype, "MakeImageFromNativeTextureUnstable", &JsiSkImageFactory::MakeImageFromNativeTextureUnstable); - installHostMethod(runtime, prototype, "MakeImage", - &JsiSkImageFactory::MakeImage); - installHostMethod(runtime, prototype, "MakeNull", - &JsiSkImageFactory::MakeNull); + installMethod(runtime, prototype, "MakeImage", + &JsiSkImageFactory::MakeImage); + installMethod(runtime, prototype, "MakeNull", &JsiSkImageFactory::MakeNull); installHostMethod(runtime, prototype, "MakeImageFromTexture", &JsiSkImageFactory::MakeImageFromTexture); installHostMethod(runtime, prototype, "MakeTextureFromImage", diff --git a/packages/skia/cpp/api/JsiSkImageFilterFactory.h b/packages/skia/cpp/api/JsiSkImageFilterFactory.h index 77119119d9..c63f600eeb 100644 --- a/packages/skia/cpp/api/JsiSkImageFilterFactory.h +++ b/packages/skia/cpp/api/JsiSkImageFilterFactory.h @@ -1,14 +1,24 @@ #pragma once #include +#include #include +#include +#include #include +#include "JsiSkColor.h" +#include "JsiSkColorFilter.h" +#include "JsiSkConverters.h" +#include "JsiSkImage.h" #include "JsiSkImageFilter.h" +#include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" #include "JsiSkPicture.h" +#include "JsiSkRect.h" #include "JsiSkRuntimeShaderBuilder.h" +#include "JsiSkShader.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -22,681 +32,417 @@ namespace RNSkia { namespace jsi = facebook::jsi; -inline bool hasOptionalArgument(const jsi::Value *arguments, size_t count, - size_t index) { - return (index < count && !arguments[index].isNull() && - !arguments[index].isUndefined()); -} - class JsiSkImageFilterFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "ImageFilterFactory"; - JSI_HOST_FUNCTION(MakeBlur) { - float sigmaX = arguments[0].asNumber(); - float sigmaY = arguments[1].asNumber(); - int tileMode = arguments[2].asNumber(); - sk_sp imageFilter = nullptr; - if (hasOptionalArgument(arguments, count, 3)) { - imageFilter = JsiSkImageFilter::fromValue(runtime, arguments[3]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 4)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[4]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::Blur(sigmaX, sigmaY, (SkTileMode)tileMode, - imageFilter, cropRect)); - return makeJsiObject(runtime, std::move(filter)); + std::shared_ptr + MakeBlur(float sigmaX, float sigmaY, int tileMode, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), + SkImageFilters::Blur(sigmaX, sigmaY, static_cast(tileMode), + orNull(std::move(input)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeColorFilter) { - auto cf = JsiSkColorFilter::fromValue(runtime, arguments[0]); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 1)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[1]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 2)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[2]); - } - auto filter = std::make_shared( + std::shared_ptr + MakeColorFilter(sk_sp cf, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::ColorFilter(std::move(cf), std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::ColorFilter(std::move(cf), orNull(std::move(input)), + toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeOffset) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 3)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[3]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::Offset(x, y, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeDisplacementMap) { - auto fXChannelSelector = - static_cast(arguments[0].asNumber()); - auto fYChannelSelector = - static_cast(arguments[1].asNumber()); - auto scale = arguments[2].asNumber(); - auto in2 = JsiSkImageFilter::fromValue(runtime, arguments[3]); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 4)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[4]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 5)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[5]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::DisplacementMap( - fXChannelSelector, fYChannelSelector, scale, - std::move(in2), std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeShader) { - auto shader = JsiSkShader::fromValue(runtime, arguments[0]); - SkImageFilters::Dither dither = SkImageFilters::Dither::kNo; - if (hasOptionalArgument(arguments, count, 1)) { - dither = arguments[1].asBool() ? SkImageFilters::Dither::kYes - : SkImageFilters::Dither::kNo; - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 2)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[2]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::Shader(std::move(shader), dither, cropRect)); - return makeJsiObject(runtime, std::move(filter)); + std::shared_ptr + MakeOffset(double x, double y, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::Offset(x, y, orNull(std::move(input)), + toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeCompose) { - sk_sp outer = nullptr; - if (hasOptionalArgument(arguments, count, 0)) { - outer = JsiSkImageFilter::fromValue(runtime, arguments[0]); - } - sk_sp inner = nullptr; - if (hasOptionalArgument(arguments, count, 1)) { - inner = JsiSkImageFilter::fromValue(runtime, arguments[1]); - } - auto filter = std::make_shared( + std::shared_ptr + MakeDisplacementMap(double xChannelSelector, double yChannelSelector, + double scale, sk_sp in2, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::Compose(std::move(outer), std::move(inner))); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::DisplacementMap( + static_cast(xChannelSelector), + static_cast(yChannelSelector), scale, + std::move(in2), orNull(std::move(input)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeBlend) { - auto mode = static_cast(arguments[0].asNumber()); - sk_sp background = - JsiSkImageFilter::fromValue(runtime, arguments[1]); - sk_sp foreground = nullptr; - - if (hasOptionalArgument(arguments, count, 2)) { - foreground = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } + std::shared_ptr MakeShader(sk_sp shader, + JsiOptional dither, + JsiOptional crop) { + auto ditherMode = dither.has_value() && *dither + ? SkImageFilters::Dither::kYes + : SkImageFilters::Dither::kNo; + return std::make_shared( + getContext(), + SkImageFilters::Shader(std::move(shader), ditherMode, toCropRect(crop))); + } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 3)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[3]); - } + std::shared_ptr + MakeCompose(JsiOptional> outer, + JsiOptional> inner) { + return std::make_shared( + getContext(), SkImageFilters::Compose(orNull(std::move(outer)), + orNull(std::move(inner)))); + } - auto filter = std::make_shared( + std::shared_ptr + MakeBlend(double mode, sk_sp background, + JsiOptional> foreground, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::Blend(std::move(mode), std::move(background), - std::move(foreground), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeDropShadow) { - auto dx = arguments[0].asNumber(); - auto dy = arguments[1].asNumber(); - auto sigmaX = arguments[2].asNumber(); - auto sigmaY = arguments[3].asNumber(); - auto color = JsiSkColor::fromValue(runtime, arguments[4]); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 6)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[6]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, - std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeDropShadowOnly) { - auto dx = arguments[0].asNumber(); - auto dy = arguments[1].asNumber(); - auto sigmaX = arguments[2].asNumber(); - auto sigmaY = arguments[3].asNumber(); - auto color = JsiSkColor::fromValue(runtime, arguments[4]); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 6)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[6]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color, - std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::Blend(static_cast(mode), + std::move(background), + orNull(std::move(foreground)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeErode) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 3)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[3]); - } - auto filter = std::make_shared( + std::shared_ptr + MakeDropShadow(double dx, double dy, double sigmaX, double sigmaY, + JsiColor color, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::Erode(rx, ry, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, + orNull(std::move(input)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeDilate) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 3)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[3]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::Dilate(rx, ry, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); + std::shared_ptr + MakeDropShadowOnly(double dx, double dy, double sigmaX, double sigmaY, + JsiColor color, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::DropShadowOnly( + dx, dy, sigmaX, sigmaY, color, + orNull(std::move(input)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeRuntimeShader) { - auto rtb = JsiSkRuntimeShaderBuilder::fromValue(runtime, arguments[0]); + std::shared_ptr + MakeErode(double rx, double ry, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::Erode(rx, ry, orNull(std::move(input)), + toCropRect(crop))); + } - std::string childNameStr = ""; - const char *childName = childNameStr.c_str(); - if (hasOptionalArgument(arguments, count, 1)) { - childNameStr = arguments[1].asString(runtime).utf8(runtime); - childName = childNameStr.c_str(); - } + std::shared_ptr + MakeDilate(double rx, double ry, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::Dilate(rx, ry, orNull(std::move(input)), + toCropRect(crop))); + } - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - auto filter = std::make_shared( + std::shared_ptr + MakeRuntimeShader(std::shared_ptr rtb, + JsiOptional childName, + JsiOptional> input) { + std::string childNameStr = childName.value_or(""); + return std::make_shared( getContext(), - SkImageFilters::RuntimeShader(*rtb, childName, std::move(input))); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeArithmetic) { - float k1 = arguments[0].asNumber(); - float k2 = arguments[1].asNumber(); - float k3 = arguments[2].asNumber(); - float k4 = arguments[3].asNumber(); - bool enforcePMColor = arguments[4].asBool(); - sk_sp background = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - background = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - sk_sp foreground = nullptr; - if (hasOptionalArgument(arguments, count, 6)) { - foreground = JsiSkImageFilter::fromValue(runtime, arguments[6]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 7)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[7]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::Arithmetic( - k1, k2, k3, k4, enforcePMColor, std::move(background), - std::move(foreground), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeCrop) { - SkRect rect = *JsiSkRect::fromValue(runtime, arguments[0]); - SkTileMode tileMode = SkTileMode::kDecal; - if (hasOptionalArgument(arguments, count, 1)) { - tileMode = (SkTileMode)arguments[1].asNumber(); - } - sk_sp imageFilter = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - imageFilter = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - auto filter = std::make_shared( + SkImageFilters::RuntimeShader(*rtb, childNameStr.c_str(), + orNull(std::move(input)))); + } + + std::shared_ptr + MakeArithmetic(float k1, float k2, float k3, float k4, bool enforcePMColor, + JsiOptional> background, + JsiOptional> foreground, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::Crop(rect, tileMode, std::move(imageFilter))); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor, + orNull(std::move(background)), + orNull(std::move(foreground)), + toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeEmpty) { - auto filter = std::make_shared(getContext(), - SkImageFilters::Empty()); - return makeJsiObject(runtime, std::move(filter)); + std::shared_ptr + MakeCrop(SkRect rect, JsiOptional tileMode, + JsiOptional> imageFilter) { + auto mode = tileMode.has_value() ? static_cast(*tileMode) + : SkTileMode::kDecal; + return std::make_shared( + getContext(), + SkImageFilters::Crop(rect, mode, orNull(std::move(imageFilter)))); } - inline SkPoint3 SkPoint3FromValue(jsi::Runtime &runtime, - const jsi::Value &obj) { - const auto &object = obj.asObject(runtime); - auto x = object.getProperty(runtime, "x").asNumber(); - auto y = object.getProperty(runtime, "y").asNumber(); - auto z = object.getProperty(runtime, "z").asNumber(); - return SkPoint3::Make(x, y, z); + std::shared_ptr MakeEmpty() { + return std::make_shared(getContext(), + SkImageFilters::Empty()); } - JSI_HOST_FUNCTION(MakeDistantLitDiffuse) { - SkPoint3 direction = SkPoint3FromValue(runtime, arguments[0]); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[1]); - float surfaceScale = arguments[2].asNumber(); - float kd = arguments[3].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 4)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[4]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 5)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[5]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::DistantLitDiffuse(direction, lightColor, surfaceScale, - kd, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakePointLitDiffuse) { - SkPoint3 location = SkPoint3FromValue(runtime, arguments[0]); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[1]); - float surfaceScale = arguments[2].asNumber(); - float kd = arguments[3].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 4)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[4]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 5)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[5]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::PointLitDiffuse(location, lightColor, surfaceScale, kd, - std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeSpotLitDiffuse) { - SkPoint3 location = SkPoint3FromValue(runtime, arguments[0]); - SkPoint3 target = SkPoint3FromValue(runtime, arguments[1]); - float falloffExponent = arguments[2].asNumber(); - float cutoffAngle = arguments[3].asNumber(); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[4]); - float surfaceScale = arguments[5].asNumber(); - float kd = arguments[6].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 7)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[7]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 8)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[8]); - } - auto filter = std::make_shared( - getContext(), - SkImageFilters::SpotLitDiffuse(location, target, falloffExponent, - cutoffAngle, lightColor, surfaceScale, - kd, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeDistantLitSpecular) { - SkPoint3 direction = SkPoint3FromValue(runtime, arguments[0]); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[1]); - float surfaceScale = arguments[2].asNumber(); - float ks = arguments[3].asNumber(); - float shininess = arguments[4].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 6)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[6]); - } - auto filter = std::make_shared( + std::shared_ptr + MakeDistantLitDiffuse(SkPoint3 direction, JsiColor lightColor, + float surfaceScale, float kd, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::DistantLitDiffuse( + direction, lightColor, surfaceScale, kd, + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr + MakePointLitDiffuse(SkPoint3 location, JsiColor lightColor, + float surfaceScale, float kd, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::PointLitDiffuse( + location, lightColor, surfaceScale, kd, + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr + MakeSpotLitDiffuse(SkPoint3 location, SkPoint3 target, float falloffExponent, + float cutoffAngle, JsiColor lightColor, float surfaceScale, + float kd, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( + getContext(), SkImageFilters::SpotLitDiffuse( + location, target, falloffExponent, cutoffAngle, + lightColor, surfaceScale, kd, + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr + MakeDistantLitSpecular(SkPoint3 direction, JsiColor lightColor, + float surfaceScale, float ks, float shininess, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), SkImageFilters::DistantLitSpecular( direction, lightColor, surfaceScale, ks, shininess, - std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakePointLitSpecular) { - SkPoint3 location = SkPoint3FromValue(runtime, arguments[0]); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[1]); - float surfaceScale = arguments[2].asNumber(); - float ks = arguments[3].asNumber(); - float shininess = arguments[4].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 6)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[6]); - } - auto filter = std::make_shared( + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr + MakePointLitSpecular(SkPoint3 location, JsiColor lightColor, + float surfaceScale, float ks, float shininess, + JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), SkImageFilters::PointLitSpecular( location, lightColor, surfaceScale, ks, shininess, - std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeSpotLitSpecular) { - SkPoint3 location = SkPoint3FromValue(runtime, arguments[0]); - SkPoint3 target = SkPoint3FromValue(runtime, arguments[1]); - float falloffExponent = arguments[2].asNumber(); - float cutoffAngle = arguments[3].asNumber(); - SkColor lightColor = JsiSkColor::fromValue(runtime, arguments[4]); - float surfaceScale = arguments[5].asNumber(); - float ks = arguments[6].asNumber(); - float shininess = arguments[7].asNumber(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 8)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[8]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 9)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[9]); - } - auto filter = std::make_shared( + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr + MakeSpotLitSpecular(SkPoint3 location, SkPoint3 target, + float falloffExponent, float cutoffAngle, + JsiColor lightColor, float surfaceScale, float ks, + float shininess, JsiOptional> input, + JsiOptional crop) { + return std::make_shared( getContext(), - SkImageFilters::SpotLitSpecular( - location, target, falloffExponent, cutoffAngle, lightColor, - surfaceScale, ks, shininess, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeImage) { - sk_sp image = JsiSkImage::fromValue(runtime, arguments[0]); - SkRect srcRect; - if (hasOptionalArgument(arguments, count, 1)) { - srcRect = *JsiSkRect::fromValue(runtime, arguments[1]); - } else { - srcRect = SkRect::Make(image->bounds()); - } - SkRect dstRect; - if (hasOptionalArgument(arguments, count, 2)) { - dstRect = *JsiSkRect::fromValue(runtime, arguments[2]); - } else { - dstRect = srcRect; - } - SkFilterMode filterMode = SkFilterMode::kNearest; - if (hasOptionalArgument(arguments, count, 3)) { - filterMode = (SkFilterMode)arguments[3].asNumber(); - } - SkMipmapMode mipmap = SkMipmapMode::kNone; - if (hasOptionalArgument(arguments, count, 4)) { - mipmap = (SkMipmapMode)arguments[4].asNumber(); - } - auto filter = std::make_shared( + SkImageFilters::SpotLitSpecular(location, target, falloffExponent, + cutoffAngle, lightColor, surfaceScale, + ks, shininess, orNull(std::move(input)), + toCropRect(crop))); + } + + std::shared_ptr + MakeImage(sk_sp image, JsiOptional src, + JsiOptional dst, JsiOptional filterMode, + JsiOptional mipmap) { + SkRect srcRect = src.has_value() ? *src : SkRect::Make(image->bounds()); + SkRect dstRect = dst.has_value() ? *dst : srcRect; + auto sampling = SkSamplingOptions(toFilterMode(filterMode), + toMipmapMode(mipmap)); + return std::make_shared( getContext(), - SkImageFilters::Image(std::move(image), srcRect, dstRect, - SkSamplingOptions(filterMode, mipmap))); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeMagnifier) { - SkRect lensBounds = *JsiSkRect::fromValue(runtime, arguments[0]); - float zoomAmount = arguments[1].asNumber(); - float inset = arguments[2].asNumber(); - SkFilterMode filterMode = SkFilterMode::kNearest; - if (hasOptionalArgument(arguments, count, 3)) { - filterMode = (SkFilterMode)arguments[3].asNumber(); - } - SkMipmapMode mipmap = SkMipmapMode::kNone; - if (hasOptionalArgument(arguments, count, 4)) { - mipmap = (SkMipmapMode)arguments[4].asNumber(); - } - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 5)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[5]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 6)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[6]); - } - auto filter = std::make_shared( + SkImageFilters::Image(std::move(image), srcRect, dstRect, sampling)); + } + + std::shared_ptr + MakeMagnifier(SkRect lensBounds, float zoomAmount, float inset, + JsiOptional filterMode, JsiOptional mipmap, + JsiOptional> input, + JsiOptional crop) { + auto sampling = SkSamplingOptions(toFilterMode(filterMode), + toMipmapMode(mipmap)); + return std::make_shared( getContext(), - SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, - SkSamplingOptions(filterMode, mipmap), input, - cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeMatrixConvolution) { - SkISize kernelSize = - SkISize::Make(arguments[0].asNumber(), arguments[1].asNumber()); - std::vector kernel; - auto kernelArray = arguments[2].asObject(runtime).asArray(runtime); - auto size = kernelArray.size(runtime); - for (size_t i = 0; i < size; i++) { - kernel.push_back(kernelArray.getValueAtIndex(runtime, i).asNumber()); - } - auto gain = arguments[3].asNumber(); - auto bias = arguments[4].asNumber(); - SkIPoint kernelOffset = - SkIPoint::Make(arguments[5].asNumber(), arguments[6].asNumber()); - auto tileMode = static_cast(arguments[7].asNumber()); - bool convolveAlpha = arguments[8].asBool(); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 9)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[9]); - } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 10)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[10]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::MatrixConvolution( - kernelSize, kernel.data(), gain, bias, kernelOffset, - tileMode, convolveAlpha, std::move(input), cropRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeMatrixTransform) { - SkMatrix matrix = *JsiSkMatrix::fromValue(runtime, arguments[0]); - SkFilterMode filterMode = SkFilterMode::kNearest; - if (hasOptionalArgument(arguments, count, 1)) { - filterMode = (SkFilterMode)arguments[1].asNumber(); - } - SkMipmapMode mipmap = SkMipmapMode::kNone; - if (hasOptionalArgument(arguments, count, 2)) { - mipmap = (SkMipmapMode)arguments[2].asNumber(); - } - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 3)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[3]); - } - auto filter = std::make_shared( + SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling, + orNull(std::move(input)), toCropRect(crop))); + } + + std::shared_ptr MakeMatrixConvolution( + int kernelSizeX, int kernelSizeY, std::vector kernel, double gain, + double bias, int kernelOffsetX, int kernelOffsetY, double tileMode, + bool convolveAlpha, JsiOptional> input, + JsiOptional crop) { + auto kernelSize = SkISize::Make(kernelSizeX, kernelSizeY); + auto kernelOffset = SkIPoint::Make(kernelOffsetX, kernelOffsetY); + return std::make_shared( getContext(), - SkImageFilters::MatrixTransform( - matrix, SkSamplingOptions(filterMode, mipmap), std::move(input))); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::MatrixConvolution( + kernelSize, kernel.data(), gain, bias, kernelOffset, + static_cast(tileMode), convolveAlpha, + orNull(std::move(input)), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakeMerge) { + std::shared_ptr + MakeMatrixTransform(SkMatrix matrix, JsiOptional filterMode, + JsiOptional mipmap, + JsiOptional> input) { + auto sampling = SkSamplingOptions(toFilterMode(filterMode), + toMipmapMode(mipmap)); + return std::make_shared( + getContext(), SkImageFilters::MatrixTransform( + matrix, sampling, orNull(std::move(input)))); + } + + std::shared_ptr + MakeMerge(std::vector>> jsiFilters, + JsiOptional crop) { std::vector> filters; - auto filtersArray = arguments[0].asObject(runtime).asArray(runtime); - auto filtersCount = filtersArray.size(runtime); - for (size_t i = 0; i < filtersCount; ++i) { - auto element = filtersArray.getValueAtIndex(runtime, i); - if (element.isNull()) { - filters.push_back(nullptr); - } else { - filters.push_back(JsiSkImageFilter::fromValue(runtime, element)); - } + filters.reserve(jsiFilters.size()); + for (auto &filter : jsiFilters) { + filters.push_back(orNull(std::move(filter))); } - SkImageFilters::CropRect cropRect = {}; - if (hasOptionalArgument(arguments, count, 1)) { - cropRect = *JsiSkRect::fromValue(runtime, arguments[1]); - } - auto filter = std::make_shared( + return std::make_shared( getContext(), - SkImageFilters::Merge(filters.data(), filtersCount, cropRect)); - return makeJsiObject(runtime, std::move(filter)); + SkImageFilters::Merge(filters.data(), filters.size(), toCropRect(crop))); } - JSI_HOST_FUNCTION(MakePicture) { - sk_sp picture = JsiSkPicture::fromValue(runtime, arguments[0]); - SkRect targetRect; - if (hasOptionalArgument(arguments, count, 1)) { - targetRect = *JsiSkRect::fromValue(runtime, arguments[1]); - } else { - targetRect = picture ? picture->cullRect() : SkRect::MakeEmpty(); - } - auto filter = std::make_shared( + std::shared_ptr MakePicture(sk_sp picture, + JsiOptional target) { + SkRect targetRect = target.has_value() + ? *target + : (picture ? picture->cullRect() + : SkRect::MakeEmpty()); + return std::make_shared( getContext(), SkImageFilters::Picture(std::move(picture), targetRect)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeRuntimeShaderWithChildren) { - auto rtb = JsiSkRuntimeShaderBuilder::fromValue(runtime, arguments[0]); - float maxSampleRadius = arguments[1].asNumber(); - std::vector childNames; - auto childNamesJS = arguments[2].asObject(runtime).asArray(runtime); - size_t length = childNamesJS.size(runtime); - for (size_t i = 0; i < length; ++i) { - auto element = childNamesJS.getValueAtIndex(runtime, i); - childNames.push_back(element.asString(runtime).utf8(runtime).c_str()); + } + + std::variant> + MakeRuntimeShaderWithChildren( + std::shared_ptr rtb, float maxSampleRadius, + std::vector childNames, + std::vector>> jsiInputs) { + if (jsiInputs.size() != childNames.size()) { + return nullptr; } std::vector childNamesStringView; childNamesStringView.reserve(childNames.size()); for (const auto &name : childNames) { childNamesStringView.push_back(std::string_view(name)); } - std::vector> inputs; - auto inputsJS = arguments[3].asObject(runtime).asArray(runtime); - if (inputsJS.size(runtime) != length) { - return jsi::Value::null(); - } - for (size_t i = 0; i < length; ++i) { - auto element = inputsJS.getValueAtIndex(runtime, i); - if (element.isNull()) { - inputs.push_back(nullptr); - } else { - inputs.push_back(JsiSkImageFilter::fromValue(runtime, element)); - } - } - auto filter = std::make_shared( - getContext(), SkImageFilters::RuntimeShader(*rtb, maxSampleRadius, - childNamesStringView.data(), - inputs.data(), length)); - return makeJsiObject(runtime, std::move(filter)); - } - - JSI_HOST_FUNCTION(MakeTile) { - SkRect src = *JsiSkRect::fromValue(runtime, arguments[0]); - SkRect dst = *JsiSkRect::fromValue(runtime, arguments[1]); - sk_sp input = nullptr; - if (hasOptionalArgument(arguments, count, 2)) { - input = JsiSkImageFilter::fromValue(runtime, arguments[2]); - } - auto filter = std::make_shared( - getContext(), SkImageFilters::Tile(src, dst, std::move(input))); - return makeJsiObject(runtime, std::move(filter)); + inputs.reserve(jsiInputs.size()); + for (auto &input : jsiInputs) { + inputs.push_back(orNull(std::move(input))); + } + return std::make_shared( + getContext(), SkImageFilters::RuntimeShader( + *rtb, maxSampleRadius, childNamesStringView.data(), + inputs.data(), inputs.size())); + } + + std::shared_ptr + MakeTile(SkRect src, SkRect dst, JsiOptional> input) { + return std::make_shared( + getContext(), SkImageFilters::Tile(src, dst, orNull(std::move(input)))); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeBlur", - &JsiSkImageFilterFactory::MakeBlur); - installHostMethod(runtime, prototype, "MakeOffset", - &JsiSkImageFilterFactory::MakeOffset); - installHostMethod(runtime, prototype, "MakeColorFilter", - &JsiSkImageFilterFactory::MakeColorFilter); - installHostMethod(runtime, prototype, "MakeShader", - &JsiSkImageFilterFactory::MakeShader); - installHostMethod(runtime, prototype, "MakeDisplacementMap", - &JsiSkImageFilterFactory::MakeDisplacementMap); - installHostMethod(runtime, prototype, "MakeCompose", - &JsiSkImageFilterFactory::MakeCompose); - installHostMethod(runtime, prototype, "MakeErode", - &JsiSkImageFilterFactory::MakeErode); - installHostMethod(runtime, prototype, "MakeDilate", - &JsiSkImageFilterFactory::MakeDilate); - installHostMethod(runtime, prototype, "MakeBlend", - &JsiSkImageFilterFactory::MakeBlend); - installHostMethod(runtime, prototype, "MakeDropShadow", - &JsiSkImageFilterFactory::MakeDropShadow); - installHostMethod(runtime, prototype, "MakeDropShadowOnly", - &JsiSkImageFilterFactory::MakeDropShadowOnly); - installHostMethod(runtime, prototype, "MakeRuntimeShader", - &JsiSkImageFilterFactory::MakeRuntimeShader); - installHostMethod(runtime, prototype, "MakeArithmetic", - &JsiSkImageFilterFactory::MakeArithmetic); - installHostMethod(runtime, prototype, "MakeCrop", - &JsiSkImageFilterFactory::MakeCrop); - installHostMethod(runtime, prototype, "MakeEmpty", - &JsiSkImageFilterFactory::MakeEmpty); - installHostMethod(runtime, prototype, "MakeImage", - &JsiSkImageFilterFactory::MakeImage); - installHostMethod(runtime, prototype, "MakeMagnifier", - &JsiSkImageFilterFactory::MakeMagnifier); - installHostMethod(runtime, prototype, "MakeMatrixConvolution", - &JsiSkImageFilterFactory::MakeMatrixConvolution); - installHostMethod(runtime, prototype, "MakeMatrixTransform", - &JsiSkImageFilterFactory::MakeMatrixTransform); - installHostMethod(runtime, prototype, "MakeMerge", - &JsiSkImageFilterFactory::MakeMerge); - installHostMethod(runtime, prototype, "MakePicture", - &JsiSkImageFilterFactory::MakePicture); - installHostMethod(runtime, prototype, "MakeRuntimeShaderWithChildren", - &JsiSkImageFilterFactory::MakeRuntimeShaderWithChildren); - installHostMethod(runtime, prototype, "MakeTile", - &JsiSkImageFilterFactory::MakeTile); - installHostMethod(runtime, prototype, "MakeDistantLitDiffuse", - &JsiSkImageFilterFactory::MakeDistantLitDiffuse); - installHostMethod(runtime, prototype, "MakePointLitDiffuse", - &JsiSkImageFilterFactory::MakePointLitDiffuse); - installHostMethod(runtime, prototype, "MakeSpotLitDiffuse", - &JsiSkImageFilterFactory::MakeSpotLitDiffuse); - installHostMethod(runtime, prototype, "MakeDistantLitSpecular", - &JsiSkImageFilterFactory::MakeDistantLitSpecular); - installHostMethod(runtime, prototype, "MakePointLitSpecular", - &JsiSkImageFilterFactory::MakePointLitSpecular); - installHostMethod(runtime, prototype, "MakeSpotLitSpecular", - &JsiSkImageFilterFactory::MakeSpotLitSpecular); + installMethod(runtime, prototype, "MakeBlur", + &JsiSkImageFilterFactory::MakeBlur); + installMethod(runtime, prototype, "MakeOffset", + &JsiSkImageFilterFactory::MakeOffset); + installMethod(runtime, prototype, "MakeColorFilter", + &JsiSkImageFilterFactory::MakeColorFilter); + installMethod(runtime, prototype, "MakeShader", + &JsiSkImageFilterFactory::MakeShader); + installMethod(runtime, prototype, "MakeDisplacementMap", + &JsiSkImageFilterFactory::MakeDisplacementMap); + installMethod(runtime, prototype, "MakeCompose", + &JsiSkImageFilterFactory::MakeCompose); + installMethod(runtime, prototype, "MakeErode", + &JsiSkImageFilterFactory::MakeErode); + installMethod(runtime, prototype, "MakeDilate", + &JsiSkImageFilterFactory::MakeDilate); + installMethod(runtime, prototype, "MakeBlend", + &JsiSkImageFilterFactory::MakeBlend); + installMethod(runtime, prototype, "MakeDropShadow", + &JsiSkImageFilterFactory::MakeDropShadow); + installMethod(runtime, prototype, "MakeDropShadowOnly", + &JsiSkImageFilterFactory::MakeDropShadowOnly); + installMethod(runtime, prototype, "MakeRuntimeShader", + &JsiSkImageFilterFactory::MakeRuntimeShader); + installMethod(runtime, prototype, "MakeArithmetic", + &JsiSkImageFilterFactory::MakeArithmetic); + installMethod(runtime, prototype, "MakeCrop", + &JsiSkImageFilterFactory::MakeCrop); + installMethod(runtime, prototype, "MakeEmpty", + &JsiSkImageFilterFactory::MakeEmpty); + installMethod(runtime, prototype, "MakeImage", + &JsiSkImageFilterFactory::MakeImage); + installMethod(runtime, prototype, "MakeMagnifier", + &JsiSkImageFilterFactory::MakeMagnifier); + installMethod(runtime, prototype, "MakeMatrixConvolution", + &JsiSkImageFilterFactory::MakeMatrixConvolution); + installMethod(runtime, prototype, "MakeMatrixTransform", + &JsiSkImageFilterFactory::MakeMatrixTransform); + installMethod(runtime, prototype, "MakeMerge", + &JsiSkImageFilterFactory::MakeMerge); + installMethod(runtime, prototype, "MakePicture", + &JsiSkImageFilterFactory::MakePicture); + installMethod(runtime, prototype, "MakeRuntimeShaderWithChildren", + &JsiSkImageFilterFactory::MakeRuntimeShaderWithChildren); + installMethod(runtime, prototype, "MakeTile", + &JsiSkImageFilterFactory::MakeTile); + installMethod(runtime, prototype, "MakeDistantLitDiffuse", + &JsiSkImageFilterFactory::MakeDistantLitDiffuse); + installMethod(runtime, prototype, "MakePointLitDiffuse", + &JsiSkImageFilterFactory::MakePointLitDiffuse); + installMethod(runtime, prototype, "MakeSpotLitDiffuse", + &JsiSkImageFilterFactory::MakeSpotLitDiffuse); + installMethod(runtime, prototype, "MakeDistantLitSpecular", + &JsiSkImageFilterFactory::MakeDistantLitSpecular); + installMethod(runtime, prototype, "MakePointLitSpecular", + &JsiSkImageFilterFactory::MakePointLitSpecular); + installMethod(runtime, prototype, "MakeSpotLitSpecular", + &JsiSkImageFilterFactory::MakeSpotLitSpecular); } size_t getMemoryPressure() override { return 2048; } explicit JsiSkImageFilterFactory(std::shared_ptr context) : JsiSkNativeObject(std::move(context)) {} + +private: + static sk_sp orNull(JsiOptional> filter) { + return filter.has_value() ? std::move(*filter) : nullptr; + } + + static SkImageFilters::CropRect toCropRect(const JsiOptional &rect) { + return rect.has_value() ? SkImageFilters::CropRect(*rect) + : SkImageFilters::CropRect{}; + } + + static SkFilterMode toFilterMode(const JsiOptional &mode) { + return mode.has_value() ? static_cast(*mode) + : SkFilterMode::kNearest; + } + + static SkMipmapMode toMipmapMode(const JsiOptional &mode) { + return mode.has_value() ? static_cast(*mode) + : SkMipmapMode::kNone; + } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkImageInfo.h b/packages/skia/cpp/api/JsiSkImageInfo.h index d1c23eb0f8..4956b9c95d 100644 --- a/packages/skia/cpp/api/JsiSkImageInfo.h +++ b/packages/skia/cpp/api/JsiSkImageInfo.h @@ -60,14 +60,12 @@ class JsiSkImageInfo std::move(context), imageInfo)); } - JSI_PROPERTY_GET(width) { return static_cast(getObject()->width()); } - JSI_PROPERTY_GET(height) { - return static_cast(getObject()->height()); - } - JSI_PROPERTY_GET(colorType) { + double getWidth() { return static_cast(getObject()->width()); } + double getHeight() { return static_cast(getObject()->height()); } + double getColorType() { return static_cast(getObject()->colorType()); } - JSI_PROPERTY_GET(alphaType) { + double getAlphaType() { return static_cast(getObject()->alphaType()); } @@ -77,13 +75,12 @@ class JsiSkImageInfo static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostGetter(runtime, prototype, "width", &JsiSkImageInfo::get_width); - installHostGetter(runtime, prototype, "height", - &JsiSkImageInfo::get_height); - installHostGetter(runtime, prototype, "colorType", - &JsiSkImageInfo::get_colorType); - installHostGetter(runtime, prototype, "alphaType", - &JsiSkImageInfo::get_alphaType); + installGetter(runtime, prototype, "width", &JsiSkImageInfo::getWidth); + installGetter(runtime, prototype, "height", &JsiSkImageInfo::getHeight); + installGetter(runtime, prototype, "colorType", + &JsiSkImageInfo::getColorType); + installGetter(runtime, prototype, "alphaType", + &JsiSkImageInfo::getAlphaType); } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkMaskFilterFactory.h b/packages/skia/cpp/api/JsiSkMaskFilterFactory.h index 6fa1be0fa8..ee352b0018 100644 --- a/packages/skia/cpp/api/JsiSkMaskFilterFactory.h +++ b/packages/skia/cpp/api/JsiSkMaskFilterFactory.h @@ -6,6 +6,7 @@ #include #include "JsiSkColorFilter.h" +#include "JsiSkConverters.h" #include "JsiSkMaskFilter.h" #include "JsiSkNativeObjects.h" @@ -25,22 +26,18 @@ class JsiSkMaskFilterFactory public: static constexpr const char *CLASS_NAME = "MaskFilterFactory"; - JSI_HOST_FUNCTION(MakeBlur) { - int blurStyle = arguments[0].asNumber(); - float sigma = arguments[1].asNumber(); - bool respectCTM = arguments[2].getBool(); - return makeJsiObject( - runtime, - std::make_shared( - getContext(), - SkMaskFilter::MakeBlur((SkBlurStyle)blurStyle, sigma, respectCTM))); + std::shared_ptr MakeBlur(int blurStyle, float sigma, + bool respectCTM) { + return std::make_shared( + getContext(), SkMaskFilter::MakeBlur(static_cast(blurStyle), + sigma, respectCTM)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeBlur", - &JsiSkMaskFilterFactory::MakeBlur); + installMethod(runtime, prototype, "MakeBlur", + &JsiSkMaskFilterFactory::MakeBlur); } explicit JsiSkMaskFilterFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkMatrix.h b/packages/skia/cpp/api/JsiSkMatrix.h index 9732b38da1..a7c6e531ce 100644 --- a/packages/skia/cpp/api/JsiSkMatrix.h +++ b/packages/skia/cpp/api/JsiSkMatrix.h @@ -2,9 +2,11 @@ #include #include +#include #include +#include "JsiSkConverters.h" #include "JsiSkNativeObjects.h" #pragma clang diagnostic push @@ -59,82 +61,39 @@ class JsiSkMatrix std::to_string(array.size(runtime))); } - JSI_HOST_FUNCTION(concat) { - auto matrix = tryGetJsiObject(runtime, arguments[0]); - if (matrix) { - getObject()->preConcat(*matrix->getObject()); - } else { - auto m3 = JsiSkMatrix::getMatrix(runtime, arguments[0]); - getObject()->preConcat(m3); - } - return thisValue.asObject(runtime); + void concat(std::shared_ptr matrix) { + getObject()->preConcat(*matrix); } - JSI_HOST_FUNCTION(translate) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - getObject()->preTranslate(x, y); - return thisValue.asObject(runtime); - } + void translate(double x, double y) { getObject()->preTranslate(x, y); } - JSI_HOST_FUNCTION(postTranslate) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - getObject()->postTranslate(x, y); - return thisValue.asObject(runtime); - } + void postTranslate(double x, double y) { getObject()->postTranslate(x, y); } - JSI_HOST_FUNCTION(scale) { - auto x = arguments[0].asNumber(); - auto y = count > 1 ? arguments[1].asNumber() : 1; - getObject()->preScale(x, y); - return thisValue.asObject(runtime); + void scale(double x, JsiOptional y) { + getObject()->preScale(x, y.has_value() ? *y : 1); } - JSI_HOST_FUNCTION(postScale) { - auto x = arguments[0].asNumber(); - auto y = count > 1 ? arguments[1].asNumber() : 1; - getObject()->postScale(x, y); - return thisValue.asObject(runtime); + void postScale(double x, JsiOptional y) { + getObject()->postScale(x, y.has_value() ? *y : 1); } - JSI_HOST_FUNCTION(skew) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - getObject()->preSkew(x, y); - return thisValue.asObject(runtime); - } + void skew(double x, double y) { getObject()->preSkew(x, y); } - JSI_HOST_FUNCTION(postSkew) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - getObject()->postSkew(x, y); - return thisValue.asObject(runtime); - } + void postSkew(double x, double y) { getObject()->postSkew(x, y); } - JSI_HOST_FUNCTION(rotate) { - auto a = arguments[0].asNumber(); - getObject()->preRotate(SkRadiansToDegrees(a)); - return thisValue.asObject(runtime); - } + void rotate(double a) { getObject()->preRotate(SkRadiansToDegrees(a)); } - JSI_HOST_FUNCTION(postRotate) { - auto a = arguments[0].asNumber(); - getObject()->postRotate(SkRadiansToDegrees(a)); - return thisValue.asObject(runtime); - } + void postRotate(double a) { getObject()->postRotate(SkRadiansToDegrees(a)); } - JSI_HOST_FUNCTION(identity) { - getObject()->setIdentity(); - return thisValue.asObject(runtime); - } + void identity() { getObject()->setIdentity(); } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Woverloaded-virtual" - JSI_HOST_FUNCTION(get) { - auto values = jsi::Array(runtime, 9); + std::vector get() { + std::vector values; + values.reserve(9); for (auto i = 0; i < 9; i++) { - values.setValueAtIndex(runtime, i, getObject()->get(i)); + values.push_back(getObject()->get(i)); } return values; } @@ -142,19 +101,23 @@ class JsiSkMatrix static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "concat", &JsiSkMatrix::concat); - installHostMethod(runtime, prototype, "translate", &JsiSkMatrix::translate); - installHostMethod(runtime, prototype, "postTranslate", - &JsiSkMatrix::postTranslate); - installHostMethod(runtime, prototype, "scale", &JsiSkMatrix::scale); - installHostMethod(runtime, prototype, "postScale", &JsiSkMatrix::postScale); - installHostMethod(runtime, prototype, "skew", &JsiSkMatrix::skew); - installHostMethod(runtime, prototype, "postSkew", &JsiSkMatrix::postSkew); - installHostMethod(runtime, prototype, "rotate", &JsiSkMatrix::rotate); - installHostMethod(runtime, prototype, "postRotate", - &JsiSkMatrix::postRotate); - installHostMethod(runtime, prototype, "identity", &JsiSkMatrix::identity); - installHostMethod(runtime, prototype, "get", &JsiSkMatrix::get); + installChainableMethod(runtime, prototype, "concat", &JsiSkMatrix::concat); + installChainableMethod(runtime, prototype, "translate", + &JsiSkMatrix::translate); + installChainableMethod(runtime, prototype, "postTranslate", + &JsiSkMatrix::postTranslate); + installChainableMethod(runtime, prototype, "scale", &JsiSkMatrix::scale); + installChainableMethod(runtime, prototype, "postScale", + &JsiSkMatrix::postScale); + installChainableMethod(runtime, prototype, "skew", &JsiSkMatrix::skew); + installChainableMethod(runtime, prototype, "postSkew", + &JsiSkMatrix::postSkew); + installChainableMethod(runtime, prototype, "rotate", &JsiSkMatrix::rotate); + installChainableMethod(runtime, prototype, "postRotate", + &JsiSkMatrix::postRotate); + installChainableMethod(runtime, prototype, "identity", + &JsiSkMatrix::identity); + installMethod(runtime, prototype, "get", &JsiSkMatrix::get); } /** diff --git a/packages/skia/cpp/api/JsiSkNativeObjects.h b/packages/skia/cpp/api/JsiSkNativeObjects.h index 09b7f52ecc..413d80fe5a 100644 --- a/packages/skia/cpp/api/JsiSkNativeObjects.h +++ b/packages/skia/cpp/api/JsiSkNativeObjects.h @@ -280,7 +280,71 @@ class JsiSkNativeObject : public rnwgpu::NativeObject { installHostSetter(runtime, prototype, name, setter); } + /** + * Installs a typed mutating method that returns `this` for chaining + * (e.g. path.moveTo(...).lineTo(...)). Arguments are converted through + * rnwgpu::JSIConverter like installMethod; the member function's return + * value (if any) is ignored and the JS function returns thisValue. + */ + template + static void installChainableMethod(jsi::Runtime &runtime, + jsi::Object &prototype, const char *name, + ReturnType (Derived::*method)(Args...)) { + auto func = jsi::Function::createFromHostFunction( + runtime, jsi::PropNameID::forUtf8(runtime, name), sizeof...(Args), + [method](jsi::Runtime &rt, const jsi::Value &thisValue, + const jsi::Value *args, size_t count) -> jsi::Value { + auto native = fromThis(rt, thisValue); + invokeChainable(native.get(), method, rt, args, + std::index_sequence_for{}, count); + return jsi::Value(rt, thisValue); + }); + prototype.setProperty(runtime, name, func); + } + + /** + * Chainable variant for methods that need the calling jsi::Runtime as + * their first parameter (e.g. the deprecated SkPath mutators, which log a + * warning to the JS console). + */ + template + static void installChainableMethodWithRuntime( + jsi::Runtime &runtime, jsi::Object &prototype, const char *name, + ReturnType (Derived::*method)(jsi::Runtime &, Args...)) { + auto func = jsi::Function::createFromHostFunction( + runtime, jsi::PropNameID::forUtf8(runtime, name), sizeof...(Args), + [method](jsi::Runtime &rt, const jsi::Value &thisValue, + const jsi::Value *args, size_t count) -> jsi::Value { + auto native = fromThis(rt, thisValue); + invokeChainableWithRuntime(native.get(), method, rt, args, + std::index_sequence_for{}, count); + return jsi::Value(rt, thisValue); + }); + prototype.setProperty(runtime, name, func); + } + private: + // Invokes a typed member function with JSI argument conversion, discarding + // the result. Used by installChainableMethod, which returns thisValue. + template + static void invokeChainable(Derived *obj, + ReturnType (Derived::*method)(Args...), + jsi::Runtime &runtime, const jsi::Value *args, + std::index_sequence, size_t count) { + (obj->*method)(rnwgpu::JSIConverter>::fromJSI( + runtime, args[Is], Is >= count)...); + } + + template + static void invokeChainableWithRuntime( + Derived *obj, ReturnType (Derived::*method)(jsi::Runtime &, Args...), + jsi::Runtime &runtime, const jsi::Value *args, std::index_sequence, + size_t count) { + (obj->*method)(runtime, + rnwgpu::JSIConverter>::fromJSI( + runtime, args[Is], Is >= count)...); + } + static void defineProperty(jsi::Runtime &runtime, jsi::Object &prototype, const char *name, jsi::Function *getter, jsi::Function *setter) { diff --git a/packages/skia/cpp/api/JsiSkPaint.h b/packages/skia/cpp/api/JsiSkPaint.h index a7e63994de..dddffcb7ae 100644 --- a/packages/skia/cpp/api/JsiSkPaint.h +++ b/packages/skia/cpp/api/JsiSkPaint.h @@ -7,6 +7,7 @@ #include "CustomBlendModes.h" #include "JsiSkColor.h" +#include "JsiSkConverters.h" #include "JsiSkColorFilter.h" #include "JsiSkImageFilter.h" #include "JsiSkMaskFilter.h" @@ -29,188 +30,129 @@ class JsiSkPaint public: static constexpr const char *CLASS_NAME = "Paint"; - JSI_HOST_FUNCTION(assign) { - SkPaint *paint = JsiSkPaint::fromValue(runtime, arguments[0]).get(); - *getObject() = *paint; - return jsi::Value::undefined(); - } + void assign(std::shared_ptr paint) { *getObject() = *paint; } - JSI_HOST_FUNCTION(copy) { + std::shared_ptr copy() { const auto *paint = getObject().get(); - return makeJsiObject( - runtime, std::make_shared(getContext(), SkPaint(*paint))); + return std::make_shared(getContext(), SkPaint(*paint)); } - JSI_HOST_FUNCTION(reset) { - getObject()->reset(); - return jsi::Value::undefined(); - } + void reset() { getObject()->reset(); } - JSI_HOST_FUNCTION(getColor) { - return JsiSkColor::toValue(runtime, getObject()->getColor()); - } + JsiColor getColor() { return {getObject()->getColor()}; } - JSI_HOST_FUNCTION(getStrokeCap) { + double getStrokeCap() { return static_cast(getObject()->getStrokeCap()); } - JSI_HOST_FUNCTION(getStrokeJoin) { + double getStrokeJoin() { return static_cast(getObject()->getStrokeJoin()); } - JSI_HOST_FUNCTION(getStrokeMiter) { + double getStrokeMiter() { return static_cast(getObject()->getStrokeMiter()); } - JSI_HOST_FUNCTION(getStrokeWidth) { + double getStrokeWidth() { return static_cast(getObject()->getStrokeWidth()); } - JSI_HOST_FUNCTION(getAlphaf) { - float alphaf = getObject()->getAlphaf(); - return jsi::Value(SkScalarToDouble(alphaf)); - } + double getAlphaf() { return SkScalarToDouble(getObject()->getAlphaf()); } - JSI_HOST_FUNCTION(setColor) { - SkColor color = JsiSkColor::fromValue(runtime, arguments[0]); - getObject()->setColor(color); - return jsi::Value::undefined(); - } + void setColor(JsiColor color) { getObject()->setColor(color); } - JSI_HOST_FUNCTION(setAlphaf) { - SkScalar alpha = arguments[0].asNumber(); - getObject()->setAlphaf(alpha); - return jsi::Value::undefined(); - } + void setAlphaf(double alpha) { getObject()->setAlphaf(alpha); } - JSI_HOST_FUNCTION(setAntiAlias) { - bool antiAliased = arguments[0].getBool(); + void setAntiAlias(bool antiAliased) { getObject()->setAntiAlias(antiAliased); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setDither) { - bool dithered = arguments[0].getBool(); - getObject()->setDither(dithered); - return jsi::Value::undefined(); - } + void setDither(bool dithered) { getObject()->setDither(dithered); } - JSI_HOST_FUNCTION(setStrokeWidth) { - SkScalar width = arguments[0].asNumber(); - getObject()->setStrokeWidth(width); - return jsi::Value::undefined(); - } + void setStrokeWidth(double width) { getObject()->setStrokeWidth(width); } - JSI_HOST_FUNCTION(setStyle) { - auto style = arguments[0].asNumber(); + void setStyle(double style) { getObject()->setStyle(static_cast(style)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setStrokeCap) { - auto cap = arguments[0].asNumber(); + void setStrokeCap(double cap) { getObject()->setStrokeCap(static_cast(cap)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setStrokeJoin) { - int join = arguments[0].asNumber(); + void setStrokeJoin(int join) { getObject()->setStrokeJoin(static_cast(join)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setStrokeMiter) { - int limit = arguments[0].asNumber(); - getObject()->setStrokeMiter(limit); - return jsi::Value::undefined(); - } + void setStrokeMiter(int limit) { getObject()->setStrokeMiter(limit); } - JSI_HOST_FUNCTION(setBlendMode) { - int blendModeValue = static_cast(arguments[0].asNumber()); + void setBlendMode(int blendModeValue) { applyBlendMode(*getObject(), blendModeValue); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setMaskFilter) { - auto maskFilter = arguments[0].isNull() || arguments[0].isUndefined() - ? nullptr - : JsiSkMaskFilter::fromValue(runtime, arguments[0]); - getObject()->setMaskFilter(std::move(maskFilter)); - return jsi::Value::undefined(); + void setMaskFilter(JsiOptional> maskFilter) { + getObject()->setMaskFilter( + maskFilter.has_value() ? std::move(*maskFilter) : nullptr); } - JSI_HOST_FUNCTION(setImageFilter) { - auto imageFilter = arguments[0].isNull() || arguments[0].isUndefined() - ? nullptr - : JsiSkImageFilter::fromValue(runtime, arguments[0]); - getObject()->setImageFilter(std::move(imageFilter)); - return jsi::Value::undefined(); + void setImageFilter(JsiOptional> imageFilter) { + getObject()->setImageFilter( + imageFilter.has_value() ? std::move(*imageFilter) : nullptr); } - JSI_HOST_FUNCTION(setColorFilter) { - auto colorFilter = arguments[0].isNull() || arguments[0].isUndefined() - ? nullptr - : JsiSkColorFilter::fromValue(runtime, arguments[0]); - getObject()->setColorFilter(std::move(colorFilter)); - return jsi::Value::undefined(); + void setColorFilter(JsiOptional> colorFilter) { + getObject()->setColorFilter( + colorFilter.has_value() ? std::move(*colorFilter) : nullptr); } - JSI_HOST_FUNCTION(setShader) { - auto shader = arguments[0].isNull() || arguments[0].isUndefined() - ? nullptr - : JsiSkShader::fromValue(runtime, arguments[0]); - getObject()->setShader(std::move(shader)); - return jsi::Value::undefined(); + void setShader(JsiOptional> shader) { + getObject()->setShader(shader.has_value() ? std::move(*shader) : nullptr); } - JSI_HOST_FUNCTION(setPathEffect) { - auto pathEffect = arguments[0].isNull() || arguments[0].isUndefined() - ? nullptr - : JsiSkPathEffect::fromValue(runtime, arguments[0]); - getObject()->setPathEffect(std::move(pathEffect)); - return jsi::Value::undefined(); + void setPathEffect(JsiOptional> pathEffect) { + getObject()->setPathEffect( + pathEffect.has_value() ? std::move(*pathEffect) : nullptr); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "assign", &JsiSkPaint::assign); - installHostMethod(runtime, prototype, "copy", &JsiSkPaint::copy); - installHostMethod(runtime, prototype, "reset", &JsiSkPaint::reset); - installHostMethod(runtime, prototype, "getAlphaf", &JsiSkPaint::getAlphaf); - installHostMethod(runtime, prototype, "getColor", &JsiSkPaint::getColor); - installHostMethod(runtime, prototype, "getStrokeCap", - &JsiSkPaint::getStrokeCap); - installHostMethod(runtime, prototype, "getStrokeJoin", - &JsiSkPaint::getStrokeJoin); - installHostMethod(runtime, prototype, "getStrokeMiter", - &JsiSkPaint::getStrokeMiter); - installHostMethod(runtime, prototype, "getStrokeWidth", - &JsiSkPaint::getStrokeWidth); - installHostMethod(runtime, prototype, "setPathEffect", - &JsiSkPaint::setPathEffect); - installHostMethod(runtime, prototype, "setShader", &JsiSkPaint::setShader); - installHostMethod(runtime, prototype, "setColorFilter", - &JsiSkPaint::setColorFilter); - installHostMethod(runtime, prototype, "setImageFilter", - &JsiSkPaint::setImageFilter); - installHostMethod(runtime, prototype, "setMaskFilter", - &JsiSkPaint::setMaskFilter); - installHostMethod(runtime, prototype, "setBlendMode", - &JsiSkPaint::setBlendMode); - installHostMethod(runtime, prototype, "setStrokeMiter", - &JsiSkPaint::setStrokeMiter); - installHostMethod(runtime, prototype, "setStrokeJoin", - &JsiSkPaint::setStrokeJoin); - installHostMethod(runtime, prototype, "setStrokeCap", - &JsiSkPaint::setStrokeCap); - installHostMethod(runtime, prototype, "setAntiAlias", - &JsiSkPaint::setAntiAlias); - installHostMethod(runtime, prototype, "setDither", &JsiSkPaint::setDither); - installHostMethod(runtime, prototype, "setStrokeWidth", - &JsiSkPaint::setStrokeWidth); - installHostMethod(runtime, prototype, "setStyle", &JsiSkPaint::setStyle); - installHostMethod(runtime, prototype, "setColor", &JsiSkPaint::setColor); - installHostMethod(runtime, prototype, "setAlphaf", &JsiSkPaint::setAlphaf); + installMethod(runtime, prototype, "assign", &JsiSkPaint::assign); + installMethod(runtime, prototype, "copy", &JsiSkPaint::copy); + installMethod(runtime, prototype, "reset", &JsiSkPaint::reset); + installMethod(runtime, prototype, "getAlphaf", &JsiSkPaint::getAlphaf); + installMethod(runtime, prototype, "getColor", &JsiSkPaint::getColor); + installMethod(runtime, prototype, "getStrokeCap", + &JsiSkPaint::getStrokeCap); + installMethod(runtime, prototype, "getStrokeJoin", + &JsiSkPaint::getStrokeJoin); + installMethod(runtime, prototype, "getStrokeMiter", + &JsiSkPaint::getStrokeMiter); + installMethod(runtime, prototype, "getStrokeWidth", + &JsiSkPaint::getStrokeWidth); + installMethod(runtime, prototype, "setPathEffect", + &JsiSkPaint::setPathEffect); + installMethod(runtime, prototype, "setShader", &JsiSkPaint::setShader); + installMethod(runtime, prototype, "setColorFilter", + &JsiSkPaint::setColorFilter); + installMethod(runtime, prototype, "setImageFilter", + &JsiSkPaint::setImageFilter); + installMethod(runtime, prototype, "setMaskFilter", + &JsiSkPaint::setMaskFilter); + installMethod(runtime, prototype, "setBlendMode", + &JsiSkPaint::setBlendMode); + installMethod(runtime, prototype, "setStrokeMiter", + &JsiSkPaint::setStrokeMiter); + installMethod(runtime, prototype, "setStrokeJoin", + &JsiSkPaint::setStrokeJoin); + installMethod(runtime, prototype, "setStrokeCap", + &JsiSkPaint::setStrokeCap); + installMethod(runtime, prototype, "setAntiAlias", + &JsiSkPaint::setAntiAlias); + installMethod(runtime, prototype, "setDither", &JsiSkPaint::setDither); + installMethod(runtime, prototype, "setStrokeWidth", + &JsiSkPaint::setStrokeWidth); + installMethod(runtime, prototype, "setStyle", &JsiSkPaint::setStyle); + installMethod(runtime, prototype, "setColor", &JsiSkPaint::setColor); + installMethod(runtime, prototype, "setAlphaf", &JsiSkPaint::setAlphaf); } JsiSkPaint(std::shared_ptr context, SkPaint paint) diff --git a/packages/skia/cpp/api/JsiSkPath.h b/packages/skia/cpp/api/JsiSkPath.h index 469c1f59f0..7bcedea8ef 100644 --- a/packages/skia/cpp/api/JsiSkPath.h +++ b/packages/skia/cpp/api/JsiSkPath.h @@ -2,13 +2,16 @@ #include #include +#include #include #include #include +#include #include #include +#include "JsiSkConverters.h" #include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" #include "JsiSkPoint.h" @@ -77,338 +80,233 @@ class JsiSkPath SkPath asPath() const { return getObject()->snapshot(); } public: - // Mutable building methods (deprecated) + // Mutable building methods (deprecated) — chainable, and they take the + // runtime for the JS console deprecation warning. - JSI_HOST_FUNCTION(moveTo) { + void moveTo(jsi::Runtime &runtime, double x, double y) { warnDeprecatedPathMethod(runtime, "moveTo", "Use Skia.PathBuilder.Make().moveTo() instead."); - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); getObject()->moveTo(x, y); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rMoveTo) { + void rMoveTo(jsi::Runtime &runtime, double x, double y) { warnDeprecatedPathMethod(runtime, "rMoveTo", "Use Skia.PathBuilder.Make().rMoveTo() instead."); - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - getObject()->rMoveTo({x, y}); - return thisValue.getObject(runtime); + getObject()->rMoveTo({static_cast(x), static_cast(y)}); } - JSI_HOST_FUNCTION(lineTo) { + void lineTo(jsi::Runtime &runtime, double x, double y) { warnDeprecatedPathMethod(runtime, "lineTo", "Use Skia.PathBuilder.Make().lineTo() instead."); - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); getObject()->lineTo(x, y); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rLineTo) { + void rLineTo(jsi::Runtime &runtime, double x, double y) { warnDeprecatedPathMethod(runtime, "rLineTo", "Use Skia.PathBuilder.Make().rLineTo() instead."); - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); getObject()->rLineTo(x, y); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(quadTo) { + void quadTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2) { warnDeprecatedPathMethod(runtime, "quadTo", "Use Skia.PathBuilder.Make().quadTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); getObject()->quadTo(x1, y1, x2, y2); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rQuadTo) { + void rQuadTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2) { warnDeprecatedPathMethod(runtime, "rQuadTo", "Use Skia.PathBuilder.Make().rQuadTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); getObject()->rQuadTo(x1, y1, x2, y2); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(conicTo) { + void conicTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2, double w) { warnDeprecatedPathMethod(runtime, "conicTo", "Use Skia.PathBuilder.Make().conicTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); - SkScalar w = arguments[4].asNumber(); getObject()->conicTo(x1, y1, x2, y2, w); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rConicTo) { + void rConicTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2, double w) { warnDeprecatedPathMethod(runtime, "rConicTo", "Use Skia.PathBuilder.Make().rConicTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); - SkScalar w = arguments[4].asNumber(); getObject()->rConicTo(x1, y1, x2, y2, w); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(cubicTo) { + void cubicTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2, double x3, double y3) { warnDeprecatedPathMethod(runtime, "cubicTo", "Use Skia.PathBuilder.Make().cubicTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); - SkScalar x3 = arguments[4].asNumber(); - SkScalar y3 = arguments[5].asNumber(); getObject()->cubicTo(x1, y1, x2, y2, x3, y3); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rCubicTo) { + void rCubicTo(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2, double x3, double y3) { warnDeprecatedPathMethod(runtime, "rCubicTo", "Use Skia.PathBuilder.Make().rCubicTo() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); - SkScalar x3 = arguments[4].asNumber(); - SkScalar y3 = arguments[5].asNumber(); getObject()->rCubicTo(x1, y1, x2, y2, x3, y3); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(close) { + void close(jsi::Runtime &runtime) { warnDeprecatedPathMethod(runtime, "close", "Use Skia.PathBuilder.Make().close() instead."); getObject()->close(); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(reset) { + void reset(jsi::Runtime &runtime) { warnDeprecatedPathMethod(runtime, "reset", "Use Skia.PathBuilder.Make().reset() instead."); getObject()->reset(); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rewind) { + void rewind(jsi::Runtime &runtime) { warnDeprecatedPathMethod(runtime, "rewind", "Use Skia.PathBuilder.Make().reset() instead."); getObject()->reset(); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addPath) { + void addPath(jsi::Runtime &runtime, std::shared_ptr src, + JsiOptional> matrix, + JsiOptional extend) { warnDeprecatedPathMethod(runtime, "addPath", "Use Skia.PathBuilder.Make().addPath() instead."); - auto src = JsiSkPath::fromValue(runtime, arguments[0]); auto srcPath = src->snapshot(); - auto matrix = - count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull() - ? JsiSkMatrix::fromValue(runtime, arguments[1]) - : nullptr; - auto extend = count > 2 && arguments[2].getBool(); - auto mode = - extend ? SkPath::kExtend_AddPathMode : SkPath::kAppend_AddPathMode; - if (matrix) { - getObject()->addPath(srcPath, *matrix, mode); + auto mode = extend.has_value() && *extend ? SkPath::kExtend_AddPathMode + : SkPath::kAppend_AddPathMode; + if (matrix.has_value()) { + getObject()->addPath(srcPath, **matrix, mode); } else { getObject()->addPath(srcPath, mode); } - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addArc) { + void addArc(jsi::Runtime &runtime, std::shared_ptr rect, + double start, double sweep) { warnDeprecatedPathMethod(runtime, "addArc", "Use Skia.PathBuilder.Make().addArc() instead."); - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto start = arguments[1].asNumber(); - auto sweep = arguments[2].asNumber(); getObject()->addArc(*rect, start, sweep); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addOval) { + void addOval(jsi::Runtime &runtime, std::shared_ptr rect, + JsiOptional isCCW, JsiOptional startIndex) { warnDeprecatedPathMethod( runtime, "addOval", "Use Skia.Path.Oval() or Skia.PathBuilder.Make().addOval() instead."); - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto isCCW = count > 1 && arguments[1].getBool(); - auto startIndex = - count > 2 ? static_cast(arguments[2].asNumber()) : 1; - auto direction = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; - getObject()->addOval(*rect, direction, startIndex); - return thisValue.getObject(runtime); + getObject()->addOval(*rect, toDirection(isCCW), + startIndex.has_value() + ? static_cast(*startIndex) + : 1); } - JSI_HOST_FUNCTION(addRect) { + void addRect(jsi::Runtime &runtime, std::shared_ptr rect, + JsiOptional isCCW) { warnDeprecatedPathMethod( runtime, "addRect", "Use Skia.Path.Rect() or Skia.PathBuilder.Make().addRect() instead."); - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto isCCW = count > 1 && arguments[1].getBool(); - auto direction = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; - getObject()->addRect(*rect, direction); - return thisValue.getObject(runtime); + getObject()->addRect(*rect, toDirection(isCCW)); } - JSI_HOST_FUNCTION(addRRect) { + void addRRect(jsi::Runtime &runtime, std::shared_ptr rrect, + JsiOptional isCCW) { warnDeprecatedPathMethod( runtime, "addRRect", "Use Skia.Path.RRect() or Skia.PathBuilder.Make().addRRect() instead."); - auto rrect = JsiSkRRect::fromValue(runtime, arguments[0]); - auto isCCW = count > 1 && arguments[1].getBool(); - auto direction = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; - getObject()->addRRect(*rrect, direction); - return thisValue.getObject(runtime); + getObject()->addRRect(*rrect, toDirection(isCCW)); } - JSI_HOST_FUNCTION(addCircle) { + void addCircle(jsi::Runtime &runtime, double x, double y, double r) { warnDeprecatedPathMethod( runtime, "addCircle", "Use Skia.Path.Circle() or Skia.PathBuilder.Make().addCircle() " "instead."); - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - SkScalar r = arguments[2].asNumber(); getObject()->addCircle(x, y, r); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addPoly) { + void addPoly(jsi::Runtime &runtime, std::vector points, + bool close) { warnDeprecatedPathMethod( runtime, "addPoly", "Use Skia.Path.Polygon() or Skia.PathBuilder.Make().addPoly() " "instead."); - auto jsiPoints = arguments[0].asObject(runtime).asArray(runtime); - auto close = arguments[1].getBool(); - auto pointsSize = static_cast(jsiPoints.size(runtime)); - std::vector points; - points.reserve(pointsSize); - for (int i = 0; i < pointsSize; i++) { - auto pt = - JsiSkPoint::fromValue(runtime, jsiPoints.getValueAtIndex(runtime, i)); - points.push_back(*pt); - } getObject()->addPolygon(SkSpan(points.data(), points.size()), close); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(arcToOval) { + void arcToOval(jsi::Runtime &runtime, std::shared_ptr rect, + double start, double sweep, bool forceMoveTo) { warnDeprecatedPathMethod( runtime, "arcToOval", "Use Skia.PathBuilder.Make().arcToOval() instead."); - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto start = arguments[1].asNumber(); - auto sweep = arguments[2].asNumber(); - auto forceMoveTo = arguments[3].getBool(); getObject()->arcTo(*rect, start, sweep, forceMoveTo); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(arcToRotated) { + void arcToRotated(jsi::Runtime &runtime, double rx, double ry, + double xAxisRotate, bool useSmallArc, bool isCCW, double x, + double y) { warnDeprecatedPathMethod( runtime, "arcToRotated", "Use Skia.PathBuilder.Make().arcToRotated() instead."); - SkScalar rx = arguments[0].asNumber(); - SkScalar ry = arguments[1].asNumber(); - SkScalar xAxisRotate = arguments[2].asNumber(); - auto useSmallArc = arguments[3].getBool(); - auto isCCW = arguments[4].getBool(); - SkScalar x = arguments[5].asNumber(); - SkScalar y = arguments[6].asNumber(); auto arcSize = useSmallArc ? SkPathBuilder::kSmall_ArcSize : SkPathBuilder::kLarge_ArcSize; auto sweep = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; getObject()->arcTo(SkPoint::Make(rx, ry), xAxisRotate, arcSize, sweep, SkPoint::Make(x, y)); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rArcTo) { + void rArcTo(jsi::Runtime &runtime, double rx, double ry, double xAxisRotate, + bool useSmallArc, bool isCCW, double dx, double dy) { warnDeprecatedPathMethod(runtime, "rArcTo", "Use Skia.PathBuilder.Make().rArcTo() instead."); - SkScalar rx = arguments[0].asNumber(); - SkScalar ry = arguments[1].asNumber(); - SkScalar xAxisRotate = arguments[2].asNumber(); - auto useSmallArc = arguments[3].getBool(); - auto isCCW = arguments[4].getBool(); - SkScalar dx = arguments[5].asNumber(); - SkScalar dy = arguments[6].asNumber(); auto arcSize = useSmallArc ? SkPathBuilder::kSmall_ArcSize : SkPathBuilder::kLarge_ArcSize; auto sweep = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; SkVector dxdy(dx, dy); SkPoint r(rx, ry); getObject()->rArcTo(r, xAxisRotate, arcSize, sweep, dxdy); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(arcToTangent) { + void arcToTangent(jsi::Runtime &runtime, double x1, double y1, double x2, + double y2, double r) { warnDeprecatedPathMethod( runtime, "arcToTangent", "Use Skia.PathBuilder.Make().arcToTangent() instead."); - SkScalar x1 = arguments[0].asNumber(); - SkScalar y1 = arguments[1].asNumber(); - SkScalar x2 = arguments[2].asNumber(); - SkScalar y2 = arguments[3].asNumber(); - SkScalar r = arguments[4].asNumber(); getObject()->arcTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), r); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(setFillType) { + void setFillType(jsi::Runtime &runtime, double ft) { warnDeprecatedPathMethod( runtime, "setFillType", "Use Skia.PathBuilder.Make().setFillType() instead."); - auto ft = arguments[0].asNumber(); getObject()->setFillType(static_cast(static_cast(ft))); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(setIsVolatile) { + void setIsVolatile(jsi::Runtime &runtime, bool v) { warnDeprecatedPathMethod( runtime, "setIsVolatile", "Use Skia.PathBuilder.Make().setIsVolatile() instead."); - auto v = arguments[0].getBool(); getObject()->setIsVolatile(v); - return thisValue.getObject(runtime); } // Mutable transform methods (deprecated) - JSI_HOST_FUNCTION(transform) { + void transform(jsi::Runtime &runtime, std::shared_ptr m3) { warnDeprecatedPathMethod( runtime, "transform", "Use Skia.PathBuilder.Make().transform() instead."); - auto m3 = *JsiSkMatrix::fromValue(runtime, arguments[0]); - getObject()->transform(m3); - return thisValue.getObject(runtime); + getObject()->transform(*m3); } - JSI_HOST_FUNCTION(offset) { + void offset(jsi::Runtime &runtime, double dx, double dy) { warnDeprecatedPathMethod(runtime, "offset", "Use Skia.PathBuilder.Make().offset() instead."); - SkScalar dx = arguments[0].asNumber(); - SkScalar dy = arguments[1].asNumber(); getObject()->offset(dx, dy); - return thisValue.getObject(runtime); } // Mutable path operations (deprecated) - JSI_HOST_FUNCTION(simplify) { + void simplify(jsi::Runtime &runtime) { warnDeprecatedPathMethod(runtime, "simplify", "Use Skia.Path.Simplify(path) instead."); auto path = asPath(); @@ -416,25 +314,22 @@ class JsiSkPath if (result.has_value()) { *getObject() = SkPathBuilder(result.value()); } - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(op) { + void op(jsi::Runtime &runtime, std::shared_ptr path2, + double pathOp) { warnDeprecatedPathMethod(runtime, "op", "Use Skia.Path.MakeFromOp() instead."); - auto path2 = JsiSkPath::fromValue(runtime, arguments[0]); - auto pathOp = - static_cast(static_cast(arguments[1].asNumber())); auto p1 = asPath(); auto p2 = path2->snapshot(); - auto result = ::Op(p1, p2, pathOp); + auto result = + ::Op(p1, p2, static_cast(static_cast(pathOp))); if (result.has_value()) { *getObject() = SkPathBuilder(result.value()); } - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(makeAsWinding) { + void makeAsWinding(jsi::Runtime &runtime) { warnDeprecatedPathMethod(runtime, "makeAsWinding", "Use Skia.Path.AsWinding(path) instead."); auto path = asPath(); @@ -442,17 +337,14 @@ class JsiSkPath if (result.has_value()) { *getObject() = SkPathBuilder(result.value()); } - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(dash) { + void dash(jsi::Runtime &runtime, double on, double off, double phase) { warnDeprecatedPathMethod( runtime, "dash", "Use Skia.Path.Dash(path, on, off, phase) instead."); auto path = asPath(); - SkScalar on = arguments[0].asNumber(); - SkScalar off = arguments[1].asNumber(); - auto phase = arguments[2].asNumber(); - SkScalar intervals[] = {on, off}; + SkScalar intervals[] = {static_cast(on), + static_cast(off)}; auto pe = SkDashPathEffect::Make(SkSpan(intervals, 2), phase); if (pe) { SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle); @@ -461,9 +353,9 @@ class JsiSkPath *getObject() = std::move(resultBuilder); } } - return thisValue.getObject(runtime); } + // Stays raw: the options object is read leniently property by property. JSI_HOST_FUNCTION(stroke) { warnDeprecatedPathMethod(runtime, "stroke", "Use Skia.Path.Stroke(path, opts) instead."); @@ -505,16 +397,14 @@ class JsiSkPath return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(trim) { + void trim(jsi::Runtime &runtime, double startValue, double endValue, + bool isComplement) { warnDeprecatedPathMethod( runtime, "trim", "Use Skia.Path.Trim(path, start, end, isComplement) instead."); auto path = asPath(); - float start = - std::clamp(static_cast(arguments[0].asNumber()), 0.0f, 1.0f); - float end = - std::clamp(static_cast(arguments[1].asNumber()), 0.0f, 1.0f); - auto isComplement = arguments[2].getBool(); + float start = std::clamp(static_cast(startValue), 0.0f, 1.0f); + float end = std::clamp(static_cast(endValue), 0.0f, 1.0f); auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal; auto pe = SkTrimPathEffect::Make(start, end, mode); @@ -525,106 +415,77 @@ class JsiSkPath *getObject() = std::move(resultBuilder); } } - return thisValue.getObject(runtime); } // Query methods - JSI_HOST_FUNCTION(computeTightBounds) { + std::shared_ptr computeTightBounds() { auto path = asPath(); - auto result = path.computeTightBounds(); - return makeJsiObject(runtime, - std::make_shared(getContext(), result)); + return std::make_shared(getContext(), + path.computeTightBounds()); } - JSI_HOST_FUNCTION(getBounds) { - auto result = getObject()->computeBounds(); - return makeJsiObject(runtime, - std::make_shared(getContext(), result)); + std::shared_ptr getBounds() { + return std::make_shared(getContext(), + getObject()->computeBounds()); } - JSI_HOST_FUNCTION(contains) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - return jsi::Value(asPath().contains(x, y)); - } + bool contains(double x, double y) { return asPath().contains(x, y); } - JSI_HOST_FUNCTION(getFillType) { - auto fillType = getObject()->fillType(); - return jsi::Value(static_cast(fillType)); - } + int getFillType() { return static_cast(getObject()->fillType()); } - JSI_HOST_FUNCTION(isVolatile) { return jsi::Value(asPath().isVolatile()); } + bool isVolatile() { return asPath().isVolatile(); } - JSI_HOST_FUNCTION(getPoint) { - auto index = arguments[0].asNumber(); + std::shared_ptr getPoint(int index) { auto point = asPath().getPoint(index); - return makeJsiObject(runtime, - std::make_shared(getContext(), point)); + return std::make_shared(getContext(), point); } - JSI_HOST_FUNCTION(isEmpty) { return jsi::Value(getObject()->isEmpty()); } + bool isEmpty() { return getObject()->isEmpty(); } - JSI_HOST_FUNCTION(countPoints) { - auto points = asPath().countPoints(); - return jsi::Value(points); - } + int countPoints() { return asPath().countPoints(); } - JSI_HOST_FUNCTION(getLastPt) { + SkPoint getLastPt() { auto last = getObject()->getLastPt(); - auto point = jsi::Object(runtime); - if (last.has_value()) { - point.setProperty(runtime, "x", static_cast(last->fX)); - point.setProperty(runtime, "y", static_cast(last->fY)); - } else { - point.setProperty(runtime, "x", 0.0); - point.setProperty(runtime, "y", 0.0); - } - return point; + return last.value_or(SkPoint::Make(0, 0)); } - JSI_HOST_FUNCTION(toSVGString) { + std::string toSVGString() { auto path = asPath(); auto s = SkParsePath::ToSVGString(path); - return jsi::String::createFromUtf8(runtime, s.c_str()); + return std::string(s.c_str()); } - JSI_HOST_FUNCTION(equals) { - auto p1 = JsiSkPath::fromValue(runtime, arguments[0]); - auto p2 = JsiSkPath::fromValue(runtime, arguments[1]); - return jsi::Value(p1->snapshot() == p2->snapshot()); + bool equals(std::shared_ptr p1, + std::shared_ptr p2) { + return p1->snapshot() == p2->snapshot(); } - JSI_HOST_FUNCTION(copy) { - auto path = asPath(); - return makeJsiObject(runtime, - std::make_shared(getContext(), path)); + std::shared_ptr copy() { + return std::make_shared(getContext(), asPath()); } - JSI_HOST_FUNCTION(isInterpolatable) { - auto path2 = JsiSkPath::fromValue(runtime, arguments[0]); + bool isInterpolatable(std::shared_ptr path2) { auto p1 = asPath(); auto p2 = path2->snapshot(); return p1.isInterpolatable(p2); } - JSI_HOST_FUNCTION(interpolate) { - auto path2 = JsiSkPath::fromValue(runtime, arguments[0]); - auto weight = arguments[1].asNumber(); + std::variant> + interpolate(std::shared_ptr path2, double weight) { auto p1 = asPath(); auto p2 = path2->snapshot(); SkPath result; auto succeed = p1.interpolate(p2, weight, &result); if (!succeed) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(result))); + return std::make_shared(getContext(), std::move(result)); } - JSI_HOST_FUNCTION(toCmds) { + std::vector> toCmds() { auto path = asPath(); - std::vector cmdList; + std::vector> cmds; SkPoint pts[4]; SkPath::Iter iter(path, false); SkPath::Verb verb; @@ -632,141 +493,141 @@ class JsiSkPath while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { switch (verb) { case SkPath::kMove_Verb: { - auto cmd = jsi::Array(runtime, 3); - cmd.setValueAtIndex(runtime, 0, static_cast(MOVE)); - cmd.setValueAtIndex(runtime, 1, static_cast(pts[0].x())); - cmd.setValueAtIndex(runtime, 2, static_cast(pts[0].y())); - cmdList.push_back(std::move(cmd)); + cmds.push_back({static_cast(MOVE), + static_cast(pts[0].x()), + static_cast(pts[0].y())}); break; } case SkPath::kLine_Verb: { - auto cmd = jsi::Array(runtime, 3); - cmd.setValueAtIndex(runtime, 0, static_cast(LINE)); - cmd.setValueAtIndex(runtime, 1, static_cast(pts[1].x())); - cmd.setValueAtIndex(runtime, 2, static_cast(pts[1].y())); - cmdList.push_back(std::move(cmd)); + cmds.push_back({static_cast(LINE), + static_cast(pts[1].x()), + static_cast(pts[1].y())}); break; } case SkPath::kQuad_Verb: { - auto cmd = jsi::Array(runtime, 5); - cmd.setValueAtIndex(runtime, 0, static_cast(QUAD)); - cmd.setValueAtIndex(runtime, 1, static_cast(pts[1].x())); - cmd.setValueAtIndex(runtime, 2, static_cast(pts[1].y())); - cmd.setValueAtIndex(runtime, 3, static_cast(pts[2].x())); - cmd.setValueAtIndex(runtime, 4, static_cast(pts[2].y())); - cmdList.push_back(std::move(cmd)); + cmds.push_back( + {static_cast(QUAD), static_cast(pts[1].x()), + static_cast(pts[1].y()), static_cast(pts[2].x()), + static_cast(pts[2].y())}); break; } case SkPath::kConic_Verb: { - auto cmd = jsi::Array(runtime, 6); - cmd.setValueAtIndex(runtime, 0, static_cast(CONIC)); - cmd.setValueAtIndex(runtime, 1, static_cast(pts[1].x())); - cmd.setValueAtIndex(runtime, 2, static_cast(pts[1].y())); - cmd.setValueAtIndex(runtime, 3, static_cast(pts[2].x())); - cmd.setValueAtIndex(runtime, 4, static_cast(pts[2].y())); - cmd.setValueAtIndex(runtime, 5, - static_cast(iter.conicWeight())); - cmdList.push_back(std::move(cmd)); + cmds.push_back( + {static_cast(CONIC), static_cast(pts[1].x()), + static_cast(pts[1].y()), static_cast(pts[2].x()), + static_cast(pts[2].y()), + static_cast(iter.conicWeight())}); break; } case SkPath::kCubic_Verb: { - auto cmd = jsi::Array(runtime, 7); - cmd.setValueAtIndex(runtime, 0, static_cast(CUBIC)); - cmd.setValueAtIndex(runtime, 1, static_cast(pts[1].x())); - cmd.setValueAtIndex(runtime, 2, static_cast(pts[1].y())); - cmd.setValueAtIndex(runtime, 3, static_cast(pts[2].x())); - cmd.setValueAtIndex(runtime, 4, static_cast(pts[2].y())); - cmd.setValueAtIndex(runtime, 5, static_cast(pts[3].x())); - cmd.setValueAtIndex(runtime, 6, static_cast(pts[3].y())); - cmdList.push_back(std::move(cmd)); + cmds.push_back( + {static_cast(CUBIC), static_cast(pts[1].x()), + static_cast(pts[1].y()), static_cast(pts[2].x()), + static_cast(pts[2].y()), static_cast(pts[3].x()), + static_cast(pts[3].y())}); break; } case SkPath::kClose_Verb: { - auto cmd = jsi::Array(runtime, 1); - cmd.setValueAtIndex(runtime, 0, static_cast(CLOSE)); - cmdList.push_back(std::move(cmd)); + cmds.push_back({static_cast(CLOSE)}); break; } default: break; } } - - // Create the jsi::Array with the exact size - auto cmds = jsi::Array(runtime, cmdList.size()); - for (size_t i = 0; i < cmdList.size(); ++i) { - cmds.setValueAtIndex(runtime, i, cmdList[i]); - } - return cmds; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); // Mutable building methods - installHostMethod(runtime, prototype, "moveTo", &JsiSkPath::moveTo); - installHostMethod(runtime, prototype, "rMoveTo", &JsiSkPath::rMoveTo); - installHostMethod(runtime, prototype, "lineTo", &JsiSkPath::lineTo); - installHostMethod(runtime, prototype, "rLineTo", &JsiSkPath::rLineTo); - installHostMethod(runtime, prototype, "quadTo", &JsiSkPath::quadTo); - installHostMethod(runtime, prototype, "rQuadTo", &JsiSkPath::rQuadTo); - installHostMethod(runtime, prototype, "conicTo", &JsiSkPath::conicTo); - installHostMethod(runtime, prototype, "rConicTo", &JsiSkPath::rConicTo); - installHostMethod(runtime, prototype, "cubicTo", &JsiSkPath::cubicTo); - installHostMethod(runtime, prototype, "rCubicTo", &JsiSkPath::rCubicTo); - installHostMethod(runtime, prototype, "close", &JsiSkPath::close); - installHostMethod(runtime, prototype, "reset", &JsiSkPath::reset); - installHostMethod(runtime, prototype, "rewind", &JsiSkPath::rewind); - installHostMethod(runtime, prototype, "addPath", &JsiSkPath::addPath); - installHostMethod(runtime, prototype, "addArc", &JsiSkPath::addArc); - installHostMethod(runtime, prototype, "addOval", &JsiSkPath::addOval); - installHostMethod(runtime, prototype, "addRect", &JsiSkPath::addRect); - installHostMethod(runtime, prototype, "addRRect", &JsiSkPath::addRRect); - installHostMethod(runtime, prototype, "addCircle", &JsiSkPath::addCircle); - installHostMethod(runtime, prototype, "addPoly", &JsiSkPath::addPoly); - installHostMethod(runtime, prototype, "arcToOval", &JsiSkPath::arcToOval); - installHostMethod(runtime, prototype, "arcToRotated", - &JsiSkPath::arcToRotated); - installHostMethod(runtime, prototype, "rArcTo", &JsiSkPath::rArcTo); - installHostMethod(runtime, prototype, "arcToTangent", - &JsiSkPath::arcToTangent); - installHostMethod(runtime, prototype, "setFillType", - &JsiSkPath::setFillType); - installHostMethod(runtime, prototype, "setIsVolatile", - &JsiSkPath::setIsVolatile); + installChainableMethodWithRuntime(runtime, prototype, "moveTo", + &JsiSkPath::moveTo); + installChainableMethodWithRuntime(runtime, prototype, "rMoveTo", + &JsiSkPath::rMoveTo); + installChainableMethodWithRuntime(runtime, prototype, "lineTo", + &JsiSkPath::lineTo); + installChainableMethodWithRuntime(runtime, prototype, "rLineTo", + &JsiSkPath::rLineTo); + installChainableMethodWithRuntime(runtime, prototype, "quadTo", + &JsiSkPath::quadTo); + installChainableMethodWithRuntime(runtime, prototype, "rQuadTo", + &JsiSkPath::rQuadTo); + installChainableMethodWithRuntime(runtime, prototype, "conicTo", + &JsiSkPath::conicTo); + installChainableMethodWithRuntime(runtime, prototype, "rConicTo", + &JsiSkPath::rConicTo); + installChainableMethodWithRuntime(runtime, prototype, "cubicTo", + &JsiSkPath::cubicTo); + installChainableMethodWithRuntime(runtime, prototype, "rCubicTo", + &JsiSkPath::rCubicTo); + installChainableMethodWithRuntime(runtime, prototype, "close", + &JsiSkPath::close); + installChainableMethodWithRuntime(runtime, prototype, "reset", + &JsiSkPath::reset); + installChainableMethodWithRuntime(runtime, prototype, "rewind", + &JsiSkPath::rewind); + installChainableMethodWithRuntime(runtime, prototype, "addPath", + &JsiSkPath::addPath); + installChainableMethodWithRuntime(runtime, prototype, "addArc", + &JsiSkPath::addArc); + installChainableMethodWithRuntime(runtime, prototype, "addOval", + &JsiSkPath::addOval); + installChainableMethodWithRuntime(runtime, prototype, "addRect", + &JsiSkPath::addRect); + installChainableMethodWithRuntime(runtime, prototype, "addRRect", + &JsiSkPath::addRRect); + installChainableMethodWithRuntime(runtime, prototype, "addCircle", + &JsiSkPath::addCircle); + installChainableMethodWithRuntime(runtime, prototype, "addPoly", + &JsiSkPath::addPoly); + installChainableMethodWithRuntime(runtime, prototype, "arcToOval", + &JsiSkPath::arcToOval); + installChainableMethodWithRuntime(runtime, prototype, "arcToRotated", + &JsiSkPath::arcToRotated); + installChainableMethodWithRuntime(runtime, prototype, "rArcTo", + &JsiSkPath::rArcTo); + installChainableMethodWithRuntime(runtime, prototype, "arcToTangent", + &JsiSkPath::arcToTangent); + installChainableMethodWithRuntime(runtime, prototype, "setFillType", + &JsiSkPath::setFillType); + installChainableMethodWithRuntime(runtime, prototype, "setIsVolatile", + &JsiSkPath::setIsVolatile); // Mutable transform methods - installHostMethod(runtime, prototype, "transform", &JsiSkPath::transform); - installHostMethod(runtime, prototype, "offset", &JsiSkPath::offset); + installChainableMethodWithRuntime(runtime, prototype, "transform", + &JsiSkPath::transform); + installChainableMethodWithRuntime(runtime, prototype, "offset", + &JsiSkPath::offset); // Mutable path operations - installHostMethod(runtime, prototype, "simplify", &JsiSkPath::simplify); - installHostMethod(runtime, prototype, "op", &JsiSkPath::op); - installHostMethod(runtime, prototype, "makeAsWinding", - &JsiSkPath::makeAsWinding); - installHostMethod(runtime, prototype, "dash", &JsiSkPath::dash); + installChainableMethodWithRuntime(runtime, prototype, "simplify", + &JsiSkPath::simplify); + installChainableMethodWithRuntime(runtime, prototype, "op", + &JsiSkPath::op); + installChainableMethodWithRuntime(runtime, prototype, "makeAsWinding", + &JsiSkPath::makeAsWinding); + installChainableMethodWithRuntime(runtime, prototype, "dash", + &JsiSkPath::dash); installHostMethod(runtime, prototype, "stroke", &JsiSkPath::stroke); - installHostMethod(runtime, prototype, "trim", &JsiSkPath::trim); + installChainableMethodWithRuntime(runtime, prototype, "trim", + &JsiSkPath::trim); // Query methods - installHostMethod(runtime, prototype, "computeTightBounds", - &JsiSkPath::computeTightBounds); - installHostMethod(runtime, prototype, "getBounds", &JsiSkPath::getBounds); - installHostMethod(runtime, prototype, "contains", &JsiSkPath::contains); - installHostMethod(runtime, prototype, "getFillType", - &JsiSkPath::getFillType); - installHostMethod(runtime, prototype, "isVolatile", &JsiSkPath::isVolatile); - installHostMethod(runtime, prototype, "getPoint", &JsiSkPath::getPoint); - installHostMethod(runtime, prototype, "isEmpty", &JsiSkPath::isEmpty); - installHostMethod(runtime, prototype, "countPoints", - &JsiSkPath::countPoints); - installHostMethod(runtime, prototype, "getLastPt", &JsiSkPath::getLastPt); - installHostMethod(runtime, prototype, "toSVGString", - &JsiSkPath::toSVGString); - installHostMethod(runtime, prototype, "equals", &JsiSkPath::equals); - installHostMethod(runtime, prototype, "copy", &JsiSkPath::copy); - installHostMethod(runtime, prototype, "isInterpolatable", - &JsiSkPath::isInterpolatable); - installHostMethod(runtime, prototype, "interpolate", - &JsiSkPath::interpolate); - installHostMethod(runtime, prototype, "toCmds", &JsiSkPath::toCmds); + installMethod(runtime, prototype, "computeTightBounds", + &JsiSkPath::computeTightBounds); + installMethod(runtime, prototype, "getBounds", &JsiSkPath::getBounds); + installMethod(runtime, prototype, "contains", &JsiSkPath::contains); + installMethod(runtime, prototype, "getFillType", &JsiSkPath::getFillType); + installMethod(runtime, prototype, "isVolatile", &JsiSkPath::isVolatile); + installMethod(runtime, prototype, "getPoint", &JsiSkPath::getPoint); + installMethod(runtime, prototype, "isEmpty", &JsiSkPath::isEmpty); + installMethod(runtime, prototype, "countPoints", &JsiSkPath::countPoints); + installMethod(runtime, prototype, "getLastPt", &JsiSkPath::getLastPt); + installMethod(runtime, prototype, "toSVGString", &JsiSkPath::toSVGString); + installMethod(runtime, prototype, "equals", &JsiSkPath::equals); + installMethod(runtime, prototype, "copy", &JsiSkPath::copy); + installMethod(runtime, prototype, "isInterpolatable", + &JsiSkPath::isInterpolatable); + installMethod(runtime, prototype, "interpolate", &JsiSkPath::interpolate); + installMethod(runtime, prototype, "toCmds", &JsiSkPath::toCmds); } JsiSkPath(std::shared_ptr context, SkPathBuilder builder) @@ -810,6 +671,12 @@ class JsiSkPath return makeJsiObject(runtime, std::make_shared(context, std::move(path))); } + +private: + static SkPathDirection toDirection(const JsiOptional &isCCW) { + return isCCW.has_value() && *isCCW ? SkPathDirection::kCCW + : SkPathDirection::kCW; + } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkPathBuilder.h b/packages/skia/cpp/api/JsiSkPathBuilder.h index 2999501005..c7565e0ebe 100644 --- a/packages/skia/cpp/api/JsiSkPathBuilder.h +++ b/packages/skia/cpp/api/JsiSkPathBuilder.h @@ -6,6 +6,7 @@ #include +#include "JsiSkConverters.h" #include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" #include "JsiSkPath.h" @@ -33,377 +34,234 @@ class JsiSkPathBuilder static constexpr const char *CLASS_NAME = "PathBuilder"; // Movement methods - JSI_HOST_FUNCTION(moveTo) { - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - getObject()->moveTo(x, y); - return thisValue.getObject(runtime); - } + void moveTo(double x, double y) { getObject()->moveTo(x, y); } - JSI_HOST_FUNCTION(rMoveTo) { - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - getObject()->rMoveTo({x, y}); - return thisValue.getObject(runtime); + void rMoveTo(double x, double y) { + getObject()->rMoveTo({static_cast(x), static_cast(y)}); } - JSI_HOST_FUNCTION(lineTo) { - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - getObject()->lineTo(x, y); - return thisValue.getObject(runtime); - } + void lineTo(double x, double y) { getObject()->lineTo(x, y); } - JSI_HOST_FUNCTION(rLineTo) { - SkScalar x = arguments[0].asNumber(); - SkScalar y = arguments[1].asNumber(); - getObject()->rLineTo(x, y); - return thisValue.getObject(runtime); - } + void rLineTo(double x, double y) { getObject()->rLineTo(x, y); } // Curve methods - JSI_HOST_FUNCTION(quadTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); + void quadTo(double x1, double y1, double x2, double y2) { getObject()->quadTo(x1, y1, x2, y2); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rQuadTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); + void rQuadTo(double x1, double y1, double x2, double y2) { getObject()->rQuadTo(x1, y1, x2, y2); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(conicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto w = arguments[4].asNumber(); + void conicTo(double x1, double y1, double x2, double y2, double w) { getObject()->conicTo(x1, y1, x2, y2, w); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rConicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto w = arguments[4].asNumber(); + void rConicTo(double x1, double y1, double x2, double y2, double w) { getObject()->rConicTo(x1, y1, x2, y2, w); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(cubicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto x3 = arguments[4].asNumber(); - auto y3 = arguments[5].asNumber(); + void cubicTo(double x1, double y1, double x2, double y2, double x3, + double y3) { getObject()->cubicTo(x1, y1, x2, y2, x3, y3); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rCubicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto x3 = arguments[4].asNumber(); - auto y3 = arguments[5].asNumber(); + void rCubicTo(double x1, double y1, double x2, double y2, double x3, + double y3) { getObject()->rCubicTo(x1, y1, x2, y2, x3, y3); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(close) { - getObject()->close(); - return thisValue.getObject(runtime); - } + void close() { getObject()->close(); } // Arc methods - JSI_HOST_FUNCTION(arcToOval) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto start = arguments[1].asNumber(); - auto sweep = arguments[2].asNumber(); - auto forceMoveTo = arguments[3].getBool(); + void arcToOval(std::shared_ptr rect, double start, double sweep, + bool forceMoveTo) { getObject()->arcTo(*rect, start, sweep, forceMoveTo); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(arcToRotated) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - auto xAxisRotate = arguments[2].asNumber(); - auto useSmallArc = arguments[3].getBool(); + void arcToRotated(double rx, double ry, double xAxisRotate, bool useSmallArc, + bool isCCW, double x, double y) { auto arcSize = useSmallArc ? SkPathBuilder::ArcSize::kSmall_ArcSize : SkPathBuilder::ArcSize::kLarge_ArcSize; - auto sweep = - arguments[4].getBool() ? SkPathDirection::kCCW : SkPathDirection::kCW; - auto x = arguments[5].asNumber(); - auto y = arguments[6].asNumber(); + auto sweep = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; getObject()->arcTo(SkPoint::Make(rx, ry), xAxisRotate, arcSize, sweep, SkPoint::Make(x, y)); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(rArcTo) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - auto xAxisRotate = arguments[2].asNumber(); - auto useSmallArc = arguments[3].getBool(); + void rArcTo(double rx, double ry, double xAxisRotate, bool useSmallArc, + bool isCCW, double dx, double dy) { auto arcSize = useSmallArc ? SkPathBuilder::ArcSize::kSmall_ArcSize : SkPathBuilder::ArcSize::kLarge_ArcSize; - auto sweep = - arguments[4].getBool() ? SkPathDirection::kCCW : SkPathDirection::kCW; - auto dx = arguments[5].asNumber(); - auto dy = arguments[6].asNumber(); + auto sweep = isCCW ? SkPathDirection::kCCW : SkPathDirection::kCW; SkPoint r(rx, ry); SkVector d(dx, dy); getObject()->rArcTo(r, xAxisRotate, arcSize, sweep, d); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(arcToTangent) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto r = arguments[4].asNumber(); + void arcToTangent(double x1, double y1, double x2, double y2, double r) { getObject()->arcTo(SkPoint::Make(x1, y1), SkPoint::Make(x2, y2), r); - return thisValue.getObject(runtime); } // Shape methods - JSI_HOST_FUNCTION(addRect) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } - getObject()->addRect(*rect, direction); - return thisValue.getObject(runtime); + void addRect(std::shared_ptr rect, JsiOptional isCCW) { + getObject()->addRect(*rect, toDirection(isCCW)); } - JSI_HOST_FUNCTION(addOval) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } - unsigned startIndex = count < 3 ? 0 : arguments[2].asNumber(); - getObject()->addOval(*rect, direction, startIndex); - return thisValue.getObject(runtime); + void addOval(std::shared_ptr rect, JsiOptional isCCW, + JsiOptional startIndex) { + getObject()->addOval(*rect, toDirection(isCCW), + startIndex.has_value() + ? static_cast(*startIndex) + : 0); } - JSI_HOST_FUNCTION(addArc) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto start = arguments[1].asNumber(); - auto sweep = arguments[2].asNumber(); + void addArc(std::shared_ptr rect, double start, double sweep) { getObject()->addArc(*rect, start, sweep); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addRRect) { - auto rrect = JsiSkRRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } - getObject()->addRRect(*rrect, direction); - return thisValue.getObject(runtime); + void addRRect(std::shared_ptr rrect, JsiOptional isCCW) { + getObject()->addRRect(*rrect, toDirection(isCCW)); } - JSI_HOST_FUNCTION(addCircle) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - auto r = arguments[2].asNumber(); - auto direction = SkPathDirection::kCW; - if (count >= 4 && arguments[3].getBool()) { - direction = SkPathDirection::kCCW; - } - getObject()->addCircle(x, y, r, direction); - return thisValue.getObject(runtime); + void addCircle(double x, double y, double r, JsiOptional isCCW) { + getObject()->addCircle(x, y, r, toDirection(isCCW)); } - JSI_HOST_FUNCTION(addPoly) { - std::vector points; - auto jsiPoints = arguments[0].asObject(runtime).asArray(runtime); - auto close = arguments[1].getBool(); - auto pointsSize = jsiPoints.size(runtime); - points.reserve(pointsSize); - for (int i = 0; i < pointsSize; i++) { - std::shared_ptr point = JsiSkPoint::fromValue( - runtime, jsiPoints.getValueAtIndex(runtime, i).asObject(runtime)); - points.push_back(*point.get()); - } + void addPoly(std::vector points, bool close) { getObject()->addPolygon(SkSpan(points.data(), points.size()), close); - return thisValue.getObject(runtime); } - JSI_HOST_FUNCTION(addPath) { - auto src = JsiSkPath::fromValue(runtime, arguments[0]); + void addPath(std::shared_ptr src, + JsiOptional> matrix, + JsiOptional extend) { auto srcPath = src->snapshot(); - auto matrix = - count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull() - ? JsiSkMatrix::fromValue(runtime, arguments[1]) - : nullptr; - auto mode = count > 2 && arguments[2].isBool() && arguments[2].getBool() - ? SkPath::kExtend_AddPathMode - : SkPath::kAppend_AddPathMode; - if (matrix == nullptr) { - getObject()->addPath(srcPath, mode); + auto mode = extend.has_value() && *extend ? SkPath::kExtend_AddPathMode + : SkPath::kAppend_AddPathMode; + if (matrix.has_value()) { + getObject()->addPath(srcPath, **matrix, mode); } else { - getObject()->addPath(srcPath, *matrix, mode); + getObject()->addPath(srcPath, mode); } - return thisValue.getObject(runtime); } // Configuration methods - JSI_HOST_FUNCTION(setFillType) { - auto ft = (SkPathFillType)arguments[0].asNumber(); - getObject()->setFillType(ft); - return thisValue.getObject(runtime); + void setFillType(double ft) { + getObject()->setFillType(static_cast(ft)); } - JSI_HOST_FUNCTION(setIsVolatile) { - auto v = arguments[0].getBool(); - getObject()->setIsVolatile(v); - return thisValue.getObject(runtime); - } + void setIsVolatile(bool v) { getObject()->setIsVolatile(v); } - JSI_HOST_FUNCTION(reset) { - getObject()->reset(); - return thisValue.getObject(runtime); - } + void reset() { getObject()->reset(); } - JSI_HOST_FUNCTION(offset) { - SkScalar dx = arguments[0].asNumber(); - SkScalar dy = arguments[1].asNumber(); - getObject()->offset(dx, dy); - return thisValue.getObject(runtime); - } + void offset(double dx, double dy) { getObject()->offset(dx, dy); } - JSI_HOST_FUNCTION(transform) { - auto m3 = *JsiSkMatrix::fromValue(runtime, arguments[0]); + void transform(std::shared_ptr m3) { // Create a path from current state, transform, then rebuild - auto path = getObject()->snapshot().makeTransform(m3); + auto path = getObject()->snapshot().makeTransform(*m3); *getObject() = SkPathBuilder(path); - return thisValue.getObject(runtime); } // Query methods - JSI_HOST_FUNCTION(computeBounds) { + std::shared_ptr computeBounds() { auto path = getObject()->snapshot(); - auto result = path.getBounds(); - return makeJsiObject(runtime, - std::make_shared(getContext(), result)); + return std::make_shared(getContext(), path.getBounds()); } - JSI_HOST_FUNCTION(isEmpty) { - return jsi::Value(getObject()->snapshot().isEmpty()); - } + bool isEmpty() { return getObject()->snapshot().isEmpty(); } - JSI_HOST_FUNCTION(getLastPt) { - SkPoint last; + SkPoint getLastPt() { + SkPoint last = SkPoint::Make(0, 0); getObject()->snapshot().getLastPt(&last); - auto point = jsi::Object(runtime); - point.setProperty(runtime, "x", static_cast(last.fX)); - point.setProperty(runtime, "y", static_cast(last.fY)); - return point; + return last; } - JSI_HOST_FUNCTION(countPoints) { - auto points = getObject()->snapshot().countPoints(); - return jsi::Value(points); - } + int countPoints() { return getObject()->snapshot().countPoints(); } // Build methods - JSI_HOST_FUNCTION(build) { + std::shared_ptr build() { // snapshot() returns a copy without resetting the builder auto path = getObject()->snapshot(); - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(path))); + return std::make_shared(getContext(), std::move(path)); } - JSI_HOST_FUNCTION(detach) { + std::shared_ptr detach() { // detach() returns the path and resets the builder auto path = getObject()->detach(); - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(path))); + return std::make_shared(getContext(), std::move(path)); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); // Movement - installHostMethod(runtime, prototype, "moveTo", &JsiSkPathBuilder::moveTo); - installHostMethod(runtime, prototype, "rMoveTo", - &JsiSkPathBuilder::rMoveTo); - installHostMethod(runtime, prototype, "lineTo", &JsiSkPathBuilder::lineTo); - installHostMethod(runtime, prototype, "rLineTo", - &JsiSkPathBuilder::rLineTo); + installChainableMethod(runtime, prototype, "moveTo", + &JsiSkPathBuilder::moveTo); + installChainableMethod(runtime, prototype, "rMoveTo", + &JsiSkPathBuilder::rMoveTo); + installChainableMethod(runtime, prototype, "lineTo", + &JsiSkPathBuilder::lineTo); + installChainableMethod(runtime, prototype, "rLineTo", + &JsiSkPathBuilder::rLineTo); // Curves - installHostMethod(runtime, prototype, "quadTo", &JsiSkPathBuilder::quadTo); - installHostMethod(runtime, prototype, "rQuadTo", - &JsiSkPathBuilder::rQuadTo); - installHostMethod(runtime, prototype, "conicTo", - &JsiSkPathBuilder::conicTo); - installHostMethod(runtime, prototype, "rConicTo", - &JsiSkPathBuilder::rConicTo); - installHostMethod(runtime, prototype, "cubicTo", - &JsiSkPathBuilder::cubicTo); - installHostMethod(runtime, prototype, "rCubicTo", - &JsiSkPathBuilder::rCubicTo); - installHostMethod(runtime, prototype, "close", &JsiSkPathBuilder::close); + installChainableMethod(runtime, prototype, "quadTo", + &JsiSkPathBuilder::quadTo); + installChainableMethod(runtime, prototype, "rQuadTo", + &JsiSkPathBuilder::rQuadTo); + installChainableMethod(runtime, prototype, "conicTo", + &JsiSkPathBuilder::conicTo); + installChainableMethod(runtime, prototype, "rConicTo", + &JsiSkPathBuilder::rConicTo); + installChainableMethod(runtime, prototype, "cubicTo", + &JsiSkPathBuilder::cubicTo); + installChainableMethod(runtime, prototype, "rCubicTo", + &JsiSkPathBuilder::rCubicTo); + installChainableMethod(runtime, prototype, "close", + &JsiSkPathBuilder::close); // Arcs - installHostMethod(runtime, prototype, "arcToOval", - &JsiSkPathBuilder::arcToOval); - installHostMethod(runtime, prototype, "arcToRotated", - &JsiSkPathBuilder::arcToRotated); - installHostMethod(runtime, prototype, "rArcTo", &JsiSkPathBuilder::rArcTo); - installHostMethod(runtime, prototype, "arcToTangent", - &JsiSkPathBuilder::arcToTangent); + installChainableMethod(runtime, prototype, "arcToOval", + &JsiSkPathBuilder::arcToOval); + installChainableMethod(runtime, prototype, "arcToRotated", + &JsiSkPathBuilder::arcToRotated); + installChainableMethod(runtime, prototype, "rArcTo", + &JsiSkPathBuilder::rArcTo); + installChainableMethod(runtime, prototype, "arcToTangent", + &JsiSkPathBuilder::arcToTangent); // Shapes - installHostMethod(runtime, prototype, "addRect", - &JsiSkPathBuilder::addRect); - installHostMethod(runtime, prototype, "addOval", - &JsiSkPathBuilder::addOval); - installHostMethod(runtime, prototype, "addArc", &JsiSkPathBuilder::addArc); - installHostMethod(runtime, prototype, "addRRect", - &JsiSkPathBuilder::addRRect); - installHostMethod(runtime, prototype, "addCircle", - &JsiSkPathBuilder::addCircle); - installHostMethod(runtime, prototype, "addPoly", - &JsiSkPathBuilder::addPoly); - installHostMethod(runtime, prototype, "addPath", - &JsiSkPathBuilder::addPath); + installChainableMethod(runtime, prototype, "addRect", + &JsiSkPathBuilder::addRect); + installChainableMethod(runtime, prototype, "addOval", + &JsiSkPathBuilder::addOval); + installChainableMethod(runtime, prototype, "addArc", + &JsiSkPathBuilder::addArc); + installChainableMethod(runtime, prototype, "addRRect", + &JsiSkPathBuilder::addRRect); + installChainableMethod(runtime, prototype, "addCircle", + &JsiSkPathBuilder::addCircle); + installChainableMethod(runtime, prototype, "addPoly", + &JsiSkPathBuilder::addPoly); + installChainableMethod(runtime, prototype, "addPath", + &JsiSkPathBuilder::addPath); // Config - installHostMethod(runtime, prototype, "setFillType", - &JsiSkPathBuilder::setFillType); - installHostMethod(runtime, prototype, "setIsVolatile", - &JsiSkPathBuilder::setIsVolatile); - installHostMethod(runtime, prototype, "reset", &JsiSkPathBuilder::reset); - installHostMethod(runtime, prototype, "offset", &JsiSkPathBuilder::offset); - installHostMethod(runtime, prototype, "transform", - &JsiSkPathBuilder::transform); + installChainableMethod(runtime, prototype, "setFillType", + &JsiSkPathBuilder::setFillType); + installChainableMethod(runtime, prototype, "setIsVolatile", + &JsiSkPathBuilder::setIsVolatile); + installChainableMethod(runtime, prototype, "reset", + &JsiSkPathBuilder::reset); + installChainableMethod(runtime, prototype, "offset", + &JsiSkPathBuilder::offset); + installChainableMethod(runtime, prototype, "transform", + &JsiSkPathBuilder::transform); // Query - installHostMethod(runtime, prototype, "computeBounds", - &JsiSkPathBuilder::computeBounds); - installHostMethod(runtime, prototype, "isEmpty", - &JsiSkPathBuilder::isEmpty); - installHostMethod(runtime, prototype, "getLastPt", - &JsiSkPathBuilder::getLastPt); - installHostMethod(runtime, prototype, "countPoints", - &JsiSkPathBuilder::countPoints); + installMethod(runtime, prototype, "computeBounds", + &JsiSkPathBuilder::computeBounds); + installMethod(runtime, prototype, "isEmpty", &JsiSkPathBuilder::isEmpty); + installMethod(runtime, prototype, "getLastPt", + &JsiSkPathBuilder::getLastPt); + installMethod(runtime, prototype, "countPoints", + &JsiSkPathBuilder::countPoints); // Build - installHostMethod(runtime, prototype, "build", &JsiSkPathBuilder::build); - installHostMethod(runtime, prototype, "detach", &JsiSkPathBuilder::detach); + installMethod(runtime, prototype, "build", &JsiSkPathBuilder::build); + installMethod(runtime, prototype, "detach", &JsiSkPathBuilder::detach); } JsiSkPathBuilder(std::shared_ptr context, @@ -426,6 +284,12 @@ class JsiSkPathBuilder return makeJsiObject(runtime, std::make_shared(context, builder)); } + +private: + static SkPathDirection toDirection(const JsiOptional &isCCW) { + return isCCW.has_value() && *isCCW ? SkPathDirection::kCCW + : SkPathDirection::kCW; + } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkPathBuilderFactory.h b/packages/skia/cpp/api/JsiSkPathBuilderFactory.h index acb21b4ec5..2fef2d585f 100644 --- a/packages/skia/cpp/api/JsiSkPathBuilderFactory.h +++ b/packages/skia/cpp/api/JsiSkPathBuilderFactory.h @@ -5,7 +5,9 @@ #include +#include "JsiSkConverters.h" #include "JsiSkNativeObjects.h" +#include "JsiSkPath.h" #include "JsiSkPathBuilder.h" #pragma clang diagnostic push @@ -25,24 +27,22 @@ class JsiSkPathBuilderFactory public: static constexpr const char *CLASS_NAME = "PathBuilderFactory"; - JSI_HOST_FUNCTION(Make) { - return makeJsiObject(runtime, std::make_shared( - getContext(), SkPathBuilder())); + std::shared_ptr Make() { + return std::make_shared(getContext(), SkPathBuilder()); } - JSI_HOST_FUNCTION(MakeFromPath) { - auto path = JsiSkPath::fromValue(runtime, arguments[0]); - return makeJsiObject(runtime, std::make_shared( - getContext(), SkPathBuilder(*path))); + std::shared_ptr + MakeFromPath(std::shared_ptr path) { + return std::make_shared(getContext(), + SkPathBuilder(*path)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "Make", - &JsiSkPathBuilderFactory::Make); - installHostMethod(runtime, prototype, "MakeFromPath", - &JsiSkPathBuilderFactory::MakeFromPath); + installMethod(runtime, prototype, "Make", &JsiSkPathBuilderFactory::Make); + installMethod(runtime, prototype, "MakeFromPath", + &JsiSkPathBuilderFactory::MakeFromPath); } explicit JsiSkPathBuilderFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkPathEffectFactory.h b/packages/skia/cpp/api/JsiSkPathEffectFactory.h index 4ffa4d598d..3286eae5c2 100644 --- a/packages/skia/cpp/api/JsiSkPathEffectFactory.h +++ b/packages/skia/cpp/api/JsiSkPathEffectFactory.h @@ -1,12 +1,17 @@ #pragma once #include +#include #include +#include #include #include +#include "JsiSkConverters.h" +#include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" +#include "JsiSkPath.h" #include "JsiSkPathEffect.h" #pragma clang diagnostic push @@ -30,104 +35,79 @@ class JsiSkPathEffectFactory public: static constexpr const char *CLASS_NAME = "PathEffectFactory"; - JSI_HOST_FUNCTION(MakeCorner) { - int radius = arguments[0].asNumber(); - auto pathEffect = std::make_shared( - getContext(), SkCornerPathEffect::Make(radius)); - return makeJsiObject(runtime, std::move(pathEffect)); + std::shared_ptr MakeCorner(int radius) { + return std::make_shared(getContext(), + SkCornerPathEffect::Make(radius)); } - JSI_HOST_FUNCTION(MakeDash) { - auto jsiIntervals = arguments[0].asObject(runtime).asArray(runtime); - auto size = static_cast(jsiIntervals.size(runtime)); - std::vector intervals; - intervals.reserve(size); - for (int i = 0; i < size; i++) { - SkScalar interval = jsiIntervals.getValueAtIndex(runtime, i).asNumber(); - intervals.push_back(interval); - } - int phase = - count >= 2 && !arguments[1].isUndefined() && !arguments[1].isNull() - ? arguments[1].asNumber() - : 0; + std::shared_ptr + MakeDash(std::vector intervals, JsiOptional phaseValue) { + int phase = phaseValue.has_value() ? *phaseValue : 0; auto i = SkSpan(intervals.data(), intervals.size()); - auto pathEffect = std::make_shared( - getContext(), SkDashPathEffect::Make(i, phase)); - return makeJsiObject(runtime, std::move(pathEffect)); + return std::make_shared(getContext(), + SkDashPathEffect::Make(i, phase)); } - JSI_HOST_FUNCTION(MakeDiscrete) { - int segLength = arguments[0].asNumber(); - int dec = arguments[1].asNumber(); - int seedAssist = arguments[2].asNumber(); - auto pathEffect = std::make_shared( + std::shared_ptr MakeDiscrete(int segLength, int dec, + int seedAssist) { + return std::make_shared( getContext(), SkDiscretePathEffect::Make(segLength, dec, seedAssist)); - return makeJsiObject(runtime, std::move(pathEffect)); } - JSI_HOST_FUNCTION(MakeCompose) { - auto outer = JsiSkPathEffect::fromValue(runtime, arguments[0]); - auto inner = JsiSkPathEffect::fromValue(runtime, arguments[1]); - auto pathEffect = std::make_shared( + std::shared_ptr MakeCompose(sk_sp outer, + sk_sp inner) { + return std::make_shared( getContext(), SkPathEffect::MakeCompose(std::move(outer), std::move(inner))); - return makeJsiObject(runtime, std::move(pathEffect)); } - JSI_HOST_FUNCTION(MakeSum) { - auto outer = JsiSkPathEffect::fromValue(runtime, arguments[0]); - auto inner = JsiSkPathEffect::fromValue(runtime, arguments[1]); - auto pathEffect = std::make_shared( + std::shared_ptr MakeSum(sk_sp outer, + sk_sp inner) { + return std::make_shared( getContext(), SkPathEffect::MakeSum(std::move(outer), std::move(inner))); - return makeJsiObject(runtime, std::move(pathEffect)); } - JSI_HOST_FUNCTION(MakePath1D) { - auto path = JsiSkPath::fromValue(runtime, arguments[0]); - auto advance = arguments[1].asNumber(); - auto phase = arguments[2].asNumber(); - auto style = - static_cast(arguments[3].asNumber()); - auto pathEffect = std::make_shared( + std::shared_ptr + MakePath1D(std::shared_ptr path, double advance, double phase, + double style) { + return std::make_shared( getContext(), - SkPath1DPathEffect::Make(path->snapshot(), advance, phase, style)); - return makeJsiObject(runtime, std::move(pathEffect)); + SkPath1DPathEffect::Make( + path->snapshot(), advance, phase, + static_cast(style))); } - JSI_HOST_FUNCTION(MakePath2D) { - auto matrix = JsiSkMatrix::fromValue(runtime, arguments[0]); - auto path = JsiSkPath::fromValue(runtime, arguments[1]); - auto pathEffect = std::make_shared( + std::shared_ptr + MakePath2D(std::shared_ptr matrix, + std::shared_ptr path) { + return std::make_shared( getContext(), SkPath2DPathEffect::Make(*matrix, path->snapshot())); - return makeJsiObject(runtime, std::move(pathEffect)); } - JSI_HOST_FUNCTION(MakeLine2D) { - auto width = arguments[0].asNumber(); - auto matrix = JsiSkMatrix::fromValue(runtime, arguments[1]); - auto pathEffect = std::make_shared( + std::shared_ptr + MakeLine2D(double width, std::shared_ptr matrix) { + return std::make_shared( getContext(), SkLine2DPathEffect::Make(width, *matrix)); - return makeJsiObject(runtime, std::move(pathEffect)); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeCorner", - &JsiSkPathEffectFactory::MakeCorner); - installHostMethod(runtime, prototype, "MakeDash", - &JsiSkPathEffectFactory::MakeDash); - installHostMethod(runtime, prototype, "MakeDiscrete", - &JsiSkPathEffectFactory::MakeDiscrete); - installHostMethod(runtime, prototype, "MakeCompose", - &JsiSkPathEffectFactory::MakeCompose); - installHostMethod(runtime, prototype, "MakeSum", - &JsiSkPathEffectFactory::MakeSum); - installHostMethod(runtime, prototype, "MakeLine2D", - &JsiSkPathEffectFactory::MakeLine2D); - installHostMethod(runtime, prototype, "MakePath1D", - &JsiSkPathEffectFactory::MakePath1D); - installHostMethod(runtime, prototype, "MakePath2D", - &JsiSkPathEffectFactory::MakePath2D); + installMethod(runtime, prototype, "MakeCorner", + &JsiSkPathEffectFactory::MakeCorner); + installMethod(runtime, prototype, "MakeDash", + &JsiSkPathEffectFactory::MakeDash); + installMethod(runtime, prototype, "MakeDiscrete", + &JsiSkPathEffectFactory::MakeDiscrete); + installMethod(runtime, prototype, "MakeCompose", + &JsiSkPathEffectFactory::MakeCompose); + installMethod(runtime, prototype, "MakeSum", + &JsiSkPathEffectFactory::MakeSum); + installMethod(runtime, prototype, "MakeLine2D", + &JsiSkPathEffectFactory::MakeLine2D); + installMethod(runtime, prototype, "MakePath1D", + &JsiSkPathEffectFactory::MakePath1D); + installMethod(runtime, prototype, "MakePath2D", + &JsiSkPathEffectFactory::MakePath2D); } size_t getMemoryPressure() override { return 1024; } diff --git a/packages/skia/cpp/api/JsiSkPathFactory.h b/packages/skia/cpp/api/JsiSkPathFactory.h index 519caae739..fbc3811c8e 100644 --- a/packages/skia/cpp/api/JsiSkPathFactory.h +++ b/packages/skia/cpp/api/JsiSkPathFactory.h @@ -2,13 +2,18 @@ #include #include +#include #include +#include #include #include +#include "JsiSkConverters.h" +#include "JsiSkFont.h" #include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" +#include "JsiSkPath.h" #include "JsiSkPathEffect.h" #include "JsiSkPoint.h" #include "JsiSkRRect.h" @@ -42,107 +47,83 @@ class JsiSkPathFactory : public JsiSkNativeObject { static const int CUBIC = 4; static const int CLOSE = 5; + using NullablePath = std::variant>; + public: static constexpr const char *CLASS_NAME = "PathFactory"; - JSI_HOST_FUNCTION(Make) { - return makeJsiObject(runtime, - std::make_shared(getContext(), SkPath())); + std::shared_ptr Make() { + return std::make_shared(getContext(), SkPath()); } - JSI_HOST_FUNCTION(MakeFromSVGString) { - auto svgString = arguments[0].asString(runtime).utf8(runtime); + std::shared_ptr MakeFromSVGString(std::string svgString) { auto result = SkParsePath::FromSVGString(svgString.c_str()); if (!result.has_value()) { - throw jsi::JSError(runtime, "Could not parse Svg path"); - return jsi::Value(nullptr); + throw std::runtime_error("Could not parse Svg path"); } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(result.value()))); + return std::make_shared(getContext(), + std::move(result.value())); } - JSI_HOST_FUNCTION(MakeFromOp) { - auto one = JsiSkPath::fromValue(runtime, arguments[0])->snapshot(); - auto two = JsiSkPath::fromValue(runtime, arguments[1])->snapshot(); - SkPathOp op = (SkPathOp)arguments[2].asNumber(); - auto result = Op(one, two, op); + NullablePath MakeFromOp(std::shared_ptr pathOne, + std::shared_ptr pathTwo, double op) { + auto one = pathOne->snapshot(); + auto two = pathTwo->snapshot(); + auto result = Op(one, two, static_cast(op)); if (!result.has_value()) { - return jsi::Value(nullptr); + return nullptr; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(result.value()))); + return std::make_shared(getContext(), + std::move(result.value())); } - JSI_HOST_FUNCTION(MakeFromCmds) { + NullablePath MakeFromCmds(std::vector> cmds) { SkPathBuilder builder; - auto cmds = arguments[0].asObject(runtime).asArray(runtime); - auto cmdCount = cmds.size(runtime); - for (int i = 0; i < cmdCount; i++) { - auto cmd = - cmds.getValueAtIndex(runtime, i).asObject(runtime).asArray(runtime); - if (cmd.size(runtime) < 1) { + for (const auto &cmd : cmds) { + if (cmd.size() < 1) { RNSkLogger::logToConsole("Invalid command found (got an empty array)"); - return jsi::Value::null(); + return nullptr; } - auto verb = static_cast(cmd.getValueAtIndex(runtime, 0).asNumber()); + auto verb = static_cast(cmd[0]); switch (verb) { case MOVE: { - if (cmd.size(runtime) < 3) { + if (cmd.size() < 3) { RNSkLogger::logToConsole("Invalid move command found"); - return jsi::Value::null(); + return nullptr; } - auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); - builder.moveTo(x, y); + builder.moveTo(cmd[1], cmd[2]); break; } case LINE: { - if (cmd.size(runtime) < 3) { + if (cmd.size() < 3) { RNSkLogger::logToConsole("Invalid line command found"); - return jsi::Value::null(); + return nullptr; } - auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); - builder.lineTo(x, y); + builder.lineTo(cmd[1], cmd[2]); break; } case QUAD: { - if (cmd.size(runtime) < 5) { + if (cmd.size() < 5) { RNSkLogger::logToConsole("Invalid line command found"); - return jsi::Value::null(); + return nullptr; } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - builder.quadTo(x1, y1, x2, y2); + builder.quadTo(cmd[1], cmd[2], cmd[3], cmd[4]); break; } case CONIC: { - if (cmd.size(runtime) < 6) { + if (cmd.size() < 6) { RNSkLogger::logToConsole("Invalid line command found"); - return jsi::Value::null(); + return nullptr; } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - auto w = cmd.getValueAtIndex(runtime, 5).asNumber(); - builder.conicTo(x1, y1, x2, y2, w); + builder.conicTo(cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]); break; } case CUBIC: { - if (cmd.size(runtime) < 7) { + if (cmd.size() < 7) { RNSkLogger::logToConsole("Invalid line command found"); - return jsi::Value::null(); + return nullptr; } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - auto x3 = cmd.getValueAtIndex(runtime, 5).asNumber(); - auto y3 = cmd.getValueAtIndex(runtime, 6).asNumber(); - builder.cubicTo(x1, y1, x2, y2, x3, y3); + builder.cubicTo(cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]); break; } case CLOSE: { @@ -151,102 +132,68 @@ class JsiSkPathFactory : public JsiSkNativeObject { } default: { RNSkLogger::logToConsole("Found an unknown command"); - return jsi::Value::null(); + return nullptr; } } } - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(MakeFromText) { - auto text = arguments[0].asString(runtime).utf8(runtime); - auto x = arguments[1].asNumber(); - auto y = arguments[2].asNumber(); - auto font = JsiSkFont::fromValue(runtime, arguments[3]); + std::shared_ptr MakeFromText(std::string text, double x, double y, + std::shared_ptr font) { SkPath path; SkTextUtils::GetPath(text.c_str(), strlen(text.c_str()), SkTextEncoding::kUTF8, x, y, *font, &path); - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(path))); + return std::make_shared(getContext(), std::move(path)); } // Static shape factories - JSI_HOST_FUNCTION(Rect) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } + std::shared_ptr Rect(SkRect rect, JsiOptional isCCW) { SkPathBuilder builder; - builder.addRect(*rect, direction); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + builder.addRect(rect, toDirection(isCCW)); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(Oval) { - auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } - unsigned startIndex = count < 3 ? 0 : arguments[2].asNumber(); + std::shared_ptr Oval(SkRect rect, JsiOptional isCCW, + JsiOptional startIndex) { SkPathBuilder builder; - builder.addOval(*rect, direction, startIndex); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + builder.addOval(rect, toDirection(isCCW), + startIndex.has_value() + ? static_cast(*startIndex) + : 0); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(Circle) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - auto r = arguments[2].asNumber(); + std::shared_ptr Circle(double x, double y, double r) { SkPathBuilder builder; builder.addCircle(x, y, r); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(RRect) { - auto rrect = JsiSkRRect::fromValue(runtime, arguments[0]); - auto direction = SkPathDirection::kCW; - if (count >= 2 && arguments[1].getBool()) { - direction = SkPathDirection::kCCW; - } + std::shared_ptr RRect(std::shared_ptr rrect, + JsiOptional isCCW) { SkPathBuilder builder; - builder.addRRect(*rrect, direction); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + builder.addRRect(*rrect, toDirection(isCCW)); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(Line) { - auto p1 = JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)); - auto p2 = JsiSkPoint::fromValue(runtime, arguments[1].asObject(runtime)); + std::shared_ptr Line(SkPoint p1, SkPoint p2) { SkPathBuilder builder; - builder.moveTo(*p1); - builder.lineTo(*p2); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + builder.moveTo(p1); + builder.lineTo(p2); + return std::make_shared(getContext(), builder.snapshot()); } - JSI_HOST_FUNCTION(Polygon) { - std::vector points; - auto jsiPoints = arguments[0].asObject(runtime).asArray(runtime); - auto close = arguments[1].getBool(); - auto pointsSize = jsiPoints.size(runtime); - points.reserve(pointsSize); - for (int i = 0; i < pointsSize; i++) { - std::shared_ptr point = JsiSkPoint::fromValue( - runtime, jsiPoints.getValueAtIndex(runtime, i).asObject(runtime)); - points.push_back(*point.get()); - } + std::shared_ptr Polygon(std::vector points, bool close) { SkPathBuilder builder; builder.addPolygon(SkSpan(points), close); - return makeJsiObject( - runtime, std::make_shared(getContext(), builder.snapshot())); + return std::make_shared(getContext(), builder.snapshot()); } // Static path operations + + // Stays raw: the options object is read leniently property by property + // (unknown properties and non-numeric values are ignored). JSI_HOST_FUNCTION(Stroke) { auto srcPath = JsiSkPath::fromValue(runtime, arguments[0]); SkPath path = srcPath->snapshot(); @@ -303,128 +250,115 @@ class JsiSkPathFactory : public JsiSkNativeObject { return jsi::Value::null(); } - JSI_HOST_FUNCTION(Trim) { - auto srcPath = JsiSkPath::fromValue(runtime, arguments[0]); - float start = - std::clamp(static_cast(arguments[1].asNumber()), 0.0f, 1.0f); - float end = - std::clamp(static_cast(arguments[2].asNumber()), 0.0f, 1.0f); - auto isComplement = arguments[3].getBool(); + NullablePath Trim(std::shared_ptr srcPath, double startValue, + double endValue, bool isComplement) { + float start = std::clamp(static_cast(startValue), 0.0f, 1.0f); + float end = std::clamp(static_cast(endValue), 0.0f, 1.0f); // If requesting the full path in normal mode, just return a copy if (start <= 0 && end >= 1 && !isComplement) { - SkPath result = srcPath->snapshot(); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(result))); + return std::make_shared(getContext(), srcPath->snapshot()); } SkPath path = srcPath->snapshot(); auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal; auto pe = SkTrimPathEffect::Make(start, end, mode); if (!pe) { - return jsi::Value::null(); + return nullptr; } SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle); SkPathBuilder resultBuilder; if (pe->filterPath(&resultBuilder, path, &rec)) { - auto result = resultBuilder.detach(); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(result))); + return std::make_shared(getContext(), resultBuilder.detach()); } - return jsi::Value::null(); + return nullptr; } - JSI_HOST_FUNCTION(Simplify) { - auto srcPath = JsiSkPath::fromValue(runtime, arguments[0]); + NullablePath Simplify(std::shared_ptr srcPath) { auto result = ::Simplify(srcPath->snapshot()); if (result.has_value()) { - return makeJsiObject( - runtime, - std::make_shared(getContext(), std::move(result.value()))); + return std::make_shared(getContext(), + std::move(result.value())); } - return jsi::Value::null(); + return nullptr; } - JSI_HOST_FUNCTION(Dash) { - auto srcPath = JsiSkPath::fromValue(runtime, arguments[0]); - SkScalar on = arguments[1].asNumber(); - SkScalar off = arguments[2].asNumber(); - auto phase = arguments[3].asNumber(); - SkScalar intervals[] = {on, off}; + NullablePath Dash(std::shared_ptr srcPath, double on, + double off, double phase) { + SkScalar intervals[] = {static_cast(on), + static_cast(off)}; auto i = SkSpan(intervals, 2); auto pe = SkDashPathEffect::Make(i, phase); if (!pe) { - return jsi::Value::null(); + return nullptr; } SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle); SkPathBuilder resultBuilder; if (pe->filterPath(&resultBuilder, srcPath->snapshot(), &rec)) { - auto result = resultBuilder.detach(); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(result))); + return std::make_shared(getContext(), resultBuilder.detach()); } - return jsi::Value::null(); + return nullptr; } - JSI_HOST_FUNCTION(AsWinding) { - auto srcPath = JsiSkPath::fromValue(runtime, arguments[0]); + NullablePath AsWinding(std::shared_ptr srcPath) { auto result = ::AsWinding(srcPath->snapshot()); if (result.has_value()) { - return makeJsiObject( - runtime, - std::make_shared(getContext(), std::move(result.value()))); + return std::make_shared(getContext(), + std::move(result.value())); } - return jsi::Value::null(); + return nullptr; } - JSI_HOST_FUNCTION(Interpolate) { - auto path1 = JsiSkPath::fromValue(runtime, arguments[0]); - auto path2 = JsiSkPath::fromValue(runtime, arguments[1]); - auto weight = arguments[2].asNumber(); - auto p1 = path1->snapshot(); - auto p2 = path2->snapshot(); + NullablePath Interpolate(std::shared_ptr pathOne, + std::shared_ptr pathTwo, + double weight) { + auto p1 = pathOne->snapshot(); + auto p2 = pathTwo->snapshot(); SkPath result; auto succeed = p1.interpolate(p2, weight, &result); if (!succeed) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(result))); + return std::make_shared(getContext(), std::move(result)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "Make", &JsiSkPathFactory::Make); - installHostMethod(runtime, prototype, "MakeFromSVGString", - &JsiSkPathFactory::MakeFromSVGString); - installHostMethod(runtime, prototype, "MakeFromOp", - &JsiSkPathFactory::MakeFromOp); - installHostMethod(runtime, prototype, "MakeFromCmds", - &JsiSkPathFactory::MakeFromCmds); - installHostMethod(runtime, prototype, "MakeFromText", - &JsiSkPathFactory::MakeFromText); + installMethod(runtime, prototype, "Make", &JsiSkPathFactory::Make); + installMethod(runtime, prototype, "MakeFromSVGString", + &JsiSkPathFactory::MakeFromSVGString); + installMethod(runtime, prototype, "MakeFromOp", + &JsiSkPathFactory::MakeFromOp); + installMethod(runtime, prototype, "MakeFromCmds", + &JsiSkPathFactory::MakeFromCmds); + installMethod(runtime, prototype, "MakeFromText", + &JsiSkPathFactory::MakeFromText); // Static shape factories - installHostMethod(runtime, prototype, "Rect", &JsiSkPathFactory::Rect); - installHostMethod(runtime, prototype, "Oval", &JsiSkPathFactory::Oval); - installHostMethod(runtime, prototype, "Circle", &JsiSkPathFactory::Circle); - installHostMethod(runtime, prototype, "RRect", &JsiSkPathFactory::RRect); - installHostMethod(runtime, prototype, "Line", &JsiSkPathFactory::Line); - installHostMethod(runtime, prototype, "Polygon", - &JsiSkPathFactory::Polygon); + installMethod(runtime, prototype, "Rect", &JsiSkPathFactory::Rect); + installMethod(runtime, prototype, "Oval", &JsiSkPathFactory::Oval); + installMethod(runtime, prototype, "Circle", &JsiSkPathFactory::Circle); + installMethod(runtime, prototype, "RRect", &JsiSkPathFactory::RRect); + installMethod(runtime, prototype, "Line", &JsiSkPathFactory::Line); + installMethod(runtime, prototype, "Polygon", &JsiSkPathFactory::Polygon); // Static path operations installHostMethod(runtime, prototype, "Stroke", &JsiSkPathFactory::Stroke); - installHostMethod(runtime, prototype, "Trim", &JsiSkPathFactory::Trim); - installHostMethod(runtime, prototype, "Simplify", - &JsiSkPathFactory::Simplify); - installHostMethod(runtime, prototype, "Dash", &JsiSkPathFactory::Dash); - installHostMethod(runtime, prototype, "AsWinding", - &JsiSkPathFactory::AsWinding); - installHostMethod(runtime, prototype, "Interpolate", - &JsiSkPathFactory::Interpolate); + installMethod(runtime, prototype, "Trim", &JsiSkPathFactory::Trim); + installMethod(runtime, prototype, "Simplify", &JsiSkPathFactory::Simplify); + installMethod(runtime, prototype, "Dash", &JsiSkPathFactory::Dash); + installMethod(runtime, prototype, "AsWinding", + &JsiSkPathFactory::AsWinding); + installMethod(runtime, prototype, "Interpolate", + &JsiSkPathFactory::Interpolate); } explicit JsiSkPathFactory(std::shared_ptr context) : JsiSkNativeObject(std::move(context)) {} + +private: + static SkPathDirection toDirection(const JsiOptional &isCCW) { + return isCCW.has_value() && *isCCW ? SkPathDirection::kCCW + : SkPathDirection::kCW; + } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkPicture.h b/packages/skia/cpp/api/JsiSkPicture.h index 71b2f28c68..1761e29246 100644 --- a/packages/skia/cpp/api/JsiSkPicture.h +++ b/packages/skia/cpp/api/JsiSkPicture.h @@ -1,7 +1,9 @@ #pragma once #include +#include +#include "JsiSkConverters.h" #include "JsiSkData.h" #include "JsiSkDispatcher.h" #include "JsiSkMatrix.h" @@ -56,22 +58,15 @@ class JsiSkPicture } } - JSI_HOST_FUNCTION(makeShader) { - auto tmx = (SkTileMode)arguments[0].asNumber(); - auto tmy = (SkTileMode)arguments[1].asNumber(); - auto fm = (SkFilterMode)arguments[2].asNumber(); - auto m = count > 3 && !arguments[3].isUndefined() - ? JsiSkMatrix::fromValue(runtime, arguments[3]).get() - : nullptr; - - auto tr = count > 4 && !arguments[4].isUndefined() - ? JsiSkRect::fromValue(runtime, arguments[4]).get() - : nullptr; - - // Create shader - auto shader = getObject()->makeShader(tmx, tmy, fm, m, tr); - return makeJsiObject(runtime, - std::make_shared(getContext(), shader)); + std::shared_ptr + makeShader(double tmx, double tmy, double fm, + std::optional> m, + std::optional> tr) { + auto shader = getObject()->makeShader( + static_cast(tmx), static_cast(tmy), + static_cast(fm), m.has_value() ? m->get() : nullptr, + tr.has_value() ? tr->get() : nullptr); + return std::make_shared(getContext(), shader); } JSI_HOST_FUNCTION(serialize) { @@ -103,8 +98,7 @@ class JsiSkPicture static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "makeShader", - &JsiSkPicture::makeShader); + installMethod(runtime, prototype, "makeShader", &JsiSkPicture::makeShader); installHostMethod(runtime, prototype, "serialize", &JsiSkPicture::serialize); } diff --git a/packages/skia/cpp/api/JsiSkPoint.h b/packages/skia/cpp/api/JsiSkPoint.h index 5bff76ac59..267afeb690 100644 --- a/packages/skia/cpp/api/JsiSkPoint.h +++ b/packages/skia/cpp/api/JsiSkPoint.h @@ -23,14 +23,14 @@ class JsiSkPoint public: static constexpr const char *CLASS_NAME = "Point"; - JSI_PROPERTY_GET(x) { return static_cast(getObject()->x()); } + double getX() { return static_cast(getObject()->x()); } - JSI_PROPERTY_GET(y) { return static_cast(getObject()->y()); } + double getY() { return static_cast(getObject()->y()); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostGetter(runtime, prototype, "x", &JsiSkPoint::get_x); - installHostGetter(runtime, prototype, "y", &JsiSkPoint::get_y); + installGetter(runtime, prototype, "x", &JsiSkPoint::getX); + installGetter(runtime, prototype, "y", &JsiSkPoint::getY); } JsiSkPoint(std::shared_ptr context, const SkPoint &point) diff --git a/packages/skia/cpp/api/JsiSkRRect.h b/packages/skia/cpp/api/JsiSkRRect.h index 9f455966f9..873969de54 100644 --- a/packages/skia/cpp/api/JsiSkRRect.h +++ b/packages/skia/cpp/api/JsiSkRRect.h @@ -26,22 +26,21 @@ class JsiSkRRect public: static constexpr const char *CLASS_NAME = "RRect"; - JSI_PROPERTY_GET(rx) { + double getRx() { return static_cast(getObject()->getSimpleRadii().x()); } - JSI_PROPERTY_GET(ry) { + double getRy() { return static_cast(getObject()->getSimpleRadii().y()); } - JSI_PROPERTY_GET(rect) { - return makeJsiObject(runtime, std::make_shared( - getContext(), getObject()->getBounds())); + std::shared_ptr getRect() { + return std::make_shared(getContext(), getObject()->getBounds()); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostGetter(runtime, prototype, "rx", &JsiSkRRect::get_rx); - installHostGetter(runtime, prototype, "ry", &JsiSkRRect::get_ry); - installHostGetter(runtime, prototype, "rect", &JsiSkRRect::get_rect); + installGetter(runtime, prototype, "rx", &JsiSkRRect::getRx); + installGetter(runtime, prototype, "ry", &JsiSkRRect::getRy); + installGetter(runtime, prototype, "rect", &JsiSkRRect::getRect); } JsiSkRRect(std::shared_ptr context, const SkRRect &rect) diff --git a/packages/skia/cpp/api/JsiSkRSXform.h b/packages/skia/cpp/api/JsiSkRSXform.h index f83f978554..7965a27b20 100644 --- a/packages/skia/cpp/api/JsiSkRSXform.h +++ b/packages/skia/cpp/api/JsiSkRSXform.h @@ -28,38 +28,25 @@ class JsiSkRSXform : JsiSkWrappingSharedPtrNativeObject( std::move(context), std::make_shared(rsxform)) {} - JSI_PROPERTY_GET(scos) { - return jsi::Value(SkScalarToDouble(getObject()->fSCos)); - } - JSI_PROPERTY_GET(ssin) { - return jsi::Value(SkScalarToDouble(getObject()->fSSin)); - } - JSI_PROPERTY_GET(tx) { - return jsi::Value(SkScalarToDouble(getObject()->fTx)); - } - JSI_PROPERTY_GET(ty) { - return jsi::Value(SkScalarToDouble(getObject()->fTy)); - } + double getScos() { return SkScalarToDouble(getObject()->fSCos); } + double getSsin() { return SkScalarToDouble(getObject()->fSSin); } + double getTx() { return SkScalarToDouble(getObject()->fTx); } + double getTy() { return SkScalarToDouble(getObject()->fTy); } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Woverloaded-virtual" - JSI_HOST_FUNCTION(set) { - auto scos = arguments[0].asNumber(); - auto ssin = arguments[1].asNumber(); - auto tx = arguments[2].asNumber(); - auto ty = arguments[3].asNumber(); + void set(double scos, double ssin, double tx, double ty) { getObject()->set(scos, ssin, tx, ty); - return jsi::Value::undefined(); } #pragma clang diagnostic pop static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostGetter(runtime, prototype, "scos", &JsiSkRSXform::get_scos); - installHostGetter(runtime, prototype, "ssin", &JsiSkRSXform::get_ssin); - installHostGetter(runtime, prototype, "tx", &JsiSkRSXform::get_tx); - installHostGetter(runtime, prototype, "ty", &JsiSkRSXform::get_ty); - installHostMethod(runtime, prototype, "set", &JsiSkRSXform::set); + installGetter(runtime, prototype, "scos", &JsiSkRSXform::getScos); + installGetter(runtime, prototype, "ssin", &JsiSkRSXform::getSsin); + installGetter(runtime, prototype, "tx", &JsiSkRSXform::getTx); + installGetter(runtime, prototype, "ty", &JsiSkRSXform::getTy); + installMethod(runtime, prototype, "set", &JsiSkRSXform::set); } /** diff --git a/packages/skia/cpp/api/JsiSkRect.h b/packages/skia/cpp/api/JsiSkRect.h index 407c831188..47377186e1 100644 --- a/packages/skia/cpp/api/JsiSkRect.h +++ b/packages/skia/cpp/api/JsiSkRect.h @@ -22,43 +22,35 @@ class JsiSkRect : public JsiSkWrappingSharedPtrNativeObject { public: static constexpr const char *CLASS_NAME = "Rect"; - JSI_PROPERTY_GET(x) { return static_cast(getObject()->x()); } - JSI_PROPERTY_GET(y) { return static_cast(getObject()->y()); } - JSI_PROPERTY_GET(width) { return static_cast(getObject()->width()); } - JSI_PROPERTY_GET(height) { - return static_cast(getObject()->height()); - } - JSI_PROPERTY_GET(left) { return static_cast(getObject()->left()); } - JSI_PROPERTY_GET(top) { return static_cast(getObject()->top()); } - JSI_PROPERTY_GET(right) { return static_cast(getObject()->right()); } - JSI_PROPERTY_GET(bottom) { - return static_cast(getObject()->bottom()); - } - - JSI_HOST_FUNCTION(setXYWH) { - getObject()->setXYWH(arguments[0].asNumber(), arguments[1].asNumber(), - arguments[2].asNumber(), arguments[3].asNumber()); - return jsi::Value::undefined(); + double getX() { return static_cast(getObject()->x()); } + double getY() { return static_cast(getObject()->y()); } + double getWidth() { return static_cast(getObject()->width()); } + double getHeight() { return static_cast(getObject()->height()); } + double getLeft() { return static_cast(getObject()->left()); } + double getTop() { return static_cast(getObject()->top()); } + double getRight() { return static_cast(getObject()->right()); } + double getBottom() { return static_cast(getObject()->bottom()); } + + void setXYWH(double x, double y, double width, double height) { + getObject()->setXYWH(x, y, width, height); } - JSI_HOST_FUNCTION(setLTRB) { - getObject()->setLTRB(arguments[0].asNumber(), arguments[1].asNumber(), - arguments[2].asNumber(), arguments[3].asNumber()); - return jsi::Value::undefined(); + void setLTRB(double left, double top, double right, double bottom) { + getObject()->setLTRB(left, top, right, bottom); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostGetter(runtime, prototype, "x", &JsiSkRect::get_x); - installHostGetter(runtime, prototype, "y", &JsiSkRect::get_y); - installHostGetter(runtime, prototype, "width", &JsiSkRect::get_width); - installHostGetter(runtime, prototype, "height", &JsiSkRect::get_height); - installHostGetter(runtime, prototype, "left", &JsiSkRect::get_left); - installHostGetter(runtime, prototype, "top", &JsiSkRect::get_top); - installHostGetter(runtime, prototype, "right", &JsiSkRect::get_right); - installHostGetter(runtime, prototype, "bottom", &JsiSkRect::get_bottom); - installHostMethod(runtime, prototype, "setXYWH", &JsiSkRect::setXYWH); - installHostMethod(runtime, prototype, "setLTRB", &JsiSkRect::setLTRB); + installGetter(runtime, prototype, "x", &JsiSkRect::getX); + installGetter(runtime, prototype, "y", &JsiSkRect::getY); + installGetter(runtime, prototype, "width", &JsiSkRect::getWidth); + installGetter(runtime, prototype, "height", &JsiSkRect::getHeight); + installGetter(runtime, prototype, "left", &JsiSkRect::getLeft); + installGetter(runtime, prototype, "top", &JsiSkRect::getTop); + installGetter(runtime, prototype, "right", &JsiSkRect::getRight); + installGetter(runtime, prototype, "bottom", &JsiSkRect::getBottom); + installMethod(runtime, prototype, "setXYWH", &JsiSkRect::setXYWH); + installMethod(runtime, prototype, "setLTRB", &JsiSkRect::setLTRB); } /** diff --git a/packages/skia/cpp/api/JsiSkRuntimeEffect.h b/packages/skia/cpp/api/JsiSkRuntimeEffect.h index ad77d168e0..8d3db04f03 100644 --- a/packages/skia/cpp/api/JsiSkRuntimeEffect.h +++ b/packages/skia/cpp/api/JsiSkRuntimeEffect.h @@ -5,6 +5,7 @@ #include #include +#include "JsiSkConverters.h" #include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" #include "JsiSkShader.h" @@ -36,108 +37,95 @@ struct RuntimeEffectUniform { bool isInteger; }; +} // namespace RNSkia + +namespace rnwgpu { + +// RuntimeEffectUniform -> {columns, rows, slot, isInteger} +template <> struct JSIConverter { + static jsi::Value toJSI(jsi::Runtime &runtime, + const RNSkia::RuntimeEffectUniform &u) { + jsi::Object result(runtime); + result.setProperty(runtime, "columns", u.columns); + result.setProperty(runtime, "rows", u.rows); + result.setProperty(runtime, "slot", u.slot); + result.setProperty(runtime, "isInteger", u.isInteger); + return result; + } +}; + +} // namespace rnwgpu + +namespace RNSkia { + class JsiSkRuntimeEffect : public JsiSkWrappingSkPtrNativeObject { public: static constexpr const char *CLASS_NAME = "RuntimeEffect"; - JSI_HOST_FUNCTION(makeShader) { - auto uniforms = castUniforms(runtime, arguments[0]); - - auto matrix = - count >= 2 && !arguments[1].isUndefined() && !arguments[1].isNull() - ? JsiSkMatrix::fromValue(runtime, arguments[1]).get() - : nullptr; - - // Create and return shader as host object - auto shader = - getObject()->makeShader(std::move(uniforms), nullptr, 0, matrix); - - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(shader))); + std::shared_ptr + makeShader(std::vector uniformValues, + JsiOptional> matrix) { + auto uniforms = castUniforms(uniformValues); + auto shader = getObject()->makeShader( + std::move(uniforms), nullptr, 0, + matrix.has_value() ? matrix->get() : nullptr); + return std::make_shared(getContext(), std::move(shader)); } - JSI_HOST_FUNCTION(makeShaderWithChildren) { - auto uniforms = castUniforms(runtime, arguments[0]); - - // Children - std::vector> children; - auto jsiChildren = arguments[1].asObject(runtime).asArray(runtime); - auto jsiChildCount = jsiChildren.size(runtime); - children.reserve(jsiChildCount); - for (int i = 0; i < jsiChildCount; i++) { - auto shader = getJsiObject( - runtime, jsiChildren.getValueAtIndex(runtime, i)) - ->getObject(); - children.push_back(shader); - } - - auto matrix = - count >= 3 && !arguments[2].isUndefined() && !arguments[2].isNull() - ? JsiSkMatrix::fromValue(runtime, arguments[2]).get() - : nullptr; - - // Create and return shader as host object - auto shader = getObject()->makeShader(std::move(uniforms), children.data(), - children.size(), matrix); - - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(shader))); + std::shared_ptr + makeShaderWithChildren(std::vector uniformValues, + std::vector> children, + JsiOptional> matrix) { + auto uniforms = castUniforms(uniformValues); + auto shader = getObject()->makeShader( + std::move(uniforms), children.data(), children.size(), + matrix.has_value() ? matrix->get() : nullptr); + return std::make_shared(getContext(), std::move(shader)); } - JSI_HOST_FUNCTION(getUniformCount) { + int getUniformCount() { return static_cast(getObject()->uniforms().size()); } - JSI_HOST_FUNCTION(getUniformFloatCount) { + int getUniformFloatCount() { return static_cast(getObject()->uniformSize() / sizeof(float)); } - JSI_HOST_FUNCTION(getUniformName) { - auto i = static_cast(arguments[0].asNumber()); + std::string getUniformName(int i) { if (i < 0 || i >= getObject()->uniforms().size()) { - throw jsi::JSError(runtime, "invalid uniform index"); + throw std::runtime_error("invalid uniform index"); } auto it = getObject()->uniforms().begin() + i; - return jsi::String::createFromAscii(runtime, std::string(it->name)); + return std::string(it->name); } - JSI_HOST_FUNCTION(getUniform) { - auto i = static_cast(arguments[0].asNumber()); + RuntimeEffectUniform getUniform(int i) { if (i < 0 || i >= getObject()->uniforms().size()) { - throw jsi::JSError(runtime, "invalid uniform index"); + throw std::runtime_error("invalid uniform index"); } auto it = getObject()->uniforms().begin() + i; - auto result = jsi::Object(runtime); - RuntimeEffectUniform su = fromUniform(*it); - result.setProperty(runtime, "columns", su.columns); - result.setProperty(runtime, "rows", su.rows); - result.setProperty(runtime, "slot", su.slot); - result.setProperty(runtime, "isInteger", su.isInteger); - return result; + return fromUniform(*it); } - JSI_HOST_FUNCTION(source) { - return jsi::String::createFromAscii(runtime, getObject()->source()); - } + std::string source() { return std::string(getObject()->source()); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "makeShader", - &JsiSkRuntimeEffect::makeShader); - installHostMethod(runtime, prototype, "makeShaderWithChildren", - &JsiSkRuntimeEffect::makeShaderWithChildren); - installHostMethod(runtime, prototype, "getUniformCount", - &JsiSkRuntimeEffect::getUniformCount); - installHostMethod(runtime, prototype, "getUniformFloatCount", - &JsiSkRuntimeEffect::getUniformFloatCount); - installHostMethod(runtime, prototype, "getUniformName", - &JsiSkRuntimeEffect::getUniformName); - installHostMethod(runtime, prototype, "getUniform", - &JsiSkRuntimeEffect::getUniform); - installHostMethod(runtime, prototype, "source", - &JsiSkRuntimeEffect::source); + installMethod(runtime, prototype, "makeShader", + &JsiSkRuntimeEffect::makeShader); + installMethod(runtime, prototype, "makeShaderWithChildren", + &JsiSkRuntimeEffect::makeShaderWithChildren); + installMethod(runtime, prototype, "getUniformCount", + &JsiSkRuntimeEffect::getUniformCount); + installMethod(runtime, prototype, "getUniformFloatCount", + &JsiSkRuntimeEffect::getUniformFloatCount); + installMethod(runtime, prototype, "getUniformName", + &JsiSkRuntimeEffect::getUniformName); + installMethod(runtime, prototype, "getUniform", + &JsiSkRuntimeEffect::getUniform); + installMethod(runtime, prototype, "source", &JsiSkRuntimeEffect::source); } JsiSkRuntimeEffect(std::shared_ptr context, @@ -206,17 +194,13 @@ class JsiSkRuntimeEffect } private: - sk_sp castUniforms(jsi::Runtime &runtime, const jsi::Value &value) { - auto jsiUniforms = value.asObject(runtime).asArray(runtime); - auto jsiUniformsSize = jsiUniforms.size(runtime); - + sk_sp castUniforms(const std::vector &values) { // verify size of input uniforms - if (jsiUniformsSize * sizeof(float) != getObject()->uniformSize()) { - std::string msg = + if (values.size() * sizeof(float) != getObject()->uniformSize()) { + throw std::runtime_error( "Uniforms size differs from effect's uniform size. Received " + - std::to_string(jsiUniformsSize) + " expected " + - std::to_string(getObject()->uniformSize() / sizeof(float)); - throw jsi::JSError(runtime, msg.c_str()); + std::to_string(values.size()) + " expected " + + std::to_string(getObject()->uniformSize() / sizeof(float))); } auto uniforms = SkData::MakeUninitialized(getObject()->uniformSize()); @@ -228,7 +212,7 @@ class JsiSkRuntimeEffect RuntimeEffectUniform reu = fromUniform(*it); for (std::size_t j = 0; j < reu.columns * reu.rows; ++j) { const std::size_t offset = reu.slot + j; - float fValue = jsiUniforms.getValueAtIndex(runtime, offset).asNumber(); + float fValue = static_cast(values[offset]); int iValue = static_cast(fValue); auto value = reu.isInteger ? SkBits2Float(iValue) : fValue; memcpy(SkTAddOffset(uniforms->writable_data(), diff --git a/packages/skia/cpp/api/JsiSkRuntimeEffectFactory.h b/packages/skia/cpp/api/JsiSkRuntimeEffectFactory.h index 9f0fe96e99..aceb09c663 100644 --- a/packages/skia/cpp/api/JsiSkRuntimeEffectFactory.h +++ b/packages/skia/cpp/api/JsiSkRuntimeEffectFactory.h @@ -18,26 +18,22 @@ class JsiSkRuntimeEffectFactory public: static constexpr const char *CLASS_NAME = "RuntimeEffectFactory"; - JSI_HOST_FUNCTION(Make) { - auto sksl = arguments[0].asString(runtime).utf8(runtime); + std::shared_ptr Make(std::string sksl) { auto result = SkRuntimeEffect::MakeForShader(SkString(sksl)); auto effect = result.effect; auto errorText = result.errorText; if (!effect) { - throw jsi::JSError(runtime, std::string("Error in sksl:\n" + - std::string(errorText.c_str())) - .c_str()); - return jsi::Value::null(); + throw std::runtime_error("Error in sksl:\n" + + std::string(errorText.c_str())); } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(effect))); + return std::make_shared(getContext(), + std::move(effect)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "Make", - &JsiSkRuntimeEffectFactory::Make); + installMethod(runtime, prototype, "Make", &JsiSkRuntimeEffectFactory::Make); } explicit JsiSkRuntimeEffectFactory( diff --git a/packages/skia/cpp/api/JsiSkRuntimeShaderBuilder.h b/packages/skia/cpp/api/JsiSkRuntimeShaderBuilder.h index 725802aa45..38056bd1cf 100644 --- a/packages/skia/cpp/api/JsiSkRuntimeShaderBuilder.h +++ b/packages/skia/cpp/api/JsiSkRuntimeShaderBuilder.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -35,26 +36,16 @@ class JsiSkRuntimeShaderBuilder SkRuntimeShaderBuilder>( std::move(context), std::make_shared(rt)) {} - JSI_HOST_FUNCTION(setUniform) { - auto name = arguments[0].asString(runtime).utf8(runtime); - auto jsiValue = arguments[1].asObject(runtime).asArray(runtime); - auto size = jsiValue.size(runtime); - std::vector value; - value.reserve(size); - for (int i = 0; i < size; i++) { - auto e = jsiValue.getValueAtIndex(runtime, i).asNumber(); - value.push_back(e); - } + void setUniform(std::string name, std::vector value) { getObject() ->uniform(name.c_str()) - .set(value.data(), static_cast(size)); - return jsi::Value::undefined(); + .set(value.data(), static_cast(value.size())); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "setUniform", - &JsiSkRuntimeShaderBuilder::setUniform); + installMethod(runtime, prototype, "setUniform", + &JsiSkRuntimeShaderBuilder::setUniform); } /** diff --git a/packages/skia/cpp/api/JsiSkSVG.h b/packages/skia/cpp/api/JsiSkSVG.h index 85e6defb9e..16ad91ad6a 100644 --- a/packages/skia/cpp/api/JsiSkSVG.h +++ b/packages/skia/cpp/api/JsiSkSVG.h @@ -29,18 +29,18 @@ class JsiSkSVG : public JsiSkWrappingSkPtrNativeObject { ~JsiSkSVG() = default; - JSI_HOST_FUNCTION(width) { + double width() { return static_cast(getObject()->containerSize().width()); } - JSI_HOST_FUNCTION(height) { + double height() { return static_cast(getObject()->containerSize().height()); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "width", &JsiSkSVG::width); - installHostMethod(runtime, prototype, "height", &JsiSkSVG::height); + installMethod(runtime, prototype, "width", &JsiSkSVG::width); + installMethod(runtime, prototype, "height", &JsiSkSVG::height); } /** diff --git a/packages/skia/cpp/api/JsiSkShaderFactory.h b/packages/skia/cpp/api/JsiSkShaderFactory.h index e77b473539..b1b7b3a576 100644 --- a/packages/skia/cpp/api/JsiSkShaderFactory.h +++ b/packages/skia/cpp/api/JsiSkShaderFactory.h @@ -6,8 +6,13 @@ #include +#include "JsiSkColor.h" #include "JsiSkColorFilter.h" +#include "JsiSkConverters.h" +#include "JsiSkMatrix.h" #include "JsiSkNativeObjects.h" +#include "JsiSkPoint.h" +#include "JsiSkShader.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -22,269 +27,192 @@ namespace RNSkia { namespace jsi = facebook::jsi; -int getFlag(const jsi::Value *values, int i, size_t size) { - if (i >= size || values[i].isUndefined()) { - return 0; - } - return values[i].asNumber(); -} - -SkMatrix *getLocalMatrix(jsi::Runtime &runtime, const jsi::Value *values, int i, - size_t size) { - if (i >= size || values[i].isUndefined()) { - return nullptr; - } - return JsiSkMatrix::fromValue(runtime, values[i]).get(); -} - -SkTileMode getTileMode(const jsi::Value *values, int i, size_t size) { - if (i >= size || values[i].isUndefined()) { - return SkTileMode::kClamp; - } - return static_cast(values[i].asNumber()); -} - -std::vector getColors(jsi::Runtime &runtime, - const jsi::Value &value) { - std::vector colors; - if (!value.isNull()) { - auto jsiColors = value.asObject(runtime).asArray(runtime); - auto size = jsiColors.size(runtime); - colors.reserve(size); - for (int i = 0; i < size; i++) { - SkColor color = - JsiSkColor::fromValue(runtime, jsiColors.getValueAtIndex(runtime, i)); - colors.push_back(SkColor4f::FromColor(color)); - } - } - return colors; -} - -std::vector getPositions(jsi::Runtime &runtime, - const jsi::Value &value) { - std::vector positions; - if (!value.isNull()) { - auto jsiPositions = value.asObject(runtime).asArray(runtime); - auto size = jsiPositions.size(runtime); - positions.reserve(size); - for (int i = 0; i < size; i++) { - SkScalar position = jsiPositions.getValueAtIndex(runtime, i).asNumber(); - positions.push_back(position); - } - } - return positions; -} - class JsiSkShaderFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "ShaderFactory"; - JSI_HOST_FUNCTION(MakeLinearGradient) { - auto p1 = - *JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)).get(); - auto p2 = - *JsiSkPoint::fromValue(runtime, arguments[1].asObject(runtime)).get(); + std::shared_ptr + MakeLinearGradient(SkPoint p1, SkPoint p2, + JsiOptional> jsiColors, + JsiOptional> jsiPositions, + JsiOptional tileMode, + JsiOptional> matrix, + JsiOptional flag) { SkPoint pts[] = {p1, p2}; - - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { - throw std::invalid_argument("colors must have at least 2 colors"); - } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { - throw std::invalid_argument( - "positions must be empty or have the same size as colors"); - } - auto tileMode = getTileMode(arguments, 4, count); - auto flag = getFlag(arguments, 6, count); - auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); - - SkGradient::Colors gradColors( - SkSpan(colors), - !positions.empty() - ? SkSpan(positions.data(), positions.size()) - : SkSpan(), - tileMode); - SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + auto colors = toColors(jsiColors); + auto positions = toPositions(jsiPositions, colors.size()); + SkGradient::Colors gradColors(SkSpan(colors), toSpan(positions), + toTileMode(tileMode)); + SkGradient grad(gradColors, + SkGradient::Interpolation::FromFlags(toFlag(flag))); sk_sp gradient = - SkShaders::LinearGradient(pts, grad, localMatrix); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + SkShaders::LinearGradient(pts, grad, toLocalMatrix(matrix)); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeRadialGradient) { - auto center = - *JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)).get(); - auto r = arguments[1].asNumber(); - - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { - throw std::invalid_argument("colors must have at least 2 colors"); - } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { - throw std::invalid_argument( - "positions must be empty or the same size as colors"); - } - auto tileMode = getTileMode(arguments, 4, count); - auto flag = getFlag(arguments, 6, count); - auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); - - SkGradient::Colors gradColors( - SkSpan(colors), - !positions.empty() - ? SkSpan(positions.data(), positions.size()) - : SkSpan(), - tileMode); - SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + std::shared_ptr + MakeRadialGradient(SkPoint center, double r, + JsiOptional> jsiColors, + JsiOptional> jsiPositions, + JsiOptional tileMode, + JsiOptional> matrix, + JsiOptional flag) { + auto colors = toColors(jsiColors); + auto positions = toPositions(jsiPositions, colors.size()); + SkGradient::Colors gradColors(SkSpan(colors), toSpan(positions), + toTileMode(tileMode)); + SkGradient grad(gradColors, + SkGradient::Interpolation::FromFlags(toFlag(flag))); sk_sp gradient = - SkShaders::RadialGradient(center, r, grad, localMatrix); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + SkShaders::RadialGradient(center, r, grad, toLocalMatrix(matrix)); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeSweepGradient) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { - throw std::invalid_argument("colors must have at least 2 colors"); - } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { - throw std::invalid_argument( - "positions must be empty or the same size as colors"); - } - auto tileMode = getTileMode(arguments, 4, count); - auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); - auto flag = getFlag(arguments, 6, count); - auto startAngle = (count < 8 || arguments[7].isUndefined()) - ? 0.0f - : static_cast(arguments[7].asNumber()); - auto endAngle = (count < 9 || arguments[8].isUndefined()) - ? 360.0f - : static_cast(arguments[8].asNumber()); - - SkGradient::Colors gradColors( - SkSpan(colors), - !positions.empty() - ? SkSpan(positions.data(), positions.size()) - : SkSpan(), - tileMode); - SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); - sk_sp gradient = SkShaders::SweepGradient( - SkPoint::Make(x, y), startAngle, endAngle, grad, localMatrix); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + std::shared_ptr + MakeSweepGradient(double x, double y, + JsiOptional> jsiColors, + JsiOptional> jsiPositions, + JsiOptional tileMode, + JsiOptional> matrix, + JsiOptional flag, JsiOptional start, + JsiOptional end) { + auto colors = toColors(jsiColors); + auto positions = toPositions(jsiPositions, colors.size()); + auto startAngle = + start.has_value() ? static_cast(*start) : 0.0f; + auto endAngle = end.has_value() ? static_cast(*end) : 360.0f; + SkGradient::Colors gradColors(SkSpan(colors), toSpan(positions), + toTileMode(tileMode)); + SkGradient grad(gradColors, + SkGradient::Interpolation::FromFlags(toFlag(flag))); + sk_sp gradient = + SkShaders::SweepGradient(SkPoint::Make(x, y), startAngle, endAngle, + grad, toLocalMatrix(matrix)); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeTwoPointConicalGradient) { - auto start = - *JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)).get(); - auto startRadius = arguments[1].asNumber(); - - auto end = - *JsiSkPoint::fromValue(runtime, arguments[2].asObject(runtime)).get(); - auto endRadius = arguments[3].asNumber(); - - std::vector colors = getColors(runtime, arguments[4]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { - throw std::invalid_argument("colors must have at least 2 colors"); - } - std::vector positions = getPositions(runtime, arguments[5]); - if (!positions.empty() && positions.size() != colorsSize) { - throw std::invalid_argument( - "positions must be empty or the same size as colors"); - } - auto tileMode = getTileMode(arguments, 6, count); - auto localMatrix = getLocalMatrix(runtime, arguments, 7, count); - auto flag = getFlag(arguments, 8, count); - - SkGradient::Colors gradColors( - SkSpan(colors), - !positions.empty() - ? SkSpan(positions.data(), positions.size()) - : SkSpan(), - tileMode); - SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + std::shared_ptr + MakeTwoPointConicalGradient(SkPoint start, double startRadius, SkPoint end, + double endRadius, + JsiOptional> jsiColors, + JsiOptional> jsiPositions, + JsiOptional tileMode, + JsiOptional> matrix, + JsiOptional flag) { + auto colors = toColors(jsiColors); + auto positions = toPositions(jsiPositions, colors.size()); + SkGradient::Colors gradColors(SkSpan(colors), toSpan(positions), + toTileMode(tileMode)); + SkGradient grad(gradColors, + SkGradient::Interpolation::FromFlags(toFlag(flag))); sk_sp gradient = SkShaders::TwoPointConicalGradient( - start, startRadius, end, endRadius, grad, localMatrix); - - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + start, startRadius, end, endRadius, grad, toLocalMatrix(matrix)); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeTurbulence) { - auto baseFreqX = arguments[0].asNumber(); - auto baseFreqY = arguments[1].asNumber(); - auto octaves = arguments[2].asNumber(); - auto seed = arguments[3].asNumber(); - auto tileW = arguments[4].asNumber(); - auto tileH = arguments[5].asNumber(); + std::shared_ptr MakeTurbulence(double baseFreqX, + double baseFreqY, double octaves, + double seed, double tileW, + double tileH) { SkISize size = SkISize::Make(tileW, tileH); sk_sp gradient = SkShaders::MakeTurbulence(baseFreqX, baseFreqY, octaves, seed, &size); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeFractalNoise) { - auto baseFreqX = arguments[0].asNumber(); - auto baseFreqY = arguments[1].asNumber(); - auto octaves = arguments[2].asNumber(); - auto seed = arguments[3].asNumber(); - auto tileW = arguments[4].asNumber(); - auto tileH = arguments[5].asNumber(); + std::shared_ptr MakeFractalNoise(double baseFreqX, + double baseFreqY, + double octaves, double seed, + double tileW, double tileH) { SkISize size = SkISize::Make(tileW, tileH); sk_sp gradient = SkShaders::MakeFractalNoise(baseFreqX, baseFreqY, octaves, seed, &size); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeBlend) { - auto blendMode = (SkBlendMode)arguments[0].asNumber(); - auto one = JsiSkShader::fromValue(runtime, arguments[1]); - auto two = JsiSkShader::fromValue(runtime, arguments[2]); - sk_sp gradient = SkShaders::Blend(blendMode, one, two); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + std::shared_ptr MakeBlend(double blendMode, sk_sp one, + sk_sp two) { + sk_sp gradient = + SkShaders::Blend(static_cast(blendMode), one, two); + return std::make_shared(getContext(), std::move(gradient)); } - JSI_HOST_FUNCTION(MakeColor) { - auto color = JsiSkColor::fromValue(runtime, arguments[0]); + std::shared_ptr MakeColor(JsiColor color) { sk_sp gradient = SkShaders::Color(color); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(gradient))); + return std::make_shared(getContext(), std::move(gradient)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeLinearGradient", - &JsiSkShaderFactory::MakeLinearGradient); - installHostMethod(runtime, prototype, "MakeRadialGradient", - &JsiSkShaderFactory::MakeRadialGradient); - installHostMethod(runtime, prototype, "MakeSweepGradient", - &JsiSkShaderFactory::MakeSweepGradient); - installHostMethod(runtime, prototype, "MakeTwoPointConicalGradient", - &JsiSkShaderFactory::MakeTwoPointConicalGradient); - installHostMethod(runtime, prototype, "MakeTurbulence", - &JsiSkShaderFactory::MakeTurbulence); - installHostMethod(runtime, prototype, "MakeFractalNoise", - &JsiSkShaderFactory::MakeFractalNoise); - installHostMethod(runtime, prototype, "MakeBlend", - &JsiSkShaderFactory::MakeBlend); - installHostMethod(runtime, prototype, "MakeColor", - &JsiSkShaderFactory::MakeColor); + installMethod(runtime, prototype, "MakeLinearGradient", + &JsiSkShaderFactory::MakeLinearGradient); + installMethod(runtime, prototype, "MakeRadialGradient", + &JsiSkShaderFactory::MakeRadialGradient); + installMethod(runtime, prototype, "MakeSweepGradient", + &JsiSkShaderFactory::MakeSweepGradient); + installMethod(runtime, prototype, "MakeTwoPointConicalGradient", + &JsiSkShaderFactory::MakeTwoPointConicalGradient); + installMethod(runtime, prototype, "MakeTurbulence", + &JsiSkShaderFactory::MakeTurbulence); + installMethod(runtime, prototype, "MakeFractalNoise", + &JsiSkShaderFactory::MakeFractalNoise); + installMethod(runtime, prototype, "MakeBlend", + &JsiSkShaderFactory::MakeBlend); + installMethod(runtime, prototype, "MakeColor", + &JsiSkShaderFactory::MakeColor); } explicit JsiSkShaderFactory(std::shared_ptr context) : JsiSkNativeObject(std::move(context)) {} + +private: + static std::vector + toColors(const JsiOptional> &jsiColors) { + std::vector colors; + if (jsiColors.has_value()) { + colors.reserve(jsiColors->size()); + for (const auto &color : *jsiColors) { + colors.push_back(SkColor4f::FromColor(color)); + } + } + if (colors.size() < 2) { + throw std::invalid_argument("colors must have at least 2 colors"); + } + return colors; + } + + static std::vector + toPositions(const JsiOptional> &jsiPositions, + size_t colorsSize) { + std::vector positions = + jsiPositions.has_value() ? *jsiPositions : std::vector{}; + if (!positions.empty() && positions.size() != colorsSize) { + throw std::invalid_argument( + "positions must be empty or have the same size as colors"); + } + return positions; + } + + static SkSpan toSpan(const std::vector &positions) { + return !positions.empty() + ? SkSpan(positions.data(), positions.size()) + : SkSpan(); + } + + static SkTileMode toTileMode(const JsiOptional &tileMode) { + return tileMode.has_value() ? static_cast(*tileMode) + : SkTileMode::kClamp; + } + + static int toFlag(const JsiOptional &flag) { + return flag.has_value() ? static_cast(*flag) : 0; + } + + static SkMatrix * + toLocalMatrix(const JsiOptional> &matrix) { + return matrix.has_value() ? matrix->get() : nullptr; + } }; } // namespace RNSkia diff --git a/packages/skia/cpp/api/JsiSkSkottie.h b/packages/skia/cpp/api/JsiSkSkottie.h index 5bbb2f7dce..39ee6a2c88 100644 --- a/packages/skia/cpp/api/JsiSkSkottie.h +++ b/packages/skia/cpp/api/JsiSkSkottie.h @@ -1,9 +1,16 @@ #pragma once +#include +#include +#include +#include +#include + #include #include "JsiSkCanvas.h" #include "JsiSkColor.h" +#include "JsiSkConverters.h" #include "JsiSkNativeObjects.h" #include "JsiSkPoint.h" #include "JsiSkRect.h" @@ -153,84 +160,64 @@ class JsiSkSkottie static constexpr const char *CLASS_NAME = "Skottie"; // #region Properties - JSI_HOST_FUNCTION(duration) { + double duration() { return static_cast(getObject()->_animation->duration()); } - JSI_HOST_FUNCTION(fps) { - return static_cast(getObject()->_animation->fps()); - } + double fps() { return static_cast(getObject()->_animation->fps()); } // #endregion // #region Methods - JSI_HOST_FUNCTION(seekFrame) { + void seekFrame(double frame, + std::optional> rectParam) { sksg::InvalidationController ic; - getObject()->_animation->seekFrame(arguments[0].asNumber(), &ic); + getObject()->_animation->seekFrame(frame, &ic); auto bounds = ic.bounds(); - if (count >= 2) { - auto rect = JsiSkRect::fromValue(runtime, arguments[1]); - if (rect != nullptr) { - rect->setXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()); - } + if (rectParam.has_value() && *rectParam != nullptr) { + auto rect = *rectParam; + rect->setXYWH(bounds.x(), bounds.y(), bounds.width(), bounds.height()); } - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(size) { - auto size = getObject()->_animation->size(); - jsi::Object jsiSize(runtime); - jsiSize.setProperty(runtime, "width", size.width()); - jsiSize.setProperty(runtime, "height", size.height()); - return jsiSize; - } + SkSize size() { return getObject()->_animation->size(); } - JSI_HOST_FUNCTION(render) { - auto canvas = getJsiObject(runtime, arguments[0])->getCanvas(); - if (count > 1) { - auto rect = JsiSkRect::fromValue(runtime, arguments[1]); - getObject()->_animation->render(canvas, rect.get()); + void render(std::shared_ptr jsiCanvas, + std::optional> rect) { + auto canvas = jsiCanvas->getCanvas(); + if (rect.has_value()) { + getObject()->_animation->render(canvas, rect->get()); } else { getObject()->_animation->render(canvas); } - - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(version) { - return jsi::String::createFromUtf8( - runtime, getObject()->_animation->version().c_str()); + std::string version() { + return std::string(getObject()->_animation->version().c_str()); } - JSI_HOST_FUNCTION(setColor) { - if (count < 2) { - return jsi::Value(false); + bool setColor(JsiOptional key, JsiOptional color) { + if (!key.has_value() || !color.has_value()) { + return false; } - auto key = arguments[0].asString(runtime).utf8(runtime); - auto color = JsiSkColor::fromValue(runtime, arguments[1]); - return getObject()->_propManager->setColor(key, color); + return getObject()->_propManager->setColor(*key, *color); } - JSI_HOST_FUNCTION(setOpacity) { - if (count < 2) { - return jsi::Value(false); + bool setOpacity(JsiOptional key, JsiOptional opacity) { + if (!key.has_value() || !opacity.has_value()) { + return false; } - - auto key = arguments[0].asString(runtime).utf8(runtime); - auto opacity = arguments[1].asNumber(); - return getObject()->_propManager->setOpacity(key, opacity); + return getObject()->_propManager->setOpacity(*key, *opacity); } - JSI_HOST_FUNCTION(setText) { - if (count < 3) { - return jsi::Value(false); + bool setText(JsiOptional key, JsiOptional text, + JsiOptional size) { + if (!key.has_value() || !text.has_value() || !size.has_value()) { + return false; } - auto key = arguments[0].asString(runtime).utf8(runtime); - auto text = arguments[1].asString(runtime).utf8(runtime); - auto size = arguments[2].asNumber(); // preserve all other text fields - auto t = getObject()->_propManager->getText(key); - t.fText = SkString(text); - t.fTextSize = size; - return getObject()->_propManager->setText(key, t); + auto t = getObject()->_propManager->getText(*key); + t.fText = SkString(*text); + t.fTextSize = *size; + return getObject()->_propManager->setText(*key, t); } JSI_HOST_FUNCTION(getTextProps) { @@ -251,27 +238,24 @@ class JsiSkSkottie return props; } - JSI_HOST_FUNCTION(setTransform) { - if (count < 7) { - return jsi::Value(false); + bool setTransform(JsiOptional key, JsiOptional anchor, + JsiOptional position, JsiOptional scale, + JsiOptional rotation, JsiOptional skew, + JsiOptional skewAxis) { + if (!key.has_value() || !anchor.has_value() || !position.has_value() || + !scale.has_value() || !rotation.has_value() || !skew.has_value() || + !skewAxis.has_value()) { + return false; } - auto key = arguments[0].asString(runtime).utf8(runtime); - auto anchor = JsiSkPoint::fromValue(runtime, arguments[1]); - auto position = JsiSkPoint::fromValue(runtime, arguments[2]); - auto scale = JsiSkPoint::fromValue(runtime, arguments[3]); - auto rotation = arguments[4].asNumber(); - auto skew = arguments[5].asNumber(); - auto skewAxis = arguments[6].asNumber(); - skottie::TransformPropertyValue transform; transform.fAnchorPoint = {anchor->x(), anchor->y()}; transform.fPosition = {position->x(), position->y()}; transform.fScale = {scale->x(), scale->y()}; - transform.fRotation = rotation; - transform.fSkew = skew; - transform.fSkewAxis = skewAxis; - return getObject()->_propManager->setTransform(key, transform); + transform.fRotation = *rotation; + transform.fSkew = *skew; + transform.fSkewAxis = *skewAxis; + return getObject()->_propManager->setTransform(*key, transform); } JSI_HOST_FUNCTION(getSlotInfo) { @@ -325,52 +309,47 @@ class JsiSkSkottie return slotInfoJS; } - JSI_HOST_FUNCTION(setColorSlot) { - if (count < 2) { - return jsi::Value(false); + bool setColorSlot(JsiOptional slotID, + JsiOptional color) { + if (!slotID.has_value() || !color.has_value()) { + return false; } - auto slotID = arguments[0].asString(runtime).utf8(runtime); - auto color = JsiSkColor::fromValue(runtime, arguments[1]); - return getObject()->_slotManager->setColorSlot(SkString(slotID), color); + return getObject()->_slotManager->setColorSlot(SkString(*slotID), *color); } - JSI_HOST_FUNCTION(setScalarSlot) { - if (count < 2) { - return jsi::Value(false); + bool setScalarSlot(JsiOptional slotID, + JsiOptional scalar) { + if (!slotID.has_value() || !scalar.has_value()) { + return false; } - auto slotID = arguments[0].asString(runtime).utf8(runtime); - auto scalar = arguments[1].asNumber(); - return getObject()->_slotManager->setScalarSlot(SkString(slotID), scalar); + return getObject()->_slotManager->setScalarSlot(SkString(*slotID), + *scalar); } - JSI_HOST_FUNCTION(setVec2Slot) { - if (count < 2) { - return jsi::Value(false); + bool setVec2Slot(JsiOptional slotID, + JsiOptional point) { + if (!slotID.has_value() || !point.has_value()) { + return false; } - auto slotID = arguments[0].asString(runtime).utf8(runtime); - auto point = JsiSkPoint::fromValue(runtime, arguments[1]); SkV2 vec2{point->x(), point->y()}; - return getObject()->_slotManager->setVec2Slot(SkString(slotID), vec2); + return getObject()->_slotManager->setVec2Slot(SkString(*slotID), vec2); } - JSI_HOST_FUNCTION(setTextSlot) { - if (count < 2) { - return jsi::Value(false); - } - auto key = arguments[0].asString(runtime).utf8(runtime); + // The text value argument is intentionally not declared: the raw binding + // never read it (the method is not implemented yet). + bool setTextSlot(JsiOptional key) { // TODO: Implement proper text slot setting - return jsi::Value(false); + return false; } - JSI_HOST_FUNCTION(setImageSlot) { - if (count < 2) { - return jsi::Value(false); + bool setImageSlot(JsiOptional slotID, + JsiOptional assetName) { + if (!slotID.has_value() || !assetName.has_value()) { + return false; } - auto slotID = arguments[0].asString(runtime).utf8(runtime); - auto assetName = arguments[1].asString(runtime).utf8(runtime); return getObject()->_slotManager->setImageSlot( - SkString(slotID), getObject()->_resourceProvider->loadImageAsset( - nullptr, assetName.data(), nullptr)); + SkString(*slotID), getObject()->_resourceProvider->loadImageAsset( + nullptr, assetName->data(), nullptr)); } JSI_HOST_FUNCTION(getColorSlot) { @@ -384,15 +363,15 @@ class JsiSkSkottie return jsi::Value::null(); } - JSI_HOST_FUNCTION(getScalarSlot) { - if (count < 1) { - return jsi::Value::null(); + std::variant + getScalarSlot(JsiOptional slotID) { + if (!slotID.has_value()) { + return nullptr; } - auto slotID = arguments[0].asString(runtime).utf8(runtime); - if (auto v = getObject()->_slotManager->getScalarSlot(SkString(slotID))) { - return jsi::Value(v.value()); + if (auto v = getObject()->_slotManager->getScalarSlot(SkString(*slotID))) { + return static_cast(v.value()); } - return jsi::Value::null(); + return nullptr; } JSI_HOST_FUNCTION(getVec2Slot) { @@ -551,29 +530,28 @@ class JsiSkSkottie static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "duration", &JsiSkSkottie::duration); - installHostMethod(runtime, prototype, "fps", &JsiSkSkottie::fps); - installHostMethod(runtime, prototype, "seekFrame", - &JsiSkSkottie::seekFrame); - installHostMethod(runtime, prototype, "render", &JsiSkSkottie::render); - installHostMethod(runtime, prototype, "size", &JsiSkSkottie::size); - installHostMethod(runtime, prototype, "version", &JsiSkSkottie::version); + installMethod(runtime, prototype, "duration", &JsiSkSkottie::duration); + installMethod(runtime, prototype, "fps", &JsiSkSkottie::fps); + installMethod(runtime, prototype, "seekFrame", &JsiSkSkottie::seekFrame); + installMethod(runtime, prototype, "render", &JsiSkSkottie::render); + installMethod(runtime, prototype, "size", &JsiSkSkottie::size); + installMethod(runtime, prototype, "version", &JsiSkSkottie::version); installHostMethod(runtime, prototype, "getSlotInfo", &JsiSkSkottie::getSlotInfo); - installHostMethod(runtime, prototype, "setColorSlot", - &JsiSkSkottie::setColorSlot); - installHostMethod(runtime, prototype, "setScalarSlot", - &JsiSkSkottie::setScalarSlot); - installHostMethod(runtime, prototype, "setVec2Slot", - &JsiSkSkottie::setVec2Slot); - installHostMethod(runtime, prototype, "setTextSlot", - &JsiSkSkottie::setTextSlot); - installHostMethod(runtime, prototype, "setImageSlot", - &JsiSkSkottie::setImageSlot); + installMethod(runtime, prototype, "setColorSlot", + &JsiSkSkottie::setColorSlot); + installMethod(runtime, prototype, "setScalarSlot", + &JsiSkSkottie::setScalarSlot); + installMethod(runtime, prototype, "setVec2Slot", + &JsiSkSkottie::setVec2Slot); + installMethod(runtime, prototype, "setTextSlot", + &JsiSkSkottie::setTextSlot); + installMethod(runtime, prototype, "setImageSlot", + &JsiSkSkottie::setImageSlot); installHostMethod(runtime, prototype, "getColorSlot", &JsiSkSkottie::getColorSlot); - installHostMethod(runtime, prototype, "getScalarSlot", - &JsiSkSkottie::getScalarSlot); + installMethod(runtime, prototype, "getScalarSlot", + &JsiSkSkottie::getScalarSlot); installHostMethod(runtime, prototype, "getVec2Slot", &JsiSkSkottie::getVec2Slot); installHostMethod(runtime, prototype, "getTextSlot", @@ -586,8 +564,8 @@ class JsiSkSkottie &JsiSkSkottie::getTransformProps); installHostMethod(runtime, prototype, "getTextProps", &JsiSkSkottie::getTextProps); - installHostMethod(runtime, prototype, "setColor", &JsiSkSkottie::setColor); - installHostMethod(runtime, prototype, "setText", &JsiSkSkottie::setText); + installMethod(runtime, prototype, "setColor", &JsiSkSkottie::setColor); + installMethod(runtime, prototype, "setText", &JsiSkSkottie::setText); } // #endregion diff --git a/packages/skia/cpp/api/JsiSkSurface.h b/packages/skia/cpp/api/JsiSkSurface.h index fe7211bc44..189af001b7 100644 --- a/packages/skia/cpp/api/JsiSkSurface.h +++ b/packages/skia/cpp/api/JsiSkSurface.h @@ -7,6 +7,7 @@ #include +#include "JsiSkConverters.h" #include "JsiSkDispatcher.h" #include "JsiSkNativeObjects.h" #include "JsiTextureInfo.h" @@ -67,27 +68,25 @@ class JsiSkSurface } // TODO-API: Properties? - JSI_HOST_FUNCTION(width) { return static_cast(getObject()->width()); } - JSI_HOST_FUNCTION(height) { - return static_cast(getObject()->height()); - } + double width() { return static_cast(getObject()->width()); } + double height() { return static_cast(getObject()->height()); } - JSI_HOST_FUNCTION(getCanvas) { + std::shared_ptr getCanvas() { auto surface = getObject(); auto canvas = std::make_shared(getContext(), surface->getCanvas()); // Keep a reference to the owning surface so the canvas can read pixels back // through a snapshot on Graphite (which lacks synchronous canvas readback). canvas->setSurface(surface); - return makeJsiObject(runtime, std::move(canvas)); + return canvas; } - JSI_HOST_FUNCTION(flush) { + void flush(JsiOptional syncParam) { auto surface = getObject(); // When `sync` is true, block until the GPU has finished executing the // submitted work. Required before a native consumer on a different command // queue reads this surface's texture via getNativeTextureUnstable(). #3916 - bool sync = count > 0 && arguments[0].isBool() && arguments[0].getBool(); + bool sync = syncParam.has_value() && *syncParam; #if defined(SK_GRAPHITE) // A raster surface (e.g. Skia.Surface.Make) has no Graphite recorder; // only Graphite-backed surfaces need to snap and submit a recording. @@ -102,7 +101,6 @@ class JsiSkSurface dContext->flushAndSubmit(sync ? GrSyncCpu::kYes : GrSyncCpu::kNo); } #endif - return jsi::Value::undefined(); } JSI_HOST_FUNCTION(makeImageSnapshot) { @@ -195,13 +193,12 @@ class JsiSkSurface static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "width", &JsiSkSurface::width); - installHostMethod(runtime, prototype, "height", &JsiSkSurface::height); - installHostMethod(runtime, prototype, "getCanvas", - &JsiSkSurface::getCanvas); + installMethod(runtime, prototype, "width", &JsiSkSurface::width); + installMethod(runtime, prototype, "height", &JsiSkSurface::height); + installMethod(runtime, prototype, "getCanvas", &JsiSkSurface::getCanvas); installHostMethod(runtime, prototype, "makeImageSnapshot", &JsiSkSurface::makeImageSnapshot); - installHostMethod(runtime, prototype, "flush", &JsiSkSurface::flush); + installMethod(runtime, prototype, "flush", &JsiSkSurface::flush); installHostMethod(runtime, prototype, "getNativeTextureUnstable", &JsiSkSurface::getNativeTextureUnstable); } diff --git a/packages/skia/cpp/api/JsiSkSurfaceFactory.h b/packages/skia/cpp/api/JsiSkSurfaceFactory.h index 28b7531094..7d84c9fa72 100644 --- a/packages/skia/cpp/api/JsiSkSurfaceFactory.h +++ b/packages/skia/cpp/api/JsiSkSurfaceFactory.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -24,16 +25,14 @@ class JsiSkSurfaceFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "SurfaceFactory"; - JSI_HOST_FUNCTION(Make) { - auto width = static_cast(arguments[0].asNumber()); - auto height = static_cast(arguments[1].asNumber()); + std::variant> Make(int width, + int height) { auto imageInfo = SkImageInfo::MakeN32Premul(width, height); auto surface = SkSurfaces::Raster(imageInfo); if (surface == nullptr) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(surface))); + return std::make_shared(getContext(), std::move(surface)); } JSI_HOST_FUNCTION(MakeOffscreen) { @@ -63,7 +62,7 @@ class JsiSkSurfaceFactory : public JsiSkNativeObject { size_t getMemoryPressure() override { return 2048; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "Make", &JsiSkSurfaceFactory::Make); + installMethod(runtime, prototype, "Make", &JsiSkSurfaceFactory::Make); installHostMethod(runtime, prototype, "MakeOffscreen", &JsiSkSurfaceFactory::MakeOffscreen); } diff --git a/packages/skia/cpp/api/JsiSkTextBlobFactory.h b/packages/skia/cpp/api/JsiSkTextBlobFactory.h index 44d4abdc28..05434943d9 100644 --- a/packages/skia/cpp/api/JsiSkTextBlobFactory.h +++ b/packages/skia/cpp/api/JsiSkTextBlobFactory.h @@ -1,11 +1,13 @@ #pragma once #include +#include #include #include #include +#include "JsiSkConverters.h" #include "JsiSkFont.h" #include "JsiSkNativeObjects.h" #include "JsiSkRSXform.h" @@ -26,88 +28,63 @@ class JsiSkTextBlobFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "TextBlobFactory"; - JSI_HOST_FUNCTION(MakeFromText) { - auto str = arguments[0].asString(runtime).utf8(runtime); - auto font = JsiSkFont::fromValue(runtime, arguments[1]); + std::shared_ptr MakeFromText(std::string str, + std::shared_ptr font) { auto textBlob = SkTextBlob::MakeFromString(str.c_str(), *font); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(textBlob))); + return std::make_shared(getContext(), std::move(textBlob)); } - JSI_HOST_FUNCTION(MakeFromGlyphs) { - auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); - auto font = JsiSkFont::fromValue(runtime, arguments[1]); + std::shared_ptr MakeFromGlyphs(std::vector glyphIds, + std::shared_ptr font) { int bytesPerGlyph = 2; std::vector glyphs; - int glyphsSize = static_cast(jsiGlyphs.size(runtime)); - glyphs.reserve(glyphsSize); - for (int i = 0; i < glyphsSize; i++) { - glyphs.push_back(jsiGlyphs.getValueAtIndex(runtime, i).asNumber()); + glyphs.reserve(glyphIds.size()); + for (auto glyph : glyphIds) { + glyphs.push_back(static_cast(glyph)); } auto textBlob = SkTextBlob::MakeFromText(glyphs.data(), glyphs.size() * bytesPerGlyph, *font, SkTextEncoding::kGlyphID); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(textBlob))); + return std::make_shared(getContext(), std::move(textBlob)); } - JSI_HOST_FUNCTION(MakeFromRSXform) { - auto str = arguments[0].asString(runtime).utf8(runtime); - auto jsiRsxforms = arguments[1].asObject(runtime).asArray(runtime); - auto font = JsiSkFont::fromValue(runtime, arguments[2]); - std::vector rsxforms; - int rsxformsSize = static_cast(jsiRsxforms.size(runtime)); - rsxforms.reserve(rsxformsSize); - for (int i = 0; i < rsxformsSize; i++) { - auto rsxform = JsiSkRSXform::fromValue( - runtime, jsiRsxforms.getValueAtIndex(runtime, i)); - rsxforms.push_back(*rsxform); - } + std::shared_ptr + MakeFromRSXform(std::string str, std::vector rsxforms, + std::shared_ptr font) { auto x = SkSpan(rsxforms.data(), rsxforms.size()); auto textBlob = SkTextBlob::MakeFromRSXform(str.c_str(), str.length(), x, *font); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(textBlob))); + return std::make_shared(getContext(), std::move(textBlob)); } - JSI_HOST_FUNCTION(MakeFromRSXformGlyphs) { - auto jsiGlyphs = arguments[0].asObject(runtime).asArray(runtime); - auto jsiRsxforms = arguments[1].asObject(runtime).asArray(runtime); - auto font = JsiSkFont::fromValue(runtime, arguments[2]); + std::shared_ptr + MakeFromRSXformGlyphs(std::vector glyphIds, + std::vector rsxforms, + std::shared_ptr font) { int bytesPerGlyph = 2; std::vector glyphs; - int glyphsSize = static_cast(jsiGlyphs.size(runtime)); - glyphs.reserve(glyphsSize); - for (int i = 0; i < glyphsSize; i++) { - glyphs.push_back(jsiGlyphs.getValueAtIndex(runtime, i).asNumber()); - } - std::vector rsxforms; - int rsxformsSize = static_cast(jsiRsxforms.size(runtime)); - rsxforms.reserve(rsxformsSize); - for (int i = 0; i < rsxformsSize; i++) { - auto rsxform = JsiSkRSXform::fromValue( - runtime, jsiRsxforms.getValueAtIndex(runtime, i)); - rsxforms.push_back(*rsxform); + glyphs.reserve(glyphIds.size()); + for (auto glyph : glyphIds) { + glyphs.push_back(static_cast(glyph)); } auto x = SkSpan(rsxforms.data(), rsxforms.size()); auto textBlob = SkTextBlob::MakeFromRSXform( glyphs.data(), glyphs.size() * bytesPerGlyph, x, *font, SkTextEncoding::kGlyphID); - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(textBlob))); + return std::make_shared(getContext(), std::move(textBlob)); } size_t getMemoryPressure() override { return 2048; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeFromText", - &JsiSkTextBlobFactory::MakeFromText); - installHostMethod(runtime, prototype, "MakeFromGlyphs", - &JsiSkTextBlobFactory::MakeFromGlyphs); - installHostMethod(runtime, prototype, "MakeFromRSXform", - &JsiSkTextBlobFactory::MakeFromRSXform); - installHostMethod(runtime, prototype, "MakeFromRSXformGlyphs", - &JsiSkTextBlobFactory::MakeFromRSXformGlyphs); + installMethod(runtime, prototype, "MakeFromText", + &JsiSkTextBlobFactory::MakeFromText); + installMethod(runtime, prototype, "MakeFromGlyphs", + &JsiSkTextBlobFactory::MakeFromGlyphs); + installMethod(runtime, prototype, "MakeFromRSXform", + &JsiSkTextBlobFactory::MakeFromRSXform); + installMethod(runtime, prototype, "MakeFromRSXformGlyphs", + &JsiSkTextBlobFactory::MakeFromRSXformGlyphs); } explicit JsiSkTextBlobFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkTypeface.h b/packages/skia/cpp/api/JsiSkTypeface.h index 667c978fd1..64bf9df6da 100644 --- a/packages/skia/cpp/api/JsiSkTypeface.h +++ b/packages/skia/cpp/api/JsiSkTypeface.h @@ -1,11 +1,13 @@ #pragma once #include +#include #include #include #include +#include "JsiSkConverters.h" #include "JsiSkNativeObjects.h" #include "utils/RNSkLog.h" @@ -32,11 +34,10 @@ class JsiSkTypeface : JsiSkWrappingSkPtrNativeObject( std::move(context), std::move(typeface)) {} - JSI_HOST_FUNCTION(getGlyphIDs) { - auto str = arguments[0].asString(runtime).utf8(runtime); + std::vector getGlyphIDs(std::string str, JsiOptional numGlyphs) { int numGlyphIDs = - count > 1 && !arguments[1].isNull() && !arguments[1].isUndefined() - ? static_cast(arguments[1].asNumber()) + numGlyphs.has_value() + ? *numGlyphs : getObject()->textToGlyphs(str.c_str(), str.length(), SkTextEncoding::kUTF8, SkSpan(nullptr, 0)); @@ -45,12 +46,7 @@ class JsiSkTypeface getObject()->textToGlyphs( str.c_str(), str.length(), SkTextEncoding::kUTF8, SkSpan(static_cast(glyphIDs.data()), numGlyphIDs)); - auto jsiGlyphIDs = jsi::Array(runtime, numGlyphIDs); - for (int i = 0; i < numGlyphIDs; i++) { - jsiGlyphIDs.setValueAtIndex(runtime, i, - jsi::Value(static_cast(glyphIDs[i]))); - } - return jsiGlyphIDs; + return std::vector(glyphIDs.begin(), glyphIDs.end()); } size_t getMemoryPressure() override { @@ -85,8 +81,8 @@ class JsiSkTypeface static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "getGlyphIDs", - &JsiSkTypeface::getGlyphIDs); + installMethod(runtime, prototype, "getGlyphIDs", + &JsiSkTypeface::getGlyphIDs); } }; diff --git a/packages/skia/cpp/api/JsiSkTypefaceFactory.h b/packages/skia/cpp/api/JsiSkTypefaceFactory.h index d5d130a6d9..f5c3624b6e 100644 --- a/packages/skia/cpp/api/JsiSkTypefaceFactory.h +++ b/packages/skia/cpp/api/JsiSkTypefaceFactory.h @@ -2,10 +2,13 @@ #include #include +#include #include +#include "JsiSkConverters.h" #include "JsiSkData.h" +#include "JsiSkFontMgrFactory.h" #include "JsiSkNativeObjects.h" #include "JsiSkTypeface.h" @@ -17,22 +20,21 @@ class JsiSkTypefaceFactory : public JsiSkNativeObject { public: static constexpr const char *CLASS_NAME = "TypefaceFactory"; - JSI_HOST_FUNCTION(MakeFreeTypeFaceFromData) { - auto data = JsiSkData::fromValue(runtime, arguments[0]); + std::variant> + MakeFreeTypeFaceFromData(sk_sp data) { auto fontMgr = JsiSkFontMgrFactory::getFontMgr(getContext()); auto typeface = fontMgr->makeFromData(std::move(data)); if (typeface == nullptr) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(typeface))); + return std::make_shared(getContext(), std::move(typeface)); } size_t getMemoryPressure() override { return 1024; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "MakeFreeTypeFaceFromData", - &JsiSkTypefaceFactory::MakeFreeTypeFaceFromData); + installMethod(runtime, prototype, "MakeFreeTypeFaceFromData", + &JsiSkTypefaceFactory::MakeFreeTypeFaceFromData); } explicit JsiSkTypefaceFactory(std::shared_ptr context) diff --git a/packages/skia/cpp/api/JsiSkTypefaceFontProvider.h b/packages/skia/cpp/api/JsiSkTypefaceFontProvider.h index 8174182fb3..01a8f2cccd 100644 --- a/packages/skia/cpp/api/JsiSkTypefaceFontProvider.h +++ b/packages/skia/cpp/api/JsiSkTypefaceFontProvider.h @@ -1,10 +1,13 @@ #pragma once #include +#include +#include #include #include +#include "JsiSkConverters.h" #include "JsiSkFontStyle.h" #include "JsiSkNativeObjects.h" #include "JsiSkTypeface.h" @@ -30,18 +33,16 @@ class JsiSkTypefaceFontProvider public: static constexpr const char *CLASS_NAME = "TypefaceFontProvider"; - JSI_HOST_FUNCTION(registerFont) { - sk_sp typeface = - JsiSkTypeface::fromValue(runtime, arguments[0]); - SkString familyName(arguments[1].asString(runtime).utf8(runtime).c_str()); + void registerFont(sk_sp typeface, std::string familyNameStr) { + SkString familyName(familyNameStr.c_str()); getObject()->registerTypeface(typeface, familyName); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(matchFamilyStyle) { - auto name = count > 0 ? arguments[0].asString(runtime).utf8(runtime) : ""; - auto fontStyle = - count > 1 ? JsiSkFontStyle::fromValue(runtime, arguments[1]) : nullptr; + std::shared_ptr + matchFamilyStyle(std::optional nameParam, + std::optional> fontStyleParam) { + auto name = nameParam.value_or(""); + auto fontStyle = fontStyleParam.value_or(nullptr); if (name == "" || fontStyle == nullptr) { throw std::runtime_error("matchFamilyStyle requires a name and a style"); } @@ -53,17 +54,15 @@ class JsiSkTypefaceFontProvider if (!typeface) { throw std::runtime_error("Could not find font style for " + name); } - return makeJsiObject(runtime, std::make_shared( - getContext(), std::move(typeface))); + return std::make_shared(getContext(), std::move(typeface)); } - JSI_HOST_FUNCTION(countFamilies) { return getObject()->countFamilies(); } + int countFamilies() { return getObject()->countFamilies(); } - JSI_HOST_FUNCTION(getFamilyName) { - auto i = static_cast(arguments[0].asNumber()); + std::string getFamilyName(int i) { SkString name; getObject()->getFamilyName(i, &name); - return jsi::String::createFromUtf8(runtime, name.c_str()); + return std::string(name.c_str()); } JsiSkTypefaceFontProvider(std::shared_ptr context, @@ -92,14 +91,14 @@ class JsiSkTypefaceFontProvider static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "registerFont", - &JsiSkTypefaceFontProvider::registerFont); - installHostMethod(runtime, prototype, "matchFamilyStyle", - &JsiSkTypefaceFontProvider::matchFamilyStyle); - installHostMethod(runtime, prototype, "countFamilies", - &JsiSkTypefaceFontProvider::countFamilies); - installHostMethod(runtime, prototype, "getFamilyName", - &JsiSkTypefaceFontProvider::getFamilyName); + installMethod(runtime, prototype, "registerFont", + &JsiSkTypefaceFontProvider::registerFont); + installMethod(runtime, prototype, "matchFamilyStyle", + &JsiSkTypefaceFontProvider::matchFamilyStyle); + installMethod(runtime, prototype, "countFamilies", + &JsiSkTypefaceFontProvider::countFamilies); + installMethod(runtime, prototype, "getFamilyName", + &JsiSkTypefaceFontProvider::getFamilyName); } }; diff --git a/packages/skia/cpp/api/JsiSkTypefaceFontProviderFactory.h b/packages/skia/cpp/api/JsiSkTypefaceFontProviderFactory.h index d2a7713676..2b455e6ea3 100644 --- a/packages/skia/cpp/api/JsiSkTypefaceFontProviderFactory.h +++ b/packages/skia/cpp/api/JsiSkTypefaceFontProviderFactory.h @@ -19,17 +19,16 @@ class JsiSkTypefaceFontProviderFactory public: static constexpr const char *CLASS_NAME = "TypefaceFontProviderFactory"; - JSI_HOST_FUNCTION(Make) { - return makeJsiObject( - runtime, std::make_shared( - getContext(), sk_make_sp())); + std::shared_ptr Make() { + return std::make_shared( + getContext(), sk_make_sp()); } size_t getMemoryPressure() override { return 2048; } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { - installHostMethod(runtime, prototype, "Make", - &JsiSkTypefaceFontProviderFactory::Make); + installMethod(runtime, prototype, "Make", + &JsiSkTypefaceFontProviderFactory::Make); } explicit JsiSkTypefaceFontProviderFactory( diff --git a/packages/skia/cpp/api/JsiSkVertices.h b/packages/skia/cpp/api/JsiSkVertices.h index 43366edb13..3d6abda72d 100644 --- a/packages/skia/cpp/api/JsiSkVertices.h +++ b/packages/skia/cpp/api/JsiSkVertices.h @@ -6,6 +6,7 @@ #include #include "JsiSkNativeObjects.h" +#include "JsiSkRect.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -28,15 +29,12 @@ class JsiSkVertices : JsiSkWrappingSkPtrNativeObject( std::move(context), std::move(vertices)) {} - JSI_HOST_FUNCTION(bounds) { + std::shared_ptr bounds() { const auto &result = getObject()->bounds(); - return makeJsiObject(runtime, - std::make_shared(getContext(), result)); + return std::make_shared(getContext(), result); } - JSI_HOST_FUNCTION(uniqueID) { - return static_cast(getObject()->uniqueID()); - } + double uniqueID() { return static_cast(getObject()->uniqueID()); } size_t getMemoryPressure() override { auto vertices = getObject(); @@ -54,8 +52,8 @@ class JsiSkVertices static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "bounds", &JsiSkVertices::bounds); - installHostMethod(runtime, prototype, "uniqueID", &JsiSkVertices::uniqueID); + installMethod(runtime, prototype, "bounds", &JsiSkVertices::bounds); + installMethod(runtime, prototype, "uniqueID", &JsiSkVertices::uniqueID); } /** diff --git a/packages/skia/cpp/api/JsiVideo.h b/packages/skia/cpp/api/JsiVideo.h index 896300d5c2..83b056e915 100644 --- a/packages/skia/cpp/api/JsiVideo.h +++ b/packages/skia/cpp/api/JsiVideo.h @@ -1,29 +1,17 @@ #pragma once #include -#include #include -#include +#include #include "JsiSkNativeObjects.h" -#include "utils/RNSkLog.h" #include -#include "JsiSkPaint.h" -#include "JsiSkPoint.h" -#include "JsiSkRect.h" -#include "JsiSkTypeface.h" +#include "JsiSkConverters.h" +#include "JsiSkImage.h" #include "rnskia/RNSkVideo.h" -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdocumentation" - -#include "include/core/SkFont.h" -#include "include/core/SkFontMetrics.h" - -#pragma clang diagnostic pop - namespace RNSkia { namespace jsi = facebook::jsi; @@ -33,83 +21,55 @@ class JsiVideo public: static constexpr const char *CLASS_NAME = "Video"; - JSI_HOST_FUNCTION(nextImage) { + std::variant> nextImage() { double timestamp = 0; - auto video = getObject(); - auto image = video->nextImage(×tamp); + auto image = getObject()->nextImage(×tamp); if (!image) { - return jsi::Value::null(); + return nullptr; } - return makeJsiObject( - runtime, std::make_shared(getContext(), std::move(image))); + return std::make_shared(getContext(), std::move(image)); } - JSI_HOST_FUNCTION(duration) { return getObject()->duration(); } + double duration() { return getObject()->duration(); } - JSI_HOST_FUNCTION(framerate) { return getObject()->framerate(); } + double framerate() { return getObject()->framerate(); } - JSI_HOST_FUNCTION(currentTime) { return getObject()->currentTime(); } + double currentTime() { return getObject()->currentTime(); } - JSI_HOST_FUNCTION(isPlaying) { return getObject()->isPlaying(); } + bool isPlaying() { return getObject()->isPlaying(); } - JSI_HOST_FUNCTION(seek) { - double timestamp = arguments[0].asNumber(); - getObject()->seek(timestamp); - return jsi::Value::undefined(); - } + void seek(double timestamp) { getObject()->seek(timestamp); } - JSI_HOST_FUNCTION(rotation) { - auto context = getContext(); - auto rot = getObject()->getRotationInDegrees(); - return jsi::Value(static_cast(rot)); + double rotation() { + return static_cast(getObject()->getRotationInDegrees()); } - JSI_HOST_FUNCTION(size) { - auto context = getContext(); - auto size = getObject()->getSize(); - auto result = jsi::Object(runtime); - result.setProperty(runtime, "width", static_cast(size.width())); - result.setProperty(runtime, "height", static_cast(size.height())); - return result; - } + SkISize size() { return getObject()->getSize(); } - JSI_HOST_FUNCTION(play) { - getObject()->play(); - return jsi::Value::undefined(); - } + void play() { getObject()->play(); } - JSI_HOST_FUNCTION(pause) { - getObject()->pause(); - return jsi::Value::undefined(); - } + void pause() { getObject()->pause(); } - JSI_HOST_FUNCTION(setVolume) { - auto volume = arguments[0].asNumber(); + void setVolume(double volume) { getObject()->setVolume(static_cast(volume)); - return jsi::Value::undefined(); } - JSI_HOST_FUNCTION(setLooping) { - auto looping = arguments[0].asBool(); - getObject()->setLooping(looping); - return jsi::Value::undefined(); - } + void setLooping(bool looping) { getObject()->setLooping(looping); } static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) { installCommon(runtime, prototype); - installHostMethod(runtime, prototype, "nextImage", &JsiVideo::nextImage); - installHostMethod(runtime, prototype, "duration", &JsiVideo::duration); - installHostMethod(runtime, prototype, "framerate", &JsiVideo::framerate); - installHostMethod(runtime, prototype, "currentTime", - &JsiVideo::currentTime); - installHostMethod(runtime, prototype, "isPlaying", &JsiVideo::isPlaying); - installHostMethod(runtime, prototype, "seek", &JsiVideo::seek); - installHostMethod(runtime, prototype, "rotation", &JsiVideo::rotation); - installHostMethod(runtime, prototype, "size", &JsiVideo::size); - installHostMethod(runtime, prototype, "play", &JsiVideo::play); - installHostMethod(runtime, prototype, "pause", &JsiVideo::pause); - installHostMethod(runtime, prototype, "setVolume", &JsiVideo::setVolume); - installHostMethod(runtime, prototype, "setLooping", &JsiVideo::setLooping); + installMethod(runtime, prototype, "nextImage", &JsiVideo::nextImage); + installMethod(runtime, prototype, "duration", &JsiVideo::duration); + installMethod(runtime, prototype, "framerate", &JsiVideo::framerate); + installMethod(runtime, prototype, "currentTime", &JsiVideo::currentTime); + installMethod(runtime, prototype, "isPlaying", &JsiVideo::isPlaying); + installMethod(runtime, prototype, "seek", &JsiVideo::seek); + installMethod(runtime, prototype, "rotation", &JsiVideo::rotation); + installMethod(runtime, prototype, "size", &JsiVideo::size); + installMethod(runtime, prototype, "play", &JsiVideo::play); + installMethod(runtime, prototype, "pause", &JsiVideo::pause); + installMethod(runtime, prototype, "setVolume", &JsiVideo::setVolume); + installMethod(runtime, prototype, "setLooping", &JsiVideo::setLooping); } JsiVideo(std::shared_ptr context, diff --git a/packages/skia/cpp/jsi/NativeObject.h b/packages/skia/cpp/jsi/NativeObject.h index a2f8b8b536..b3f5726ede 100644 --- a/packages/skia/cpp/jsi/NativeObject.h +++ b/packages/skia/cpp/jsi/NativeObject.h @@ -392,6 +392,11 @@ class NativeObject : public jsi::NativeState, /** * Install a method on the prototype. + * + * The installers below resolve `this` with NativeObject::fromValue + * (explicitly qualified): derived classes may shadow fromValue with a + * public static of the same name that returns the wrapped inner object + * (the RNSkia wrappers do), which must not be picked up here. */ template static void installMethod(jsi::Runtime &runtime, jsi::Object &prototype, @@ -401,7 +406,7 @@ class NativeObject : public jsi::NativeState, runtime, jsi::PropNameID::forUtf8(runtime, name), sizeof...(Args), [method](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) -> jsi::Value { - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); return callMethod(native.get(), method, rt, args, std::index_sequence_for{}, count); }); @@ -421,7 +426,7 @@ class NativeObject : public jsi::NativeState, runtime, jsi::PropNameID::forUtf8(runtime, name), sizeof...(Args), [method](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) -> jsi::Value { - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); return callMethodWithRuntime(native.get(), method, rt, args, std::index_sequence_for{}, count); @@ -441,7 +446,7 @@ class NativeObject : public jsi::NativeState, 0, [getter](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) -> jsi::Value { - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); if constexpr (std::is_same_v) { (native.get()->*getter)(); return jsi::Value::undefined(); @@ -481,7 +486,7 @@ class NativeObject : public jsi::NativeState, if (count < 1) { throw jsi::JSError(rt, "Setter requires a value argument"); } - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); auto value = rnwgpu::JSIConverter>::fromJSI( rt, args[0], false); (native.get()->*setter)(std::move(value)); @@ -528,7 +533,7 @@ class NativeObject : public jsi::NativeState, 0, [getter](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) -> jsi::Value { - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); ReturnType result = (native.get()->*getter)(); return rnwgpu::JSIConverter>::toJSI( rt, std::move(result)); @@ -542,7 +547,7 @@ class NativeObject : public jsi::NativeState, if (count < 1) { throw jsi::JSError(rt, "Setter requires a value argument"); } - auto native = Derived::fromValue(rt, thisVal); + auto native = NativeObject::fromValue(rt, thisVal); auto value = rnwgpu::JSIConverter>::fromJSI( rt, args[0], false); (native.get()->*setter)(std::move(value));