use enums::*;
use error::D2DResult;
use factory::Factory;
use math;
use stroke_style::StrokeStyle;
use std::{mem, ptr};
use winapi::shared::minwindef::*;
use winapi::shared::winerror::*;
use winapi::um::d2d1::*;
use winapi::um::d2d1_1::*;
use winapi::um::d2dbasetypes::{D2D1_POINT_2F, D2D1_RECT_F, D2D_VECTOR_2F};
use wio::com::ComPtr;
#[doc(inline)]
pub use self::ellipse::Ellipse;
#[doc(inline)]
pub use self::generic::GenericGeometry;
#[doc(inline)]
pub use self::group::Group;
#[doc(inline)]
pub use self::path::Path;
#[doc(inline)]
pub use self::rectangle::Rectangle;
#[doc(inline)]
pub use self::rounded_rectangle::RoundedRectangle;
#[doc(inline)]
pub use self::transformed::Transformed;
pub mod ellipse;
pub mod generic;
pub mod group;
pub mod path;
pub mod rectangle;
pub mod rounded_rectangle;
pub mod transformed;
pub trait Geometry {
unsafe fn get_ptr(&self) -> *mut ID2D1Geometry;
#[inline]
fn get_factory(&self) -> Factory {
unsafe {
let geom = self.get_ptr();
let mut ptr = ptr::null_mut();
(*geom).GetFactory(&mut ptr);
let ptr: ComPtr<ID2D1Factory1> = ComPtr::from_raw(ptr).cast().unwrap();
Factory::from_raw(ptr.into_raw())
}
}
#[inline]
fn to_generic(&self) -> GenericGeometry {
unsafe {
let ptr = self.get_ptr();
(*ptr).AddRef();
GenericGeometry::from_raw(ptr)
}
}
#[inline]
fn get_bounds(&self, world_transform: Option<&math::Matrix3x2F>) -> D2DResult<math::RectF> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut rect: D2D1_RECT_F = mem::uninitialized();
let result = (*ptr).GetBounds(matrix, &mut rect);
if SUCCEEDED(result) {
Ok(math::RectF(rect))
} else {
Err(From::from(result))
}
}
}
#[inline]
fn get_widened_bounds(
&self,
stroke_width: f32,
stroke_style: Option<&StrokeStyle>,
world_transform: Option<&math::Matrix3x2F>,
) -> D2DResult<math::RectF> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let stroke_style = match stroke_style {
Some(stroke) => stroke.get_raw() as *mut _,
None => ptr::null_mut(),
};
let mut rect: D2D1_RECT_F = mem::uninitialized();
let result = (*ptr).GetWidenedBounds(
stroke_width,
stroke_style,
matrix,
D2D1_DEFAULT_FLATTENING_TOLERANCE,
&mut rect,
);
if SUCCEEDED(result) {
Ok(math::RectF(rect))
} else {
Err(From::from(result))
}
}
}
#[inline]
fn stroke_contains_point(
&self,
point: math::Point2F,
stroke_width: f32,
stroke_style: Option<&StrokeStyle>,
world_transform: Option<&math::Matrix3x2F>,
) -> D2DResult<bool> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let stroke_style = match stroke_style {
Some(stroke) => stroke.get_raw() as *mut _,
None => ptr::null_mut(),
};
let mut contains: BOOL = 0;
let result = (*ptr).StrokeContainsPoint(
point.0,
stroke_width,
stroke_style,
matrix,
D2D1_DEFAULT_FLATTENING_TOLERANCE,
&mut contains,
);
if SUCCEEDED(result) {
Ok(contains != 0)
} else {
Err(From::from(result))
}
}
}
#[inline]
fn fill_contains_point(
&self,
point: math::Point2F,
world_transform: Option<&math::Matrix3x2F>,
) -> D2DResult<bool> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut contains: BOOL = 0;
let result = (*ptr).FillContainsPoint(
point.0,
matrix,
D2D1_DEFAULT_FLATTENING_TOLERANCE,
&mut contains,
);
if SUCCEEDED(result) {
Ok(contains != 0)
} else {
Err(From::from(result))
}
}
}
#[inline]
fn compare_with_geometry<T: Geometry>(
&self,
input: &T,
input_transform: Option<&math::Matrix3x2F>,
) -> D2DResult<UncheckedEnum<GeometryRelation>> {
unsafe {
let self_ptr = self.get_ptr();
let input_ptr = input.get_ptr();
let matrix = match input_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut relation: D2D1_GEOMETRY_RELATION = D2D1_GEOMETRY_RELATION_UNKNOWN;
let result = (*self_ptr).CompareWithGeometry(
input_ptr,
matrix,
D2D1_DEFAULT_FLATTENING_TOLERANCE,
&mut relation,
);
if SUCCEEDED(result) {
Ok(relation.into())
} else {
Err(From::from(result))
}
}
}
#[inline]
fn compute_area(&self, world_transform: Option<&math::Matrix3x2F>) -> D2DResult<f32> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut area = 0.0;
let tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
let result = (*ptr).ComputeArea(matrix, tolerance, &mut area);
if SUCCEEDED(result) {
Ok(area)
} else {
Err(From::from(result))
}
}
}
#[inline]
fn compute_length(&self, world_transform: Option<&math::Matrix3x2F>) -> D2DResult<f32> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut length = 0.0;
let tolerance = D2D1_DEFAULT_FLATTENING_TOLERANCE;
let result = (*ptr).ComputeLength(matrix, tolerance, &mut length);
if SUCCEEDED(result) {
Ok(length)
} else {
Err(From::from(result))
}
}
}
#[inline]
fn compute_point_at_length(
&self,
length: f32,
world_transform: Option<&math::Matrix3x2F>,
) -> D2DResult<(math::Point2F, math::Vector2F)> {
unsafe {
let ptr = self.get_ptr();
let matrix = match world_transform {
Some(mat) => &mat.0 as *const _,
None => ptr::null(),
};
let mut point: D2D1_POINT_2F = mem::uninitialized();
let mut tangent: D2D1_POINT_2F = mem::uninitialized();
let result = (*ptr).ComputePointAtLength(
length,
matrix,
D2D1_DEFAULT_FLATTENING_TOLERANCE,
&mut point,
&mut tangent,
);
if SUCCEEDED(result) {
Ok((
math::Point2F(point),
math::Vector2F(D2D_VECTOR_2F {
x: tangent.x,
y: tangent.y,
}),
))
} else {
Err(From::from(result))
}
}
}
#[inline]
fn transformed(&self, transform: &math::Matrix3x2F) -> D2DResult<Transformed> {
let factory = self.get_factory();
unsafe {
let raw_factory = factory.get_raw();
let mut geometry = ptr::null_mut();
let hr = (*raw_factory).CreateTransformedGeometry(
self.get_ptr(),
&transform.0,
&mut geometry,
);
if SUCCEEDED(hr) {
Ok(Transformed::from_raw(geometry))
} else {
Err(hr.into())
}
}
}
}
impl<'a, T: Geometry> Geometry for &'a T {
#[inline]
unsafe fn get_ptr(&self) -> *mut ID2D1Geometry {
T::get_ptr(*self)
}
}