acdream/tests/AcDream.App.Tests
Erik cf41b27c9a feat(ui): CT-A1 — multi-line text elements can carry coloured runs
Campaign CT slice A1. No behaviour change: this is the capability the rest of
Group A needs.

UiText already drew several differently-coloured runs on one line
(TextRun/RunsProvider, used by the character stat panel) but the path was gated
to OneLine == true, and the chat transcript is multi-line — so a chat line
could only ever be one colour. Retail's is not: a tagged glyph run takes the
element's TAG colour (property 0x1D) while the rest of the line takes the
ordinary one (0x1B), per UIElement_Text::InqGlyphs @0x00468EA0.

LineRunsProvider is a SIDECAR keyed by line index rather than a field on Line.
Roughly fifty files construct Line, and widening its shape would put every one
of them in the blast radius of a chat feature; a line with no runs draws
exactly as before.

The runs fold into the existing datLines list as extra entries at advancing
pen-X, so the S1 outline-then-fill batching is untouched — a multi-colour line
still submits its whole outline pass before any fill, and cannot notch the
descender of the line above.

Two things are deliberately load-bearing:

  - RunsMatchLine. Selection, hit-testing and the caret all index into the FLAT
    line text, so a run list that disagrees with it would draw one thing and
    select another. The draw path verifies the runs say exactly the same
    characters and falls back to the flat line if not, rather than trusting the
    caller.
  - LayoutRuns is pure. The pen-advance is the part that silently mis-renders
    if it drifts, so it is testable without a font atlas or a GPU — which also
    keeps its tests in the ordinary gate rather than the SystemFont lane.

Solution builds clean; full hermetic gate green, 0 failures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 07:18:55 +02:00
..
Architecture test: replace gameplay owner source freezes 2026-08-18 16:49:38 +02:00
Audio feat(audio): Campaign A slice A2 — retail's 2D pan+gain mixer replaces AL 3D 2026-08-08 21:58:50 +02:00
Combat fix(ui,runtime): OP4 review fixes — live re-seed, enable-gating, Combat panel re-point, universal timestamps 2026-08-11 05:30:26 +02:00
Composition fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Configuration fix(app): Campaign LA gate round 2 — session-config launches force the retail UI on 2026-08-15 08:42:33 +02:00
Credentials test: make prerequisite lanes fail honestly 2026-08-18 12:09:41 +02:00
Diagnostics test: replace campaign labels with behavior names 2026-08-18 12:25:00 +02:00
Input test: replace input and physics source freezes 2026-08-18 15:31:57 +02:00
Interaction fix: social panel completion batch (user gate 2026-08-13, "fix all") 2026-08-13 19:30:51 +02:00
Net fix(chat): announce enchantment expiry; stop double-printing tells 2026-08-21 06:11:33 +02:00
Physics test: replace input and physics source freezes 2026-08-18 15:31:57 +02:00
Platform feat(platform): Campaign LA LA0 — extract ApplicationPathSet to AcDream.Platform 2026-08-14 15:19:02 +02:00
Plugins feat(plugins): MossTank — a self-buffing plugin, and the automation surface it needed 2026-08-20 16:22:28 +02:00
Rendering fix(world): rotate the DAT-scenery root too — the flyers actually orbit now 2026-08-21 05:52:44 +02:00
Runtime test: replace gameplay owner source freezes 2026-08-18 16:49:38 +02:00
Settings fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Spells feat(headless): share immutable gameplay content 2026-07-27 09:00:48 +02:00
Streaming test: replace streaming source freezes 2026-08-18 15:14:41 +02:00
UI feat(ui): CT-A1 — multi-line text elements can carry coloured runs 2026-08-21 07:18:55 +02:00
World test: replace create authority source pin 2026-08-18 16:52:22 +02:00
AcDream.App.Tests.csproj build: make release restore reproducible 2026-08-18 10:29:00 +02:00
BoundedTestDatCollection.cs perf(content): remove exception-driven setup probes 2026-07-24 15:12:21 +02:00
FramePhaseTestDoubles.cs refactor(runtime): move session lifetime and ordered transport 2026-07-25 19:39:24 +02:00
FrameProfilerReportTests.cs perf(diag): complete trustworthy Slice A capture tooling 2026-07-24 12:46:51 +02:00
FrameStatsBufferTests.cs fix(pipeline): MP0 - profiler toggle-path hygiene + Max() seed (review follow-up) 2026-07-05 19:26:28 +02:00
GameRuntimeTestFactory.cs refactor(runtime): cut graphical host over to canonical root 2026-07-26 19:06:09 +02:00
GlobalUsings.cs feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
LiveEntityRuntimeFixture.cs test(runtime): restore the world-frame precondition across first-entry fixtures 2026-08-03 13:32:28 +02:00
LiveEntitySpawnFixture.cs feat(runtime): C3c - production placement cutover: both hosts on the residence conductors (routes 1+8) 2026-08-02 18:10:33 +02:00
packages.neutral.lock.json build: make release restore reproducible 2026-08-18 10:29:00 +02:00
RuntimeDatAccessArchitectureTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeDatCollectionFactoryTests.cs feat(headless): share immutable process content 2026-07-27 08:37:24 +02:00
RuntimeOptionsRetailUiTests.cs test(runtime): add deterministic world gate artifacts 2026-07-20 22:37:16 +02:00
RuntimeOptionsTests.cs fix(launcher): close Campaign LA LA1 review findings 2026-08-14 17:00:09 +02:00
RuntimeWorldTransitTestDriver.cs refactor(runtime): own teleport destination correlation 2026-07-26 17:52:34 +02:00
ZeroAllocationProbe.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00
ZeroAllocationProbeTests.cs test(app): measure the warmed path, not the path being warmed (#250) 2026-07-29 03:42:08 +02:00