Aperture UI
Engineer Notes

ApertureUI Rendering Pipeline

This document describes the complete rendering pipeline from HTML source to GPU draw calls.

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

FilePurpose
HTMLParser.h/cppMain parser interface wrapping Gumbo
HTMLParserOptions.hConfiguration for parsing behavior
HTMLUtils.h/cppHelper utilities for HTML processing

Flow

  1. Input: Raw HTML string
  2. Process: Gumbo parses HTML5-compliant markup
  3. 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

FilePurpose
Element.h/cppBase DOM element class
Document.h/cppRoot document node
ElementFactory.h/cppCreates typed elements from tags
Node.h/cppBase 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

  1. Input: GumboOutput*
  2. Process: Recursive traversal, creating Element nodes
  3. Output: Document with 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

FilePurpose
StyleSheet.h/cppCSS parsing, cascade, and inheritance
CSSParser.h/cppTokenizes and parses CSS syntax
ComputedValues.h/cppFinal computed style values per element
Selectors.h/cppCSS selector matching logic

Style Resolution Order

  1. User-Agent Stylesheet - Browser defaults (defined in APUIView.cpp)
  2. Author Stylesheets - <style> tags and linked CSS files
  3. Inline Styles - style="" attribute on elements
  4. Cascade - Specificity and source order resolution
  5. Inheritance - Inherited properties flow to children
  6. 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

FilePurpose
LayoutEngine.h/cppMain layout orchestration
LayoutBox.h/cppPer-element layout data
YogaIntegration.h/cppYoga library wrapper

Layout Process

  1. Style to Yoga: Convert CSS properties to Yoga node properties
  2. Yoga Calculate: Run Yoga layout algorithm
  3. 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

FilePurpose
HTMLRenderElement.h/cppRenderable element with paint data
RenderTree.h/cppPaint tree construction and traversal
RenderData.h/cppPer-element render state

HTMLRenderElement

Each visible element gets an HTMLRenderElement containing:

  • Reference to source Element
  • Computed LayoutBox with final geometry
  • Computed ComputedValues with resolved styles
  • Paint order (z-index, stacking context)

Paint Order

Elements are sorted for correct overlapping:

  1. Background and borders of root element
  2. Descendants in tree order (with z-index consideration)
  3. 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

ModulePurpose
BackgroundModuleSolid colors, gradients, images
BorderModuleBorder rendering with radius support
TextModuleText layout and glyph rendering
ImageModule<img> element rendering
OutlineModuleFocus 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

FilePurpose
APHIRenderContext.h/cppPlatform-agnostic render interface
APHICommandEncoder.h/cppBatches and encodes draw commands
APHIRenderPath.h/cppRender backend abstraction

Command Types

CommandDescription
DrawRectFilled rectangle (backgrounds)
DrawRoundedRectRectangle with border-radius
DrawBorderBorder lines with optional radius
DrawTextGlyph rendering
DrawImageTextured quad
SetClipClipping region (overflow: hidden)
PushTransformMatrix 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

FilePurpose
D3D11RenderPath.h/cppD3D11 backend implementation
D3D11CommandBuffer.h/cppD3D11 command translation
D3D11Resources.h/cppTexture, buffer management

Render Pass

  1. Begin Frame: Clear render target, set viewport
  2. Process Commands: Translate Harrlow commands to D3D11 calls
  3. 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

SymptomLikely CauseCheck
Element not visibleTransparent backgroundVerify background-color in CSS
Wrong positionLayout calculationInspect LayoutBox values
Missing textFont loading failedCheck font path and format
Clipped contentoverflow: hiddenCheck parent clipping
Z-order wrongStacking contextVerify 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

  1. After Parse: Dump DOM tree structure
  2. After Style: Log computed values per element
  3. After Layout: Print LayoutBox coordinates
  4. After Paint: List generated Harrlow commands

Performance Considerations

Optimization Techniques

  1. Dirty Rectangles: Only repaint changed regions
  2. Layer Caching: Cache complex subtrees to textures
  3. Command Batching: Minimize GPU state changes
  4. 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

Copyright © 2026