An open API service indexing awesome lists of open source software.

https://github.com/gogpu/gg

Enterprise-grade 2D graphics library for Go. Pure Go, zero CGO. Part of GoGPU ecosystem.
https://github.com/gogpu/gg

2d-graphics canvas creative-coding drawing enterprise go golang gpu graphics pure-go rendering

Last synced: 5 days ago
JSON representation

Enterprise-grade 2D graphics library for Go. Pure Go, zero CGO. Part of GoGPU ecosystem.

Awesome Lists containing this project

README

          

gg


2D Graphics Library for Go

Pure Go | GPU Accelerated | Production Ready


CI
codecov
Go Reference
Go Report Card
License
Latest Release
Go Version


Part of the GoGPU ecosystem

---

## Overview

**gg** is a 2D graphics library for Go designed to power IDEs, browsers, and graphics-intensive applications. Built with modern patterns inspired by [vello](https://github.com/linebender/vello) and [tiny-skia](https://github.com/RazrFalcon/tiny-skia), it delivers production-grade rendering with zero CGO dependencies.



Seven-Tier GPU Rendering: SDF shapes, convex polygons, stencil+cover paths, MSDF text, Vello compute pipeline, glyph mask cache



Six-tier GPU rendering: SDF shapes, convex polygons, stencil+cover paths, MSDF text, Vello compute, and glyph mask cache.
Pure Go, Vulkan/DX12/GLES backends, zero CGO. (source)

### Key Features

| Category | Capabilities |
|----------|--------------|
| **Rendering** | Immediate and retained mode, seven-tier GPU acceleration (SDF, Convex, Stencil+Cover, Textured Quad, MSDF Text, Compute, Glyph Mask), per-context GPU isolation (Skia GrContext pattern), scene GPU auto-select, Skia AAA pixel-perfect rasterizer, CPU fallback |
| **Shapes** | Rectangles, circles, ellipses, arcs, bezier curves, polygons, stars |
| **Text** | TrueType fonts, MSDF + glyph mask dual-strategy rendering, TextMode auto-selection, DPI-aware HiDPI text, ClearType LCD subpixel rendering, font hinting (auto-hinter), transform-aware CPU text (scale/rotate/shear), glyph outline caching, emoji support, bidirectional text, HarfBuzz shaping |
| **Compositing** | 29 blend modes (Porter-Duff, Advanced, HSL), layer isolation, alpha masks (per-shape, per-layer, luminance, post-process) |
| **Images** | 7 pixel formats, PNG/JPEG/WebP I/O, mipmaps, affine transforms |
| **SVG** | Full SVG renderer (`gg/svg`): parse + render SVG XML with color override for theming, SVG path data parser (`ParseSVGPath`), transform-aware `FillPath`/`StrokePath` |
| **Vector Export** | Recording system with PDF and SVG backends |
| **Rasterizer** | Smart per-path algorithm selection (scanline, 4×4 tiles, 16×16 tiles, SDF, compute), text-aware area-based routing |
| **Performance** | Tile-based parallel rendering, LRU caching |

---

## Installation

```bash
go get github.com/gogpu/gg
```

**Requirements:** Go 1.25+

---

## Quick Start

```go
package main

import (
"github.com/gogpu/gg"
"github.com/gogpu/gg/text"
)

func main() {
// Create drawing context
dc := gg.NewContext(512, 512)
defer dc.Close()

dc.ClearWithColor(gg.White)

// Draw shapes
dc.SetHexColor("#3498db")
dc.DrawCircle(256, 256, 100)
dc.Fill()

// Render text
source, _ := text.NewFontSourceFromFile("arial.ttf")
defer source.Close()

dc.SetFont(source.Face(32))
dc.SetColor(gg.Black)
dc.DrawString("Hello, GoGPU!", 180, 260)

dc.SavePNG("output.png")
}
```

---

## Rendering

### Software Rendering (Default)

The CPU rasterizer automatically selects the optimal algorithm per-path:

| Algorithm | Tiles | Best For |
|-----------|-------|----------|
| **AnalyticFiller** (Skia AAA) | — | Simple paths, small shapes (< 32px). Pixel-perfect with Skia Chrome/Android. |
| **AnalyticFiller Convex** | — | Convex shapes (rect, circle, triangle). 1.6x faster, kSnapDigit X snapping. |
| **SparseStrips** | 4×4 | Complex paths, CPU/SIMD workloads |
| **TileCompute** | 16×16 | Extreme complexity (10K+ segments) |

```go
dc := gg.NewContext(800, 600)
defer dc.Close()

// Auto-selection (default) — optimal algorithm per-path
dc.DrawCircle(400, 300, 100)
dc.Fill()

// Force specific algorithm for benchmarking
dc.SetRasterizerMode(gg.RasterizerSparseStrips)
```

### GPU Acceleration (Optional)

gg supports optional GPU acceleration through the `GPUAccelerator` interface with
a seven-tier rendering pipeline:

| Tier | Method | Best For |
|------|--------|----------|
| **1. SDF** | Signed Distance Field | Circles, ellipses, rectangles, rounded rects |
| **2a. Convex** | Direct vertex emission | Convex polygons, single draw call |
| **2b. Stencil+Cover** | Fan tessellation + stencil buffer | Arbitrary complex paths, EvenOdd/NonZero fill |
| **3. Textured Quad** | GPU image sampling | DrawImage, DrawGPUTexture (zero-readback compositing) |
| **4. MSDF Text** | Multi-channel Signed Distance Field | Dynamic/animated text, resolution-independent |
| **5. Compute** | 9-stage Vello compute pipeline | Full scenes with many paths (GPU parallel rasterization) |
| **6. Glyph Mask** | CPU-rasterized R8 alpha atlas | Static UI text ≤48px, pixel-perfect quality |

Tiers 1–4, 6 use a render-pass pipeline; Tier 5 uses compute shaders dispatched
via `PipelineMode` (Auto/RenderPass/Compute). Text auto-selection routes horizontal
text ≤48px to Glyph Mask (Skia/Chrome pattern), else MSDF.

When no GPU is registered, rendering uses the high-quality CPU rasterizer (default).

```go
import (
"github.com/gogpu/gg"
_ "github.com/gogpu/gg/gpu" // opt-in GPU acceleration
)

func main() {
// GPU automatically used when available, falls back to CPU
dc := gg.NewContext(800, 600)
defer dc.Close()

dc.DrawCircle(400, 300, 100)
dc.Fill() // tries GPU first, falls back to CPU transparently
}
```

For zero-copy rendering directly to a GPU surface (e.g., in a gogpu window),
use [`ggcanvas.Canvas.RenderDirect`](integration/ggcanvas/) — see the
[gogpu integration example](examples/gogpu_integration/). The example uses
event-driven rendering with `AnimationToken` for power-efficient VSync (0% CPU when idle).

### Custom Pixmap

```go
// Use existing pixmap
pm := gg.NewPixmap(800, 600)
dc := gg.NewContext(800, 600, gg.WithPixmap(pm))
```

---

## Architecture

```
gg (Public API)

┌───────────────────┼───────────────────┐
│ │ │
Immediate Mode Retained Mode Resources
(Context API) (Scene Graph) (Images, Fonts)
│ │ │
└───────────────────┼───────────────────┘

┌──────────────┴──────────────┐
│ │
CPU Raster GPUAccelerator
(always available) (opt-in via gg/gpu)
│ │
internal/raster ┌──────────┼──────────┐
│ │ │
Render Pass MSDF Text Compute
(Tiers 1-4,6) (Tier 4) (Tier 5)
```

### Rendering Structure

| Component | Location | Description |
|-----------|----------|-------------|
| **CPU Raster** | `internal/raster/` | Skia AAA analytic anti-aliasing (pixel-perfect port of Chrome/Android rasterizer). General + convex fast path. |
| **Tile Rasterizers** | `internal/gpu/` (4×4), `internal/gpu/tilecompute/` (16×16) | SparseStrips + TileCompute, both ported from Vello |
| **GPU Accelerator** | `internal/gpu` | Seven-tier GPU pipeline (SDF, Convex, Stencil+Cover, Textured Quad, MSDF Text, Compute, Glyph Mask) |
| **GPU + Tiles** | `gpu/` | Opt-in via `import _ "github.com/gogpu/gg/gpu"` (GPU + tile rasterizers) |
| **Tiles Only** | `raster/` | Opt-in via `import _ "github.com/gogpu/gg/raster"` (CPU-only tiles) |
| **Software** | Root `gg` package | Default CPU renderer with smart algorithm selection |

---

## Core APIs

### Immediate Mode (Context)

Canvas-style drawing with transformation stack:

```go
dc := gg.NewContext(800, 600)
defer dc.Close()

// Transforms
dc.Push()
dc.Translate(400, 300)
dc.Rotate(math.Pi / 4)
dc.DrawRectangle(-50, -50, 100, 100)
dc.SetRGB(0.2, 0.5, 0.8)
dc.Fill()
dc.Pop()

// Bezier paths
dc.MoveTo(100, 100)
dc.QuadraticTo(200, 50, 300, 100)
dc.CubicTo(350, 150, 350, 250, 300, 300)
dc.SetLineWidth(3)
dc.Stroke()
```

### Fluent Path Builder

Type-safe path construction with method chaining:

```go
path := gg.BuildPath().
MoveTo(100, 100).
LineTo(200, 100).
QuadTo(250, 150, 200, 200).
CubicTo(150, 250, 100, 250, 50, 200).
Close().
Circle(300, 150, 50).
Star(400, 150, 40, 20, 5).
Build()

dc.SetPath(path)
dc.Fill()
```

### Retained Mode (Scene Graph)

GPU-optimized scene graph for complex applications:

```go
import "github.com/gogpu/gg/render"

s := render.NewScene()

s.SetFillColor(color.RGBA{R: 255, A: 200})
s.Circle(150, 200, 100)
s.Fill()

s.SetFillColor(color.RGBA{B: 255, A: 200})
s.Circle(250, 200, 100)
s.Fill()

renderer := render.NewSoftwareRenderer()
target := render.NewPixmapTarget(800, 600)
renderer.Render(target, s)
```

### Text Rendering

Full Unicode support with font fallback and optional HarfBuzz-level shaping:

```go
// Font composition
mainFont, _ := text.NewFontSourceFromFile("Roboto.ttf")
emojiFont, _ := text.NewFontSourceFromFile("NotoEmoji.ttf")
defer mainFont.Close()
defer emojiFont.Close()

multiFace, _ := text.NewMultiFace(
mainFont.Face(24),
text.NewFilteredFace(emojiFont.Face(24), text.RangeEmoji),
)

dc.SetFont(multiFace)
dc.DrawString("Hello World! Nice day!", 50, 100)

// Optional: enable HarfBuzz shaping for ligatures, kerning, complex scripts
shaper := text.NewGoTextShaper()
text.SetShaper(shaper)
defer text.SetShaper(nil)

// Text layout with wrapping
opts := text.LayoutOptions{
MaxWidth: 400,
WrapMode: text.WrapWordChar,
Alignment: text.AlignCenter,
}
layout := text.LayoutText("Long text...", face, opts)
```

#### Transform-Aware Text

Text rendering respects the full transformation matrix (scale, rotation, shear):

```go
dc.SetFont(source.Face(24))
dc.SetRGB(0, 0, 0)

// Scaled text — rendered at device resolution (no pixelation)
dc.Push()
dc.Scale(2, 2)
dc.DrawString("2x Scale", 50, 50)
dc.Pop()

// Rotated text — glyph outlines converted to vector paths
dc.Push()
dc.Translate(200, 200)
dc.Rotate(math.Pi / 6) // 30 degrees
dc.DrawString("Rotated", 0, 0)
dc.Pop()
```

Text rendering strategy is selectable per-Context via `SetTextMode()`:

| Mode | Strategy | Best for |
|------|----------|----------|
| `TextModeAuto` | Auto-select (default) | General use |
| `TextModeMSDF` | GPU MSDF atlas | Games, animations, real-time scaling |
| `TextModeVector` | Glyph outlines as paths | UI labels, quality-critical text |
| `TextModeBitmap` | CPU bitmap rasterization | PNG/PDF export, static text |

The CPU text pipeline uses a three-tier strategy (modeled after Skia/Cairo/Vello):
translation-only → bitmap, uniform scale ≤256px → bitmap at device size,
everything else → glyph outlines as vector paths with cached outlines via `GlyphCache`.

### Color Emoji

Full color emoji support with CBDT/CBLC (bitmap) and COLR/CPAL (vector) formats:


COLR Color Palette


175 colors from Segoe UI Emoji COLR/CPAL palette

```go
// Extract color emoji from font
extractor, _ := emoji.NewCBDTExtractor(cbdtData, cblcData)
glyph, _ := extractor.GetGlyph(glyphID, ppem)
img, _ := png.Decode(bytes.NewReader(glyph.Data))

// Parse COLR/CPAL vector layers
parser, _ := emoji.NewCOLRParser(colrData, cpalData)
glyph, _ := parser.GetGlyph(glyphID, paletteIndex)
for _, layer := range glyph.Layers {
// Render each layer with layer.Color
}
```

See [`examples/color_emoji/`](examples/color_emoji/) for a complete example.

### Layer Compositing

29 blend modes with isolated layers:

```go
dc.PushLayer(gg.BlendOverlay, 0.7)

dc.SetRGB(1, 0, 0)
dc.DrawCircle(150, 200, 100)
dc.Fill()

dc.SetRGB(0, 0, 1)
dc.DrawCircle(250, 200, 100)
dc.Fill()

dc.PopLayer()
```

### Alpha Masks

Per-shape masking — each draw individually masked:

```go
// Create a circular mask
dc.DrawCircle(200, 200, 100)
mask := dc.AsMask() // capture path as mask (before Fill!)
dc.ClearPath()

// Apply mask: only the circle area is visible
dc.SetMask(mask)
dc.SetRGB(0, 0, 1)
dc.DrawRectangle(0, 0, 400, 400)
dc.Fill() // blue only inside the circle
```

Per-layer masking — mask an entire group of draws:

```go
mask := gg.NewMask(400, 400)
// ... fill mask with desired shape ...

dc.PushMaskLayer(mask)
dc.DrawCircle(100, 100, 50)
dc.Fill()
dc.DrawRectangle(200, 200, 80, 80)
dc.Fill()
dc.PopLayer() // entire layer masked, then composited
```

### Recording & Vector Export

Record drawing operations and export to PDF or SVG:

```go
import (
"github.com/gogpu/gg/recording"
_ "github.com/gogpu/gg-pdf" // Register PDF backend
_ "github.com/gogpu/gg-svg" // Register SVG backend
)

// Create recorder
rec := recording.NewRecorder(800, 600)

// Draw using familiar API
rec.SetColor(gg.Blue)
rec.DrawCircle(400, 300, 100)
rec.Fill()

// Finish recording and play back to a raster backend
r := rec.FinishRecording()
backend := raster.NewBackend()
r.Playback(backend)
backend.SaveToFile("output.png")
```

---

## Why "Context" Instead of "Canvas"?

The drawing type is named `Context` following industry conventions:

| Library | Drawing Type |
|---------|-------------|
| HTML5 Canvas | `CanvasRenderingContext2D` |
| Cairo | `cairo_t` (context) |
| Apple CoreGraphics | `CGContext` |
| piet (Rust) | `RenderContext` |

In HTML5, Canvas is the element while **Context** performs drawing (`canvas.getContext("2d")`). The `Context` contains drawing state and provides the drawing API.

**Convention:** `dc` for drawing context, `ctx` for `context.Context`:

```go
dc := gg.NewContext(512, 512) // dc = drawing context
```

---

## Performance

| Operation | Time | Notes |
|-----------|------|-------|
| sRGB to Linear | 0.16ns | 260x faster than math.Pow |
| LayerCache.Get | 90ns | Thread-safe LRU |
| DirtyRegion.Mark | 10.9ns | Lock-free atomic |
| MSDF lookup | <10ns | Zero-allocation |
| Path iteration | 23ns | SOA Iterate(), 0 allocs |
| FillRect | 77µs | **0 allocs** (zero-alloc pipeline) |
| FillCircle r100 | 2ms | **0 allocs** (zero-alloc pipeline) |
| Gradient ColorAt | 33ns | 0 allocs (pre-sorted stops) |

---

## Ecosystem

**gg** is part of the [GoGPU](https://github.com/gogpu) ecosystem.

| Project | Description |
|---------|-------------|
| [gogpu/gogpu](https://github.com/gogpu/gogpu) | GPU framework with windowing and input |
| [gogpu/wgpu](https://github.com/gogpu/wgpu) | Pure Go WebGPU implementation |
| [gogpu/naga](https://github.com/gogpu/naga) | Shader compiler (WGSL to SPIR-V, MSL, GLSL) |
| **gogpu/gg** | **2D graphics (this repo)** |
| [gogpu/gg-pdf](https://github.com/gogpu/gg-pdf) | PDF export backend for recording |
| [gogpu/gg-svg](https://github.com/gogpu/gg-svg) | SVG export backend for recording |
| [gogpu/ui](https://github.com/gogpu/ui) | GUI toolkit (planned) |

---

## Documentation

- **[ARCHITECTURE.md](docs/ARCHITECTURE.md)** — System architecture
- **[ROADMAP.md](ROADMAP.md)** — Development milestones
- **[CHANGELOG.md](CHANGELOG.md)** — Release notes
- **[CONTRIBUTING.md](CONTRIBUTING.md)** — Contribution guidelines
- **[pkg.go.dev](https://pkg.go.dev/github.com/gogpu/gg)** — API reference

### Articles

- [GoGPU: From Idea to 100K Lines in Two Weeks](https://dev.to/kolkov/gogpu-from-idea-to-100k-lines-in-two-weeks-building-gos-gpu-ecosystem-3b2)
- [Pure Go 2D Graphics Library with GPU Acceleration](https://dev.to/kolkov/pure-go-2d-graphics-library-with-gpu-acceleration-introducing-gogpugg-538h)
- [GoGPU Announcement](https://dev.to/kolkov/gogpu-a-pure-go-graphics-library-for-gpu-programming-2j5d)

---

## Contributing

Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

**Priority areas:**
- API feedback and testing
- Examples and documentation
- Performance benchmarks
- Cross-platform testing

---

## License

MIT License — see [LICENSE](LICENSE) for details.

---


gg — 2D Graphics for Go