Commit aea3b0e
committed
feat: implement full CSS flexbox specification (Phases 0-3)
Two-pass layout engine with iterative freeze algorithm inspired by
Facebook Yoga. Consolidate flex item properties into TemplateElement
base class, add flex-wrap with greedy line-breaking, per-line flex
resolution, align-content distribution (7 modes), and wrap-reverse.
Phases implemented:
- Phase 0-1: Foundation (flex properties on base class, align-self,
display:none, direction reverse, non-uniform padding/margin)
- Phase 2: Core flexbox (iterative freeze, flex-basis with min/max
clamping, factor flooring, shrink scaled by basis, overflow
fallback, justify-content SpaceEvenly, SkiaRenderer align support)
- Phase 3: Wrapping (flex-wrap, CalculateFlexLines, ResolveFlexForLine,
LayoutWrappedFlex, align-content with overflow fallback,
wrap-reverse, row-gap/column-gap, MaxFlexLines resource limit)
All 1151 tests pass on both net8.0 and net10.0.
docs: add flexbox expansion documentation and improve Linux/Docker visibility
Add comprehensive documentation for the flexbox expansion project:
- Implementation plan, algorithm reviews, test fixtures, architecture
reviews, and Yoga comparison review (20 docs, ~380KB)
- API reference for all flexbox properties (1152 lines)
Improve SkiaSharp Linux/Docker discoverability:
- Add prominent [!IMPORTANT] callout in README after install command
- Add Linux note to NuGet package descriptions (Skia + MetaPackage)
- Add Linux/Docker warning to llms.txt and llms-full.txt
- Add MaxFlexLines to AGENTS.md resource limits table
feat: implement CSS positioning, overflow, aspect-ratio, and auto margins (Phases 4-5)
Phase 4 — Advanced Features:
- Position absolute: excluded from flex flow, inset-based positioning and sizing
- Position relative: offset from normal flow (left/right/top/bottom with CSS priority)
- Overflow:hidden: canvas clipping in SkiaRenderer via Save/ClipRect/Restore
- Aspect ratio: width/height inference when one dimension is known
Phase 5 — Auto Margins:
- MarginValue/MarginValues readonly record structs with auto support
- PaddingParser.ParseMargin for auto token handling in CSS shorthand
- Main axis auto margins consume free space before justify-content
- Cross axis auto margins override align-items (center/push)
- Works for both Row and Column directions
Tests: 1204 total (53 new), 0 failures on net8.0 and net10.0
fix: absolute positioning fallback + aspect-ratio after flex-grow
- Absolute children without insets now respect parent's justify-content
and align-items instead of defaulting to (0,0)
- Aspect ratio is re-applied after flex-grow/shrink resolution in both
column and row layouts
- Updated AGENTS.md, llms.txt, llms-full.txt with Phase 4-5 features
- Added final architecture and algorithm review documents
- 1207 tests passing
test: add column-direction tests for absolute positioning and aspect-ratio
Cover column layout paths for absolute justify/align fallback and
aspect-ratio after flex-grow (1210 tests)
fix: cross-axis alignment now subtracts margins in non-wrapped paths
Center/End/Stretch cross-axis alignment formulas in LayoutColumnFlex
and LayoutRowFlex now correctly subtract margins from available space,
matching the wrapped path behavior. Added 6 tests (1216 total).
feat: add configurable BMP color depth with 6 encoding modes
Add BmpColorMode enum with Bgra32 (32-bit), Rgb24 (24-bit), Rgb565
(16-bit), Grayscale8 (8-bit), Grayscale4 (4-bit), and Monochrome1
(1-bit) modes. Each mode produces valid BMP files with proper headers,
color tables, row padding, and sub-byte pixel packing.
Expose --bmp-color CLI option in render and watch commands. Pass color
mode through SkiaRender → SkiaRenderer → BmpEncoder pipeline.
refactor: address code review findings in BmpEncoder
Replace stackalloc with ArrayPool<byte> for row buffers exceeding 1024
bytes to prevent stack overflow on wide images. Add exhaustive default
throws in WritePixelData and WriteColorTable switch statements.
Standardize row buffer clearing with Clear() across all modes. Add
Math.Min clamp to Grayscale8 luminance for defensive correctness.1 parent 75a12d0 commit aea3b0e
74 files changed
Lines changed: 18679 additions & 748 deletions
File tree
- docs/flexbox-expansion
- src
- FlexRender.Cli/Commands
- FlexRender.Core
- Configuration
- Layout
- Units
- Parsing/Ast
- FlexRender.MetaPackage
- FlexRender.Skia
- Rendering
- FlexRender.Yaml/Parsing
- tests/FlexRender.Tests
- Layout
- Units
- Parsing/Ast
- Rendering
- Snapshots/golden
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
148 | | - | |
| 148 | + | |
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
162 | | - | |
| 162 | + | |
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| |||
178 | 178 | | |
179 | 179 | | |
180 | 180 | | |
| 181 | + | |
181 | 182 | | |
182 | 183 | | |
183 | 184 | | |
| |||
201 | 202 | | |
202 | 203 | | |
203 | 204 | | |
| 205 | + | |
204 | 206 | | |
205 | 207 | | |
206 | 208 | | |
| |||
364 | 366 | | |
365 | 367 | | |
366 | 368 | | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
367 | 448 | | |
368 | 449 | | |
369 | 450 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
63 | 71 | | |
64 | 72 | | |
65 | 73 | | |
| |||
81 | 89 | | |
82 | 90 | | |
83 | 91 | | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | 92 | | |
97 | 93 | | |
98 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
0 commit comments