exodeui-react-native 1.0.10 → 1.1.0
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.
- package/package.json +1 -1
- package/src/engine.ts +60 -7
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -1670,12 +1670,47 @@ export class ExodeUIEngine {
|
|
|
1670
1670
|
canvas.drawText(text, x, y, paint, font);
|
|
1671
1671
|
}
|
|
1672
1672
|
|
|
1673
|
+
private getOrDecodeImage(src: string): any {
|
|
1674
|
+
if (!src) return null;
|
|
1675
|
+
if (this.imageCache.has(src)) return this.imageCache.get(src)!;
|
|
1676
|
+
|
|
1677
|
+
if (src.startsWith('data:image')) {
|
|
1678
|
+
try {
|
|
1679
|
+
const base64Str = src.includes(',') ? src.split(',')[1] : src;
|
|
1680
|
+
const data = Skia.Data.fromBase64(base64Str);
|
|
1681
|
+
const img = Skia.Image.MakeImageFromEncoded(data);
|
|
1682
|
+
if (img) {
|
|
1683
|
+
this.imageCache.set(src, img);
|
|
1684
|
+
return img;
|
|
1685
|
+
}
|
|
1686
|
+
} catch (e) {
|
|
1687
|
+
console.error('[ExodeUIEngine] Failed to decode base64 image:', e);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
return null;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1673
1693
|
private renderImage(canvas: any, obj: any, w: number, h: number) {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
|
|
1694
|
+
const state = this.objectStates.get(obj.id);
|
|
1695
|
+
const geom = state?.geometry || obj.geometry;
|
|
1696
|
+
const src = obj.src || geom.src || '';
|
|
1697
|
+
|
|
1698
|
+
const img = this.getOrDecodeImage(src);
|
|
1699
|
+
if (img) {
|
|
1700
|
+
const paint = Skia.Paint();
|
|
1701
|
+
paint.setAlphaf(state?.opacity ?? 1);
|
|
1702
|
+
canvas.drawImageRect(
|
|
1703
|
+
img,
|
|
1704
|
+
{ x: 0, y: 0, width: img.width(), height: img.height() },
|
|
1705
|
+
{ x: -w/2, y: -h/2, width: w, height: h },
|
|
1706
|
+
paint
|
|
1707
|
+
);
|
|
1708
|
+
} else {
|
|
1709
|
+
// Fallback placeholder
|
|
1710
|
+
const paint = Skia.Paint();
|
|
1711
|
+
paint.setColor(Skia.Color('#374151'));
|
|
1712
|
+
canvas.drawRect({ x: -w/2, y: -h/2, width: w, height: h }, paint);
|
|
1713
|
+
}
|
|
1679
1714
|
}
|
|
1680
1715
|
|
|
1681
1716
|
private renderButton(canvas: any, obj: any, w: number, h: number) {
|
|
@@ -2248,8 +2283,26 @@ export class ExodeUIEngine {
|
|
|
2248
2283
|
|
|
2249
2284
|
if (style.fill) {
|
|
2250
2285
|
const paint = Skia.Paint();
|
|
2251
|
-
|
|
2252
|
-
|
|
2286
|
+
|
|
2287
|
+
let hasImageFill = false;
|
|
2288
|
+
if ((style.fill.type === 'Image' || style.fill.type === 'Pattern' || style.fill.url) && style.fill.url) {
|
|
2289
|
+
const img = this.getOrDecodeImage(style.fill.url);
|
|
2290
|
+
if (img) {
|
|
2291
|
+
const matrix = Skia.Matrix();
|
|
2292
|
+
matrix.translate(-w/2, -h/2);
|
|
2293
|
+
matrix.scale(w / img.width(), h / img.height());
|
|
2294
|
+
paint.setShader(img.makeShaderOptions(0, 0, 0, 0, matrix));
|
|
2295
|
+
hasImageFill = true;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
if (!hasImageFill) {
|
|
2300
|
+
const fillCol = style.fill.color;
|
|
2301
|
+
const fillColStr = typeof fillCol === 'string' ? fillCol.replace(/\s+/g, '') : '#000000';
|
|
2302
|
+
try { paint.setColor(Skia.Color(fillColStr)); } catch { paint.setColor(Skia.Color('#000000')); }
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
paint.setAlphaf(Math.max(0, Math.min(1, (state.opacity ?? 1) * (style.fill.opacity ?? 1))));
|
|
2253
2306
|
paint.setStyle(PaintStyle.Fill);
|
|
2254
2307
|
|
|
2255
2308
|
if (style.shadow && style.shadow.opacity > 0) {
|