#![allow(clippy::many_single_char_names)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![cfg(not(target_arch = "wasm32"))]
use crate::{
BaseLine, CanvasContext, Color, Direction, Gradient, GradientType, LineCap,
LineJoin, LinearGradient, PatternExtend, Point, RadialGradient, Rect, RgbaColor, Size,
TextAlign, TextMetrics, TextStyle, TextWeight,
};
use cairo::{self, FontFace, FontSlant, FontWeight};
use std::any::Any;
#[derive(Debug, Clone)]
pub struct Pattern {
pub extend: PatternExtend,
pub inner: cairo::SurfacePattern,
}
impl Pattern {
pub fn new(extend: PatternExtend, inner: cairo::SurfacePattern) -> Self {
Self { extend, inner }
}
}
pub struct Canvas<'a> {
ctx: &'a cairo::Context,
}
impl<'a> Canvas<'a> {
#[allow(dead_code)]
pub fn new(ctx: &'a cairo::Context) -> Self {
Self { ctx }
}
}
impl<'a> CanvasContext<Pattern> for Canvas<'a> {
fn get_direction(&self) -> Direction {
unimplemented!()
}
fn set_direction(&self, value: Direction) -> String {
info!("NOT IMPLEMENTED");
unimplemented!()
}
fn set_fill_color(&self, value: Color) {
let RgbaColor {
red,
green,
blue,
alpha,
} = value.into();
self.ctx.set_source_rgba(
red as f64 / 255.,
green as f64 / 255.,
blue as f64 / 255.,
alpha as f64 / 255.,
);
}
fn set_fill_gradient(&self, value: &Gradient) {
match value.kind {
GradientType::Linear(params) => {
let LinearGradient { x0, y0, x1, y1 } = params;
let gradient = cairo::LinearGradient::new(x0, y0, x1, y1);
let stops = value.stops.borrow();
for stop in stops.iter() {
let RgbaColor {
red,
green,
blue,
alpha,
} = stop.color.into();
gradient.add_color_stop_rgba(
stop.offset,
red as f64 / 255.,
green as f64 / 255.,
blue as f64 / 255.,
alpha as f64 / 255.,
);
}
self.ctx.set_source(&gradient);
}
GradientType::Radial(params) => {
let RadialGradient {
x0,
y0,
r0,
x1,
y1,
r1,
} = params;
let gradient = cairo::RadialGradient::new(x0, y0, r0, x1, y1, r1);
let stops = value.stops.borrow();
for stop in stops.iter() {
let RgbaColor {
red,
green,
blue,
alpha,
} = stop.color.into();
gradient.add_color_stop_rgba(
stop.offset,
red as f64 / 255.,
green as f64 / 255.,
blue as f64 / 255.,
alpha as f64 / 255.,
);
}
self.ctx.set_source(&gradient);
}
}
}
fn set_fill_pattern(&self, pattern: &Pattern) {
let extend = match pattern.extend {
PatternExtend::None => cairo::Extend::None,
PatternExtend::Repeat => cairo::Extend::Repeat,
PatternExtend::Reflect => cairo::Extend::Reflect,
PatternExtend::Pad => cairo::Extend::Pad,
};
pattern.inner.set_extend(extend);
self.ctx.set_source(&pattern.inner);
}
fn get_filter(&self) -> String {
unimplemented!()
}
fn set_filter(&self, value: &str) {
unimplemented!()
}
fn get_font(&self) -> String {
unimplemented!()
}
fn set_font(&self, family: &str, style: TextStyle, weight: TextWeight, size: f64) {
let slant = match style {
TextStyle::Italic => FontSlant::Italic,
TextStyle::Normal => FontSlant::Normal,
TextStyle::Oblique => FontSlant::Oblique,
};
let weight = match weight {
TextWeight::Bold => FontWeight::Bold,
_ => FontWeight::Normal,
};
self.ctx.select_font_face(family, slant, weight);
self.ctx.set_font_size(size);
}
fn get_global_alpha(&self) -> f64 {
unimplemented!()
}
fn set_global_alpha(&self, value: f64) {
unimplemented!()
}
fn get_global_composite_operation(&self) -> String {
unimplemented!()
}
fn set_global_composite_operation(&self, value: &str) {
unimplemented!()
}
fn is_image_smoothing_enabled(&self) -> bool {
unimplemented!()
}
fn set_image_smoothing(&self, value: bool) {
unimplemented!()
}
fn get_line_cap(&self) -> LineCap {
let result = self.ctx.get_line_cap();
unimplemented!()
}
fn set_line_cap(&self, value: LineCap) {
}
fn get_line_dash_offset(&self) -> f64 {
let (_, result) = self.ctx.get_dash();
result
}
fn set_line_dash_offset(&self, value: f64) {
unimplemented!()
}
fn get_line_join(&self) -> LineJoin {
let result = self.ctx.get_line_join();
unimplemented!()
}
fn set_line_join(&self, value: LineJoin) {
}
fn get_line_width(&self) -> f64 {
self.ctx.get_line_width()
}
fn set_line_width(&self, value: f64) {
self.ctx.set_line_width(value);
}
fn get_miter_limit(&self) -> f64 {
self.ctx.get_miter_limit()
}
fn set_miter_limit(&self, value: f64) {
self.ctx.set_miter_limit(value);
}
fn get_shadow_blur(&self) -> f64 {
unimplemented!()
}
fn set_shadow_blur(&self, value: f64) {
unimplemented!()
}
fn get_shadow_color(&self) -> Color {
unimplemented!()
}
fn set_shadow_color(&self, value: Color) {
unimplemented!()
}
fn get_shadow_offset_x(&self) -> f64 {
unimplemented!()
}
fn set_shadow_offset_x(&self, value: f64) {
unimplemented!()
}
fn get_shadow_offset_y(&self) -> f64 {
unimplemented!()
}
fn set_shadow_offset_y(&self, value: f64) {
unimplemented!()
}
fn set_stroke_color(&self, value: Color) {
let color: RgbaColor = value.into();
self.ctx.set_source_rgba(
color.red as f64 / 255.,
color.green as f64 / 255.,
color.blue as f64 / 255.,
color.alpha as f64 / 255.,
);
}
fn set_stroke_gradient(&self, value: &Gradient) {
match value.kind {
GradientType::Linear(params) => {
let LinearGradient { x0, y0, x1, y1 } = params;
let gradient = cairo::LinearGradient::new(x0, y0, x1, y1);
let stops = value.stops.borrow();
for stop in stops.iter() {
let RgbaColor {
red,
green,
blue,
alpha,
} = stop.color.into();
gradient.add_color_stop_rgba(
stop.offset,
red as f64 / 255.,
green as f64 / 255.,
blue as f64 / 255.,
alpha as f64 / 255.,
);
}
self.ctx.set_source(&gradient);
}
GradientType::Radial(params) => {
let RadialGradient {
x0,
y0,
r0,
x1,
y1,
r1,
} = params;
let gradient = cairo::RadialGradient::new(x0, y0, r0, x1, y1, r1);
let stops = value.stops.borrow();
for stop in stops.iter() {
let RgbaColor {
red,
green,
blue,
alpha,
} = stop.color.into();
gradient.add_color_stop_rgba(
stop.offset,
red as f64 / 255.,
green as f64 / 255.,
blue as f64 / 255.,
alpha as f64 / 255.,
);
}
self.ctx.set_source(&gradient);
}
}
}
fn set_stroke_pattern(&self, pattern: &Pattern) {
println!("SET STROKE PATTERN");
let extend = match pattern.extend {
PatternExtend::None => cairo::Extend::None,
PatternExtend::Repeat => cairo::Extend::Repeat,
PatternExtend::Reflect => cairo::Extend::Reflect,
PatternExtend::Pad => cairo::Extend::Pad,
};
pattern.inner.set_extend(extend);
self.ctx.set_source(&pattern.inner);
}
fn get_text_align(&self) -> TextAlign {
unimplemented!()
}
fn set_text_align(&self, value: TextAlign) {
}
fn get_text_baseline(&self) -> BaseLine {
unimplemented!()
}
fn set_text_baseline(&self, value: BaseLine) {
}
fn arc(
&self,
x: f64,
y: f64,
radius: f64,
start_angle: f64,
end_angle: f64,
anticlockwise: bool,
) {
if anticlockwise {
self.ctx.arc_negative(x, y, radius, start_angle, end_angle);
} else {
self.ctx.arc(x, y, radius, start_angle, end_angle);
}
}
fn arc_to(&self, x1: f64, y1: f64, x2: f64, y2: f64, radius: f64) {
unimplemented!()
}
fn begin_path(&self) {
self.ctx.new_path();
}
fn bezier_curve_to(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
self.ctx.curve_to(cp1x, cp1y, cp2x, cp2y, x, y);
}
fn clear_rect(&self, x: f64, y: f64, width: f64, height: f64) {
self.ctx.save();
self.ctx.set_source_rgba(0., 0., 0., 0.);
self.ctx.set_operator(cairo::Operator::Clear);
self.ctx.rectangle(x, y, width, height);
self.ctx.fill();
self.ctx.restore();
}
fn close_path(&self) {
self.ctx.close_path();
}
fn ellipse(
&self,
x: f64,
y: f64,
radius_x: f64,
radius_y: f64,
rotation: f64,
start_angle: f64,
end_angle: f64,
anticlockwise: bool,
) {
self.ctx.save();
self.ctx.translate(x, y);
self.ctx.scale(1., radius_y / radius_x);
self.ctx.rotate(rotation);
self.ctx.translate(-x, -y);
self.ctx.arc(x, y, radius_x, start_angle, end_angle);
self.ctx.restore();
}
fn fill(&self) {
self.ctx.fill();
}
fn fill_rect(&self, x: f64, y: f64, width: f64, height: f64) {
self.ctx.rectangle(x, y, width, height);
self.ctx.fill();
}
fn fill_text(&self, text: &str, x: f64, y: f64) {
self.ctx.save();
self.ctx.move_to(x, y);
self.ctx.text_path(text);
self.ctx.fill();
self.ctx.restore();
}
fn get_line_dash(&self) -> Vec<f64> {
let (result, _) = self.ctx.get_dash();
result
}
fn line_to(&self, x: f64, y: f64) {
self.ctx.line_to(x, y);
}
fn measure_text(&self, text: &str) -> TextMetrics {
let ext = self.ctx.text_extents(text);
TextMetrics {
width: ext.width,
height: ext.height,
}
}
fn move_to(&self, x: f64, y: f64) {
self.ctx.move_to(x, y);
}
fn quadratic_curve_to(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
let (x0, y0) = self.ctx.get_current_point();
self.ctx.curve_to(
2.0 / 3.0 * cpx + 1.0 / 3.0 * x0,
2.0 / 3.0 * cpy + 1.0 / 3.0 * y0,
2.0 / 3.0 * cpx + 1.0 / 3.0 * x,
2.0 / 3.0 * cpy + 1.0 / 3.0 * y,
x,
y,
);
}
fn rect(&self, x: f64, y: f64, width: f64, height: f64) {
self.ctx.rectangle(x, y, width, height);
}
fn reset_transform(&self) {
unimplemented!()
}
fn restore(&self) {
self.ctx.restore();
}
fn rotate(&self, angle: f64) {
self.ctx.rotate(angle);
}
fn save(&self) {
self.ctx.save();
}
fn scale(&self, x: f64, y: f64) {
self.ctx.scale(x, y);
}
fn set_line_dash(&self, dash: Vec<f64>) {
unimplemented!()
}
fn set_transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
let m = cairo::Matrix::new(a, b, c, d, e, f);
self.ctx.transform(m);
}
fn stroke(&self) {
self.ctx.stroke();
}
fn stroke_rect(&self, x: f64, y: f64, width: f64, height: f64) {
self.ctx.save();
self.ctx.rectangle(x, y, width, height);
self.ctx.fill();
self.ctx.restore();
}
fn stroke_text(&self, text: &str, x: f64, y: f64) {
self.ctx.save();
self.ctx.move_to(x, y);
self.ctx.text_path(text);
self.ctx.stroke();
self.ctx.restore();
}
fn transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
let m = cairo::Matrix::new(a, b, c, d, e, f);
self.ctx.transform(m);
}
fn translate(&self, x: f64, y: f64) {
self.ctx.translate(x, y);
}
}