rngine 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,56 @@
1
+ package com.margelo.nitro.rngine
2
+
3
+ import android.util.Log
4
+ import androidx.annotation.Keep
5
+ import com.margelo.nitro.NitroModules
6
+ import java.io.IOException
7
+ import java.net.URL
8
+
9
+ @Keep
10
+ object ImageLoaderHelper {
11
+ @JvmStatic
12
+ fun loadFromUrl(uri: String): ByteArray {
13
+ Log.d("ImageLoaderHelper", "loadFromUrl: fetching $uri")
14
+ return try {
15
+ val bytes = URL(uri).openStream().use { it.readBytes() }
16
+ Log.d("ImageLoaderHelper", "loadFromUrl: success, ${bytes.size} bytes for $uri")
17
+ bytes
18
+ } catch (e: IOException) {
19
+ Log.e("ImageLoaderHelper", "loadFromUrl: network/IO failure for $uri", e)
20
+ throw e
21
+ } catch (e: Exception) {
22
+ Log.e("ImageLoaderHelper", "loadFromUrl: unexpected failure for $uri", e)
23
+ throw e
24
+ }
25
+ }
26
+
27
+ @JvmStatic
28
+ fun loadFromResource(uri: String): ByteArray {
29
+ Log.d("ImageLoaderHelper", "loadFromResource: resolving resource for '$uri'")
30
+ val context = NitroModules.applicationContext
31
+ if (context == null) {
32
+ Log.e(
33
+ "ImageLoaderHelper",
34
+ "loadFromResource: applicationContext is null, NitroModules not initialized?"
35
+ )
36
+ throw IllegalStateException("No Context available!")
37
+ }
38
+ var resId = context.resources.getIdentifier(uri, "raw", context.packageName)
39
+ if (resId == 0) {
40
+ resId = context.resources.getIdentifier(uri, "drawable", context.packageName)
41
+ }
42
+ if (resId == 0) {
43
+ Log.e("ImageLoaderHelper", "loadFromResource: no resource found for '$uri'")
44
+ throw IllegalStateException("Could not resolve raw resource for asset: $uri")
45
+ }
46
+ Log.d("ImageLoaderHelper", "loadFromResource: resolved '$uri' -> resId=$resId")
47
+ return try {
48
+ val bytes = context.resources.openRawResource(resId).use { it.readBytes() }
49
+ Log.d("ImageLoaderHelper", "loadFromResource: success, ${bytes.size} bytes for '$uri'")
50
+ bytes
51
+ } catch (e: Exception) {
52
+ Log.e("ImageLoaderHelper", "loadFromResource: failed reading resId=$resId for '$uri'", e)
53
+ throw e
54
+ }
55
+ }
56
+ }
@@ -81,9 +81,9 @@ const loadAsset = async asset => {
81
81
  if (!assetUri) {
82
82
  throw new Error(`loadAssets: could not resolve asset URI for ${asset}`);
83
83
  }
84
- const isSvgLoaded = await gameMethods.loadSvg(asset, assetUri);
85
- if (!isSvgLoaded) {
86
- throw new Error('loadAssets: Failed to load svg asset');
84
+ const isLoaded = await gameMethods.loadImage(asset, assetUri);
85
+ if (!isLoaded) {
86
+ throw new Error('loadAssets: Failed to load image asset');
87
87
  }
88
88
  return asset;
89
89
  }
@@ -1 +1 @@
1
- {"version":3,"names":["gameMethods","Image","configure","world","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setWorld","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray","assetCache","WeakMap","nextId","loadAsset","asset","Error","has","get","assetId","set","isLottieLoaded","loadLottie","JSON","stringify","isAssetLoaded","assetUri","resolveAssetSource","uri","isSvgLoaded","loadSvg","loadAssets","assets","keys","Object","result","key"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["gameMethods","Image","configure","world","screen","entities","systems","paused","nativeSystems","system","push","collisions","onTick","e","c","start","Date","now","finish","setWorld","setScreen","setEntities","setSystems","pause","resume","spawn","entityArray","Array","isArray","despawn","id","update","updates","entityUpdateArray","assetCache","WeakMap","nextId","loadAsset","asset","Error","has","get","assetId","set","isLottieLoaded","loadLottie","JSON","stringify","isAssetLoaded","assetUri","resolveAssetSource","uri","isLoaded","loadImage","loadAssets","assets","keys","Object","result","key"],"sourceRoot":"../../src","sources":["GameMethods.ts"],"mappings":"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","ignoreList":[]}
@@ -15,7 +15,7 @@ interface GameMethods extends HybridObject<{
15
15
  update(updates: EntityUpdate[]): void;
16
16
  isAssetLoaded(id: number): boolean;
17
17
  loadLottie(id: number, jsonStr: string): Promise<boolean>;
18
- loadSvg(id: number, svgUri: string): Promise<boolean>;
18
+ loadImage(id: number, imageUri: string): Promise<boolean>;
19
19
  }
20
20
  export declare const gameMethods: GameMethods;
21
21
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAGvB,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEtC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,WAAW,aACqC,CAAC"}
1
+ {"version":3,"file":"GameMethods.nitro.d.ts","sourceRoot":"","sources":["../../../src/GameMethods.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EACV,MAAM,EACN,YAAY,EACZ,MAAM,EACN,MAAM,EACN,KAAK,EACN,MAAM,eAAe,CAAC;AAGvB,UAAU,WAAY,SAAQ,YAAY,CAAC;IACzC,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,KAAK,CAAC;CAChB,CAAC;IACA,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAEtC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAED,eAAO,MAAM,WAAW,aACqC,CAAC"}
@@ -25,7 +25,7 @@ namespace margelo::nitro::rngine {
25
25
  prototype.registerHybridMethod("update", &HybridGameMethodsSpec::update);
26
26
  prototype.registerHybridMethod("isAssetLoaded", &HybridGameMethodsSpec::isAssetLoaded);
27
27
  prototype.registerHybridMethod("loadLottie", &HybridGameMethodsSpec::loadLottie);
28
- prototype.registerHybridMethod("loadSvg", &HybridGameMethodsSpec::loadSvg);
28
+ prototype.registerHybridMethod("loadImage", &HybridGameMethodsSpec::loadImage);
29
29
  });
30
30
  }
31
31
 
@@ -75,7 +75,7 @@ namespace margelo::nitro::rngine {
75
75
  virtual void update(const std::vector<EntityUpdate>& updates) = 0;
76
76
  virtual bool isAssetLoaded(double id) = 0;
77
77
  virtual std::shared_ptr<Promise<bool>> loadLottie(double id, const std::string& jsonStr) = 0;
78
- virtual std::shared_ptr<Promise<bool>> loadSvg(double id, const std::string& svgUri) = 0;
78
+ virtual std::shared_ptr<Promise<bool>> loadImage(double id, const std::string& imageUri) = 0;
79
79
 
80
80
  protected:
81
81
  // Hybrid Setup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rngine",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "React Native 2D game engine powered by Nitro Modules",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -2,6 +2,7 @@
2
2
  #include "EntityUpdate.hpp"
3
3
  #include "GameLoop.hpp"
4
4
  #include "GameRenderer.hpp"
5
+ #include "include/core/SkImage.h"
5
6
  #include "include/core/SkStream.h"
6
7
  #include <android/log.h>
7
8
  #include <fbjni/fbjni.h>
@@ -176,9 +177,9 @@ bool GameMethods::isAssetLoaded(double id) {
176
177
  auto &gameRenderer = GameRenderer::getInstance();
177
178
 
178
179
  if (id > 0) {
179
- auto &svgCache = gameRenderer.getSvgCacheInternal();
180
- auto it = svgCache.find(id);
181
- return it != svgCache.end();
180
+ auto &imageCache = gameRenderer.getImageCacheInternal();
181
+ auto it = imageCache.find(id);
182
+ return it != imageCache.end();
182
183
  }
183
184
 
184
185
  if (id < 0) {
@@ -213,53 +214,86 @@ GameMethods::loadLottie(double id, const std::string &jsonStr) {
213
214
  });
214
215
  };
215
216
 
216
- std::shared_ptr<Promise<bool>> GameMethods::loadSvg(double id,
217
- const std::string &svgUri) {
217
+ std::shared_ptr<Promise<bool>>
218
+ GameMethods::loadImage(double id, const std::string &imageUri) {
218
219
  return Promise<bool>::async([=]() -> bool {
219
- std::string svgStr;
220
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
221
+ "loadImage: start id=%.0f uri=%s", id,
222
+ imageUri.c_str());
223
+ std::string imageStr;
220
224
 
221
225
  using namespace facebook::jni;
222
226
 
223
- ThreadScope::WithClassLoader([&] {
224
- static const auto helperClass =
225
- findClassStatic("com/margelo/nitro/rngine/SvgLoaderHelper");
226
-
227
- local_ref<JArrayByte> byteArray;
228
-
229
- if (svgUri.rfind("http://", 0) == 0 || svgUri.rfind("https://", 0) == 0) {
230
- static const auto method =
231
- helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
232
- "loadFromUrl");
233
- byteArray = method(helperClass, make_jstring(svgUri));
234
- } else {
235
- static const auto method =
236
- helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
237
- "loadFromResource");
238
- byteArray = method(helperClass, make_jstring(svgUri));
239
- }
227
+ try {
228
+ ThreadScope::WithClassLoader([&] {
229
+ static const auto helperClass =
230
+ findClassStatic("com/margelo/nitro/rngine/ImageLoaderHelper");
231
+
232
+ local_ref<JArrayByte> byteArray;
233
+
234
+ if (imageUri.rfind("http://", 0) == 0 ||
235
+ imageUri.rfind("https://", 0) == 0) {
236
+ static const auto method =
237
+ helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
238
+ "loadFromUrl");
239
+ byteArray = method(helperClass, make_jstring(imageUri));
240
+ } else {
241
+ static const auto method =
242
+ helperClass->getStaticMethod<JArrayByte(local_ref<JString>)>(
243
+ "loadFromResource");
244
+ byteArray = method(helperClass, make_jstring(imageUri));
245
+ }
246
+
247
+ if (!byteArray) {
248
+ throw std::runtime_error("Failed to load image bytes for: " +
249
+ imageUri);
250
+ }
251
+
252
+ size_t len = byteArray->size();
253
+ imageStr.resize(len);
254
+ byteArray->getRegion(0, len,
255
+ reinterpret_cast<int8_t *>(imageStr.data()));
256
+ });
257
+ } catch (const std::exception &e) {
258
+ __android_log_print(ANDROID_LOG_ERROR, "GameMethods",
259
+ "loadImage: JNI fetch failed id=%.0f: %s", id,
260
+ e.what());
261
+ return false;
262
+ }
240
263
 
241
- if (!byteArray) {
242
- throw std::runtime_error("Failed to load SVG bytes for: " + svgUri);
243
- }
264
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
265
+ "loadImage: fetched %zu bytes id=%.0f", imageStr.size(),
266
+ id);
244
267
 
245
- size_t len = byteArray->size();
246
- svgStr.resize(len);
247
- byteArray->getRegion(0, len, reinterpret_cast<int8_t *>(svgStr.data()));
248
- });
268
+ auto &gameRenderer = GameRenderer::getInstance();
269
+ auto &imageCache = gameRenderer.getImageCacheInternal();
249
270
 
250
- auto stream = SkMemoryStream::MakeDirect(svgStr.data(), svgStr.size());
271
+ auto stream = SkMemoryStream::MakeDirect(imageStr.data(), imageStr.size());
251
272
  auto svgDom = SkSVGDOM::MakeFromStream(*stream);
252
273
 
253
- if (!svgDom) {
254
- return false;
274
+ if (svgDom) {
275
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
276
+ "loadImage: parsed as SVG id=%.0f", id);
277
+ imageCache[id] = std::move(svgDom);
278
+ return true;
255
279
  }
256
280
 
257
- auto &gameRenderer = GameRenderer::getInstance();
258
- auto &svgCache = gameRenderer.getSvgCacheInternal();
281
+ auto data = SkData::MakeWithCopy(imageStr.data(), imageStr.size());
282
+ auto raster = SkImages::DeferredFromEncodedData(std::move(data));
259
283
 
260
- svgCache[id] = std::move(svgDom);
284
+ if (raster) {
285
+ __android_log_print(ANDROID_LOG_DEBUG, "GameMethods",
286
+ "loadImage: parsed as raster id=%.0f", id);
287
+ imageCache[id] = std::move(raster);
288
+ return true;
289
+ }
261
290
 
262
- return true;
291
+ __android_log_print(ANDROID_LOG_ERROR, "GameMethods",
292
+ "loadImage: both SVG parse and raster decode failed "
293
+ "id=%.0f",
294
+ id);
295
+
296
+ return false;
263
297
  });
264
298
  };
265
299
  } // namespace margelo::nitro::rngine
@@ -31,7 +31,7 @@ public:
31
31
  std::shared_ptr<Promise<bool>>
32
32
  loadLottie(double id, const std::string &jsonStr) override;
33
33
 
34
- std::shared_ptr<Promise<bool>> loadSvg(double id,
35
- const std::string &svgUri) override;
34
+ std::shared_ptr<Promise<bool>> loadImage(double id,
35
+ const std::string &svgUri) override;
36
36
  };
37
37
  } // namespace margelo::nitro::rngine
@@ -10,6 +10,7 @@
10
10
  #include "include/core/SkColorSpace.h"
11
11
  #include "include/core/SkPaint.h"
12
12
  #include "include/core/SkRect.h"
13
+ #include "include/core/SkRefCnt.h"
13
14
  #include "include/core/SkSurface.h"
14
15
 
15
16
  #include "include/gpu/ganesh/GrBackendSurface.h"
@@ -19,6 +20,7 @@
19
20
 
20
21
  #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
21
22
  #include "include/gpu/ganesh/gl/GrGLInterface.h"
23
+ #include "modules/svg/include/SkSVGDOM.h"
22
24
 
23
25
  #include <EGL/egl.h>
24
26
  #include <GLES3/gl3.h>
@@ -151,29 +153,58 @@ void GameRenderer::render(const Screen &screen,
151
153
  if (screen.asset.has_value() && screen.asset.value() != 0) {
152
154
  double assetId = screen.asset.value();
153
155
 
154
- auto svgIt = _svgCache.find(assetId);
155
- if (svgIt != _svgCache.end() && svgIt->second) {
156
- auto &svgDom = svgIt->second;
157
-
158
- SkSize intrinsicSize = svgDom->containerSize();
159
- if (intrinsicSize.isEmpty()) {
160
- svgDom->setContainerSize(SkSize::Make(virtualWidth, virtualHeight));
161
- intrinsicSize = SkSize::Make(virtualWidth, virtualHeight);
162
- }
156
+ auto imageIt = _imageCache.find(assetId);
157
+ if (imageIt != _imageCache.end()) {
158
+ std::visit(
159
+ [&](const auto image) {
160
+ using T = std::decay_t<decltype(image)>;
161
+ if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
162
+ SkSize intrinsicSize = image->containerSize();
163
+
164
+ if (intrinsicSize.isEmpty()) {
165
+ image->setContainerSize(
166
+ SkSize::Make(virtualWidth, virtualHeight));
167
+ intrinsicSize = SkSize::Make(virtualWidth, virtualHeight);
168
+ }
163
169
 
164
- float scaleX = virtualWidth / intrinsicSize.width();
165
- float scaleY = virtualHeight / intrinsicSize.height();
170
+ float scaleX = virtualWidth / intrinsicSize.width();
171
+ float scaleY = virtualHeight / intrinsicSize.height();
166
172
 
167
- canvas->save();
168
- if (screen.flipH.has_value() || screen.flipV.has_value()) {
169
- canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
170
- canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
171
- screen.flipV.value_or(false) ? -1.f : 1.f);
172
- canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
173
- }
174
- canvas->scale(scaleX, scaleY);
175
- svgDom->render(canvas);
176
- canvas->restore();
173
+ canvas->save();
174
+ if (screen.flipH.has_value() || screen.flipV.has_value()) {
175
+ canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
176
+ canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
177
+ screen.flipV.value_or(false) ? -1.f : 1.f);
178
+ canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
179
+ }
180
+ canvas->scale(scaleX, scaleY);
181
+ image->render(canvas);
182
+ canvas->restore();
183
+ } else {
184
+ float intrinsicW = static_cast<float>(image->width());
185
+ float intrinsicH = static_cast<float>(image->height());
186
+ if (intrinsicW <= 0.f || intrinsicH <= 0.f)
187
+ return;
188
+
189
+ float scaleX = virtualWidth / intrinsicW;
190
+ float scaleY = virtualHeight / intrinsicH;
191
+
192
+ canvas->save();
193
+ if (screen.flipH.has_value() || screen.flipV.has_value()) {
194
+ canvas->translate(virtualWidth / 2.f, virtualHeight / 2.f);
195
+ canvas->scale(screen.flipH.value_or(false) ? -1.f : 1.f,
196
+ screen.flipV.value_or(false) ? -1.f : 1.f);
197
+ canvas->translate(-virtualWidth / 2.f, -virtualHeight / 2.f);
198
+ }
199
+ canvas->scale(scaleX, scaleY);
200
+
201
+ SkSamplingOptions sampling(SkFilterMode::kLinear,
202
+ SkMipmapMode::kLinear);
203
+ canvas->drawImage(image, 0.f, 0.f, sampling);
204
+ canvas->restore();
205
+ }
206
+ },
207
+ imageIt->second);
177
208
  } else {
178
209
  auto lottieIt = _lottieCache.find(assetId);
179
210
  if (lottieIt != _lottieCache.end() && lottieIt->second) {
@@ -246,23 +277,43 @@ void GameRenderer::render(const Screen &screen,
246
277
  canvas->translate(-width / 2.f, -height / 2.f);
247
278
  }
248
279
 
249
- auto svgIt = _svgCache.find(assetId);
250
- if (svgIt != _svgCache.end() && svgIt->second) {
251
- auto &svgDom = svgIt->second;
252
-
253
- SkSize intrinsicSize = svgDom->containerSize();
254
- if (intrinsicSize.isEmpty()) {
255
- svgDom->setContainerSize(SkSize::Make(width, height));
256
- intrinsicSize = SkSize::Make(width, height);
257
- }
258
-
259
- float scaleX = width / intrinsicSize.width();
260
- float scaleY = height / intrinsicSize.height();
261
-
262
- canvas->save();
263
- canvas->scale(scaleX, scaleY);
264
- svgDom->render(canvas);
265
- canvas->restore();
280
+ auto imageIt = _imageCache.find(assetId);
281
+ if (imageIt != _imageCache.end()) {
282
+ std::visit(
283
+ [&](const auto image) {
284
+ using T = std::decay_t<decltype(image)>;
285
+ if constexpr (std::is_same_v<T, sk_sp<SkSVGDOM>>) {
286
+ SkSize intrinsicSize = image->containerSize();
287
+ if (intrinsicSize.isEmpty()) {
288
+ image->setContainerSize(SkSize::Make(width, height));
289
+ intrinsicSize = SkSize::Make(width, height);
290
+ }
291
+
292
+ float scaleX = width / intrinsicSize.width();
293
+ float scaleY = height / intrinsicSize.height();
294
+
295
+ canvas->save();
296
+ canvas->scale(scaleX, scaleY);
297
+ image->render(canvas);
298
+ canvas->restore();
299
+ } else {
300
+ float intrinsicW = static_cast<float>(image->width());
301
+ float intrinsicH = static_cast<float>(image->height());
302
+ if (intrinsicW <= 0.f || intrinsicH <= 0.f)
303
+ return;
304
+
305
+ float scaleX = width / intrinsicW;
306
+ float scaleY = height / intrinsicH;
307
+
308
+ canvas->save();
309
+ canvas->scale(scaleX, scaleY);
310
+ SkSamplingOptions sampling(SkFilterMode::kLinear,
311
+ SkMipmapMode::kLinear);
312
+ canvas->drawImage(image, 0.f, 0.f, sampling);
313
+ canvas->restore();
314
+ }
315
+ },
316
+ imageIt->second);
266
317
  } else {
267
318
  auto lottieIt = _lottieCache.find(assetId);
268
319
  if (lottieIt != _lottieCache.end() && lottieIt->second) {
@@ -1,6 +1,7 @@
1
1
  #pragma once
2
2
  #include "Entity.hpp"
3
3
  #include "Screen.hpp"
4
+ #include "include/core/SkImage.h"
4
5
  #include "include/core/SkSurface.h"
5
6
  #include "include/gpu/ganesh/GrDirectContext.h"
6
7
  #include "modules/skottie/include/Skottie.h"
@@ -21,9 +22,11 @@ public:
21
22
 
22
23
  ~GameRenderer();
23
24
 
24
- std::map<double, sk_sp<SkSVGDOM>> &getSvgCacheInternal() {
25
- return _svgCache;
25
+ std::map<double, std::variant<sk_sp<SkSVGDOM>, sk_sp<SkImage>>> &
26
+ getImageCacheInternal() {
27
+ return _imageCache;
26
28
  };
29
+
27
30
  std::map<double, sk_sp<skottie::Animation>> &getLottieCacheInternal() {
28
31
  return _lottieCache;
29
32
  };
@@ -52,8 +55,8 @@ private:
52
55
  int _height{0};
53
56
  bool _initialized{false};
54
57
 
55
- std::map<double, sk_sp<SkSVGDOM>> _svgCache;
56
58
  std::map<double, sk_sp<skottie::Animation>> _lottieCache;
59
+ std::map<double, std::variant<sk_sp<SkSVGDOM>, sk_sp<SkImage>>> _imageCache;
57
60
 
58
61
  bool isEntityVisible(const Entity &entity, float screenWidth,
59
62
  float screenHeight);
@@ -24,7 +24,7 @@ interface GameMethods extends HybridObject<{
24
24
 
25
25
  isAssetLoaded(id: number): boolean;
26
26
  loadLottie(id: number, jsonStr: string): Promise<boolean>;
27
- loadSvg(id: number, svgUri: string): Promise<boolean>;
27
+ loadImage(id: number, imageUri: string): Promise<boolean>;
28
28
  }
29
29
 
30
30
  export const gameMethods =
@@ -89,9 +89,9 @@ const loadAsset = async (asset: unknown) => {
89
89
  if (!assetUri) {
90
90
  throw new Error(`loadAssets: could not resolve asset URI for ${asset}`);
91
91
  }
92
- const isSvgLoaded = await gameMethods.loadSvg(asset, assetUri);
93
- if (!isSvgLoaded) {
94
- throw new Error('loadAssets: Failed to load svg asset');
92
+ const isLoaded = await gameMethods.loadImage(asset, assetUri);
93
+ if (!isLoaded) {
94
+ throw new Error('loadAssets: Failed to load image asset');
95
95
  }
96
96
  return asset;
97
97
  }
@@ -1,24 +0,0 @@
1
- package com.margelo.nitro.rngine
2
-
3
- import androidx.annotation.Keep
4
- import com.margelo.nitro.NitroModules
5
- import java.net.URL
6
-
7
- @Keep
8
- object SvgLoaderHelper {
9
- @JvmStatic
10
- fun loadFromUrl(uri: String): ByteArray {
11
- return URL(uri).openStream().use { it.readBytes() }
12
- }
13
-
14
- @JvmStatic
15
- fun loadFromResource(uri: String): ByteArray {
16
- val context = NitroModules.applicationContext
17
- ?: throw IllegalStateException("No Context available!")
18
- val resId = context.resources.getIdentifier(uri, "raw", context.packageName)
19
- if (resId == 0) {
20
- throw IllegalStateException("Could not resolve raw resource for asset: $uri")
21
- }
22
- return context.resources.openRawResource(resId).use { it.readBytes() }
23
- }
24
- }