// // DrawableFrameHostObject.mm // VisionCamera // // Created by Marc Rousavy on 20.07.23. // Copyright © 2023 mrousavy. All rights reserved. // #import "DrawableFrameHostObject.h" #import "SkCanvas.h" #import "SkImageHelpers.h" std::vector DrawableFrameHostObject::getPropertyNames(jsi::Runtime& rt) { auto result = FrameHostObject::getPropertyNames(rt); // Skia - Render Frame result.push_back(jsi::PropNameID::forUtf8(rt, std::string("render"))); if (_canvas != nullptr) { auto canvasPropNames = _canvas->getPropertyNames(rt); for (auto& prop : canvasPropNames) { result.push_back(std::move(prop)); } } return result; } SkRect inscribe(SkSize size, SkRect rect) { auto halfWidthDelta = (rect.width() - size.width()) / 2.0; auto halfHeightDelta = (rect.height() - size.height()) / 2.0; return SkRect::MakeXYWH(rect.x() + halfWidthDelta, rect.y() + halfHeightDelta, size.width(), size.height()); } jsi::Value DrawableFrameHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) { auto name = propName.utf8(runtime); if (name == "render") { auto render = JSI_HOST_FUNCTION_LAMBDA { if (_canvas == nullptr) { throw jsi::JSError(runtime, "Trying to render a Frame without a Skia Canvas! Did you install Skia?"); } // convert CMSampleBuffer to SkImage auto context = _canvas->getCanvas()->recordingContext(); auto image = SkImageHelpers::convertCMSampleBufferToSkImage(context, frame.buffer); // draw SkImage if (count > 0) { // ..with paint/shader auto paintHostObject = arguments[0].asObject(runtime).asHostObject(runtime); auto paint = paintHostObject->getObject(); _canvas->getCanvas()->drawImage(image, 0, 0, SkSamplingOptions(), paint.get()); } else { // ..without paint/shader _canvas->getCanvas()->drawImage(image, 0, 0); } return jsi::Value::undefined(); }; return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "render"), 1, render); } if (name == "isDrawable") { return jsi::Value(_canvas != nullptr); } if (_canvas != nullptr) { // If we have a Canvas, try to access the property on there. auto result = _canvas->get(runtime, propName); if (!result.isUndefined()) { return result; } } // fallback to base implementation return FrameHostObject::get(runtime, propName); } void DrawableFrameHostObject::invalidateCanvas() { _canvas = nullptr; }