goatdee-canvas 0.0.75 → 0.0.77

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/index.cjs CHANGED
@@ -1935,13 +1935,25 @@ class Manager {
1935
1935
  }
1936
1936
  }
1937
1937
  /**
1938
- * 缓存一份字体 buffer,留给导出 worker 内部的独立 wasm 实例使用。
1938
+ * 缓存字体 buffer,留给导出 worker 内部的独立 wasm 实例使用。
1939
1939
  * 与主 wasm 的字体注册无关:主 wasm 已经吃掉自己那份副本。
1940
+ * 同名会覆盖;须为独立 ArrayBuffer,便于 transfer 给 worker。
1940
1941
  */
1941
- cacheFontBuffers(fonts) {
1942
+ appendExportWorkerFontBuffers(fonts) {
1942
1943
  if (!fonts || fonts.length === 0)
1943
1944
  return;
1944
- this.exportWorkerFontBuffers_ = fonts.slice();
1945
+ for (const font of fonts) {
1946
+ if (!(font === null || font === void 0 ? void 0 : font.name) || !font.buffer)
1947
+ continue;
1948
+ const idx = this.exportWorkerFontBuffers_.findIndex((f) => f.name === font.name);
1949
+ const entry = { name: font.name, buffer: font.buffer };
1950
+ if (idx >= 0) {
1951
+ this.exportWorkerFontBuffers_[idx] = entry;
1952
+ }
1953
+ else {
1954
+ this.exportWorkerFontBuffers_.push(entry);
1955
+ }
1956
+ }
1945
1957
  }
1946
1958
  getExportWorkerFontBuffers() {
1947
1959
  return this.exportWorkerFontBuffers_;
@@ -1958,22 +1970,31 @@ const manager = Manager.getInstance();
1958
1970
  // ———————————————————— 导出 API ————————————————————
1959
1971
  // exportImageClient 的 lazy import 句柄;首次访问后才把 worker chunk 拉下来。
1960
1972
  let exportImageClientPromise_ = null;
1973
+ function configureExportImageClient(client) {
1974
+ const license = manager.getExportWorkerSessionLicense();
1975
+ const fonts = manager.getExportWorkerFontBuffers();
1976
+ client.configure({
1977
+ sessionLicense: license !== null && license !== void 0 ? license : undefined,
1978
+ fonts: fonts.length > 0 ? fonts : undefined,
1979
+ });
1980
+ }
1961
1981
  async function getExportImageClient() {
1962
1982
  if (!exportImageClientPromise_) {
1963
1983
  exportImageClientPromise_ = Promise.resolve().then(function () { return exportImage_client; }).then((mod) => {
1964
1984
  const client = mod.exportImageClient;
1965
- // 把 manager 上缓存的 license / 字体一次性同步过去
1966
- const license = manager.getExportWorkerSessionLicense();
1967
- const fonts = manager.getExportWorkerFontBuffers();
1968
- client.configure({
1969
- sessionLicense: license !== null && license !== void 0 ? license : undefined,
1970
- fonts: fonts && fonts.length > 0 ? fonts : undefined,
1971
- });
1985
+ configureExportImageClient(client);
1972
1986
  return client;
1973
1987
  });
1974
1988
  }
1975
1989
  return exportImageClientPromise_;
1976
1990
  }
1991
+ /** registerFonts 等场景下,把最新字体列表同步给已 lazy 加载的 export worker。 */
1992
+ async function syncExportWorkerFonts() {
1993
+ if (!exportImageClientPromise_)
1994
+ return;
1995
+ const client = await exportImageClientPromise_;
1996
+ configureExportImageClient(client);
1997
+ }
1977
1998
  /**
1978
1999
  * 平移画布。
1979
2000
  * @category 画布操作
@@ -2382,6 +2403,12 @@ const registerFonts = async (fonts) => {
2382
2403
  await registerFontToBrowser({ name: font.fontName, buffer });
2383
2404
  await manager.getCanvas().registerFont(font.fontName, new Uint8Array(buffer));
2384
2405
  manager.addRegisteredFont(font.fontName);
2406
+ // 导出 worker 使用独立 wasm,须单独缓存字体二进制(见 fontManager BUILD_SINGLE_THREAD)
2407
+ const standaloneBuffer = buffer.slice(0);
2408
+ manager.appendExportWorkerFontBuffers([
2409
+ { name: font.fontName, buffer: standaloneBuffer },
2410
+ ]);
2411
+ void syncExportWorkerFonts();
2385
2412
  }
2386
2413
  catch (error) {
2387
2414
  console.warn(`${font.fontName} 字体注册失败:`, error);
@@ -5228,7 +5255,7 @@ const debug = () => {
5228
5255
  if (typeof window === "undefined") {
5229
5256
  return;
5230
5257
  }
5231
- window.__gd = { ...ManagerAPI };
5258
+ window.__gd = { ...window.__gd, ...ManagerAPI };
5232
5259
  };
5233
5260
 
5234
5261
  /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -6116,6 +6143,9 @@ const TGFXBind = (module) => {
6116
6143
  setTGFXModule(module);
6117
6144
  module.module = module;
6118
6145
  module.ScalerContext = ScalerContext;
6146
+ // tgfx 升级后 WebPathRasterizer.cpp 通过 val::module_property("PathRasterizer") 查找
6147
+ // 这里必须用 PathRasterizer 这个 key 注册;保留 WebMask 作为兼容回退。
6148
+ module.PathRasterizer = PathRasterizer;
6119
6149
  module.WebMask = PathRasterizer;
6120
6150
  module.Matrix = Matrix;
6121
6151
  module.tgfx = { ...tgfx };
@@ -6127,19 +6157,42 @@ const TGFXBind = (module) => {
6127
6157
  *
6128
6158
  * 副作用:把字体 buffer 复制一份缓存到 manager,供导出 worker(exportImageClient)
6129
6159
  * 在它自己的 wasm 实例里再注册一次。
6160
+ *
6161
+ * ⚠️ 必须同时显式声明 `.wasm` 的 `new URL` 引用,否则消费者 bundler(webpack/vite/rspack)
6162
+ * 只会 emit `.js`,Emscripten 运行时按 sibling 路径 fetch `.wasm` 会拿到 SPA fallback
6163
+ * 的 HTML,报 "expected magic word 00 61 73 6d, found 3c 21 44 4f"。
6164
+ * 解析出的 URL 通过 emscripten `locateFile` 钩子注入,覆盖默认 sibling 推断。
6130
6165
  */
6131
6166
  async function loadWasmModule() {
6167
+ // @ts-ignore - 构建时会被替换为实际值
6132
6168
  let wasmModule = null;
6133
- {
6134
- wasmModule = await Promise.resolve().then(function () { return ZHCanvasCore; });
6135
- }
6136
- // 使用单例:避免多线程下重复创建 pthread workers
6137
- let infiniteCanvas;
6169
+ let wasmBinaryUrl = null;
6170
+ wasmModule = await Promise.resolve().then(function () { return ZHCanvasCore; });
6171
+ try {
6172
+ wasmBinaryUrl = new URL(
6173
+ "../../wasm/ZHCanvasCore.wasm",
6174
+ (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)),
6175
+ ).href;
6176
+ } catch (_e) {
6177
+ wasmBinaryUrl = null;
6178
+ }
6179
+ let infiniteCanvas;
6138
6180
  try {
6139
6181
  infiniteCanvas = manager.getModule();
6140
6182
  }
6141
- catch (_a) {
6142
- manager.registerModuleFactory(() => wasmModule.default());
6183
+ catch (_c) {
6184
+ manager.registerModuleFactory(() => {
6185
+ const opts = {};
6186
+ if (wasmBinaryUrl) {
6187
+ // 关键:覆盖 emscripten 默认的 sibling 推断,强制用 bundler emit 出的带 hash URL。
6188
+ opts.locateFile = (path, prefix) => {
6189
+ if (path.endsWith(".wasm"))
6190
+ return wasmBinaryUrl;
6191
+ return prefix + path;
6192
+ };
6193
+ }
6194
+ return wasmModule.default(opts);
6195
+ });
6143
6196
  infiniteCanvas = await manager.getOrCreateModule();
6144
6197
  }
6145
6198
  TGFXBind(infiniteCanvas);
@@ -6156,7 +6209,7 @@ async function loadWasmModule() {
6156
6209
  // 注意:必须用独立的 ArrayBuffer,避免后续 transfer 让主线程的 fontData.array 失效。
6157
6210
  try {
6158
6211
  const standaloneBuffer = fontData.sourceHan.array.slice().buffer;
6159
- manager.cacheFontBuffers([
6212
+ manager.appendExportWorkerFontBuffers([
6160
6213
  { name: fontData.sourceHan.name, buffer: standaloneBuffer },
6161
6214
  ]);
6162
6215
  }
@@ -6604,10 +6657,13 @@ class ExportImageClient {
6604
6657
  }
6605
6658
  const { jsUrl: wasmUrl, wasmBinaryUrl } = this.wasmUrls_;
6606
6659
  const sessionLicense = this.sessionLicense_;
6607
- const fonts = this.fonts_;
6608
- this.initPromise_ = this.postRequest({ type: 'INIT', wasmUrl, wasmBinaryUrl, sessionLicense, fonts },
6609
- // 字体 buffer wasm 已 copy 到 heap,这里 transfer 给 worker 后主线程不再使用。
6610
- fonts.map((f) => f.buffer))
6660
+ // 拷贝后再 transfer:避免 postMessage transfer 把 manager 里缓存的 buffer detach,
6661
+ // 否则 worker reset 后无法再次 INIT
6662
+ const fonts = this.fonts_.map((f) => ({
6663
+ name: f.name,
6664
+ buffer: f.buffer.slice(0),
6665
+ }));
6666
+ this.initPromise_ = this.postRequest({ type: 'INIT', wasmUrl, wasmBinaryUrl, sessionLicense, fonts }, fonts.map((f) => f.buffer))
6611
6667
  .then(() => undefined)
6612
6668
  .catch((e) => {
6613
6669
  this.initPromise_ = null;