2019-01-14 17:20:36 -05:00
|
|
|
// pathfinder/renderer/src/scene.rs
|
|
|
|
//
|
|
|
|
// Copyright © 2019 The Pathfinder Project Developers.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2020-07-13 19:18:23 -04:00
|
|
|
//! The vector scene to be rendered.
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2019-04-30 22:13:28 -04:00
|
|
|
use crate::builder::SceneBuilder;
|
|
|
|
use crate::concurrent::executor::Executor;
|
2020-06-23 16:03:13 -04:00
|
|
|
use crate::gpu::options::RendererLevel;
|
2020-07-02 22:49:01 -04:00
|
|
|
use crate::gpu::renderer::Renderer;
|
|
|
|
use crate::gpu_data::RenderCommand;
|
2019-06-05 17:35:46 -04:00
|
|
|
use crate::options::{BuildOptions, PreparedBuildOptions};
|
|
|
|
use crate::options::{PreparedRenderTransform, RenderCommandListener};
|
2020-04-17 14:50:46 -04:00
|
|
|
use crate::paint::{MergedPaletteInfo, Paint, PaintId, PaintInfo, Palette};
|
2020-04-03 01:03:42 -04:00
|
|
|
use pathfinder_content::effects::BlendMode;
|
2020-02-17 17:44:48 -05:00
|
|
|
use pathfinder_content::fill::FillRule;
|
2020-02-22 00:42:15 -05:00
|
|
|
use pathfinder_content::outline::Outline;
|
2020-03-03 18:50:48 -05:00
|
|
|
use pathfinder_content::render_target::RenderTargetId;
|
2019-06-21 13:06:19 -04:00
|
|
|
use pathfinder_geometry::rect::RectF;
|
2019-07-11 17:35:06 -04:00
|
|
|
use pathfinder_geometry::transform2d::Transform2F;
|
2020-03-31 14:28:34 -04:00
|
|
|
use pathfinder_geometry::vector::{Vector2I, vec2f};
|
2020-07-02 22:49:01 -04:00
|
|
|
use pathfinder_gpu::Device;
|
|
|
|
use std::mem;
|
2020-06-23 16:03:13 -04:00
|
|
|
use std::ops::Range;
|
2020-04-16 19:54:52 -04:00
|
|
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
2020-07-02 22:49:01 -04:00
|
|
|
use std::sync::{Arc, Mutex};
|
2020-06-23 16:03:13 -04:00
|
|
|
use std::u64;
|
2020-04-16 19:54:52 -04:00
|
|
|
|
|
|
|
static NEXT_SCENE_ID: AtomicUsize = AtomicUsize::new(0);
|
2019-01-14 17:20:36 -05:00
|
|
|
|
2020-07-13 19:18:23 -04:00
|
|
|
/// The vector scene to be rendered.
|
2019-01-29 17:50:15 -05:00
|
|
|
#[derive(Clone)]
|
2019-01-14 17:20:36 -05:00
|
|
|
pub struct Scene {
|
2020-06-23 16:03:13 -04:00
|
|
|
display_list: Vec<DisplayItem>,
|
|
|
|
draw_paths: Vec<DrawPath>,
|
|
|
|
clip_paths: Vec<ClipPath>,
|
2020-02-05 22:59:40 -05:00
|
|
|
palette: Palette,
|
2019-05-29 22:13:42 -04:00
|
|
|
bounds: RectF,
|
|
|
|
view_box: RectF,
|
2020-04-16 19:54:52 -04:00
|
|
|
id: SceneId,
|
2020-06-23 16:03:13 -04:00
|
|
|
epoch: SceneEpoch,
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
|
|
|
|
2020-04-16 19:54:52 -04:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
pub struct SceneId(pub u32);
|
|
|
|
|
2019-01-14 17:20:36 -05:00
|
|
|
impl Scene {
|
|
|
|
#[inline]
|
|
|
|
pub fn new() -> Scene {
|
2020-04-16 19:54:52 -04:00
|
|
|
let scene_id = SceneId(NEXT_SCENE_ID.fetch_add(1, Ordering::Relaxed) as u32);
|
2019-01-14 17:20:36 -05:00
|
|
|
Scene {
|
2020-02-19 20:44:41 -05:00
|
|
|
display_list: vec![],
|
2020-06-23 16:03:13 -04:00
|
|
|
draw_paths: vec![],
|
2020-02-15 16:21:12 -05:00
|
|
|
clip_paths: vec![],
|
2020-04-16 19:54:52 -04:00
|
|
|
palette: Palette::new(scene_id),
|
2019-05-29 22:13:42 -04:00
|
|
|
bounds: RectF::default(),
|
|
|
|
view_box: RectF::default(),
|
2020-04-16 19:54:52 -04:00
|
|
|
id: scene_id,
|
2020-06-23 16:03:13 -04:00
|
|
|
epoch: SceneEpoch::new(0, 1),
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
pub fn push_draw_path(&mut self, draw_path: DrawPath) {
|
|
|
|
let draw_path_index = DrawPathId(self.draw_paths.len() as u32);
|
|
|
|
self.draw_paths.push(draw_path);
|
|
|
|
self.push_draw_path_with_index(draw_path_index);
|
2020-04-02 19:30:49 -04:00
|
|
|
}
|
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
fn push_draw_path_with_index(&mut self, draw_path_id: DrawPathId) {
|
|
|
|
let new_path_bounds = self.draw_paths[draw_path_id.0 as usize].outline.bounds();
|
|
|
|
self.bounds = self.bounds.union_rect(new_path_bounds);
|
2020-02-19 20:44:41 -05:00
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
let end_path_id = DrawPathId(draw_path_id.0 + 1);
|
|
|
|
match self.display_list.last_mut() {
|
|
|
|
Some(DisplayItem::DrawPaths(ref mut range)) => range.end = end_path_id,
|
|
|
|
_ => self.display_list.push(DisplayItem::DrawPaths(draw_path_id..end_path_id)),
|
2020-02-19 20:44:41 -05:00
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
|
|
|
|
self.epoch.next();
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
|
2020-02-15 16:21:12 -05:00
|
|
|
pub fn push_clip_path(&mut self, clip_path: ClipPath) -> ClipPathId {
|
|
|
|
self.bounds = self.bounds.union_rect(clip_path.outline.bounds());
|
|
|
|
let clip_path_id = ClipPathId(self.clip_paths.len() as u32);
|
|
|
|
self.clip_paths.push(clip_path);
|
2020-06-23 16:03:13 -04:00
|
|
|
self.epoch.next();
|
2020-02-15 16:21:12 -05:00
|
|
|
clip_path_id
|
|
|
|
}
|
|
|
|
|
2020-02-22 00:42:15 -05:00
|
|
|
pub fn push_render_target(&mut self, render_target: RenderTarget) -> RenderTargetId {
|
|
|
|
let render_target_id = self.palette.push_render_target(render_target);
|
|
|
|
self.display_list.push(DisplayItem::PushRenderTarget(render_target_id));
|
2020-06-23 16:03:13 -04:00
|
|
|
self.epoch.next();
|
2020-02-22 00:42:15 -05:00
|
|
|
render_target_id
|
2020-02-19 20:44:41 -05:00
|
|
|
}
|
|
|
|
|
2020-02-22 00:42:15 -05:00
|
|
|
pub fn pop_render_target(&mut self) {
|
|
|
|
self.display_list.push(DisplayItem::PopRenderTarget);
|
|
|
|
}
|
|
|
|
|
2020-04-02 16:49:30 -04:00
|
|
|
pub fn append_scene(&mut self, scene: Scene) {
|
2020-04-17 14:50:46 -04:00
|
|
|
let MergedPaletteInfo {
|
|
|
|
render_target_mapping,
|
|
|
|
paint_mapping,
|
|
|
|
} = self.palette.append_palette(scene.palette);
|
2020-04-02 16:49:30 -04:00
|
|
|
|
|
|
|
// Merge clip paths.
|
|
|
|
let mut clip_path_mapping = Vec::with_capacity(scene.clip_paths.len());
|
|
|
|
for clip_path in scene.clip_paths {
|
|
|
|
clip_path_mapping.push(self.clip_paths.len());
|
|
|
|
self.clip_paths.push(clip_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Merge draw paths.
|
2020-06-23 16:03:13 -04:00
|
|
|
let mut draw_path_mapping = Vec::with_capacity(scene.draw_paths.len());
|
|
|
|
for draw_path in scene.draw_paths {
|
|
|
|
draw_path_mapping.push(self.draw_paths.len() as u32);
|
|
|
|
self.draw_paths.push(DrawPath {
|
2020-04-02 16:49:30 -04:00
|
|
|
outline: draw_path.outline,
|
|
|
|
paint: paint_mapping[&draw_path.paint],
|
|
|
|
clip_path: draw_path.clip_path.map(|clip_path_id| {
|
|
|
|
ClipPathId(clip_path_mapping[clip_path_id.0 as usize] as u32)
|
|
|
|
}),
|
|
|
|
fill_rule: draw_path.fill_rule,
|
|
|
|
blend_mode: draw_path.blend_mode,
|
|
|
|
name: draw_path.name,
|
|
|
|
});
|
|
|
|
}
|
2020-04-02 19:30:49 -04:00
|
|
|
|
|
|
|
// Merge display items.
|
|
|
|
for display_item in scene.display_list {
|
|
|
|
match display_item {
|
|
|
|
DisplayItem::PushRenderTarget(old_render_target_id) => {
|
|
|
|
let new_render_target_id = render_target_mapping[&old_render_target_id];
|
|
|
|
self.display_list.push(DisplayItem::PushRenderTarget(new_render_target_id));
|
|
|
|
}
|
|
|
|
DisplayItem::PopRenderTarget => {
|
|
|
|
self.display_list.push(DisplayItem::PopRenderTarget);
|
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
DisplayItem::DrawPaths(range) => {
|
|
|
|
for old_path_index in (range.start.0 as usize)..(range.end.0 as usize) {
|
|
|
|
let old_draw_path_id = DrawPathId(draw_path_mapping[old_path_index]);
|
|
|
|
self.push_draw_path_with_index(old_draw_path_id);
|
2020-04-02 19:30:49 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
|
|
|
|
// Bump epoch.
|
|
|
|
self.epoch.next();
|
2020-04-02 16:49:30 -04:00
|
|
|
}
|
|
|
|
|
2020-02-05 22:59:40 -05:00
|
|
|
#[inline]
|
2020-07-13 19:18:23 -04:00
|
|
|
pub(crate) fn build_paint_info(&mut self, render_transform: Transform2F) -> PaintInfo {
|
2020-04-02 14:17:03 -04:00
|
|
|
self.palette.build_paint_info(render_transform)
|
2020-02-05 22:59:40 -05:00
|
|
|
}
|
|
|
|
|
2019-01-14 17:20:36 -05:00
|
|
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
|
|
|
pub fn push_paint(&mut self, paint: &Paint) -> PaintId {
|
2020-06-23 16:03:13 -04:00
|
|
|
let paint_id = self.palette.push_paint(paint);
|
|
|
|
self.epoch.next();
|
|
|
|
paint_id
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-05-29 22:13:42 -04:00
|
|
|
pub fn bounds(&self) -> RectF {
|
2019-04-30 22:13:28 -04:00
|
|
|
self.bounds
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-05-29 22:13:42 -04:00
|
|
|
pub fn set_bounds(&mut self, new_bounds: RectF) {
|
2019-04-30 22:13:28 -04:00
|
|
|
self.bounds = new_bounds;
|
2020-06-23 16:03:13 -04:00
|
|
|
self.epoch.next();
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-05-29 22:13:42 -04:00
|
|
|
pub fn view_box(&self) -> RectF {
|
2019-04-30 22:13:28 -04:00
|
|
|
self.view_box
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2019-05-29 22:13:42 -04:00
|
|
|
pub fn set_view_box(&mut self, new_view_box: RectF) {
|
2019-04-30 22:13:28 -04:00
|
|
|
self.view_box = new_view_box;
|
2020-06-23 16:03:13 -04:00
|
|
|
self.epoch.next();
|
2019-04-18 18:09:37 -04:00
|
|
|
}
|
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
pub(crate) fn apply_render_options(&self,
|
|
|
|
original_outline: &Outline,
|
|
|
|
options: &PreparedBuildOptions)
|
|
|
|
-> Outline {
|
2019-02-09 22:24:30 -05:00
|
|
|
let mut outline;
|
2019-02-06 21:09:37 -05:00
|
|
|
match options.transform {
|
2019-04-29 19:45:29 -04:00
|
|
|
PreparedRenderTransform::Perspective {
|
|
|
|
ref perspective,
|
|
|
|
ref clip_polygon,
|
|
|
|
..
|
|
|
|
} => {
|
2019-02-09 22:24:30 -05:00
|
|
|
if original_outline.is_outside_polygon(clip_polygon) {
|
|
|
|
outline = Outline::new();
|
|
|
|
} else {
|
|
|
|
outline = (*original_outline).clone();
|
2020-03-27 17:50:02 -04:00
|
|
|
outline.close_all_contours();
|
2019-02-09 22:24:30 -05:00
|
|
|
outline.clip_against_polygon(clip_polygon);
|
|
|
|
outline.apply_perspective(perspective);
|
2019-03-20 16:40:48 -04:00
|
|
|
|
2019-03-25 19:13:56 -04:00
|
|
|
// TODO(pcwalton): Support subpixel AA in 3D.
|
2019-02-09 22:24:30 -05:00
|
|
|
}
|
2019-01-30 17:42:06 -05:00
|
|
|
}
|
2019-03-25 19:13:56 -04:00
|
|
|
_ => {
|
2019-02-09 22:24:30 -05:00
|
|
|
// TODO(pcwalton): Short circuit.
|
|
|
|
outline = (*original_outline).clone();
|
2020-03-27 17:50:02 -04:00
|
|
|
outline.close_all_contours();
|
2019-03-25 19:13:56 -04:00
|
|
|
if options.transform.is_2d() || options.subpixel_aa_enabled {
|
|
|
|
let mut transform = match options.transform {
|
|
|
|
PreparedRenderTransform::Transform2D(transform) => transform,
|
2019-07-11 17:35:06 -04:00
|
|
|
PreparedRenderTransform::None => Transform2F::default(),
|
2019-03-25 19:13:56 -04:00
|
|
|
PreparedRenderTransform::Perspective { .. } => unreachable!(),
|
|
|
|
};
|
|
|
|
if options.subpixel_aa_enabled {
|
2020-03-31 14:28:34 -04:00
|
|
|
transform *= Transform2F::from_scale(vec2f(3.0, 1.0))
|
2019-03-25 19:13:56 -04:00
|
|
|
}
|
|
|
|
outline.transform(&transform);
|
|
|
|
}
|
2019-02-02 14:36:42 -05:00
|
|
|
}
|
2019-01-30 17:42:06 -05:00
|
|
|
}
|
2019-02-06 21:09:37 -05:00
|
|
|
|
|
|
|
if !options.dilation.is_zero() {
|
|
|
|
outline.dilate(options.dilation);
|
|
|
|
}
|
|
|
|
|
2019-02-02 14:36:42 -05:00
|
|
|
outline
|
2019-01-16 19:53:10 -05:00
|
|
|
}
|
2019-03-06 22:35:57 -05:00
|
|
|
|
2019-03-25 19:13:56 -04:00
|
|
|
#[inline]
|
2019-06-05 17:35:46 -04:00
|
|
|
pub(crate) fn effective_view_box(&self, render_options: &PreparedBuildOptions) -> RectF {
|
2019-03-25 19:13:56 -04:00
|
|
|
if render_options.subpixel_aa_enabled {
|
2020-04-01 20:20:32 -04:00
|
|
|
self.view_box * vec2f(3.0, 1.0)
|
2019-03-25 19:13:56 -04:00
|
|
|
} else {
|
|
|
|
self.view_box
|
|
|
|
}
|
|
|
|
}
|
2019-04-30 22:13:28 -04:00
|
|
|
|
|
|
|
#[inline]
|
2020-06-23 16:03:13 -04:00
|
|
|
pub fn build<'a, 'b, E>(&mut self,
|
|
|
|
options: BuildOptions,
|
|
|
|
sink: &'b mut SceneSink<'a>,
|
|
|
|
executor: &E)
|
|
|
|
where E: Executor {
|
2019-05-03 15:35:19 -04:00
|
|
|
let prepared_options = options.prepare(self.bounds);
|
2020-06-23 16:03:13 -04:00
|
|
|
SceneBuilder::new(self, &prepared_options, sink).build(executor)
|
2019-04-30 22:13:28 -04:00
|
|
|
}
|
2020-02-27 11:13:14 -05:00
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
#[inline]
|
|
|
|
pub fn display_list(&self) -> &[DisplayItem] {
|
|
|
|
&self.display_list
|
2019-06-15 10:50:25 -04:00
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn draw_paths(&self) -> &[DrawPath] {
|
|
|
|
&self.draw_paths
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn clip_paths(&self) -> &[ClipPath] {
|
|
|
|
&self.clip_paths
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn get_draw_path(&self, draw_path_id: DrawPathId) -> &DrawPath {
|
|
|
|
&self.draw_paths[draw_path_id.0 as usize]
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn get_clip_path(&self, clip_path_id: ClipPathId) -> &ClipPath {
|
|
|
|
&self.clip_paths[clip_path_id.0 as usize]
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2020-07-13 19:18:23 -04:00
|
|
|
pub fn get_paint(&self, paint_id: PaintId) -> &Paint {
|
|
|
|
self.palette.paints.get(paint_id.0 as usize).expect("No paint with that ID!")
|
2020-06-23 16:03:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn id(&self) -> SceneId {
|
|
|
|
self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn epoch(&self) -> SceneEpoch {
|
|
|
|
self.epoch
|
|
|
|
}
|
2020-07-02 22:49:01 -04:00
|
|
|
|
|
|
|
/// A convenience method to build a scene and accumulate commands into a vector.
|
|
|
|
pub fn build_into_vector<D, E>(&mut self,
|
|
|
|
renderer: &mut Renderer<D>,
|
|
|
|
build_options: BuildOptions,
|
|
|
|
executor: E)
|
|
|
|
-> Vec<RenderCommand>
|
|
|
|
where D: Device, E: Executor {
|
|
|
|
let commands = Arc::new(Mutex::new(vec![]));
|
|
|
|
let commands_for_listener = commands.clone();
|
|
|
|
let listener = RenderCommandListener::new(Box::new(move |command| {
|
|
|
|
commands_for_listener.lock().unwrap().push(command)
|
|
|
|
}));
|
|
|
|
let mut sink = SceneSink::new(listener, renderer.mode().level);
|
|
|
|
self.build(build_options, &mut sink, &executor);
|
|
|
|
let mut commands = commands.lock().unwrap();
|
|
|
|
mem::replace(&mut *commands, vec![])
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A convenience method to build a scene and send the resulting commands to the given
|
|
|
|
/// renderer.
|
|
|
|
pub fn build_and_render<D, E>(&mut self,
|
|
|
|
renderer: &mut Renderer<D>,
|
|
|
|
build_options: BuildOptions,
|
|
|
|
executor: E)
|
|
|
|
where D: Device, E: Executor {
|
|
|
|
let commands = self.build_into_vector(renderer, build_options, executor);
|
|
|
|
renderer.begin_scene();
|
|
|
|
commands.into_iter().for_each(|command| renderer.render_command(&command));
|
|
|
|
renderer.end_scene();
|
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SceneSink<'a> {
|
|
|
|
pub(crate) listener: RenderCommandListener<'a>,
|
|
|
|
pub(crate) renderer_level: RendererLevel,
|
|
|
|
pub(crate) last_scene: Option<LastSceneInfo>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) struct LastSceneInfo {
|
|
|
|
pub(crate) scene_id: SceneId,
|
|
|
|
pub(crate) scene_epoch: SceneEpoch,
|
|
|
|
pub(crate) draw_segment_ranges: Vec<Range<u32>>,
|
|
|
|
pub(crate) clip_segment_ranges: Vec<Range<u32>>,
|
2019-06-15 10:50:25 -04:00
|
|
|
}
|
2020-01-31 03:16:34 -05:00
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
|
|
|
pub struct SceneEpoch {
|
|
|
|
pub hi: u64,
|
|
|
|
pub lo: u64,
|
2019-06-15 10:50:25 -04:00
|
|
|
}
|
2020-01-31 03:16:34 -05:00
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
impl SceneEpoch {
|
|
|
|
#[inline]
|
|
|
|
fn new(hi: u64, lo: u64) -> SceneEpoch {
|
|
|
|
SceneEpoch { hi, lo }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn successor(&self) -> SceneEpoch {
|
|
|
|
if self.lo == u64::MAX {
|
|
|
|
SceneEpoch { hi: self.hi + 1, lo: 0 }
|
|
|
|
} else {
|
|
|
|
SceneEpoch { hi: self.hi, lo: self.lo + 1 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn next(&mut self) {
|
|
|
|
*self = self.successor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SceneSink<'a> {
|
|
|
|
#[inline]
|
|
|
|
pub fn new(listener: RenderCommandListener<'a>, renderer_level: RendererLevel)
|
|
|
|
-> SceneSink<'a> {
|
|
|
|
SceneSink { listener, renderer_level, last_scene: None }
|
2019-06-15 10:50:25 -04:00
|
|
|
}
|
2019-01-29 17:50:15 -05:00
|
|
|
}
|
2020-01-31 03:16:34 -05:00
|
|
|
|
2019-01-15 14:42:25 -05:00
|
|
|
#[derive(Clone, Debug)]
|
2020-02-15 15:39:15 -05:00
|
|
|
pub struct DrawPath {
|
2020-06-23 16:03:13 -04:00
|
|
|
pub outline: Outline,
|
|
|
|
pub paint: PaintId,
|
|
|
|
pub clip_path: Option<ClipPathId>,
|
|
|
|
pub fill_rule: FillRule,
|
|
|
|
pub blend_mode: BlendMode,
|
|
|
|
pub name: String,
|
2020-02-15 16:21:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct ClipPath {
|
2020-06-23 16:03:13 -04:00
|
|
|
pub outline: Outline,
|
2020-07-01 15:07:07 -04:00
|
|
|
pub clip_path: Option<ClipPathId>,
|
2020-06-23 16:03:13 -04:00
|
|
|
pub fill_rule: FillRule,
|
|
|
|
pub name: String,
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct DrawPathId(pub u32);
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
2020-02-15 16:21:12 -05:00
|
|
|
pub struct ClipPathId(pub u32);
|
|
|
|
|
2020-06-23 16:03:13 -04:00
|
|
|
/// Either a draw path ID or a clip path ID, depending on context.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
|
|
|
pub struct PathId(pub u32);
|
|
|
|
|
2020-02-22 00:42:15 -05:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct RenderTarget {
|
|
|
|
size: Vector2I,
|
|
|
|
name: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Drawing commands.
|
2020-02-19 20:44:41 -05:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum DisplayItem {
|
2020-02-22 00:42:15 -05:00
|
|
|
/// Draws paths to the render target on top of the stack.
|
2020-06-23 16:03:13 -04:00
|
|
|
DrawPaths(Range<DrawPathId>),
|
2020-02-22 00:42:15 -05:00
|
|
|
|
|
|
|
/// Pushes a render target onto the top of the stack.
|
|
|
|
PushRenderTarget(RenderTargetId),
|
|
|
|
|
|
|
|
/// Pops a render target from the stack.
|
|
|
|
PopRenderTarget,
|
2020-02-19 20:44:41 -05:00
|
|
|
}
|
|
|
|
|
2020-02-15 15:39:15 -05:00
|
|
|
impl DrawPath {
|
2019-01-14 17:20:36 -05:00
|
|
|
#[inline]
|
2020-02-26 15:43:07 -05:00
|
|
|
pub fn new(outline: Outline, paint: PaintId) -> DrawPath {
|
|
|
|
DrawPath {
|
|
|
|
outline,
|
|
|
|
paint,
|
|
|
|
clip_path: None,
|
|
|
|
fill_rule: FillRule::Winding,
|
|
|
|
blend_mode: BlendMode::SrcOver,
|
|
|
|
name: String::new(),
|
|
|
|
}
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
2019-01-29 17:50:15 -05:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn outline(&self) -> &Outline {
|
|
|
|
&self.outline
|
|
|
|
}
|
2019-05-14 17:28:21 -04:00
|
|
|
|
2020-02-15 16:21:12 -05:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn clip_path(&self) -> Option<ClipPathId> {
|
|
|
|
self.clip_path
|
|
|
|
}
|
|
|
|
|
2020-02-26 15:43:07 -05:00
|
|
|
#[inline]
|
|
|
|
pub fn set_clip_path(&mut self, new_clip_path: Option<ClipPathId>) {
|
|
|
|
self.clip_path = new_clip_path
|
|
|
|
}
|
|
|
|
|
2019-05-14 17:28:21 -04:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn paint(&self) -> PaintId {
|
|
|
|
self.paint
|
|
|
|
}
|
2020-02-17 17:44:48 -05:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn fill_rule(&self) -> FillRule {
|
|
|
|
self.fill_rule
|
|
|
|
}
|
2020-02-20 18:52:40 -05:00
|
|
|
|
2020-02-26 15:43:07 -05:00
|
|
|
#[inline]
|
|
|
|
pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) {
|
|
|
|
self.fill_rule = new_fill_rule
|
|
|
|
}
|
|
|
|
|
2020-02-20 18:52:40 -05:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn blend_mode(&self) -> BlendMode {
|
|
|
|
self.blend_mode
|
|
|
|
}
|
2020-02-26 15:43:07 -05:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_blend_mode(&mut self, new_blend_mode: BlendMode) {
|
|
|
|
self.blend_mode = new_blend_mode
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_name(&mut self, new_name: String) {
|
|
|
|
self.name = new_name
|
|
|
|
}
|
2019-01-14 17:20:36 -05:00
|
|
|
}
|
2020-02-15 16:21:12 -05:00
|
|
|
|
|
|
|
impl ClipPath {
|
|
|
|
#[inline]
|
2020-02-26 15:43:07 -05:00
|
|
|
pub fn new(outline: Outline) -> ClipPath {
|
2020-07-01 15:07:07 -04:00
|
|
|
ClipPath { outline, clip_path: None, fill_rule: FillRule::Winding, name: String::new() }
|
2020-02-15 16:21:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn outline(&self) -> &Outline {
|
|
|
|
&self.outline
|
|
|
|
}
|
2020-02-17 17:44:48 -05:00
|
|
|
|
2020-07-01 15:07:07 -04:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn clip_path(&self) -> Option<ClipPathId> {
|
|
|
|
self.clip_path
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_clip_path(&mut self, new_clip_path: Option<ClipPathId>) {
|
|
|
|
self.clip_path = new_clip_path
|
|
|
|
}
|
|
|
|
|
2020-02-17 17:44:48 -05:00
|
|
|
#[inline]
|
|
|
|
pub(crate) fn fill_rule(&self) -> FillRule {
|
|
|
|
self.fill_rule
|
|
|
|
}
|
2020-02-26 15:43:07 -05:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_fill_rule(&mut self, new_fill_rule: FillRule) {
|
|
|
|
self.fill_rule = new_fill_rule
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn set_name(&mut self, new_name: String) {
|
|
|
|
self.name = new_name
|
|
|
|
}
|
2020-02-15 16:21:12 -05:00
|
|
|
}
|
2020-02-22 00:42:15 -05:00
|
|
|
|
|
|
|
impl RenderTarget {
|
|
|
|
#[inline]
|
|
|
|
pub fn new(size: Vector2I, name: String) -> RenderTarget {
|
|
|
|
RenderTarget { size, name }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn size(&self) -> Vector2I {
|
|
|
|
self.size
|
|
|
|
}
|
|
|
|
}
|
2020-06-23 16:03:13 -04:00
|
|
|
|
|
|
|
impl DrawPathId {
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn to_path_id(self) -> PathId {
|
|
|
|
PathId(self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ClipPathId {
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn to_path_id(self) -> PathId {
|
|
|
|
PathId(self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PathId {
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn to_clip_path_id(self) -> ClipPathId {
|
|
|
|
ClipPathId(self.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn to_draw_path_id(self) -> DrawPathId {
|
|
|
|
DrawPathId(self.0)
|
|
|
|
}
|
|
|
|
}
|