@niivue/uikit 1.0.0-rc.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.
- package/README.md +61 -0
- package/dist/annotationOverlay.d.ts +31 -0
- package/dist/crosshair.d.ts +81 -0
- package/dist/crosshairOverlay.d.ts +18 -0
- package/dist/fonts/ubuntu.json.d.ts +1509 -0
- package/dist/index.d.ts +19 -0
- package/dist/line.d.ts +34 -0
- package/dist/lineOverlay.d.ts +13 -0
- package/dist/render/glLineRenderer.d.ts +13 -0
- package/dist/render/glTextRenderer.d.ts +16 -0
- package/dist/render/shaders.d.ts +6 -0
- package/dist/render/wgpuLineRenderer.d.ts +16 -0
- package/dist/render/wgpuTextRenderer.d.ts +34 -0
- package/dist/ruler.d.ts +47 -0
- package/dist/rulerOverlay.d.ts +16 -0
- package/dist/text/defaultFont.d.ts +3 -0
- package/dist/text/font.d.ts +55 -0
- package/dist/text/layout.d.ts +54 -0
- package/dist/textOverlay.d.ts +23 -0
- package/dist/uikit.js +2384 -0
- package/package.json +58 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type { AnnotationGeometryOptions } from './annotationOverlay';
|
|
2
|
+
export { buildAnnotationGeometry, UIKitAnnotationOverlay, } from './annotationOverlay';
|
|
3
|
+
export type { CrosshairGeometry, CrosshairSpec } from './crosshair';
|
|
4
|
+
export { buildCrosshair } from './crosshair';
|
|
5
|
+
export type { CrosshairPlacement } from './crosshairOverlay';
|
|
6
|
+
export { UIKitCrosshairOverlay } from './crosshairOverlay';
|
|
7
|
+
export type { LineData, LineTerminators } from './line';
|
|
8
|
+
export { buildLine, buildTerminatedLine, LineTerminator } from './line';
|
|
9
|
+
export { UIKitLineOverlay } from './lineOverlay';
|
|
10
|
+
export type { RulerGeometry, RulerSpec, Vec2 } from './ruler';
|
|
11
|
+
export { buildRuler } from './ruler';
|
|
12
|
+
export { UIKitRulerOverlay } from './rulerOverlay';
|
|
13
|
+
export { loadDefaultFont } from './text/defaultFont';
|
|
14
|
+
export type { RawFontFile, UIKitFont, UIKitFontMetrics, UIKitGlyph, } from './text/font';
|
|
15
|
+
export { parseFont, screenPxRange } from './text/font';
|
|
16
|
+
export type { RGBA, TextLayoutOptions } from './text/layout';
|
|
17
|
+
export { autoOutlineColor, layoutText, measureWidth, readableAngle, } from './text/layout';
|
|
18
|
+
export type { UIKitTextItem } from './textOverlay';
|
|
19
|
+
export { UIKitTextOverlay } from './textOverlay';
|
package/dist/line.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export type LineData = {
|
|
2
|
+
data: Float32Array;
|
|
3
|
+
};
|
|
4
|
+
export declare const FLOATS_PER_LINE = 12;
|
|
5
|
+
export declare function buildLine(startX: number, startY: number, endX: number, endY: number, thickness?: number, color?: readonly number[]): LineData;
|
|
6
|
+
/**
|
|
7
|
+
* Line-end decorations. Only NONE and ARROW are implemented; CIRCLE and RING are
|
|
8
|
+
* reserved so callers and the enum can grow to the old uikit terminator set (they
|
|
9
|
+
* need a filled-disc primitive that this line-segment builder does not provide).
|
|
10
|
+
*/
|
|
11
|
+
export declare enum LineTerminator {
|
|
12
|
+
NONE = 0,
|
|
13
|
+
ARROW = 1,
|
|
14
|
+
CIRCLE = 2,
|
|
15
|
+
RING = 3
|
|
16
|
+
}
|
|
17
|
+
export interface LineTerminators {
|
|
18
|
+
/** Decoration at the start point. Defaults to NONE. */
|
|
19
|
+
start?: LineTerminator;
|
|
20
|
+
/** Decoration at the end point. Defaults to NONE. */
|
|
21
|
+
end?: LineTerminator;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A line plus optional end/start terminators, returned as plain {@link LineData}
|
|
25
|
+
* segments (the shaft first, then any terminator barbs). Terminators are composed
|
|
26
|
+
* from short line segments, so a plain line renderer draws them unchanged and both
|
|
27
|
+
* backends render them identically. Mirrors the old uikit `drawLine({ terminator })`
|
|
28
|
+
* in this data-emitting model.
|
|
29
|
+
*
|
|
30
|
+
* ARROW shortens the shaft by half a barb length at the terminated end so it does
|
|
31
|
+
* not poke through the arrowhead. A zero-length line has no direction, so it is
|
|
32
|
+
* returned as the bare shaft with no terminators.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildTerminatedLine(startX: number, startY: number, endX: number, endY: number, thickness?: number, color?: readonly number[], terminators?: LineTerminators): LineData[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { LineData } from './line';
|
|
3
|
+
export declare class UIKitLineOverlay implements UIKitOverlayRenderer {
|
|
4
|
+
private lines;
|
|
5
|
+
private readonly gl;
|
|
6
|
+
private readonly wgpu;
|
|
7
|
+
constructor(lines?: LineData[]);
|
|
8
|
+
/** Replace the lines drawn each frame. Trigger a redraw via the controller. */
|
|
9
|
+
setLines(lines: LineData[]): void;
|
|
10
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
11
|
+
/** Release GPU resources on both backends. */
|
|
12
|
+
destroy(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LineData } from '../line';
|
|
2
|
+
export declare class GlLineRenderer {
|
|
3
|
+
private gl;
|
|
4
|
+
private program;
|
|
5
|
+
private vao;
|
|
6
|
+
private buffer;
|
|
7
|
+
private uCanvasSize;
|
|
8
|
+
private scratch;
|
|
9
|
+
private ensure;
|
|
10
|
+
/** Draw `lines` in screen-pixel space over a `width` x `height` bounds rect. */
|
|
11
|
+
draw(gl: WebGL2RenderingContext, lines: LineData[], width: number, height: number): void;
|
|
12
|
+
destroy(): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class GlTextRenderer {
|
|
2
|
+
private gl;
|
|
3
|
+
private program;
|
|
4
|
+
private vao;
|
|
5
|
+
private buffer;
|
|
6
|
+
private texture;
|
|
7
|
+
private textureImage;
|
|
8
|
+
private uCanvasSize;
|
|
9
|
+
private uScreenPxRange;
|
|
10
|
+
private uFontTexture;
|
|
11
|
+
private ensureProgram;
|
|
12
|
+
private ensureTexture;
|
|
13
|
+
/** Draw one already-laid-out glyph run (screen-pixel vertices). */
|
|
14
|
+
draw(gl: WebGL2RenderingContext, image: ImageBitmap, vertices: Float32Array, count: number, screenPxRange: number, width: number, height: number): void;
|
|
15
|
+
destroy(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const GL_LINE_VERT = "#version 300 es\nprecision highp float;\nuniform vec2 canvasSize;\nin vec2 lineStart;\nin vec2 lineEnd;\nin float lineThickness;\nin vec4 lineColor;\nout vec4 vColor;\n\nvoid main() {\n int vIdx = gl_VertexID;\n vec2 delta = lineEnd - lineStart;\n vec2 dir = normalize(delta);\n vec2 perp = vec2(-dir.y, dir.x);\n float halfThickness = lineThickness * 0.5;\n vec2 offset;\n if (vIdx == 0) {\n offset = -perp * halfThickness;\n } else if (vIdx == 1) {\n offset = perp * halfThickness;\n } else if (vIdx == 2) {\n offset = -perp * halfThickness + delta;\n } else {\n offset = perp * halfThickness + delta;\n }\n vec2 pixelPos = lineStart + offset;\n vec2 ndc = (pixelPos / canvasSize) * 2.0 - 1.0;\n gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);\n vColor = lineColor;\n}\n";
|
|
2
|
+
export declare const GL_LINE_FRAG = "#version 300 es\nprecision highp float;\nin vec4 vColor;\nout vec4 fragColor;\n\nvoid main() {\n fragColor = vColor;\n}\n";
|
|
3
|
+
export declare const WGSL_LINE = "\nstruct LineUniforms {\n canvasSize: vec2f,\n};\n\nstruct Line {\n start: vec2f,\n end: vec2f,\n thickness: f32,\n _pad0: f32,\n _pad1: f32,\n _pad2: f32,\n color: vec4f,\n};\n\n@group(0) @binding(0) var<uniform> u: LineUniforms;\n@group(0) @binding(1) var<storage, read> lines: array<Line>;\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) color: vec4f,\n};\n\n@vertex\nfn vertex_main(\n @builtin(vertex_index) vIdx: u32,\n @builtin(instance_index) iIdx: u32\n) -> VertexOutput {\n let line = lines[iIdx];\n let delta = line.end - line.start;\n let dir = normalize(delta);\n let perp = vec2f(-dir.y, dir.x);\n let halfThickness = line.thickness * 0.5;\n var offset = vec2f(0.0);\n if (vIdx == 0u) {\n offset = -perp * halfThickness;\n } else if (vIdx == 1u) {\n offset = perp * halfThickness;\n } else if (vIdx == 2u) {\n offset = -perp * halfThickness + delta;\n } else {\n offset = perp * halfThickness + delta;\n }\n let pixelPos = line.start + offset;\n let ndc = (pixelPos / u.canvasSize) * 2.0 - 1.0;\n var out: VertexOutput;\n out.position = vec4f(ndc.x, -ndc.y, 0.0, 1.0);\n out.color = line.color;\n return out;\n}\n\n@fragment\nfn fragment_main(in: VertexOutput) -> @location(0) vec4f {\n return in.color;\n}\n";
|
|
4
|
+
export declare const GL_TEXT_VERT = "#version 300 es\nprecision highp float;\nuniform vec2 canvasSize;\nin vec2 pos;\nin vec2 uv;\nin vec4 color;\nout vec2 vUv;\nout vec4 vColor;\n\nvoid main() {\n vec2 ndc = (pos / canvasSize) * 2.0 - 1.0;\n gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);\n vUv = uv;\n vColor = color;\n}\n";
|
|
5
|
+
export declare const GL_TEXT_FRAG = "#version 300 es\nprecision highp float;\nuniform highp sampler2D fontTexture;\nuniform float screenPxRange;\nin vec2 vUv;\nin vec4 vColor;\nout vec4 fragColor;\n\nfloat median(float r, float g, float b) {\n return max(min(r, g), min(max(r, g), b));\n}\n\nvoid main() {\n vec3 msd = texture(fontTexture, vUv).rgb;\n float sd = median(msd.r, msd.g, msd.b);\n float opacity = clamp(screenPxRange * (sd - 0.5) + 0.5, 0.0, 1.0);\n if (opacity <= 0.0) discard;\n fragColor = vec4(vColor.rgb, vColor.a * opacity);\n}\n";
|
|
6
|
+
export declare const WGSL_TEXT = "\nstruct TextUniforms {\n canvasSize: vec2f,\n screenPxRange: f32,\n _pad: f32,\n};\n\n@group(0) @binding(0) var<uniform> u: TextUniforms;\n@group(0) @binding(1) var fontTex: texture_2d<f32>;\n@group(0) @binding(2) var fontSampler: sampler;\n\nstruct VertexOutput {\n @builtin(position) position: vec4f,\n @location(0) uv: vec2f,\n @location(1) color: vec4f,\n};\n\n@vertex\nfn vertex_main(\n @location(0) pos: vec2f,\n @location(1) uv: vec2f,\n @location(2) color: vec4f\n) -> VertexOutput {\n var out: VertexOutput;\n let ndc = (pos / u.canvasSize) * 2.0 - 1.0;\n out.position = vec4f(ndc.x, -ndc.y, 0.0, 1.0);\n out.uv = uv;\n out.color = color;\n return out;\n}\n\nfn median(r: f32, g: f32, b: f32) -> f32 {\n return max(min(r, g), min(max(r, g), b));\n}\n\n@fragment\nfn fragment_main(in: VertexOutput) -> @location(0) vec4f {\n let msd = textureSample(fontTex, fontSampler, in.uv).rgb;\n let sd = median(msd.r, msd.g, msd.b);\n let opacity = clamp(u.screenPxRange * (sd - 0.5) + 0.5, 0.0, 1.0);\n return vec4f(in.color.rgb, in.color.a * opacity);\n}\n";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LineData } from '../line';
|
|
2
|
+
export declare class WgpuLineRenderer {
|
|
3
|
+
private device;
|
|
4
|
+
private pipeline;
|
|
5
|
+
private bindLayout;
|
|
6
|
+
private paramsBuffer;
|
|
7
|
+
private storageBuffer;
|
|
8
|
+
private bindGroup;
|
|
9
|
+
private capacity;
|
|
10
|
+
private key;
|
|
11
|
+
private ensurePipeline;
|
|
12
|
+
private ensureCapacity;
|
|
13
|
+
/** Append `lines` (screen-pixel space) to the open pass over a bounds rect. */
|
|
14
|
+
draw(device: GPUDevice, pass: GPURenderPassEncoder, colorFormat: GPUTextureFormat, sampleCount: number, depthFormat: GPUTextureFormat | undefined, lines: LineData[], width: number, height: number): void;
|
|
15
|
+
destroy(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** One already-laid-out glyph run to draw: its vertices, vertex count and AA range. */
|
|
2
|
+
export type TextRun = {
|
|
3
|
+
vertices: Float32Array;
|
|
4
|
+
count: number;
|
|
5
|
+
screenPxRange: number;
|
|
6
|
+
};
|
|
7
|
+
export declare class WgpuTextRenderer {
|
|
8
|
+
private device;
|
|
9
|
+
private pipeline;
|
|
10
|
+
private bindLayout;
|
|
11
|
+
private uniformBuffer;
|
|
12
|
+
private vertexBuffer;
|
|
13
|
+
private sampler;
|
|
14
|
+
private texture;
|
|
15
|
+
private textureImage;
|
|
16
|
+
private bindGroup;
|
|
17
|
+
private capacityBytes;
|
|
18
|
+
private uniformCapacity;
|
|
19
|
+
private key;
|
|
20
|
+
private ensurePipeline;
|
|
21
|
+
private ensureTexture;
|
|
22
|
+
private ensureUniformBuffer;
|
|
23
|
+
private ensureVertexBuffer;
|
|
24
|
+
private ensureBindGroup;
|
|
25
|
+
/**
|
|
26
|
+
* Draw all already-laid-out glyph runs into the open pass. Every run's
|
|
27
|
+
* vertices are packed into one vertex buffer and its (width, height,
|
|
28
|
+
* screenPxRange) uniform into its own 256-byte slot, so each draw reads its
|
|
29
|
+
* own data — writing every run into a single shared buffer would collapse to
|
|
30
|
+
* the last run before the deferred pass executes.
|
|
31
|
+
*/
|
|
32
|
+
drawAll(device: GPUDevice, pass: GPURenderPassEncoder, colorFormat: GPUTextureFormat, sampleCount: number, depthFormat: GPUTextureFormat | undefined, image: ImageBitmap, runs: readonly TextRun[], width: number, height: number): void;
|
|
33
|
+
destroy(): void;
|
|
34
|
+
}
|
package/dist/ruler.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LineData } from './line';
|
|
2
|
+
import { UIKitTextItem } from './textOverlay';
|
|
3
|
+
export type Vec2 = readonly [number, number];
|
|
4
|
+
export type RGBA = readonly [number, number, number, number];
|
|
5
|
+
export interface RulerSpec {
|
|
6
|
+
/** Endpoints in screen pixels. */
|
|
7
|
+
a: Vec2;
|
|
8
|
+
b: Vec2;
|
|
9
|
+
/** Measured length to display (in `units`). */
|
|
10
|
+
length: number;
|
|
11
|
+
/** Unit suffix, e.g. 'mm'. */
|
|
12
|
+
units?: string;
|
|
13
|
+
/** Label text height in pixels. Default 36. */
|
|
14
|
+
sizePx?: number;
|
|
15
|
+
/** Decimals in the length label. Default 1. */
|
|
16
|
+
decimals?: number;
|
|
17
|
+
lineColor?: RGBA;
|
|
18
|
+
textColor?: RGBA;
|
|
19
|
+
/** Line thickness in pixels. Default 2. */
|
|
20
|
+
thickness?: number;
|
|
21
|
+
/** Half-length of a minor tick in pixels. Default 6. */
|
|
22
|
+
tickLength?: number;
|
|
23
|
+
/** Draw tick marks every unit (majors every 5). Default true. */
|
|
24
|
+
showTicks?: boolean;
|
|
25
|
+
/** Draw the number at every major tick. Default false. */
|
|
26
|
+
showTickNumbers?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Draw long perpendicular end caps crossing the start and end points to mark
|
|
29
|
+
* the measurement's exact extent (longer than a major tick). Default true.
|
|
30
|
+
*/
|
|
31
|
+
showEndCaps?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Outline width (px) for the label + tick text, for readability over busy
|
|
34
|
+
* backgrounds. Default 2. The outline color auto-contrasts the text color
|
|
35
|
+
* (black on light text, white on dark). Set 0 to disable.
|
|
36
|
+
*/
|
|
37
|
+
textOutlineWidthPx?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface RulerGeometry {
|
|
40
|
+
lines: LineData[];
|
|
41
|
+
text: UIKitTextItem[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the line + text draw data for a ruler. Pure geometry; font-independent
|
|
45
|
+
* (glyph widths are resolved when the text is laid out at draw time).
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildRuler(spec: RulerSpec): RulerGeometry;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { RulerSpec } from './ruler';
|
|
3
|
+
import { UIKitFont } from './text/font';
|
|
4
|
+
export declare class UIKitRulerOverlay implements UIKitOverlayRenderer {
|
|
5
|
+
private readonly lines;
|
|
6
|
+
private readonly labels;
|
|
7
|
+
private hasRuler;
|
|
8
|
+
constructor(font: UIKitFont, spec?: RulerSpec);
|
|
9
|
+
/** Set (or update) the ruler. Trigger a redraw via the controller. */
|
|
10
|
+
setRuler(spec: RulerSpec): void;
|
|
11
|
+
/** Clear the ruler so nothing draws. */
|
|
12
|
+
clear(): void;
|
|
13
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
14
|
+
/** Release GPU resources on both backends. */
|
|
15
|
+
destroy(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface UIKitGlyph {
|
|
2
|
+
/** [left, bottom, width, height] in [0,1] atlas UV space. */
|
|
3
|
+
readonly uv: readonly [number, number, number, number];
|
|
4
|
+
/** [left, bottom, width, height] in em units (quad to place). */
|
|
5
|
+
readonly plane: readonly [number, number, number, number];
|
|
6
|
+
/** Horizontal advance in em units. */
|
|
7
|
+
readonly xadv: number;
|
|
8
|
+
}
|
|
9
|
+
export interface UIKitFontMetrics {
|
|
10
|
+
/** MSDF distance range in pixels (from atlas gen). */
|
|
11
|
+
readonly distanceRange: number;
|
|
12
|
+
/** Atlas glyph em size in pixels. */
|
|
13
|
+
readonly size: number;
|
|
14
|
+
/** Atlas texture dimensions in pixels. */
|
|
15
|
+
readonly textureSize: readonly [number, number];
|
|
16
|
+
readonly glyphs: ReadonlyMap<string, UIKitGlyph>;
|
|
17
|
+
}
|
|
18
|
+
/** A parsed font plus its uploaded-once atlas image, consumed by the renderers. */
|
|
19
|
+
export interface UIKitFont {
|
|
20
|
+
readonly metrics: UIKitFontMetrics;
|
|
21
|
+
readonly image: ImageBitmap;
|
|
22
|
+
}
|
|
23
|
+
interface RawGlyph {
|
|
24
|
+
unicode: number;
|
|
25
|
+
advance: number;
|
|
26
|
+
atlasBounds?: {
|
|
27
|
+
left: number;
|
|
28
|
+
top: number;
|
|
29
|
+
right: number;
|
|
30
|
+
bottom: number;
|
|
31
|
+
};
|
|
32
|
+
planeBounds?: {
|
|
33
|
+
left: number;
|
|
34
|
+
top: number;
|
|
35
|
+
right: number;
|
|
36
|
+
bottom: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface RawFontFile {
|
|
40
|
+
atlas: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
distanceRange: number;
|
|
44
|
+
size: number;
|
|
45
|
+
};
|
|
46
|
+
glyphs: RawGlyph[];
|
|
47
|
+
}
|
|
48
|
+
/** Parse msdf-atlas-gen JSON into a UIKit font metrics table. */
|
|
49
|
+
export declare function parseFont(raw: RawFontFile): UIKitFontMetrics;
|
|
50
|
+
/**
|
|
51
|
+
* MSDF anti-aliasing range in screen pixels for a given text size, matching the
|
|
52
|
+
* old uikit: `max((size / atlasSize) * distanceRange, 1)`. Passed to the shader.
|
|
53
|
+
*/
|
|
54
|
+
export declare function screenPxRange(metrics: UIKitFontMetrics, sizePx: number): number;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { UIKitFontMetrics } from './font';
|
|
2
|
+
export declare const FLOATS_PER_VERTEX = 8;
|
|
3
|
+
export declare const VERTICES_PER_GLYPH = 6;
|
|
4
|
+
export type RGBA = readonly [number, number, number, number];
|
|
5
|
+
export interface TextLayoutOptions {
|
|
6
|
+
/** Anchor position in screen pixels (baseline reference before alignment). */
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
/** Text height in screen pixels (the em size; scales the atlas plane bounds). */
|
|
10
|
+
sizePx: number;
|
|
11
|
+
/** Rotation in radians, measured in screen space (0 = left-to-right, y-down). */
|
|
12
|
+
rotation?: number;
|
|
13
|
+
color?: RGBA;
|
|
14
|
+
/** Horizontal alignment along the (rotated) baseline: 0 left, 0.5 center, 1 right. */
|
|
15
|
+
align?: number;
|
|
16
|
+
/** Shift perpendicular to the text direction, in pixels (positive = above line). */
|
|
17
|
+
liftPx?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Outline (halo) width in screen pixels; 0 (default) draws no outline. The
|
|
20
|
+
* effective width is bounded by the atlas SDF range, so a small value (1-2)
|
|
21
|
+
* reads best with the bundled MSDF atlas.
|
|
22
|
+
*/
|
|
23
|
+
outlineWidthPx?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Outline color. Omit to auto-pick black or white for contrast against the
|
|
26
|
+
* fill color (see {@link autoOutlineColor}).
|
|
27
|
+
*/
|
|
28
|
+
outlineColor?: RGBA;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pick a high-contrast outline color for a fill: black for light fills, white
|
|
32
|
+
* for dark ones, using perceptual (Rec. 601) luminance.
|
|
33
|
+
*/
|
|
34
|
+
export declare function autoOutlineColor(fill: RGBA): RGBA;
|
|
35
|
+
/** Total advance width of `str` in pixels at `sizePx`. */
|
|
36
|
+
export declare function measureWidth(metrics: UIKitFontMetrics, str: string, sizePx: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Normalize a line direction angle so text drawn along it is never upside down.
|
|
39
|
+
* When the raw angle points leftward (cos < 0), the label would render mirrored;
|
|
40
|
+
* flip it by pi. Returns the readable angle and whether a flip occurred (the
|
|
41
|
+
* caller flips the perpendicular lift so the label stays on the same side).
|
|
42
|
+
*/
|
|
43
|
+
export declare function readableAngle(rotation: number): {
|
|
44
|
+
angle: number;
|
|
45
|
+
flipped: boolean;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Lay out `str` into screen-pixel triangle vertices. Returns the packed vertex
|
|
49
|
+
* buffer (8 floats/vertex) and the vertex count (6 per rendered glyph).
|
|
50
|
+
*/
|
|
51
|
+
export declare function layoutText(metrics: UIKitFontMetrics, str: string, opts: TextLayoutOptions): {
|
|
52
|
+
vertices: Float32Array;
|
|
53
|
+
count: number;
|
|
54
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { UIKitFont } from './text/font';
|
|
3
|
+
import { TextLayoutOptions } from './text/layout';
|
|
4
|
+
/** One piece of text to draw: the string plus its layout pose. */
|
|
5
|
+
export type UIKitTextItem = TextLayoutOptions & {
|
|
6
|
+
str: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class UIKitTextOverlay implements UIKitOverlayRenderer {
|
|
9
|
+
private font;
|
|
10
|
+
private items;
|
|
11
|
+
private readonly gl;
|
|
12
|
+
private readonly wgpu;
|
|
13
|
+
private runs;
|
|
14
|
+
constructor(font: UIKitFont, items?: UIKitTextItem[]);
|
|
15
|
+
/** Swap the font atlas (metrics + image). Trigger a redraw via the controller. */
|
|
16
|
+
setFont(font: UIKitFont): void;
|
|
17
|
+
/** Replace the text items drawn each frame. Trigger a redraw via the controller. */
|
|
18
|
+
setItems(items: UIKitTextItem[]): void;
|
|
19
|
+
private layoutRuns;
|
|
20
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
21
|
+
/** Release GPU resources on both backends. */
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|