///|
/// Create a callback-backed pixel source with typed content.
///
/// Raster-source patterns require Cairo 1.12 or newer. `width` and `height`
/// are the non-negative maximum sample-area dimensions, not an allocated image.
/// Register an acquire callback before drawing. Raises `InvalidSize`,
/// `InvalidContent`, allocation failure, or another creation status.
pub fn Pattern::raster_source(
content : Content,
width : Int,
height : Int,
) -> Pattern raise CairoError {
let raw = @pattern_impl.create_raster_source_raw(
content.to_raw(),
width,
height,
)
check_pattern_status_raw(@pattern_impl.status_raw(raw))
Pattern::from_raw(raw)
}
///|
/// Create a callback-backed pixel source from a Cairo content integer.
///
/// For pycairo compatibility, accepted values are exactly `0x1000` (color),
/// `0x2000` (alpha), and `0x3000` (color plus alpha). Other values raise
/// `CairoInvalidArgument(InvalidContent, _)` before C; dimensions and Cairo
/// 1.12 requirements match `raster_source()`.
pub fn Pattern::raster_source_raw(
content : Int,
width : Int,
height : Int,
) -> Pattern raise CairoError {
let raw = @pattern_impl.create_raster_source_raw(
checked_content_raw(content),
width,
height,
)
check_pattern_status_raw(@pattern_impl.status_raw(raw))
Pattern::from_raw(raw)
}
///|
/// Install the mandatory raster acquire callback and optional release callback.
///
/// For each request, `acquire` receives the target and a pixel rectangle in
/// sample space. Return a compatible surface covering that rectangle; use
/// `target.create_similar_image()` and a device offset for a subregion. The
/// binding retains the returned surface until Cairo releases the acquisition.
/// Both closures are retained until replacement, clearing, or finalization.
pub fn Pattern::raster_set_acquire(
self : Pattern,
acquire : (Surface, RectangleInt) -> Surface,
release? : ((Surface) -> Unit)? = None,
) -> Unit raise CairoError {
self.raster_set_callbacks(acquire=Some(acquire), release~)
}
///|
/// Replace this raster pattern's callback registration.
///
/// Callback types are non-raising: recoverable MoonBit errors must be handled
/// inside the closure and must never unwind through Cairo. A finished or error
/// surface returned by `acquire` is rejected and the drawing operation reports
/// a Cairo error. `release`, when present, receives each successfully acquired
/// surface before the binding drops its retained owner; internal cleanup still
/// runs when no user release is registered.
///
/// Passing both options as `None` clears the registration. Release-only state
/// is queryable but cannot supply pixels. Replacement requested from inside a
/// callback is deferred until all acquisitions using the old pair are released,
/// preserving closure and surface lifetimes. Raises `PatternTypeMismatch` on a
/// non-raster pattern or another checked registration status.
pub fn Pattern::raster_set_callbacks(
self : Pattern,
acquire? : ((Surface, RectangleInt) -> Surface)? = None,
release? : ((Surface) -> Unit)? = None,
) -> Unit raise CairoError {
let raw_acquire = match acquire {
None => None
Some(acquire) =>
Some(fn(target, x, y, width, height) {
acquire(
Surface::from_raw(target),
RectangleInt::new(x~, y~, width~, height~),
).to_raw()
})
}
let raw_release = match release {
None => None
Some(release) => Some(fn(surface) { release(Surface::from_raw(surface)) })
}
check_pattern_status_raw(
@pattern_impl.raster_set_callbacks_raw(
self.to_raw(),
acquire=raw_acquire,
release=raw_release,
),
)
}
///|
/// Return the currently effective acquire and release closures.
///
/// Returned closures are strong MoonBit references and may outlive a later
/// replacement. During a callback-triggered deferred replacement, this reports
/// the pair still serving outstanding acquisitions. Raises
/// `PatternTypeMismatch` on a non-raster pattern or a sticky pattern error.
pub fn Pattern::raster_get_callbacks(
self : Pattern,
) -> (((Surface, RectangleInt) -> Surface)?, ((Surface) -> Unit)?) raise CairoError {
let has_acquire = Ref(0)
let has_release = Ref(0)
let status = Ref(0)
let _ = @pattern_impl.raster_has_callbacks_raw(
self.to_raw(),
has_acquire,
has_release,
status,
)
check_pattern_status_raw(status.val)
let acquire = if has_acquire.val == 0 {
None
} else {
let acquire_status = Ref(0)
let raw_acquire = @pattern_impl.raster_get_acquire_raw(
self.to_raw(),
acquire_status,
)
check_pattern_status_raw(acquire_status.val)
Some(fn(target : Surface, extents : RectangleInt) {
Surface::from_raw(
raw_acquire(
target.to_raw(),
extents.x,
extents.y,
extents.width,
extents.height,
),
)
})
}
let release = if has_release.val == 0 {
None
} else {
let release_status = Ref(0)
let raw_release = @pattern_impl.raster_get_release_raw(
self.to_raw(),
release_status,
)
check_pattern_status_raw(release_status.val)
Some(fn(surface : Surface) { raw_release(surface.to_raw()) })
}
(acquire, release)
}
///|
/// Clear both raster callbacks and release their retained closures.
///
/// If called from acquire or release, clearing takes effect after every
/// outstanding acquisition using the current pair has run internal cleanup.
/// Raises `PatternTypeMismatch` on a non-raster pattern or a sticky error.
pub fn Pattern::raster_clear_callbacks(self : Pattern) -> Unit raise CairoError {
self.raster_clear_acquire()
}
///|
/// Clear the raster acquire/release pair.
///
/// This is the pycairo-compatible name for `raster_clear_callbacks()`. It uses
/// the same deferred, reentrant-safe cleanup and raises the same checked errors.
pub fn Pattern::raster_clear_acquire(self : Pattern) -> Unit raise CairoError {
check_pattern_status_raw(
@pattern_impl.raster_clear_callbacks_raw(self.to_raw()),
)
}
///|
/// Return the acquire callback paired with its optional release callback.
///
/// Returns `None` when no acquire callback is effective, including release-only
/// registration. The returned closures are strong references. Raises
/// `PatternTypeMismatch` on a non-raster pattern or a sticky pattern error.
pub fn Pattern::raster_get_acquire(
self : Pattern,
) -> ((Surface, RectangleInt) -> Surface, ((Surface) -> Unit)?)? raise CairoError {
let (acquire, release) = self.raster_get_callbacks()
match acquire {
None => None
Some(acquire) => Some((acquire, release))
}
}