#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
#![warn(clippy::missing_safety_doc)]
mod color;
#[cfg(feature = "sys")]
pub mod sys;
#[cfg(not(feature = "sys"))]
mod sys;
use std::borrow::Cow;
use bytemuck::cast;
use bytemuck::cast_ref;
pub const FLUTTER_ARTEFACT_COMMIT: &str = include_str!("../ENGINE_SHA");
pub use sys::BlendMode;
pub use sys::BlurStyle;
pub use sys::PixelFormat;
pub use sys::ClipOperation;
pub use sys::ColorSpace;
pub use sys::DrawStyle;
pub use sys::FillType;
pub use sys::FontStyle;
pub use sys::FontWeight;
pub use sys::StrokeCap;
pub use sys::StrokeJoin;
pub use sys::TextAlignment;
pub use sys::TextDirection;
pub use sys::TextDecorationStyle;
pub use sys::TextureSampling;
pub use sys::TileMode;
pub use sys::{
ImpellerColor as Color, ImpellerColorMatrix as ColorMatrix,
ImpellerContextVulkanInfo as VulkanInfo, ImpellerRange as Range,
};
#[allow(missing_docs)]
pub type Rect = euclid::Rect<f32, euclid::UnknownUnit>;
#[allow(missing_docs)]
pub type Point = euclid::Point2D<f32, euclid::UnknownUnit>;
#[allow(missing_docs)]
pub type ISize = euclid::Size2D<i64, euclid::UnknownUnit>;
#[allow(missing_docs)]
pub type Size = euclid::Size2D<f32, euclid::UnknownUnit>;
#[allow(missing_docs)]
pub type Matrix = euclid::Transform3D<f32, euclid::UnknownUnit, euclid::UnknownUnit>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ImpellerVersion(u32);
impl ImpellerVersion {
pub fn get_header_version() -> Self {
Self(
(sys::IMPELLER_VERSION_VARIANT << 29)
| (sys::IMPELLER_VERSION_MAJOR << 22)
| (sys::IMPELLER_VERSION_MINOR << 12)
| sys::IMPELLER_VERSION_PATCH,
)
}
pub fn get_variant(self) -> u32 {
self.0 >> 29
}
pub fn get_major(self) -> u32 {
(self.0 & (!0 >> 3)) >> 22
}
pub fn get_minor(self) -> u32 {
(self.0 & (!0 >> 12)) >> 12
}
pub fn get_patch(self) -> u32 {
self.0 & (!0 >> 20)
}
pub fn get_tuple(self) -> (u32, u32, u32, u32) {
(
self.get_major(),
self.get_minor(),
self.get_patch(),
self.get_variant(),
)
}
#[doc(alias = "ImpellerGetVersion")]
pub fn get_linked_version() -> Self {
Self(unsafe { sys::ImpellerGetVersion() })
}
pub fn sanity_check() -> bool {
Self::get_header_version() == Self::get_linked_version()
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerVulkanSwapchain")]
pub struct VkSwapChain(sys::ImpellerVulkanSwapchain);
impl Drop for VkSwapChain {
#[doc(alias = "ImpellerVulkanSwapchainRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerVulkanSwapchainRelease(self.0);
}
}
}
impl VkSwapChain {
#[doc(alias = "ImpellerVulkanSwapchainAcquireNextSurfaceNew")]
pub fn acquire_next_surface_new(&mut self) -> Option<Surface> {
let surface = unsafe { sys::ImpellerVulkanSwapchainAcquireNextSurfaceNew(self.0) };
if surface.is_null() {
None
} else {
Some(Surface(surface))
}
}
}
#[derive(Debug)]
#[doc(alias = "ImpellerContext")]
pub struct Context(sys::ImpellerContext, ContextType);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
enum ContextType {
Gl,
Vk,
Mtl,
}
impl Drop for Context {
#[doc(alias = "ImpellerContextRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerContextRelease(self.0);
}
}
}
unsafe extern "C" fn wrap_gl_proc_address<F: FnMut(&str) -> *mut std::os::raw::c_void>(
name: *const std::os::raw::c_char,
user_data: *mut std::os::raw::c_void,
) -> *mut std::os::raw::c_void {
let name = if name.is_null() {
c""
} else {
unsafe { std::ffi::CStr::from_ptr(name) }
};
let Ok(name) = name.to_str() else {
panic!("Invalid GL function name: {}", name.to_string_lossy());
};
(*(user_data as *mut F))(name)
}
unsafe extern "C" fn wrap_vk_proc_address<
F: FnMut(*mut std::os::raw::c_void, *const std::os::raw::c_char) -> *mut std::os::raw::c_void,
>(
vulkan_instance: *mut std::os::raw::c_void,
vulkan_proc_name: *const std::os::raw::c_char,
user_data: *mut std::os::raw::c_void,
) -> *mut std::os::raw::c_void {
(*(user_data as *mut F))(vulkan_instance, vulkan_proc_name)
}
impl Context {
#[must_use = "opengl context has scary lifetime requirements. So, prefer dropping it explicitly with `std::mem:drop`"]
#[doc(alias = "ImpellerContextCreateOpenGLESNew")]
pub unsafe fn new_opengl_es<F: FnMut(&str) -> *mut std::os::raw::c_void>(
mut gl_proc_address: F,
) -> Result<Context, &'static str> {
if !ImpellerVersion::sanity_check() {
return Err("Impeller version mismatch when creating opengl context");
}
let ctx = unsafe {
sys::ImpellerContextCreateOpenGLESNew(
ImpellerVersion::get_linked_version().0,
Some(wrap_gl_proc_address::<F>),
&raw mut gl_proc_address as *mut _,
)
};
if ctx.is_null() {
Err("ImpellerContextCreateOpenGLESNew returned null :(")
} else {
Ok(Self(ctx, ContextType::Gl))
}
}
pub unsafe fn wrap_fbo(
&mut self,
fbo: u64,
format: PixelFormat,
size: ISize,
) -> Option<Surface> {
assert_eq!(self.1, ContextType::Gl);
let surface = unsafe {
sys::ImpellerSurfaceCreateWrappedFBONew(self.0, fbo, format, cast_ref(&size))
};
if surface.is_null() {
None
} else {
Some(Surface(surface))
}
}
#[doc(alias = "ImpellerTextureCreateWithContentsNew")]
pub unsafe fn create_texture_with_rgba8(
&self,
contents: Cow<'static, [u8]>,
width: u32,
height: u32,
) -> Result<Texture, &'static str> {
if width == 0 || height == 0 {
return Err("width and height must be greater than zero");
}
let total_bytes = width as usize * height as usize * 4;
if contents.len() != total_bytes {
return Err("provided buffer size does not match expected size");
}
let mip_count = flutter_mip_count(width as f32, height as f32);
let t = unsafe {
let (mapping, user_data) = sys::ImpellerMapping::from_cow(contents);
sys::ImpellerTextureCreateWithContentsNew(
self.0,
&sys::ImpellerTextureDescriptor {
size: cast(ISize::new(width.into(), height.into())),
pixel_format: PixelFormat::RGBA8888,
mip_count,
},
&mapping,
user_data,
)
};
if t.is_null() {
Err("ImpellerTextureCreateWithContentsNew returned null")
} else {
Ok(Texture(t))
}
}
#[doc(alias = "ImpellerTextureCreateWithOpenGLTextureHandleNew")]
pub unsafe fn adopt_opengl_texture(
&self,
width: u32,
height: u32,
mip_count: u32,
handle: u64,
) -> Option<Texture> {
assert_eq!(self.1, ContextType::Gl);
let size = sys::ImpellerISize {
width: width.into(),
height: height.into(),
};
let t = sys::ImpellerTextureCreateWithOpenGLTextureHandleNew(
self.0,
&sys::ImpellerTextureDescriptor {
pixel_format: PixelFormat::RGBA8888,
size,
mip_count,
},
handle,
);
if t.is_null() {
None
} else {
Some(Texture(t))
}
}
#[doc(alias = "ImpellerContextCreateMetalNew")]
#[must_use = "don't just drop a context like that. They usually have scary lifetimes, so prefer dropping them with an explicit `std::mem::drop`"]
pub unsafe fn new_metal() -> Result<Context, &'static str> {
if !ImpellerVersion::sanity_check() {
return Err("ImpellerVersion::sanity_check failed");
}
let ctx = sys::ImpellerContextCreateMetalNew(ImpellerVersion::get_linked_version().0);
if ctx.is_null() {
Err("ImpellerContextCreateMetalNew returned null")
} else {
Ok(Self(ctx, ContextType::Mtl))
}
}
#[must_use = "don't just drop vulkan context like that :( It's lifetimes are scary, so prefer dropping it explicitly using `std::mem::drop`"]
#[doc(alias = "ImpellerContextCreateVulkanNew")]
pub unsafe fn new_vulkan<
F: FnMut(*mut std::os::raw::c_void, *const std::os::raw::c_char) -> *mut std::os::raw::c_void,
>(
enable_validation: bool,
mut proc_address_callback: F,
) -> Result<Context, &'static str> {
if !ImpellerVersion::sanity_check() {
return Err("ImpellerVersion::sanity_check failed");
}
let settings = sys::ImpellerContextVulkanSettings {
user_data: &raw mut proc_address_callback as *mut _,
proc_address_callback: Some(wrap_vk_proc_address::<F>),
enable_vulkan_validation: enable_validation,
};
let ctx =
sys::ImpellerContextCreateVulkanNew(ImpellerVersion::get_linked_version().0, &settings);
if ctx.is_null() {
Err("ImpellerContextCreateVulkanNew returned null")
} else {
Ok(Self(ctx, ContextType::Vk))
}
}
#[doc(alias = "ImpellerContextGetVulkanInfo")]
pub fn get_vulkan_info(&self) -> Result<VulkanInfo, &'static str> {
assert_eq!(self.1, ContextType::Vk);
let mut vulkan_info = VulkanInfo::default();
if unsafe { sys::ImpellerContextGetVulkanInfo(self.0, &mut vulkan_info) } {
Ok(vulkan_info)
} else {
Err("ImpellerContextGetVulkanInfo returned false. Is the context a Vulkan context?")
}
}
#[doc(alias = "ImpellerVulkanSwapchainCreateNew")]
pub unsafe fn create_new_vulkan_swapchain(
&self,
vulkan_surface_khr: *mut std::os::raw::c_void,
) -> Option<VkSwapChain> {
assert_eq!(self.1, ContextType::Vk);
let swapchain = sys::ImpellerVulkanSwapchainCreateNew(self.0, vulkan_surface_khr);
if swapchain.is_null() {
None
} else {
Some(VkSwapChain(swapchain))
}
}
pub unsafe fn wrap_metal_drawable(
&self,
metal_drawable: *mut std::os::raw::c_void,
) -> Option<Surface> {
assert_eq!(self.1, ContextType::Mtl);
let surface = sys::ImpellerSurfaceCreateWrappedMetalDrawableNew(self.0, metal_drawable);
if surface.is_null() {
None
} else {
Some(Surface(surface))
}
}
pub unsafe fn new_color_source_from_fragment_program(
&self,
frag_program: &FragmentProgram,
samplers: &[Texture],
uniform_data: &[u8],
) -> ColorSource {
let samplers_len = samplers.len();
let mut samplers: Vec<sys::ImpellerTexture> = samplers.iter().map(|t| t.0).collect();
let cs = unsafe {
sys::ImpellerColorSourceCreateFragmentProgramNew(
self.0,
frag_program.0,
if samplers_len == 0 {
std::ptr::null_mut()
} else {
samplers.as_mut_ptr()
},
samplers_len,
uniform_data.as_ptr(),
uniform_data.len(),
)
};
assert!(!cs.is_null());
ColorSource(cs)
}
pub unsafe fn new_image_filter_from_fragment_program(
&self,
frag_program: &FragmentProgram,
samplers: &[Texture],
uniform_data: &[u8],
) -> ImageFilter {
let samplers_len = samplers.len();
let mut samplers: Vec<sys::ImpellerTexture> = samplers.iter().map(|t| t.0).collect();
let cs = unsafe {
sys::ImpellerImageFilterCreateFragmentProgramNew(
self.0,
frag_program.0,
if samplers_len == 0 {
std::ptr::null_mut()
} else {
samplers.as_mut_ptr()
},
samplers_len,
uniform_data.as_ptr(),
uniform_data.len(),
)
};
assert!(!cs.is_null());
ImageFilter(cs)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerDisplayList")]
pub struct DisplayList(sys::ImpellerDisplayList);
unsafe impl Send for DisplayList {}
unsafe impl Sync for DisplayList {}
impl Clone for DisplayList {
#[doc(alias = "ImpellerDisplayListRetain")]
fn clone(&self) -> Self {
unsafe {
sys::ImpellerDisplayListRetain(self.0);
}
Self(self.0)
}
}
impl Drop for DisplayList {
fn drop(&mut self) {
unsafe {
sys::ImpellerDisplayListRelease(self.0);
}
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerDisplayListBuilder")]
pub struct DisplayListBuilder(sys::ImpellerDisplayListBuilder);
unsafe impl Send for DisplayListBuilder {}
unsafe impl Sync for DisplayListBuilder {}
impl Drop for DisplayListBuilder {
fn drop(&mut self) {
unsafe {
sys::ImpellerDisplayListBuilderRelease(self.0);
}
}
}
impl DisplayListBuilder {
#[doc(alias = "ImpellerDisplayListBuilderNew")]
pub fn new(cull_rect: Option<&Rect>) -> Self {
let result = unsafe {
sys::ImpellerDisplayListBuilderNew(cull_rect.map_or(std::ptr::null(), |r| cast_ref(r)))
};
assert!(!result.is_null(), "Failed to create display list builder");
Self(result)
}
#[must_use]
#[doc(alias = "ImpellerDisplayListBuilderCreateDisplayListNew")]
pub fn build(&mut self) -> Option<DisplayList> {
let d = unsafe { sys::ImpellerDisplayListBuilderCreateDisplayListNew(self.0) };
if d.is_null() {
None
} else {
Some(DisplayList(d))
}
}
#[doc(alias = "ImpellerDisplayListBuilderSave")]
pub fn save(&mut self) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderSave(self.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderSaveLayer")]
pub fn save_layer(
&mut self,
bounds: &Rect,
paint: Option<&Paint>,
backdrop: Option<&ImageFilter>,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderSaveLayer(
self.0,
cast_ref(bounds),
paint.map_or(std::ptr::null_mut(), |p| p.0),
backdrop.map_or(std::ptr::null_mut(), |b| b.0),
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderRestore")]
pub fn restore(&mut self) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderRestore(self.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderScale")]
pub fn scale(&mut self, x_scale: f32, y_scale: f32) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderScale(self.0, x_scale, y_scale);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderRotate")]
pub fn rotate(&mut self, angle_degrees: f32) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderRotate(self.0, angle_degrees);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderTranslate")]
pub fn translate(&mut self, x_translation: f32, y_translation: f32) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderTranslate(self.0, x_translation, y_translation);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderTransform")]
pub fn transform(&mut self, transform: &Matrix) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderTransform(self.0, cast_ref(transform));
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderSetTransform")]
pub fn set_transform(&mut self, transform: &Matrix) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderSetTransform(self.0, cast_ref(transform));
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderGetTransform")]
pub fn get_transform(&self) -> Matrix {
let mut out_transform = Matrix::default();
unsafe {
sys::ImpellerDisplayListBuilderGetTransform(
self.0,
bytemuck::cast_mut(&mut out_transform),
);
}
out_transform
}
#[doc(alias = "ImpellerDisplayListBuilderResetTransform")]
pub fn reset_transform(&mut self) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderResetTransform(self.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderGetSaveCount")]
pub fn get_save_count(&mut self) -> u32 {
unsafe { sys::ImpellerDisplayListBuilderGetSaveCount(self.0) }
}
#[doc(alias = "ImpellerDisplayListBuilderRestoreToCount")]
pub fn restore_to_count(&mut self, count: u32) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderRestoreToCount(self.0, count);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderClipRect")]
pub fn clip_rect(&mut self, rect: &Rect, op: ClipOperation) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderClipRect(self.0, cast_ref(rect), op);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderClipOval")]
pub fn clip_oval(&mut self, oval_bounds: &Rect, op: ClipOperation) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderClipOval(self.0, cast_ref(oval_bounds), op);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderClipRoundedRect")]
pub fn clip_rounded_rect(
&mut self,
rect: &Rect,
radii: &RoundingRadii,
op: ClipOperation,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderClipRoundedRect(
self.0,
cast_ref(rect),
&radii.into(),
op,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderClipPath")]
pub fn clip_path(&mut self, path: &Path, op: ClipOperation) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderClipPath(self.0, path.0, op);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawPaint")]
pub fn draw_paint(&mut self, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawPaint(self.0, paint.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawLine")]
pub fn draw_line(&mut self, from: Point, to: Point, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawLine(
self.0,
cast_ref(&from),
cast_ref(&to),
paint.0,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawDashedLine")]
pub fn draw_dashed_line(
&mut self,
from: Point,
to: Point,
on_length: f32,
off_length: f32,
paint: &Paint,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawDashedLine(
self.0,
cast_ref(&from),
cast_ref(&to),
on_length,
off_length,
paint.0,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawRect")]
pub fn draw_rect(&mut self, rect: &Rect, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawRect(self.0, cast_ref(rect), paint.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawOval")]
pub fn draw_oval(&mut self, oval_bounds: &Rect, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawOval(self.0, cast_ref(oval_bounds), paint.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawRoundedRect")]
pub fn draw_rounded_rect(
&mut self,
rect: &Rect,
radii: &RoundingRadii,
paint: &Paint,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawRoundedRect(
self.0,
cast_ref(rect),
&radii.into(),
paint.0,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawRoundedRectDifference")]
pub fn draw_rounded_rect_difference(
&mut self,
outer_rect: &Rect,
outer_radii: &RoundingRadii,
inner_rect: &Rect,
inner_radii: &RoundingRadii,
paint: &Paint,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawRoundedRectDifference(
self.0,
cast_ref(outer_rect),
&outer_radii.into(),
cast_ref(inner_rect),
&inner_radii.into(),
paint.0,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawPath")]
pub fn draw_path(&mut self, path: &Path, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawPath(self.0, path.0, paint.0);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawDisplayList")]
pub fn draw_display_list(&mut self, display_list: &DisplayList, opacity: f32) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawDisplayList(self.0, display_list.0, opacity);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawParagraph")]
pub fn draw_paragraph(&mut self, paragraph: &Paragraph, point: Point) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawParagraph(self.0, paragraph.0, cast_ref(&point));
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawShadow")]
pub fn draw_shadow(
&mut self,
path: &Path,
color: &Color,
elevation: f32,
occluder_is_transparent: bool,
device_pixel_ratio: f32,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawShadow(
self.0,
path.0,
cast_ref(color),
elevation,
occluder_is_transparent,
device_pixel_ratio,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawTexture")]
pub fn draw_texture(
&mut self,
texture: &Texture,
point: Point,
sampling: TextureSampling,
paint: &Paint,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawTexture(
self.0,
texture.0,
cast_ref(&point),
sampling,
paint.0,
);
}
self
}
#[doc(alias = "ImpellerDisplayListBuilderDrawTextureRect")]
pub fn draw_texture_rect(
&mut self,
texture: &Texture,
src_rect: &Rect,
dst_rect: &Rect,
sampling: TextureSampling,
paint: Option<&Paint>,
) -> &mut Self {
unsafe {
sys::ImpellerDisplayListBuilderDrawTextureRect(
self.0,
texture.0,
cast_ref(src_rect),
cast_ref(dst_rect),
sampling,
paint.map_or(std::ptr::null_mut(), |p| p.0),
);
}
self
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerPaint")]
pub struct Paint(sys::ImpellerPaint);
unsafe impl Send for Paint {}
unsafe impl Sync for Paint {}
impl Drop for Paint {
fn drop(&mut self) {
unsafe {
sys::ImpellerPaintRelease(self.0);
}
}
}
impl Default for Paint {
fn default() -> Self {
let p = unsafe { sys::ImpellerPaintNew() };
assert!(!p.is_null());
Self(p)
}
}
impl Paint {
#[doc(alias = "ImpellerPaintSetColor")]
pub fn set_color(&mut self, color: Color) -> &mut Self {
unsafe {
sys::ImpellerPaintSetColor(self.0, &color);
}
self
}
#[doc(alias = "ImpellerPaintSetBlendMode")]
pub fn set_blend_mode(&mut self, mode: BlendMode) -> &mut Self {
unsafe {
sys::ImpellerPaintSetBlendMode(self.0, mode);
}
self
}
#[doc(alias = "ImpellerPaintSetDrawStyle")]
pub fn set_draw_style(&mut self, style: DrawStyle) -> &mut Self {
unsafe {
sys::ImpellerPaintSetDrawStyle(self.0, style);
}
self
}
#[doc(alias = "ImpellerPaintSetStrokeCap")]
pub fn set_stroke_cap(&mut self, cap: StrokeCap) -> &mut Self {
unsafe {
sys::ImpellerPaintSetStrokeCap(self.0, cap);
}
self
}
#[doc(alias = "ImpellerPaintSetStrokeJoin")]
pub fn set_stroke_join(&mut self, join: StrokeJoin) -> &mut Self {
unsafe {
sys::ImpellerPaintSetStrokeJoin(self.0, join);
}
self
}
#[doc(alias = "ImpellerPaintSetStrokeWidth")]
pub fn set_stroke_width(&mut self, width: f32) -> &mut Self {
unsafe {
sys::ImpellerPaintSetStrokeWidth(self.0, width);
}
self
}
#[doc(alias = "ImpellerPaintSetStrokeMiter")]
pub fn set_stroke_miter(&mut self, miter: f32) -> &mut Self {
unsafe {
sys::ImpellerPaintSetStrokeMiter(self.0, miter);
}
self
}
#[doc(alias = "ImpellerPaintSetColorFilter")]
pub fn set_color_filter(&mut self, color_filter: &ColorFilter) -> &mut Self {
unsafe {
sys::ImpellerPaintSetColorFilter(self.0, color_filter.0);
}
self
}
#[doc(alias = "ImpellerPaintSetImageFilter")]
pub fn set_image_filter(&mut self, image_filter: &ImageFilter) -> &mut Self {
unsafe {
sys::ImpellerPaintSetImageFilter(self.0, image_filter.0);
}
self
}
#[doc(alias = "ImpellerPaintSetColorSource")]
pub fn set_color_source(&mut self, color_source: &ColorSource) -> &mut Self {
unsafe {
sys::ImpellerPaintSetColorSource(self.0, color_source.0);
}
self
}
#[doc(alias = "ImpellerPaintSetMaskFilter")]
pub fn set_mask_filter(&mut self, mask_filter: &MaskFilter) -> &mut Self {
unsafe {
sys::ImpellerPaintSetMaskFilter(self.0, mask_filter.0);
}
self
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerColorFilter")]
pub struct ColorFilter(sys::ImpellerColorFilter);
unsafe impl Send for ColorFilter {}
unsafe impl Sync for ColorFilter {}
impl Clone for ColorFilter {
fn clone(&self) -> Self {
unsafe {
sys::ImpellerColorFilterRetain(self.0);
}
Self(self.0)
}
}
impl Drop for ColorFilter {
fn drop(&mut self) {
unsafe {
sys::ImpellerColorFilterRelease(self.0);
}
}
}
impl ColorFilter {
#[doc(alias = "ImpellerColorFilterCreateBlendNew")]
pub fn new_blend(color: Color, blend_mode: BlendMode) -> Self {
unsafe { Self(sys::ImpellerColorFilterCreateBlendNew(&color, blend_mode)) }
}
#[doc(alias = "ImpellerColorFilterCreateColorMatrixNew")]
pub fn new_matrix(color_matrix: ColorMatrix) -> Self {
unsafe { Self(sys::ImpellerColorFilterCreateColorMatrixNew(&color_matrix)) }
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerColorSource")]
pub struct ColorSource(sys::ImpellerColorSource);
unsafe impl Send for ColorSource {}
unsafe impl Sync for ColorSource {}
impl Clone for ColorSource {
#[doc(alias = "ImpellerColorSourceRetain")]
fn clone(&self) -> Self {
unsafe {
sys::ImpellerColorSourceRetain(self.0);
}
Self(self.0)
}
}
impl Drop for ColorSource {
fn drop(&mut self) {
unsafe {
sys::ImpellerColorSourceRelease(self.0);
}
}
}
impl ColorSource {
#[doc(alias = "ImpellerColorSourceCreateLinearGradientNew")]
pub fn new_linear_gradient(
start: Point,
end: Point,
colors: &[Color],
stops: &[f32],
tile_mode: TileMode,
transformation: Option<&Matrix>,
) -> Self {
assert_eq!(colors.len(), stops.len());
assert!(!colors.is_empty());
let result = unsafe {
sys::ImpellerColorSourceCreateLinearGradientNew(
cast_ref(&start),
cast_ref(&end),
stops.len() as _,
colors.as_ptr(),
stops.as_ptr(),
tile_mode,
transformation.map_or(std::ptr::null(), |m| cast_ref(m)),
)
};
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerColorSourceCreateRadialGradientNew")]
pub fn new_radial_gradient(
center: Point,
radius: f32,
colors: &[Color],
stops: &[f32],
tile_mode: TileMode,
transformation: Option<&Matrix>,
) -> Self {
assert_eq!(colors.len(), stops.len());
assert!(!colors.is_empty());
let result = unsafe {
sys::ImpellerColorSourceCreateRadialGradientNew(
cast_ref(¢er),
radius,
stops.len() as _,
colors.as_ptr(),
stops.as_ptr(),
tile_mode,
transformation.map_or(std::ptr::null(), |m| cast_ref(m)),
)
};
assert!(!result.is_null());
Self(result)
}
#[allow(clippy::too_many_arguments)]
#[doc(alias = "ImpellerColorSourceCreateConicalGradientNew")]
pub fn new_conical_gradient(
start_center: Point,
start_radius: f32,
end_center: Point,
end_radius: f32,
colors: &[Color],
stops: &[f32],
tile_mode: TileMode,
transformation: Option<&Matrix>,
) -> Self {
assert_eq!(colors.len(), stops.len());
assert!(!colors.is_empty());
let result = unsafe {
sys::ImpellerColorSourceCreateConicalGradientNew(
cast_ref(&start_center),
start_radius,
cast_ref(&end_center),
end_radius,
stops.len() as _,
colors.as_ptr(),
stops.as_ptr(),
tile_mode,
transformation.map_or(std::ptr::null(), |m| cast_ref(m)),
)
};
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerColorSourceCreateSweepGradientNew")]
pub fn new_sweep_gradient(
center: Point,
start: f32,
end: f32,
colors: &[Color],
stops: &[f32],
tile_mode: TileMode,
transformation: Option<&Matrix>,
) -> Self {
assert_eq!(colors.len(), stops.len());
assert!(!colors.is_empty());
let result = unsafe {
sys::ImpellerColorSourceCreateSweepGradientNew(
cast_ref(¢er),
start,
end,
stops.len() as _,
colors.as_ptr(),
stops.as_ptr(),
tile_mode,
transformation.map_or(std::ptr::null(), |m| cast_ref(m)),
)
};
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerColorSourceCreateImageNew")]
pub fn new_image(
image: &Texture,
horizontal_tile_mode: TileMode,
vertical_tile_mode: TileMode,
sampling: TextureSampling,
transformation: Option<&Matrix>,
) -> Self {
let result = unsafe {
sys::ImpellerColorSourceCreateImageNew(
image.0,
horizontal_tile_mode,
vertical_tile_mode,
sampling,
transformation.map_or(std::ptr::null(), |m| cast_ref(m)),
)
};
assert!(!result.is_null());
Self(result)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerImageFilter")]
pub struct ImageFilter(sys::ImpellerImageFilter);
unsafe impl Send for ImageFilter {}
unsafe impl Sync for ImageFilter {}
impl Clone for ImageFilter {
fn clone(&self) -> Self {
unsafe {
sys::ImpellerImageFilterRetain(self.0);
}
Self(self.0)
}
}
impl Drop for ImageFilter {
fn drop(&mut self) {
unsafe {
sys::ImpellerImageFilterRelease(self.0);
}
}
}
impl ImageFilter {
#[doc(alias = "ImpellerImageFilterCreateBlurNew")]
pub fn new_blur(x_sigma: f32, y_sigma: f32, tile_mode: TileMode) -> Self {
let result = unsafe { sys::ImpellerImageFilterCreateBlurNew(x_sigma, y_sigma, tile_mode) };
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerImageFilterCreateDilateNew")]
pub fn new_dilate(x_radius: f32, y_radius: f32) -> Self {
let result = unsafe { sys::ImpellerImageFilterCreateDilateNew(x_radius, y_radius) };
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerImageFilterCreateErodeNew")]
pub fn new_erode(x_radius: f32, y_radius: f32) -> Self {
let result = unsafe { sys::ImpellerImageFilterCreateErodeNew(x_radius, y_radius) };
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerImageFilterCreateMatrixNew")]
pub fn new_matrix(matrix: &Matrix, sampling: TextureSampling) -> Self {
let result = unsafe { sys::ImpellerImageFilterCreateMatrixNew(cast_ref(matrix), sampling) };
assert!(!result.is_null());
Self(result)
}
#[doc(alias = "ImpellerImageFilterCreateComposeNew")]
pub fn new_compose(outer: &Self, inner: &Self) -> Self {
let result = unsafe { sys::ImpellerImageFilterCreateComposeNew(outer.0, inner.0) };
assert!(!result.is_null());
Self(result)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerMaskFilter")]
pub struct MaskFilter(sys::ImpellerMaskFilter);
unsafe impl Send for MaskFilter {}
unsafe impl Sync for MaskFilter {}
impl Clone for MaskFilter {
fn clone(&self) -> Self {
unsafe {
sys::ImpellerMaskFilterRetain(self.0);
}
Self(self.0)
}
}
impl Drop for MaskFilter {
fn drop(&mut self) {
unsafe {
sys::ImpellerMaskFilterRelease(self.0);
}
}
}
impl MaskFilter {
#[doc(alias = "ImpellerMaskFilterCreateBlurNew")]
pub fn new_blur(style: BlurStyle, sigma: f32) -> Self {
let result = unsafe { sys::ImpellerMaskFilterCreateBlurNew(style, sigma) };
assert!(!result.is_null());
Self(result)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerFragmentProgram")]
pub struct FragmentProgram(sys::ImpellerFragmentProgram);
unsafe impl Sync for FragmentProgram {}
unsafe impl Send for FragmentProgram {}
impl Clone for FragmentProgram {
#[doc(alias = "ImpellerFragmentProgramRetain")]
fn clone(&self) -> Self {
unsafe {
sys::ImpellerFragmentProgramRetain(self.0);
}
Self(self.0)
}
}
impl Drop for FragmentProgram {
#[doc(alias = "ImpellerFragmentProgramRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerFragmentProgramRelease(self.0);
}
}
}
impl FragmentProgram {
#[doc(alias = "ImpellerFragmentProgramNew")]
pub unsafe fn new(glsl_shader_compiled_by_impellerc: Cow<'static, [u8]>) -> Option<Self> {
let f = unsafe {
let (mapping, userdata) =
sys::ImpellerMapping::from_cow(glsl_shader_compiled_by_impellerc);
sys::ImpellerFragmentProgramNew(&mapping, userdata)
};
if f.is_null() {
None
} else {
Some(Self(f))
}
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerTypographyContext")]
pub struct TypographyContext(sys::ImpellerTypographyContext);
impl Drop for TypographyContext {
fn drop(&mut self) {
unsafe {
sys::ImpellerTypographyContextRelease(self.0);
}
}
}
impl Default for TypographyContext {
fn default() -> Self {
let result = unsafe { sys::ImpellerTypographyContextNew() };
assert!(!result.is_null());
Self(result)
}
}
impl TypographyContext {
#[doc(alias = "ImpellerTypographyContextRegisterFont")]
pub fn register_font(
&mut self,
font_data: Cow<'static, [u8]>,
family_name_alias: Option<&str>,
) -> Result<(), &'static str> {
let family_name_alias = if let Some(s) = family_name_alias {
Some(std::ffi::CString::new(s).map_err(|_| "the family name alias has a null byte")?)
} else {
None
};
let result = unsafe {
let (mapping, userdata) = sys::ImpellerMapping::from_cow(font_data);
sys::ImpellerTypographyContextRegisterFont(
self.0,
&mapping,
userdata,
family_name_alias
.as_ref()
.map_or(std::ptr::null(), |s| s.as_ptr()),
)
};
std::mem::drop(family_name_alias);
result.then_some(()).ok_or("Failed to register font")
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerParagraph")]
pub struct Paragraph(sys::ImpellerParagraph);
unsafe impl Send for Paragraph {}
unsafe impl Sync for Paragraph {}
impl Clone for Paragraph {
fn clone(&self) -> Self {
unsafe {
sys::ImpellerParagraphRetain(self.0);
}
Self(self.0)
}
}
impl Drop for Paragraph {
fn drop(&mut self) {
unsafe {
sys::ImpellerParagraphRelease(self.0);
}
}
}
impl Paragraph {
#[doc(alias = "ImpellerParagraphGetMaxWidth")]
pub fn get_max_width(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetMaxWidth(self.0) }
}
#[doc(alias = "ImpellerParagraphGetHeight")]
pub fn get_height(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetHeight(self.0) }
}
#[doc(alias = "ImpellerParagraphGetLongestLineWidth")]
pub fn get_longest_line_width(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetLongestLineWidth(self.0) }
}
#[doc(alias = "ImpellerParagraphGetMinIntrinsicWidth")]
pub fn get_min_intrinsic_width(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetMinIntrinsicWidth(self.0) }
}
#[doc(alias = "ImpellerParagraphGetMaxIntrinsicWidth")]
pub fn get_max_intrinsic_width(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetMaxIntrinsicWidth(self.0) }
}
#[doc(alias = "ImpellerParagraphGetIdeographicBaseline")]
pub fn get_ideographic_baseline(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetIdeographicBaseline(self.0) }
}
#[doc(alias = "ImpellerParagraphGetAlphabeticBaseline")]
pub fn get_alphabetic_baseline(&self) -> f32 {
unsafe { sys::ImpellerParagraphGetAlphabeticBaseline(self.0) }
}
#[doc(alias = "ImpellerParagraphGetLineCount")]
pub fn get_line_count(&self) -> u32 {
unsafe { sys::ImpellerParagraphGetLineCount(self.0) }
}
#[doc(alias = "ImpellerParagraphGetWordBoundary")]
pub fn get_word_boundary_utf16(&self, code_unit_index: usize) -> Range {
let mut range = Range::default();
unsafe { sys::ImpellerParagraphGetWordBoundary(self.0, code_unit_index, &raw mut range) };
range
}
#[doc(alias = "ImpellerParagraphGetLineMetrics")]
pub fn get_line_metrics(&self) -> Option<LineMetrics> {
let ptr = unsafe { sys::ImpellerParagraphGetLineMetrics(self.0) };
if ptr.is_null() {
None
} else {
unsafe { sys::ImpellerLineMetricsRetain(ptr) };
Some(LineMetrics(ptr))
}
}
#[doc(alias = "ImpellerParagraphCreateGlyphInfoAtCodeUnitIndexNew")]
pub fn create_glyph_info_at_code_unit_index_utf16(
&self,
code_unit_index: usize,
) -> Option<GlyphInfo> {
let ptr = unsafe {
sys::ImpellerParagraphCreateGlyphInfoAtCodeUnitIndexNew(self.0, code_unit_index)
};
if ptr.is_null() {
None
} else {
Some(GlyphInfo(ptr))
}
}
#[doc(alias = "ImpellerParagraphCreateGlyphInfoAtParagraphCoordinatesNew")]
pub fn create_glyph_info_at_paragraph_coordinates(&self, x: f64, y: f64) -> Option<GlyphInfo> {
let ptr =
unsafe { sys::ImpellerParagraphCreateGlyphInfoAtParagraphCoordinatesNew(self.0, x, y) };
if ptr.is_null() {
None
} else {
Some(GlyphInfo(ptr))
}
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerLineMetrics")]
pub struct LineMetrics(sys::ImpellerLineMetrics);
unsafe impl Send for LineMetrics {}
unsafe impl Sync for LineMetrics {}
impl Clone for LineMetrics {
#[doc(alias = "ImpellerLineMetricsRetain")]
fn clone(&self) -> Self {
unsafe {
sys::ImpellerLineMetricsRetain(self.0);
}
Self(self.0)
}
}
impl Drop for LineMetrics {
#[doc(alias = "ImpellerLineMetricsRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerLineMetricsRelease(self.0);
}
}
}
impl LineMetrics {
#[doc(alias = "ImpellerLineMetricsGetUnscaledAscent")]
pub fn get_unscaled_ascent(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetUnscaledAscent(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetAscent")]
pub fn get_ascent(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetAscent(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetDescent")]
pub fn get_descent(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetDescent(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetBaseline")]
pub fn get_baseline(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetBaseline(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsIsHardbreak")]
pub fn is_hardbreak(&self, line: usize) -> bool {
unsafe { sys::ImpellerLineMetricsIsHardbreak(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetWidth")]
pub fn get_width(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetWidth(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetHeight")]
pub fn get_height(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetHeight(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetLeft")]
pub fn get_left(&self, line: usize) -> f64 {
unsafe { sys::ImpellerLineMetricsGetLeft(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetCodeUnitStartIndex")]
pub fn get_code_unit_start_index_utf16(&self, line: usize) -> usize {
unsafe { sys::ImpellerLineMetricsGetCodeUnitStartIndex(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetCodeUnitEndIndex")]
pub fn get_code_unit_end_index_utf16(&self, line: usize) -> usize {
unsafe { sys::ImpellerLineMetricsGetCodeUnitEndIndex(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetCodeUnitEndIndexExcludingWhitespace")]
pub fn get_code_unit_end_index_excluding_whitespace_utf16(&self, line: usize) -> usize {
unsafe { sys::ImpellerLineMetricsGetCodeUnitEndIndexExcludingWhitespace(self.0, line) }
}
#[doc(alias = "ImpellerLineMetricsGetCodeUnitEndIndexIncludingNewline")]
pub fn get_code_unit_end_index_including_newline_utf16(&self, line: usize) -> usize {
unsafe { sys::ImpellerLineMetricsGetCodeUnitEndIndexIncludingNewline(self.0, line) }
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerGlyphInfo")]
pub struct GlyphInfo(sys::ImpellerGlyphInfo);
impl Clone for GlyphInfo {
#[doc(alias = "ImpellerGlyphInfoRetain")]
fn clone(&self) -> Self {
unsafe { sys::ImpellerGlyphInfoRetain(self.0) };
GlyphInfo(self.0)
}
}
unsafe impl Send for GlyphInfo {}
unsafe impl Sync for GlyphInfo {}
impl Drop for GlyphInfo {
#[doc(alias = "ImpellerGlyphInfoRelease")]
fn drop(&mut self) {
unsafe { sys::ImpellerGlyphInfoRelease(self.0) };
}
}
impl GlyphInfo {
#[doc(alias = "ImpellerGlyphInfoGetGraphemeClusterCodeUnitRangeBegin")]
pub fn get_grapheme_cluster_code_unit_range_begin_utf16(&self) -> usize {
unsafe { sys::ImpellerGlyphInfoGetGraphemeClusterCodeUnitRangeBegin(self.0) }
}
#[doc(alias = "ImpellerGlyphInfoGetGraphemeClusterCodeUnitRangeEnd")]
pub fn get_grapheme_cluster_code_unit_range_end_utf16(&self) -> usize {
unsafe { sys::ImpellerGlyphInfoGetGraphemeClusterCodeUnitRangeEnd(self.0) }
}
#[doc(alias = "ImpellerGlyphInfoGetGraphemeClusterBounds")]
pub fn get_grapheme_cluster_bounds(&self) -> Rect {
let mut rect = crate::sys::ImpellerRect::default();
unsafe { sys::ImpellerGlyphInfoGetGraphemeClusterBounds(self.0, &raw mut rect) };
cast(rect)
}
#[doc(alias = "ImpellerGlyphInfoIsEllipsis")]
pub fn is_ellipsis(&self) -> bool {
unsafe { sys::ImpellerGlyphInfoIsEllipsis(self.0) }
}
#[doc(alias = "ImpellerGlyphInfoGetTextDirection")]
pub fn get_text_direction(&self) -> TextDirection {
unsafe { sys::ImpellerGlyphInfoGetTextDirection(self.0) }
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerParagraphBuilder")]
pub struct ParagraphBuilder(sys::ImpellerParagraphBuilder);
impl Drop for ParagraphBuilder {
#[doc(alias = "ImpellerParagraphBuilderRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerParagraphBuilderRelease(self.0);
}
}
}
impl ParagraphBuilder {
#[doc(alias = "ImpellerParagraphBuilderNew")]
pub fn new(context: &TypographyContext) -> Option<ParagraphBuilder> {
let result = unsafe { sys::ImpellerParagraphBuilderNew(context.0) };
(!result.is_null()).then_some(ParagraphBuilder(result))
}
#[doc(alias = "ImpellerParagraphBuilderPushStyle")]
pub fn push_style(&mut self, style: &ParagraphStyle) -> &mut Self {
unsafe {
sys::ImpellerParagraphBuilderPushStyle(self.0, style.0);
}
self
}
#[doc(alias = "ImpellerParagraphBuilderPopStyle")]
pub fn pop_style(&mut self) -> &mut Self {
unsafe {
sys::ImpellerParagraphBuilderPopStyle(self.0);
}
self
}
#[doc(alias = "ImpellerParagraphBuilderAddText")]
pub fn add_text(&mut self, text: &str) -> &mut Self {
unsafe {
sys::ImpellerParagraphBuilderAddText(
self.0,
text.as_ptr(),
text.len().try_into().unwrap(),
);
}
self
}
#[must_use]
#[doc(alias = "ImpellerParagraphBuilderBuildParagraphNew")]
pub fn build(self, width: f32) -> Option<Paragraph> {
let result = unsafe { sys::ImpellerParagraphBuilderBuildParagraphNew(self.0, width) };
(!result.is_null()).then_some(Paragraph(result))
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc = "ImpellerParagraphStyle"]
pub struct ParagraphStyle(sys::ImpellerParagraphStyle);
unsafe impl Send for ParagraphStyle {}
unsafe impl Sync for ParagraphStyle {}
impl Drop for ParagraphStyle {
fn drop(&mut self) {
unsafe {
sys::ImpellerParagraphStyleRelease(self.0);
}
}
}
impl Default for ParagraphStyle {
fn default() -> Self {
let result = unsafe { sys::ImpellerParagraphStyleNew() };
assert!(!result.is_null());
Self(result)
}
}
impl ParagraphStyle {
#[doc(alias = "ImpellerParagraphStyleSetForeground")]
pub fn set_foreground(&mut self, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetForeground(self.0, paint.0);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetBackground")]
pub fn set_background(&mut self, paint: &Paint) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetBackground(self.0, paint.0);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetFontWeight")]
pub fn set_font_weight(&mut self, weight: FontWeight) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetFontWeight(self.0, weight);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetFontStyle")]
pub fn set_font_style(&mut self, style: FontStyle) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetFontStyle(self.0, style);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetFontFamily")]
pub fn set_font_family(&mut self, family_name: &str) -> &mut Self {
let family_name =
std::ffi::CString::new(family_name).expect("failed to create Cstring from family name");
unsafe {
sys::ImpellerParagraphStyleSetFontFamily(self.0, family_name.as_ptr());
}
std::mem::drop(family_name);
self
}
#[doc(alias = "ImpellerParagraphStyleSetFontSize")]
pub fn set_font_size(&mut self, size: f32) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetFontSize(self.0, size);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetHeight")]
pub fn set_height(&mut self, height: f32) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetHeight(self.0, height);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetTextAlignment")]
pub fn set_text_alignment(&mut self, align: TextAlignment) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetTextAlignment(self.0, align);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetTextDirection")]
pub fn set_text_direction(&mut self, direction: TextDirection) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetTextDirection(self.0, direction);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetTextDecoration")]
pub fn set_text_decoration(
&mut self,
decoration_type: TextDecorationType,
color: &Color,
style: TextDecorationStyle,
thickness_multiplier: f32,
) -> &mut Self {
let decoration = sys::ImpellerTextDecoration {
types: decoration_type.bits(),
style,
color: *color,
thickness_multiplier,
};
unsafe {
sys::ImpellerParagraphStyleSetTextDecoration(self.0, &raw const decoration);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetMaxLines")]
pub fn set_max_lines(&mut self, max_lines: u32) -> &mut Self {
unsafe {
sys::ImpellerParagraphStyleSetMaxLines(self.0, max_lines);
}
self
}
#[doc(alias = "ImpellerParagraphStyleSetLocale")]
pub fn set_locale(&mut self, locale: &str) -> &mut Self {
let locale = std::ffi::CString::new(locale).expect("failed to create Cstring from locale");
unsafe {
sys::ImpellerParagraphStyleSetLocale(self.0, locale.as_ptr());
}
std::mem::drop(locale);
self
}
#[doc(alias = "ImpellerParagraphStyleSetEllipsis")]
pub fn set_ellipsis(&mut self, ellipsis: Option<&str>) -> &mut Self {
let ellipsis = ellipsis.map(|ellipsis| {
std::ffi::CString::new(ellipsis).expect("failed to create cstr from ellipsis str")
});
unsafe {
sys::ImpellerParagraphStyleSetEllipsis(
self.0,
ellipsis
.as_ref()
.map(|c| c.as_ptr())
.unwrap_or(std::ptr::null()),
);
}
std::mem::drop(ellipsis);
self
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc(alias = "ImpellerPath")]
pub struct Path(sys::ImpellerPath);
unsafe impl Send for Path {}
unsafe impl Sync for Path {}
impl Clone for Path {
fn clone(&self) -> Self {
unsafe {
sys::ImpellerPathRetain(self.0);
}
Self(self.0)
}
}
impl Drop for Path {
fn drop(&mut self) {
unsafe {
sys::ImpellerPathRelease(self.0);
}
}
}
impl Path {
#[doc(alias = "ImpellerPathGetBounds")]
pub fn get_bounds(&self) -> Rect {
let mut rect = sys::ImpellerRect::default();
unsafe {
sys::ImpellerPathGetBounds(self.0, &raw mut rect);
}
cast(rect)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc = "ImpellerPathBuilder"]
pub struct PathBuilder(sys::ImpellerPathBuilder);
unsafe impl Send for PathBuilder {}
unsafe impl Sync for PathBuilder {}
impl Drop for PathBuilder {
#[doc(alias = "ImpellerPathBuilderRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerPathBuilderRelease(self.0);
}
}
}
impl Default for PathBuilder {
#[doc(alias = "ImpellerPathBuilderNew")]
fn default() -> Self {
let p = unsafe { sys::ImpellerPathBuilderNew() };
assert!(!p.is_null());
Self(p)
}
}
impl PathBuilder {
#[doc = "ImpellerPathBuilderMoveTo"]
pub fn move_to(&mut self, location: Point) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderMoveTo(self.0, cast_ref(&location));
}
self
}
#[doc = "ImpellerPathBuilderLineTo"]
pub fn line_to(&mut self, location: Point) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderLineTo(self.0, cast_ref(&location));
}
self
}
#[doc = "ImpellerPathBuilderQuadraticCurveTo"]
pub fn quadratic_curve_to(&mut self, control_point: Point, end_point: Point) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderQuadraticCurveTo(
self.0,
cast_ref(&control_point),
cast_ref(&end_point),
);
}
self
}
#[doc = "ImpellerPathBuilderCubicCurveTo"]
pub fn cubic_curve_to(
&mut self,
control_point_1: Point,
control_point_2: Point,
end_point: Point,
) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderCubicCurveTo(
self.0,
cast_ref(&control_point_1),
cast_ref(&control_point_2),
cast_ref(&end_point),
);
}
self
}
#[doc = "ImpellerPathBuilderAddRect"]
pub fn add_rect(&mut self, rect: &Rect) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderAddRect(self.0, cast_ref(rect));
}
self
}
#[doc = "ImpellerPathBuilderAddArc"]
pub fn add_arc(
&mut self,
oval_bounds: &Rect,
start_angle_degrees: f32,
end_angle_degrees: f32,
) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderAddArc(
self.0,
cast_ref(oval_bounds),
start_angle_degrees,
end_angle_degrees,
);
}
self
}
#[doc = "ImpellerPathBuilderAddOval"]
pub fn add_oval(&mut self, oval_bounds: &Rect) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderAddOval(self.0, cast_ref(oval_bounds));
}
self
}
#[doc = "ImpellerPathBuilderAddRoundedRect"]
pub fn add_rounded_rect(
&mut self,
oval_bounds: &Rect,
rounding_radii: &RoundingRadii,
) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderAddRoundedRect(
self.0,
cast_ref(oval_bounds),
&rounding_radii.into(),
);
}
self
}
#[doc = "ImpellerPathBuilderClose"]
pub fn close(&mut self) -> &mut Self {
unsafe {
sys::ImpellerPathBuilderClose(self.0);
}
self
}
#[doc = "ImpellerPathBuilderCopyPathNew"]
pub fn copy_path_new(&mut self, fill: FillType) -> Path {
let p = unsafe { sys::ImpellerPathBuilderCopyPathNew(self.0, fill) };
assert!(!p.is_null());
Path(p)
}
#[doc = "ImpellerPathBuilderTakePathNew"]
pub fn take_path_new(&mut self, fill: FillType) -> Path {
let p = unsafe { sys::ImpellerPathBuilderTakePathNew(self.0, fill) };
assert!(!p.is_null());
Path(p)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc = "ImpellerSurface"]
pub struct Surface(sys::ImpellerSurface);
impl Drop for Surface {
#[doc(alias = "ImpellerSurfaceRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerSurfaceRelease(self.0);
}
}
}
impl Surface {
#[doc = "ImpellerSurfaceDrawDisplayList"]
pub fn draw_display_list(&mut self, display_list: &DisplayList) -> Result<(), &'static str> {
unsafe { sys::ImpellerSurfaceDrawDisplayList(self.0, display_list.0) }
.then_some(())
.ok_or("failed to draw to surface")
}
#[doc = "ImpellerSurfacePresent"]
pub fn present(self) -> Result<(), &'static str> {
unsafe { sys::ImpellerSurfacePresent(self.0) }
.then_some(())
.ok_or("failed to present surface")
}
}
#[derive(Debug)]
#[repr(transparent)]
#[doc = "ImpellerTexture"]
pub struct Texture(sys::ImpellerTexture);
unsafe impl Sync for Texture {}
unsafe impl Send for Texture {}
impl Clone for Texture {
#[doc(alias = "ImpellerTextureRetain")]
fn clone(&self) -> Self {
unsafe {
sys::ImpellerTextureRetain(self.0);
}
Self(self.0)
}
}
impl Drop for Texture {
#[doc(alias = "ImpellerTextureRelease")]
fn drop(&mut self) {
unsafe {
sys::ImpellerTextureRelease(self.0);
}
}
}
impl Texture {
#[doc = "ImpellerTextureGetOpenGLHandle"]
pub fn get_opengl_handle(&self) -> u64 {
unsafe { sys::ImpellerTextureGetOpenGLHandle(self.0) }
}
}
pub fn flutter_mip_count(width: f32, height: f32) -> u32 {
let mut result = width.log2().ceil().max(height.log2().ceil()) as u32;
if result > 1 {
result -= 1;
}
std::cmp::max(result, 1)
}
impl Color {
pub const TRANSPARENT: Self = Self::new_srgba(0.0, 0.0, 0.0, 0.0);
pub const fn new_srgb(red: f32, green: f32, blue: f32) -> Self {
Self::new_srgba(red, green, blue, 1.0)
}
pub const fn new_srgba(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
Self {
red,
green,
blue,
alpha,
color_space: ColorSpace::SRGB,
}
}
pub const fn with_alpha(self, alpha: f32) -> Self {
Self { alpha, ..self }
}
}
bitflags::bitflags! {
pub struct TextDecorationType: std::ffi::c_int {
const NONE = sys::TextDecorationType::None as std::ffi::c_int;
const UNDERLINE = sys::TextDecorationType::Underline as std::ffi::c_int;
const OVERLINE = sys::TextDecorationType::Overline as std::ffi::c_int;
const LINETHROUGH = sys::TextDecorationType::LineThrough as std::ffi::c_int;
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct RoundingRadii {
pub top_left: Point,
pub top_right: Point,
pub bottom_left: Point,
pub bottom_right: Point,
}
impl From<&RoundingRadii> for sys::ImpellerRoundingRadii {
fn from(value: &RoundingRadii) -> Self {
Self {
top_left: sys::ImpellerPoint {
x: value.top_left.x,
y: value.top_left.y,
},
top_right: sys::ImpellerPoint {
x: value.top_right.x,
y: value.top_right.y,
},
bottom_left: sys::ImpellerPoint {
x: value.bottom_left.x,
y: value.bottom_left.y,
},
bottom_right: sys::ImpellerPoint {
x: value.bottom_right.x,
y: value.bottom_right.y,
},
}
}
}
impl sys::ImpellerMapping {
unsafe fn from_cow(contents: Cow<'static, [u8]>) -> (Self, *mut std::ffi::c_void) {
let contents: Box<Cow<'static, [u8]>> = Box::new(contents);
let data: *const u8 = contents.as_ptr();
let length = contents.len() as u64;
let user_data: *mut Cow<'static, [u8]> = Box::leak(contents);
extern "C" fn boxed_cow_slice_dropper(on_release_user_data: *mut std::ffi::c_void) {
let contents: Box<Cow<'static, [u8]>> =
unsafe { Box::from_raw(on_release_user_data as *mut _) };
drop(contents);
}
(
sys::ImpellerMapping {
data,
length,
on_release: Some(boxed_cow_slice_dropper),
},
user_data.cast(),
)
}
}
unsafe impl bytemuck::Zeroable for sys::ImpellerISize {}
unsafe impl bytemuck::Pod for sys::ImpellerISize {}
unsafe impl bytemuck::Zeroable for sys::ImpellerPoint {}
unsafe impl bytemuck::Pod for sys::ImpellerPoint {}
unsafe impl bytemuck::Zeroable for sys::ImpellerSize {}
unsafe impl bytemuck::Pod for sys::ImpellerSize {}
unsafe impl bytemuck::Zeroable for sys::ImpellerMatrix {}
unsafe impl bytemuck::Pod for sys::ImpellerMatrix {}
unsafe impl bytemuck::Zeroable for sys::ImpellerRect {}
unsafe impl bytemuck::Pod for sys::ImpellerRect {}
unsafe impl bytemuck::Zeroable for sys::ImpellerColor {}
unsafe impl bytemuck::Pod for sys::ImpellerColor {}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_version() {
assert_eq!(
ImpellerVersion::get_header_version().get_variant(),
sys::IMPELLER_VERSION_VARIANT
);
assert_eq!(
ImpellerVersion::get_linked_version().get_variant(),
sys::IMPELLER_VERSION_VARIANT
);
assert_eq!(
ImpellerVersion::get_header_version().get_major(),
sys::IMPELLER_VERSION_MAJOR
);
assert_eq!(
ImpellerVersion::get_linked_version().get_major(),
sys::IMPELLER_VERSION_MAJOR
);
assert_eq!(
ImpellerVersion::get_header_version().get_minor(),
sys::IMPELLER_VERSION_MINOR
);
assert_eq!(
ImpellerVersion::get_linked_version().get_minor(),
sys::IMPELLER_VERSION_MINOR
);
assert_eq!(
ImpellerVersion::get_header_version().get_patch(),
sys::IMPELLER_VERSION_PATCH
);
assert_eq!(
ImpellerVersion::get_linked_version().get_patch(),
sys::IMPELLER_VERSION_PATCH
);
}
}