@bun-win32/dwrite 1.0.0

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/AI.md ADDED
@@ -0,0 +1,71 @@
1
+ # AI Guide for @bun-win32/dwrite
2
+
3
+ How to use this package, not what the Win32 API does.
4
+
5
+ ## Usage
6
+
7
+ ```ts
8
+ import Dwrite, { SomeFlag } from '@bun-win32/dwrite';
9
+
10
+ // Methods bind lazily on first call
11
+ const result = Dwrite.SomeFunctionW(arg1, arg2);
12
+
13
+ // Preload: array, single string, or no args (all symbols)
14
+ Dwrite.Preload(['SomeFunctionW', 'AnotherFunction']);
15
+ Dwrite.Preload('SomeFunctionW');
16
+ Dwrite.Preload();
17
+ ```
18
+
19
+ ## Where To Look
20
+
21
+ | Need | Read |
22
+ | --------------------------------- | -------------------- |
23
+ | Find a method or its MS Docs link | `structs/Dwrite.ts` |
24
+ | Find types, enums, constants | `types/Dwrite.ts` |
25
+ | Quick examples | `README.md` |
26
+
27
+ `index.ts` re-exports the class and all types — import from `@bun-win32/dwrite` directly.
28
+
29
+ ## Calling Convention
30
+
31
+ All documented `dwrite.dll` exports are bound. Each method maps 1:1 to its DLL export. Names, parameter names, and order match Microsoft Docs.
32
+
33
+ ### Strings
34
+
35
+ `W` methods take UTF-16LE NUL-terminated buffers. `A` methods take ANSI strings.
36
+
37
+ ```ts
38
+ const wide = Buffer.from('Hello\0', 'utf16le'); // LPCWSTR
39
+ Dwrite.SomeFunctionW(wide.ptr);
40
+
41
+ // Reading a wide string back from a buffer:
42
+ const text = new TextDecoder('utf-16').decode(buf).replace(/\0.*$/, '');
43
+ ```
44
+
45
+ ### Return types
46
+
47
+ - `HANDLE`, `HWND`, etc. → `bigint`
48
+ - `DWORD`, `UINT`, `BOOL`, `INT`, `LONG` → `number`
49
+ - `LPVOID`, `LPWSTR`, etc. → `Pointer`
50
+ - Win32 `BOOL` is `number` (0 or non-zero), **not** JS `boolean`. Do not compare with `=== true`.
51
+
52
+ ### Pointers, handles, out-parameters
53
+
54
+ - **Pointer** params (`LP*`, `P*`, `Pointer`): pass `buffer.ptr` from a caller-allocated `Buffer`.
55
+ - **Handle** params (`HANDLE`, `HWND`, etc.): pass a `bigint` value.
56
+ - **Out-parameters**: allocate a `Buffer`, pass `.ptr`, read the result after the call.
57
+
58
+ ```ts
59
+ const out = Buffer.alloc(4);
60
+ Dwrite.SomeFunction(out.ptr);
61
+ const value = out.readUInt32LE(0);
62
+ ```
63
+
64
+ ### Nullability
65
+
66
+ - `| NULL` in a signature → pass `null` (optional pointer).
67
+ - `| 0n` in a signature → pass `0n` (optional handle).
68
+
69
+ ## Errors and Cleanup
70
+
71
+ Return values are raw. If the Win32 function uses last-error semantics, read via `GetLastError()`. Resource cleanup is your responsibility — same as raw Win32.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @bun-win32/dwrite
2
+
3
+ Zero-dependency, zero-overhead Win32 DirectWrite bindings for [Bun](https://bun.sh) on Windows.
4
+
5
+ ## Overview
6
+
7
+ `@bun-win32/dwrite` exposes the `dwrite.dll` export using [Bun](https://bun.sh)'s FFI. It provides a single class, `Dwrite`, which lazily binds the native symbol on first use. You can optionally preload it up-front via `Preload()`.
8
+
9
+ `dwrite.dll` exports exactly **one** flat function — `DWriteCreateFactory`. It hands back an `IDWriteFactory`, and the entire DirectWrite surface (font enumeration, text layout, glyph metrics, ClearType/grayscale rasterization, typography, shaping) lives behind that object's COM vtable. This package binds the factory entry point; the included examples demonstrate the hand-driven COM vtable pattern (`read.u64` + `CFunction`) for everything beyond it — the same proven approach used by `@bun-win32/dxgi` and `@bun-win32/combase`.
10
+
11
+ The bindings are strongly typed for a smooth DX in TypeScript.
12
+
13
+ ## Features
14
+
15
+ - [Bun](https://bun.sh)-first ergonomics on Windows 10/11.
16
+ - Direct FFI to `dwrite.dll` (DirectWrite font and text layout/typography engine).
17
+ - In-source docs in `structs/Dwrite.ts` with links to Microsoft Docs.
18
+ - Lazy binding on first call; optional eager preload (`Dwrite.Preload()`).
19
+ - No wrapper overhead; calls map 1:1 to native APIs.
20
+ - Strongly-typed Win32 aliases (see `types/Dwrite.ts`).
21
+
22
+ ## Requirements
23
+
24
+ - [Bun](https://bun.sh) runtime
25
+ - Windows 10 or later
26
+
27
+ ## Installation
28
+
29
+ ```sh
30
+ bun add @bun-win32/dwrite
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```ts
36
+ import Dwrite, { DWRITE_FACTORY_TYPE } from '@bun-win32/dwrite';
37
+
38
+ // __uuidof(IDWriteFactory) = b859ee5a-d838-4b5b-a2e8-1adc7d93db48
39
+ const iid = Buffer.from([0x5a, 0xee, 0x59, 0xb8, 0x38, 0xd8, 0x5b, 0x4b, 0xa2, 0xe8, 0x1a, 0xdc, 0x7d, 0x93, 0xdb, 0x48]);
40
+
41
+ const factory = Buffer.alloc(8);
42
+ const hr = Dwrite.DWriteCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED, iid.ptr!, factory.ptr!);
43
+ console.log(`DWriteCreateFactory → 0x${(hr >>> 0).toString(16)}`);
44
+
45
+ // factory.readBigUInt64LE(0) is now an IDWriteFactory*; walk its COM vtable
46
+ // with `read.u64` + `CFunction` (see example/font-observatory.ts).
47
+ ```
48
+
49
+ > [!NOTE]
50
+ > AI agents: see `AI.md` for the package binding contract and source-navigation guidance. It explains how to use the package without scanning the entire implementation.
51
+
52
+ ## Examples
53
+
54
+ Run the included examples:
55
+
56
+ ```sh
57
+ bun run example/glyph-forge.ts
58
+ bun run example/font-observatory.ts
59
+ ```
60
+
61
+ ## Notes
62
+
63
+ - Either rely on lazy binding or call `Dwrite.Preload()`.
64
+ - `iid` is a caller-allocated 16-byte GUID buffer (`Pointer`); `factory` is a caller-allocated 8-byte slot (`Pointer`) that receives an `IUnknown*`/`IDWriteFactory*` interface pointer, read back as a `bigint`.
65
+ - All DirectWrite objects are COM interfaces — invoke their methods through the vtable and `Release` them when finished.
66
+ - Windows only. Bun runtime required.
package/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ import Dwrite from './structs/Dwrite';
2
+
3
+ export * from './types/Dwrite';
4
+ export default Dwrite;
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "author": "Stev Peifer <stev@bell.net>",
3
+ "bugs": {
4
+ "url": "https://github.com/ObscuritySRL/bun-win32/issues"
5
+ },
6
+ "dependencies": {
7
+ "@bun-win32/core": "1.1.2"
8
+ },
9
+ "description": "Zero-dependency, zero-overhead Win32 DWRITE bindings for Bun (FFI) on Windows.",
10
+ "devDependencies": {
11
+ "@types/bun": "latest"
12
+ },
13
+ "exports": {
14
+ ".": "./index.ts"
15
+ },
16
+ "license": "MIT",
17
+ "module": "index.ts",
18
+ "name": "@bun-win32/dwrite",
19
+ "peerDependencies": {
20
+ "typescript": "^5"
21
+ },
22
+ "private": false,
23
+ "homepage": "https://github.com/ObscuritySRL/bun-win32#readme",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git://github.com/ObscuritySRL/bun-win32.git",
27
+ "directory": "packages/dwrite"
28
+ },
29
+ "type": "module",
30
+ "version": "1.0.0",
31
+ "main": "./index.ts",
32
+ "keywords": [
33
+ "bun",
34
+ "ffi",
35
+ "win32",
36
+ "windows",
37
+ "dwrite",
38
+ "directwrite",
39
+ "fonts",
40
+ "typography",
41
+ "text",
42
+ "bindings",
43
+ "typescript",
44
+ "dll"
45
+ ],
46
+ "files": [
47
+ "AI.md",
48
+ "README.md",
49
+ "index.ts",
50
+ "structs/*.ts",
51
+ "types/*.ts"
52
+ ],
53
+ "sideEffects": false,
54
+ "engines": {
55
+ "bun": ">=1.1.0"
56
+ },
57
+ "scripts": {
58
+ "example:font-observatory": "bun ./example/font-observatory.ts",
59
+ "example:glyph-forge": "bun ./example/glyph-forge.ts"
60
+ }
61
+ }
@@ -0,0 +1,49 @@
1
+ import { type FFIFunction, FFIType } from 'bun:ffi';
2
+
3
+ import { Win32 } from '@bun-win32/core';
4
+
5
+ import type { DWRITE_FACTORY_TYPE, HRESULT, LPLPVOID, REFIID } from '../types/Dwrite';
6
+
7
+ /**
8
+ * Thin, lazy-loaded FFI bindings for `dwrite.dll`.
9
+ *
10
+ * Each static method corresponds one-to-one with a Win32 export declared in `Symbols`.
11
+ * The first call to a method binds the underlying native symbol via `bun:ffi` and
12
+ * memoizes it on the class for subsequent calls. For bulk, up-front binding, use `Preload`.
13
+ *
14
+ * Symbols are defined with explicit `FFIType` signatures and kept alphabetized.
15
+ * You normally do not access `Symbols` directly; call the static methods or preload
16
+ * a subset for hot paths.
17
+ *
18
+ * `dwrite.dll` exports exactly one flat function, `DWriteCreateFactory`. Every other
19
+ * DirectWrite capability is reached through the COM vtable of the `IDWriteFactory`
20
+ * it returns (see the package examples for the vtable-walk pattern).
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * import Dwrite, { DWRITE_FACTORY_TYPE } from './structs/Dwrite';
25
+ *
26
+ * // Lazy: bind on first call
27
+ * const iid = Buffer.alloc(16); // __uuidof(IDWriteFactory)
28
+ * const factory = Buffer.alloc(8);
29
+ * const hr = Dwrite.DWriteCreateFactory(DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED, iid.ptr, factory.ptr);
30
+ *
31
+ * // Or preload to avoid per-symbol lazy binding cost
32
+ * Dwrite.Preload('DWriteCreateFactory');
33
+ * ```
34
+ */
35
+ class Dwrite extends Win32 {
36
+ protected static override name = 'dwrite.dll';
37
+
38
+ /** @inheritdoc */
39
+ protected static override readonly Symbols = {
40
+ DWriteCreateFactory: { args: [FFIType.u32, FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
41
+ } as const satisfies Record<string, FFIFunction>;
42
+
43
+ // https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-dwritecreatefactory
44
+ public static DWriteCreateFactory(factoryType: DWRITE_FACTORY_TYPE, iid: REFIID, factory: LPLPVOID): HRESULT {
45
+ return Dwrite.Load('DWriteCreateFactory')(factoryType, iid, factory);
46
+ }
47
+ }
48
+
49
+ export default Dwrite;
@@ -0,0 +1,12 @@
1
+ import type { Pointer } from 'bun:ffi';
2
+
3
+ export type { HRESULT } from '@bun-win32/core';
4
+
5
+ export enum DWRITE_FACTORY_TYPE {
6
+ DWRITE_FACTORY_TYPE_ISOLATED = 1,
7
+ DWRITE_FACTORY_TYPE_SHARED = 0,
8
+ }
9
+
10
+ export type IUnknown = Pointer;
11
+ export type LPLPVOID = Pointer;
12
+ export type REFIID = Pointer;