exodeui-react-native 1.2.1 → 1.3.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 +36 -24
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -1535,8 +1535,19 @@ export class ExodeUIEngine {
|
|
|
1535
1535
|
|
|
1536
1536
|
canvas.save();
|
|
1537
1537
|
canvas.translate(cx, cy);
|
|
1538
|
-
|
|
1539
|
-
|
|
1538
|
+
|
|
1539
|
+
// Rotate around the center of the object
|
|
1540
|
+
if (rotation !== 0) {
|
|
1541
|
+
canvas.translate(w / 2, h / 2);
|
|
1542
|
+
canvas.rotate(rotation * Math.PI / 180, 0, 0);
|
|
1543
|
+
canvas.translate(-w / 2, -h / 2);
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
if (scaleX !== 1 || scaleY !== 1) {
|
|
1547
|
+
canvas.translate(w / 2, h / 2);
|
|
1548
|
+
canvas.scale(scaleX, scaleY);
|
|
1549
|
+
canvas.translate(-w / 2, -h / 2);
|
|
1550
|
+
}
|
|
1540
1551
|
|
|
1541
1552
|
if (this._renderCount % 120 === 1) {
|
|
1542
1553
|
console.log(`[ExodeUIEngine] - Drawing object: ${obj.name || obj.id} (${obj.type}), pos: ${cx.toFixed(1)},${cy.toFixed(1)}`);
|
|
@@ -1638,15 +1649,15 @@ export class ExodeUIEngine {
|
|
|
1638
1649
|
const segments = geom.segments || obj.segments || [];
|
|
1639
1650
|
|
|
1640
1651
|
if (enableSegments && segments.length > 0) {
|
|
1641
|
-
let offsetX =
|
|
1652
|
+
let offsetX = 0;
|
|
1642
1653
|
const totalWidth = segments.reduce((acc: number, seg: any) => {
|
|
1643
1654
|
const font = this.getFont(seg.fontSize || geom.fontSize || 14, seg.fontFamily || geom.fontFamily || 'System');
|
|
1644
1655
|
return acc + font.getTextWidth(seg.text);
|
|
1645
1656
|
}, 0);
|
|
1646
1657
|
|
|
1647
1658
|
const align = geom.textAlign || 'left';
|
|
1648
|
-
if (align === 'center') offsetX = -totalWidth / 2;
|
|
1649
|
-
else if (align === 'right') offsetX = w
|
|
1659
|
+
if (align === 'center') offsetX = (w - totalWidth) / 2;
|
|
1660
|
+
else if (align === 'right') offsetX = w - totalWidth;
|
|
1650
1661
|
|
|
1651
1662
|
segments.forEach((seg: any) => {
|
|
1652
1663
|
const font = this.getFont(seg.fontSize || geom.fontSize || 14, seg.fontFamily || geom.fontFamily || 'System');
|
|
@@ -1655,7 +1666,9 @@ export class ExodeUIEngine {
|
|
|
1655
1666
|
try { paint.setColor(Skia.Color(col.replace(/\s+/g, ''))); } catch { paint.setColor(Skia.Color('#ffffff')); }
|
|
1656
1667
|
paint.setAlphaf((state?.opacity ?? 1) * (seg.fill?.opacity ?? 1));
|
|
1657
1668
|
|
|
1658
|
-
|
|
1669
|
+
const fontSize = seg.fontSize || geom.fontSize || 14;
|
|
1670
|
+
const y = fontSize; // Basic baseline
|
|
1671
|
+
canvas.drawText(seg.text, offsetX, y, paint, font);
|
|
1659
1672
|
offsetX += font.getTextWidth(seg.text);
|
|
1660
1673
|
});
|
|
1661
1674
|
return;
|
|
@@ -1682,12 +1695,12 @@ export class ExodeUIEngine {
|
|
|
1682
1695
|
|
|
1683
1696
|
const align = geom.textAlign || obj.textAlign || 'center';
|
|
1684
1697
|
const textWidth = font.getTextWidth(text);
|
|
1685
|
-
let x =
|
|
1686
|
-
if (align === 'center') x = -textWidth / 2;
|
|
1687
|
-
else if (align === 'right') x = w
|
|
1698
|
+
let x = 0;
|
|
1699
|
+
if (align === 'center') x = (w - textWidth) / 2;
|
|
1700
|
+
else if (align === 'right') x = w - textWidth;
|
|
1688
1701
|
|
|
1689
1702
|
// Check baseline
|
|
1690
|
-
const y = geom.verticalAlign === 'center' || !geom.verticalAlign ? fontSize /
|
|
1703
|
+
const y = geom.verticalAlign === 'center' || !geom.verticalAlign ? (h + fontSize/2) / 2 : fontSize;
|
|
1691
1704
|
canvas.drawText(text, x, y, paint, font);
|
|
1692
1705
|
}
|
|
1693
1706
|
|
|
@@ -1722,8 +1735,8 @@ export class ExodeUIEngine {
|
|
|
1722
1735
|
paint.setAlphaf(state?.opacity ?? 1);
|
|
1723
1736
|
canvas.drawImageRect(
|
|
1724
1737
|
img,
|
|
1725
|
-
|
|
1726
|
-
|
|
1738
|
+
Skia.XYWHRect(0, 0, img.width(), img.height()),
|
|
1739
|
+
Skia.XYWHRect(0, 0, w, h),
|
|
1727
1740
|
paint
|
|
1728
1741
|
);
|
|
1729
1742
|
} else {
|
|
@@ -2308,8 +2321,8 @@ export class ExodeUIEngine {
|
|
|
2308
2321
|
const style = state.style || obj.style;
|
|
2309
2322
|
|
|
2310
2323
|
const path = Skia.Path.Make();
|
|
2324
|
+
const rect = Skia.XYWHRect(0, 0, w, h);
|
|
2311
2325
|
if (geometry.type === 'Rectangle') {
|
|
2312
|
-
const rect = { x: -w/2, y: -h/2, width: w, height: h };
|
|
2313
2326
|
if (state.cornerRadius !== undefined || geometry.corner_radius !== undefined) {
|
|
2314
2327
|
const rawCr = state.cornerRadius ?? geometry.corner_radius;
|
|
2315
2328
|
const cr = Array.isArray(rawCr) ? rawCr[0] : Number(rawCr);
|
|
@@ -2318,11 +2331,11 @@ export class ExodeUIEngine {
|
|
|
2318
2331
|
path.addRect(rect);
|
|
2319
2332
|
}
|
|
2320
2333
|
} else if (geometry.type === 'Ellipse') {
|
|
2321
|
-
path.addOval(
|
|
2334
|
+
path.addOval(rect);
|
|
2322
2335
|
} else if (geometry.type === 'Triangle') {
|
|
2323
|
-
path.moveTo(
|
|
2324
|
-
path.lineTo(w
|
|
2325
|
-
path.lineTo(
|
|
2336
|
+
path.moveTo(w / 2, 0);
|
|
2337
|
+
path.lineTo(w, h);
|
|
2338
|
+
path.lineTo(0, h);
|
|
2326
2339
|
path.close();
|
|
2327
2340
|
} else if (geometry.type === 'Star') {
|
|
2328
2341
|
const ir = geometry.inner_radius || 20;
|
|
@@ -2331,8 +2344,8 @@ export class ExodeUIEngine {
|
|
|
2331
2344
|
for (let i = 0; i < sp * 2; i++) {
|
|
2332
2345
|
const a = (i * Math.PI / sp) - (Math.PI / 2);
|
|
2333
2346
|
const rad = i % 2 === 0 ? or : ir;
|
|
2334
|
-
const px = rad * Math.cos(a);
|
|
2335
|
-
const py = rad * Math.sin(a);
|
|
2347
|
+
const px = w/2 + rad * Math.cos(a);
|
|
2348
|
+
const py = h/2 + rad * Math.sin(a);
|
|
2336
2349
|
if (i === 0) path.moveTo(px, py);
|
|
2337
2350
|
else path.lineTo(px, py);
|
|
2338
2351
|
}
|
|
@@ -2346,14 +2359,14 @@ export class ExodeUIEngine {
|
|
|
2346
2359
|
if (style.fill.type === 'LinearGradient' && style.fill.stops && style.fill.stops.length >= 2) {
|
|
2347
2360
|
const colors = style.fill.stops.map((s: any) => Skia.Color(s.color.replace(/\s+/g, '')));
|
|
2348
2361
|
const offsets = style.fill.stops.map((s: any) => s.offset);
|
|
2349
|
-
const start = style.fill.start ? { x:
|
|
2350
|
-
const end = style.fill.end ? { x:
|
|
2362
|
+
const start = style.fill.start ? { x: style.fill.start[0] * w, y: style.fill.start[1] * h } : { x: 0, y: 0 };
|
|
2363
|
+
const end = style.fill.end ? { x: style.fill.end[0] * w, y: style.fill.end[1] * h } : { x: w, y: 0 };
|
|
2351
2364
|
paint.setShader(Skia.Shader.MakeLinearGradient(Skia.Point(start.x, start.y), Skia.Point(end.x, end.y), colors, offsets, TileMode.Clamp));
|
|
2352
2365
|
hasShader = true;
|
|
2353
2366
|
} else if (style.fill.type === 'RadialGradient' && style.fill.stops && style.fill.stops.length >= 2) {
|
|
2354
2367
|
const colors = style.fill.stops.map((s: any) => Skia.Color(s.color.replace(/\s+/g, '')));
|
|
2355
2368
|
const offsets = style.fill.stops.map((s: any) => s.offset);
|
|
2356
|
-
const center = style.fill.center ? { x:
|
|
2369
|
+
const center = style.fill.center ? { x: style.fill.center[0] * w, y: style.fill.center[1] * h } : { x: w/2, y: h/2 };
|
|
2357
2370
|
const radius = (style.fill.radius || 0.5) * Math.max(w, h);
|
|
2358
2371
|
paint.setShader(Skia.Shader.MakeRadialGradient(Skia.Point(center.x, center.y), radius, colors, offsets, TileMode.Clamp));
|
|
2359
2372
|
hasShader = true;
|
|
@@ -2361,7 +2374,6 @@ export class ExodeUIEngine {
|
|
|
2361
2374
|
const img = this.getOrDecodeImage(style.fill.url);
|
|
2362
2375
|
if (img) {
|
|
2363
2376
|
const matrix = Skia.Matrix();
|
|
2364
|
-
matrix.translate(-w/2, -h/2);
|
|
2365
2377
|
matrix.scale(w / img.width(), h / img.height());
|
|
2366
2378
|
paint.setShader(img.makeShaderOptions(0, 0, 0, 0, matrix));
|
|
2367
2379
|
hasShader = true;
|
|
@@ -2379,7 +2391,7 @@ export class ExodeUIEngine {
|
|
|
2379
2391
|
|
|
2380
2392
|
// Apply clipping for Frame types before drawing
|
|
2381
2393
|
if (obj.type === 'Frame' || (obj as any).clipContent) {
|
|
2382
|
-
canvas.clipRect(
|
|
2394
|
+
canvas.clipRect(rect, ClipOp.Intersect, true);
|
|
2383
2395
|
}
|
|
2384
2396
|
|
|
2385
2397
|
if (style.shadow && style.shadow.opacity > 0) {
|