gfx/graphics.h
Graphics: the drawing API a component paints through.
#include <sonore/gfx/graphics.h>- 1type
- Guides: The native editor
On this page
Design notes
What it is
A cursor over a Bitmap carrying a colour, a transform and a clip, with a stack so a component can change any of them and put them back. Everything else -- rectangles, ellipses, lines, strokes -- goes through the one rasteriser underneath, so there is one antialiasing quality and one place a bug can be.
The state stack, and why it is not optional
A component paints its children by translating into each one's coordinates and clipping to its bounds. Without a stack, every component would have to restore what it changed, and the one that forgets corrupts the drawing of every sibling after it -- a bug that shows up in a component that is itself correct. ScopedState makes it structural: the restore happens when the scope ends, including on an early return.
Clipping is a rectangle, and only a rectangle
A framework clips to arbitrary regions. This clips to one PixelRect, because is what a component tree actually needs -- nested rectangles -- and an arbitrary clip means the rasteriser needs a coverage mask per pixel. If a rounded panel ever needs its children clipped to its corners, that is the point to add it, not before.
Types 1
The drawing context a component paints through: a cursor over a Bitmap with a brush (colour, gradient or tiled image), a transform and a clip, and a stack to put them back. See the file comment for why the stack is not optional; ScopedState is the way to use it.
Mirrors the reference's Graphics. Coordinates handed to it are in the current USER space -- a component's own, once the tree has translated into it -- and the clip is kept in device pixels. The clip only narrows: clipTo a rectangle is free, clipToPath and masks cost a byte per pixel of their area, and layers (beginLayer/endLayer) group drawing so it fades as one.
Does not own the target Bitmap, which must outlive it. A Graphics is made for one paint and thrown away; it is not shared between threads, and it draws on whatever thread paints (the message thread for an editor).