ApertureUI Rendering Pipeline
ApertureUI Rendering Pipeline
This document describes the complete rendering pipeline from HTML source to GPU draw calls.
Pipeline Overview
┌─────────────────────────────────────────────────────────────────────────────┐
│ ApertureUI Rendering Pipeline │
└─────────────────────────────────────────────────────────────────────────────┘
HTML Source DOM Tree Layout Tree Paint Tree
───────────────────────────────────────────────────────────────────────────►
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐
│ Gumbo │ │ Element │ │ Yoga │ │ HTMLRenderElement│
│ Parser │ ───► │ Tree │ ───► │ Layout │ ───► │ Paint Tree │
└──────────┘ └──────────┘ └──────────┘ └──────────────────┘
│
▼
┌──────────┐ ┌──────────┐ ┌──────────────────────────────────────┐
│ GPU │ ◄─── │ Harrlow │ ◄─── │ Paint Modules │
│ (D3D11) │ │ Commands │ │ (Background, Border, Text, Image) │
└──────────┘ └──────────┘ └──────────────────────────────────────┘
Stage 1: HTML Parsing (Gumbo)
Location: Code/ApertureUISource/APHTML/Parser/
The parsing stage converts raw HTML text into a structured DOM tree.
Key Components
| File | Purpose |
|---|---|
HTMLParser.h/cpp | Main parser interface wrapping Gumbo |
HTMLParserOptions.h | Configuration for parsing behavior |
HTMLUtils.h/cpp | Helper utilities for HTML processing |
Flow
- Input: Raw HTML string
- Process: Gumbo parses HTML5-compliant markup
- Output:
GumboOutput*containing parsed node tree
// Example usage
aperture::html::HTMLParser parser;
aperture::html::HTMLParserOptions options;
GumboOutput* output = parser.Parse(htmlString, options);
Error Handling
- Gumbo is an error-tolerant parser (matches browser behavior)
- Malformed HTML is corrected according to HTML5 spec
- Parse errors are collected but don't halt parsing
Stage 2: DOM Tree Construction
Location: Code/ApertureUISource/APHTML/DOM/
Converts Gumbo output into our internal Element tree.
Key Components
| File | Purpose |
|---|---|
Element.h/cpp | Base DOM element class |
Document.h/cpp | Root document node |
ElementFactory.h/cpp | Creates typed elements from tags |
Node.h/cpp | Base node class (text, comment, element) |
Element Hierarchy
Node (base)
├── Element (has attributes, children, styles)
│ ├── HTMLElement
│ ├── HTMLDivElement
│ ├── HTMLSpanElement
│ ├── HTMLImageElement
│ └── ... (specialized element types)
├── TextNode (text content)
└── CommentNode (HTML comments)
Flow
- Input:
GumboOutput* - Process: Recursive traversal, creating Element nodes
- Output:
Documentwith complete Element tree
Stage 3: CSS Style Resolution
Location: Code/ApertureUISource/APHTML/CSS/
Applies CSS rules to elements and computes final style values.
Key Components
| File | Purpose |
|---|---|
StyleSheet.h/cpp | CSS parsing, cascade, and inheritance |
CSSParser.h/cpp | Tokenizes and parses CSS syntax |
ComputedValues.h/cpp | Final computed style values per element |
Selectors.h/cpp | CSS selector matching logic |
Style Resolution Order
- User-Agent Stylesheet - Browser defaults (defined in
APUIView.cpp) - Author Stylesheets -
<style>tags and linked CSS files - Inline Styles -
style=""attribute on elements - Cascade - Specificity and source order resolution
- Inheritance - Inherited properties flow to children
- Computed Values - Final values with units resolved
User-Agent Stylesheet Defaults
/* Key defaults from APUIView.cpp */
html {
display: block;
color: black;
background-color: white;
}
body {
display: block;
margin: 8px;
background-color: inherit; /* Inherits white from html */
}
div, p, h1-h6, ul, ol, li, header, footer, section, article, nav, aside, main {
display: block;
}
span, a, strong, em, b, i, u {
display: inline;
}
CSS Inheritance
Per CSS specification:
- Inherited properties:
color,font-*,text-align,line-height,visibility - Non-inherited properties:
background-*,border-*,margin,padding,width,height
The inherit keyword explicitly forces inheritance for any property:
// StyleSheet.cpp line ~352
if (value == "inherit" && parentValues) {
outValues.backgroundColor = parentValues->backgroundColor;
}
Stage 4: Layout Calculation (Yoga)
Location: Code/ApertureUISource/APHTML/Layout/
Calculates element positions and sizes using Facebook's Yoga flexbox engine.
Key Components
| File | Purpose |
|---|---|
LayoutEngine.h/cpp | Main layout orchestration |
LayoutBox.h/cpp | Per-element layout data |
YogaIntegration.h/cpp | Yoga library wrapper |
Layout Process
- Style to Yoga: Convert CSS properties to Yoga node properties
- Yoga Calculate: Run Yoga layout algorithm
- Extract Results: Copy computed positions/sizes to LayoutBox
Supported Layout Modes
- Block Layout: Vertical stacking of block elements
- Inline Layout: Horizontal flow with line wrapping
- Flexbox: Full CSS Flexbox support via Yoga
- Absolute/Fixed Positioning: Out-of-flow positioning
LayoutBox Data
struct LayoutBox {
float x, y; // Position relative to parent
float width, height; // Content box dimensions
float paddingTop, paddingRight, paddingBottom, paddingLeft;
float borderTop, borderRight, borderBottom, borderLeft;
float marginTop, marginRight, marginBottom, marginLeft;
};
Stage 5: Paint Tree Generation
Location: Code/ApertureUISource/APHTML/Render/
Creates the render tree with paint-ready elements.
Key Components
| File | Purpose |
|---|---|
HTMLRenderElement.h/cpp | Renderable element with paint data |
RenderTree.h/cpp | Paint tree construction and traversal |
RenderData.h/cpp | Per-element render state |
HTMLRenderElement
Each visible element gets an HTMLRenderElement containing:
- Reference to source
Element - Computed
LayoutBoxwith final geometry - Computed
ComputedValueswith resolved styles - Paint order (z-index, stacking context)
Paint Order
Elements are sorted for correct overlapping:
- Background and borders of root element
- Descendants in tree order (with z-index consideration)
- Positioned elements (absolute, fixed, relative with z-index)
Stage 6: Paint Modules
Location: Code/ApertureUISource/APHTML/Paint/
Specialized modules that emit draw commands for different visual features.
Paint Module Architecture
class PaintModule {
public:
virtual bool ShouldHandle(HTMLRenderElement* element) = 0;
virtual void Paint(HTMLRenderElement* element, PaintContext& ctx) = 0;
};
Available Modules
| Module | Purpose |
|---|---|
BackgroundModule | Solid colors, gradients, images |
BorderModule | Border rendering with radius support |
TextModule | Text layout and glyph rendering |
ImageModule | <img> element rendering |
OutlineModule | Focus outlines |
BackgroundModule Detail
bool BackgroundModule::ShouldHandle(HTMLRenderElement* element) {
const auto& bg = element->GetComputedValues().backgroundColor;
// Skip fully transparent backgrounds
return bg.w > 0.0f; // Alpha > 0
}
void BackgroundModule::Paint(HTMLRenderElement* element, PaintContext& ctx) {
// Emit Harrlow DrawRect command with background color
ctx.DrawRect(element->GetLayoutBox(), element->GetComputedValues().backgroundColor);
}
Stage 7: Harrlow Command Generation
Location: Code/ApertureUISource/APHarrlow/
Harrlow is the rendering abstraction layer that converts paint operations to GPU commands.
Key Components
| File | Purpose |
|---|---|
APHIRenderContext.h/cpp | Platform-agnostic render interface |
APHICommandEncoder.h/cpp | Batches and encodes draw commands |
APHIRenderPath.h/cpp | Render backend abstraction |
Command Types
| Command | Description |
|---|---|
DrawRect | Filled rectangle (backgrounds) |
DrawRoundedRect | Rectangle with border-radius |
DrawBorder | Border lines with optional radius |
DrawText | Glyph rendering |
DrawImage | Textured quad |
SetClip | Clipping region (overflow: hidden) |
PushTransform | Matrix transformation |
Batching
Commands are batched for efficiency:
- Consecutive same-type commands merged
- Texture atlasing for fonts and small images
- State change minimization
Stage 8: GPU Execution (D3D11)
Location: Code/ApertureUISource/APHarrlow/D3D11/
Final stage: execute commands on the GPU.
Key Components
| File | Purpose |
|---|---|
D3D11RenderPath.h/cpp | D3D11 backend implementation |
D3D11CommandBuffer.h/cpp | D3D11 command translation |
D3D11Resources.h/cpp | Texture, buffer management |
Render Pass
- Begin Frame: Clear render target, set viewport
- Process Commands: Translate Harrlow commands to D3D11 calls
- End Frame: Present to swap chain
Shader Pipeline
- Vertex Shader: Transform vertices, pass UVs and colors
- Pixel Shader: Sample textures, apply colors, blend
Debugging the Pipeline
Common Issues
| Symptom | Likely Cause | Check |
|---|---|---|
| Element not visible | Transparent background | Verify background-color in CSS |
| Wrong position | Layout calculation | Inspect LayoutBox values |
| Missing text | Font loading failed | Check font path and format |
| Clipped content | overflow: hidden | Check parent clipping |
| Z-order wrong | Stacking context | Verify z-index and position |
Debug Logging
Debug builds include detailed logging (guarded by NS_COMPILE_FOR_DEBUG):
// StyleSheet.cpp - CSS resolution logging
// PaintModule.cpp - Paint decision logging
Inspection Points
- After Parse: Dump DOM tree structure
- After Style: Log computed values per element
- After Layout: Print LayoutBox coordinates
- After Paint: List generated Harrlow commands
Performance Considerations
Optimization Techniques
- Dirty Rectangles: Only repaint changed regions
- Layer Caching: Cache complex subtrees to textures
- Command Batching: Minimize GPU state changes
- Font Atlasing: Pre-render glyphs to atlas textures
Profiling
Key metrics to monitor:
- Parse time per document
- Style resolution time
- Layout calculation time
- Paint time per frame
- GPU command count per frame
Related Documentation
- README_HTML.md - HTML parsing details
- README_RenderPath.md - Harrlow render backend
- README_RenderLayers.md - Layer compositing
- README_PublicCaching.md - Resource caching

