xbintsc 0.5.6 → 0.5.21
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/AGENTS.md +20 -10
- package/README.md +8 -7
- package/README.zh-CN.md +6 -6
- package/dist/src/binder/declarations.js +14 -3
- package/dist/src/binder/declarations.js.map +1 -1
- package/dist/src/cli/hints.js +7 -1
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +115 -15
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/watch.d.ts +25 -0
- package/dist/src/cli/watch.js +93 -0
- package/dist/src/cli/watch.js.map +1 -0
- package/dist/src/codegen/generator/calls/access.js +11 -2
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.js +12 -4
- package/dist/src/codegen/generator/calls/closures.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +8 -0
- package/dist/src/codegen/generator/context.js +22 -3
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/operators.js +17 -15
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.js +5 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/module.js +0 -7
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/numeric.d.ts +6 -3
- package/dist/src/codegen/generator/numeric.js +54 -11
- package/dist/src/codegen/generator/numeric.js.map +1 -1
- package/dist/src/codegen/generator/state.js +23 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +1 -4
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
- package/dist/src/codegen/generator/statements/loops.js +48 -16
- package/dist/src/codegen/generator/statements/loops.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +26 -1
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +3 -1
- package/dist/src/diagnostics/diagnostic.js +23 -3
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/driver/app-artifacts.d.ts +42 -0
- package/dist/src/driver/app-artifacts.js +53 -0
- package/dist/src/driver/app-artifacts.js.map +1 -0
- package/dist/src/driver/build-key.d.ts +29 -0
- package/dist/src/driver/build-key.js +35 -0
- package/dist/src/driver/build-key.js.map +1 -0
- package/dist/src/driver/bundler/graph.js +61 -12
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +7 -1
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +10 -67
- package/dist/src/driver/compiler.js +95 -234
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +3 -0
- package/dist/src/driver/config.js +8 -0
- package/dist/src/driver/config.js.map +1 -1
- package/dist/src/driver/frontend.d.ts +37 -0
- package/dist/src/driver/frontend.js +92 -0
- package/dist/src/driver/frontend.js.map +1 -0
- package/dist/src/driver/index.d.ts +1 -1
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/options.d.ts +64 -0
- package/dist/src/driver/options.js +9 -0
- package/dist/src/driver/options.js.map +1 -0
- package/dist/src/driver/runtime-objects.d.ts +38 -0
- package/dist/src/driver/runtime-objects.js +112 -0
- package/dist/src/driver/runtime-objects.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +4 -0
- package/dist/src/driver/toolchain-provider.js +4 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -1
- package/dist/src/driver/toolchain.d.ts +32 -1
- package/dist/src/driver/toolchain.js +115 -11
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/driver/version.d.ts +12 -0
- package/dist/src/driver/version.js +13 -0
- package/dist/src/driver/version.js.map +1 -0
- package/dist/src/driver/win-icon.d.ts +7 -9
- package/dist/src/driver/win-icon.js +37 -35
- package/dist/src/driver/win-icon.js.map +1 -1
- package/dist/src/extensions/node/fs/index.d.ts +4 -3
- package/dist/src/extensions/node/fs/index.js +12 -3
- package/dist/src/extensions/node/fs/index.js.map +1 -1
- package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
- package/dist/src/extensions/node/fs-promises/index.js +15 -6
- package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
- package/dist/src/parser/declarations/classes.js +5 -0
- package/dist/src/parser/declarations/classes.js.map +1 -1
- package/dist/src/parser/declarations/functions.js +13 -1
- package/dist/src/parser/declarations/functions.js.map +1 -1
- package/dist/src/parser/modules.js +8 -3
- package/dist/src/parser/modules.js.map +1 -1
- package/dist/src/parser/parser.d.ts +1 -0
- package/dist/src/parser/parser.js +23 -0
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/tests/cli/check.test.d.ts +6 -0
- package/dist/tests/cli/check.test.js +68 -0
- package/dist/tests/cli/check.test.js.map +1 -0
- package/dist/tests/cli/main.test.js +19 -0
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/cli/watch.test.d.ts +6 -0
- package/dist/tests/cli/watch.test.js +72 -0
- package/dist/tests/cli/watch.test.js.map +1 -0
- package/dist/tests/codegen/expressions.test.js +15 -3
- package/dist/tests/codegen/expressions.test.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +16 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/diagnostics/diagnostic.test.js +8 -0
- package/dist/tests/diagnostics/diagnostic.test.js.map +1 -1
- package/dist/tests/docs/structure.test.d.ts +1 -0
- package/dist/tests/docs/structure.test.js +92 -0
- package/dist/tests/docs/structure.test.js.map +1 -0
- package/dist/tests/driver/compiler.test.js +6 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/config.test.js +9 -0
- package/dist/tests/driver/config.test.js.map +1 -1
- package/dist/tests/driver/icon.test.js +19 -32
- package/dist/tests/driver/icon.test.js.map +1 -1
- package/dist/tests/driver/invalid-input.test.d.ts +10 -0
- package/dist/tests/driver/invalid-input.test.js +29 -0
- package/dist/tests/driver/invalid-input.test.js.map +1 -0
- package/dist/tests/driver/modules.test.js +42 -3
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/driver/toolchain-provider.test.js +27 -1
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +60 -2
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/array-buffer.test.d.ts +5 -0
- package/dist/tests/e2e/array-buffer.test.js +38 -0
- package/dist/tests/e2e/array-buffer.test.js.map +1 -0
- package/dist/tests/e2e/array-from-iterables.test.d.ts +7 -0
- package/dist/tests/e2e/array-from-iterables.test.js +34 -0
- package/dist/tests/e2e/array-from-iterables.test.js.map +1 -0
- package/dist/tests/e2e/array-symbol-iterator.test.d.ts +8 -0
- package/dist/tests/e2e/array-symbol-iterator.test.js +42 -0
- package/dist/tests/e2e/array-symbol-iterator.test.js.map +1 -0
- package/dist/tests/e2e/async-await.test.js +1 -1
- package/dist/tests/e2e/async-fs.test.d.ts +9 -0
- package/dist/tests/e2e/async-fs.test.js +119 -0
- package/dist/tests/e2e/async-fs.test.js.map +1 -0
- package/dist/tests/e2e/async-generators.test.d.ts +1 -0
- package/dist/tests/e2e/async-generators.test.js +154 -0
- package/dist/tests/e2e/async-generators.test.js.map +1 -0
- package/dist/tests/e2e/await-ordering.test.d.ts +5 -0
- package/dist/tests/e2e/await-ordering.test.js +37 -0
- package/dist/tests/e2e/await-ordering.test.js.map +1 -0
- package/dist/tests/e2e/compile-builtins.test.js +1 -1
- package/dist/tests/e2e/compile-modules.test.js +7 -0
- package/dist/tests/e2e/compile-modules.test.js.map +1 -1
- package/dist/tests/e2e/date-parse.test.d.ts +8 -0
- package/dist/tests/e2e/date-parse.test.js +38 -0
- package/dist/tests/e2e/date-parse.test.js.map +1 -0
- package/dist/tests/e2e/default-anonymous-exports.test.d.ts +7 -0
- package/dist/tests/e2e/default-anonymous-exports.test.js +23 -0
- package/dist/tests/e2e/default-anonymous-exports.test.js.map +1 -0
- package/dist/tests/e2e/fetch.test.js +24 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -1
- package/dist/tests/e2e/globals-microtask.test.d.ts +9 -0
- package/dist/tests/e2e/globals-microtask.test.js +37 -0
- package/dist/tests/e2e/globals-microtask.test.js.map +1 -0
- package/dist/tests/e2e/gui-inline-svg.test.d.ts +11 -0
- package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
- package/dist/tests/e2e/gui-inline-svg.test.js.map +1 -0
- package/dist/tests/e2e/gui-media.test.js +8 -1
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/inspect-builtins.test.d.ts +10 -0
- package/dist/tests/e2e/inspect-builtins.test.js +43 -0
- package/dist/tests/e2e/inspect-builtins.test.js.map +1 -0
- package/dist/tests/e2e/json-builtin-objects.test.d.ts +9 -0
- package/dist/tests/e2e/json-builtin-objects.test.js +23 -0
- package/dist/tests/e2e/json-builtin-objects.test.js.map +1 -0
- package/dist/tests/e2e/json-circular.test.d.ts +6 -0
- package/dist/tests/e2e/json-circular.test.js +43 -0
- package/dist/tests/e2e/json-circular.test.js.map +1 -0
- package/dist/tests/e2e/json-parse-reviver.test.d.ts +6 -0
- package/dist/tests/e2e/json-parse-reviver.test.js +29 -0
- package/dist/tests/e2e/json-parse-reviver.test.js.map +1 -0
- package/dist/tests/e2e/json-stringify-replacer.test.d.ts +6 -0
- package/dist/tests/e2e/json-stringify-replacer.test.js +27 -0
- package/dist/tests/e2e/json-stringify-replacer.test.js.map +1 -0
- package/dist/tests/e2e/json-stringify-space.test.d.ts +6 -0
- package/dist/tests/e2e/json-stringify-space.test.js +23 -0
- package/dist/tests/e2e/json-stringify-space.test.js.map +1 -0
- package/dist/tests/e2e/method-dispatch-errors.test.d.ts +9 -0
- package/dist/tests/e2e/method-dispatch-errors.test.js +38 -0
- package/dist/tests/e2e/method-dispatch-errors.test.js.map +1 -0
- package/dist/tests/e2e/native-extensions.test.js +1 -1
- package/dist/tests/e2e/native-extensions.test.js.map +1 -1
- package/dist/tests/e2e/promise-with-resolvers.test.d.ts +5 -0
- package/dist/tests/e2e/promise-with-resolvers.test.js +20 -0
- package/dist/tests/e2e/promise-with-resolvers.test.js.map +1 -0
- package/dist/tests/e2e/property-descriptors.test.d.ts +5 -0
- package/dist/tests/e2e/property-descriptors.test.js +25 -0
- package/dist/tests/e2e/property-descriptors.test.js.map +1 -0
- package/dist/tests/e2e/property-ic.test.d.ts +1 -0
- package/dist/tests/e2e/property-ic.test.js +55 -0
- package/dist/tests/e2e/property-ic.test.js.map +1 -0
- package/dist/tests/e2e/runtime-errors.test.d.ts +10 -0
- package/dist/tests/e2e/runtime-errors.test.js +52 -0
- package/dist/tests/e2e/runtime-errors.test.js.map +1 -0
- package/dist/tests/e2e/structured-clone.test.d.ts +6 -0
- package/dist/tests/e2e/structured-clone.test.js +49 -0
- package/dist/tests/e2e/structured-clone.test.js.map +1 -0
- package/dist/tests/e2e/text-codec.test.d.ts +6 -0
- package/dist/tests/e2e/text-codec.test.js +24 -0
- package/dist/tests/e2e/text-codec.test.js.map +1 -0
- package/dist/tests/e2e/typed-array-views.test.d.ts +6 -0
- package/dist/tests/e2e/typed-array-views.test.js +39 -0
- package/dist/tests/e2e/typed-array-views.test.js.map +1 -0
- package/dist/tests/e2e/url-search-params.test.d.ts +5 -0
- package/dist/tests/e2e/url-search-params.test.js +30 -0
- package/dist/tests/e2e/url-search-params.test.js.map +1 -0
- package/dist/tests/e2e/weak-collections.test.d.ts +1 -0
- package/dist/tests/e2e/weak-collections.test.js +88 -0
- package/dist/tests/e2e/weak-collections.test.js.map +1 -0
- package/dist/tests/parser/declarations.test.js +12 -0
- package/dist/tests/parser/declarations.test.js.map +1 -1
- package/dist/tests/parser/module-syntax.test.js +9 -0
- package/dist/tests/parser/module-syntax.test.js.map +1 -1
- package/dist/tests/parser/parser.test.js +7 -0
- package/dist/tests/parser/parser.test.js.map +1 -1
- package/dist/tests/version.test.js +5 -1
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/README.md +4 -3
- package/doc/ai/cli.md +41 -0
- package/doc/ai/contributing.md +20 -16
- package/doc/ai/extensions.md +13 -10
- package/doc/ai/language-support.md +19 -14
- package/doc/ai/troubleshooting.md +11 -9
- package/doc/ai/zh-CN/README.md +3 -2
- package/doc/ai/zh-CN/cli.md +35 -0
- package/doc/ai/zh-CN/contributing.md +16 -15
- package/doc/ai/zh-CN/extensions.md +12 -9
- package/doc/ai/zh-CN/language-support.md +19 -15
- package/doc/ai/zh-CN/troubleshooting.md +9 -8
- package/doc/gui/api.md +8 -0
- package/doc/gui/build.md +13 -4
- package/doc/gui/known-issues.md +19 -14
- package/doc/gui/media.md +32 -3
- package/doc/gui/rendering.md +3 -1
- package/doc/gui.md +28 -5
- package/doc/icon.md +5 -4
- package/doc/implemented/async.md +51 -0
- package/doc/implemented/binder.md +13 -0
- package/doc/implemented/cli.md +47 -0
- package/doc/implemented/codegen.md +33 -0
- package/doc/implemented/collections.md +26 -0
- package/doc/implemented/driver.md +19 -0
- package/doc/implemented/extensions.md +19 -0
- package/doc/implemented/fetch.md +44 -0
- package/doc/implemented/lexer.md +23 -0
- package/doc/implemented/modules.md +28 -0
- package/doc/implemented/node/assert.md +17 -0
- package/doc/implemented/node/buffer.md +29 -0
- package/doc/implemented/node/child-process.md +29 -0
- package/doc/implemented/node/crypto.md +9 -0
- package/doc/implemented/node/dgram.md +15 -0
- package/doc/implemented/node/events.md +37 -0
- package/doc/implemented/node/fs-promises.md +49 -0
- package/doc/implemented/node/fs.md +112 -0
- package/doc/implemented/node/http.md +21 -0
- package/doc/implemented/node/net.md +17 -0
- package/doc/implemented/node/os.md +22 -0
- package/doc/implemented/node/path.md +33 -0
- package/doc/implemented/node/process.md +23 -0
- package/doc/implemented/node/querystring.md +20 -0
- package/doc/implemented/node/stream-promises.md +8 -0
- package/doc/implemented/node/stream.md +19 -0
- package/doc/implemented/node/test.md +10 -0
- package/doc/implemented/node/url.md +8 -0
- package/doc/implemented/node/util.md +25 -0
- package/doc/implemented/node/worker-threads.md +10 -0
- package/doc/implemented/node/zlib.md +8 -0
- package/doc/implemented/node.md +48 -0
- package/doc/implemented/operators.md +38 -0
- package/doc/implemented/parser.md +58 -0
- package/doc/implemented/pipeline.md +28 -0
- package/doc/implemented/runtime-core.md +32 -0
- package/doc/implemented/stdlib.md +78 -0
- package/doc/implemented/strings.md +27 -0
- package/doc/implemented/tests.md +10 -0
- package/doc/implemented/typed-arrays.md +26 -0
- package/doc/implemented/value-model.md +18 -0
- package/doc/implemented.md +54 -355
- package/doc/node-implemented.md +3 -585
- package/doc/node-unimplemented.md +3 -164
- package/doc/requirements.md +23 -8
- package/doc/unimplemented/classes.md +22 -0
- package/doc/unimplemented/deviations.md +27 -0
- package/doc/unimplemented/expressions.md +26 -0
- package/doc/unimplemented/functions.md +21 -0
- package/doc/unimplemented/modules.md +22 -0
- package/doc/unimplemented/node/async.md +20 -0
- package/doc/unimplemented/node/bun.md +9 -0
- package/doc/unimplemented/node/fs-promises.md +20 -0
- package/doc/unimplemented/node/fs.md +30 -0
- package/doc/unimplemented/node/globals.md +23 -0
- package/doc/unimplemented/node/modules.md +21 -0
- package/doc/unimplemented/node.md +21 -0
- package/doc/unimplemented/statements.md +18 -0
- package/doc/unimplemented/stdlib.md +54 -0
- package/doc/unimplemented/toolchain.md +14 -0
- package/doc/unimplemented/types.md +12 -0
- package/doc/unimplemented.md +18 -275
- package/doc/xbintsc.config.schema.json +12 -0
- package/doc/zh-CN/gui/api.md +7 -0
- package/doc/zh-CN/gui/build.md +11 -3
- package/doc/zh-CN/gui/known-issues.md +17 -11
- package/doc/zh-CN/gui/media.md +26 -2
- package/doc/zh-CN/gui/rendering.md +2 -1
- package/doc/zh-CN/gui.md +21 -3
- package/doc/zh-CN/icon.md +5 -4
- package/doc/zh-CN/implemented/async.md +49 -0
- package/doc/zh-CN/implemented/binder.md +13 -0
- package/doc/zh-CN/implemented/cli.md +46 -0
- package/doc/zh-CN/implemented/codegen.md +33 -0
- package/doc/zh-CN/implemented/collections.md +26 -0
- package/doc/zh-CN/implemented/driver.md +19 -0
- package/doc/zh-CN/implemented/extensions.md +19 -0
- package/doc/zh-CN/implemented/fetch.md +31 -0
- package/doc/zh-CN/implemented/lexer.md +23 -0
- package/doc/zh-CN/implemented/modules.md +28 -0
- package/doc/zh-CN/implemented/node/assert.md +17 -0
- package/doc/zh-CN/implemented/node/buffer.md +25 -0
- package/doc/zh-CN/implemented/node/child-process.md +27 -0
- package/doc/zh-CN/implemented/node/crypto.md +9 -0
- package/doc/zh-CN/implemented/node/dgram.md +15 -0
- package/doc/zh-CN/implemented/node/events.md +36 -0
- package/doc/zh-CN/implemented/node/fs-promises.md +30 -0
- package/doc/zh-CN/implemented/node/fs.md +105 -0
- package/doc/zh-CN/implemented/node/http.md +17 -0
- package/doc/zh-CN/implemented/node/net.md +17 -0
- package/doc/zh-CN/implemented/node/os.md +21 -0
- package/doc/zh-CN/implemented/node/path.md +26 -0
- package/doc/zh-CN/implemented/node/process.md +23 -0
- package/doc/zh-CN/implemented/node/querystring.md +20 -0
- package/doc/zh-CN/implemented/node/stream-promises.md +8 -0
- package/doc/zh-CN/implemented/node/stream.md +15 -0
- package/doc/zh-CN/implemented/node/test.md +10 -0
- package/doc/zh-CN/implemented/node/url.md +8 -0
- package/doc/zh-CN/implemented/node/util.md +25 -0
- package/doc/zh-CN/implemented/node/worker-threads.md +9 -0
- package/doc/zh-CN/implemented/node/zlib.md +8 -0
- package/doc/zh-CN/implemented/node.md +45 -0
- package/doc/zh-CN/implemented/operators.md +38 -0
- package/doc/zh-CN/implemented/parser.md +58 -0
- package/doc/zh-CN/implemented/pipeline.md +25 -0
- package/doc/zh-CN/implemented/runtime-core.md +31 -0
- package/doc/zh-CN/implemented/stdlib.md +76 -0
- package/doc/zh-CN/implemented/strings.md +27 -0
- package/doc/zh-CN/implemented/tests.md +10 -0
- package/doc/zh-CN/implemented/typed-arrays.md +26 -0
- package/doc/zh-CN/implemented/value-model.md +18 -0
- package/doc/zh-CN/implemented.md +50 -350
- package/doc/zh-CN/node-implemented.md +4 -531
- package/doc/zh-CN/node-unimplemented.md +4 -139
- package/doc/zh-CN/plan-require-node-modules.md +4 -4
- package/doc/zh-CN/requirements.md +20 -6
- package/doc/zh-CN/unimplemented/classes.md +22 -0
- package/doc/zh-CN/unimplemented/deviations.md +24 -0
- package/doc/zh-CN/unimplemented/expressions.md +24 -0
- package/doc/zh-CN/unimplemented/functions.md +21 -0
- package/doc/zh-CN/unimplemented/modules.md +19 -0
- package/doc/zh-CN/unimplemented/node/async.md +20 -0
- package/doc/zh-CN/unimplemented/node/bun.md +8 -0
- package/doc/zh-CN/unimplemented/node/fs-promises.md +12 -0
- package/doc/zh-CN/unimplemented/node/fs.md +24 -0
- package/doc/zh-CN/unimplemented/node/globals.md +14 -0
- package/doc/zh-CN/unimplemented/node/modules.md +15 -0
- package/doc/zh-CN/unimplemented/node.md +18 -0
- package/doc/zh-CN/unimplemented/statements.md +15 -0
- package/doc/zh-CN/unimplemented/stdlib.md +54 -0
- package/doc/zh-CN/unimplemented/toolchain.md +14 -0
- package/doc/zh-CN/unimplemented/types.md +11 -0
- package/doc/zh-CN/unimplemented.md +14 -237
- package/llms.txt +32 -4
- package/package.json +1 -1
- package/runtime/ext_gui/inline_svg.cpp +219 -0
- package/runtime/ext_gui/inline_svg.h +41 -0
- package/runtime/ext_gui/layout.cpp +18 -0
- package/runtime/ext_gui/layout.h +7 -0
- package/runtime/ext_gui/layout_flow.cpp +4 -3
- package/runtime/ext_gui/paint.cpp +14 -0
- package/runtime/ext_gui/paint.h +5 -1
- package/runtime/ext_gui/renderer_image.cpp +53 -25
- package/runtime/ext_gui/renderer_shaders.h +2 -2
- package/runtime/ext_gui/stb_image.h +1 -17
- package/runtime/ext_gui/style_ua.cpp +3 -0
- package/runtime/ext_gui/svg.cpp +122 -39
- package/runtime/ext_gui/svg.h +14 -3
- package/runtime/ext_gui/window.cpp +28 -0
- package/runtime/ext_node/child_process/child_process.c +173 -73
- package/runtime/ext_node/fs/async_api.c +314 -0
- package/runtime/ext_node/fs/async_complete.c +99 -0
- package/runtime/ext_node/fs/async_fh.c +206 -0
- package/runtime/ext_node/fs/async_job.c +81 -0
- package/runtime/ext_node/fs/async_job.h +132 -0
- package/runtime/ext_node/fs/async_worker.c +534 -0
- package/runtime/ext_node/fs/async_worker_dir.c +439 -0
- package/runtime/ext_node/fs/async_worker_dir.h +33 -0
- package/runtime/ext_node/fs/async_worker_fd.c +74 -0
- package/runtime/ext_node/fs/dir.c +60 -15
- package/runtime/ext_node/fs/fs_common.h +9 -0
- package/runtime/ext_node/fs/fs_ops.c +18 -29
- package/runtime/ext_node/fs/parts/builtins.inc +34 -0
- package/runtime/ext_node/fs/parts/platform.inc +66 -0
- package/runtime/ext_node/fs/promises.c +44 -234
- package/runtime/rt.h +15 -0
- package/runtime/rt_internal.h +108 -0
- package/runtime/xt_alloc.c +43 -7
- package/runtime/xt_array_buffer.c +284 -0
- package/runtime/xt_async.c +46 -21
- package/runtime/xt_async_io.c +333 -0
- package/runtime/xt_async_io.h +47 -0
- package/runtime/xt_bigint/helpers.inc +3 -3
- package/runtime/xt_builtins.c +21 -17
- package/runtime/xt_constructors.c +12 -2
- package/runtime/xt_containers/access.inc +148 -3
- package/runtime/xt_containers/objects.inc +26 -2
- package/runtime/xt_containers/shapes.inc +71 -0
- package/runtime/xt_containers.c +1 -0
- package/runtime/xt_coroutine.c +17 -0
- package/runtime/xt_fetch/async.inc +295 -0
- package/runtime/xt_fetch/request.inc +6 -183
- package/runtime/xt_fetch/socket.inc +5 -4
- package/runtime/xt_fetch.c +6 -4
- package/runtime/xt_generator.c +299 -10
- package/runtime/xt_io/inspect.inc +112 -0
- package/runtime/xt_loop.c +79 -7
- package/runtime/xt_performance.c +37 -0
- package/runtime/xt_promise.c +63 -1
- package/runtime/xt_stdlib/arrays.inc +1 -1
- package/runtime/xt_stdlib/dispatch.inc +46 -11
- package/runtime/xt_stdlib/strings.inc +1 -1
- package/runtime/xt_stdlib2/array-statics.inc +25 -0
- package/runtime/xt_stdlib2/arrays.inc +5 -3
- package/runtime/xt_stdlib2/container.inc +5 -0
- package/runtime/xt_stdlib2/date.inc +111 -3
- package/runtime/xt_stdlib2/error.inc +24 -0
- package/runtime/xt_stdlib2/json.inc +310 -19
- package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
- package/runtime/xt_stdlib2/objects.inc +122 -0
- package/runtime/xt_stdlib2/set.inc +1 -1
- package/runtime/xt_structured_clone.c +159 -0
- package/runtime/xt_symbol.c +2 -2
- package/runtime/xt_text_codec.c +69 -0
- package/runtime/xt_typed_array/construction.inc +35 -5
- package/runtime/xt_typed_array/elements.inc +159 -0
- package/runtime/xt_typed_array/methods.inc +21 -5
- package/runtime/xt_typed_array.c +7 -10
- package/runtime/xt_url.c +375 -0
- package/runtime/xt_values/arithmetic.inc +2 -2
- package/runtime/xt_values/conversions.inc +1 -1
- package/runtime/xt_weak.c +281 -0
- package/scripts/build-gui.ts +133 -60
- package/scripts/check-version.ts +3 -3
- package/src/binder/declarations.ts +14 -3
- package/src/cli/hints.ts +8 -1
- package/src/cli/main.ts +119 -18
- package/src/cli/watch.ts +101 -0
- package/src/codegen/generator/calls/access.ts +10 -2
- package/src/codegen/generator/calls/closures.ts +12 -4
- package/src/codegen/generator/context.ts +23 -3
- package/src/codegen/generator/expressions/operators.ts +27 -13
- package/src/codegen/generator/expressions/primary.ts +4 -0
- package/src/codegen/generator/module.ts +0 -7
- package/src/codegen/generator/numeric.ts +85 -11
- package/src/codegen/generator/state.ts +23 -0
- package/src/codegen/generator/statements/control-flow.ts +1 -4
- package/src/codegen/generator/statements/loops.ts +50 -16
- package/src/codegen/generator/tables.ts +26 -1
- package/src/diagnostics/diagnostic.ts +23 -3
- package/src/driver/app-artifacts.ts +77 -0
- package/src/driver/build-key.ts +55 -0
- package/src/driver/bundler/graph.ts +63 -13
- package/src/driver/bundler/merge.ts +4 -1
- package/src/driver/compiler.ts +94 -328
- package/src/driver/config.ts +11 -0
- package/src/driver/frontend.ts +120 -0
- package/src/driver/index.ts +0 -1
- package/src/driver/options.ts +70 -0
- package/src/driver/runtime-objects.ts +134 -0
- package/src/driver/toolchain-provider.ts +4 -0
- package/src/driver/toolchain.ts +154 -10
- package/src/driver/version.ts +12 -0
- package/src/driver/win-icon.ts +36 -36
- package/src/extensions/node/fs/index.ts +12 -3
- package/src/extensions/node/fs-promises/index.ts +15 -6
- package/src/parser/declarations/classes.ts +4 -0
- package/src/parser/declarations/functions.ts +12 -1
- package/src/parser/modules.ts +8 -4
- package/src/parser/parser.ts +28 -0
|
@@ -44,7 +44,8 @@ float Layouter::verticalEdges(const LayoutBox *box) const {
|
|
|
44
44
|
float Layouter::preferredContentWidth(const LayoutBox *box, float available) const {
|
|
45
45
|
const XtStyle &style = *box->style;
|
|
46
46
|
if (!isAuto(style.width)) return px(style.width, available, style.font_size, 0.0f);
|
|
47
|
-
if ((box->is_image || box->is_canvas) && box->intrinsic_width > 0)
|
|
47
|
+
if ((box->is_image || box->is_canvas || box->is_inline_svg) && box->intrinsic_width > 0)
|
|
48
|
+
return box->intrinsic_width;
|
|
48
49
|
float best = 0;
|
|
49
50
|
for (const std::unique_ptr<LayoutBox> &child : box->children) {
|
|
50
51
|
if (child->display == Display::None) continue;
|
|
@@ -225,8 +226,8 @@ float Layouter::layoutBlock(LayoutBox *box, float x, float y, float availableWid
|
|
|
225
226
|
if (contentHeight < 0) contentHeight = 0;
|
|
226
227
|
}
|
|
227
228
|
/* Replaced elements keep their aspect ratio when only one axis is set. */
|
|
228
|
-
if ((box->is_image || box->is_canvas) && forcedContentHeight < 0 &&
|
|
229
|
-
box->intrinsic_width > 0 && box->intrinsic_height > 0) {
|
|
229
|
+
if ((box->is_image || box->is_canvas || box->is_inline_svg) && forcedContentHeight < 0 &&
|
|
230
|
+
isAuto(style.height) && box->intrinsic_width > 0 && box->intrinsic_height > 0) {
|
|
230
231
|
contentHeight = contentWidth * box->intrinsic_height / box->intrinsic_width;
|
|
231
232
|
}
|
|
232
233
|
box->content_height = contentHeight;
|
|
@@ -187,6 +187,16 @@ void paintBox(const LayoutBox *box, DisplayList &out, const PaintClip &clip) {
|
|
|
187
187
|
image.media_id = box->media_id;
|
|
188
188
|
image.transform = matrix;
|
|
189
189
|
addImage(image, out, clip);
|
|
190
|
+
} else if (box->is_inline_svg && !box->svg_markup.empty() && box->content_width > 0.0f &&
|
|
191
|
+
box->content_height > 0.0f) {
|
|
192
|
+
PaintImage image;
|
|
193
|
+
image.x = box->content_x;
|
|
194
|
+
image.y = box->content_y;
|
|
195
|
+
image.width = box->content_width;
|
|
196
|
+
image.height = box->content_height;
|
|
197
|
+
image.svg = box->svg_markup;
|
|
198
|
+
image.transform = matrix;
|
|
199
|
+
addImage(image, out, clip);
|
|
190
200
|
} else if (box->is_image && !box->image_src.empty() && box->content_width > 0.0f &&
|
|
191
201
|
box->content_height > 0.0f) {
|
|
192
202
|
PaintImage image;
|
|
@@ -243,6 +253,10 @@ std::string DisplayList::dump() const {
|
|
|
243
253
|
std::snprintf(buffer, sizeof(buffer), "image x=%.1f y=%.1f w=%.1f h=%.1f media=%llu",
|
|
244
254
|
image.x, image.y, image.width, image.height,
|
|
245
255
|
(unsigned long long)image.media_id);
|
|
256
|
+
} else if (!image.svg.empty()) {
|
|
257
|
+
std::snprintf(buffer, sizeof(buffer),
|
|
258
|
+
"image x=%.1f y=%.1f w=%.1f h=%.1f inline-svg=%zu", image.x, image.y,
|
|
259
|
+
image.width, image.height, image.svg.size());
|
|
246
260
|
} else if (image.canvas_id != 0) {
|
|
247
261
|
std::snprintf(buffer, sizeof(buffer), "image x=%.1f y=%.1f w=%.1f h=%.1f canvas=%llu",
|
|
248
262
|
image.x, image.y, image.width, image.height,
|
package/runtime/ext_gui/paint.h
CHANGED
|
@@ -51,13 +51,17 @@ struct PaintText {
|
|
|
51
51
|
/** An image to draw, scaled into the given rectangle (viewport-relative).
|
|
52
52
|
* A non-zero `media_id` names a live `<video>` frame owned by the media
|
|
53
53
|
* subsystem; a non-zero `canvas_id` names a live `<canvas>` bitmap owned by the
|
|
54
|
-
* DOM; `src` is then empty and the renderer binds that subsystem's texture.
|
|
54
|
+
* DOM; `src` is then empty and the renderer binds that subsystem's texture.
|
|
55
|
+
* A non-empty `svg` carries the serialized `<svg>` subtree of an inline SVG
|
|
56
|
+
* element, which the renderer rasterises at the drawn device size (there is no
|
|
57
|
+
* file to load). */
|
|
55
58
|
struct PaintImage {
|
|
56
59
|
float x = 0;
|
|
57
60
|
float y = 0;
|
|
58
61
|
float width = 0;
|
|
59
62
|
float height = 0;
|
|
60
63
|
std::string src;
|
|
64
|
+
std::string svg;
|
|
61
65
|
uint64_t media_id = 0;
|
|
62
66
|
uint64_t canvas_id = 0;
|
|
63
67
|
Matrix2D transform;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include "canvas.h"
|
|
13
13
|
#include "image.h"
|
|
14
14
|
#include "media.h"
|
|
15
|
+
#include "svg.h"
|
|
15
16
|
|
|
16
17
|
#include "renderer_shaders.h"
|
|
17
18
|
|
|
@@ -227,6 +228,32 @@ SDL_GPUGraphicsPipeline *createImagePipeline(SDL_GPUDevice *device, SDL_Window *
|
|
|
227
228
|
return pipeline;
|
|
228
229
|
}
|
|
229
230
|
|
|
231
|
+
/** Create an RGBA texture holding `image` and upload its pixels. Returns null
|
|
232
|
+
* (after reporting the SDL error) when either step fails. */
|
|
233
|
+
SDL_GPUTexture *createImageTexture(SDL_GPUDevice *device, const xtgui::Image &image) {
|
|
234
|
+
SDL_GPUTextureCreateInfo info;
|
|
235
|
+
memset(&info, 0, sizeof(info));
|
|
236
|
+
info.type = SDL_GPU_TEXTURETYPE_2D;
|
|
237
|
+
info.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
238
|
+
info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
|
239
|
+
info.width = (Uint32)image.width;
|
|
240
|
+
info.height = (Uint32)image.height;
|
|
241
|
+
info.layer_count_or_depth = 1;
|
|
242
|
+
info.num_levels = 1;
|
|
243
|
+
info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
|
244
|
+
SDL_GPUTexture *texture = SDL_CreateGPUTexture(device, &info);
|
|
245
|
+
if (texture == nullptr) {
|
|
246
|
+
fprintf(stderr, "xt_gui: image texture creation failed: %s\n", SDL_GetError());
|
|
247
|
+
return nullptr;
|
|
248
|
+
}
|
|
249
|
+
uint32_t bytes = (uint32_t)(image.pixels.size());
|
|
250
|
+
if (!uploadPixels(device, texture, image.width, image.height, image.pixels.data(), bytes)) {
|
|
251
|
+
SDL_ReleaseGPUTexture(device, texture);
|
|
252
|
+
return nullptr;
|
|
253
|
+
}
|
|
254
|
+
return texture;
|
|
255
|
+
}
|
|
256
|
+
|
|
230
257
|
/** Decode `src` (cached) and upload it as an RGBA texture. Vector sources are
|
|
231
258
|
* rasterised at the drawn pixel size and cached by that size; bitmaps decode at
|
|
232
259
|
* their intrinsic size and are cached by path. */
|
|
@@ -246,30 +273,29 @@ SDL_GPUTexture *ensureImageTexture(SDL_GPUDevice *device, const std::string &src
|
|
|
246
273
|
return nullptr;
|
|
247
274
|
}
|
|
248
275
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
info.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
|
254
|
-
info.width = (Uint32)image->width;
|
|
255
|
-
info.height = (Uint32)image->height;
|
|
256
|
-
info.layer_count_or_depth = 1;
|
|
257
|
-
info.num_levels = 1;
|
|
258
|
-
info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
|
259
|
-
SDL_GPUTexture *texture = SDL_CreateGPUTexture(device, &info);
|
|
260
|
-
if (texture == nullptr) {
|
|
261
|
-
fprintf(stderr, "xt_gui: image texture creation failed: %s\n", SDL_GetError());
|
|
262
|
-
g_image_textures.emplace(key, nullptr);
|
|
263
|
-
return nullptr;
|
|
264
|
-
}
|
|
276
|
+
SDL_GPUTexture *texture = createImageTexture(device, *image);
|
|
277
|
+
g_image_textures.emplace(key, texture);
|
|
278
|
+
return texture;
|
|
279
|
+
}
|
|
265
280
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
281
|
+
/** Rasterise the serialized subtree of an inline `<svg>` at the drawn pixel
|
|
282
|
+
* size and upload it. The markup is the cache key: a static document therefore
|
|
283
|
+
* rasterises once per drawn size, and an edited one gets a fresh texture. */
|
|
284
|
+
SDL_GPUTexture *ensureInlineSvgTexture(SDL_GPUDevice *device, const std::string &markup,
|
|
285
|
+
int pixel_width, int pixel_height) {
|
|
286
|
+
std::string key = "inline-svg@" + std::to_string(pixel_width) + "x" +
|
|
287
|
+
std::to_string(pixel_height) + ":" + markup;
|
|
288
|
+
auto found = g_image_textures.find(key);
|
|
289
|
+
if (found != g_image_textures.end()) return found->second;
|
|
290
|
+
|
|
291
|
+
xtgui::Image image;
|
|
292
|
+
if (!xtgui::xt_svg_markup_render(markup, pixel_width, pixel_height, &image)) {
|
|
293
|
+
fprintf(stderr, "xt_gui: could not rasterise inline SVG\n");
|
|
269
294
|
g_image_textures.emplace(key, nullptr);
|
|
270
295
|
return nullptr;
|
|
271
296
|
}
|
|
272
297
|
|
|
298
|
+
SDL_GPUTexture *texture = createImageTexture(device, image);
|
|
273
299
|
g_image_textures.emplace(key, texture);
|
|
274
300
|
return texture;
|
|
275
301
|
}
|
|
@@ -298,18 +324,20 @@ void xt_gui_image_upload(SDL_GPUDevice *device, XtGuiGeometry *geometry,
|
|
|
298
324
|
for (size_t index = 0; index < list.images.size(); index++) {
|
|
299
325
|
const xtgui::PaintImage &image = list.images[index];
|
|
300
326
|
if (image.width <= 0.0f || image.height <= 0.0f) continue;
|
|
327
|
+
/* Draw-time device pixels: an SVG (file or inline) is rasterised at this
|
|
328
|
+
* size so it stays crisp on HiDPI and when scaled. */
|
|
329
|
+
int pixel_width = (int)(image.width * scale + 0.5f);
|
|
330
|
+
int pixel_height = (int)(image.height * scale + 0.5f);
|
|
331
|
+
if (pixel_width < 1) pixel_width = 1;
|
|
332
|
+
if (pixel_height < 1) pixel_height = 1;
|
|
301
333
|
SDL_GPUTexture *texture = nullptr;
|
|
302
334
|
if (image.canvas_id != 0) {
|
|
303
335
|
texture = ensureCanvasTexture(device, image.canvas_id);
|
|
304
336
|
} else if (image.media_id != 0) {
|
|
305
337
|
texture = ensureMediaTexture(device, image.media_id);
|
|
338
|
+
} else if (!image.svg.empty()) {
|
|
339
|
+
texture = ensureInlineSvgTexture(device, image.svg, pixel_width, pixel_height);
|
|
306
340
|
} else {
|
|
307
|
-
/* Draw-time device pixels: an SVG is rasterised at this size so it stays
|
|
308
|
-
* crisp on HiDPI and when scaled. */
|
|
309
|
-
int pixel_width = (int)(image.width * scale + 0.5f);
|
|
310
|
-
int pixel_height = (int)(image.height * scale + 0.5f);
|
|
311
|
-
if (pixel_width < 1) pixel_width = 1;
|
|
312
|
-
if (pixel_height < 1) pixel_height = 1;
|
|
313
341
|
texture = ensureImageTexture(device, image.src, pixel_width, pixel_height);
|
|
314
342
|
}
|
|
315
343
|
if (texture == nullptr) continue;
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* them, one per SDL_GPU backend:
|
|
7
7
|
*
|
|
8
8
|
* - Metal: the MSL string literals below, which SDL_GPU compiles at runtime.
|
|
9
|
-
* - Vulkan: SPIR-V blobs in `renderer_shaders_data.h`, compiled from
|
|
10
|
-
*
|
|
9
|
+
* - Vulkan: SPIR-V blobs in `renderer_shaders_data.h`, compiled from the
|
|
10
|
+
* `.vert`/`.frag` sources in `spirv/` by `scripts/build-gui-shaders.mjs`.
|
|
11
11
|
* - Direct3D 12: DXIL blobs from the same header, compiled from `shaders.hlsl`.
|
|
12
12
|
*
|
|
13
13
|
* `selectShader` resolves a logical program and stage to whichever of those the
|
|
@@ -706,21 +706,6 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
|
|
706
706
|
#define STBI_NO_SIMD
|
|
707
707
|
#endif
|
|
708
708
|
|
|
709
|
-
#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD)
|
|
710
|
-
// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET
|
|
711
|
-
//
|
|
712
|
-
// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the
|
|
713
|
-
// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant.
|
|
714
|
-
// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not
|
|
715
|
-
// simultaneously enabling "-mstackrealign".
|
|
716
|
-
//
|
|
717
|
-
// See https://github.com/nothings/stb/issues/81 for more information.
|
|
718
|
-
//
|
|
719
|
-
// So default to no SSE2 on 32-bit MinGW. If you've read this far and added
|
|
720
|
-
// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2.
|
|
721
|
-
#define STBI_NO_SIMD
|
|
722
|
-
#endif
|
|
723
|
-
|
|
724
709
|
#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
|
|
725
710
|
#define STBI_SSE2
|
|
726
711
|
#include <emmintrin.h>
|
|
@@ -7805,10 +7790,9 @@ STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user
|
|
|
7805
7790
|
bug with < 92 byte PIC,PNM,HDR,TGA
|
|
7806
7791
|
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
|
|
7807
7792
|
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
|
|
7808
|
-
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
|
|
7809
7793
|
2.03 (2015-04-12) extra corruption checking (mmozeiko)
|
|
7810
7794
|
stbi_set_flip_vertically_on_load (nguillemot)
|
|
7811
|
-
fix NEON support
|
|
7795
|
+
fix NEON support
|
|
7812
7796
|
2.02 (2015-01-19) fix incorrect assert, fix warning
|
|
7813
7797
|
2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2
|
|
7814
7798
|
2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
|
|
@@ -40,6 +40,9 @@ void xt_style_apply_user_agent(const Node *node, XtStyle *style) {
|
|
|
40
40
|
style->display = Display::InlineBlock;
|
|
41
41
|
}
|
|
42
42
|
if (tag == "img") style->display = Display::InlineBlock;
|
|
43
|
+
/* An inline `<svg>` is a replaced inline-block too: its intrinsic size comes
|
|
44
|
+
* from the SVG document and its subtree is vector art, not HTML boxes. */
|
|
45
|
+
if (tag == "svg") style->display = Display::InlineBlock;
|
|
43
46
|
/* `<video>` mirrors `<img>` (a replaced inline-block; 300x150 by default from
|
|
44
47
|
* layout), while `<audio>` and its `<source>`/`<track>` children have no
|
|
45
48
|
* rendered box of their own. */
|
package/runtime/ext_gui/svg.cpp
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The heavy lifting is the vendored NanoSVG library (`nanosvg.h` +
|
|
5
5
|
* `nanosvgrast.h`, zlib licence, fetched verbatim). This file is only the glue:
|
|
6
|
-
* path detection,
|
|
7
|
-
* emits straight (non-premultiplied) RGBA8,
|
|
8
|
-
* layout the rest of the engine expects.
|
|
6
|
+
* path detection, parsed-document caches (per file and per inline markup) and
|
|
7
|
+
* the scale-to-fit call. NanoSVG emits straight (non-premultiplied) RGBA8,
|
|
8
|
+
* which is exactly the `Image` layout the rest of the engine expects.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
#include "svg.h"
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
#include <algorithm>
|
|
33
33
|
#include <cctype>
|
|
34
|
+
#include <cstdint>
|
|
34
35
|
#include <cstdio>
|
|
35
36
|
#include <fstream>
|
|
36
37
|
#include <string>
|
|
@@ -89,16 +90,13 @@ NSVGrasterizer *&rasterizer() {
|
|
|
89
90
|
return value;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
/**
|
|
93
|
-
*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
cache.emplace(path, image);
|
|
100
|
-
return image;
|
|
101
|
-
}
|
|
93
|
+
/** One parsed inline-SVG document in the markup cache. `stamp` is the last use
|
|
94
|
+
* (see `parseMarkup`); `image` is null when the markup failed to parse so a
|
|
95
|
+
* broken document is not retried on every layout. */
|
|
96
|
+
struct MarkupDocument {
|
|
97
|
+
NSVGimage *image = nullptr;
|
|
98
|
+
uint64_t stamp = 0;
|
|
99
|
+
};
|
|
102
100
|
|
|
103
101
|
float intrinsicWidth(const NSVGimage *image) {
|
|
104
102
|
return image->width > 0.0f ? image->width : kDefaultWidth;
|
|
@@ -108,33 +106,53 @@ float intrinsicHeight(const NSVGimage *image) {
|
|
|
108
106
|
return image->height > 0.0f ? image->height : kDefaultHeight;
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
|
|
109
|
+
/** Inline SVG markup is authored in the document and can change at any time, so
|
|
110
|
+
* unlike the per-path file cache this one is bounded: a script that animates an
|
|
111
|
+
* inline `<svg>` attribute every frame would otherwise add one parse (and its
|
|
112
|
+
* NSVGimage tree) per frame forever. */
|
|
113
|
+
constexpr size_t kMaxMarkupDocuments = 256;
|
|
112
114
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (found != cache.end()) return found->second;
|
|
117
|
-
bool result = hasSvgExtension(path) || prefixLooksLikeSvg(path);
|
|
118
|
-
cache.emplace(path, result);
|
|
119
|
-
return result;
|
|
115
|
+
std::unordered_map<std::string, MarkupDocument> &markupCache() {
|
|
116
|
+
static std::unordered_map<std::string, MarkupDocument> cache;
|
|
117
|
+
return cache;
|
|
120
118
|
}
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
float w = intrinsicWidth(image);
|
|
126
|
-
float h = intrinsicHeight(image);
|
|
127
|
-
if (w <= 0.0f || h <= 0.0f) return false;
|
|
128
|
-
if (width != nullptr) *width = (int)(w + 0.5f);
|
|
129
|
-
if (height != nullptr) *height = (int)(h + 0.5f);
|
|
130
|
-
return true;
|
|
120
|
+
uint64_t nextStamp() {
|
|
121
|
+
static uint64_t counter = 0;
|
|
122
|
+
return ++counter;
|
|
131
123
|
}
|
|
132
124
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
125
|
+
/** Parse an inline SVG document once and remember the result. Evicts the
|
|
126
|
+
* least-recently-used entry when the table is full; nothing outside this module
|
|
127
|
+
* keeps an `NSVGimage*`, so a parse can always be dropped safely. */
|
|
128
|
+
NSVGimage *parseMarkup(const std::string &markup) {
|
|
129
|
+
auto &cache = markupCache();
|
|
130
|
+
uint64_t stamp = nextStamp();
|
|
131
|
+
auto found = cache.find(markup);
|
|
132
|
+
if (found != cache.end()) {
|
|
133
|
+
found->second.stamp = stamp;
|
|
134
|
+
return found->second.image;
|
|
135
|
+
}
|
|
136
|
+
if (cache.size() >= kMaxMarkupDocuments) {
|
|
137
|
+
auto oldest = cache.begin();
|
|
138
|
+
for (auto it = cache.begin(); it != cache.end(); ++it) {
|
|
139
|
+
if (it->second.stamp < oldest->second.stamp) oldest = it;
|
|
140
|
+
}
|
|
141
|
+
if (oldest->second.image != nullptr) nsvgDelete(oldest->second.image);
|
|
142
|
+
cache.erase(oldest);
|
|
143
|
+
}
|
|
144
|
+
/* NanoSVG's XML parser NUL-terminates tags in place, so it needs its own
|
|
145
|
+
* mutable copy of the document. */
|
|
146
|
+
std::string document = markup;
|
|
147
|
+
NSVGimage *image = nsvgParse(document.data(), "px", 96.0f);
|
|
148
|
+
cache.emplace(markup, MarkupDocument{image, stamp});
|
|
149
|
+
return image;
|
|
150
|
+
}
|
|
137
151
|
|
|
152
|
+
/** Rasterise a parsed document at `width` x `height` device pixels, at the
|
|
153
|
+
* larger axis scale so neither axis is under-sampled. Returns false when the
|
|
154
|
+
* size is unusable or the rasteriser cannot be created. */
|
|
155
|
+
bool rasterize(NSVGimage *image, int width, int height, Image *out) {
|
|
138
156
|
float source_width = intrinsicWidth(image);
|
|
139
157
|
float source_height = intrinsicHeight(image);
|
|
140
158
|
int target_width = width > 0 ? width : (int)(source_width + 0.5f);
|
|
@@ -143,11 +161,6 @@ bool xt_svg_render(const std::string &path, int width, int height, Image *out) {
|
|
|
143
161
|
target_width = std::min(target_width, kMaxDimension);
|
|
144
162
|
target_height = std::min(target_height, kMaxDimension);
|
|
145
163
|
|
|
146
|
-
/* Rasterise at the source aspect ratio, at the larger of the two axis scales
|
|
147
|
-
* (so neither axis is under-sampled), then let the quad stretch the texture
|
|
148
|
-
* to the box — exactly how a bitmap would behave under CSS `object-fit:
|
|
149
|
-
* fill`. The common case (layout preserved the aspect ratio) makes this equal
|
|
150
|
-
* to the requested size. */
|
|
151
164
|
float scale = std::max((float)target_width / source_width, (float)target_height / source_height);
|
|
152
165
|
scale = std::min(scale, (float)kMaxDimension / source_width);
|
|
153
166
|
scale = std::min(scale, (float)kMaxDimension / source_height);
|
|
@@ -167,12 +180,82 @@ bool xt_svg_render(const std::string &path, int width, int height, Image *out) {
|
|
|
167
180
|
return true;
|
|
168
181
|
}
|
|
169
182
|
|
|
183
|
+
/** Parse `path` once and remember the result (including failures, so a missing
|
|
184
|
+
* file is not retried every frame). */
|
|
185
|
+
NSVGimage *parseCached(const std::string &path) {
|
|
186
|
+
auto &cache = parsedCache();
|
|
187
|
+
auto found = cache.find(path);
|
|
188
|
+
if (found != cache.end()) return found->second;
|
|
189
|
+
NSVGimage *image = nsvgParseFromFile(path.c_str(), "px", 96.0f);
|
|
190
|
+
cache.emplace(path, image);
|
|
191
|
+
return image;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
} // namespace
|
|
195
|
+
|
|
196
|
+
bool xt_svg_is_svg(const std::string &path) {
|
|
197
|
+
auto &cache = detectCache();
|
|
198
|
+
auto found = cache.find(path);
|
|
199
|
+
if (found != cache.end()) return found->second;
|
|
200
|
+
bool result = hasSvgExtension(path) || prefixLooksLikeSvg(path);
|
|
201
|
+
cache.emplace(path, result);
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
bool xt_svg_size(const std::string &path, int *width, int *height) {
|
|
206
|
+
NSVGimage *image = parseCached(path);
|
|
207
|
+
if (image == nullptr) return false;
|
|
208
|
+
float w = intrinsicWidth(image);
|
|
209
|
+
float h = intrinsicHeight(image);
|
|
210
|
+
if (w <= 0.0f || h <= 0.0f) return false;
|
|
211
|
+
if (width != nullptr) *width = (int)(w + 0.5f);
|
|
212
|
+
if (height != nullptr) *height = (int)(h + 0.5f);
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
bool xt_svg_render(const std::string &path, int width, int height, Image *out) {
|
|
217
|
+
if (out == nullptr) return false;
|
|
218
|
+
NSVGimage *image = parseCached(path);
|
|
219
|
+
if (image == nullptr) return false;
|
|
220
|
+
return rasterize(image, width, height, out);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
bool xt_svg_markup_size(const std::string &markup, int *width, int *height) {
|
|
224
|
+
NSVGimage *image = parseMarkup(markup);
|
|
225
|
+
if (image == nullptr) return false;
|
|
226
|
+
float w = intrinsicWidth(image);
|
|
227
|
+
float h = intrinsicHeight(image);
|
|
228
|
+
if (w <= 0.0f || h <= 0.0f) return false;
|
|
229
|
+
if (width != nullptr) *width = (int)(w + 0.5f);
|
|
230
|
+
if (height != nullptr) *height = (int)(h + 0.5f);
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
bool xt_svg_markup_render(const std::string &markup, int width, int height, Image *out) {
|
|
235
|
+
if (out == nullptr) return false;
|
|
236
|
+
NSVGimage *image = parseMarkup(markup);
|
|
237
|
+
if (image == nullptr) return false;
|
|
238
|
+
return rasterize(image, width, height, out);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
int xt_svg_markup_shapes(const std::string &markup) {
|
|
242
|
+
NSVGimage *image = parseMarkup(markup);
|
|
243
|
+
if (image == nullptr) return 0;
|
|
244
|
+
int count = 0;
|
|
245
|
+
for (const NSVGshape *shape = image->shapes; shape != nullptr; shape = shape->next) count++;
|
|
246
|
+
return count;
|
|
247
|
+
}
|
|
248
|
+
|
|
170
249
|
void xt_svg_shutdown() {
|
|
171
250
|
for (auto &entry : parsedCache()) {
|
|
172
251
|
if (entry.second != nullptr) nsvgDelete(entry.second);
|
|
173
252
|
}
|
|
174
253
|
parsedCache().clear();
|
|
175
254
|
detectCache().clear();
|
|
255
|
+
for (auto &entry : markupCache()) {
|
|
256
|
+
if (entry.second.image != nullptr) nsvgDelete(entry.second.image);
|
|
257
|
+
}
|
|
258
|
+
markupCache().clear();
|
|
176
259
|
if (rasterizer() != nullptr) {
|
|
177
260
|
nsvgDeleteRasterizer(rasterizer());
|
|
178
261
|
rasterizer() = nullptr;
|
package/runtime/ext_gui/svg.h
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
* (`nanosvg.h` + `nanosvgrast.h`) — the same class of low-level, third-party
|
|
10
10
|
* image library `stb_image` is (see doc/gui.md).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Both SVG *files* (`<img src="logo.svg">`) and inline `<svg>` trees go through
|
|
13
|
+
* this module: an inline element's DOM subtree is serialized into a document by
|
|
14
|
+
* `inline_svg.{h,cpp}` and parsed with the markup entry points below, so both
|
|
15
|
+
* kinds produce the same RGBA8 `Image` at the drawn device size.
|
|
15
16
|
*/
|
|
16
17
|
#ifndef XT_GUI_SVG_H
|
|
17
18
|
#define XT_GUI_SVG_H
|
|
@@ -30,6 +31,16 @@ bool xt_svg_is_svg(const std::string &path);
|
|
|
30
31
|
* false when the file is missing or cannot be parsed. Cached per path. */
|
|
31
32
|
bool xt_svg_size(const std::string &path, int *width, int *height);
|
|
32
33
|
|
|
34
|
+
/** The same two operations for an SVG *document string* rather than a file:
|
|
35
|
+
* the markup of an inline `<svg>` subtree (see `inline_svg.h`). The parse is
|
|
36
|
+
* cached by content (least-recently-used, so an animated document cannot grow
|
|
37
|
+
* the cache without bound); each rasterisation is fresh. */
|
|
38
|
+
bool xt_svg_markup_size(const std::string &markup, int *width, int *height);
|
|
39
|
+
bool xt_svg_markup_render(const std::string &markup, int width, int height, Image *out);
|
|
40
|
+
|
|
41
|
+
/** Number of shapes NanoSVG parsed out of `markup` (diagnostics/tests). */
|
|
42
|
+
int xt_svg_markup_shapes(const std::string &markup);
|
|
43
|
+
|
|
33
44
|
/** Rasterise `path` to RGBA8. `width`/`height` are the requested pixel size;
|
|
34
45
|
* when either is `<= 0` the intrinsic SVG size is used. The viewBox is scaled
|
|
35
46
|
* uniformly at the larger of the two axis scales (preserving the SVG's aspect
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
#include <algorithm>
|
|
14
14
|
|
|
15
|
+
#include "inline_svg.h"
|
|
15
16
|
#include "paint.h"
|
|
16
17
|
#include "text.h"
|
|
17
18
|
|
|
@@ -216,6 +217,32 @@ static xt_value win_paint_count(xt_value self, xt_value env, int32_t argc, xt_va
|
|
|
216
217
|
return xt_number((double)list.rects.size());
|
|
217
218
|
}
|
|
218
219
|
|
|
220
|
+
/** Diagnostic/test hook: the serialized SVG document of the first `<svg>`
|
|
221
|
+
* element matching `selector`, plus the intrinsic size and shape count the
|
|
222
|
+
* NanoSVG parse yields. Returns `undefined` when there is no such element. */
|
|
223
|
+
static xt_value win_inline_svg(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
224
|
+
(void)env;
|
|
225
|
+
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
226
|
+
if (win == nullptr || win->document == nullptr || argc < 1) return XT_UNDEFINED;
|
|
227
|
+
xt_gui_flush_dom(win);
|
|
228
|
+
xt_value selectorValue = xt_to_string(xt_arg(argc, argv, 0));
|
|
229
|
+
const char *selector = xt_string_data(selectorValue);
|
|
230
|
+
if (selector == nullptr) return XT_UNDEFINED;
|
|
231
|
+
const xtgui::Node *node = win->document->querySelector(selector);
|
|
232
|
+
if (!xtgui::xt_inline_svg_is_root(node)) return XT_UNDEFINED;
|
|
233
|
+
std::string markup = xtgui::xt_inline_svg_serialize(node);
|
|
234
|
+
int width = 0;
|
|
235
|
+
int height = 0;
|
|
236
|
+
xtgui::xt_svg_markup_size(markup, &width, &height);
|
|
237
|
+
xt_value object = xt_object_new();
|
|
238
|
+
xt_object_set(object, xt_string_from_cstr("markup"), xt_string_from_cstr(markup.c_str()));
|
|
239
|
+
xt_object_set(object, xt_string_from_cstr("width"), xt_number(width));
|
|
240
|
+
xt_object_set(object, xt_string_from_cstr("height"), xt_number(height));
|
|
241
|
+
xt_object_set(object, xt_string_from_cstr("shapes"),
|
|
242
|
+
xt_number(xtgui::xt_svg_markup_shapes(markup)));
|
|
243
|
+
return object;
|
|
244
|
+
}
|
|
245
|
+
|
|
219
246
|
/** Diagnostic/test hook: advance the CSS transition clock by `ms`. */
|
|
220
247
|
static xt_value win_advance(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
221
248
|
(void)env;
|
|
@@ -527,6 +554,7 @@ xt_value xt_gui_window_proto(void) {
|
|
|
527
554
|
define_method(proto, "setBackground", (void *)win_set_background);
|
|
528
555
|
define_method(proto, "paintList", (void *)win_paint_list);
|
|
529
556
|
define_method(proto, "paintCount", (void *)win_paint_count);
|
|
557
|
+
define_method(proto, "inlineSvg", (void *)win_inline_svg);
|
|
530
558
|
define_method(proto, "advance", (void *)win_advance);
|
|
531
559
|
define_method(proto, "measureText", (void *)win_measure_text);
|
|
532
560
|
define_method(proto, "fontMetrics", (void *)win_font_metrics);
|