@chrtco/sdk 0.7.0 → 0.7.1
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/atlas/browser.cjs +196 -2
- package/dist/atlas/browser.cjs.map +1 -1
- package/dist/atlas/browser.d.cts +63 -1
- package/dist/atlas/browser.d.ts +63 -1
- package/dist/atlas/browser.js +191 -1
- package/dist/atlas/browser.js.map +1 -1
- package/package.json +20 -3
package/dist/atlas/browser.cjs
CHANGED
|
@@ -20,10 +20,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/atlas/browser.ts
|
|
21
21
|
var browser_exports = {};
|
|
22
22
|
__export(browser_exports, {
|
|
23
|
+
clearS52SymbolImageCache: () => clearS52SymbolImageCache,
|
|
24
|
+
getS52AtlasVersion: () => getS52AtlasVersion,
|
|
23
25
|
loadS52SymbolImages: () => loadS52SymbolImages,
|
|
26
|
+
loadS52SymbolImagesCached: () => loadS52SymbolImagesCached,
|
|
24
27
|
loadSymbolImages: () => loadSymbolImages,
|
|
25
28
|
loadThemedBridgeImages: () => loadThemedBridgeImages,
|
|
26
|
-
reloadS52SymbolImages: () => reloadS52SymbolImages
|
|
29
|
+
reloadS52SymbolImages: () => reloadS52SymbolImages,
|
|
30
|
+
reloadS52SymbolImagesCached: () => reloadS52SymbolImagesCached
|
|
27
31
|
});
|
|
28
32
|
module.exports = __toCommonJS(browser_exports);
|
|
29
33
|
|
|
@@ -807,6 +811,192 @@ async function reloadS52SymbolImages(map, colorTable) {
|
|
|
807
811
|
await Promise.all(promises);
|
|
808
812
|
}
|
|
809
813
|
|
|
814
|
+
// src/atlas/s52-image-cache.ts
|
|
815
|
+
var SDF_SYMBOLS2 = /* @__PURE__ */ new Set(["LIGHTS11", "LIGHTS13"]);
|
|
816
|
+
var LOGICAL_SIZE2 = 32;
|
|
817
|
+
var PIXEL_RATIO2 = 2;
|
|
818
|
+
var RENDER_SIZE2 = LOGICAL_SIZE2 * PIXEL_RATIO2;
|
|
819
|
+
var DB_NAME = "chrt-s52-atlas";
|
|
820
|
+
var DB_VERSION = 1;
|
|
821
|
+
var STORE_NAME = "bitmaps";
|
|
822
|
+
var PARAM_VERSION = "v2";
|
|
823
|
+
function computeAtlasVersion() {
|
|
824
|
+
const names = Object.keys(ALL_S52_SVGS).sort().join("|");
|
|
825
|
+
let h = 2166136261;
|
|
826
|
+
for (let i = 0; i < names.length; i++) {
|
|
827
|
+
h ^= names.charCodeAt(i);
|
|
828
|
+
h = Math.imul(h, 16777619);
|
|
829
|
+
}
|
|
830
|
+
return `${PARAM_VERSION}-${(h >>> 0).toString(16)}-${Object.keys(ALL_S52_SVGS).length}`;
|
|
831
|
+
}
|
|
832
|
+
var ATLAS_VERSION = /* @__PURE__ */ computeAtlasVersion();
|
|
833
|
+
function makeKey(colorTable, name) {
|
|
834
|
+
return `${ATLAS_VERSION}:${colorTable}:${name}`;
|
|
835
|
+
}
|
|
836
|
+
function upsampleSvg2(svg2) {
|
|
837
|
+
return svg2.replace(
|
|
838
|
+
/width="(\d+)"\s+height="(\d+)"/,
|
|
839
|
+
`width="${RENDER_SIZE2}" height="${RENDER_SIZE2}"`
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
function prepareSvg2(rawSvg, colorTable) {
|
|
843
|
+
return upsampleSvg2(applyStrokeBoost(applyColorTheme(rawSvg, colorTable), S52_STROKE_BOOST));
|
|
844
|
+
}
|
|
845
|
+
function hasIndexedDB() {
|
|
846
|
+
return typeof indexedDB !== "undefined";
|
|
847
|
+
}
|
|
848
|
+
function hasCanvasToBitmap() {
|
|
849
|
+
return typeof createImageBitmap === "function" && typeof document !== "undefined" && typeof document.createElement === "function";
|
|
850
|
+
}
|
|
851
|
+
var dbPromise = null;
|
|
852
|
+
function openDb() {
|
|
853
|
+
if (!hasIndexedDB()) return Promise.reject(new Error("IndexedDB not available"));
|
|
854
|
+
if (dbPromise) return dbPromise;
|
|
855
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
856
|
+
const req = indexedDB.open(DB_NAME, DB_VERSION);
|
|
857
|
+
req.onupgradeneeded = () => {
|
|
858
|
+
const db = req.result;
|
|
859
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
860
|
+
db.createObjectStore(STORE_NAME);
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
req.onsuccess = () => resolve(req.result);
|
|
864
|
+
req.onerror = () => reject(req.error ?? new Error("indexedDB.open failed"));
|
|
865
|
+
req.onblocked = () => reject(new Error("indexedDB.open blocked"));
|
|
866
|
+
});
|
|
867
|
+
dbPromise.catch(() => {
|
|
868
|
+
dbPromise = null;
|
|
869
|
+
});
|
|
870
|
+
return dbPromise;
|
|
871
|
+
}
|
|
872
|
+
async function idbPut(key, value) {
|
|
873
|
+
const db = await openDb();
|
|
874
|
+
return new Promise((resolve, reject) => {
|
|
875
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
876
|
+
const store = tx.objectStore(STORE_NAME);
|
|
877
|
+
const req = store.put(value, key);
|
|
878
|
+
req.onsuccess = () => resolve();
|
|
879
|
+
req.onerror = () => reject(req.error);
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
async function idbGetAllForTheme(colorTable) {
|
|
883
|
+
const out = /* @__PURE__ */ new Map();
|
|
884
|
+
const db = await openDb();
|
|
885
|
+
const names = Object.keys(ALL_S52_SVGS);
|
|
886
|
+
await new Promise((resolve, reject) => {
|
|
887
|
+
const tx = db.transaction(STORE_NAME, "readonly");
|
|
888
|
+
const store = tx.objectStore(STORE_NAME);
|
|
889
|
+
tx.oncomplete = () => resolve();
|
|
890
|
+
tx.onerror = () => reject(tx.error);
|
|
891
|
+
tx.onabort = () => reject(tx.error ?? new Error("idb txn aborted"));
|
|
892
|
+
for (const name of names) {
|
|
893
|
+
const req = store.get(makeKey(colorTable, name));
|
|
894
|
+
req.onsuccess = () => {
|
|
895
|
+
const bm = req.result;
|
|
896
|
+
if (bm) out.set(name, bm);
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
return out;
|
|
901
|
+
}
|
|
902
|
+
function decodeSvgToImage(themedSvg) {
|
|
903
|
+
return new Promise((resolve) => {
|
|
904
|
+
const img = new Image(RENDER_SIZE2, RENDER_SIZE2);
|
|
905
|
+
img.onload = () => resolve(img);
|
|
906
|
+
img.onerror = () => resolve(null);
|
|
907
|
+
img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(themedSvg)}`;
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
async function imageToBitmap(img) {
|
|
911
|
+
try {
|
|
912
|
+
const canvas = document.createElement("canvas");
|
|
913
|
+
canvas.width = RENDER_SIZE2;
|
|
914
|
+
canvas.height = RENDER_SIZE2;
|
|
915
|
+
const ctx = canvas.getContext("2d");
|
|
916
|
+
if (!ctx) return null;
|
|
917
|
+
ctx.drawImage(img, 0, 0, RENDER_SIZE2, RENDER_SIZE2);
|
|
918
|
+
return await createImageBitmap(canvas);
|
|
919
|
+
} catch {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
function addImageToMap(map, name, image) {
|
|
924
|
+
if (map.hasImage(name)) return;
|
|
925
|
+
try {
|
|
926
|
+
map.addImage(name, image, {
|
|
927
|
+
sdf: SDF_SYMBOLS2.has(name),
|
|
928
|
+
pixelRatio: PIXEL_RATIO2
|
|
929
|
+
});
|
|
930
|
+
} catch {
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
function getS52AtlasVersion() {
|
|
934
|
+
return ATLAS_VERSION;
|
|
935
|
+
}
|
|
936
|
+
async function loadS52SymbolImagesCached(map, colorTable = "DAY", opts = {}) {
|
|
937
|
+
if (!hasIndexedDB() || !hasCanvasToBitmap()) {
|
|
938
|
+
return loadS52SymbolImages(map, colorTable);
|
|
939
|
+
}
|
|
940
|
+
const names = Object.keys(ALL_S52_SVGS);
|
|
941
|
+
let cached;
|
|
942
|
+
if (opts.forceRefresh) {
|
|
943
|
+
cached = /* @__PURE__ */ new Map();
|
|
944
|
+
} else {
|
|
945
|
+
try {
|
|
946
|
+
cached = await idbGetAllForTheme(colorTable);
|
|
947
|
+
} catch {
|
|
948
|
+
cached = /* @__PURE__ */ new Map();
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
for (const [name, bitmap] of cached) {
|
|
952
|
+
addImageToMap(map, name, bitmap);
|
|
953
|
+
}
|
|
954
|
+
const missing = names.filter((n) => !cached.has(n) && !map.hasImage(n));
|
|
955
|
+
if (missing.length === 0) return;
|
|
956
|
+
await Promise.all(
|
|
957
|
+
missing.map(async (name) => {
|
|
958
|
+
const rawSvg = ALL_S52_SVGS[name];
|
|
959
|
+
if (!rawSvg) return;
|
|
960
|
+
const themed = prepareSvg2(rawSvg, colorTable);
|
|
961
|
+
const img = await decodeSvgToImage(themed);
|
|
962
|
+
if (!img) return;
|
|
963
|
+
addImageToMap(map, name, img);
|
|
964
|
+
try {
|
|
965
|
+
const bitmap = await imageToBitmap(img);
|
|
966
|
+
if (!bitmap) return;
|
|
967
|
+
await idbPut(makeKey(colorTable, name), bitmap);
|
|
968
|
+
} catch {
|
|
969
|
+
}
|
|
970
|
+
})
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
async function reloadS52SymbolImagesCached(map, colorTable) {
|
|
974
|
+
if (!hasIndexedDB() || !hasCanvasToBitmap()) {
|
|
975
|
+
return reloadS52SymbolImages(map, colorTable);
|
|
976
|
+
}
|
|
977
|
+
for (const name of Object.keys(ALL_S52_SVGS)) {
|
|
978
|
+
try {
|
|
979
|
+
if (map.hasImage(name)) map.removeImage(name);
|
|
980
|
+
} catch {
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return loadS52SymbolImagesCached(map, colorTable);
|
|
984
|
+
}
|
|
985
|
+
async function clearS52SymbolImageCache() {
|
|
986
|
+
if (!hasIndexedDB()) return;
|
|
987
|
+
try {
|
|
988
|
+
const db = await openDb();
|
|
989
|
+
await new Promise((resolve, reject) => {
|
|
990
|
+
const tx = db.transaction(STORE_NAME, "readwrite");
|
|
991
|
+
const store = tx.objectStore(STORE_NAME);
|
|
992
|
+
const req = store.clear();
|
|
993
|
+
req.onsuccess = () => resolve();
|
|
994
|
+
req.onerror = () => reject(req.error);
|
|
995
|
+
});
|
|
996
|
+
} catch {
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
810
1000
|
// src/atlas/symbols.ts
|
|
811
1001
|
var SIZE = 32;
|
|
812
1002
|
function svg(inner) {
|
|
@@ -3237,9 +3427,13 @@ async function loadThemedBridgeImages(map, colorTable) {
|
|
|
3237
3427
|
}
|
|
3238
3428
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3239
3429
|
0 && (module.exports = {
|
|
3430
|
+
clearS52SymbolImageCache,
|
|
3431
|
+
getS52AtlasVersion,
|
|
3240
3432
|
loadS52SymbolImages,
|
|
3433
|
+
loadS52SymbolImagesCached,
|
|
3241
3434
|
loadSymbolImages,
|
|
3242
3435
|
loadThemedBridgeImages,
|
|
3243
|
-
reloadS52SymbolImages
|
|
3436
|
+
reloadS52SymbolImages,
|
|
3437
|
+
reloadS52SymbolImagesCached
|
|
3244
3438
|
});
|
|
3245
3439
|
//# sourceMappingURL=browser.cjs.map
|