A tiny, single-header <canvas>-like 2D rasterizer for C++
C++
623
4 commits
updated Feb 29, 2024
This is a tiny, single-header C++ library for rasterizing immediate-mode 2D vector graphics, closely modeled on the basic W3C (not WHATWG) HTML5 2D canvas specification.
The priorities for this library are high-quality rendering, ease of use, and compact size. Speed is important too, but secondary to the other priorities. Notably, this library takes an opinionated approach and does not provide options for trading off quality for speed.
Despite its small size, it supports nearly everything listed in the W3C HTML5 2D canvas specification, except for hit regions and getting certain properties. The main differences lie in the surface-level API to make this easier for C++ use, while the underlying implementation is carefully based on the specification. In particular, stroke, fill, gradient, pattern, image, and font styles are specified slightly differently (avoiding strings and auxiliary classes). Nonetheless, the goal is that this library could produce a conforming HTML5 2D canvas implementation if wrapped in a thin layer of JavaScript bindings. See the accompanying C++ automated test suite and its HTML5 port for a mapping between the APIs and a comparison of this library's rendering output against browser canvas implementations.
The following complete example program writes out a TGA image file and demonstrates path building, fills, strokes, line dash patterns, line joins, line caps, linear gradients, drop shadows, and compositing operations. See the HTML5 equivalent of the example on the right (scroll the code horizontally if needed) and compare them line-by-line. Note that the minor differences in shading are due to the library's use of gamma-correct blending whereas browsers typically ignore this.
| canvas_ity | HTML5 |
|---|---|
![]() | ![]() |
|
|
std::vector instances embedded in the canvas
instance handle all dynamic memory. This reduces fragmentation and
makes it easy to change the code to reserve memory up front or even to
use statically allocated vectors.This is a single-header library. You may freely
include it in any of your source files to declare the canvas_ity namespace
and its members. However, to get the implementation, you must
#define CANVAS_ITY_IMPLEMENTATION
in exactly one C++ file before including this header.
Then, construct an instance of the canvas_ity::canvas class with the pixel
dimensions that you want and draw into it using any of the various drawing
functions. You can then use the get_image_data() function to retrieve the
currently drawn image at any time.
See each of the public member function and data member (i.e., method and field) declarations for the full API documentation. Also see the accompanying C++ automated test suite for examples of the usage of each public member, and the test suite's HTML5 port for how these map to the HTML5 canvas API.
To build the test program, either just compile the one source file directly to an executable with a C++ compiler, e.g.:
g++ -O3 -o test test.cpp
or else use the accompanying CMake file. The CMake file enables extensive warnings and also offers targets for static analysis, dynamic analysis, measuring code size, and measuring test coverage.
By default, the test harness simply runs each test once and reports the
results. However, with command line arguments, it can write PNG images of
the test results, run tests repeatedly to benchmark them, run just a subset
of the test, or write out a new table of expected image hashes. Run the
program with --help to see the usage guide for more on these.
This software is distributed as open source under the terms of the permissive ISC license.
Please do not send pull requests! They will be politely declined at this time. This library is open source, but not currently open to outside code contributions. It is also considered largely feature-complete. (Moreover, this GitHub repository is only a mirror for publishing releases from the author's local Mercurial repository.)
Bug reports, discussions, kudos, and notices of nifty projects built using this library are most welcome, however.
4 commits
C++
66.1%
HTML
31.6%
CMake
2.4%
A tiny, single-header <canvas>-like 2D rasterizer for C++
C++
623
4 commits
updated Feb 29, 2024
This is a tiny, single-header C++ library for rasterizing immediate-mode 2D vector graphics, closely modeled on the basic W3C (not WHATWG) HTML5 2D canvas specification.
The priorities for this library are high-quality rendering, ease of use, and compact size. Speed is important too, but secondary to the other priorities. Notably, this library takes an opinionated approach and does not provide options for trading off quality for speed.
Despite its small size, it supports nearly everything listed in the W3C HTML5 2D canvas specification, except for hit regions and getting certain properties. The main differences lie in the surface-level API to make this easier for C++ use, while the underlying implementation is carefully based on the specification. In particular, stroke, fill, gradient, pattern, image, and font styles are specified slightly differently (avoiding strings and auxiliary classes). Nonetheless, the goal is that this library could produce a conforming HTML5 2D canvas implementation if wrapped in a thin layer of JavaScript bindings. See the accompanying C++ automated test suite and its HTML5 port for a mapping between the APIs and a comparison of this library's rendering output against browser canvas implementations.
The following complete example program writes out a TGA image file and demonstrates path building, fills, strokes, line dash patterns, line joins, line caps, linear gradients, drop shadows, and compositing operations. See the HTML5 equivalent of the example on the right (scroll the code horizontally if needed) and compare them line-by-line. Note that the minor differences in shading are due to the library's use of gamma-correct blending whereas browsers typically ignore this.
| canvas_ity | HTML5 |
|---|---|
![]() | ![]() |
|
|
std::vector instances embedded in the canvas
instance handle all dynamic memory. This reduces fragmentation and
makes it easy to change the code to reserve memory up front or even to
use statically allocated vectors.This is a single-header library. You may freely
include it in any of your source files to declare the canvas_ity namespace
and its members. However, to get the implementation, you must
#define CANVAS_ITY_IMPLEMENTATION
in exactly one C++ file before including this header.
Then, construct an instance of the canvas_ity::canvas class with the pixel
dimensions that you want and draw into it using any of the various drawing
functions. You can then use the get_image_data() function to retrieve the
currently drawn image at any time.
See each of the public member function and data member (i.e., method and field) declarations for the full API documentation. Also see the accompanying C++ automated test suite for examples of the usage of each public member, and the test suite's HTML5 port for how these map to the HTML5 canvas API.
To build the test program, either just compile the one source file directly to an executable with a C++ compiler, e.g.:
g++ -O3 -o test test.cpp
or else use the accompanying CMake file. The CMake file enables extensive warnings and also offers targets for static analysis, dynamic analysis, measuring code size, and measuring test coverage.
By default, the test harness simply runs each test once and reports the
results. However, with command line arguments, it can write PNG images of
the test results, run tests repeatedly to benchmark them, run just a subset
of the test, or write out a new table of expected image hashes. Run the
program with --help to see the usage guide for more on these.
This software is distributed as open source under the terms of the permissive ISC license.
Please do not send pull requests! They will be politely declined at this time. This library is open source, but not currently open to outside code contributions. It is also considered largely feature-complete. (Moreover, this GitHub repository is only a mirror for publishing releases from the author's local Mercurial repository.)
Bug reports, discussions, kudos, and notices of nifty projects built using this library are most welcome, however.
4 commits
C++
66.1%
HTML
31.6%
CMake
2.4%