@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 +71 -0
- package/README.md +66 -0
- package/index.ts +4 -0
- package/package.json +61 -0
- package/structs/Dwrite.ts +49 -0
- package/types/Dwrite.ts +12 -0
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
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;
|
package/types/Dwrite.ts
ADDED
|
@@ -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;
|