canvu-react 0.4.34 → 0.4.35
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/dist/native.cjs +136 -1
- package/dist/native.cjs.map +1 -1
- package/dist/native.js +137 -2
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
package/dist/native.cjs
CHANGED
|
@@ -1404,6 +1404,141 @@ function smoothFreehandPointsToPathD(points) {
|
|
|
1404
1404
|
d += ` Q ${pLast.x} ${pLast.y} ${pEnd.x} ${pEnd.y}`;
|
|
1405
1405
|
return d;
|
|
1406
1406
|
}
|
|
1407
|
+
var DEFAULT_NATIVE_IMAGE_CACHE_MAX_ENTRIES = 96;
|
|
1408
|
+
function disposeCachedImage(image) {
|
|
1409
|
+
try {
|
|
1410
|
+
image.dispose?.();
|
|
1411
|
+
} catch {
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
function createNativeImageCache({
|
|
1415
|
+
loadImage,
|
|
1416
|
+
maxEntries = DEFAULT_NATIVE_IMAGE_CACHE_MAX_ENTRIES
|
|
1417
|
+
}) {
|
|
1418
|
+
const safeMaxEntries = Math.max(1, Math.round(maxEntries));
|
|
1419
|
+
const entries = /* @__PURE__ */ new Map();
|
|
1420
|
+
let clock = 0;
|
|
1421
|
+
const touchEntry = (entry) => {
|
|
1422
|
+
clock += 1;
|
|
1423
|
+
entry.lastUsed = clock;
|
|
1424
|
+
};
|
|
1425
|
+
const createEntry = () => {
|
|
1426
|
+
clock += 1;
|
|
1427
|
+
return {
|
|
1428
|
+
lastUsed: clock,
|
|
1429
|
+
retainCount: 0
|
|
1430
|
+
};
|
|
1431
|
+
};
|
|
1432
|
+
const prune = () => {
|
|
1433
|
+
const cachedEntries = [...entries.entries()].filter(
|
|
1434
|
+
(entry) => entry[1].image != null && entry[1].retainCount === 0
|
|
1435
|
+
);
|
|
1436
|
+
if (cachedEntries.length <= safeMaxEntries) return;
|
|
1437
|
+
const evictedEntries = cachedEntries.sort(
|
|
1438
|
+
(leftEntry, rightEntry) => leftEntry[1].lastUsed - rightEntry[1].lastUsed
|
|
1439
|
+
).slice(0, cachedEntries.length - safeMaxEntries);
|
|
1440
|
+
for (const [href, entry] of evictedEntries) {
|
|
1441
|
+
entries.delete(href);
|
|
1442
|
+
disposeCachedImage(entry.image);
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
const getCached = (href) => {
|
|
1446
|
+
const entry = entries.get(href);
|
|
1447
|
+
if (!entry?.image) return null;
|
|
1448
|
+
touchEntry(entry);
|
|
1449
|
+
return entry.image;
|
|
1450
|
+
};
|
|
1451
|
+
const load = async (href) => {
|
|
1452
|
+
const cachedImage = getCached(href);
|
|
1453
|
+
if (cachedImage) return cachedImage;
|
|
1454
|
+
const existingEntry = entries.get(href);
|
|
1455
|
+
if (existingEntry?.promise) return await existingEntry.promise;
|
|
1456
|
+
const entry = existingEntry ?? createEntry();
|
|
1457
|
+
const promise = loadImage(href).then((image) => {
|
|
1458
|
+
if (!image) {
|
|
1459
|
+
if (entry.retainCount === 0) entries.delete(href);
|
|
1460
|
+
return null;
|
|
1461
|
+
}
|
|
1462
|
+
entry.image = image;
|
|
1463
|
+
entry.promise = void 0;
|
|
1464
|
+
touchEntry(entry);
|
|
1465
|
+
prune();
|
|
1466
|
+
return image;
|
|
1467
|
+
}).catch((error) => {
|
|
1468
|
+
entries.delete(href);
|
|
1469
|
+
throw error;
|
|
1470
|
+
});
|
|
1471
|
+
entry.promise = promise;
|
|
1472
|
+
entries.set(href, entry);
|
|
1473
|
+
return await promise;
|
|
1474
|
+
};
|
|
1475
|
+
const retain = (href) => {
|
|
1476
|
+
const entry = entries.get(href) ?? createEntry();
|
|
1477
|
+
entry.retainCount += 1;
|
|
1478
|
+
touchEntry(entry);
|
|
1479
|
+
entries.set(href, entry);
|
|
1480
|
+
let released = false;
|
|
1481
|
+
return () => {
|
|
1482
|
+
if (released) return;
|
|
1483
|
+
released = true;
|
|
1484
|
+
entry.retainCount = Math.max(0, entry.retainCount - 1);
|
|
1485
|
+
if (!entry.image && !entry.promise && entry.retainCount === 0) {
|
|
1486
|
+
entries.delete(href);
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
prune();
|
|
1490
|
+
};
|
|
1491
|
+
};
|
|
1492
|
+
const clear = () => {
|
|
1493
|
+
for (const entry of entries.values()) {
|
|
1494
|
+
if (entry.image) disposeCachedImage(entry.image);
|
|
1495
|
+
}
|
|
1496
|
+
entries.clear();
|
|
1497
|
+
};
|
|
1498
|
+
const size = () => [...entries.values()].filter((entry) => entry.image != null).length;
|
|
1499
|
+
return { getCached, load, retain, clear, size };
|
|
1500
|
+
}
|
|
1501
|
+
async function loadSkiaImageFromHref(href) {
|
|
1502
|
+
const { Skia } = await import('@shopify/react-native-skia');
|
|
1503
|
+
const data = await Skia.Data.fromURI(href);
|
|
1504
|
+
return Skia.Image.MakeImageFromEncoded(data);
|
|
1505
|
+
}
|
|
1506
|
+
var nativeSkiaImageCache = createNativeImageCache({
|
|
1507
|
+
loadImage: loadSkiaImageFromHref
|
|
1508
|
+
});
|
|
1509
|
+
function useCachedSkiaImage(href) {
|
|
1510
|
+
const [loadedImage, setLoadedImage] = react.useState(
|
|
1511
|
+
() => href ? { href, image: nativeSkiaImageCache.getCached(href) } : null
|
|
1512
|
+
);
|
|
1513
|
+
react.useEffect(() => {
|
|
1514
|
+
if (!href) {
|
|
1515
|
+
setLoadedImage(null);
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const releaseImage = nativeSkiaImageCache.retain(href);
|
|
1519
|
+
const cachedImage = nativeSkiaImageCache.getCached(href);
|
|
1520
|
+
if (cachedImage) {
|
|
1521
|
+
setLoadedImage({ href, image: cachedImage });
|
|
1522
|
+
return releaseImage;
|
|
1523
|
+
}
|
|
1524
|
+
let active = true;
|
|
1525
|
+
setLoadedImage({ href, image: null });
|
|
1526
|
+
void nativeSkiaImageCache.load(href).then(
|
|
1527
|
+
(loadedImage2) => {
|
|
1528
|
+
if (active) setLoadedImage({ href, image: loadedImage2 });
|
|
1529
|
+
},
|
|
1530
|
+
() => {
|
|
1531
|
+
if (active) setLoadedImage({ href, image: null });
|
|
1532
|
+
}
|
|
1533
|
+
);
|
|
1534
|
+
return () => {
|
|
1535
|
+
active = false;
|
|
1536
|
+
releaseImage();
|
|
1537
|
+
};
|
|
1538
|
+
}, [href]);
|
|
1539
|
+
if (!href || loadedImage?.href !== href) return null;
|
|
1540
|
+
return loadedImage.image;
|
|
1541
|
+
}
|
|
1407
1542
|
|
|
1408
1543
|
// src/native/skia-transform.ts
|
|
1409
1544
|
function parseNum(s) {
|
|
@@ -1668,7 +1803,7 @@ function SvgNodeItem({ node }) {
|
|
|
1668
1803
|
function SvgImageNodeItem({
|
|
1669
1804
|
node
|
|
1670
1805
|
}) {
|
|
1671
|
-
const image =
|
|
1806
|
+
const image = useCachedSkiaImage(node.href);
|
|
1672
1807
|
if (!image) return null;
|
|
1673
1808
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1674
1809
|
reactNativeSkia.Image,
|