# Peta::FFI::Cairo::Surface
📦 std
`Cairo::Surface` family package plug-in.
One file per the seven-file fan-out plan covers the whole surface family,
because every concrete surface (`Cairo::ImageSurface`, `Cairo::PdfSurface`,
`Cairo::PsSurface`, `Cairo::SvgSurface`, `Cairo::RecordingSurface`) is a
`Cairo::Surface` subclass blessed by the SAME type-dispatch table
(`cairo_surface_get_type`), and they share the surface-family cairo
symbols. This module resolves those symbols itself via `super::cairo_dlsym`
over the shared handle, so the foundation’s symbol table never carries
surface entries and parallel package agents never contend on it.
Refcount contract (census section 4): every `create*` constructor and
`create_similar` / `create_for_rectangle` return a +1 surface, blessed
directly (`_noinc`). `DESTROY` drops exactly one reference via
`cairo_surface_destroy`. Enum-returning methods (`status`, `get_type`,
`get_content`, `get_format`) surface the cairo int as its string nickname.
Version scope (census top block): the 1.109 phenotype is the floor; we bind
it 1:1 against the loaded libcairo 1.18.4. Backend-specific ctors and the
> =1.16 PDF metadata/outline methods are dlsym-gated: on a feature-stripped
> libcairo the symbol resolves to `None` and the method croaks with a
> targeted ”built without X support“ message rather than dereferencing null.
Deferred (later dedicated pass, census section 5 hard-parts 1 and 4): the
stream ctors and `write_to_png_stream` / `create_from_png_stream` need a
Perl write/read callback re-entered from inside libcairo through a C
trampoline; `set_mime_data` / `get_mime_data` cross an SV lifetime into
libcairo. These are registered as croaking stubs so the API surface is
present but flags the unimplemented path explicitly.
## Functions
### Other Functions
#### `image_surface_create`
`Cairo::ImageSurface->create($format, $width, $height)` -> blessed surface. Mirrors cairo_image_surface_create; C_ARGS drops the leading class. The constructor owns +1, so we type-dispatch bless without an extra reference.
#### `image_surface_create_for_data`
`Cairo::ImageSurface->create_for_data($data, $format, $width, $height, $stride)`. Mirrors cairo_image_surface_create_for_data: the raw bytes are borrowed by cairo (not copied), so the SV must outlive the surface - matching the XS, which passes the SV’s PV pointer straight through.
#### `image_get_data`
`$image_surface->get_data` -> SV string of height\*stride bytes, or undef. Mirrors the XS which reads height and stride to size the SV.
#### `image_get_format`
`$image_surface->get_format` -> format nickname (enum-string return).
#### `image_create_from_png`
`Cairo::ImageSurface->create_from_png($filename)` -> blessed surface. PNG is a build option; the symbol is dlsym-gated (census runtime-env note).
#### `surface_destroy`
`$surface->DESTROY` -> cairo_surface_destroy, dropping the one reference this wrapper owns (census section 4).
#### `surface_status`
`$surface->status` -> status nickname (enum-string return).
#### `surface_get_type`
`$surface->get_type` -> surface-type nickname (enum-string return).
#### `surface_get_content`
`$surface->get_content` -> content nickname (enum-string return).
#### `surface_write_to_png`
`$surface->write_to_png($filename)` -> status nickname. PNG is dlsym-gated.
#### `surface_create_similar`
`create_similar` in its dual class/instance form (CairoSurface.xs L313): Cairo::Surface->create_similar($other, $content, $w, $h) (items==5) $other->create_similar($content, $w, $h) (items==4) The extra leading class shifts the arg offset by one. content is an enum string; the result is a +1 surface blessed type-dispatched.
#### `surface_set_device_offset`
`$surface->set_device_offset($x, $y)`.
#### `surface_get_device_offset`
`$surface->get_device_offset` -> ($x_offset, $y_offset) (OUTLIST list).
#### `surface_set_fallback_resolution`
`$surface->set_fallback_resolution($x_ppi, $y_ppi)`.
#### `surface_get_fallback_resolution`
`$surface->get_fallback_resolution` -> ($x_ppi, $y_ppi) (OUTLIST list).
#### `surface_get_font_options`
`$surface->get_font_options` -> blessed Cairo::FontOptions. Mirrors the XS CODE block: allocate a fresh options with cairo_font_options_create, fill it via cairo_surface_get_font_options, then bless the +1 pointer directly (font options are their own object owned by the Font package).
#### `surface_mark_dirty_rectangle`
`$surface->mark_dirty_rectangle($x, $y, $width, $height)` (four ints).
#### `surface_has_show_text_glyphs`
`$surface->has_show_text_glyphs` -> bool (0/1).
#### `surface_create_for_rectangle`
`Cairo::Surface->create_for_rectangle($target, $x, $y, $width, $height)`. Mirrors the XS `class, target, x, y, w, h` with C_ARGS dropping class; the result is a +1 surface blessed type-dispatched.
#### `surface_supports_mime_type`
`$surface->supports_mime_type($mime_type)` -> bool (0/1).
#### `pdf_restrict_to_version`
`$pdf->restrict_to_version($version)` (enum string arg).
#### `pdf_set_metadata`
`$pdf->set_metadata($metadata, $utf8)` (>=1.16). metadata is an enum string.
#### `pdf_set_page_label`
`$pdf->set_page_label($utf8)` (>=1.16).
#### `pdf_set_thumbnail_size`
`$pdf->set_thumbnail_size($width, $height)` (>=1.16).
#### `pdf_add_outline`
`$pdf->add_outline($parent_id, $utf8, $link_attribs, $flags)` -> int (>=1.16). flags is the outline-flags enum as an integer bitmask (not a nickname in the XS - it is a plain int typemap for this method).
#### `pdf_outline_root`
`Cairo::PdfSurface::OUTLINE_ROOT` -> 0 (CAIRO_PDF_OUTLINE_ROOT constant).
#### `ps_dsc_comment`
`$ps->dsc_comment($comment)`.
#### `ps_restrict_to_level`
`$ps->restrict_to_level($level)` (enum string arg).
#### `ps_set_eps`
`$ps->set_eps($bool)`.
#### `ps_get_eps`
`$ps->get_eps` -> bool (0/1).
#### `svg_restrict_to_version`
`$svg->restrict_to_version($version)` (enum string arg).
#### `recording_create`
`Cairo::RecordingSurface->create($content, $extents_or_undef)`. Mirrors the XS `class, content, cairo_rectangle_t_ornull *extents`: content is an enum string; extents is either an unblessed {x,y,width,height} hashref (a bounded recording surface) or undef/absent (unbounded, NULL rectangle).
#### `recording_ink_extents`
`$recording->ink_extents` -> ($x0, $y0, $width, $height) (OUTLIST list).
#### `recording_get_extents`
`$recording->get_extents` -> {x,y,width,height} hashref, or undef when the surface is unbounded. Mirrors the XS: the cairo_bool_t return gates whether the filled rectangle is returned at all.
#### `format_stride_for_width`
`Cairo::Format::stride_for_width($format, $width)` -> int. Mirrors cairo_format_stride_for_width; format is an enum string. Called as a plain function (not a method), so the format is ST(0).
#### `write_to_png_stream`
`$surface->write_to_png_stream($closure [, $data])` -> status nickname. One-shot write_func: the closure lives only for the call, so we free it immediately afterwards (no set_user_data). Mirrors CairoSurface.xs cairo_surface_write_to_png_stream. PNG is dlsym-gated.
#### `create_from_png_stream`
`Cairo::ImageSurface->create_from_png_stream($closure [, $data])` -> blessed surface. read_func ctor; +1 surface blessed type-dispatched. The closure is consumed only during the ctor call, so free it immediately after. PNG gated.
#### `set_mime_data`
`$surface->set_mime_data($mime_type, $data)` -> status nickname (>=1.10). Mirrors CairoSurface.xs: SvREFCNT_inc the passed $data SV (NOT a copy), hand its raw bytes to cairo, and register data_destroy (SvREFCNT_dec) so cairo owns exactly one reference until it drops the buffer. The SV’s PV must stay valid for the surface’s life, which the retained reference guarantees.
#### `get_mime_data`
`$surface->get_mime_data($mime_type)` -> SV string, or undef if the surface carries no data for that MIME type (>=1.10). cairo writes an out double- pointer + length; the XS builds newSVpvn(data, length). We return undef when cairo reports a null data pointer (no attached blob) rather than an empty string, since a genuine zero-length blob is indistinguishable and undef is the more useful phenotype for ”absent“.