use core::ptr::NonNull;
use std::ffi::c_void;
use crate::ffi::{
noesis_base_component_release, noesis_blur_effect_create, noesis_blur_effect_get_radius,
noesis_blur_effect_set_radius, noesis_drop_shadow_effect_create, noesis_drop_shadow_effect_get,
noesis_drop_shadow_effect_set_blur_radius, noesis_drop_shadow_effect_set_color,
noesis_drop_shadow_effect_set_direction, noesis_drop_shadow_effect_set_opacity,
noesis_drop_shadow_effect_set_shadow_depth, noesis_gradient_brush_add_stop,
noesis_gradient_brush_get_mapping_mode, noesis_gradient_brush_get_spread_method,
noesis_gradient_brush_get_stop, noesis_gradient_brush_set_mapping_mode,
noesis_gradient_brush_set_spread_method, noesis_gradient_brush_stop_count,
noesis_image_brush_create, noesis_image_brush_get_image_source,
noesis_image_brush_set_image_source, noesis_linear_gradient_brush_create,
noesis_linear_gradient_brush_get_points, noesis_linear_gradient_brush_set_end_point,
noesis_linear_gradient_brush_set_start_point, noesis_radial_gradient_brush_create,
noesis_radial_gradient_brush_get_radius, noesis_radial_gradient_brush_set_center,
noesis_radial_gradient_brush_set_gradient_origin, noesis_radial_gradient_brush_set_radius,
noesis_solid_color_brush_create, noesis_solid_color_brush_get_color,
noesis_solid_color_brush_set_color, noesis_tile_brush_get_alignment_x,
noesis_tile_brush_get_alignment_y, noesis_tile_brush_get_stretch,
noesis_tile_brush_get_tile_mode, noesis_tile_brush_get_viewbox,
noesis_tile_brush_get_viewbox_units, noesis_tile_brush_get_viewport,
noesis_tile_brush_get_viewport_units, noesis_tile_brush_set_alignment_x,
noesis_tile_brush_set_alignment_y, noesis_tile_brush_set_stretch,
noesis_tile_brush_set_tile_mode, noesis_tile_brush_set_viewbox,
noesis_tile_brush_set_viewbox_units, noesis_tile_brush_set_viewport,
noesis_tile_brush_set_viewport_units, noesis_visual_brush_create,
noesis_visual_brush_get_visual, noesis_visual_brush_set_visual,
};
pub trait Brush {
fn brush_raw(&self) -> *mut c_void;
}
pub trait Effect {
fn effect_raw(&self) -> *mut c_void;
}
macro_rules! base_component_handle {
($name:ident) => {
unsafe impl Send for $name {}
impl $name {
#[must_use]
pub fn raw(&self) -> *mut c_void {
self.ptr.as_ptr()
}
}
impl Drop for $name {
fn drop(&mut self) {
unsafe { noesis_base_component_release(self.ptr.as_ptr()) }
}
}
};
}
pub struct SolidColorBrush {
ptr: NonNull<c_void>,
}
base_component_handle!(SolidColorBrush);
impl SolidColorBrush {
#[must_use]
pub fn new(rgba: [f32; 4]) -> Self {
let ptr = unsafe { noesis_solid_color_brush_create(rgba.as_ptr()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_solid_color_brush_create returned null"),
}
}
pub fn set_color(&mut self, rgba: [f32; 4]) {
unsafe {
noesis_solid_color_brush_set_color(self.ptr.as_ptr(), rgba.as_ptr());
}
}
#[must_use]
pub fn color(&self) -> [f32; 4] {
let mut out = [0.0f32; 4];
unsafe {
noesis_solid_color_brush_get_color(self.ptr.as_ptr(), out.as_mut_ptr());
}
out
}
}
impl Brush for SolidColorBrush {
fn brush_raw(&self) -> *mut c_void {
self.raw()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct GradientStop {
pub offset: f32,
pub color: [f32; 4],
}
impl GradientStop {
#[must_use]
pub fn new(offset: f32, color: [f32; 4]) -> Self {
Self { offset, color }
}
}
fn gradient_add_stop(ptr: *mut c_void, stop: GradientStop) -> Option<usize> {
let idx = unsafe { noesis_gradient_brush_add_stop(ptr, stop.offset, stop.color.as_ptr()) };
(idx >= 0).then_some(idx as usize)
}
fn gradient_stop_count(ptr: *mut c_void) -> usize {
let n = unsafe { noesis_gradient_brush_stop_count(ptr) };
n.max(0) as usize
}
fn gradient_get_stop(ptr: *mut c_void, index: usize) -> Option<GradientStop> {
let mut offset = 0.0f32;
let mut color = [0.0f32; 4];
let ok = unsafe {
noesis_gradient_brush_get_stop(
ptr,
index as u32,
&mut offset as *mut f32,
color.as_mut_ptr(),
)
};
ok.then_some(GradientStop { offset, color })
}
fn gradient_set_spread_method(ptr: *mut c_void, method: GradientSpreadMethod) -> bool {
unsafe { noesis_gradient_brush_set_spread_method(ptr, method as i32) }
}
fn gradient_spread_method(ptr: *mut c_void) -> Option<GradientSpreadMethod> {
GradientSpreadMethod::from_ordinal(unsafe { noesis_gradient_brush_get_spread_method(ptr) })
}
fn gradient_set_mapping_mode(ptr: *mut c_void, mode: BrushMappingMode) -> bool {
unsafe { noesis_gradient_brush_set_mapping_mode(ptr, mode as i32) }
}
fn gradient_mapping_mode(ptr: *mut c_void) -> Option<BrushMappingMode> {
BrushMappingMode::from_ordinal(unsafe { noesis_gradient_brush_get_mapping_mode(ptr) })
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum GradientSpreadMethod {
Pad = 0,
Reflect = 1,
Repeat = 2,
}
impl GradientSpreadMethod {
fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::Pad),
1 => Some(Self::Reflect),
2 => Some(Self::Repeat),
_ => None,
}
}
}
pub struct LinearGradientBrush {
ptr: NonNull<c_void>,
}
base_component_handle!(LinearGradientBrush);
impl Default for LinearGradientBrush {
fn default() -> Self {
Self::new()
}
}
impl LinearGradientBrush {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_linear_gradient_brush_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_linear_gradient_brush_create returned null"),
}
}
pub fn set_start_point(&mut self, x: f32, y: f32) {
unsafe { noesis_linear_gradient_brush_set_start_point(self.ptr.as_ptr(), x, y) };
}
pub fn set_end_point(&mut self, x: f32, y: f32) {
unsafe { noesis_linear_gradient_brush_set_end_point(self.ptr.as_ptr(), x, y) };
}
#[must_use]
pub fn points(&self) -> ([f32; 2], [f32; 2]) {
let mut out = [0.0f32; 4];
unsafe { noesis_linear_gradient_brush_get_points(self.ptr.as_ptr(), out.as_mut_ptr()) };
([out[0], out[1]], [out[2], out[3]])
}
pub fn add_stop(&mut self, stop: GradientStop) -> Option<usize> {
gradient_add_stop(self.ptr.as_ptr(), stop)
}
#[must_use]
pub fn stop_count(&self) -> usize {
gradient_stop_count(self.ptr.as_ptr())
}
#[must_use]
pub fn stop(&self, index: usize) -> Option<GradientStop> {
gradient_get_stop(self.ptr.as_ptr(), index)
}
pub fn set_spread_method(&mut self, method: GradientSpreadMethod) -> bool {
gradient_set_spread_method(self.ptr.as_ptr(), method)
}
#[must_use]
pub fn spread_method(&self) -> Option<GradientSpreadMethod> {
gradient_spread_method(self.ptr.as_ptr())
}
pub fn set_mapping_mode(&mut self, mode: BrushMappingMode) -> bool {
gradient_set_mapping_mode(self.ptr.as_ptr(), mode)
}
#[must_use]
pub fn mapping_mode(&self) -> Option<BrushMappingMode> {
gradient_mapping_mode(self.ptr.as_ptr())
}
pub fn builder() -> LinearGradientBrushBuilder {
LinearGradientBrushBuilder {
brush: LinearGradientBrush::new(),
}
}
}
#[must_use]
pub struct LinearGradientBrushBuilder {
brush: LinearGradientBrush,
}
impl LinearGradientBrushBuilder {
pub fn start(mut self, x: f32, y: f32) -> Self {
self.brush.set_start_point(x, y);
self
}
pub fn end(mut self, x: f32, y: f32) -> Self {
self.brush.set_end_point(x, y);
self
}
pub fn spread_method(mut self, method: GradientSpreadMethod) -> Self {
self.brush.set_spread_method(method);
self
}
pub fn mapping_mode(mut self, mode: BrushMappingMode) -> Self {
self.brush.set_mapping_mode(mode);
self
}
pub fn stop(mut self, offset: f32, color: [f32; 4]) -> Self {
self.brush.add_stop(GradientStop { offset, color });
self
}
#[must_use]
pub fn build(self) -> LinearGradientBrush {
self.brush
}
}
impl Brush for LinearGradientBrush {
fn brush_raw(&self) -> *mut c_void {
self.raw()
}
}
pub struct RadialGradientBrush {
ptr: NonNull<c_void>,
}
base_component_handle!(RadialGradientBrush);
impl Default for RadialGradientBrush {
fn default() -> Self {
Self::new()
}
}
impl RadialGradientBrush {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_radial_gradient_brush_create() };
Self {
ptr: NonNull::new(ptr).expect("noesis_radial_gradient_brush_create returned null"),
}
}
pub fn set_center(&mut self, x: f32, y: f32) {
unsafe { noesis_radial_gradient_brush_set_center(self.ptr.as_ptr(), x, y) };
}
pub fn set_gradient_origin(&mut self, x: f32, y: f32) {
unsafe { noesis_radial_gradient_brush_set_gradient_origin(self.ptr.as_ptr(), x, y) };
}
pub fn set_radius(&mut self, rx: f32, ry: f32) {
unsafe { noesis_radial_gradient_brush_set_radius(self.ptr.as_ptr(), rx, ry) };
}
#[must_use]
pub fn radius(&self) -> (f32, f32) {
let mut rx = 0.0f32;
let mut ry = 0.0f32;
unsafe {
noesis_radial_gradient_brush_get_radius(
self.ptr.as_ptr(),
&mut rx as *mut f32,
&mut ry as *mut f32,
)
};
(rx, ry)
}
pub fn add_stop(&mut self, stop: GradientStop) -> Option<usize> {
gradient_add_stop(self.ptr.as_ptr(), stop)
}
#[must_use]
pub fn stop_count(&self) -> usize {
gradient_stop_count(self.ptr.as_ptr())
}
#[must_use]
pub fn stop(&self, index: usize) -> Option<GradientStop> {
gradient_get_stop(self.ptr.as_ptr(), index)
}
pub fn set_spread_method(&mut self, method: GradientSpreadMethod) -> bool {
gradient_set_spread_method(self.ptr.as_ptr(), method)
}
#[must_use]
pub fn spread_method(&self) -> Option<GradientSpreadMethod> {
gradient_spread_method(self.ptr.as_ptr())
}
pub fn set_mapping_mode(&mut self, mode: BrushMappingMode) -> bool {
gradient_set_mapping_mode(self.ptr.as_ptr(), mode)
}
#[must_use]
pub fn mapping_mode(&self) -> Option<BrushMappingMode> {
gradient_mapping_mode(self.ptr.as_ptr())
}
pub fn builder() -> RadialGradientBrushBuilder {
RadialGradientBrushBuilder {
brush: RadialGradientBrush::new(),
}
}
}
#[must_use]
pub struct RadialGradientBrushBuilder {
brush: RadialGradientBrush,
}
impl RadialGradientBrushBuilder {
pub fn center(mut self, x: f32, y: f32) -> Self {
self.brush.set_center(x, y);
self
}
pub fn gradient_origin(mut self, x: f32, y: f32) -> Self {
self.brush.set_gradient_origin(x, y);
self
}
pub fn radius(mut self, rx: f32, ry: f32) -> Self {
self.brush.set_radius(rx, ry);
self
}
pub fn spread_method(mut self, method: GradientSpreadMethod) -> Self {
self.brush.set_spread_method(method);
self
}
pub fn mapping_mode(mut self, mode: BrushMappingMode) -> Self {
self.brush.set_mapping_mode(mode);
self
}
pub fn stop(mut self, offset: f32, color: [f32; 4]) -> Self {
self.brush.add_stop(GradientStop { offset, color });
self
}
#[must_use]
pub fn build(self) -> RadialGradientBrush {
self.brush
}
}
impl Brush for RadialGradientBrush {
fn brush_raw(&self) -> *mut c_void {
self.raw()
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum AlignmentX {
Left = 0,
Center = 1,
Right = 2,
}
impl AlignmentX {
fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::Left),
1 => Some(Self::Center),
2 => Some(Self::Right),
_ => None,
}
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum AlignmentY {
Top = 0,
Center = 1,
Bottom = 2,
}
impl AlignmentY {
fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::Top),
1 => Some(Self::Center),
2 => Some(Self::Bottom),
_ => None,
}
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Stretch {
None = 0,
Fill = 1,
Uniform = 2,
UniformToFill = 3,
}
impl Stretch {
pub(crate) fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::None),
1 => Some(Self::Fill),
2 => Some(Self::Uniform),
3 => Some(Self::UniformToFill),
_ => None,
}
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum TileMode {
None = 0,
Tile = 1,
FlipX = 2,
FlipY = 3,
FlipXY = 4,
}
impl TileMode {
fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::None),
1 => Some(Self::Tile),
2 => Some(Self::FlipX),
3 => Some(Self::FlipY),
4 => Some(Self::FlipXY),
_ => None,
}
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum BrushMappingMode {
Absolute = 0,
RelativeToBoundingBox = 1,
}
impl BrushMappingMode {
fn from_ordinal(v: i32) -> Option<Self> {
match v {
0 => Some(Self::Absolute),
1 => Some(Self::RelativeToBoundingBox),
_ => None,
}
}
}
pub trait TileBrush: Brush {
fn set_alignment_x(&mut self, value: AlignmentX) {
unsafe { noesis_tile_brush_set_alignment_x(self.brush_raw(), value as i32) };
}
fn alignment_x(&self) -> Option<AlignmentX> {
AlignmentX::from_ordinal(unsafe { noesis_tile_brush_get_alignment_x(self.brush_raw()) })
}
fn set_alignment_y(&mut self, value: AlignmentY) {
unsafe { noesis_tile_brush_set_alignment_y(self.brush_raw(), value as i32) };
}
fn alignment_y(&self) -> Option<AlignmentY> {
AlignmentY::from_ordinal(unsafe { noesis_tile_brush_get_alignment_y(self.brush_raw()) })
}
fn set_stretch(&mut self, value: Stretch) {
unsafe { noesis_tile_brush_set_stretch(self.brush_raw(), value as i32) };
}
fn stretch(&self) -> Option<Stretch> {
Stretch::from_ordinal(unsafe { noesis_tile_brush_get_stretch(self.brush_raw()) })
}
fn set_tile_mode(&mut self, value: TileMode) {
unsafe { noesis_tile_brush_set_tile_mode(self.brush_raw(), value as i32) };
}
fn tile_mode(&self) -> Option<TileMode> {
TileMode::from_ordinal(unsafe { noesis_tile_brush_get_tile_mode(self.brush_raw()) })
}
fn set_viewport(&mut self, rect: [f32; 4]) {
unsafe {
noesis_tile_brush_set_viewport(self.brush_raw(), rect[0], rect[1], rect[2], rect[3])
};
}
fn viewport(&self) -> [f32; 4] {
let mut out = [0.0f32; 4];
unsafe { noesis_tile_brush_get_viewport(self.brush_raw(), out.as_mut_ptr()) };
out
}
fn set_viewport_units(&mut self, value: BrushMappingMode) {
unsafe { noesis_tile_brush_set_viewport_units(self.brush_raw(), value as i32) };
}
fn viewport_units(&self) -> Option<BrushMappingMode> {
BrushMappingMode::from_ordinal(unsafe {
noesis_tile_brush_get_viewport_units(self.brush_raw())
})
}
fn set_viewbox(&mut self, rect: [f32; 4]) {
unsafe {
noesis_tile_brush_set_viewbox(self.brush_raw(), rect[0], rect[1], rect[2], rect[3])
};
}
fn viewbox(&self) -> [f32; 4] {
let mut out = [0.0f32; 4];
unsafe { noesis_tile_brush_get_viewbox(self.brush_raw(), out.as_mut_ptr()) };
out
}
fn set_viewbox_units(&mut self, value: BrushMappingMode) {
unsafe { noesis_tile_brush_set_viewbox_units(self.brush_raw(), value as i32) };
}
fn viewbox_units(&self) -> Option<BrushMappingMode> {
BrushMappingMode::from_ordinal(unsafe {
noesis_tile_brush_get_viewbox_units(self.brush_raw())
})
}
}
pub struct ImageBrush {
ptr: NonNull<c_void>,
}
base_component_handle!(ImageBrush);
impl Default for ImageBrush {
fn default() -> Self {
Self::new()
}
}
impl ImageBrush {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_image_brush_create(core::ptr::null_mut()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_image_brush_create returned null"),
}
}
#[must_use]
pub unsafe fn with_source(image_source: *mut c_void) -> Option<Self> {
let ptr = unsafe { noesis_image_brush_create(image_source) };
NonNull::new(ptr).map(|ptr| Self { ptr })
}
pub unsafe fn set_image_source(&mut self, image_source: *mut c_void) -> bool {
unsafe { noesis_image_brush_set_image_source(self.ptr.as_ptr(), image_source) }
}
#[must_use]
pub fn image_source(&self) -> Option<NonNull<c_void>> {
let p = unsafe { noesis_image_brush_get_image_source(self.ptr.as_ptr()) };
NonNull::new(p)
}
}
impl Brush for ImageBrush {
fn brush_raw(&self) -> *mut c_void {
self.raw()
}
}
impl TileBrush for ImageBrush {}
pub struct VisualBrush {
ptr: NonNull<c_void>,
}
base_component_handle!(VisualBrush);
impl Default for VisualBrush {
fn default() -> Self {
Self::new()
}
}
impl VisualBrush {
#[must_use]
pub fn new() -> Self {
let ptr = unsafe { noesis_visual_brush_create(core::ptr::null_mut()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_visual_brush_create returned null"),
}
}
#[must_use]
pub fn from_element(element: &crate::view::FrameworkElement) -> Self {
let ptr = unsafe { noesis_visual_brush_create(element.raw()) };
Self {
ptr: NonNull::new(ptr).expect("noesis_visual_brush_create returned null"),
}
}
#[must_use = "a false return means the property was not set (unknown name / type mismatch / read-only)"]
pub fn set_visual(&mut self, element: &crate::view::FrameworkElement) -> bool {
unsafe { noesis_visual_brush_set_visual(self.ptr.as_ptr(), element.raw()) }
}
pub fn clear_visual(&mut self) -> bool {
unsafe { noesis_visual_brush_set_visual(self.ptr.as_ptr(), core::ptr::null_mut()) }
}
#[must_use]
pub fn visual(&self) -> Option<NonNull<c_void>> {
let p = unsafe { noesis_visual_brush_get_visual(self.ptr.as_ptr()) };
NonNull::new(p)
}
}
impl Brush for VisualBrush {
fn brush_raw(&self) -> *mut c_void {
self.raw()
}
}
impl TileBrush for VisualBrush {}
pub struct BlurEffect {
ptr: NonNull<c_void>,
}
base_component_handle!(BlurEffect);
impl BlurEffect {
#[must_use]
pub fn new(radius: f32) -> Self {
let ptr = unsafe { noesis_blur_effect_create(radius) };
Self {
ptr: NonNull::new(ptr).expect("noesis_blur_effect_create returned null"),
}
}
pub fn set_radius(&mut self, radius: f32) {
unsafe { noesis_blur_effect_set_radius(self.ptr.as_ptr(), radius) };
}
#[must_use]
pub fn radius(&self) -> f32 {
let mut out = 0.0f32;
unsafe { noesis_blur_effect_get_radius(self.ptr.as_ptr(), &mut out as *mut f32) };
out
}
}
impl Effect for BlurEffect {
fn effect_raw(&self) -> *mut c_void {
self.raw()
}
}
pub struct DropShadowEffect {
ptr: NonNull<c_void>,
}
base_component_handle!(DropShadowEffect);
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct DropShadowParams {
pub color: [f32; 4],
pub blur_radius: f32,
pub direction: f32,
pub shadow_depth: f32,
pub opacity: f32,
}
impl Default for DropShadowParams {
fn default() -> Self {
Self {
color: [0.0, 0.0, 0.0, 1.0],
blur_radius: 5.0,
direction: 315.0,
shadow_depth: 5.0,
opacity: 1.0,
}
}
}
impl DropShadowEffect {
#[must_use]
pub fn from_params(params: DropShadowParams) -> Self {
Self::new(
params.color,
params.blur_radius,
params.direction,
params.shadow_depth,
params.opacity,
)
}
#[must_use]
pub fn new(
color: [f32; 4],
blur_radius: f32,
direction: f32,
shadow_depth: f32,
opacity: f32,
) -> Self {
let ptr = unsafe {
noesis_drop_shadow_effect_create(
color.as_ptr(),
blur_radius,
direction,
shadow_depth,
opacity,
)
};
Self {
ptr: NonNull::new(ptr).expect("noesis_drop_shadow_effect_create returned null"),
}
}
#[must_use]
pub fn params(&self) -> DropShadowParams {
let mut color = [0.0f32; 4];
let mut blur_radius = 0.0f32;
let mut direction = 0.0f32;
let mut shadow_depth = 0.0f32;
let mut opacity = 0.0f32;
unsafe {
noesis_drop_shadow_effect_get(
self.ptr.as_ptr(),
color.as_mut_ptr(),
&mut blur_radius as *mut f32,
&mut direction as *mut f32,
&mut shadow_depth as *mut f32,
&mut opacity as *mut f32,
)
};
DropShadowParams {
color,
blur_radius,
direction,
shadow_depth,
opacity,
}
}
pub fn set_params(&mut self, params: DropShadowParams) {
self.set_color(params.color);
self.set_blur_radius(params.blur_radius);
self.set_direction(params.direction);
self.set_shadow_depth(params.shadow_depth);
self.set_opacity(params.opacity);
}
pub fn set_color(&mut self, rgba: [f32; 4]) {
unsafe { noesis_drop_shadow_effect_set_color(self.ptr.as_ptr(), rgba.as_ptr()) };
}
pub fn set_blur_radius(&mut self, blur_radius: f32) {
unsafe { noesis_drop_shadow_effect_set_blur_radius(self.ptr.as_ptr(), blur_radius) };
}
pub fn set_direction(&mut self, direction: f32) {
unsafe { noesis_drop_shadow_effect_set_direction(self.ptr.as_ptr(), direction) };
}
pub fn set_shadow_depth(&mut self, shadow_depth: f32) {
unsafe { noesis_drop_shadow_effect_set_shadow_depth(self.ptr.as_ptr(), shadow_depth) };
}
pub fn set_opacity(&mut self, opacity: f32) {
unsafe { noesis_drop_shadow_effect_set_opacity(self.ptr.as_ptr(), opacity) };
}
}
impl Effect for DropShadowEffect {
fn effect_raw(&self) -> *mut c_void {
self.raw()
}
}