# Peta::FFI::Cairo::Pattern
📦 std
`Cairo::Pattern` family plug-in (CairoPattern.xs phenotype).
Covers the base `Cairo::Pattern` plus its five concrete subclasses:
`Cairo::SolidPattern`, `Cairo::SurfacePattern`, `Cairo::Gradient`
(abstract - only add_color_stop_\* / get_color_stops), and the two
gradient leaves `Cairo::LinearGradient` / `Cairo::RadialGradient`. This
module owns the `cairo_pattern_*` symbols, resolving them itself via
`super::cairo_dlsym` over the shared handle so the foundation’s table
never carries pattern entries.
## Refcount contract (census section 4)
A pattern is cairo-refcounted. Every constructor here
(`create_rgb`/`create_rgba`/`create` for-surface/`create` linear/radial)
returns a +1 pattern (the XS `cairo_pattern_t_noinc` return type), so we
bless the pointer directly. `DESTROY` drops exactly one reference via
`cairo_pattern_destroy`.
## Type-dispatched blessing (census section 4)
Constructors do NOT bless into the nominal package. The XS
`cairo_pattern_to_sv` calls `cairo_pattern_get_type` and picks the
concrete subclass. `bless_pattern_noinc` below replicates that dispatch
(0->SolidPattern, 1->SurfacePattern, 2->LinearGradient,
3->RadialGradient, else Pattern), byte-identical to the private helper
in Context.rs. `create_rgb` returning a solid pattern therefore comes
back blessed `Cairo::SolidPattern`, matching upstream.
## Cross-package ABI: get_matrix -> Cairo::Matrix (review-critical)
`get_matrix` mirrors `cairo_perl_copy_matrix`: allocate a fresh
`cairo_matrix_t` on the heap, let cairo fill it, bless into
`Cairo::Matrix`. We allocate with `libc::malloc(size_of::())`
(6 f64 = 48 bytes) EXACTLY as Context.rs’s `get_matrix` and Matrix.rs’s
constructors do, so the resulting pointer is uniformly `libc::free`-
compatible with `Cairo::Matrix::DESTROY`. Any other allocator here would
double-free or leak.
## get_surface -> type-dispatched Cairo::Surface (borrowed)
`get_surface` returns a surface the pattern still owns (borrowed
getter). Per the refcount contract we `cairo_surface_reference` it before
blessing, then type-dispatch on `cairo_surface_get_type` - the same table
as the foundation’s `bless_surface_noinc`, replicated locally so this
file stays independent of the Surface package.
## Superset: gradient dithering (cairo 1.18)
`set_dither`/`get_dither` (`cairo_dither_t`) have no 1.109 XS original;
the census VERSION SCOPE mandates binding them into the Pattern package
as a clean superset addition (the gradient-banding fix). The symbols are
dlsym-gated: if the loaded libcairo predates 1.18 they resolve to `None`
and the method croaks «requires cairo >= 1.18».
## Functions
### Other Functions
#### `pattern_destroy`
`$pattern->DESTROY` -> cairo_pattern_destroy, dropping the wrapper’s one reference.
#### `set_matrix`
`$pattern->set_matrix($matrix)` -> cairo_pattern_set_matrix. ST(1) is a Cairo::Matrix (blessed pointer to a cairo_matrix_t).
#### `get_matrix`
`$pattern->get_matrix` -> a fresh Cairo::Matrix. Mirrors `cairo_perl_copy_matrix`: heap-alloc a cairo_matrix_t with libc::malloc (matching Cairo::Matrix::DESTROY’s libc::free), let cairo fill it, bless. See the module ABI note.
#### `status`
`$pattern->status` -> status nickname (enum-string return).
#### `set_dither`
`$pattern->set_dither($dither)` (cairo 1.18 superset). dlsym-gated: croak if the loaded libcairo predates 1.18 (symbol absent).
#### `get_dither`
`$pattern->get_dither` -> dither nickname (cairo 1.18 superset).
#### `create_rgb`
`Cairo::SolidPattern->create_rgb($r,$g,$b)` -> +1 pattern, type-dispatch blessed. ST(0) is the class (dropped); the 3 doubles follow.
#### `create_rgba`
`Cairo::SolidPattern->create_rgba($r,$g,$b,$a)` -> +1 pattern.
#### `get_rgba`
`$pattern->get_rgba` -> list ($r,$g,$b,$a) (cairo >= 1.4). PPCODE list-return with a status-check (CAIRO_PERL_CHECK_STATUS -> croak).
#### `surface_pattern_create`
`Cairo::SurfacePattern->create($surface)` -> +1 pattern (cairo_pattern_create_for_surface), type-dispatch blessed. ST(0) is the class (dropped), ST(1) is the surface.
#### `get_surface`
`$pattern->get_surface` -> the pattern’s surface (cairo >= 1.4). Borrowed getter: reference + type-dispatch bless. Status-check per the XS.
#### `add_color_stop_rgb`
`$gradient->add_color_stop_rgb($offset,$r,$g,$b)`.
#### `add_color_stop_rgba`
`$gradient->add_color_stop_rgba($offset,$r,$g,$b,$a)`.
#### `get_color_stops`
`$gradient->get_color_stops` -> list of 5-elem arrayrefs [offset,r,g,b,a] (cairo >= 1.4). Mirrors the PPCODE loop: get_color_stop_count then get_color_stop_rgba per index, status-checked.
#### `linear_create`
`Cairo::LinearGradient->create($x0,$y0,$x1,$y1)` -> +1 pattern.
#### `get_points`
`$linear->get_points` -> list ($x0,$y0,$x1,$y1) (cairo >= 1.4).
#### `radial_create`
`Cairo::RadialGradient->create($cx0,$cy0,$r0,$cx1,$cy1,$r1)` -> +1 pattern.
#### `get_circles`
`$radial->get_circles` -> list of 6 doubles ($x0,$y0,$r0,$x1,$y1,$r1) (cairo >= 1.4).