1 #pragma once 2 3 #include <memory> 4 #include <utility> 5 6 #include <jsi/jsi.h> 7 8 #include "JsiPromises.h" 9 #include "JsiSkData.h" 10 #include "SkBase64.h" 11 12 namespace RNSkia { 13 14 namespace jsi = facebook::jsi; 15 16 class JsiSkDataFactory : public JsiSkHostObject { 17 public: JSI_HOST_FUNCTION(fromURI)18 JSI_HOST_FUNCTION(fromURI) { 19 auto jsiLocalUri = arguments[0].asString(runtime); 20 auto localUri = jsiLocalUri.utf8(runtime); 21 auto context = getContext(); 22 return RNJsi::JsiPromises::createPromiseAsJSIValue( 23 runtime, 24 [context = std::move(context), localUri = std::move(localUri)]( 25 jsi::Runtime &runtime, 26 std::shared_ptr<RNJsi::JsiPromises::Promise> promise) -> void { 27 // Create a stream operation - this will be run in a 28 // separate thread 29 context->performStreamOperation( 30 localUri, 31 [&runtime, context = std::move(context), 32 promise = std::move(promise)]( 33 std::unique_ptr<SkStreamAsset> stream) -> void { 34 // Schedule drawCallback on the Javascript thread 35 auto result = 36 SkData::MakeFromStream(stream.get(), stream->getLength()); 37 context->runOnJavascriptThread([&runtime, 38 context = std::move(context), 39 promise = std::move(promise), 40 result = std::move(result)]() { 41 promise->resolve(jsi::Object::createFromHostObject( 42 runtime, std::make_shared<JsiSkData>(std::move(context), 43 std::move(result)))); 44 }); 45 }); 46 }); 47 }; 48 JSI_HOST_FUNCTION(fromBytes)49 JSI_HOST_FUNCTION(fromBytes) { 50 auto array = arguments[0].asObject(runtime); 51 jsi::ArrayBuffer buffer = 52 array.getProperty(runtime, jsi::PropNameID::forAscii(runtime, "buffer")) 53 .asObject(runtime) 54 .getArrayBuffer(runtime); 55 56 auto data = 57 SkData::MakeWithCopy(buffer.data(runtime), buffer.size(runtime)); 58 return jsi::Object::createFromHostObject( 59 runtime, std::make_shared<JsiSkData>(getContext(), std::move(data))); 60 } 61 JSI_HOST_FUNCTION(fromBase64)62 JSI_HOST_FUNCTION(fromBase64) { 63 auto base64 = arguments[0].asString(runtime); 64 auto base64Str = base64.utf8(runtime); 65 auto size = base64Str.size(); 66 67 // Calculate length 68 size_t len; 69 auto err = 70 SkBase64::Decode(&base64.utf8(runtime).c_str()[0], size, nullptr, &len); 71 if (err != SkBase64::Error::kNoError) { 72 throw jsi::JSError(runtime, "Error decoding base64 string"); 73 return jsi::Value::undefined(); 74 } 75 76 // Create data object and decode 77 auto data = SkData::MakeUninitialized(len); 78 err = SkBase64::Decode(&base64.utf8(runtime).c_str()[0], size, 79 data->writable_data(), &len); 80 if (err != SkBase64::Error::kNoError) { 81 throw jsi::JSError(runtime, "Error decoding base64 string"); 82 return jsi::Value::undefined(); 83 } 84 85 return jsi::Object::createFromHostObject( 86 runtime, std::make_shared<JsiSkData>(getContext(), std::move(data))); 87 } 88 JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC (JsiSkDataFactory,fromURI),JSI_EXPORT_FUNC (JsiSkDataFactory,fromBytes),JSI_EXPORT_FUNC (JsiSkDataFactory,fromBase64))89 JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkDataFactory, fromURI), 90 JSI_EXPORT_FUNC(JsiSkDataFactory, fromBytes), 91 JSI_EXPORT_FUNC(JsiSkDataFactory, fromBase64)) 92 93 explicit JsiSkDataFactory(std::shared_ptr<RNSkPlatformContext> context) 94 : JsiSkHostObject(std::move(context)) {} 95 }; 96 97 } // namespace RNSkia 98