Convert Figma logo to code with AI

tdewolff logocanvas

Cairo in Go: vector to raster, SVG, PDF, EPS, WASM, OpenGL, Gio, etc.

1,565
103
1,565
20

Top Related Projects

4,525

Go Graphics - 2D rendering in Go with a simple API.

1,111

2D rendering for different output (raster, pdf, svg)

2,176

Go Language Library for SVG generation

Quick Overview

tdewolff/canvas is a Go library for vector graphics rendering. It provides a powerful and flexible API for creating complex graphics, supporting various output formats including SVG, PDF, and raster images. The library aims to offer high performance and extensive features for 2D drawing tasks.

Pros

  • High-performance rendering with optimized algorithms
  • Support for multiple output formats (SVG, PDF, PNG, etc.)
  • Extensive set of drawing primitives and operations
  • Clean and intuitive API design

Cons

  • Limited documentation and examples compared to some other graphics libraries
  • Steeper learning curve for beginners due to its comprehensive feature set
  • Lack of built-in support for some advanced graphical effects (e.g., complex gradients)

Code Examples

  1. Creating a simple shape:
import "github.com/tdewolff/canvas"

c := canvas.New(100, 100)
ctx := canvas.NewContext(c)
ctx.SetFillColor(canvas.Black)
ctx.DrawCircle(50, 50, 30)
ctx.Fill()
  1. Drawing text:
import "github.com/tdewolff/canvas"

c := canvas.New(200, 100)
ctx := canvas.NewContext(c)
face := canvas.NewFontFamily("sans-serif")
face.LoadSystemFont("Arial")
ctx.SetFont(face, 24)
ctx.DrawText(10, 50, "Hello, Canvas!")
  1. Saving to different formats:
import (
    "github.com/tdewolff/canvas"
    "github.com/tdewolff/canvas/renderers"
)

c := canvas.New(100, 100)
// ... drawing operations ...

renderers.Write("output.svg", c)
renderers.Write("output.pdf", c)
renderers.Write("output.png", c)

Getting Started

To use tdewolff/canvas in your Go project:

  1. Install the library:

    go get -u github.com/tdewolff/canvas
    
  2. Import the package in your Go code:

    import "github.com/tdewolff/canvas"
    
  3. Create a new canvas and context:

    c := canvas.New(width, height)
    ctx := canvas.NewContext(c)
    
  4. Use the context to draw shapes, text, or images, and then save the output using the appropriate renderer.

Competitor Comparisons

4,525

Go Graphics - 2D rendering in Go with a simple API.

Pros of gg

  • Simpler API with fewer concepts to learn
  • Better suited for quick, straightforward drawing tasks
  • More extensive documentation and examples

Cons of gg

  • Less feature-rich compared to canvas
  • Limited support for advanced text rendering and font handling
  • Fewer options for fine-grained control over drawing operations

Code Comparison

gg:

dc := gg.NewContext(1000, 1000)
dc.DrawCircle(500, 500, 400)
dc.SetRGB(0, 0, 0)
dc.Fill()
dc.SavePNG("output.png")

canvas:

c := canvas.New(1000, 1000)
ctx := canvas.NewContext(c)
ctx.SetFillColor(color.Black)
ctx.DrawCircle(500, 500, 400)
ctx.FillStroke()
c.SavePNG("output.png")

Both libraries provide similar functionality for basic drawing operations, but canvas offers more advanced features and greater flexibility at the cost of a slightly more complex API. gg is ideal for simpler projects or quick prototypes, while canvas is better suited for more complex graphics applications requiring fine-tuned control and advanced rendering capabilities.

1,111

2D rendering for different output (raster, pdf, svg)

Pros of draw2d

  • More mature project with longer development history
  • Wider range of drawing primitives and features
  • Better documentation and examples

Cons of draw2d

  • Slower performance for complex drawings
  • Less active development in recent years
  • Larger codebase and dependencies

Code Comparison

draw2d:

gc := draw2d.NewGraphicContext(dest)
gc.SetStrokeColor(color.Black)
gc.SetLineWidth(1)
gc.MoveTo(10, 10)
gc.LineTo(100, 100)

canvas:

ctx := canvas.NewContext(dest)
ctx.SetStrokeColor(color.Black)
ctx.SetLineWidth(1)
ctx.MoveTo(10, 10)
ctx.LineTo(100, 100)

Summary

Both draw2d and canvas are Go libraries for 2D graphics rendering. draw2d offers a more comprehensive set of features and has been around longer, making it a solid choice for complex drawing tasks. However, canvas provides better performance and is actively maintained, making it suitable for projects requiring efficiency and ongoing support. The API usage is similar between the two, allowing for relatively easy migration if needed.

2,176

Go Language Library for SVG generation

Pros of svgo

  • Simpler API, easier to get started for basic SVG creation
  • Lightweight and focused specifically on SVG generation
  • Includes built-in support for common SVG elements and attributes

Cons of svgo

  • Less feature-rich compared to canvas's broader graphics capabilities
  • Limited to SVG output, while canvas supports multiple output formats
  • Lacks advanced text rendering and font handling features

Code Comparison

svgo:

canvas := svg.New(os.Stdout)
canvas.Start(500, 500)
canvas.Circle(250, 250, 125, "fill:none;stroke:black")
canvas.Text(250, 250, "Hello, SVG!", "text-anchor:middle")
canvas.End()

canvas:

c := canvas.New(500, 500)
ctx := canvas.NewContext(c)
ctx.SetStrokeColor(color.Black)
ctx.DrawCircle(250, 250, 125)
ctx.SetFillColor(color.Black)
ctx.DrawText("Hello, Canvas!", 250, 250)

Both libraries offer straightforward ways to create basic shapes and text, but canvas provides more fine-grained control over drawing operations and styles. svgo's API is more concise for simple SVG generation, while canvas offers a more comprehensive set of drawing functions and greater flexibility in output formats.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Canvas

API reference User guide Go Report Card Coverage Status

API documentation

User guide

Live HTMLCanvas demo

Canvas is a common vector drawing target that can output SVG, PDF, EPS, raster images (PNG, JPG, GIF, ...), HTML Canvas through WASM, OpenGL, and Gio. It has a wide range of path manipulation functionality such as flattening, stroking and dashing implemented. Additionally, it has a text formatter and embeds and subsets fonts (TTF, OTF, WOFF, WOFF2, or EOT) or converts them to outlines. It can be considered a Cairo or node-canvas alternative in Go. See the example below in Figure 1 for an overview of the functionality.

Preview

Figure 1: top-left you can see text being fitted into a box, justified using Donald Knuth's linea breaking algorithm to stretch the spaces between words to fill the whole width. You can observe a variety of styles and text decorations applied, as well as support for LTR/RTL mixing and complex scripts. In the bottom-right the word "stroke" is being stroked and drawn as a path. Top-right we see a LaTeX formula that has been converted to a path. Left of that we see an ellipse showcasing precise dashing, notably the length of e.g. the short dash is equal wherever it is on the curve. Note that the dashes themselves are elliptical arcs as well (thus exactly precise even if magnified greatly). To the right we see a closed polygon of four points being smoothed by cubic Béziers that are smooth along the whole path, and the blue line on the left shows a smoothed open path. On the bottom you can see a rotated rasterized image. The bottom-left shows path boolean operations. The result is equivalent for all renderers (PNG, PDF, SVG, etc.).

Sponsors

I'm actively looking for support in the form of donations or sponsorships to keep developing this library and highly appreciate any gesture. Please see the Sponsors button in GitHub for ways to contribute, or contact me directly.

State

Whether this library is ready for production environments is up to your own judgment. In general, this library is written thoughtfully and complete, but the scope of this work is so big and the implementation can be quite complex that inevitably it must have a great amount of bugs. Effort was put in writing unit and fuzz tests so that I suspect only special use-cases will stumble into bugs, but coverage is still lacking. As time permits, work is done to flesh-out functionality, find bugs, and optimize code. Optimization could be in execution time / reducing code complexity, reducing memory footprint, or reducing the length of paths from operation.

Execution performance is actually really good, especially the rasterizer is highly optimized with ASM. See for example a comparison of an extreme case in https://github.com/tdewolff/canvas/issues/280#issuecomment-1995990038, where this library is at least twice as fast as existing solutions, and can handle bigger images than the likes of Inkscape and Cairo.

The path intersection code and path boolean operation code is quite complete and fast, and more importantly has a time complexity of O(n log n). It is numerically stable and does not suffer from floating-point precision errors.

Please issue bug reports or feature requests to help this library mature! All help is appreciated. Also see Wiki - Planning for an inexhaustive list of ideas and TODOs.

Features

General

  • Path segment types: MoveTo, LineTo, QuadTo, CubeTo, ArcTo, Close (see Paths)
  • Precise path flattening, stroking, and dashing for all segment types (see papers below)
  • Smooth spline generation through points for open and closed paths
  • LaTeX to path conversion (native Go and CGO implementations available)
  • sRGB compliance (use SRGBColorSpace, only available for rasterizer)

Rendering targets

Paths can be exported as or rendered to:

  • Raster images (PNG, GIF, JPEG, TIFF, BMP, WEBP, AVIF, ...)
  • PDF
  • SVG and SVGZ
  • PS and EPS
  • HTMLCanvas
  • OpenGL
  • Gio
  • Fyne

Additionally, it has bindings to be used as renderer for:

See Renderers for more information.

Stable path boolean operations

Numerically stable (!) path boolean operations, supporting AND, OR, XOR, NOT, and DIV operations in O((n+k) log n), with n the number of segments and k the number of intersections. This is very fast and allows handling huge paths. It uses 64-bit floating-point precision for highly accurate computation and employs an additional strategy to ensure numerical stability. In particular:

  • Allows paths, subject or clipping, with any number of (overlapping) contours.
  • Allows contours with any orientation, clockwise or anticlockwise.
  • Contours may be concave or of any shape.
  • Contours may self-intersect any number of times.
  • Segments may overlap any number of times by any contour.
  • Points may be crossed any number of times.
  • Segments may be vertical.
  • Clipping path is implicitly closed (it makes no sense if it's an open path).
  • Subject path may be either open or closed.
  • Paths are currently flattened, but supporting Bézier or elliptical arcs is a WIP (not anytime soon).

Numerical stability refers to cases where two segments are extremely close where floating-point precision can alter the computation whether they intersect or not. This is a very difficult problem to solve, and many libraries cannot handle this properly (nor can they handle 'degenerate' paths in general, see the list of properties above). Note that fixed-point precision suffers from the same problem. This library builds on papers from Bentley & Ottmann, de Berg, Martínez, Hobby, and Hershberger (see bibliography below).

Correctness and performance has been tested by drawing all land masses and islands from OpenStreetMap at various scales, which is a huge input (1 GB of compressed Shape files) with extremely degenerate data (many overlapping segments, overlapping points, vertical segments, self-intersections, extremely close intersections, different contour orientations, and so on).

TODO: add benchmark with other libraries

See Boolean operations for more information.

Advanced text rendering

High-quality (comparable to TeX) text rendering and line breaking. It uses HarfBuzz for text shaping (native Go and CGO implementations available) and FriBidi for text bidirectionality (native Go and CGO implementations available), and uses Donald Knuth's line breaking algorithm for text layout. This enables the following features:

  • Align text left, center, right and justified, including indentation.
  • Align text top, middle, bottom in a text box, including setting line spacing.
  • Handle any script, eg. latin, cyrillic, devanagari, arabic, hebrew, han, etc.
  • Handle left-to-right, right-to-left, or top-to-bottom/bottom-to-top writing systems.
  • Mix scripts and fonts in a single line, eg. combine latin and arabic, or bold and regular styles.

Additionally, many font formats are supported (such as TTF, OTF, WOFF, WOFF2, EOT) and rendering can apply a gamma correction of 1.43 for better results. See Fonts & Text for more information.

Examples

Amsterdam city centre: the centre of Amsterdam is drawn from data loaded from the Open Street Map API.

Mauna-Loa CO2 concentration: using data from the Mauna-Loa observatory, carbon dioxide concentrations over time are drawn

Text document: an example of a text document using the PDF backend.

OpenGL: an example using the OpenGL backend.

Gio: an example using the Gio backend.

Fyne: an example using the Fyne backend.

TeX/PGF: an example showing the usage of the PGF (TikZ) LaTeX package as renderer in order to generated a PDF using LaTeX.

go-chart: an example using the go-chart library, plotting a financial graph.

gonum/plot: an example using the gonum/plot library.

HTMLCanvas: an example using the HTMLCanvas backend, see the live demo.

Users

This is a non-exhaustive list of library users I've come across. PRs are welcome to extend the list!

Articles

My own

Papers

License

Released under the MIT license.

Be aware that Fribidi uses the LGPL license.