Add graphics state saving and restoration to the canvas API
This commit is contained in:
parent
a86a87a670
commit
3ba4ce117c
|
@ -16,15 +16,15 @@ use pathfinder_geometry::color::ColorU;
|
||||||
use pathfinder_geometry::outline::{Contour, Outline};
|
use pathfinder_geometry::outline::{Contour, Outline};
|
||||||
use pathfinder_geometry::stroke::OutlineStrokeToFill;
|
use pathfinder_geometry::stroke::OutlineStrokeToFill;
|
||||||
use pathfinder_renderer::scene::{Paint, PathObject, Scene};
|
use pathfinder_renderer::scene::{Paint, PathObject, Scene};
|
||||||
|
use std::default::Default;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
const HAIRLINE_STROKE_WIDTH: f32 = 0.0333;
|
const HAIRLINE_STROKE_WIDTH: f32 = 0.0333;
|
||||||
|
|
||||||
pub struct CanvasRenderingContext2D {
|
pub struct CanvasRenderingContext2D {
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
current_fill_paint: Paint,
|
current_state: State,
|
||||||
current_stroke_paint: Paint,
|
saved_states: Vec<State>,
|
||||||
current_line_width: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasRenderingContext2D {
|
impl CanvasRenderingContext2D {
|
||||||
|
@ -37,12 +37,7 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_scene(scene: Scene) -> CanvasRenderingContext2D {
|
pub fn from_scene(scene: Scene) -> CanvasRenderingContext2D {
|
||||||
CanvasRenderingContext2D {
|
CanvasRenderingContext2D { scene, current_state: State::default(), saved_states: vec![] }
|
||||||
scene,
|
|
||||||
current_fill_paint: Paint { color: ColorU::black() },
|
|
||||||
current_stroke_paint: Paint { color: ColorU::black() },
|
|
||||||
current_line_width: 1.0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -66,33 +61,63 @@ impl CanvasRenderingContext2D {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_line_width(&mut self, new_line_width: f32) {
|
pub fn set_line_width(&mut self, new_line_width: f32) {
|
||||||
self.current_line_width = new_line_width
|
self.current_state.line_width = new_line_width
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_fill_style(&mut self, new_fill_style: FillStyle) {
|
pub fn set_fill_style(&mut self, new_fill_style: FillStyle) {
|
||||||
self.current_fill_paint = new_fill_style.to_paint();
|
self.current_state.fill_paint = new_fill_style.to_paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_stroke_style(&mut self, new_stroke_style: FillStyle) {
|
pub fn set_stroke_style(&mut self, new_stroke_style: FillStyle) {
|
||||||
self.current_stroke_paint = new_stroke_style.to_paint();
|
self.current_state.stroke_paint = new_stroke_style.to_paint();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fill_path(&mut self, path: Path2D) {
|
pub fn fill_path(&mut self, path: Path2D) {
|
||||||
let paint_id = self.scene.push_paint(&self.current_fill_paint);
|
let paint_id = self.scene.push_paint(&self.current_state.fill_paint);
|
||||||
self.scene.push_object(PathObject::new(path.into_outline(), paint_id, String::new()))
|
self.scene.push_object(PathObject::new(path.into_outline(), paint_id, String::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stroke_path(&mut self, path: Path2D) {
|
pub fn stroke_path(&mut self, path: Path2D) {
|
||||||
let paint_id = self.scene.push_paint(&self.current_stroke_paint);
|
let paint_id = self.scene.push_paint(&self.current_state.stroke_paint);
|
||||||
let stroke_width = f32::max(self.current_line_width, HAIRLINE_STROKE_WIDTH);
|
let stroke_width = f32::max(self.current_state.line_width, HAIRLINE_STROKE_WIDTH);
|
||||||
let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_width);
|
let mut stroke_to_fill = OutlineStrokeToFill::new(path.into_outline(), stroke_width);
|
||||||
stroke_to_fill.offset();
|
stroke_to_fill.offset();
|
||||||
self.scene.push_object(PathObject::new(stroke_to_fill.outline, paint_id, String::new()))
|
self.scene.push_object(PathObject::new(stroke_to_fill.outline, paint_id, String::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn save(&mut self) {
|
||||||
|
self.saved_states.push(self.current_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn restore(&mut self) {
|
||||||
|
if let Some(state) = self.saved_states.pop() {
|
||||||
|
self.current_state = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct State {
|
||||||
|
fill_paint: Paint,
|
||||||
|
stroke_paint: Paint,
|
||||||
|
line_width: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for State {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> State {
|
||||||
|
State {
|
||||||
|
fill_paint: Paint { color: ColorU::black() },
|
||||||
|
stroke_paint: Paint { color: ColorU::black() },
|
||||||
|
line_width: 1.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -165,8 +190,6 @@ pub enum FillStyle {
|
||||||
impl FillStyle {
|
impl FillStyle {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_paint(&self) -> Paint {
|
fn to_paint(&self) -> Paint {
|
||||||
match *self {
|
match *self { FillStyle::Color(color) => Paint { color } }
|
||||||
FillStyle::Color(color) => Paint { color },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue