How GIMP Converts Vector Anchors to Screen Pixels
When rendering vector paths, GIMP translates floating-point anchor and control coordinates from internal canvas space into discrete screen-space pixels using an affine transformation pipeline combined with curve evaluation via the Cairo graphics library. The process begins by retrieving the mathematical coordinates of the path strokes, applying the active viewport's view transformation matrix to account for canvas zoom, panning, and rotation, and finally flattening the resulting cubic Bézier curves into rasterized, anti-aliased line segments directly mapped to the user's display buffer.
1. Vector Coordinate Storage in Image Space
Within GIMP’s architecture, paths are managed by data structures such
as GimpVectors and GimpBezierStroke. Each path
component consists of anchor points flanked by directional handles
(control points). These points are stored as floating-point values in
image coordinate space, independent of display scaling, window
dimensions, or display DPI. Storing coordinates as double-precision
floating-point numbers ensures that vector data retains geometric
precision regardless of image dimensions or subsequent user edits.
2. The Viewport Transformation Matrix
To map coordinates from image space to screen space, GIMP utilizes
its display shell system (GimpDisplayShell). The display
shell constructs a 2D affine transformation matrix that captures all
current display parameters:
- Scaling: Adjusts for the current zoom factor (e.g., 50%, 100%, 800%).
- Translation: Accounts for canvas panning offsets within the application window.
- Rotation and Flipping: Accommodates arbitrary canvas rotation angles or horizontal/vertical canvas flips.
Mathematically, any anchor coordinate \((x_{\text{image}}, y_{\text{image}})\) is converted to an unrounded screen coordinate \((x_{\text{screen}}, y_{\text{screen}})\) through affine matrix multiplication:
\[\begin{bmatrix} x_{\text{screen}} \\ y_{\text{screen}} \\ 1 \end{bmatrix} = \begin{bmatrix} a & c & t_x \\ b & d & t_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_{\text{image}} \\ y_{\text{image}} \\ 1 \end{bmatrix}\]
Here, \(a\) and \(d\) represent scaling, \(b\) and \(c\) represent shearing/rotation components, and \(t_x\) and \(t_y\) represent viewport panning translations.
3. Curve Evaluation and Flattening
Once anchor points and their corresponding control handles are transformed into the display coordinate frame, GIMP utilizes the Cairo 2D graphics library to process the curves. A segment between two anchors is defined as a cubic Bézier curve:
\[B(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t) t^2 P_2 + t^3 P_3, \quad t \in [0, 1]\]
Where \(P_0\) and \(P_3\) are transformed anchor points, and \(P_1\) and \(P_2\) are transformed control handles.
Because computer screens cannot display pure mathematical curves directly, Cairo performs curve flattening (adaptive subdivision). The algorithm recursively calculates midpoints using de Casteljau's algorithm until the deviation between the true curve and a straight line approximation falls below a specific flatness tolerance—typically a fraction of a screen pixel. This converts the smooth curve into a contiguous sequence of tiny linear segments.
4. Screen-Space Rasterization and Anti-Aliasing
The final phase converts the flattened linear segments into pixels on the GTK drawing surface:
- Pixel Alignment and Rounding: The coordinates of the linear segments, while in screen coordinate space, are still floating-point values. GIMP and Cairo align these lines relative to the pixel grid, typically offsetting coordinates by 0.5 pixels when drawing 1-pixel-wide path outlines to ensure sharp, non-blurry line rendering.
- Coverage Calculation (Anti-Aliasing): For each pixel intersecting a path line segment, Cairo calculates sub-pixel coverage. Pixels entirely covered by the path are set to the stroke's foreground color, while partially covered boundary pixels receive an alpha-blended value proportional to their coverage area.
- Buffer Blitting: The resulting pixel values are written directly to the display shell's Cairo context, compositing the path handles and lines over the rendered image tile cache in the GTK widget viewport.