Top Related Projects
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
- 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()
- 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!")
- 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:
-
Install the library:
go get -u github.com/tdewolff/canvas
-
Import the package in your Go code:
import "github.com/tdewolff/canvas"
-
Create a new canvas and context:
c := canvas.New(width, height) ctx := canvas.NewContext(c)
-
Use the context to draw shapes, text, or images, and then save the output using the appropriate renderer.
Competitor Comparisons
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.
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.
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 designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
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.
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.
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.
Recent changes
This has been reverted, the coordinate view is first performed to the coordinate, and then the view applies as a affine transformation matrix for all objects (including their coordinates). This less error prone (as evidenced by recents bugs in ParseSVG). If you previously usedContext
view and coordinate view have been altered.View
now doesn't affect the coordinate view/system. To achieve the same as before, replacectx.SetView(m)
byctx.SetView(m); ctx.SetCoordView(m)
. The change makes coordinate systems more intuitive when using in combination with views, the given coordinate reflects the coordinate where it is drawn irrespective of the view.ctx.SetCoordView(m); ctx.SetView(m)
, now only the latter is needed. Otherwise, you may need to update your coordinates when usingctx.SetView(m)
.
Features
- Path segment types: MoveTo, LineTo, QuadTo, CubeTo, ArcTo, Close
- Precise path flattening, stroking, and dashing for all segment type uing papers (see below)
- Smooth spline generation through points for open and closed paths
- Path boolean operations: AND, OR, XOR, NOT, Divide
- LaTeX to path conversion (native Go and CGO implementations available)
- Font formats support
-
- SFNT (such as TTF, OTF, WOFF, WOFF2, EOT) supporting TrueType, CFF, and CFF2 tables
- HarfBuzz for text shaping (native Go and CGO implementations available)
- FriBidi for text bidirectionality (native Go and CGO implementations available)
- Donald Knuth's line breaking algorithm for text layout
- sRGB compliance (use
SRGBColorSpace
, only available for rasterizer) - Font rendering with gamma correction of 1.43
- Rendering targets
-
- Raster images (PNG, GIF, JPEG, TIFF, BMP, WEBP)
-
-
- SVG and SVGZ
-
- PS and EPS
-
- HTMLCanvas
-
- OpenGL
- Rendering sources
-
- Canvas itself
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!
- https://github.com/aldernero/gaul (generative art utility library)
- https://github.com/aldernero/sketchy (generative art framework)
- https://github.com/carbocation/genomisc (genomics tools)
- https://github.com/davidhampgonsalves/life-dashboard (show text and emoticons in Kindle)
- https://github.com/davidhampgonsalves/quickdraw (grid of Google Quick Draw Drawings)
- https://github.com/dotaspirit/dotaspirit (draw Dota match data: https://vk.com/rsltdtk)
- https://github.com/engelsjk/go-annular (generative art of annular rings)
- https://github.com/eukarya-inc/reearth-plateauview
- https://github.com/holedaemon/gopster (Topster port)
- https://github.com/html2any/layout (flex layout)
- https://github.com/iand/genster (family trees)
- https://github.com/jansorg/marketplace-stats (reports for JetBrains marketplace)
- https://github.com/kpym/marianne (French repulic logo)
- https://github.com/mrmelon54/favicon (Favicon generator)
- https://github.com/namsor/go-qrcode (QR code encoder)
- https://github.com/octohelm/gio-compose (UI component solution for Gio)
- https://github.com/omniskop/vitrum (GUI framework)
- https://github.com/Pavel7004/GraphPlot (plot graphs)
- https://github.com/peteraba/roadmapper (tracking roadmaps: https://rdmp.app/)
- https://github.com/Preston-PLB/choRenderer (render chord charts in propresenter7)
- https://github.com/stv0g/vand (camper/van monitor and control)
- https://github.com/uncopied/chirograph (barcode security for art)
- https://github.com/uncopied/go-qrcode (QR code encoder)
- https://github.com/wisepythagoras/gis-utils (GIS utilities)
- https://supertxt.net/git/st-int.html (SuperTXT integrations)
- https://github.com/kenshaw/fv (Command-line font viewer using terminal graphics)
Articles
- Numerically stable quadratic formula
- Quadratic Bézier length
- Bézier spline through open path
- Bézier spline through closed path
- Point inclusion in polygon test
My own
Papers
- M. Walter, A. Fournier, Approximate Arc Length Parametrization, Anais do IX SIBGRAPHI (1996), p. 143--150
- T.F. Hain, et al., Fast, precise flattening of cubic Bézier path and offset curves, Computers & Graphics 29 (2005). p. 656--666
- M. Goldapp, Approximation of circular arcs by cubic polynomials, Computer Aided Geometric Design 8 (1991), p. 227--238
- L. Maisonobe, Drawing and elliptical arc using polylines, quadratic or cubic Bézier curves (2003)
- S.H. Kim and Y.J. Ahn, An approximation of circular arcs by quartic Bezier curves, Computer-Aided Design 39 (2007, p. 490--493)
- D.E. Knuth and M.F. Plass, Breaking Paragraphs into Lines, Software: Practive and Experience 11 (1981), p. 1119--1184
- L. Subramaniam, Partition of a non-simple polygon into simple pologons, 2003
License
Released under the MIT license.
Be aware that Fribidi uses the LGPL license.
Top Related Projects
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot