///|
/// An owned, mutable Cairo region made from integer-aligned rectangles.
///
/// Assigning this wrapper shares the same underlying region. Use `copy()` for
/// an independently mutable snapshot. MoonBit releases the Cairo handle when
/// the final wrapper becomes unreachable. Unlike pycairo, boolean mutators
/// return the receiver so operations can be chained.
struct Region(@region_impl.RawRegion)
///|
fn Region::from_raw(raw : @region_impl.RawRegion) -> Region {
Region(raw)
}
///|
fn Region::to_raw(self : Region) -> @region_impl.RawRegion {
self.0
}
///|
fn region_status_from_raw(raw : Int) -> Status {
status_from_raw(raw) catch {
_ => InvalidStatus
}
}
///|
fn check_region_status_raw(raw : Int) -> Unit raise CairoError {
check_status(status_from_raw(raw))
}
///|
fn region_overlap_from_raw(raw : Int) -> RegionOverlap {
match raw {
0 => RegionOverlapIn
1 => RegionOverlapOut
2 => RegionOverlapPart
_ => RegionOverlapOut
}
}
///|
/// Create a new empty region.
///
/// Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate it.
pub fn Region::new() -> Region raise CairoError {
let raw = @region_impl.create_raw()
check_region_status_raw(@region_impl.status_raw(raw))
Region::from_raw(raw)
}
///|
/// Create a region containing `rectangle`.
///
/// The rectangle is copied into Cairo and is not retained. Raises
/// `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the region.
pub fn Region::from_rectangle(
rectangle : RectangleInt,
) -> Region raise CairoError {
let raw = @region_impl.create_rectangle_raw(
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
)
check_region_status_raw(@region_impl.status_raw(raw))
Region::from_raw(raw)
}
///|
/// Create a region containing the union of `rectangles`.
///
/// An empty view creates an empty region. Cairo copies and normalizes the
/// input, so it may merge or split rectangles and does not preserve their
/// count or order. Raises `CairoMemoryError(NoMemory, _)` on allocation
/// failure.
pub fn Region::from_rectangles(
rectangles : ArrayView[RectangleInt],
) -> Region raise CairoError {
let count = rectangles.length()
let status = Ref(0)
let raw = @region_impl.create_rectangles_raw(
FixedArray::makei(count, index => rectangles[index].x),
FixedArray::makei(count, index => rectangles[index].y),
FixedArray::makei(count, index => rectangles[index].width),
FixedArray::makei(count, index => rectangles[index].height),
status,
)
check_region_status_raw(status.val)
check_region_status_raw(@region_impl.status_raw(raw))
Region::from_raw(raw)
}
///|
/// Create an independently owned copy of this region's current coverage.
///
/// Later mutations of either region do not affect the other. Raises
/// `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the copy.
pub fn Region::copy(self : Region) -> Region raise CairoError {
let raw = @region_impl.copy_raw(self.to_raw())
check_region_status_raw(@region_impl.status_raw(raw))
Region::from_raw(raw)
}
///|
/// Return the status stored in this region without raising it.
///
/// Public constructors and mutators check their status before returning, so
/// `Success` is expected for regions obtained through the public API.
pub fn Region::status(self : Region) -> Status {
region_status_from_raw(@region_impl.status_raw(self.to_raw()))
}
///|
fn rectangle_int_from_region_output(
f : (Ref[Int], Ref[Int], Ref[Int], Ref[Int]) -> Int,
) -> RectangleInt raise CairoError {
let x = Ref(0)
let y = Ref(0)
let width = Ref(0)
let height = Ref(0)
check_region_status_raw(f(x, y, width, height))
RectangleInt::new(x=x.val, y=y.val, width=width.val, height=height.val)
}
///|
/// Return the integer bounding rectangle of the entire region.
///
/// This is an extent, not one element of Cairo's normalized decomposition.
/// Raises the region's checked `CairoError` status if the query fails.
pub fn Region::get_extents(self : Region) -> RectangleInt raise CairoError {
rectangle_int_from_region_output((x, y, width, height) => {
@region_impl.get_extents_raw(self.to_raw(), x, y, width, height)
})
}
///|
/// Return the number of rectangles in Cairo's normalized decomposition.
///
/// The result need not equal the number passed to `from_rectangles`.
pub fn Region::num_rectangles(self : Region) -> Int {
@region_impl.num_rectangles_raw(self.to_raw())
}
///|
/// Return rectangle `index` from Cairo's normalized decomposition.
///
/// Decomposition order is Cairo-defined and must not be used as a stable
/// serialization format. Raises `CairoInvalidArgument(InvalidIndex, _)` for a
/// negative or out-of-range index, or the region's checked status on failure.
pub fn Region::get_rectangle(
self : Region,
index : Int,
) -> RectangleInt raise CairoError {
if index < 0 || index >= self.num_rectangles() {
raise CairoInvalidArgument(InvalidIndex, InvalidIndex.message())
}
rectangle_int_from_region_output((x, y, width, height) => {
@region_impl.get_rectangle_raw(self.to_raw(), index, x, y, width, height)
})
}
///|
/// Return whether this region covers no area.
pub fn Region::is_empty(self : Region) -> Bool {
@region_impl.is_empty_raw(self.to_raw())
}
///|
/// Return whether the integer point `(x, y)` lies inside this region.
pub fn Region::contains_point(self : Region, x : Int, y : Int) -> Bool {
@region_impl.contains_point_raw(self.to_raw(), x, y)
}
///|
/// Classify how this region covers `rectangle`.
///
/// Returns `RegionOverlapIn` for complete coverage, `RegionOverlapOut` for no
/// overlap, and `RegionOverlapPart` for partial coverage.
pub fn Region::contains_rectangle(
self : Region,
rectangle : RectangleInt,
) -> RegionOverlap {
region_overlap_from_raw(
@region_impl.contains_rectangle_raw(
self.to_raw(),
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
),
)
}
///|
/// Return whether two regions cover exactly the same area.
///
/// Equality is independent of wrapper identity, allocation identity, and the
/// rectangle decomposition chosen by Cairo.
pub fn Region::equal(self : Region, other : Region) -> Bool {
@region_impl.equal_raw(self.to_raw(), other.to_raw())
}
///|
pub impl Eq for Region with fn equal(self, other) {
self.equal(other)
}
///|
/// Translate this region in place by the integer offset `(dx, dy)`.
///
/// This method returns `Unit`. Raises the checked `CairoError` status reported
/// after the mutation.
pub fn Region::translate(
self : Region,
dx : Int,
dy : Int,
) -> Unit raise CairoError {
check_region_status_raw(@region_impl.translate_raw(self.to_raw(), dx, dy))
}
///|
/// Replace this region with its intersection with `other`.
///
/// `other` is neither retained nor mutated. Returns this same receiver for
/// chaining. Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate
/// the result.
pub fn Region::intersect(
self : Region,
other : Region,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.intersect_raw(self.to_raw(), other.to_raw()),
)
self
}
///|
/// Replace this region with its intersection with `rectangle`.
///
/// The rectangle is not retained. Returns this same receiver for chaining.
/// Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the result.
pub fn Region::intersect_rectangle(
self : Region,
rectangle : RectangleInt,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.intersect_rectangle_raw(
self.to_raw(),
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
),
)
self
}
///|
/// Remove every point covered by `other` from this region.
///
/// `other` is neither retained nor mutated. Returns this same receiver for
/// chaining. Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate
/// the result.
pub fn Region::subtract(
self : Region,
other : Region,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.subtract_raw(self.to_raw(), other.to_raw()),
)
self
}
///|
/// Remove every point covered by `rectangle` from this region.
///
/// The rectangle is not retained. Returns this same receiver for chaining.
/// Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the result.
pub fn Region::subtract_rectangle(
self : Region,
rectangle : RectangleInt,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.subtract_rectangle_raw(
self.to_raw(),
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
),
)
self
}
///|
/// Replace this region with its union with `other`.
///
/// `other` is neither retained nor mutated. Returns this same receiver for
/// chaining. Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate
/// the result.
pub fn Region::union(self : Region, other : Region) -> Region raise CairoError {
check_region_status_raw(@region_impl.union_raw(self.to_raw(), other.to_raw()))
self
}
///|
/// Replace this region with its union with `rectangle`.
///
/// The rectangle is not retained. Returns this same receiver for chaining.
/// Raises `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the result.
pub fn Region::union_rectangle(
self : Region,
rectangle : RectangleInt,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.union_rectangle_raw(
self.to_raw(),
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
),
)
self
}
///|
/// Replace this region with the symmetric difference from `other`.
///
/// The result covers points present in exactly one operand. `other` is neither
/// retained nor mutated. Returns this same receiver for chaining. Raises
/// `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the result.
pub fn Region::xor(self : Region, other : Region) -> Region raise CairoError {
check_region_status_raw(@region_impl.xor_raw(self.to_raw(), other.to_raw()))
self
}
///|
/// Replace this region with the symmetric difference from `rectangle`.
///
/// The result covers points present in exactly one operand. The rectangle is
/// not retained. Returns this same receiver for chaining. Raises
/// `CairoMemoryError(NoMemory, _)` if Cairo cannot allocate the result.
pub fn Region::xor_rectangle(
self : Region,
rectangle : RectangleInt,
) -> Region raise CairoError {
check_region_status_raw(
@region_impl.xor_rectangle_raw(
self.to_raw(),
rectangle.x,
rectangle.y,
rectangle.width,
rectangle.height,
),
)
self
}