# LibGfx: The Core Graphics Engine Behind Ladybird's Rendering Pipeline

> Discover how LibGfx powers Ladybird's rendering pipeline. This core graphics engine abstracts pixel operations via a Painter API, enabling Skia, Vulkan, or Metal rendering without code changes.

- Repository: [Ladybird/ladybird](https://github.com/LadybirdBrowser/ladybird)
- Tags: internals
- Published: 2026-03-05

---

**LibGfx is the foundational 2D graphics subsystem in Ladybird that abstracts all pixel-level operations through a backend-agnostic Painter API, enabling the browser to render web content, canvas elements, and UI surfaces using Skia, Vulkan, or Metal without changing high-level drawing logic.**

LadybirdBrowser/ladybird relies on LibGfx as the single source of truth for every visual output in the browser. This core library provides the essential data structures, drawing primitives, and rasterization abstractions that bridge the high-level rendering logic of LibWeb with hardware-accelerated backends.

## LibGfx Architecture: Bridging High-Level Rendering and Hardware Acceleration

LibGfx serves as the intermediary layer between Ladybird's web engine and the underlying graphics hardware. The library exposes a unified interface that allows the rest of the codebase to remain agnostic about whether pixels are being pushed by a CPU rasterizer or a GPU compute pipeline.

### Core Data Structures: Bitmaps and Geometry

At the heart of LibGfx are the pixel buffer abstractions defined in [`Libraries/LibGfx/Bitmap.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/Bitmap.h) and [`Libraries/LibGfx/Bitmap.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/Bitmap.cpp). The library provides three primary bitmap types:

- **`Bitmap`** – A mutable, memory-backed pixel buffer used as the primary paint target
- **`ImmutableBitmap`** – A read-optimized variant for static image data  
- **`ShareableBitmap`** – A buffer designed for cross-process texture sharing

These are complemented by essential geometry primitives including **`Point`**, **`Rect`**, **`Size`**, and **`VectorN`**, alongside color management utilities like **`Color`**, **`Palette`**, and **`SystemTheme`** defined in the Gfx namespace.

### The Painter API: Backend-Agnostic Drawing

The abstract **`Painter`** interface in [`Libraries/LibGfx/Painter.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/Painter.h) defines the complete set of 2D drawing operations available to the rest of Ladybird. This includes:

- Rectangular fills and strokes
- Path-based rendering (stroke and fill)
- Bitmap blitting and compositing
- Clipping regions and transform matrices
- Blend modes and alpha compositing

Calling `Gfx::Painter::create()` instantiates the default **Skia-based implementation** ([`PainterSkia.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/PainterSkia.cpp)), though the same interface can target **Vulkan** ([`VulkanContext.h/.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/VulkanContext.h/.cpp)) or **Metal** (`MetalContext.h/.mm`) when hardware acceleration is enabled.

## Image Decoding and Encoding Pipeline

LibGfx handles all image format I/O through decoders located in `Libraries/LibGfx/ImageFormats/`. These loaders support PNG, JPEG, WebP, GIF, TIFF, and other formats, decoding raw bytes into `Bitmap` instances that the layout engine can paint directly.

When a web page references an image, Ladybird's ImageDecoder service utilizes these LibGfx loaders to produce a `Bitmap`. Conversely, the `PNGWriter` and similar encoders allow the browser to export rendered content back to standard file formats.

## Integration Points: How LibGfx Powers Ladybird's Components

Every visual output in Ladybird passes through LibGfx, from HTML canvas elements to native UI surfaces.

### HTML5 Canvas Implementation

In [`Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp), the web engine creates a `Gfx::Painter` instance bound to the canvas's backing bitmap. This allows the Canvas 2D API methods to map directly to LibGfx drawing commands:

```cpp
auto painter = Gfx::Painter::create(image_data->bitmap());
// Canvas fill_path(), stroke_path(), etc. implemented via painter-> methods

```

### UI Front-End Rendering

Platform-specific UI layers obtain a `Painter` to composite the final frame. In [`UI/Qt/WebContentView.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Qt/WebContentView.cpp), the Qt front-end allocates a `Bitmap`, wraps it with a `Painter`, and has LibWeb paint the page layout into it before handing the pixels to Qt for display. Similarly, [`UI/Android/src/main/cpp/WebViewImplementationNative.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Android/src/main/cpp/WebViewImplementationNative.cpp) uses the same pattern for Android surfaces.

### System Theme and Color Management

The `PageClient::setup_palette()` method constructs a `Gfx::PaletteImpl` using LibGfx types, ensuring consistent color handling across the browser chrome and rendered web content.

## Practical Usage Examples

The following examples demonstrate how LibGfx operates within the Ladybird codebase.

### Creating a Bitmap, Drawing, and Exporting to PNG

This pattern from `Libraries/LibGfx/` shows the complete workflow from allocation to file output:

```cpp
// Allocate a 200×100 RGBA bitmap
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA8888, Gfx::IntSize {200, 100}).release_value();

// Obtain a Painter for the bitmap (Skia backend by default)
auto painter = Gfx::Painter::create(*bitmap);

// Fill the whole bitmap with a light‑gray background
painter->fill_rect({0, 0, 200, 100}, Gfx::Color(0xd0d0d0ff));

// Draw a red rectangle with a 5‑pixel border
painter->fill_rect({20, 20, 160, 60}, Gfx::Color::Red);
painter->stroke_rect({20, 20, 160, 60}, Gfx::Color::Black, 5);

// Flush drawing commands (Skia does this automatically on destruction)
painter.clear();

// Encode the bitmap as PNG and write to disk
Gfx::PNGWriter writer;
writer.write_bitmap_to_file("example.png", *bitmap);

```

### Rendering HTML5 Canvas Content

As implemented in [`Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp):

```cpp
// Inside CanvasRenderingContext2D.cpp
auto painter = Gfx::Painter::create(image_data->bitmap());
// ... use painter->fill_path(), stroke_path(), etc. to implement the Canvas API

```

### Compositing to a Native Qt Surface

From [`UI/Qt/WebContentView.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Qt/WebContentView.cpp), simplified:

```cpp
auto bitmap = Gfx::Bitmap::create(...);
auto painter = Gfx::Painter::create(bitmap);
// LibWeb paints the layout into the bitmap
page.paint(painter, ...);
// The bitmap is then handed to Qt for display

```

## Key Implementation Files

Understanding LibGfx requires familiarity with these specific source files in the LadybirdBrowser/ladybird repository:

- **[`Libraries/LibGfx/Bitmap.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/Bitmap.h)** & **[`Bitmap.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Bitmap.cpp)** – Core pixel buffer allocation and memory management
- **[`Libraries/LibGfx/Painter.h`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/Painter.h)** & **[`Painter.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Painter.cpp)** – Abstract drawing interface and factory methods
- **[`Libraries/LibGfx/PainterSkia.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/PainterSkia.cpp)** – Concrete Skia rasterization backend
- **[`Libraries/LibGfx/VulkanContext.h/.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibGfx/VulkanContext.h/.cpp)** – GPU acceleration via Vulkan
- **`Libraries/LibGfx/MetalContext.h/.mm`** – macOS GPU acceleration via Metal
- **`Libraries/LibGfx/ImageFormats/*.cpp`** – Format-specific codecs (PNG, JPEG, WebP, GIF, TIFF)
- **[`Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp)** – Web Canvas API integration
- **[`UI/Qt/WebContentView.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Qt/WebContentView.cpp)** – Qt front-end integration
- **[`UI/Android/src/main/cpp/WebViewImplementationNative.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Android/src/main/cpp/WebViewImplementationNative.cpp)** – Android front-end integration

## Summary

- **LibGfx** provides the foundational **`Bitmap`** data model and **`Painter`** abstraction that every visual element in Ladybird requires.
- The library's **backend-agnostic design** allows seamless switching between Skia (CPU), Vulkan, and Metal (GPU) rasterization without modifying high-level rendering code.
- All image I/O operations pass through LibGfx's format-specific decoders in `ImageFormats/`, producing standard Bitmap objects for layout and painting.
- Integration points in **LibWeb**, **Qt**, and **Android** front-ends demonstrate that LibGfx is the single source of truth for pixel-level operations across the entire browser architecture.

## Frequently Asked Questions

### What graphics backends does LibGfx support in Ladybird?

LibGfx currently supports three rasterization backends. The default implementation uses **Skia** ([`PainterSkia.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/PainterSkia.cpp)) for CPU-accelerated 2D drawing. When hardware acceleration is enabled, LibGfx can target **Vulkan** ([`VulkanContext.h/.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/VulkanContext.h/.cpp)) on supported platforms or **Metal** (`MetalContext.h/.mm`) on macOS, all through the same abstract `Painter` interface.

### How does LibGfx handle image loading for web pages?

When Ladybird encounters an image resource, the **ImageDecoder** service invokes LibGfx's format-specific loaders located in `Libraries/LibGfx/ImageFormats/`. These decoders handle PNG, JPEG, WebP, GIF, and TIFF formats, converting raw file bytes into `Bitmap` instances that the layout engine can composite onto the page using the standard `Painter` API.

### Is LibGfx used only for web content rendering?

No. While LibGfx powers the **LibWeb** rendering pipeline for HTML and Canvas, it also handles all UI chrome rendering for Ladybird's native front-ends. Both the **Qt** ([`UI/Qt/WebContentView.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Qt/WebContentView.cpp)) and **Android** ([`UI/Android/src/main/cpp/WebViewImplementationNative.cpp`](https://github.com/LadybirdBrowser/ladybird/blob/main/UI/Android/src/main/cpp/WebViewImplementationNative.cpp)) implementations use LibGfx to allocate bitmaps and obtain `Painter` instances for drawing the final composed frames displayed to users.

### Can LibGfx be used independently of the Ladybird browser?

Yes. LibGfx is a standalone library within the Ladybird project (`Libraries/LibGfx/`) that depends only on lower-level system libraries and optional graphics backends like Skia. The code examples in this article demonstrate how to create bitmaps, draw primitives, and encode images using only LibGfx APIs without requiring the full web engine stack.