use crate::boolean_ops::composite_boolean_operation;
use crate::intersection::Quad;
use crate::layers::folder_layer::FolderLayer;
use crate::layers::image_layer::ImageLayer;
use crate::layers::layer_info::{Layer, LayerData, LayerDataType, LayerDataTypeDiscriminant};
use crate::layers::nodegraph_layer::NodeGraphFrameLayer;
use crate::layers::shape_layer::ShapeLayer;
use crate::layers::style::RenderData;
use crate::layers::text_layer::{Font, FontCache, TextLayer};
use crate::{DocumentError, DocumentResponse, Operation};
use graphene_std::vector::subpath::Subpath;
use glam::{DAffine2, DVec2};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::cmp::max;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
/// A number that identifies a layer.
/// This does not technically need to be unique globally, only within a folder.
pub type LayerId = u64;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Document {
/// The root layer, usually a [FolderLayer](layers::folder_layer::FolderLayer) that contains all other [Layers](layers::layer_info::Layer).
pub root: Layer,
/// The state_identifier serves to provide a way to uniquely identify a particular state that the document is in.
/// This identifier is not a hash and is not guaranteed to be equal for equivalent documents.
#[serde(skip)]
pub state_identifier: DefaultHasher,
}
impl PartialEq for Document {
fn eq(&self, other: &Self) -> bool {
self.state_identifier.finish() == other.state_identifier.finish()
}
}
impl Default for Document {
fn default() -> Self {
Self {
root: Layer::new(LayerDataType::Folder(FolderLayer::default()), DAffine2::IDENTITY.to_cols_array()),
state_identifier: DefaultHasher::new(),
}
}
}
impl Document {
/// Wrapper around render, that returns the whole document as a Response.
pub fn render_root(&mut self, render_data: RenderData) -> String {
// Render and append to the defs section
let mut svg_defs = String::from("");
self.root.render(&mut vec![], &mut svg_defs, render_data);
svg_defs.push_str("");
// Append the cached rendered SVG
svg_defs.push_str(&self.root.cache);
svg_defs
}
/// Renders everything below the given layer contained within its parent folder.
pub fn render_layers_below(&mut self, below_layer_path: &[LayerId], render_data: RenderData) -> Option {
// Split the path into the layer ID and its parent folder
let (layer_id_to_render_below, parent_folder_path) = below_layer_path.split_last()?;
// Note: it is bad practice to directly clone and modify the document structure, this is a temporary hack until this whole system is replaced by the node graph
let mut temp_subset_folder = self.layer_mut(parent_folder_path).ok()?.clone();
if let LayerDataType::Folder(ref mut folder) = temp_subset_folder.data {
// Remove the upper layers to leave behind the lower subset for rendering
let count_of_layers_below = folder.layer_ids.iter().position(|id| id == layer_id_to_render_below).unwrap();
folder.layer_ids.truncate(count_of_layers_below);
folder.layers.truncate(count_of_layers_below);
// Render and append to the defs section
let mut svg_defs = String::from("");
temp_subset_folder.render(&mut vec![], &mut svg_defs, render_data);
svg_defs.push_str("");
// Append the cached rendered SVG
svg_defs.push_str(&temp_subset_folder.cache);
Some(svg_defs)
} else {
None
}
}
/// Renders a layer and its children
pub fn render_layer(&mut self, layer_path: &[LayerId], render_data: RenderData) -> Option {
// Note: it is bad practice to directly clone and modify the document structure, this is a temporary hack until this whole system is replaced by the node graph
let mut temp_clone = self.layer_mut(layer_path).ok()?.clone();
// Render and append to the defs section
let mut svg_defs = String::from("");
temp_clone.render(&mut vec![], &mut svg_defs, render_data);
svg_defs.push_str("");
// Append the cached rendered SVG
svg_defs.push_str(&temp_clone.cache);
Some(svg_defs)
}
pub fn current_state_identifier(&self) -> u64 {
self.state_identifier.finish()
}
/// Checks whether each layer under `path` intersects with the provided `quad` and adds all intersection layers as paths to `intersections`.
pub fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache) {
self.layer(path).unwrap().intersects_quad(quad, path, intersections, font_cache);
}
/// Checks whether each layer under the root path intersects with the provided `quad` and returns the paths to all intersecting layers.
pub fn intersects_quad_root(&self, quad: Quad, font_cache: &FontCache) -> Vec> {
let mut intersections = Vec::new();
self.intersects_quad(quad, &mut vec![], &mut intersections, font_cache);
intersections
}
/// Returns a reference to the requested folder. Fails if the path does not exist,
/// or if the requested layer is not of type folder.
pub fn folder(&self, path: impl AsRef<[LayerId]>) -> Result<&FolderLayer, DocumentError> {
let mut root = &self.root;
for id in path.as_ref() {
root = root.as_folder()?.layer(*id).ok_or_else(|| DocumentError::LayerNotFound(path.as_ref().into()))?;
}
root.as_folder()
}
/// Returns a mutable reference to the requested folder. Fails if the path does not exist,
/// or if the requested layer is not of type folder.
/// If you manually edit the folder you have to set the cache_dirty flag yourself.
fn folder_mut(&mut self, path: &[LayerId]) -> Result<&mut FolderLayer, DocumentError> {
let mut root = &mut self.root;
for id in path {
root = root.as_folder_mut()?.layer_mut(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
root.as_folder_mut()
}
/// Returns a reference to the layer or folder at the path.
pub fn layer(&self, path: &[LayerId]) -> Result<&Layer, DocumentError> {
if path.is_empty() {
return Ok(&self.root);
}
let (path, id) = split_path(path)?;
self.folder(path)?.layer(id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))
}
/// Returns a mutable reference to the layer or folder at the path.
pub fn layer_mut(&mut self, path: &[LayerId]) -> Result<&mut Layer, DocumentError> {
if path.is_empty() {
return Ok(&mut self.root);
}
let (path, id) = split_path(path)?;
self.folder_mut(path)?.layer_mut(id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))
}
/// Returns vector `Shape`s for each specified in `paths`.
/// If any path is not a shape, or does not exist, `DocumentError::InvalidPath` is returned.
fn transformed_shapes(&self, paths: &[Vec]) -> Result, DocumentError> {
let mut shapes: Vec = Vec::new();
let undo_viewport = self.root.transform.inverse();
for path in paths {
match (self.multiply_transforms(path), &self.layer(path)?.data) {
(Ok(shape_transform), LayerDataType::Shape(shape)) => {
let mut new_shape = shape.clone();
new_shape.shape.apply_affine(undo_viewport * shape_transform);
shapes.push(new_shape);
}
(Ok(_), _) => return Err(DocumentError::InvalidPath),
(Err(err), _) => return Err(err),
}
}
Ok(shapes)
}
/// Return a copy of all [Subpath]s currently in the document.
pub fn all_subpaths(&self) -> Vec {
self.root.iter().flat_map(|layer| layer.as_subpath_copy()).collect::>()
}
/// Returns references to all [Subpath]s currently in the document.
pub fn all_subpaths_ref(&self) -> Vec<&Subpath> {
self.root.iter().flat_map(|layer| layer.as_subpath()).collect::>()
}
/// Returns a reference to the requested [Subpath] by providing a path to its owner layer.
pub fn subpath_ref<'a>(&'a self, path: &[LayerId]) -> Option<&'a Subpath> {
self.layer(path).ok()?.as_subpath()
}
/// Returns a mutable reference of the requested [Subpath] by providing a path to its owner layer.
pub fn subpath_mut<'a>(&'a mut self, path: &'a [LayerId]) -> Option<&'a mut Subpath> {
self.layer_mut(path).ok()?.as_subpath_mut()
}
/// Set a [Subpath] at the specified path.
pub fn set_subpath(&mut self, path: &[LayerId], shape: Subpath) {
let layer = self.layer_mut(path);
if let Ok(layer) = layer {
if let LayerDataType::Shape(shape_layer) = &mut layer.data {
shape_layer.shape = shape;
// Is this needed?
layer.cache_dirty = true;
}
}
}
/// Set [Subpath]s for multiple paths at once.
pub fn set_subpaths<'a>(&'a mut self, paths: impl Iterator, shapes: Vec) {
paths.zip(shapes).for_each(|(path, shape)| self.set_subpath(path, shape));
}
pub fn common_layer_path_prefix<'a>(&self, layers: impl Iterator) -> &'a [LayerId] {
layers.reduce(|a, b| &a[..a.iter().zip(b.iter()).take_while(|&(a, b)| a == b).count()]).unwrap_or_default()
}
/// Filters out the non folders from an iterator of paths.
/// Takes and Iterator over &[LayerId] or &Vec.
pub fn folders<'a, T>(&'a self, layers: impl Iterator + 'a) -> impl Iterator + 'a
where
T: AsRef<[LayerId]> + std::cmp::Ord + 'a,
{
layers.filter(|layer| self.is_folder(layer.as_ref()))
}
/// Returns the shallowest folder given the selection, even if the selection doesn't contain any folders
pub fn shallowest_common_folder<'a>(&self, layers: impl Iterator) -> Result<&'a [LayerId], DocumentError> {
let common_prefix_of_path = self.common_layer_path_prefix(layers);
Ok(match self.layer(common_prefix_of_path)?.data {
LayerDataType::Folder(_) => common_prefix_of_path,
_ => &common_prefix_of_path[..common_prefix_of_path.len() - 1],
})
}
/// Returns all folders that are not contained in any other of the given folders
/// Takes and Iterator over &[LayerId] or &Vec.
pub fn shallowest_folders<'a, T>(&'a self, layers: impl Iterator) -> Vec
where
T: AsRef<[LayerId]> + std::cmp::Ord + 'a,
{
Self::shallowest_unique_layers(self.folders(layers))
}
/// Returns all layers that are not contained in any other of the given folders
/// Takes and Iterator over &[LayerId] or &Vec.
pub fn shallowest_unique_layers<'a, T>(layers: impl Iterator) -> Vec
where
T: AsRef<[LayerId]> + std::cmp::Ord + 'a,
{
let mut sorted_layers: Vec<_> = layers.collect();
sorted_layers.sort();
// Sorting here creates groups of similar UUID paths
sorted_layers.dedup_by(|a, b| a.as_ref().starts_with(b.as_ref()));
sorted_layers
}
/// Deepest to shallowest (longest to shortest path length)
/// Takes and Iterator over &[LayerId] or &Vec.
pub fn sorted_folders_by_depth<'a, T>(&'a self, layers: impl Iterator) -> Vec
where
T: AsRef<[LayerId]> + std::cmp::Ord + 'a,
{
let mut folders: Vec<_> = self.folders(layers).collect();
folders.sort_by_key(|a| std::cmp::Reverse(a.as_ref().len()));
folders
}
pub fn folder_children_paths(&self, path: &[LayerId]) -> Vec> {
if let Ok(folder) = self.folder(&path) {
folder.list_layers().iter().map(|f| [path, &[*f]].concat()).collect()
} else {
vec![]
}
}
pub fn is_folder(&self, path: impl AsRef<[LayerId]>) -> bool {
return self.folder(path.as_ref()).is_ok();
}
// Determines which layer is closer to the root, if path_a return true, if path_b return false
// Answers the question: Is A closer to the root than B?
pub fn layer_closer_to_root(&self, path_a: &[u64], path_b: &[u64]) -> bool {
// Convert UUIDs to indices
let indices_for_path_a = self.indices_for_path(path_a).unwrap();
let indices_for_path_b = self.indices_for_path(path_b).unwrap();
let longest = max(indices_for_path_a.len(), indices_for_path_b.len());
for i in 0..longest {
// usize::MAX becomes negative one here, sneaky. So folders are compared as [X, -1]. This is intentional.
let index_a = *indices_for_path_a.get(i).unwrap_or(&usize::MAX) as i32;
let index_b = *indices_for_path_b.get(i).unwrap_or(&usize::MAX) as i32;
// At the point at which the two paths first differ, compare to see which is closer to the root
if index_a != index_b {
// If index_a is smaller, index_a is closer to the root
return index_a < index_b;
}
}
false
}
// Is the target layer between a <-> b layers, inclusive
pub fn layer_is_between(&self, target: &[u64], path_a: &[u64], path_b: &[u64]) -> bool {
// If the target is the root, it isn't between
if target.is_empty() {
return false;
}
// This function is inclusive, so we consider path_a, path_b to be between themselves
if target == path_a || target == path_b {
return true;
};
// These can't both be true and be between two values
let layer_vs_a = self.layer_closer_to_root(target, path_a);
let layer_vs_b = self.layer_closer_to_root(target, path_b);
// To be in-between you need to be above A and below B or vice versa
layer_vs_a != layer_vs_b
}
/// Given a path to a layer, returns a vector of the indices in the layer tree
/// These indices can be used to order a list of layers
pub fn indices_for_path(&self, path: &[LayerId]) -> Result, DocumentError> {
let mut root = self.root.as_folder()?;
let mut indices = vec![];
let (path, layer_id) = split_path(path)?;
// TODO: appears to be n^2? should we maintain a lookup table?
for id in path {
let pos = root.layer_ids.iter().position(|x| *x == *id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
indices.push(pos);
root = root.folder(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
indices.push(root.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?);
Ok(indices)
}
/// Replaces the layer at the specified `path` with `layer`.
pub fn set_layer(&mut self, path: &[LayerId], layer: Layer, insert_index: isize) -> Result<(), DocumentError> {
let mut folder = self.root.as_folder_mut()?;
let mut layer_id = None;
if let Ok((path, id)) = split_path(path) {
layer_id = Some(id);
self.mark_as_dirty(path)?;
folder = self.folder_mut(path)?;
if let Some(folder_layer) = folder.layer_mut(id) {
*folder_layer = layer;
return Ok(());
}
}
folder.add_layer(layer, layer_id, insert_index).ok_or(DocumentError::IndexOutOfBounds)?;
Ok(())
}
/// Visit each layer recursively, marks all children as dirty
pub fn mark_children_as_dirty(layer: &mut Layer) -> bool {
match layer.data {
LayerDataType::Folder(ref mut folder) => {
for sub_layer in folder.layers_mut() {
if Document::mark_children_as_dirty(sub_layer) {
layer.cache_dirty = true;
}
}
}
_ => layer.cache_dirty = true,
}
layer.cache_dirty
}
/// Adds a new layer to the folder specified by `path`.
/// Passing a negative `insert_index` indexes relative to the end.
/// -1 is equivalent to adding the layer to the top.
pub fn add_layer(&mut self, path: &[LayerId], layer: Layer, insert_index: isize) -> Result {
let folder = self.folder_mut(path)?;
folder.add_layer(layer, None, insert_index).ok_or(DocumentError::IndexOutOfBounds)
}
/// Deletes the layer specified by `path`.
pub fn delete(&mut self, path: &[LayerId]) -> Result<(), DocumentError> {
let (path, id) = split_path(path)?;
self.mark_as_dirty(path)?;
self.folder_mut(path)?.remove_layer(id)
}
pub fn visible_layers(&self, path: &mut Vec, paths: &mut Vec>) -> Result<(), DocumentError> {
if !self.layer(path)?.visible {
return Ok(());
}
if let Ok(folder) = self.folder(&path) {
for layer in folder.layer_ids.iter() {
path.push(*layer);
self.visible_layers(path, paths)?;
path.pop();
}
} else {
paths.push(path.clone());
}
Ok(())
}
pub fn viewport_bounding_box(&self, path: &[LayerId], font_cache: &FontCache) -> Result