1 #pragma once 2 3 #include <memory> 4 #include <utility> 5 6 #include <jsi/jsi.h> 7 8 #include "JsiSkHostObjects.h" 9 #include "JsiSkPathEffect.h" 10 11 #pragma clang diagnostic push 12 #pragma clang diagnostic ignored "-Wdocumentation" 13 14 #include <SkPath.h> 15 #include <SkPathOps.h> 16 #include <RNSkLog.h> 17 18 #pragma clang diagnostic pop 19 20 namespace RNSkia { 21 22 using namespace facebook; 23 24 class JsiSkPathFactory : public JsiSkHostObject { 25 26 static const int MOVE = 0; 27 static const int LINE = 1; 28 static const int QUAD = 2; 29 static const int CONIC = 3; 30 static const int CUBIC = 4; 31 static const int CLOSE = 5; 32 33 public: JSI_HOST_FUNCTION(Make)34 JSI_HOST_FUNCTION(Make) { 35 return jsi::Object::createFromHostObject( 36 runtime, std::make_shared<JsiSkPath>(getContext(), SkPath())); 37 } 38 JSI_HOST_FUNCTION(MakeFromSVGString)39 JSI_HOST_FUNCTION(MakeFromSVGString) { 40 auto svgString = arguments[0].asString(runtime).utf8(runtime); 41 SkPath result; 42 43 if (!SkParsePath::FromSVGString(svgString.c_str(), &result)) { 44 throw jsi::JSError(runtime, "Could not parse Svg path"); 45 return jsi::Value(nullptr); 46 } 47 48 return jsi::Object::createFromHostObject( 49 runtime, std::make_shared<JsiSkPath>(getContext(), std::move(result))); 50 } 51 JSI_HOST_FUNCTION(MakeFromOp)52 JSI_HOST_FUNCTION(MakeFromOp) { 53 SkPath one = *JsiSkPath::fromValue(runtime, arguments[0]).get(); 54 SkPath two = *JsiSkPath::fromValue(runtime, arguments[1]).get(); 55 SkPathOp op = (SkPathOp)arguments[2].asNumber(); 56 SkPath result; 57 bool success = Op(one, two, op, &result); 58 if (!success) { 59 return jsi::Value(nullptr); 60 } 61 return jsi::Object::createFromHostObject( 62 runtime, std::make_shared<JsiSkPath>(getContext(), std::move(result))); 63 } 64 JSI_HOST_FUNCTION(MakeFromCmds)65 JSI_HOST_FUNCTION(MakeFromCmds) { 66 SkPath path; 67 auto cmds = arguments[0].asObject(runtime).asArray(runtime); 68 auto cmdCount = cmds.size(runtime); 69 for (int i = 0; i < cmdCount; i++) { 70 auto cmd = cmds.getValueAtIndex(runtime, i).asObject(runtime).asArray(runtime); 71 if (cmd.size(runtime) < 1) { 72 RNSkLogger::logToConsole("Invalid command found (got an empty array)"); 73 return jsi::Value::null(); 74 } 75 auto verb = static_cast<int>(cmd.getValueAtIndex(runtime, 0).asNumber()); 76 switch (verb) { 77 case MOVE: { 78 if (cmd.size(runtime) < 3) { 79 RNSkLogger::logToConsole( "Invalid move command found"); 80 return jsi::Value::null(); 81 } 82 auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); 83 auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); 84 path.moveTo(x, y); 85 break; 86 } 87 case LINE: { 88 if (cmd.size(runtime) < 3) { 89 RNSkLogger::logToConsole("Invalid line command found"); 90 return jsi::Value::null(); 91 } 92 auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); 93 auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); 94 path.lineTo(x, y); 95 break; 96 } 97 case QUAD: { 98 if (cmd.size(runtime) < 5) { 99 RNSkLogger::logToConsole("Invalid line command found"); 100 return jsi::Value::null(); 101 } 102 auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); 103 auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); 104 auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); 105 auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); 106 path.quadTo(x1, y1, x2, y2); 107 break; 108 } 109 case CONIC: { 110 if (cmd.size(runtime) < 6) { 111 RNSkLogger::logToConsole("Invalid line command found"); 112 return jsi::Value::null(); 113 } 114 auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); 115 auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); 116 auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); 117 auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); 118 auto w = cmd.getValueAtIndex(runtime, 5).asNumber(); 119 path.conicTo(x1, y1, x2, y2, w); 120 break; 121 } 122 case CUBIC: { 123 if (cmd.size(runtime) < 7) { 124 RNSkLogger::logToConsole("Invalid line command found"); 125 return jsi::Value::null(); 126 } 127 auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); 128 auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); 129 auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); 130 auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); 131 auto x3 = cmd.getValueAtIndex(runtime, 5).asNumber(); 132 auto y3 = cmd.getValueAtIndex(runtime, 6).asNumber(); 133 path.cubicTo(x1, y1, x2, y2, x3, y3); 134 break; 135 } 136 case CLOSE: { 137 path.close(); 138 break; 139 } 140 default: { 141 RNSkLogger::logToConsole("Found an unknown command"); 142 return jsi::Value::null(); 143 } 144 } 145 } 146 return jsi::Object::createFromHostObject( 147 runtime, std::make_shared<JsiSkPath>(getContext(), std::move(path))); 148 } 149 JSI_HOST_FUNCTION(MakeFromText)150 JSI_HOST_FUNCTION(MakeFromText) { 151 auto text = arguments[0].asString(runtime).utf8(runtime); 152 auto x = arguments[1].asNumber(); 153 auto y = arguments[2].asNumber(); 154 auto font = JsiSkFont::fromValue(runtime, arguments[3]); 155 SkPath path; 156 SkTextUtils::GetPath(text.c_str(), strlen(text.c_str()), 157 SkTextEncoding::kUTF8, x, y, *font, &path); 158 return jsi::Object::createFromHostObject( 159 runtime, std::make_shared<JsiSkPath>(getContext(), std::move(path)));; 160 } 161 JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC (JsiSkPathFactory,Make),JSI_EXPORT_FUNC (JsiSkPathFactory,MakeFromSVGString),JSI_EXPORT_FUNC (JsiSkPathFactory,MakeFromOp),JSI_EXPORT_FUNC (JsiSkPathFactory,MakeFromCmds),JSI_EXPORT_FUNC (JsiSkPathFactory,MakeFromText))162 JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkPathFactory, Make), 163 JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromSVGString), 164 JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromOp), 165 JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromCmds), 166 JSI_EXPORT_FUNC(JsiSkPathFactory, MakeFromText)) 167 168 JsiSkPathFactory(std::shared_ptr<RNSkPlatformContext> context) 169 : JsiSkHostObject(std::move(context)) {} 170 }; 171 172 } // namespace RNSkia 173