use crate::point2f::Point2f;
use crate::sizef::Sizef;
#[cfg(all(windows, feature = "d2d"))]
use winapi::um::d2d1::D2D1_ARC_SEGMENT;
#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct ArcSegment {
pub point: Point2f,
pub size: Sizef,
pub rotation_angle: f32,
pub sweep_direction: SweepDirection,
pub arc_size: ArcSize,
}
impl ArcSegment {
#[inline]
pub fn new(
point: impl Into<Point2f>,
size: impl Into<Sizef>,
rotation_angle: f32,
sweep_direction: SweepDirection,
arc_size: ArcSize,
) -> ArcSegment {
ArcSegment {
point: point.into(),
size: size.into(),
rotation_angle,
sweep_direction,
arc_size,
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[repr(u32)]
pub enum SweepDirection {
CounterClockwise = 0,
Clockwise = 1,
}
impl Default for SweepDirection {
#[inline]
fn default() -> Self {
SweepDirection::CounterClockwise
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[repr(u32)]
pub enum ArcSize {
Small = 0,
Large = 1,
}
impl Default for ArcSize {
#[inline]
fn default() -> Self {
ArcSize::Small
}
}
#[cfg(all(windows, feature = "d2d"))]
impl From<ArcSegment> for D2D1_ARC_SEGMENT {
#[inline]
fn from(seg: ArcSegment) -> D2D1_ARC_SEGMENT {
D2D1_ARC_SEGMENT {
point: seg.point.into(),
size: seg.size.into(),
rotationAngle: seg.rotation_angle,
sweepDirection: seg.sweep_direction as u32,
arcSize: seg.arc_size as u32,
}
}
}
#[cfg(all(test, windows, feature = "d2d"))]
#[test]
fn arc_d2d_bin_compat() {
use std::mem::size_of_val;
fn ptr_eq<T, U>(a: &T, b: &U) -> bool {
assert_eq!(size_of_val(a), size_of_val(b));
(a as *const T) == (b as *const U as *const T)
}
let arc = ArcSegment::new(
(0.0, 0.0),
(1.0, 1.0),
90.0,
SweepDirection::CounterClockwise,
ArcSize::Small,
);
let d2d = unsafe { &*((&arc) as *const _ as *const D2D1_ARC_SEGMENT) };
assert!(ptr_eq(&arc.point.x, &d2d.point.x));
assert!(ptr_eq(&arc.point.y, &d2d.point.y));
assert!(ptr_eq(&arc.size.width, &d2d.size.width));
assert!(ptr_eq(&arc.size.height, &d2d.size.height));
assert!(ptr_eq(&arc.rotation_angle, &d2d.rotationAngle));
assert!(ptr_eq(&arc.sweep_direction, &d2d.sweepDirection));
assert!(ptr_eq(&arc.arc_size, &d2d.arcSize));
assert_eq!(size_of_val(&arc), size_of_val(d2d));
}