Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ resvg = { version = "0.34.0", default-features = false, features = [
"raster-images",
"text",
] }
console_error_panic_hook = "0.1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
napi = { version = "3", features = ["serde-json", "async"] }
Expand Down Expand Up @@ -64,5 +65,5 @@ panic = "unwind"
codegen-units = 1

[patch.crates-io]
resvg = { git = "https://github.com/zimond/resvg", rev = "3495d870" }
resvg = { git = "https://github.com/ptz0n/resvg", rev = "1759f23c3258328a2f3ae9bda2905b352143610b" }
woff2 = { git="https://github.com/yisibl/woff2-rs", branch="fix-total-compressed-size" }
13 changes: 13 additions & 0 deletions __test__/wasm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ test("should be no error: RuntimeError { message: 'unreachable', }", async (t) =
t.is(result.getHeight(), 300)
})

test('should not panic when a clipped group is entirely below the canvas', async (t) => {
const svg = `<svg viewBox="0 0 1200 630" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip"><rect x="0" y="0" width="1200" height="630"/></clipPath>
</defs>
<g clip-path="url(#clip)">
<rect x="0" y="1300" width="10" height="10" fill="#404040"/>
</g>
</svg>`
const resvg = new Resvg(svg)
t.notThrows(() => resvg.render())
})

test('buffer input', async (t) => {
const filePath = '../example/text.svg'
const svg = await fs.readFile(join(__dirname, filePath))
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@
"bundle:dts": "dts-bundle-generator --external-types -o wasm/index.d.ts wasm-binding.ts",
"build": "napi build --platform --release --js js-binding.js --dts js-binding.d.ts",
"build:debug": "napi build --platform --js js-binding.js --dts js-binding.d.ts",
"build:wasm": "run-s build:wasm-web copy-wasm bundle",
"build:wasm": "run-s build:wasm-web patch-wasm-reset copy-wasm bundle",
"build:wasm-web": "wasm-pack build --target web --out-name index --out-dir wasm/dist --release",
"patch-wasm-reset": "node scripts/patch-wasm-reset.mjs",
"copy-wasm": "copyfiles -f wasm/dist/index_bg.wasm ./wasm",
"playground": "copyfiles -f playground/index.html ./wasm",
"format": "run-p format:md format:json format:yaml format:source format:rs",
Expand Down
23 changes: 23 additions & 0 deletions scripts/patch-wasm-reset.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Adds an export to wasm-pack's generated wasm/dist/index.js that clears
// the module-level `wasm` singleton, letting resetWasm() force a fresh
// instance. Re-applied on every `wasm-pack build` (see build:wasm-web),
// so it survives the file being regenerated.
import { readFileSync, writeFileSync } from 'node:fs'

const marker = '// __resvgJsResetWasmModule patch'

const jsTarget = new URL('../wasm/dist/index.js', import.meta.url)
const jsSrc = readFileSync(jsTarget, 'utf8')
if (jsSrc.includes(marker)) {
console.log('patch-wasm-reset: already applied, skipping')
process.exit(0)
}
const jsAddition = `\n${marker}\nexport function __resvgJsResetWasmModule() {\n wasm = undefined;\n}\n`
writeFileSync(jsTarget, jsSrc + jsAddition)

const dtsTarget = new URL('../wasm/dist/index.d.ts', import.meta.url)
const dtsSrc = readFileSync(dtsTarget, 'utf8')
const dtsAddition = `\n${marker}\nexport function __resvgJsResetWasmModule(): void;\n`
writeFileSync(dtsTarget, dtsSrc + dtsAddition)

console.log('patch-wasm-reset: applied to wasm/dist/index.js and index.d.ts')
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ impl Resvg {
options: Option<String>,
custom_font_buffers: Option<js_sys::Array>,
) -> Result<Resvg, js_sys::Error> {
console_error_panic_hook::set_once();
let js_options: JsOptions = options
.and_then(|o| serde_json::from_str(o.as_str()).ok())
.unwrap_or_default();
Expand Down
13 changes: 12 additions & 1 deletion wasm-binding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import init, { Resvg as _Resvg, InitInput } from './wasm/dist'
import init, { Resvg as _Resvg, InitInput, __resvgJsResetWasmModule } from './wasm/dist'
import { CustomFontsOptions, ResvgRenderOptions, SystemFontsOptions } from './wasm/index'

let initialized = false
Expand All @@ -16,6 +16,17 @@ export const initWasm = async (module_or_path: Promise<InitInput> | InitInput):
initialized = true
}

/**
* Discard the current Wasm instance and initialize a fresh one (new linear memory).
* Only call this once no `Resvg`/`RenderedImage` from the old instance are still alive.
* @param module_or_path WebAssembly Module or .wasm url
*/
export const resetWasm = async (module_or_path: Promise<InitInput> | InitInput): Promise<void> => {
__resvgJsResetWasmModule()
await init(await module_or_path)
initialized = true
}

export const Resvg = class extends _Resvg {
/**
* @param {Uint8Array | string} svg
Expand Down
6 changes: 6 additions & 0 deletions wasm/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export type SystemFontsOptions = {
*
*/
export declare const initWasm: (module_or_path: Promise<InitInput> | InitInput) => Promise<void>;
/**
* Discard the current Wasm instance and initialize a fresh one (new linear memory).
* Only call this once no `Resvg`/`RenderedImage` from the old instance are still alive.
* @param module_or_path WebAssembly Module or .wasm url
*/
export declare const resetWasm: (module_or_path: Promise<InitInput> | InitInput) => Promise<void>;
export declare const Resvg: {
new (svg: Uint8Array | string, options?: ResvgRenderOptions): {
free(): void;
Expand Down
33 changes: 32 additions & 1 deletion wasm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
var wasm_binding_exports = {};
__export(wasm_binding_exports, {
Resvg: () => Resvg2,
initWasm: () => initWasm
initWasm: () => initWasm,
resetWasm: () => resetWasm
});
module.exports = __toCommonJS(wasm_binding_exports);

Expand Down Expand Up @@ -537,6 +538,28 @@ function __wbg_get_imports() {
const ret = getObject(arg0).push(getObject(arg1));
return ret;
};
imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
const ret = new Error();
return addHeapObject(ret);
};
imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
const ret = getObject(arg1).stack;
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
let deferred0_0;
let deferred0_1;
try {
deferred0_0 = arg0;
deferred0_1 = arg1;
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
}
};
imports.wbg.__wbg_length_c20a40f15020d68a = function(arg0) {
const ret = getObject(arg0).length;
return ret;
Expand Down Expand Up @@ -572,6 +595,9 @@ async function __wbg_init(input) {
return __wbg_finalize_init(instance, module2);
}
var dist_default = __wbg_init;
function __resvgJsResetWasmModule() {
wasm = void 0;
}

// wasm-binding.ts
var initialized = false;
Expand All @@ -582,6 +608,11 @@ var initWasm = async (module_or_path) => {
await dist_default(await module_or_path);
initialized = true;
};
var resetWasm = async (module_or_path) => {
__resvgJsResetWasmModule();
await dist_default(await module_or_path);
initialized = true;
};
var Resvg2 = class extends Resvg {
/**
* @param {Uint8Array | string} svg
Expand Down
2 changes: 1 addition & 1 deletion wasm/index.min.js

Large diffs are not rendered by default.

33 changes: 32 additions & 1 deletion wasm/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,28 @@ function __wbg_get_imports() {
const ret = getObject(arg0).push(getObject(arg1));
return ret;
};
imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
const ret = new Error();
return addHeapObject(ret);
};
imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
const ret = getObject(arg1).stack;
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len1;
getInt32Memory0()[arg0 / 4 + 0] = ptr1;
};
imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
let deferred0_0;
let deferred0_1;
try {
deferred0_0 = arg0;
deferred0_1 = arg1;
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
}
};
imports.wbg.__wbg_length_c20a40f15020d68a = function(arg0) {
const ret = getObject(arg0).length;
return ret;
Expand Down Expand Up @@ -545,6 +567,9 @@ async function __wbg_init(input) {
return __wbg_finalize_init(instance, module);
}
var dist_default = __wbg_init;
function __resvgJsResetWasmModule() {
wasm = void 0;
}

// wasm-binding.ts
var initialized = false;
Expand All @@ -555,6 +580,11 @@ var initWasm = async (module_or_path) => {
await dist_default(await module_or_path);
initialized = true;
};
var resetWasm = async (module_or_path) => {
__resvgJsResetWasmModule();
await dist_default(await module_or_path);
initialized = true;
};
var Resvg2 = class extends Resvg {
/**
* @param {Uint8Array | string} svg
Expand Down Expand Up @@ -582,5 +612,6 @@ function isCustomFontsOptions(value) {
}
export {
Resvg2 as Resvg,
initWasm
initWasm,
resetWasm
};
Binary file modified wasm/index_bg.wasm
Binary file not shown.