DIR.Lib 9.2.3071

This package has a SemVer 2.0.0 package version: 9.2.3071+a4c44b8658e0079a736fb81c10b962514f65f7d5.
dotnet add package DIR.Lib --version 9.2.3071
                    
NuGet\Install-Package DIR.Lib -Version 9.2.3071
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DIR.Lib" Version="9.2.3071" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DIR.Lib" Version="9.2.3071" />
                    
Directory.Packages.props
<PackageReference Include="DIR.Lib" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DIR.Lib --version 9.2.3071
                    
#r "nuget: DIR.Lib, 9.2.3071"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DIR.Lib@9.2.3071
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DIR.Lib&version=9.2.3071
                    
Install as a Cake Addin
#tool nuget:?package=DIR.Lib&version=9.2.3071
                    
Install as a Cake Tool

DIR.Lib

Device-Independent input + Rendering library for .NET. Provides the shared foundation for GPU (SDL3 + Vulkan), terminal (Console), and browser (WebGL2 / Blazor WebAssembly) applications. Pure-managed, AOT-compatible, no native dependencies.

Rendering Primitives

  • PointInt — 2D integer point
  • RectInt — 2D integer rectangle (note: constructor argument order is (LowerRight, UpperLeft))
  • RectF32 — 2D float rectangle (x, y, width, height) for pixel-based layout
  • RGBAColor32 — 32-bit RGBA color with Lerp, WithAlpha, Luminance
  • TextAlign — Near/Center/Far alignment enum
  • Renderer<TSurface> — Abstract renderer: FillRectangle, FillRoundedRectangle, DrawRectangle, FillEllipse / DrawEllipse, DrawLine, DrawLineDashed, DrawPolyline, DrawPolylineDashed, DrawText, MeasureText
  • RgbaImage / RgbaImageRenderer : Renderer<RgbaImage> — pure software renderer for tests and headless scenarios; output is plain RGBA pixels (callers own the choice of PNG / JPEG / TIFF / sixel encoder)
  • GlyphBitmap / SdfGlyphBitmap — raw RGBA glyph bitmap with bearing/advance info; SDF variant for scalable text on the GPU side
  • ManagedFontRasterizer — pure-managed glyph rasterizer backed by SharpAstro.Fonts.OpenTypeFont; supports COLRv1 color glyphs, grayscale, and PDF subset fonts. AOT-compatible, no GC pinning, no native bindings.
  • FontResolver — resolves platform-default monospace fonts and enumerates installed font files across system + per-user font directories (incl. Windows 11 %LOCALAPPDATA%\Microsoft\Windows\Fonts)
  • FontFallbackResolver — splits a string into runs that each draw with a face that covers them; with faces declared by role (FromRoles), a codepoint whose Unicode default presentation is emoji is taken from the emoji face even where the primary covers it
  • EmojiPresentation — the UTS #51 Emoji_Presentation property (IsDefaultFor), over a table generated from the Unicode Character Database by tools/gen-emoji-presentation
  • ListCursor -- the keyboard's position in a list the layout tree already declares. A row states ListItemHit(list, index) for its click binding and is navigable by that alone: PixelWidgetBase.ListCursor + HandleListKey move and act, Layout.Node.FocusBackground (.BgFocus) shows where it is, and a row that is not clickable -- or one declared .Disabled(reason) -- is unreachable without anything beside the list saying so. Open(listId, index, count) adds the row count a VIRTUALISED list needs, so the arrows can step onto a row the last paint did not draw; Moved is where a consumer hangs EnsureVisible
  • FloatingPalette — a floating, grip-dragged, collapsible palette of toggle rows, as a Layout.Node tree plus the pure state and colour rules around it (FloatingPaletteState, PaletteItem, PaletteColors); Build returns the tree and touches no surface

Input Handling

  • InputEvent — open record hierarchy: KeyDown, TextInput, MouseDown, MouseUp, MouseMove, Scroll, Pinch, PinchEnd
  • InputKey — platform-agnostic key codes (letters, digits, function keys, navigation, symbols)
  • InputModifier — modifier flags (Shift, Ctrl, Alt)
  • MouseButton -- Left / Middle / Right, plus None for a pointer moving with nothing held
  • KeyChord -- a key plus its modifiers, and the precedence rule on it: BeatsFocusedField is true for Ctrl, Alt and the function keys, false for a bare letter. Stated once so a router and a test read the same fact, instead of each host special-casing its own global key by name
  • PointerPress / PointerMove / DragCapture -- a press with its position, button, modifiers and click count; the capture a press handler returns to own every move and the release until the button comes up
  • InputRouter: the dispatcher, so a host stops writing one. It takes an InputEvent and hands it to the regions, fields, shortcuts, captures and scroll controllers the last paint declared, in one fixed order: an open popover reads a key first, then any painted node's declared Shortcut if KeyChord.BeatsFocusedField lets it through, then the focused field, then the host's own Unhandled. A press places the caret or arms a drag, a wheel finds the innermost list under the pointer, and AfterPaint blurs a field that left the screen, answers a focusOnOpen request and expires a stale tooltip. CursorAt(x, y) and Tooltip are what a host paints from
  • IWidget — shared interface with HandleInput for both pixel and terminal widgets

Platform bridges (in downstream packages):

  • SdlVulkan.Renderer provides SdlInputMapping (SDL3 Scancode → InputKey)
  • Console.Lib provides ConsoleInputMapping (ConsoleKey → InputKey)
  • WebGl.Renderer provides WebGlCanvas, a Blazor component that maps DOM pointer / wheel / pinch events to backing-space coordinates (CanvasPointerEventArgs, CanvasWheelEventArgs, CanvasPinchEventArgs) and forwards keydown raw; the browser KeyboardEvent.Key → InputKey map lives in the consuming app (see MapKey in TianWen.UI.Web's Planner)

Widget System

  • IPixelWidget — extends IWidget with pixel-coordinate hit testing and click dispatch, plus what a router reads back from the last paint: CollectPaintedRegions / CollectPaintedNodes (a composite folds its children's in), Pointer, ScrollTargetAt, HitTestCursor and CaretIndexAt
  • PixelWidgetBase<TSurface> -- base class for pixel widgets: clickable regions, text input, buttons, dropdowns, drawing helpers. MeasureLayout / MeasureContext are the measure seam (a box is the MEASUREMENT of its content, through the same context arrange and paint share); ScrollTargetAt(x, y) answers which declared list a wheel belongs to; DimTowards(color, background) is the one grey a disabled thing is painted in
  • PixelLayout + PixelDockStyle — dock-based layout engine (Top/Bottom/Left/Right/Fill)
  • DockLayout<T> — generic dock layout using INumber<T> (the integer / pixel layouts above are built on this)
  • ClickableRegion + ClickableRegionTracker — registered during render, walked in reverse for hit testing
  • HitResult — open discriminated union: TextInputHit, ButtonHit, ListItemHit, SlotHit<T>, SliderHit
  • DropdownMenuState — dropdown / popup menu state machine

Declarative Layout (DIR.Lib.Layout)

A surface-agnostic declarative layout engine. Describe a tree of immutable records; the engine measures + arranges it into rects; a per-surface painter (PixelWidgetBase.PaintLayout) draws each node and binds its click region from the same arranged rect — draw == hit by construction, with no separate hit-rect arithmetic that can drift.

  • Layout.Node — the tree. Variants: Stack (vertical/horizontal), Dock (edge strips + a fill remainder), Grid, Wrap (children flow and wrap into new lines when out of extent — the flexbox wrap for toolbars/chip rows on narrow surfaces), Overlay (base/top, for modals/popups), Split (two resizable panes + a draggable divider), Leaf (a Content). Chrome lives on the base node: Width/Height (Sizing), Padding, Background, Hit, OnClick, CollapseThreshold.
  • What a node DECLARES, beyond its chrome (9.2) -- OnPress (a press with its position, returning a DragCapture to own the drag that follows), OnActivate (what Enter does when it differs from a click), Tooltip, DisabledReason (IsDisabled), Scroll (a ListScrollController whose viewport this node's arranged rect IS), Shortcut (a KeyChord). The painter binds every one of them to the same arranged rect it drew in, so what is declared and what responds cannot drift. Painting a tooltip and firing a shortcut belong to the router; declaring them does not wait for it.
  • Layout.Content — leaf payload: Text (value + colour + alignment), Box (fixed icon/swatch/spacer), Fill (an app-drawn escape hatch — chart, image, text input; routed by Key).
  • Layout.SizingFixed(designUnits) | Auto (shrink-to-content) | Star(weight, min, max) (proportional split of leftover). Values are design units mapped to surface units (px × DPI, or character cells) by Layout.IMeasureContext. Min/Max clamp the resolved extent of an Auto/Star axis (0 = unclamped): a min-clamped Star holds its floor and overflows visibly instead of starving to zero when Fixed siblings eat the container, and a max-clamped Star's surplus redistributes to its Star siblings.
  • Collapse-below-minimum.CollapseBelow(designUnits): when a parent Stack would give the node a main-axis extent under the threshold, it drops out of the arrangement entirely (not painted, no hit, no gap) and its space redistributes to the survivors. The declarative form of "show the strip only when it is at least N tall".
  • Layout.Engine.Arrange(root, rect, ctx) — two-pass measure/arrange; returns a pre-order ImmutableArray<Layout.ArrangedNode> the painter walks in order for correct z-stacking. Generic over the coordinate type (float pixels / int cells), so it is headless-testable with a stub IMeasureContext.

Layout.Builder DSL

Author trees with the fluent DSL rather than new Layout.Node.X { } initializers — it emits the same records:

using Layout = DIR.Lib.Layout;   // alias once per project; keep `using DIR.Lib;`

Layout.Builder.HStack(
        Layout.Builder.Text(label, 14f, dim).WStar(0.35f).HStar(),
        Layout.Builder.Fill(key: "input").Stretch())
    .RowH(28f)
    .Bg(active ? activeBg : normalBg)
    .Clickable(new HitResult.ButtonHit("go"), onClick);
  • FactoriesVStack / HStack / Text / Box / Fill / Spacer / Grid / WrapH / WrapV / Overlay / Split / Dock (+ Left/Right/Top/Bottom dock-strip helpers).
  • Fluent modifiers (instance methods on Layout.Node, each a pure this with { … } transform) -- .W/.H/.WFixed/.WStar(weight, min, max)/.WAuto (+ H*), .WClamp/.HClamp(min, max) (clamp the current kind), .RowH(u) (full-width row), .ColW(u) (fixed-width column), .Stretch() (fill both axes), .Bg, .Radius(u), .Pad, .Clickable(hit, onClick?), .CollapseBelow(u), .WithGap/.WithGaps/.WithLineGap/.WithColumns.
  • Behaviour modifiers (9.2) -- .Pressable(hit, onPress) (the press is handed a PointerPress and returns a DragCapture or null to decline, so a slider arms its drag from the node it was painted on), .Activatable(onActivate) (Enter pins where a click selects), .WithTooltip(text), .Disabled(reason) / .Disabled(when, reason) (dims the subtree, swallows the press with a NotAllowed cursor, and the list cursor steps over it), .WithScroll(controller) (the arranged rect becomes the viewport; PixelWidgetBase.ScrollTargetAt(x, y) answers which list a wheel belongs to), .WithShortcut(key, mods). They are named With* where a bare verb would shadow the property it sets -- the rule .WithCursor and .WithGap already follow.
  • Grid column sizing -- .WithColumns(Sizing.Auto, Sizing.Star(), …): Auto takes its own column's widest cell, Fixed is fixed, Star shares the rest, columns past the stated ones are Star(1), and stating none keeps the even split a grid has always done. That is a table without any column arithmetic at the call site.
  • .Radius(u) is chrome, not geometry. It rounds the node's .Bg (and a Box leaf's own fill) by u design units, but arrange never sees it — a rounded node occupies and insets exactly the rect a square one would, so rounding a panel can never shift the layout inside or around it. Each surface honours it as far as it can: a pixel painter via Renderer.FillRoundedRectangle (which a GPU backend may override with one SDF quad), a cell painter via arc corners ╭ ╮ ╰ ╯, since a character grid cannot round by fractions of a cell. A radius of 0 takes the plain FillRectangle path, so untouched trees paint byte-identically.
  • Consumer convention — alias using Layout = DIR.Lib.Layout; (a global using, or a csproj <Using Include="DIR.Lib.Layout" Alias="Layout" />) and write the qualified Layout.Node / Layout.Builder. Do not using DIR.Lib.Layout; directly — it drops the collision-prone barewords (Node, Content, Size<T>) into scope. (A plain using DIR.Lib; does not surface the nested Layout namespace; a using-directive imports types, not nested namespaces.) A consumer that already owns a Layout type must rename it.

Text Input

  • TextInputState — single-line text input state machine with cursor and selection
  • TextInputRenderer — renders text input using any Renderer<T> (blinking cursor, selection highlight, and a horizontal scroll that keeps the caret inside a box too narrow for the whole value)
  • Word motion: Ctrl+Left / Ctrl+Right step to the start of the neighbouring word, Shift extends the selection with them, Ctrl+Backspace deletes back over one and Ctrl+X cuts. InputKey.ToTextInputKey is the one place a chord becomes a meaning, so every surface reads the keyboard the same way.
  • Callbacks: OnCommit (async), OnCancel, OnTextChanged, OnKeyOverride

Signals & Async

  • SignalBus — thread-safe typed event bus. Post<T>() is thread-safe, ProcessPending() runs on the render thread.
  • Built-in signals: ActivateTextInputSignal, DeactivateTextInputSignal, RequestExitSignal, RequestRedrawSignal
  • SignalDirectory (source-generated) — the package ships a Roslyn source generator that emits SignalDirectory.BuildFactories(SignalBus bus, …overrides), a name → Action<JsonElement> map over every *Signal type in the consuming assembly, with no runtime reflection. Each factory constructs its signal from a JSON payload via the reflection-free SignalJson scalar binders (camelCase key = parameter name; missing field → the parameter's declared default) and posts it to the bus. Lets a live UI inspector / test harness list and post any bus signal by name. Gated on the DEBUG symbol (nothing generated in Release) and on SignalBus being referenced; signals with a required non-scalar parameter are skipped.
  • BackgroundTaskTracker — collects background tasks, checks completions per frame, logs errors via ILogger. Call ProcessCompletions() each frame, DrainAsync() at shutdown.

Math Layout (DIR.Lib.MathLayout)

TeX-style box model for rendering mathematical expressions. Each Box exposes Width / Height (ascent) / Depth (descent) and paints itself relative to a (penX, baselineY) the parent provides.

  • Box + BoxStyle — abstract box with baseline, plus a record of font / size / spacing parameters threaded through layout. Pixel-valued math metrics (axis height, fraction-rule thickness, …) come from the font's OpenType MATH table when available, with TeX-style ratio fallbacks.
  • Box types: GlyphBox, MathGlyphBox, HBox, FracBox, SqrtBox, BracketBox, BigOperatorBox, SupSubBox, AccentBox, LimitsBox, MatrixBox, OverlayBox, StretchyVerticalBox
  • BoxRasterizer.RenderToRgba(box, style) — rasterizes a Box to a transparent RgbaImage. Pure — no encoder coupling; callers choose PNG / sixel / half-block downstream.

Markdown + LaTeX (DIR.Lib.Markdown)

A LALR.CC-driven markdown + math-mode LaTeX pipeline. The math, markdown-inline, and markdown-block grammars (grammars/*.lalr.yaml) are compiled at build time by the SharpAstro.LALR.CC source generator into partial classes baked into this assembly — no runtime parser construction, AOT-clean.

  • MdAst — block & inline AST records (MdParagraph, MdHeading, MdMathBlock, MdList, MdTable, MdInline, …)
  • MarkdownBlockVisitor / MarkdownInlineVisitor — visitors over the generated grammars; produce the AST.
  • LatexUnicodeVisitor — math-mode LaTeX → Unicode (inline math: $x^2$).
  • BoxBuildingVisitor — math-mode LaTeX → deferred Box builders (display math: $$..$$MathLayout box tree → BoxRasterizer).
  • Mhchem — renders an mhchem \ce{...} body to Unicode (auto-subscripts, arrows, ion charges, …).
  • MarkdownMacros — parser-side facade: macro expansion (\text{}, \boxed{}, \ce{}, \begin/\end environments), backslash-escape resolution, and the RenderMathUnicode entry point.

Usage

using DIR.Lib;
using DIR.Lib.MathLayout;
using DIR.Lib.Markdown;

// Rendering
renderer.FillRectangle(rect, new RGBAColor32(0x30, 0x50, 0x90, 0xff));
renderer.DrawText("Hello", fontPath, 14f, white, layout);
renderer.DrawPolyline(points, color, thickness: 2);

// Input handling
widget.HandleInput(new InputEvent.KeyDown(InputKey.Enter, InputModifier.Ctrl));

// Pixel layout
var layout = new PixelLayout(contentRect);
var header  = layout.Dock(PixelDockStyle.Top, 28f);
var sidebar = layout.Dock(PixelDockStyle.Left, 200f);
var content = layout.Fill();

// Background tasks
tracker.Run(async () => await SaveAsync(), "Save profile");
if (tracker.ProcessCompletions(logger)) needsRedraw = true;

// Math rendering (display LaTeX → RGBA image)
var unicode = MarkdownMacros.RenderMathUnicode("E = mc^2");      // "E = mc²"
var image   = BoxRasterizer.RenderToRgba(boxBuilder(style), style);

Dependencies

DIR.Lib is codec-agnostic (4.0+): BoxRasterizer.RenderToRgba returns an RgbaImage, and consumers that need TIFF / PNG / JPEG / ICC encoding declare those packages (SharpAstro.Tiff, SharpAstro.Png, SharpAstro.Color.Icc, …) themselves.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on DIR.Lib:

Package Downloads
TianWen.Lib

Astronomical imaging and device-control library for .NET: cameras, mounts, focusers, filter wheels, cover/calibrators and guiders over ASCOM, Alpaca, ZWO, QHYCCD, Meade LX200, Skywatcher, OnStep and PHD2, plus plate solving, deep-sky and planetary stacking, auto-focus and unattended session automation. First-class multi-OTA (dual rig) support. AOT compatible.

SdlVulkan.Renderer

SDL3 + Vulkan rendering backend for DIR.Lib's Renderer<TSurface>: window, device and swapchain lifecycle, pre-baked SPIR-V pipelines, bitmap and MSDF glyph atlases, and a surfaceless offscreen path for headless rendering and tests. Desktop and Android, AOT compatible.

Console.Lib

Terminal application toolkit for .NET: dock-based layouts that recompute on resize, a widget set (text bars, scrollable lists, tree views, text areas, menus, Markdown), mouse and keyboard input, VT styling, and a fast Sixel graphics encoder with sextant / half-block fallbacks. Built on DIR.Lib, AOT compatible.

DIR.Lib.Shaping

Pure-managed OpenType text-shaping adapter for DIR.Lib: an ITextShaper backed by SharpAstro.Fonts.Shaping (script itemization, GSUB/GPOS, Arabic joining, RTL). Optional satellite — DIR.Lib core stays shaping-free.

WebGl.Renderer

WebGL2 rendering backend for DIR.Lib's Renderer<TSurface> — Blazor WebAssembly, command-buffer JS interop, MSDF text via the shared SdfFontAtlas core. AOT compatible.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
9.2.3071 0 9/15/2026
9.2.3051 0 9/15/2026
9.1.3001 13 9/15/2026
9.0.2981 110 9/15/2026
9.0.2971 18 9/15/2026
9.0.2941 177 9/14/2026
9.0.2931 25 9/14/2026
8.21.2921 30 9/12/2026
8.20.2901 163 9/12/2026
8.20.2881 29 9/12/2026
8.19.2861 365 9/11/2026
8.18.2841 22 9/11/2026
8.17.2821 25 9/11/2026
8.17.2801 28 9/11/2026
8.16.2781 52 9/10/2026
8.15.2761 46 9/9/2026
8.14.2741 90 9/9/2026
8.14.2731 132 9/8/2026
8.13.2721 278 9/4/2026
8.13.2701 860 8/28/2026
Loading failed