x-graphics 0.2.1

Graphics framework for X
Documentation
pub use crate::backend::path::*;
use crate::{
    device::{DeviceContext, DeviceContextBackend},
    error::GraphicsError,
    geometry::FRect,
    DefaultDeviceContext, DefaultPath, Float,
};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FillType {
    Winding,
    EvenOdd,
}

pub trait PathBackend {
    type DeviceContextType: DeviceContextBackend;

    fn new(context: Option<&Self::DeviceContextType>) -> Result<Self, GraphicsError>
    where
        Self: Sized;
    fn get_fill_type(&self) -> FillType;
    fn set_fill_type(&mut self, fill_type: FillType);
    fn begin(&mut self);
    fn close(&mut self);
    fn move_to(&mut self, x: Float, y: Float);
    fn line_to(&mut self, x: Float, y: Float);
    fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float);
    fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float);
    fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float);
    fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool);
    fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float);
    fn add_circle(&mut self, x: Float, y: Float, radius: Float);
    fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float);
    fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float);
    fn bounds(&self) -> FRect;
    fn is_empty(&self) -> bool;
}

pub struct Path<T: PathBackend> {
    pub(crate) backend: T,
}

impl<T: PathBackend> Path<T> {
    pub fn new(context: Option<&DeviceContext<T::DeviceContextType>>) -> Result<Self, GraphicsError> {
        Ok(Self {
            backend: T::new(context.map(|ctx| &ctx.backend))?,
        })
    }

    pub fn get_fill_type(&self) -> FillType {
        self.backend.get_fill_type()
    }

    pub fn set_fill_type(&mut self, fill_type: FillType) {
        self.backend.set_fill_type(fill_type);
    }

    pub fn begin(&mut self) {
        self.backend.begin();
    }

    pub fn close(&mut self) {
        self.backend.close();
    }

    pub fn move_to(&mut self, x: Float, y: Float) {
        self.backend.move_to(x, y);
    }

    pub fn line_to(&mut self, x: Float, y: Float) {
        self.backend.line_to(x, y);
    }

    pub fn arc_to(&mut self, x1: Float, y1: Float, x2: Float, y2: Float, radius: Float) {
        self.backend.arc_to(x1, y1, x2, y2, radius);
    }

    pub fn bezier_curve_to(&mut self, cpx1: Float, cpy1: Float, cpx2: Float, cpy2: Float, x: Float, y: Float) {
        self.backend.bezier_curve_to(cpx1, cpy1, cpx2, cpy2, x, y);
    }

    pub fn quad_curve_to(&mut self, cpx: Float, cpy: Float, x: Float, y: Float) {
        self.backend.quad_curve_to(cpx, cpy, x, y);
    }

    pub fn add_arc(&mut self, x: Float, y: Float, radius: Float, start_angle: Float, end_angle: Float, clockwise: bool) {
        self.backend.add_arc(x, y, radius, start_angle, end_angle, clockwise);
    }

    pub fn add_rect(&mut self, x: Float, y: Float, width: Float, height: Float) {
        self.backend.add_rect(x, y, width, height);
    }

    pub fn add_circle(&mut self, x: Float, y: Float, radius: Float) {
        self.backend.add_circle(x, y, radius);
    }

    pub fn add_ellipse(&mut self, x: Float, y: Float, width: Float, height: Float) {
        self.backend.add_ellipse(x, y, width, height);
    }

    pub fn add_rounded_rect(&mut self, x: Float, y: Float, width: Float, height: Float, radius: Float) {
        self.backend.add_rounded_rect(x, y, width, height, radius);
    }

    pub fn bounds(&self) -> FRect {
        self.backend.bounds()
    }

    pub fn is_empty(&self) -> bool {
        self.backend.is_empty()
    }
}

impl Path<DefaultPath> {
    pub fn new_default(context: Option<&DeviceContext<DefaultDeviceContext>>) -> Result<Self, GraphicsError> {
        Self::new(context)
    }
}