quickwin 1.0.2 → 1.1.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.
Files changed (78) hide show
  1. package/README.en.md +204 -204
  2. package/README.md +203 -203
  3. package/examples/PdfCanvas.tsx +83 -83
  4. package/examples/exec_server.ts +35 -35
  5. package/examples/pdf_preview2.ts +375 -375
  6. package/examples/pdf_viewer.tsx +279 -279
  7. package/examples/test_gallery.tsx +285 -285
  8. package/examples/test_react_lazy.tsx +63 -63
  9. package/examples/test_react_listbox.tsx +71 -71
  10. package/examples/test_root_window.tsx +41 -41
  11. package/examples/test_tab.tsx +75 -75
  12. package/examples/tray_demo.tsx +81 -81
  13. package/lib/assert.ts +6 -6
  14. package/lib/cache-utils.ts +40 -40
  15. package/lib/dumpRects.ts +25 -25
  16. package/lib/fetch.ts +502 -502
  17. package/lib/http-common.ts +399 -399
  18. package/lib/http-server.ts +424 -424
  19. package/lib/polyfill.ts +171 -171
  20. package/lib/react-qw/components/index.ts +17 -17
  21. package/lib/react-qw/index.ts +90 -90
  22. package/lib/react-qw/jsx.d.ts +34 -34
  23. package/lib/react-qw/layout.ts +111 -111
  24. package/lib/react-qw/props.ts +36 -36
  25. package/lib/react-qw/reconciler.ts +373 -373
  26. package/lib/stream.ts +21 -21
  27. package/lib/text-codec.ts +171 -171
  28. package/lib/text-measure.ts +54 -54
  29. package/lib/url.ts +201 -201
  30. package/lib/vendor/web-streams/ponyfill.d.mts +829 -829
  31. package/lib/vendor/web-streams/ponyfill.mjs +8 -8
  32. package/lib/websocket.js +8 -0
  33. package/lib/websocket.ts +563 -555
  34. package/package.json +50 -44
  35. package/qwin-nowasm-x86.exe +0 -0
  36. package/qwin-nowasm.exe +0 -0
  37. package/qwin-x86.exe +0 -0
  38. package/qwin.exe +0 -0
  39. package/test/run.ts +96 -96
  40. package/test/test_basic.ts +9 -9
  41. package/test/test_basic_fetch.ts +33 -33
  42. package/test/test_brotli.ts +52 -52
  43. package/test/test_fetch_cache.ts +187 -187
  44. package/test/test_ffi.ts +174 -174
  45. package/test/test_frame_encoding.ts +132 -132
  46. package/test/test_helper.ts +80 -80
  47. package/test/test_http_import.ts +74 -74
  48. package/test/test_http_server.ts +136 -136
  49. package/test/test_import_dir.ts +5 -5
  50. package/test/test_ipv6.ts +129 -129
  51. package/test/test_meta_url.ts +4 -4
  52. package/test/test_mupdf_render.ts +74 -74
  53. package/test/test_mupdf_twice.ts +81 -81
  54. package/test/test_mupdf_wasm.ts +30 -30
  55. package/test/test_net_event.ts +55 -55
  56. package/test/test_net_fetch.ts +238 -238
  57. package/test/test_net_websocket.ts +164 -164
  58. package/test/test_polyfill.ts +159 -159
  59. package/test/test_url.ts +183 -183
  60. package/test/test_wasm_basic.ts +73 -73
  61. package/test/test_wasm_import_global.ts +45 -45
  62. package/test/test_wasm_sjlj.ts +125 -125
  63. package/test/test_wasm_types.ts +124 -124
  64. package/test/test_worker.ts +24 -24
  65. package/test/test_worker_fetch.ts +27 -27
  66. package/test/test_worker_net.ts +54 -54
  67. package/test/test_worker_wasm_concurrent.ts +45 -45
  68. package/test/worker_fetch.ts +13 -13
  69. package/test/worker_helper.ts +1 -1
  70. package/test/worker_http.ts +20 -20
  71. package/test/worker_import_lib.ts +13 -13
  72. package/test/worker_module.ts +17 -17
  73. package/test/worker_wasm_concurrent.ts +22 -22
  74. package/tsconfig.json +27 -27
  75. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -571
  76. package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -2749
  77. package/vendor/mupdf-wasm/mupdf.d.ts +939 -939
  78. package/vendor/mupdf-wasm/mupdf.js +3317 -3317
package/lib/stream.ts CHANGED
@@ -1,22 +1,22 @@
1
- export {}
2
-
3
- import {
4
- ReadableStream as ReadableStreamImpl,
5
- ReadableStreamDefaultController as ReadableStreamDefaultControllerImpl,
6
- ReadableStreamDefaultReader as ReadableStreamDefaultReaderImpl,
7
- } from './vendor/web-streams/ponyfill.mjs'
8
-
9
- declare global {
10
- type ReadableStreamReadResult<R = any> =
11
- | { done: false; value: R }
12
- | { done: true; value?: undefined }
13
-
14
- interface ReadableStreamReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {}
15
- interface ReadableStreamDefaultReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {}
16
- interface ReadableStream<R = any> extends ReadableStreamImpl<R> {}
17
- interface ReadableStreamDefaultController<R = any> extends ReadableStreamDefaultControllerImpl<R> {}
18
-
19
- var ReadableStream: typeof ReadableStreamImpl
20
- }
21
-
1
+ export {}
2
+
3
+ import {
4
+ ReadableStream as ReadableStreamImpl,
5
+ ReadableStreamDefaultController as ReadableStreamDefaultControllerImpl,
6
+ ReadableStreamDefaultReader as ReadableStreamDefaultReaderImpl,
7
+ } from './vendor/web-streams/ponyfill.mjs'
8
+
9
+ declare global {
10
+ type ReadableStreamReadResult<R = any> =
11
+ | { done: false; value: R }
12
+ | { done: true; value?: undefined }
13
+
14
+ interface ReadableStreamReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {}
15
+ interface ReadableStreamDefaultReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {}
16
+ interface ReadableStream<R = any> extends ReadableStreamImpl<R> {}
17
+ interface ReadableStreamDefaultController<R = any> extends ReadableStreamDefaultControllerImpl<R> {}
18
+
19
+ var ReadableStream: typeof ReadableStreamImpl
20
+ }
21
+
22
22
  globalThis.ReadableStream = ReadableStreamImpl
package/lib/text-codec.ts CHANGED
@@ -1,171 +1,171 @@
1
- export {} // make this a module so declare global works
2
-
3
- declare global {
4
- interface TextDecoder<T extends _Label | undefined = _Label | undefined> extends TextDecoderImpl<T> {}
5
- var TextDecoder: typeof TextDecoderImpl
6
-
7
- interface TextEncoder<T extends _Label | undefined = _Label | undefined> extends TextEncoderImpl<T> {}
8
- var TextEncoder: typeof TextEncoderImpl
9
- }
10
-
11
- const _labelMap = {
12
- 'utf-8': 'utf-8',
13
- 'utf8': 'utf-8',
14
- 'unicode-1-1-utf-8': 'utf-8',
15
- 'utf-16': 'utf-16le',
16
- 'utf-16le': 'utf-16le',
17
- 'utf-16be': 'utf-16be',
18
- } as const
19
-
20
- type _Label = keyof typeof _labelMap
21
- type _Encoding = typeof _labelMap[_Label]
22
- type _Result<T> = T extends _Label ? typeof _labelMap[T] : 'utf-8'
23
-
24
- function _normalizeLabel<T extends _Label | undefined>(label: T): _Result<T> {
25
- if (!label) return 'utf-8' as _Result<T>
26
- const result = _labelMap[label.trim().toLowerCase() as _Label]
27
- if (result) return result as _Result<T>
28
- throw new RangeError(`The encoding label "${label}" is not supported`)
29
- }
30
-
31
- function _decodeUTF8(buf: Uint8Array, fatal: boolean): string {
32
- let out = ''
33
- for (let i = 0; i < buf.length; ) {
34
- const b = buf[i++]!
35
- if (b < 0x80) { out += String.fromCharCode(b); continue }
36
- if (b < 0xC0) { out += fatal ? (() => { throw new TypeError('unexpected continuation byte') })() : '\uFFFD'; continue }
37
- let c: number, min: number
38
- if (b < 0xE0) {
39
- if (i >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
40
- const b2 = buf[i++]!
41
- if ((b2 & 0xC0) !== 0x80) { out += '\uFFFD'; continue }
42
- c = ((b & 0x1F) << 6) | (b2 & 0x3F)
43
- min = 0x80
44
- } else if (b < 0xF0) {
45
- if (i + 1 >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
46
- const b2 = buf[i++]!; const b3 = buf[i++]!
47
- if (((b2 & 0xC0) !== 0x80) || ((b3 & 0xC0) !== 0x80)) { out += '\uFFFD'; continue }
48
- c = ((b & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)
49
- min = 0x800
50
- } else if (b < 0xF8) {
51
- if (i + 2 >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
52
- const b2 = buf[i++]!; const b3 = buf[i++]!; const b4 = buf[i++]!
53
- if (((b2 & 0xC0) !== 0x80) || ((b3 & 0xC0) !== 0x80) || ((b4 & 0xC0) !== 0x80)) { out += '\uFFFD'; continue }
54
- c = ((b & 0x07) << 18) | ((b2 & 0x3F) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F)
55
- min = 0x10000
56
- } else { out += fatal ? (() => { throw new TypeError('invalid utf-8 start') })() : '\uFFFD'; continue }
57
- if (c < min || (c >= 0xD800 && c <= 0xDFFF) || c > 0x10FFFF) {
58
- out += fatal ? (() => { throw new TypeError('invalid utf-8 codepoint') })() : '\uFFFD'; continue
59
- }
60
- if (c <= 0xFFFF) out += String.fromCharCode(c)
61
- else { c -= 0x10000; out += String.fromCharCode(0xD800 | (c >> 10), 0xDC00 | (c & 0x3FF)) }
62
- }
63
- return out
64
- }
65
-
66
- function _decodeUTF16(buf: Uint8Array, le: boolean, fatal: boolean): string {
67
- const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
68
- let out = ''
69
- for (let i = 0; i + 1 < buf.length; i += 2) {
70
- let c = dv.getUint16(i, le)
71
- if (c >= 0xD800 && c <= 0xDBFF) {
72
- i += 2
73
- if (i + 1 >= buf.length) {
74
- out += fatal ? (() => { throw new TypeError('truncated surrogate pair') })() : '\uFFFD'; break
75
- }
76
- const c2 = dv.getUint16(i, le)
77
- if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
78
- out += String.fromCharCode(c, c2)
79
- } else {
80
- out += fatal ? (() => { throw new TypeError('invalid surrogate pair') })() : '\uFFFD'
81
- i -= 2
82
- }
83
- } else if (c >= 0xDC00 && c <= 0xDFFF) {
84
- out += fatal ? (() => { throw new TypeError('unexpected trailing surrogate') })() : '\uFFFD'
85
- } else {
86
- out += String.fromCharCode(c)
87
- }
88
- }
89
- return out
90
- }
91
-
92
- class TextDecoderImpl<T extends _Label | undefined = _Label | undefined> {
93
- _encoding: _Encoding
94
- _fatal: boolean
95
- _ignoreBOM: boolean
96
-
97
- constructor(label?: T, options?: { fatal?: boolean, ignoreBOM?: boolean }) {
98
- this._encoding = _normalizeLabel(label)
99
- this._fatal = options?.fatal ?? false
100
- this._ignoreBOM = options?.ignoreBOM ?? false
101
- }
102
-
103
- get encoding(): _Result<T> { return this._encoding as _Result<T> }
104
- get fatal(): boolean { return this._fatal }
105
- get ignoreBOM(): boolean { return this._ignoreBOM }
106
-
107
- decode(buffer?: ArrayBufferView | ArrayBuffer | null): string {
108
- if (!buffer) return ''
109
- const arr = buffer instanceof Uint8Array ? buffer
110
- : buffer instanceof ArrayBuffer ? new Uint8Array(buffer)
111
- : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength)
112
-
113
- if (this._encoding === 'utf-8') {
114
- return _decodeUTF8(arr, this._fatal)
115
- }
116
-
117
- const le = this._encoding === 'utf-16le'
118
- let offset = 0
119
-
120
- if (arr.length >= 2 && !this._ignoreBOM) {
121
- const bomLo = le ? arr[0]! : arr[1]!
122
- const bomHi = le ? arr[1]! : arr[0]!
123
- const bom = (bomHi << 8) | bomLo
124
- if (bom === 0xFEFF || bom === 0xFFFE) {
125
- offset = 2
126
- }
127
- }
128
-
129
- return _decodeUTF16(arr.slice(offset), le, this._fatal)
130
- }
131
- }
132
-
133
- class TextEncoderImpl<T extends _Label | undefined = _Label | undefined> {
134
- _encoding: _Encoding
135
-
136
- constructor(label?: T) {
137
- this._encoding = _normalizeLabel(label)
138
- }
139
-
140
- get encoding(): _Result<T> { return this._encoding as _Result<T> }
141
-
142
- encode(input?: string): Uint8Array<ArrayBuffer> {
143
- if (!input) return new Uint8Array(0)
144
-
145
- if (this._encoding === 'utf-8') {
146
- const bytes: number[] = []
147
- for (let i = 0; i < input.length; i++) {
148
- let c = input.charCodeAt(i)
149
- if (c < 0x80) { bytes.push(c) }
150
- else if (c < 0x800) { bytes.push(0xC0 | (c >> 6), 0x80 | (c & 0x3F)) }
151
- else if (c < 0xD800 || c >= 0xE000) { bytes.push(0xE0 | (c >> 12), 0x80 | ((c >> 6) & 0x3F), 0x80 | (c & 0x3F)) }
152
- else { i++; const c2 = input.charCodeAt(i); c = 0x10000 + ((c & 0x3FF) << 10) | (c2 & 0x3FF); bytes.push(0xF0 | (c >> 18), 0x80 | ((c >> 12) & 0x3F), 0x80 | ((c >> 6) & 0x3F), 0x80 | (c & 0x3F)) }
153
- }
154
- return new Uint8Array(bytes)
155
- }
156
-
157
- const le = this._encoding === 'utf-16le'
158
- const buf = new ArrayBuffer(input.length * 2)
159
- const dv = new DataView(buf)
160
- for (let i = 0; i < input.length; i++) dv.setUint16(i * 2, input.charCodeAt(i), le)
161
- return new Uint8Array(buf)
162
- }
163
- }
164
-
165
- if (typeof globalThis.TextDecoder === 'undefined') {
166
- globalThis.TextDecoder = TextDecoderImpl
167
- }
168
-
169
- if (typeof globalThis.TextEncoder === 'undefined') {
170
- globalThis.TextEncoder = TextEncoderImpl
171
- }
1
+ export {} // make this a module so declare global works
2
+
3
+ declare global {
4
+ interface TextDecoder<T extends _Label | undefined = _Label | undefined> extends TextDecoderImpl<T> {}
5
+ var TextDecoder: typeof TextDecoderImpl
6
+
7
+ interface TextEncoder<T extends _Label | undefined = _Label | undefined> extends TextEncoderImpl<T> {}
8
+ var TextEncoder: typeof TextEncoderImpl
9
+ }
10
+
11
+ const _labelMap = {
12
+ 'utf-8': 'utf-8',
13
+ 'utf8': 'utf-8',
14
+ 'unicode-1-1-utf-8': 'utf-8',
15
+ 'utf-16': 'utf-16le',
16
+ 'utf-16le': 'utf-16le',
17
+ 'utf-16be': 'utf-16be',
18
+ } as const
19
+
20
+ type _Label = keyof typeof _labelMap
21
+ type _Encoding = typeof _labelMap[_Label]
22
+ type _Result<T> = T extends _Label ? typeof _labelMap[T] : 'utf-8'
23
+
24
+ function _normalizeLabel<T extends _Label | undefined>(label: T): _Result<T> {
25
+ if (!label) return 'utf-8' as _Result<T>
26
+ const result = _labelMap[label.trim().toLowerCase() as _Label]
27
+ if (result) return result as _Result<T>
28
+ throw new RangeError(`The encoding label "${label}" is not supported`)
29
+ }
30
+
31
+ function _decodeUTF8(buf: Uint8Array, fatal: boolean): string {
32
+ let out = ''
33
+ for (let i = 0; i < buf.length; ) {
34
+ const b = buf[i++]!
35
+ if (b < 0x80) { out += String.fromCharCode(b); continue }
36
+ if (b < 0xC0) { out += fatal ? (() => { throw new TypeError('unexpected continuation byte') })() : '\uFFFD'; continue }
37
+ let c: number, min: number
38
+ if (b < 0xE0) {
39
+ if (i >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
40
+ const b2 = buf[i++]!
41
+ if ((b2 & 0xC0) !== 0x80) { out += '\uFFFD'; continue }
42
+ c = ((b & 0x1F) << 6) | (b2 & 0x3F)
43
+ min = 0x80
44
+ } else if (b < 0xF0) {
45
+ if (i + 1 >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
46
+ const b2 = buf[i++]!; const b3 = buf[i++]!
47
+ if (((b2 & 0xC0) !== 0x80) || ((b3 & 0xC0) !== 0x80)) { out += '\uFFFD'; continue }
48
+ c = ((b & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)
49
+ min = 0x800
50
+ } else if (b < 0xF8) {
51
+ if (i + 2 >= buf.length) { out += fatal ? (() => { throw new TypeError('incomplete utf-8') })() : '\uFFFD'; break }
52
+ const b2 = buf[i++]!; const b3 = buf[i++]!; const b4 = buf[i++]!
53
+ if (((b2 & 0xC0) !== 0x80) || ((b3 & 0xC0) !== 0x80) || ((b4 & 0xC0) !== 0x80)) { out += '\uFFFD'; continue }
54
+ c = ((b & 0x07) << 18) | ((b2 & 0x3F) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F)
55
+ min = 0x10000
56
+ } else { out += fatal ? (() => { throw new TypeError('invalid utf-8 start') })() : '\uFFFD'; continue }
57
+ if (c < min || (c >= 0xD800 && c <= 0xDFFF) || c > 0x10FFFF) {
58
+ out += fatal ? (() => { throw new TypeError('invalid utf-8 codepoint') })() : '\uFFFD'; continue
59
+ }
60
+ if (c <= 0xFFFF) out += String.fromCharCode(c)
61
+ else { c -= 0x10000; out += String.fromCharCode(0xD800 | (c >> 10), 0xDC00 | (c & 0x3FF)) }
62
+ }
63
+ return out
64
+ }
65
+
66
+ function _decodeUTF16(buf: Uint8Array, le: boolean, fatal: boolean): string {
67
+ const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
68
+ let out = ''
69
+ for (let i = 0; i + 1 < buf.length; i += 2) {
70
+ let c = dv.getUint16(i, le)
71
+ if (c >= 0xD800 && c <= 0xDBFF) {
72
+ i += 2
73
+ if (i + 1 >= buf.length) {
74
+ out += fatal ? (() => { throw new TypeError('truncated surrogate pair') })() : '\uFFFD'; break
75
+ }
76
+ const c2 = dv.getUint16(i, le)
77
+ if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
78
+ out += String.fromCharCode(c, c2)
79
+ } else {
80
+ out += fatal ? (() => { throw new TypeError('invalid surrogate pair') })() : '\uFFFD'
81
+ i -= 2
82
+ }
83
+ } else if (c >= 0xDC00 && c <= 0xDFFF) {
84
+ out += fatal ? (() => { throw new TypeError('unexpected trailing surrogate') })() : '\uFFFD'
85
+ } else {
86
+ out += String.fromCharCode(c)
87
+ }
88
+ }
89
+ return out
90
+ }
91
+
92
+ class TextDecoderImpl<T extends _Label | undefined = _Label | undefined> {
93
+ _encoding: _Encoding
94
+ _fatal: boolean
95
+ _ignoreBOM: boolean
96
+
97
+ constructor(label?: T, options?: { fatal?: boolean, ignoreBOM?: boolean }) {
98
+ this._encoding = _normalizeLabel(label)
99
+ this._fatal = options?.fatal ?? false
100
+ this._ignoreBOM = options?.ignoreBOM ?? false
101
+ }
102
+
103
+ get encoding(): _Result<T> { return this._encoding as _Result<T> }
104
+ get fatal(): boolean { return this._fatal }
105
+ get ignoreBOM(): boolean { return this._ignoreBOM }
106
+
107
+ decode(buffer?: ArrayBufferView | ArrayBuffer | null): string {
108
+ if (!buffer) return ''
109
+ const arr = buffer instanceof Uint8Array ? buffer
110
+ : buffer instanceof ArrayBuffer ? new Uint8Array(buffer)
111
+ : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength)
112
+
113
+ if (this._encoding === 'utf-8') {
114
+ return _decodeUTF8(arr, this._fatal)
115
+ }
116
+
117
+ const le = this._encoding === 'utf-16le'
118
+ let offset = 0
119
+
120
+ if (arr.length >= 2 && !this._ignoreBOM) {
121
+ const bomLo = le ? arr[0]! : arr[1]!
122
+ const bomHi = le ? arr[1]! : arr[0]!
123
+ const bom = (bomHi << 8) | bomLo
124
+ if (bom === 0xFEFF || bom === 0xFFFE) {
125
+ offset = 2
126
+ }
127
+ }
128
+
129
+ return _decodeUTF16(arr.slice(offset), le, this._fatal)
130
+ }
131
+ }
132
+
133
+ class TextEncoderImpl<T extends _Label | undefined = _Label | undefined> {
134
+ _encoding: _Encoding
135
+
136
+ constructor(label?: T) {
137
+ this._encoding = _normalizeLabel(label)
138
+ }
139
+
140
+ get encoding(): _Result<T> { return this._encoding as _Result<T> }
141
+
142
+ encode(input?: string): Uint8Array<ArrayBuffer> {
143
+ if (!input) return new Uint8Array(0)
144
+
145
+ if (this._encoding === 'utf-8') {
146
+ const bytes: number[] = []
147
+ for (let i = 0; i < input.length; i++) {
148
+ let c = input.charCodeAt(i)
149
+ if (c < 0x80) { bytes.push(c) }
150
+ else if (c < 0x800) { bytes.push(0xC0 | (c >> 6), 0x80 | (c & 0x3F)) }
151
+ else if (c < 0xD800 || c >= 0xE000) { bytes.push(0xE0 | (c >> 12), 0x80 | ((c >> 6) & 0x3F), 0x80 | (c & 0x3F)) }
152
+ else { i++; const c2 = input.charCodeAt(i); c = 0x10000 + ((c & 0x3FF) << 10) | (c2 & 0x3FF); bytes.push(0xF0 | (c >> 18), 0x80 | ((c >> 12) & 0x3F), 0x80 | ((c >> 6) & 0x3F), 0x80 | (c & 0x3F)) }
153
+ }
154
+ return new Uint8Array(bytes)
155
+ }
156
+
157
+ const le = this._encoding === 'utf-16le'
158
+ const buf = new ArrayBuffer(input.length * 2)
159
+ const dv = new DataView(buf)
160
+ for (let i = 0; i < input.length; i++) dv.setUint16(i * 2, input.charCodeAt(i), le)
161
+ return new Uint8Array(buf)
162
+ }
163
+ }
164
+
165
+ if (typeof globalThis.TextDecoder === 'undefined') {
166
+ globalThis.TextDecoder = TextDecoderImpl
167
+ }
168
+
169
+ if (typeof globalThis.TextEncoder === 'undefined') {
170
+ globalThis.TextEncoder = TextEncoderImpl
171
+ }
@@ -1,54 +1,54 @@
1
- import * as ffi from 'ffi'
2
- import * as win from 'win'
3
- import * as gui from 'gui'
4
-
5
- function loadProc(lib: win.HMODULE, name: string): number {
6
- const ptr = win.GetProcAddress(lib, name)
7
- if (!ptr) throw new Error(`Cannot load ${name}`)
8
- return ptr
9
- }
10
-
11
- const user32 = win.LoadLibrary('user32.dll')
12
- const gdi32 = win.LoadLibrary('gdi32.dll')
13
- if (!user32 || !gdi32) throw new Error('Failed to load system DLLs')
14
- const DrawTextW = loadProc(user32, 'DrawTextW')
15
- const GetDC = loadProc(user32, 'GetDC')
16
- const ReleaseDC = loadProc(user32, 'ReleaseDC')
17
- const SelectObject = loadProc(gdi32, 'SelectObject')
18
-
19
- const FFI_TYPE_UINT64 = ffi.FFI_TYPE_UINT64
20
- const FFI_S32 = ffi.FFI_TYPE_SINT32
21
- const FFI_PTR = ffi.FFI_TYPE_POINTER
22
-
23
- export function measureText(hdc: number, text: string, maxWidth: number): { width: number; height: number } {
24
- const textBuf = new TextEncoder('utf-16le').encode(text + '\0').buffer
25
- const rect = new ArrayBuffer(16)
26
- const dv = new DataView(rect)
27
- dv.setInt32(8, maxWidth, true)
28
- ffi.ffiCall(DrawTextW, [FFI_TYPE_UINT64, FFI_PTR, FFI_S32, FFI_PTR, FFI_S32], [hdc, textBuf, -1, rect, gui.DrawTextFlag.CALCRECT], FFI_TYPE_UINT64)
29
- return { width: dv.getInt32(8, true), height: dv.getInt32(12, true) }
30
- }
31
-
32
- export function getButtonIdealSize(hwnd: gui.HWND): { width: number; height: number } {
33
- const size = new ArrayBuffer(8)
34
- gui.SendMessage(hwnd, gui.ButtonExtMsg.GETIDEALSIZE, 0, ffi.bufferPtr(size))
35
- const dv = new DataView(size)
36
- return { width: dv.getInt32(0, true), height: dv.getInt32(4, true) }
37
- }
38
-
39
- export function measureTextForHwnd(hwnd: gui.HWND, text: string): { width: number; height: number } {
40
- const hdc = ffi.ffiCall(GetDC, [FFI_TYPE_UINT64], [hwnd], FFI_TYPE_UINT64)
41
- if (!hdc) return { width: 0, height: 0 }
42
- const hFont = gui.SendMessage(hwnd, gui.WmMsg.GETFONT, 0, 0)
43
- const oldFont = hFont ? ffi.ffiCall(SelectObject, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hdc, hFont], FFI_TYPE_UINT64) : 0
44
- const result = measureText(hdc, text, 0)
45
- if (hFont) ffi.ffiCall(SelectObject, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hdc, oldFont], FFI_TYPE_UINT64)
46
- ffi.ffiCall(ReleaseDC, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hwnd, hdc], FFI_S32)
47
- const wr = gui.GetWindowRect(hwnd)
48
- const cr = gui.GetClientRect(hwnd)
49
- if (wr && cr) {
50
- result.width += (wr.right - wr.left) - (cr.right - cr.left)
51
- result.height += (wr.bottom - wr.top) - (cr.bottom - cr.top)
52
- }
53
- return result
54
- }
1
+ import * as ffi from 'ffi'
2
+ import * as win from 'win'
3
+ import * as gui from 'gui'
4
+
5
+ function loadProc(lib: win.HMODULE, name: string): number {
6
+ const ptr = win.GetProcAddress(lib, name)
7
+ if (!ptr) throw new Error(`Cannot load ${name}`)
8
+ return ptr
9
+ }
10
+
11
+ const user32 = win.LoadLibrary('user32.dll')
12
+ const gdi32 = win.LoadLibrary('gdi32.dll')
13
+ if (!user32 || !gdi32) throw new Error('Failed to load system DLLs')
14
+ const DrawTextW = loadProc(user32, 'DrawTextW')
15
+ const GetDC = loadProc(user32, 'GetDC')
16
+ const ReleaseDC = loadProc(user32, 'ReleaseDC')
17
+ const SelectObject = loadProc(gdi32, 'SelectObject')
18
+
19
+ const FFI_TYPE_UINT64 = ffi.FFI_TYPE_UINT64
20
+ const FFI_S32 = ffi.FFI_TYPE_SINT32
21
+ const FFI_PTR = ffi.FFI_TYPE_POINTER
22
+
23
+ export function measureText(hdc: number, text: string, maxWidth: number): { width: number; height: number } {
24
+ const textBuf = new TextEncoder('utf-16le').encode(text + '\0').buffer
25
+ const rect = new ArrayBuffer(16)
26
+ const dv = new DataView(rect)
27
+ dv.setInt32(8, maxWidth, true)
28
+ ffi.ffiCall(DrawTextW, [FFI_TYPE_UINT64, FFI_PTR, FFI_S32, FFI_PTR, FFI_S32], [hdc, textBuf, -1, rect, gui.DrawTextFlag.CALCRECT], FFI_TYPE_UINT64)
29
+ return { width: dv.getInt32(8, true), height: dv.getInt32(12, true) }
30
+ }
31
+
32
+ export function getButtonIdealSize(hwnd: gui.HWND): { width: number; height: number } {
33
+ const size = new ArrayBuffer(8)
34
+ gui.SendMessage(hwnd, gui.ButtonExtMsg.GETIDEALSIZE, 0, ffi.bufferPtr(size))
35
+ const dv = new DataView(size)
36
+ return { width: dv.getInt32(0, true), height: dv.getInt32(4, true) }
37
+ }
38
+
39
+ export function measureTextForHwnd(hwnd: gui.HWND, text: string): { width: number; height: number } {
40
+ const hdc = ffi.ffiCall(GetDC, [FFI_TYPE_UINT64], [hwnd], FFI_TYPE_UINT64)
41
+ if (!hdc) return { width: 0, height: 0 }
42
+ const hFont = gui.SendMessage(hwnd, gui.WmMsg.GETFONT, 0, 0)
43
+ const oldFont = hFont ? ffi.ffiCall(SelectObject, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hdc, hFont], FFI_TYPE_UINT64) : 0
44
+ const result = measureText(hdc, text, 0)
45
+ if (hFont) ffi.ffiCall(SelectObject, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hdc, oldFont], FFI_TYPE_UINT64)
46
+ ffi.ffiCall(ReleaseDC, [FFI_TYPE_UINT64, FFI_TYPE_UINT64], [hwnd, hdc], FFI_S32)
47
+ const wr = gui.GetWindowRect(hwnd)
48
+ const cr = gui.GetClientRect(hwnd)
49
+ if (wr && cr) {
50
+ result.width += (wr.right - wr.left) - (cr.right - cr.left)
51
+ result.height += (wr.bottom - wr.top) - (cr.bottom - cr.top)
52
+ }
53
+ return result
54
+ }