# 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).