Skip to content

gogpu/gg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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 and tiny-skia, it delivers production-grade rendering with zero CGO dependencies.

Key Features

Category Capabilities
Rendering Immediate and retained mode, GPU acceleration, CPU fallback
Shapes Rectangles, circles, ellipses, arcs, bezier curves, polygons, stars
Text TrueType fonts, MSDF rendering, emoji support, bidirectional text
Compositing 29 blend modes (Porter-Duff, Advanced, HSL), layer isolation
Images 7 pixel formats, PNG/JPEG I/O, mipmaps, affine transforms
Performance Tile-based parallel rendering, LRU caching

Installation

go get github.com/gogpu/gg

Requirements: Go 1.25+


Quick Start

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")
}

Renderer Dependency Injection

gg supports pluggable renderers through the Renderer interface, enabling GPU acceleration via gogpu integration.

Software Rendering (Default)

// Default software renderer
dc := gg.NewContext(800, 600)
defer dc.Close()

GPU Rendering via Native Backend

gg includes a built-in GPU backend using gogpu/wgpu:

import (
    "github.com/gogpu/gg"
    "github.com/gogpu/gg/backend/native"
)

func main() {
    // Create GPU-accelerated context using native backend
    device := native.NewDevice()
    defer device.Destroy()

    // Draw with GPU acceleration
    device.DrawCircle(400, 300, 100)
    device.Fill()
}

For integration with gogpu windowing, see the examples/gpu/ directory.

Custom Pixmap

// 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)
         │                   │                   │
         └───────────────────┼───────────────────┘
                             │
                    Renderer Interface
                             │
            ┌────────────────┼────────────────┐
            │                                 │
       Software                             GPU
       (Default)                     (backend/native/)

Backend Structure

Backend Package Description
Native backend/native/ Pure Go WebGPU via gogpu/wgpu
Rust backend/rust/ wgpu-native FFI via go-webgpu/webgpu
Software backend/software/ CPU-based default renderer

Core APIs

Immediate Mode (Context)

Canvas-style drawing with transformation stack:

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:

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:

scene := gg.NewScene()

scene.PushLayer(gg.BlendMultiply, 0.8)
scene.Fill(style, transform, gg.Solid(gg.Red), gg.Circle(150, 200, 100))
scene.Fill(style, transform, gg.Solid(gg.Blue), gg.Circle(250, 200, 100))
scene.PopLayer()

renderer := scene.NewRenderer()
renderer.Render(target, scene)

Text Rendering

Full Unicode support with font fallback:

// 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)

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

Layer Compositing

29 blend modes with isolated layers:

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

Sophisticated compositing with masks:

dc.DrawCircle(200, 200, 100)
dc.Fill()
mask := dc.AsMask()

dc2 := gg.NewContext(400, 400)
dc2.SetMask(mask)
dc2.DrawRectangle(0, 0, 400, 400)
dc2.Fill() // Only visible through mask

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:

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 438ns iter.Seq, 0 allocs

Ecosystem

gg is part of the GoGPU ecosystem.

Project Description
gogpu/gogpu GPU framework with windowing and input
gogpu/wgpu Pure Go WebGPU implementation
gogpu/naga Shader compiler (WGSL to SPIR-V, MSL, GLSL)
gogpu/gg 2D graphics (this repo)
gogpu/ui GUI toolkit (planned)

Documentation

Articles


Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

Priority areas:

  • API feedback and testing
  • Examples and documentation
  • Performance benchmarks
  • Cross-platform testing

License

MIT License — see LICENSE for details.


gg — 2D Graphics for Go

About

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

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published