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