# Peta::FFI::Cairo::Context
📦 std
`Cairo::Context` package plug-in.
The drawing context (`cairo_t`). This module owns the context cairo
symbols, resolving them itself via `super::cairo_dlsym` over the shared
handle so the foundation’s symbol table never carries context entries.
Refcount contract (census section 4): `create` returns a +1 context
blessed directly; `DESTROY` drops exactly one reference via
`cairo_destroy`. Borrowed getters (`get_source`, `get_target`,
`get_group_target`, `get_font_face`) return objects the caller does not
own, so we `cairo_*_reference` them before blessing; `pop_group` already
returns +1 (matching `newSVCairoPattern_noinc`) so it is blessed directly.
## Cross-package ABI assumptions (FLAGGED for review)
Two getters here manufacture objects that live in SIBLING packages, so
this file makes allocator/refcount assumptions about how those packages”
`DESTROY` will free them. Both are documented at their call sites:
- `get_matrix` / `get_font_matrix` return a `Cairo::Matrix`. Upstream
`cairo_perl_copy_matrix` does `New(0, m, 1, cairo_matrix_t); *m = src`
and `Cairo::Matrix::DESTROY` does `Safefree(m)`. We mirror that with a
raw `libc::malloc` of `size_of::()` (6 f64 = 48 bytes),
write the matrix into it via `cairo_get_matrix`, and bless the pointer
into `Cairo::Matrix`. The Matrix package’s `DESTROY` MUST free it with
the matching `libc::free`. If Matrix uses a different allocator, this is
a mismatch - hence the shared-repr definition below.
- `get_font_options` returns a `Cairo::FontOptions` allocated with
`cairo_font_options_create()` (a +1 cairo object). The Font package’s
`Cairo::FontOptions::DESTROY` MUST call `cairo_font_options_destroy`.
## Functions
### Other Functions
#### `context_create`
`Cairo::Context->create($surface)` -> blessed Cairo::Context. Mirrors cairo_create with the `_noinc` contract; ST(0) is the class (dropped).
#### `context_destroy`
`$cr->DESTROY` -> cairo_destroy, dropping the wrapper’s one reference.
#### `context_status`
`$cr->status` -> status nickname (enum-string return).
#### `pop_group`
`$cr->pop_group` -> the group as a pattern. cairo_pop_group already returns +1 (newSVCairoPattern_noinc), so we bless directly, type-dispatched.
#### `get_source`
`$cr->get_source` -> the current source pattern (borrowed; reference + type-dispatched bless).
#### `set_dash`
`$cr->set_dash($offset, @dashes)`. Variadic: mirrors the XS which mallocs `items - 2` doubles from ST(2..) and passes (dashes, ndash, offset).
#### `get_dash`
`$cr->get_dash` -> list ($offset, @dashes). Mirrors the PPCODE XS: cairo_get_dash_count then cairo_get_dash into a buffer, push offset first.
#### `has_current_point`
`$cr->has_current_point` -> bool (>=1.6). dlsym-gated: absent -> croak.
#### `get_current_point`
`$cr->get_current_point` -> ($x, $y) OUTLIST.
#### `in_clip`
`$cr->in_clip(x, y)` -> bool (>=1.10). dlsym-gated via context_hit.
#### `select_font_face`
`$cr->select_font_face($family, $slant, $weight)`. utf8 family + 2 enums.
#### `get_font_options`
`$cr->get_font_options` -> Cairo::FontOptions. Allocs a fresh options object (cairo_font_options_create, +1 owned), fills it, blesses into the Font package’s FontOptions (whose DESTROY calls cairo_font_options_destroy). See module ABI note.
#### `get_scaled_font`
`$cr->get_scaled_font` -> Cairo::ScaledFont (>=1.4). This is a borrowed getter in the XS (ref-INC via newSVCairoScaledFont); we take a reference through cairo_scaled_font_reference if present, then bless into the nominal Cairo::ScaledFont (no subclass dispatch for scaled fonts).
#### `show_text`
`$cr->show_text($utf8)`.
#### `text_path`
`$cr->text_path($utf8)`.
#### `get_font_face`
`$cr->get_font_face` -> Cairo::FontFace subclass (borrowed; ref + dispatch).
#### `font_extents`
`$cr->font_extents` -> hashref {ascent,descent,height,max_x_advance, max_y_advance}. Keys fixed by newSVCairoFontExtents.
#### `text_extents`
`$cr->text_extents($utf8)` -> hashref {x_bearing,y_bearing,width,height, x_advance,y_advance}. Keys fixed by newSVCairoTextExtents.
#### `get_target`
`$cr->get_target` -> the target surface (borrowed; ref + type-dispatch).
#### `get_group_target`
`$cr->get_group_target` -> the current group’s target surface (>=1.2).
#### `tag_begin`
`$cr->tag_begin($tag_name, $attributes)` (>=1.16). dlsym-gated.
#### `tag_end`
`$cr->tag_end($tag_name)` (>=1.16). dlsym-gated.
#### `show_glyphs`
`$cr->show_glyphs(@glyphs)` (Cairo.xs). Variadic LIST of glyph hashrefs; marshal each with SvCairoGlyph, then `cairo_show_glyphs`. Void return.
#### `glyph_path`
`$cr->glyph_path(@glyphs)` (Cairo.xs). Variadic LIST; `cairo_glyph_path`. Void return.
#### `glyph_extents`
`$cr->glyph_extents(@glyphs)` (Cairo.xs) -> text_extents hashref {x_bearing,y_bearing,width,height,x_advance,y_advance}. Variadic LIST.
#### `show_text_glyphs`
`$cr->show_text_glyphs($utf8, \@glyphs, \@clusters, $cluster_flags)` (Cairo.xs, >=1.8). utf8 string + glyph arrayref + cluster arrayref + text-cluster-flags. The XS allocates the glyph/cluster arrays with cairo’s own `cairo_glyph_allocate` / `cairo_text_cluster_allocate` and frees them with the matching `_free` after the call, so we do the same. Void return.
#### `copy_path`
`Cairo::Context::copy_path` (Cairo.xs:893) -> cairo_copy_path -> a tied `Cairo::Path` live view. cairo returns a +1 path; the tie’s DESTROY frees it via cairo_path_destroy, so we wrap it directly (newSVCairoPath).
#### `copy_path_flat`
`Cairo::Context::copy_path_flat` (Cairo.xs:895): same wrapping, flattened path (curves approximated by line segments).
#### `append_path`
`Cairo::Context::append_path` (Cairo.xs:897): take a `Cairo::Path` (or a plain arrayref-of-hashes) and cairo_append_path it. `SvCairoPath` recovers the C pointer from tie magic, or marshals an arrayref via path_from_array; the latter is a temp we must free once cairo has copied it (cairo acts on the path immediately, per CairoPath.xs:129-132).
#### `copy_clip_rectangle_list`
`Cairo::Context::copy_clip_rectangle_list` (Cairo.xs:641-651): return the current clip as a list of `{x,y,width,height}` (nv) hashrefs. Mirrors the XS PPCODE: check list->status (croak on error), push each rectangle, then cairo_rectangle_list_destroy. Not a tie - a plain list return (census 2.2). Requires libcairo >= 1.4 (dlsym-gated).