diff --git a/document-legacy/src/document.rs b/document-legacy/src/document.rs index 0bc4de008..7a8041996 100644 --- a/document-legacy/src/document.rs +++ b/document-legacy/src/document.rs @@ -1,12 +1,11 @@ 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::layers::text_layer::{Font, TextLayer}; use crate::{DocumentError, DocumentResponse, Operation}; use graphene_std::vector::subpath::Subpath; @@ -49,7 +48,7 @@ impl Default for Document { impl Document { /// Wrapper around render, that returns the whole document as a Response. - pub fn render_root(&mut self, render_data: RenderData) -> String { + 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); @@ -62,7 +61,7 @@ impl Document { } /// 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 { + 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()?; @@ -89,7 +88,7 @@ impl Document { } /// Renders a layer and its children - pub fn render_layer(&mut self, layer_path: &[LayerId], render_data: RenderData) -> Option { + 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(); @@ -109,14 +108,14 @@ impl Document { } /// 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); + pub fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData) { + self.layer(path).unwrap().intersects_quad(quad, path, intersections, render_data); } /// 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> { + pub fn intersects_quad_root(&self, quad: Quad, render_data: &RenderData) -> Vec> { let mut intersections = Vec::new(); - self.intersects_quad(quad, &mut vec![], &mut intersections, font_cache); + self.intersects_quad(quad, &mut vec![], &mut intersections, render_data); intersections } @@ -407,32 +406,32 @@ impl Document { Ok(()) } - pub fn viewport_bounding_box(&self, path: &[LayerId], font_cache: &FontCache) -> Result, DocumentError> { + pub fn viewport_bounding_box(&self, path: &[LayerId], render_data: &RenderData) -> Result, DocumentError> { let layer = self.layer(path)?; let transform = self.multiply_transforms(path)?; - Ok(layer.data.bounding_box(transform, font_cache)) + Ok(layer.data.bounding_box(transform, render_data)) } - pub fn bounding_box_and_transform(&self, path: &[LayerId], font_cache: &FontCache) -> Result, DocumentError> { + pub fn bounding_box_and_transform(&self, path: &[LayerId], render_data: &RenderData) -> Result, DocumentError> { let layer = self.layer(path)?; let transform = self.multiply_transforms(&path[..path.len() - 1])?; - Ok(layer.data.bounding_box(layer.transform, font_cache).map(|bounds| (bounds, transform))) + Ok(layer.data.bounding_box(layer.transform, render_data).map(|bounds| (bounds, transform))) } /// Compute the center of transformation multiplied with `Document::multiply_transforms`. - pub fn pivot(&self, path: &[LayerId], font_cache: &FontCache) -> Option { + pub fn pivot(&self, path: &[LayerId], render_data: &RenderData) -> Option { let layer = self.layer(path).ok()?; - Some(self.multiply_transforms(path).unwrap_or_default().transform_point2(layer.layerspace_pivot(font_cache))) + Some(self.multiply_transforms(path).unwrap_or_default().transform_point2(layer.layerspace_pivot(render_data))) } - pub fn visible_layers_bounding_box(&self, font_cache: &FontCache) -> Option<[DVec2; 2]> { + pub fn visible_layers_bounding_box(&self, render_data: &RenderData) -> Option<[DVec2; 2]> { let mut paths = vec![]; self.visible_layers(&mut vec![], &mut paths).ok()?; - self.combined_viewport_bounding_box(paths.iter().map(|x| x.as_slice()), font_cache) + self.combined_viewport_bounding_box(paths.iter().map(|x| x.as_slice()), render_data) } - pub fn combined_viewport_bounding_box<'a>(&self, paths: impl Iterator, font_cache: &FontCache) -> Option<[DVec2; 2]> { - let boxes = paths.filter_map(|path| self.viewport_bounding_box(path, font_cache).ok()?); + pub fn combined_viewport_bounding_box<'a>(&self, paths: impl Iterator, render_data: &RenderData) -> Option<[DVec2; 2]> { + let boxes = paths.filter_map(|path| self.viewport_bounding_box(path, render_data).ok()?); boxes.reduce(|a, b| [a[0].min(b[0]), a[1].max(b[1])]) } @@ -552,7 +551,7 @@ impl Document { /// Mutate the document by applying the `operation` to it. If the operation necessitates a /// reaction from the frontend, responses may be returned. - pub fn handle_operation(&mut self, operation: Operation, font_cache: &FontCache) -> Result>, DocumentError> { + pub fn handle_operation(&mut self, operation: Operation, render_data: &RenderData) -> Result>, DocumentError> { use DocumentResponse::*; operation.pseudo_hash().hash(&mut self.state_identifier); @@ -590,7 +589,7 @@ impl Document { font_style, } => { let font = Font::new(font_name, font_style); - let layer_text = TextLayer::new(text, style, size, font, font_cache); + let layer_text = TextLayer::new(text, style, size, font, render_data); let layer_data = LayerDataType::Text(layer_text); let layer = Layer::new(layer_data, transform); @@ -598,20 +597,6 @@ impl Document { Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(&path)].concat()) } - Operation::AddImage { - path, - transform, - insert_index, - image_data, - mime, - } => { - let image_data = std::sync::Arc::new(image_data); - let layer = Layer::new(LayerDataType::Image(ImageLayer::new(mime, image_data)), transform); - - self.set_layer(&path, layer, insert_index)?; - - Some([vec![DocumentChanged, CreatedLayer { path: path.clone() }], update_thumbnails_upstream(&path)].concat()) - } Operation::AddNodeGraphFrame { path, insert_index, @@ -658,7 +643,7 @@ impl Document { .layer_mut(id) .ok_or_else(|| DocumentError::LayerNotFound(path.clone()))? .as_text_mut()? - .update_text(new_text, font_cache); + .update_text(new_text, render_data); self.mark_as_dirty(&path)?; @@ -808,7 +793,7 @@ impl Document { text.font = Font::new(font_family, font_style); text.size = size; - text.cached_path = Some(text.generate_path(text.load_face(font_cache))); + text.cached_path = Some(text.generate_path(text.load_face(render_data))); self.mark_as_dirty(&path)?; Some([vec![DocumentChanged, LayerChanged { path: path.clone() }], update_thumbnails_upstream(&path)].concat()) } @@ -836,18 +821,14 @@ impl Document { Some([vec![DocumentChanged], update_thumbnails_upstream(&path)].concat()) } Operation::SetLayerBlobUrl { layer_path, blob_url, resolution } => { - let layer = self.layer_mut(&layer_path).unwrap_or_else(|_| panic!("Blob url for invalid layer with path '{:?}'", layer_path)); - match &mut layer.data { - LayerDataType::Image(image) => { - image.blob_url = Some(blob_url); - image.dimensions = resolution.into(); - } - LayerDataType::NodeGraphFrame(node_graph_frame) => { - node_graph_frame.blob_url = Some(blob_url); - node_graph_frame.dimensions = resolution.into(); - } - _ => panic!("Incorrectly trying to set the image blob URL for a layer that is not an Image, NodeGraphFrame or Imaginate layer type"), - } + let layer = self.layer_mut(&layer_path).unwrap_or_else(|_| panic!("Blob URL for invalid layer with path '{:?}'", layer_path)); + + let LayerDataType::NodeGraphFrame(node_graph_frame) = &mut layer.data else { + panic!("Incorrectly trying to set the image blob URL for a layer that is not a NodeGraphFrame layer type"); + }; + + node_graph_frame.blob_url = Some(blob_url); + node_graph_frame.dimensions = resolution.into(); self.mark_as_dirty(&layer_path)?; Some([vec![DocumentChanged, LayerChanged { path: layer_path.clone() }], update_thumbnails_upstream(&layer_path)].concat()) @@ -1099,7 +1080,7 @@ impl Document { // Delete the layer if there are no longer any manipulator groups if (shape.manipulator_groups().len() - 1) == 0 { // Delegate deletion to DeleteLayer to update Layer Tree in frontend - match self.handle_operation(Operation::DeleteLayer { path: layer_path.clone() }, font_cache) { + match self.handle_operation(Operation::DeleteLayer { path: layer_path.clone() }, render_data) { Ok(Some(delete_responses)) => { responses.extend(delete_responses); responses.push(DocumentResponse::DeletedSelectedManipulatorPoints); @@ -1169,8 +1150,8 @@ fn update_thumbnails_upstream(path: &[LayerId]) -> Vec { responses } -pub fn pick_layer_safe_imaginate_resolution(layer: &Layer, font_cache: &FontCache) -> (u64, u64) { - let layer_bounds = layer.bounding_transform(font_cache); +pub fn pick_layer_safe_imaginate_resolution(layer: &Layer, render_data: &RenderData) -> (u64, u64) { + let layer_bounds = layer.bounding_transform(render_data); let layer_bounds_size = (layer_bounds.transform_vector2((1., 0.).into()).length(), layer_bounds.transform_vector2((0., 1.).into()).length()); pick_safe_imaginate_resolution(layer_bounds_size) diff --git a/document-legacy/src/layers/folder_layer.rs b/document-legacy/src/layers/folder_layer.rs index f7b9b3b31..7b15ac690 100644 --- a/document-legacy/src/layers/folder_layer.rs +++ b/document-legacy/src/layers/folder_layer.rs @@ -1,7 +1,6 @@ use super::layer_info::{Layer, LayerData, LayerDataType}; use super::style::RenderData; use crate::intersection::Quad; -use crate::layers::text_layer::FontCache; use crate::{DocumentError, LayerId}; use glam::DVec2; @@ -21,7 +20,7 @@ pub struct FolderLayer { } impl LayerData for FolderLayer { - fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { + fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool { let mut any_child_requires_redraw = false; for layer in &mut self.layers { let (svg_value, requires_redraw) = layer.render(transforms, svg_defs, render_data); @@ -31,18 +30,18 @@ impl LayerData for FolderLayer { any_child_requires_redraw } - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache) { + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData) { for (layer, layer_id) in self.layers().iter().zip(&self.layer_ids) { path.push(*layer_id); - layer.intersects_quad(quad, path, intersections, font_cache); + layer.intersects_quad(quad, path, intersections, render_data); path.pop(); } } - fn bounding_box(&self, transform: glam::DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]> { + fn bounding_box(&self, transform: glam::DAffine2, render_data: &RenderData) -> Option<[DVec2; 2]> { self.layers .iter() - .filter_map(|layer| layer.data.bounding_box(transform * layer.transform, font_cache)) + .filter_map(|layer| layer.data.bounding_box(transform * layer.transform, render_data)) .reduce(|a, b| [a[0].min(b[0]), a[1].max(b[1])]) } } diff --git a/document-legacy/src/layers/image_layer.rs b/document-legacy/src/layers/image_layer.rs deleted file mode 100644 index fd11e6f3f..000000000 --- a/document-legacy/src/layers/image_layer.rs +++ /dev/null @@ -1,116 +0,0 @@ -use super::base64_serde; -use super::layer_info::LayerData; -use super::style::{RenderData, ViewMode}; -use crate::intersection::{intersect_quad_bez_path, Quad}; -use crate::layers::text_layer::FontCache; -use crate::LayerId; - -use glam::{DAffine2, DMat2, DVec2}; -use kurbo::{Affine, BezPath, Shape as KurboShape}; -use serde::{Deserialize, Serialize}; -use std::fmt::Write; - -#[derive(Clone, PartialEq, Deserialize, Serialize, specta::Type)] -pub struct ImageLayer { - pub mime: String, - #[serde(serialize_with = "base64_serde::as_base64", deserialize_with = "base64_serde::from_base64")] - #[specta(type = String)] - pub image_data: std::sync::Arc>, - // TODO: Have the browser dispose of this blob URL when this is dropped (like when the layer is deleted) - #[serde(skip)] - pub blob_url: Option, - #[serde(skip)] - pub dimensions: DVec2, -} - -impl LayerData for ImageLayer { - fn render(&mut self, svg: &mut String, _svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { - let transform = self.transform(transforms, render_data.view_mode); - let inverse = transform.inverse(); - - if !inverse.is_finite() { - let _ = write!(svg, ""); - return false; - } - - let _ = writeln!(svg, r#""#); - - let svg_transform = transform - .to_cols_array() - .iter() - .enumerate() - .map(|(i, entry)| entry.to_string() + if i == 5 { "" } else { "," }) - .collect::(); - let _ = write!( - svg, - r#""#, - self.dimensions.x, - self.dimensions.y, - svg_transform, - self.blob_url.as_ref().unwrap_or(&String::new()) - ); - let _ = svg.write_str(""); - - false - } - - fn bounding_box(&self, transform: glam::DAffine2, _font_cache: &FontCache) -> Option<[DVec2; 2]> { - let mut path = self.bounds(); - - if transform.matrix2 == DMat2::ZERO { - return None; - } - path.apply_affine(glam_to_kurbo(transform)); - - let kurbo::Rect { x0, y0, x1, y1 } = path.bounding_box(); - Some([(x0, y0).into(), (x1, y1).into()]) - } - - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, _font_cache: &FontCache) { - if intersect_quad_bez_path(quad, &self.bounds(), true) { - intersections.push(path.clone()); - } - } -} - -impl ImageLayer { - pub fn new(mime: String, image_data: std::sync::Arc>) -> Self { - Self { - mime, - image_data, - blob_url: None, - dimensions: DVec2::ONE, - } - } - - pub fn transform(&self, transforms: &[DAffine2], mode: ViewMode) -> DAffine2 { - let start = match mode { - ViewMode::Outline => 0, - _ => (transforms.len() as i32 - 1).max(0) as usize, - }; - transforms.iter().skip(start).cloned().reduce(|a, b| a * b).unwrap_or(DAffine2::IDENTITY) - } - - fn bounds(&self) -> BezPath { - kurbo::Rect::from_origin_size(kurbo::Point::ZERO, kurbo::Size::new(self.dimensions.x, self.dimensions.y)).to_path(0.) - } -} - -impl std::fmt::Debug for ImageLayer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("ImageLayer") - .field("mime", &self.mime) - .field("image_data", &"...") - .field("blob_url", &self.blob_url) - .field("dimensions", &self.dimensions) - .finish() - } -} - -fn glam_to_kurbo(transform: DAffine2) -> Affine { - Affine::new(transform.to_cols_array()) -} diff --git a/document-legacy/src/layers/layer_info.rs b/document-legacy/src/layers/layer_info.rs index 8ebac6317..d1c7a2077 100644 --- a/document-legacy/src/layers/layer_info.rs +++ b/document-legacy/src/layers/layer_info.rs @@ -1,12 +1,10 @@ use super::blend_mode::BlendMode; use super::folder_layer::FolderLayer; -use super::image_layer::ImageLayer; use super::nodegraph_layer::NodeGraphFrameLayer; use super::shape_layer::ShapeLayer; use super::style::{PathStyle, RenderData}; use super::text_layer::TextLayer; use crate::intersection::Quad; -use crate::layers::text_layer::FontCache; use crate::DocumentError; use crate::LayerId; @@ -26,8 +24,6 @@ pub enum LayerDataType { Shape(ShapeLayer), /// A layer that wraps a [TextLayer] struct. Text(TextLayer), - /// A layer that wraps an [ImageLayer] struct. - Image(ImageLayer), /// A layer that wraps an [NodeGraphFrameLayer] struct. NodeGraphFrame(NodeGraphFrameLayer), } @@ -38,7 +34,6 @@ impl LayerDataType { LayerDataType::Shape(s) => s, LayerDataType::Folder(f) => f, LayerDataType::Text(t) => t, - LayerDataType::Image(i) => i, LayerDataType::NodeGraphFrame(n) => n, } } @@ -48,7 +43,6 @@ impl LayerDataType { LayerDataType::Shape(s) => s, LayerDataType::Folder(f) => f, LayerDataType::Text(t) => t, - LayerDataType::Image(i) => i, LayerDataType::NodeGraphFrame(n) => n, } } @@ -83,7 +77,6 @@ impl From<&LayerDataType> for LayerDataTypeDiscriminant { Folder(_) => LayerDataTypeDiscriminant::Folder, Shape(_) => LayerDataTypeDiscriminant::Shape, Text(_) => LayerDataTypeDiscriminant::Text, - Image(_) => LayerDataTypeDiscriminant::Image, NodeGraphFrame(_) => LayerDataTypeDiscriminant::NodeGraphFrame, } } @@ -133,8 +126,8 @@ pub trait LayerData { /// /// // Render the shape without any transforms, in normal view mode /// # let font_cache = Default::default(); - /// let render_data = RenderData::new(ViewMode::Normal, &font_cache, None); - /// shape.render(&mut svg, &mut String::new(), &mut vec![], render_data); + /// let render_data = RenderData::new(&font_cache, ViewMode::Normal, None); + /// shape.render(&mut svg, &mut String::new(), &mut vec![], &render_data); /// /// assert_eq!( /// svg, @@ -143,13 +136,13 @@ pub trait LayerData { /// " /// ); /// ``` - fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool; + fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool; /// Determine the layers within this layer that intersect a given quad. /// # Example /// ``` /// # use graphite_document_legacy::layers::shape_layer::ShapeLayer; - /// # use graphite_document_legacy::layers::style::{Fill, PathStyle, ViewMode}; + /// # use graphite_document_legacy::layers::style::{Fill, PathStyle, ViewMode, RenderData}; /// # use graphite_document_legacy::layers::layer_info::LayerData; /// # use graphite_document_legacy::intersection::Quad; /// # use glam::f64::{DAffine2, DVec2}; @@ -162,18 +155,20 @@ pub trait LayerData { /// let quad = Quad::from_box([DVec2::ZERO, DVec2::ONE]); /// let mut intersections = vec![]; /// - /// shape.intersects_quad(quad, &mut vec![shape_id], &mut intersections, &Default::default()); + /// let font_cache = Default::default(); + /// let render_data = RenderData::new(&font_cache, Default::default(), None); + /// shape.intersects_quad(quad, &mut vec![shape_id], &mut intersections, &render_data); /// /// assert_eq!(intersections, vec![vec![shape_id]]); /// ``` - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache); + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData); // TODO: this doctest fails because 0 != 1e-32, maybe assert difference < epsilon? /// Calculate the bounding box for the layer's contents after applying a given transform. /// # Example /// ```no_run /// # use graphite_document_legacy::layers::shape_layer::ShapeLayer; - /// # use graphite_document_legacy::layers::style::{Fill, PathStyle}; + /// # use graphite_document_legacy::layers::style::{Fill, PathStyle, RenderData}; /// # use graphite_document_legacy::layers::layer_info::LayerData; /// # use glam::f64::{DAffine2, DVec2}; /// # use std::collections::HashMap; @@ -182,24 +177,26 @@ pub trait LayerData { /// // Calculate the bounding box without applying any transformations. /// // (The identity transform maps every vector to itself.) /// let transform = DAffine2::IDENTITY; - /// let bounding_box = shape.bounding_box(transform, &Default::default()); + /// let font_cache = Default::default(); + /// let render_data = RenderData::new(&font_cache, Default::default(), None); + /// let bounding_box = shape.bounding_box(transform, &render_data); /// /// assert_eq!(bounding_box, Some([DVec2::ZERO, DVec2::ONE])); /// ``` - fn bounding_box(&self, transform: glam::DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]>; + fn bounding_box(&self, transform: glam::DAffine2, render_data: &RenderData) -> Option<[DVec2; 2]>; } impl LayerData for LayerDataType { - fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { + fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool { self.inner_mut().render(svg, svg_defs, transforms, render_data) } - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache) { - self.inner().intersects_quad(quad, path, intersections, font_cache) + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData) { + self.inner().intersects_quad(quad, path, intersections, render_data) } - fn bounding_box(&self, transform: glam::DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]> { - self.inner().bounding_box(transform, font_cache) + fn bounding_box(&self, transform: glam::DAffine2, render_data: &RenderData) -> Option<[DVec2; 2]> { + self.inner().bounding_box(transform, render_data) } } @@ -305,7 +302,7 @@ impl Layer { } /// Renders the layer, returning the result and if a redraw is required - pub fn render(&mut self, transforms: &mut Vec, svg_defs: &mut String, render_data: RenderData) -> (&str, bool) { + pub fn render(&mut self, transforms: &mut Vec, svg_defs: &mut String, render_data: &RenderData) -> (&str, bool) { if !self.visible { return ("", false); } @@ -314,10 +311,7 @@ impl Layer { // Skip rendering if outside the viewport bounds if let Some(viewport_bounds) = render_data.culling_bounds { - if let Some(bounding_box) = self - .data - .bounding_box(transforms.iter().cloned().reduce(|a, b| a * b).unwrap_or(DAffine2::IDENTITY), render_data.font_cache) - { + if let Some(bounding_box) = self.data.bounding_box(transforms.iter().cloned().reduce(|a, b| a * b).unwrap_or(DAffine2::IDENTITY), render_data) { let is_overlapping = viewport_bounds[0].x < bounding_box[1].x && bounding_box[0].x < viewport_bounds[1].x && viewport_bounds[0].y < bounding_box[1].y && bounding_box[0].y < viewport_bounds[1].y; if !is_overlapping { @@ -363,13 +357,13 @@ impl Layer { (self.cache.as_str(), requires_redraw) } - pub fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache) { + pub fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData) { if !self.visible { return; } let transformed_quad = self.transform.inverse() * quad; - self.data.intersects_quad(transformed_quad, path, intersections, font_cache) + self.data.intersects_quad(transformed_quad, path, intersections, render_data) } /// Compute the bounding box of the layer after applying a transform to it. @@ -378,7 +372,7 @@ impl Layer { /// ``` /// # use graphite_document_legacy::layers::shape_layer::ShapeLayer; /// # use graphite_document_legacy::layers::layer_info::Layer; - /// # use graphite_document_legacy::layers::style::PathStyle; + /// # use graphite_document_legacy::layers::style::{PathStyle, RenderData}; /// # use glam::DVec2; /// # use glam::f64::DAffine2; /// # use std::collections::HashMap; @@ -386,27 +380,30 @@ impl Layer { /// let layer: Layer = ShapeLayer::rectangle(PathStyle::default()).into(); /// /// // Apply the Identity transform, which leaves the points unchanged + /// let transform = DAffine2::IDENTITY; + /// let font_cache = Default::default(); + /// let render_data = RenderData::new(&font_cache, Default::default(), None); /// assert_eq!( - /// layer.aabb_for_transform(DAffine2::IDENTITY, &Default::default()), + /// layer.aabb_for_transform(transform, &render_data), /// Some([DVec2::ZERO, DVec2::ONE]), /// ); /// /// // Apply a transform that scales every point by a factor of two /// let transform = DAffine2::from_scale(DVec2::ONE * 2.); /// assert_eq!( - /// layer.aabb_for_transform(transform, &Default::default()), + /// layer.aabb_for_transform(transform, &render_data), /// Some([DVec2::ZERO, DVec2::ONE * 2.]), /// ); - pub fn aabb_for_transform(&self, transform: DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]> { - self.data.bounding_box(transform, font_cache) + pub fn aabb_for_transform(&self, transform: DAffine2, render_data: &RenderData) -> Option<[DVec2; 2]> { + self.data.bounding_box(transform, render_data) } - pub fn aabb(&self, font_cache: &FontCache) -> Option<[DVec2; 2]> { - self.aabb_for_transform(self.transform, font_cache) + pub fn aabb(&self, render_data: &RenderData) -> Option<[DVec2; 2]> { + self.aabb_for_transform(self.transform, render_data) } - pub fn bounding_transform(&self, font_cache: &FontCache) -> DAffine2 { - let scale = match self.aabb_for_transform(DAffine2::IDENTITY, font_cache) { + pub fn bounding_transform(&self, render_data: &RenderData) -> DAffine2 { + let scale = match self.aabb_for_transform(DAffine2::IDENTITY, render_data) { Some([a, b]) => { let dimensions = b - a; DAffine2::from_scale(dimensions) @@ -417,8 +414,8 @@ impl Layer { self.transform * scale } - pub fn layerspace_pivot(&self, font_cache: &FontCache) -> DVec2 { - let [mut min, max] = self.aabb_for_transform(DAffine2::IDENTITY, font_cache).unwrap_or([DVec2::ZERO, DVec2::ONE]); + pub fn layerspace_pivot(&self, render_data: &RenderData) -> DVec2 { + let [mut min, max] = self.aabb_for_transform(DAffine2::IDENTITY, render_data).unwrap_or([DVec2::ZERO, DVec2::ONE]); // If the layer bounds are 0 in either axis then set them to one (to avoid div 0) if (max.x - min.x) < f64::EPSILON * 1000. { @@ -560,12 +557,6 @@ impl From for Layer { } } -impl From for Layer { - fn from(from: ImageLayer) -> Layer { - Layer::new(LayerDataType::Image(from), DAffine2::IDENTITY.to_cols_array()) - } -} - impl<'a> IntoIterator for &'a Layer { type Item = &'a Layer; type IntoIter = LayerIter<'a>; diff --git a/document-legacy/src/layers/mod.rs b/document-legacy/src/layers/mod.rs index ac32fab0d..94306fa1a 100644 --- a/document-legacy/src/layers/mod.rs +++ b/document-legacy/src/layers/mod.rs @@ -5,8 +5,7 @@ //! * [Folder layers](folder_layer::FolderLayer), which encapsulate sub-layers //! * [Shape layers](shape_layer::ShapeLayer), which contain generic SVG [``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path)s //! * [Text layers](text_layer::TextLayer), which contain a description of laid out text -//! * [Image layers](image_layer::ImageLayer), which contain a bitmap image -//! * [Nodegraph layers](nodegraph_layer::NodegraphLayer), which contain a node graph frame +//! * [Node Graph layers](nodegraph_layer::NodegraphLayer), which contain a node graph frame //! //! Refer to the module-level documentation for detailed information on each layer. //! @@ -20,8 +19,6 @@ pub mod base64_serde; pub mod blend_mode; /// Contains the [FolderLayer](folder_layer::FolderLayer) type that encapsulates other layers, including more folders. pub mod folder_layer; -/// Contains the [ImageLayer](image_layer::ImageLayer) type that contains a bitmap image. -pub mod image_layer; /// Contains the base [Layer](layer_info::Layer) type, an abstraction over the different types of layers. pub mod layer_info; /// Contains the [NodegraphLayer](nodegraph_layer::NodegraphLayer) type that contains a node graph. diff --git a/document-legacy/src/layers/nodegraph_layer.rs b/document-legacy/src/layers/nodegraph_layer.rs index 9106e05aa..4ce26c3bd 100644 --- a/document-legacy/src/layers/nodegraph_layer.rs +++ b/document-legacy/src/layers/nodegraph_layer.rs @@ -2,7 +2,6 @@ use super::base64_serde; use super::layer_info::LayerData; use super::style::{RenderData, ViewMode}; use crate::intersection::{intersect_quad_bez_path, Quad}; -use crate::layers::text_layer::FontCache; use crate::LayerId; use glam::{DAffine2, DMat2, DVec2}; @@ -34,7 +33,7 @@ pub struct ImageData { } impl LayerData for NodeGraphFrameLayer { - fn render(&mut self, svg: &mut String, _svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { + fn render(&mut self, svg: &mut String, _svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool { let transform = self.transform(transforms, render_data.view_mode); let inverse = transform.inverse(); @@ -81,7 +80,7 @@ impl LayerData for NodeGraphFrameLayer { false } - fn bounding_box(&self, transform: glam::DAffine2, _font_cache: &FontCache) -> Option<[DVec2; 2]> { + fn bounding_box(&self, transform: glam::DAffine2, _render_data: &RenderData) -> Option<[DVec2; 2]> { let mut path = self.bounds(); if transform.matrix2 == DMat2::ZERO { @@ -93,7 +92,7 @@ impl LayerData for NodeGraphFrameLayer { Some([(x0, y0).into(), (x1, y1).into()]) } - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, _font_cache: &FontCache) { + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, _render_data: &RenderData) { if intersect_quad_bez_path(quad, &self.bounds(), true) { intersections.push(path.clone()); } diff --git a/document-legacy/src/layers/shape_layer.rs b/document-legacy/src/layers/shape_layer.rs index b53392c02..48873ba3d 100644 --- a/document-legacy/src/layers/shape_layer.rs +++ b/document-legacy/src/layers/shape_layer.rs @@ -1,7 +1,6 @@ use super::layer_info::LayerData; use super::style::{self, PathStyle, RenderData, ViewMode}; use crate::intersection::{intersect_quad_bez_path, Quad}; -use crate::layers::text_layer::FontCache; use crate::LayerId; use graphene_std::vector::subpath::Subpath; @@ -27,7 +26,7 @@ pub struct ShapeLayer { } impl LayerData for ShapeLayer { - fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { + fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool { let mut subpath = self.shape.clone(); let layer_bounds = subpath.bounding_box().unwrap_or_default(); @@ -58,7 +57,7 @@ impl LayerData for ShapeLayer { false } - fn bounding_box(&self, transform: glam::DAffine2, _font_cache: &FontCache) -> Option<[DVec2; 2]> { + fn bounding_box(&self, transform: glam::DAffine2, _render_data: &RenderData) -> Option<[DVec2; 2]> { let mut subpath = self.shape.clone(); if transform.matrix2 == DMat2::ZERO { return None; @@ -68,7 +67,7 @@ impl LayerData for ShapeLayer { subpath.bounding_box() } - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, _font_cache: &FontCache) { + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, _render_data: &RenderData) { let filled = self.style.fill().is_some() || self.shape.manipulator_groups().last().filter(|manipulator_group| manipulator_group.is_close()).is_some(); if intersect_quad_bez_path(quad, &(&self.shape).into(), filled) { intersections.push(path.clone()); diff --git a/document-legacy/src/layers/style/mod.rs b/document-legacy/src/layers/style/mod.rs index e6507d14f..bf0884280 100644 --- a/document-legacy/src/layers/style/mod.rs +++ b/document-legacy/src/layers/style/mod.rs @@ -35,16 +35,16 @@ pub enum ViewMode { /// Contains metadata for rendering the document as an svg #[derive(Debug, Clone, Copy)] pub struct RenderData<'a> { - pub view_mode: ViewMode, pub font_cache: &'a FontCache, + pub view_mode: ViewMode, pub culling_bounds: Option<[DVec2; 2]>, } impl<'a> RenderData<'a> { - pub fn new(view_mode: ViewMode, font_cache: &'a FontCache, culling_bounds: Option<[DVec2; 2]>) -> Self { + pub fn new(font_cache: &'a FontCache, view_mode: ViewMode, culling_bounds: Option<[DVec2; 2]>) -> Self { Self { - view_mode, font_cache, + view_mode, culling_bounds, } } diff --git a/document-legacy/src/layers/text_layer.rs b/document-legacy/src/layers/text_layer.rs index 4f061d460..2c7a51842 100644 --- a/document-legacy/src/layers/text_layer.rs +++ b/document-legacy/src/layers/text_layer.rs @@ -34,7 +34,7 @@ pub struct TextLayer { } impl LayerData for TextLayer { - fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: RenderData) -> bool { + fn render(&mut self, svg: &mut String, svg_defs: &mut String, transforms: &mut Vec, render_data: &RenderData) -> bool { let transform = self.transform(transforms, render_data.view_mode); let inverse = transform.inverse(); @@ -67,7 +67,7 @@ impl LayerData for TextLayer { font.map(|_| r#" style="font-family: local-font;""#).unwrap_or_default() ); } else { - let buzz_face = self.load_face(render_data.font_cache); + let buzz_face = self.load_face(render_data); let mut path = self.to_subpath(buzz_face); @@ -89,8 +89,8 @@ impl LayerData for TextLayer { false } - fn bounding_box(&self, transform: glam::DAffine2, font_cache: &FontCache) -> Option<[DVec2; 2]> { - let buzz_face = Some(self.load_face(font_cache)?); + fn bounding_box(&self, transform: glam::DAffine2, render_data: &RenderData) -> Option<[DVec2; 2]> { + let buzz_face = Some(self.load_face(render_data)?); if transform.matrix2 == DMat2::ZERO { return None; @@ -99,8 +99,8 @@ impl LayerData for TextLayer { Some((transform * self.bounding_box(&self.text, buzz_face)).bounding_box()) } - fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, font_cache: &FontCache) { - let buzz_face = self.load_face(font_cache); + fn intersects_quad(&self, quad: Quad, path: &mut Vec, intersections: &mut Vec>, render_data: &RenderData) { + let buzz_face = self.load_face(render_data); if intersect_quad_bez_path(quad, &self.bounding_box(&self.text, buzz_face).path(), true) { intersections.push(path.clone()); @@ -109,8 +109,8 @@ impl LayerData for TextLayer { } impl TextLayer { - pub fn load_face<'a>(&self, font_cache: &'a FontCache) -> Option> { - font_cache.get(&self.font).map(|data| rustybuzz::Face::from_slice(data, 0).expect("Loading font failed")) + pub fn load_face<'a>(&self, render_data: &'a RenderData) -> Option> { + render_data.font_cache.get(&self.font).map(|data| rustybuzz::Face::from_slice(data, 0).expect("Loading font failed")) } pub fn transform(&self, transforms: &[DAffine2], mode: ViewMode) -> DAffine2 { @@ -121,7 +121,7 @@ impl TextLayer { transforms.iter().skip(start).cloned().reduce(|a, b| a * b).unwrap_or(DAffine2::IDENTITY) } - pub fn new(text: String, style: PathStyle, size: f64, font: Font, font_cache: &FontCache) -> Self { + pub fn new(text: String, style: PathStyle, size: f64, font: Font, render_data: &RenderData) -> Self { let mut new = Self { text, path_style: style, @@ -132,7 +132,7 @@ impl TextLayer { cached_path: None, }; - new.cached_path = Some(new.generate_path(new.load_face(font_cache))); + new.cached_path = Some(new.generate_path(new.load_face(render_data))); new } @@ -150,8 +150,8 @@ impl TextLayer { /// Converts to a [Subpath], without populating the cache. #[inline] - pub fn to_subpath_nonmut(&self, font_cache: &FontCache) -> Subpath { - let buzz_face = self.load_face(font_cache); + pub fn to_subpath_nonmut(&self, render_data: &RenderData) -> Subpath { + let buzz_face = self.load_face(render_data); self.cached_path .clone() @@ -170,8 +170,8 @@ impl TextLayer { Quad::from_box([DVec2::ZERO, far]) } - pub fn update_text(&mut self, text: String, font_cache: &FontCache) { - let buzz_face = self.load_face(font_cache); + pub fn update_text(&mut self, text: String, render_data: &RenderData) { + let buzz_face = self.load_face(render_data); self.text = text; self.cached_path = Some(self.generate_path(buzz_face)); diff --git a/document-legacy/src/operation.rs b/document-legacy/src/operation.rs index 409063096..01f4b1f02 100644 --- a/document-legacy/src/operation.rs +++ b/document-legacy/src/operation.rs @@ -45,13 +45,6 @@ pub enum Operation { font_name: String, font_style: String, }, - AddImage { - path: Vec, - insert_index: isize, - transform: [f64; 6], - mime: String, - image_data: Vec, - }, AddNodeGraphFrame { path: Vec, insert_index: isize, diff --git a/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs b/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs index 69a242580..d242cfd2e 100644 --- a/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs +++ b/editor/src/messages/portfolio/document/artboard/artboard_message_handler.rs @@ -1,10 +1,10 @@ use crate::application::generate_uuid; +use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::*; use document_legacy::color::Color; use document_legacy::document::Document as DocumentLegacy; use document_legacy::layers::style::{self, Fill, RenderData, ViewMode}; -use document_legacy::layers::text_layer::FontCache; use document_legacy::DocumentResponse; use document_legacy::LayerId; use document_legacy::Operation as DocumentOperation; @@ -18,30 +18,34 @@ pub struct ArtboardMessageHandler { pub artboard_ids: Vec, } -impl MessageHandler for ArtboardMessageHandler { +impl MessageHandler for ArtboardMessageHandler { #[remain::check] - fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque, font_cache: &FontCache) { + fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque, persistent_data: &PersistentData) { use ArtboardMessage::*; #[remain::sorted] match message { // Sub-messages #[remain::unsorted] - DispatchOperation(operation) => match self.artboards_document.handle_operation(*operation, font_cache) { - Ok(Some(document_responses)) => { - for response in document_responses { - match &response { - DocumentResponse::LayerChanged { path } => responses.push_back(PropertiesPanelMessage::CheckSelectedWasUpdated { path: path.clone() }.into()), - DocumentResponse::DeletedLayer { path } => responses.push_back(PropertiesPanelMessage::CheckSelectedWasDeleted { path: path.clone() }.into()), - DocumentResponse::DocumentChanged => responses.push_back(ArtboardMessage::RenderArtboards.into()), - _ => {} - }; - responses.push_back(BroadcastEvent::DocumentIsDirty.into()); + DispatchOperation(operation) => { + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, None); + + match self.artboards_document.handle_operation(*operation, &render_data) { + Ok(Some(document_responses)) => { + for response in document_responses { + match &response { + DocumentResponse::LayerChanged { path } => responses.push_back(PropertiesPanelMessage::CheckSelectedWasUpdated { path: path.clone() }.into()), + DocumentResponse::DeletedLayer { path } => responses.push_back(PropertiesPanelMessage::CheckSelectedWasDeleted { path: path.clone() }.into()), + DocumentResponse::DocumentChanged => responses.push_back(ArtboardMessage::RenderArtboards.into()), + _ => {} + }; + responses.push_back(BroadcastEvent::DocumentIsDirty.into()); + } } + Ok(None) => {} + Err(e) => error!("Artboard Error: {:?}", e), } - Ok(None) => {} - Err(e) => error!("Artboard Error: {:?}", e), - }, + } // Messages AddArtboard { id, position, size } => { @@ -85,10 +89,10 @@ impl MessageHandler for ArtboardMessageHandler { .into(), ) } else { - let render_data = RenderData::new(ViewMode::Normal, font_cache, None); + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, None); responses.push_back( FrontendMessage::UpdateDocumentArtboards { - svg: self.artboards_document.render_root(render_data), + svg: self.artboards_document.render_root(&render_data), } .into(), ); diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index acf3d59ec..30689a13e 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -29,7 +29,7 @@ use document_legacy::layers::blend_mode::BlendMode; use document_legacy::layers::folder_layer::FolderLayer; use document_legacy::layers::layer_info::{LayerDataType, LayerDataTypeDiscriminant}; use document_legacy::layers::style::{Fill, RenderData, ViewMode}; -use document_legacy::layers::text_layer::{Font, FontCache}; +use document_legacy::layers::text_layer::Font; use document_legacy::{DocumentError, DocumentResponse, LayerId, Operation as DocumentOperation}; use graph_craft::document::NodeId; use graphene_std::vector::subpath::Subpath; @@ -114,70 +114,74 @@ impl MessageHandler match self.document_legacy.handle_operation(*op, &persistent_data.font_cache) { - Ok(Some(document_responses)) => { - for response in document_responses { - match &response { - DocumentResponse::FolderChanged { path } => responses.push_back(FolderChanged { affected_folder_path: path.clone() }.into()), - DocumentResponse::DeletedLayer { path } => { - self.layer_metadata.remove(path); - } - DocumentResponse::LayerChanged { path } => responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()), - DocumentResponse::CreatedLayer { path } => { - if self.layer_metadata.contains_key(path) { - warn!("CreatedLayer overrides existing layer metadata."); + DispatchOperation(op) => { + match self.document_legacy.handle_operation(*op, &render_data) { + Ok(Some(document_responses)) => { + for response in document_responses { + match &response { + DocumentResponse::FolderChanged { path } => responses.push_back(FolderChanged { affected_folder_path: path.clone() }.into()), + DocumentResponse::DeletedLayer { path } => { + self.layer_metadata.remove(path); } - self.layer_metadata.insert(path.clone(), LayerMetadata::new(false)); + DocumentResponse::LayerChanged { path } => responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()), + DocumentResponse::CreatedLayer { path } => { + if self.layer_metadata.contains_key(path) { + warn!("CreatedLayer overrides existing layer metadata."); + } + self.layer_metadata.insert(path.clone(), LayerMetadata::new(false)); - responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()); - self.layer_range_selection_reference = path.clone(); - responses.push_back( - AddSelectedLayers { - additional_layers: vec![path.clone()], - } - .into(), - ); - } - DocumentResponse::DocumentChanged => responses.push_back(RenderDocument.into()), - DocumentResponse::DeletedSelectedManipulatorPoints => { - // Clear Properties panel after deleting all points by updating backend widget state. - responses.push_back( - LayoutMessage::SendLayout { - layout: Layout::WidgetLayout(WidgetLayout::new(vec![])), - layout_target: LayoutTarget::PropertiesOptions, - } - .into(), - ); - responses.push_back( - LayoutMessage::SendLayout { - layout: Layout::WidgetLayout(WidgetLayout::new(vec![])), - layout_target: LayoutTarget::PropertiesSections, - } - .into(), - ); - } - }; - responses.push_back(BroadcastEvent::DocumentIsDirty.into()); + responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()); + self.layer_range_selection_reference = path.clone(); + responses.push_back( + AddSelectedLayers { + additional_layers: vec![path.clone()], + } + .into(), + ); + } + DocumentResponse::DocumentChanged => responses.push_back(RenderDocument.into()), + DocumentResponse::DeletedSelectedManipulatorPoints => { + // Clear Properties panel after deleting all points by updating backend widget state. + responses.push_back( + LayoutMessage::SendLayout { + layout: Layout::WidgetLayout(WidgetLayout::new(vec![])), + layout_target: LayoutTarget::PropertiesOptions, + } + .into(), + ); + responses.push_back( + LayoutMessage::SendLayout { + layout: Layout::WidgetLayout(WidgetLayout::new(vec![])), + layout_target: LayoutTarget::PropertiesSections, + } + .into(), + ); + } + }; + responses.push_back(BroadcastEvent::DocumentIsDirty.into()); + } } + // Display boolean operation error to the user (except if it is a nothing done error). + Err(DocumentError::BooleanOperationError(boolean_operation_error)) if boolean_operation_error != BooleanOperationError::NothingDone => responses.push_back( + DialogMessage::DisplayDialogError { + title: "Failed to calculate boolean operation".into(), + description: format!("Unfortunately, this feature not that robust yet.\n\nError: {boolean_operation_error:?}"), + } + .into(), + ), + Err(e) => error!("DocumentError: {:?}", e), + Ok(_) => (), } - // Display boolean operation error to the user (except if it is a nothing done error). - Err(DocumentError::BooleanOperationError(boolean_operation_error)) if boolean_operation_error != BooleanOperationError::NothingDone => responses.push_back( - DialogMessage::DisplayDialogError { - title: "Failed to calculate boolean operation".into(), - description: format!("Unfortunately, this feature not that robust yet.\n\nError: {boolean_operation_error:?}"), - } - .into(), - ), - Err(e) => error!("DocumentError: {:?}", e), - Ok(_) => (), - }, + } #[remain::unsorted] Artboard(message) => { - self.artboard_message_handler.process_message(message, responses, &persistent_data.font_cache); + self.artboard_message_handler.process_message(message, responses, persistent_data); } #[remain::unsorted] Navigation(message) => { @@ -185,13 +189,12 @@ impl MessageHandler { - self.overlays_message_handler - .process_message(message, responses, (self.overlays_visible, &persistent_data.font_cache, ipp)); + self.overlays_message_handler.process_message(message, responses, (self.overlays_visible, persistent_data, ipp)); } #[remain::unsorted] TransformLayer(message) => { self.transform_layer_handler - .process_message(message, responses, (&mut self.layer_metadata, &mut self.document_legacy, ipp, &persistent_data.font_cache)); + .process_message(message, responses, (&mut self.layer_metadata, &mut self.document_legacy, ipp, &render_data)); } #[remain::unsorted] PropertiesPanel(message) => { @@ -219,20 +222,20 @@ impl MessageHandler { for layer_path in &additional_layers { - responses.extend(self.select_layer(layer_path, &persistent_data.font_cache)); + responses.extend(self.select_layer(layer_path, &render_data)); } // TODO: Correctly update layer panel in clear_selection instead of here responses.push_back(FolderChanged { affected_folder_path: vec![] }.into()); responses.push_back(BroadcastEvent::SelectionChanged.into()); - self.update_layer_tree_options_bar_widgets(responses, &persistent_data.font_cache); + self.update_layer_tree_options_bar_widgets(responses, &render_data); } AlignSelectedLayers { axis, aggregate } => { self.backup(responses); let (paths, boxes): (Vec<_>, Vec<_>) = self .selected_layers() - .filter_map(|path| self.document_legacy.viewport_bounding_box(path, &persistent_data.font_cache).ok()?.map(|b| (path, b))) + .filter_map(|path| self.document_legacy.viewport_bounding_box(path, &render_data).ok()?.map(|b| (path, b))) .unzip(); let axis = match axis { @@ -240,7 +243,7 @@ impl MessageHandler DVec2::Y, }; let lerp = |bbox: &[DVec2; 2]| bbox[0].lerp(bbox[1], 0.5); - if let Some(combined_box) = self.document_legacy.combined_viewport_bounding_box(self.selected_layers(), &persistent_data.font_cache) { + if let Some(combined_box) = self.document_legacy.combined_viewport_bounding_box(self.selected_layers(), &render_data) { let aggregated = match aggregate { AlignAggregate::Min => combined_box[0], AlignAggregate::Max => combined_box[1], @@ -376,14 +379,9 @@ impl MessageHandler self.all_layer_bounds(&persistent_data.font_cache), - ExportBounds::Selection => self.selected_visible_layers_bounding_box(&persistent_data.font_cache), - ExportBounds::Artboard(id) => self - .artboard_message_handler - .artboards_document - .layer(&[id]) - .ok() - .and_then(|layer| layer.aabb(&persistent_data.font_cache)), + ExportBounds::AllArtwork => self.all_layer_bounds(&render_data), + ExportBounds::Selection => self.selected_visible_layers_bounding_box(&render_data), + ExportBounds::Artboard(id) => self.artboard_message_handler.artboards_document.layer(&[id]).ok().and_then(|layer| layer.aabb(&render_data)), } .unwrap_or_default(); let size = bounds[1] - bounds[0]; @@ -412,7 +410,7 @@ impl MessageHandler DVec2::new(-1., 1.), FlipAxis::Y => DVec2::new(1., -1.), }; - if let Some([min, max]) = self.document_legacy.combined_viewport_bounding_box(self.selected_layers(), &persistent_data.font_cache) { + if let Some([min, max]) = self.document_legacy.combined_viewport_bounding_box(self.selected_layers(), &render_data) { let center = (max + min) / 2.; let bbox_trans = DAffine2::from_translation(-center); for path in self.selected_layers() { @@ -483,11 +481,11 @@ impl MessageHandler { - if let Ok(layer_entry) = self.layer_panel_entry(affected_layer_path.clone(), &persistent_data.font_cache) { + if let Ok(layer_entry) = self.layer_panel_entry(affected_layer_path.clone(), &render_data) { responses.push_back(FrontendMessage::UpdateDocumentLayerDetails { data: layer_entry }.into()); } responses.push_back(PropertiesPanelMessage::CheckSelectedWasUpdated { path: affected_layer_path }.into()); - self.update_layer_tree_options_bar_widgets(responses, &persistent_data.font_cache); + self.update_layer_tree_options_bar_widgets(responses, &render_data); } MoveSelectedLayersTo { folder_path, @@ -632,10 +630,9 @@ impl MessageHandler responses.push_back(DocumentOperation::RenameLayer { layer_path, new_name }.into()), RenderDocument => { - let render_data = RenderData::new(self.view_mode, &persistent_data.font_cache, Some(ipp.document_bounds())); responses.push_back( FrontendMessage::UpdateDocumentArtwork { - svg: self.document_legacy.render_root(render_data), + svg: self.document_legacy.render_root(&render_data), } .into(), ); @@ -645,7 +642,7 @@ impl MessageHandler {} other => panic!( "Setting blob URL for invalid layer type, which must be an `Imaginate`, `NodeGraphFrame` or `Image`. Found: `{:?}`", other @@ -803,7 +799,7 @@ impl MessageHandler { - if let Some(layer) = self.layer_panel_entry_from_path(&layer_path, &persistent_data.font_cache) { + if let Some(layer) = self.layer_panel_entry_from_path(&layer_path, &render_data) { // Only save the history state if the name actually changed to something different if layer.name != name { self.backup(responses); @@ -926,7 +922,7 @@ impl MessageHandler { - if let Some(bounds) = self.document_bounds(&persistent_data.font_cache) { + if let Some(bounds) = self.document_bounds(&render_data) { responses.push_back( NavigationMessage::FitViewportToBounds { bounds, @@ -1057,14 +1053,14 @@ impl DocumentMessageHandler { pub fn render_document(&mut self, size: DVec2, transform: DAffine2, persistent_data: &PersistentData, render_mode: DocumentRenderMode) -> String { // Render the document SVG code - let render_data = RenderData::new(ViewMode::Normal, &persistent_data.font_cache, None); + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, None); let (artwork, outside) = match render_mode { - DocumentRenderMode::Root => (self.document_legacy.render_root(render_data), None), - DocumentRenderMode::OnlyBelowLayerInFolder(below_layer_path) => (self.document_legacy.render_layers_below(below_layer_path, render_data).unwrap(), None), - DocumentRenderMode::LayerCutout(layer_path, background) => (self.document_legacy.render_layer(layer_path, render_data).unwrap(), Some(background)), + DocumentRenderMode::Root => (self.document_legacy.render_root(&render_data), None), + DocumentRenderMode::OnlyBelowLayerInFolder(below_layer_path) => (self.document_legacy.render_layers_below(below_layer_path, &render_data).unwrap(), None), + DocumentRenderMode::LayerCutout(layer_path, background) => (self.document_legacy.render_layer(layer_path, &render_data).unwrap(), Some(background)), }; - let artboards = self.artboard_message_handler.artboards_document.render_root(render_data); + let artboards = self.artboard_message_handler.artboards_document.render_root(&render_data); let outside_artboards_color = outside.map_or_else( || if self.artboard_message_handler.artboard_ids.is_empty() { "ffffff" } else { "222222" }.to_string(), |col| col.rgba_hex(), @@ -1129,12 +1125,14 @@ impl DocumentMessageHandler { && self.name.starts_with(DEFAULT_DOCUMENT_NAME) } - fn select_layer(&mut self, path: &[LayerId], font_cache: &FontCache) -> Option { + fn select_layer(&mut self, path: &[LayerId], render_data: &RenderData) -> Option { println!("Select_layer fail: {:?}", self.all_layers_sorted()); if let Some(layer) = self.layer_metadata.get_mut(path) { + let render_data = RenderData::new(render_data.font_cache, self.view_mode, None); + layer.selected = true; - let data = self.layer_panel_entry(path.to_vec(), font_cache).ok()?; + let data = self.layer_panel_entry(path.to_vec(), &render_data).ok()?; (!path.is_empty()).then(|| FrontendMessage::UpdateDocumentLayerDetails { data }.into()) } else { warn!("Tried to select non existing layer {:?}", path); @@ -1142,13 +1140,13 @@ impl DocumentMessageHandler { } } - pub fn selected_visible_layers_bounding_box(&self, font_cache: &FontCache) -> Option<[DVec2; 2]> { + pub fn selected_visible_layers_bounding_box(&self, render_data: &RenderData) -> Option<[DVec2; 2]> { let paths = self.selected_visible_layers(); - self.document_legacy.combined_viewport_bounding_box(paths, font_cache) + self.document_legacy.combined_viewport_bounding_box(paths, render_data) } - pub fn artboard_bounding_box_and_transform(&self, path: &[LayerId], font_cache: &FontCache) -> Option<([DVec2; 2], DAffine2)> { - self.artboard_message_handler.artboards_document.bounding_box_and_transform(path, font_cache).unwrap_or(None) + pub fn artboard_bounding_box_and_transform(&self, path: &[LayerId], render_data: &RenderData) -> Option<([DVec2; 2], DAffine2)> { + self.artboard_message_handler.artboards_document.bounding_box_and_transform(path, render_data).unwrap_or(None) } pub fn selected_layers(&self) -> impl Iterator { @@ -1220,16 +1218,16 @@ impl DocumentMessageHandler { } /// Returns the bounding boxes for all visible layers and artboards, optionally excluding any paths. - pub fn bounding_boxes<'a>(&'a self, ignore_document: Option<&'a Vec>>, ignore_artboard: Option, font_cache: &'a FontCache) -> impl Iterator + 'a { + pub fn bounding_boxes<'a>(&'a self, ignore_document: Option<&'a Vec>>, ignore_artboard: Option, render_data: &'a RenderData) -> impl Iterator + 'a { self.visible_layers() .filter(move |path| ignore_document.map_or(true, |ignore_document| !ignore_document.iter().any(|ig| ig.as_slice() == *path))) - .filter_map(|path| self.document_legacy.viewport_bounding_box(path, font_cache).ok()?) + .filter_map(|path| self.document_legacy.viewport_bounding_box(path, render_data).ok()?) .chain( self.artboard_message_handler .artboard_ids .iter() .filter(move |&&id| Some(id) != ignore_artboard) - .filter_map(|&path| self.artboard_message_handler.artboards_document.viewport_bounding_box(&[path], font_cache).ok()?), + .filter_map(|&path| self.artboard_message_handler.artboards_document.viewport_bounding_box(&[path], render_data).ok()?), ) } @@ -1505,31 +1503,31 @@ impl DocumentMessageHandler { } // TODO: This should probably take a slice not a vec, also why does this even exist when `layer_panel_entry_from_path` also exists? - pub fn layer_panel_entry(&mut self, path: Vec, font_cache: &FontCache) -> Result { + pub fn layer_panel_entry(&mut self, path: Vec, render_data: &RenderData) -> Result { let data: LayerMetadata = *self .layer_metadata .get_mut(&path) .ok_or_else(|| EditorError::Document(format!("Could not get layer metadata for {:?}", path)))?; let layer = self.document_legacy.layer(&path)?; - let entry = LayerPanelEntry::new(&data, self.document_legacy.multiply_transforms(&path)?, layer, path, font_cache); + let entry = LayerPanelEntry::new(&data, self.document_legacy.multiply_transforms(&path)?, layer, path, render_data); Ok(entry) } /// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain /// any actual data, but rather attributes such as visibility and names of the layers. - pub fn layer_panel(&mut self, path: &[LayerId], font_cache: &FontCache) -> Result, EditorError> { + pub fn layer_panel(&mut self, path: &[LayerId], render_data: &RenderData) -> Result, EditorError> { let folder = self.document_legacy.folder(path)?; let paths: Vec> = folder.layer_ids.iter().map(|id| [path, &[*id]].concat()).collect(); - let entries = paths.iter().rev().filter_map(|path| self.layer_panel_entry_from_path(path, font_cache)).collect(); + let entries = paths.iter().rev().filter_map(|path| self.layer_panel_entry_from_path(path, render_data)).collect(); Ok(entries) } - pub fn layer_panel_entry_from_path(&self, path: &[LayerId], font_cache: &FontCache) -> Option { + pub fn layer_panel_entry_from_path(&self, path: &[LayerId], render_data: &RenderData) -> Option { let layer_metadata = self.layer_metadata(path); let transform = self.document_legacy.generate_transform_across_scope(path, Some(self.document_legacy.root.transform.inverse())).ok()?; let layer = self.document_legacy.layer(path).ok()?; - Some(LayerPanelEntry::new(layer_metadata, transform, layer, path.to_vec(), font_cache)) + Some(LayerPanelEntry::new(layer_metadata, transform, layer, path.to_vec(), render_data)) } /// When working with an insert index, deleting the layers may cause the insert index to point to a different location (if the layer being deleted was located before the insert index). @@ -1544,16 +1542,16 @@ impl DocumentMessageHandler { } /// Calculates the bounding box of all layers in the document - pub fn all_layer_bounds(&self, font_cache: &FontCache) -> Option<[DVec2; 2]> { - self.document_legacy.viewport_bounding_box(&[], font_cache).ok().flatten() + pub fn all_layer_bounds(&self, render_data: &RenderData) -> Option<[DVec2; 2]> { + self.document_legacy.viewport_bounding_box(&[], render_data).ok().flatten() } /// Calculates the document bounds used for scrolling and centring (the layer bounds or the artboard (if applicable)) - pub fn document_bounds(&self, font_cache: &FontCache) -> Option<[DVec2; 2]> { + pub fn document_bounds(&self, render_data: &RenderData) -> Option<[DVec2; 2]> { if self.artboard_message_handler.is_infinite_canvas() { - self.all_layer_bounds(font_cache) + self.all_layer_bounds(render_data) } else { - self.artboard_message_handler.artboards_document.viewport_bounding_box(&[], font_cache).ok().flatten() + self.artboard_message_handler.artboards_document.viewport_bounding_box(&[], render_data).ok().flatten() } } @@ -1581,11 +1579,6 @@ impl DocumentMessageHandler { LayerDataType::Text(text) => { fonts.insert(text.font.clone()); } - LayerDataType::Image(image) => image_data.push(FrontendImageData { - path: path.clone(), - image_data: image.image_data.clone(), - mime: image.mime.clone(), - }), LayerDataType::NodeGraphFrame(node_graph_frame) => { if let Some(data) = &node_graph_frame.image_data { image_data.push(FrontendImageData { @@ -1829,7 +1822,7 @@ impl DocumentMessageHandler { ); } - pub fn update_layer_tree_options_bar_widgets(&self, responses: &mut VecDeque, font_cache: &FontCache) { + pub fn update_layer_tree_options_bar_widgets(&self, responses: &mut VecDeque, render_data: &RenderData) { let mut opacity = None; let mut opacity_is_mixed = false; @@ -1838,7 +1831,7 @@ impl DocumentMessageHandler { self.layer_metadata .keys() - .filter_map(|path| self.layer_panel_entry_from_path(path, font_cache)) + .filter_map(|path| self.layer_panel_entry_from_path(path, render_data)) .filter(|layer_panel_entry| layer_panel_entry.layer_metadata.selected) .flat_map(|layer_panel_entry| self.document_legacy.layer(layer_panel_entry.path.as_slice())) .for_each(|layer| { diff --git a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs index 40386d4ad..c24731311 100644 --- a/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs +++ b/editor/src/messages/portfolio/document/overlays/overlays_message_handler.rs @@ -1,27 +1,31 @@ +use crate::messages::portfolio::utility_types::PersistentData; use crate::messages::prelude::*; use document_legacy::document::Document as DocumentLegacy; use document_legacy::layers::style::{RenderData, ViewMode}; -use document_legacy::layers::text_layer::FontCache; #[derive(Debug, Clone, Default)] pub struct OverlaysMessageHandler { pub overlays_document: DocumentLegacy, } -impl MessageHandler for OverlaysMessageHandler { +impl MessageHandler for OverlaysMessageHandler { #[remain::check] - fn process_message(&mut self, message: OverlaysMessage, responses: &mut VecDeque, (overlays_visible, font_cache, ipp): (bool, &FontCache, &InputPreprocessorMessageHandler)) { + fn process_message(&mut self, message: OverlaysMessage, responses: &mut VecDeque, (overlays_visible, persistent_data, ipp): (bool, &PersistentData, &InputPreprocessorMessageHandler)) { use OverlaysMessage::*; #[remain::sorted] match message { // Sub-messages #[remain::unsorted] - DispatchOperation(operation) => match self.overlays_document.handle_operation(*operation, font_cache) { - Ok(_) => responses.push_back(OverlaysMessage::Rerender.into()), - Err(e) => error!("OverlaysError: {:?}", e), - }, + DispatchOperation(operation) => { + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, Some(ipp.document_bounds())); + + match self.overlays_document.handle_operation(*operation, &render_data) { + Ok(_) => responses.push_back(OverlaysMessage::Rerender.into()), + Err(e) => error!("OverlaysError: {:?}", e), + } + } // Messages ClearAllOverlays => { @@ -33,8 +37,8 @@ impl MessageHandler MessageHandler)> for PropertiesPanelMessageHandler { #[remain::check] fn process_message(&mut self, message: PropertiesPanelMessage, responses: &mut VecDeque, (persistent_data, data): (&PersistentData, PropertiesPanelMessageHandlerData)) { + use PropertiesPanelMessage::*; + let PropertiesPanelMessageHandlerData { artwork_document, artboard_document, @@ -30,7 +33,8 @@ impl<'a> MessageHandler artboard_document, TargetDocument::Artwork => artwork_document, }; - use PropertiesPanelMessage::*; + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, None); + match message { SetActiveLayers { paths, document } => { if paths.len() != 1 { @@ -99,7 +103,7 @@ impl<'a> MessageHandler [f64; 6] { +pub fn apply_transform_operation(layer: &Layer, transform_op: TransformOp, value: f64, render_data: &RenderData) -> [f64; 6] { let transformation = match transform_op { TransformOp::X => DAffine2::update_x, TransformOp::Y => DAffine2::update_y, @@ -29,8 +29,8 @@ pub fn apply_transform_operation(layer: &Layer, transform_op: TransformOp, value }; let scale = match transform_op { - TransformOp::Width => layer.bounding_transform(font_cache).scale_x() / layer.transform.scale_x(), - TransformOp::Height => layer.bounding_transform(font_cache).scale_y() / layer.transform.scale_y(), + TransformOp::Width => layer.bounding_transform(render_data).scale_x() / layer.transform.scale_x(), + TransformOp::Height => layer.bounding_transform(render_data).scale_y() / layer.transform.scale_y(), _ => 1., }; @@ -43,7 +43,7 @@ pub fn apply_transform_operation(layer: &Layer, transform_op: TransformOp, value } // Find the layerspace pivot - let pivot = DAffine2::from_translation(layer.transform.transform_point2(layer.layerspace_pivot(font_cache))); + let pivot = DAffine2::from_translation(layer.transform.transform_point2(layer.layerspace_pivot(render_data))); // Find the delta transform let mut delta = layer.transform.inverse() * transform; @@ -94,17 +94,15 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ }]; let properties_body = { - let shape = if let LayerDataType::Shape(shape) = &layer.data { - shape - } else { + let LayerDataType::Shape(shape) = &layer.data else { panic!("Artboards can only be shapes") }; - let color = if let Fill::Solid(color) = shape.style.fill() { - color - } else { + let Fill::Solid(color) = shape.style.fill() else { panic!("Artboard must have a solid fill") }; - let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(&persistent_data.font_cache)); + + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::default(), None); + let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(&render_data)); vec![LayoutGroup::Section { name: "Artboard".into(), @@ -167,7 +165,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ WidgetHolder::related_separator(), WidgetHolder::unrelated_separator(), WidgetHolder::new(Widget::NumberInput(NumberInput { - value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_x()), + value: Some(layer.bounding_transform(&render_data).scale_x()), label: "W".into(), unit: " px".into(), is_integer: true, @@ -183,7 +181,7 @@ pub fn register_artboard_layer_properties(layer: &Layer, responses: &mut VecDequ })), WidgetHolder::related_separator(), WidgetHolder::new(Widget::NumberInput(NumberInput { - value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_y()), + value: Some(layer.bounding_transform(&render_data).scale_y()), label: "H".into(), unit: " px".into(), is_integer: true, @@ -267,11 +265,6 @@ pub fn register_artwork_layer_properties( tooltip: "Text".into(), ..Default::default() })), - LayerDataType::Image(_) => WidgetHolder::new(Widget::IconLabel(IconLabel { - icon: "NodeImage".into(), - tooltip: "Image".into(), - ..Default::default() - })), LayerDataType::NodeGraphFrame(_) => WidgetHolder::new(Widget::IconLabel(IconLabel { icon: "NodeNodes".into(), tooltip: "Node Graph Frame".into(), @@ -321,9 +314,6 @@ pub fn register_artwork_layer_properties( node_section_stroke(&text.path_style.stroke().unwrap_or_default()), ] } - LayerDataType::Image(_) => { - vec![node_section_transform(layer, persistent_data)] - } LayerDataType::NodeGraphFrame(node_graph_frame) => { let mut properties_sections = vec![node_section_transform(layer, persistent_data)]; @@ -360,7 +350,8 @@ pub fn register_artwork_layer_properties( } fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> LayoutGroup { - let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(&persistent_data.font_cache)); + let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::default(), None); + let pivot = layer.transform.transform_vector2(layer.layerspace_pivot(&render_data)); LayoutGroup::Section { name: "Transform".into(), layout: vec![ @@ -492,7 +483,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La WidgetHolder::unrelated_separator(), // TODO: Remove these when we have proper entry row formatting that includes room for Assists. WidgetHolder::unrelated_separator(), WidgetHolder::new(Widget::NumberInput(NumberInput { - value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_x()), + value: Some(layer.bounding_transform(&render_data).scale_x()), label: "W".into(), unit: " px".into(), on_update: WidgetCallback::new(|number_input: &NumberInput| { @@ -506,7 +497,7 @@ fn node_section_transform(layer: &Layer, persistent_data: &PersistentData) -> La })), WidgetHolder::related_separator(), WidgetHolder::new(Widget::NumberInput(NumberInput { - value: Some(layer.bounding_transform(&persistent_data.font_cache).scale_y()), + value: Some(layer.bounding_transform(&render_data).scale_y()), label: "H".into(), unit: " px".into(), on_update: WidgetCallback::new(|number_input: &NumberInput| { diff --git a/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs b/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs index ed784a975..78fb87d71 100644 --- a/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs +++ b/editor/src/messages/portfolio/document/transform_layer/transform_layer_message_handler.rs @@ -5,9 +5,9 @@ use crate::messages::portfolio::document::utility_types::transformation::{Axis, use crate::messages::prelude::*; use document_legacy::document::Document; +use document_legacy::layers::style::RenderData; use document_legacy::LayerId; -use document_legacy::layers::text_layer::FontCache; use glam::DVec2; #[derive(Debug, Clone, Default, PartialEq)] @@ -25,10 +25,10 @@ pub struct TransformLayerMessageHandler { pivot: DVec2, } -type TransformData<'a> = (&'a mut HashMap, LayerMetadata>, &'a mut Document, &'a InputPreprocessorMessageHandler, &'a FontCache); +type TransformData<'a> = (&'a mut HashMap, LayerMetadata>, &'a mut Document, &'a InputPreprocessorMessageHandler, &'a RenderData<'a>); impl<'a> MessageHandler> for TransformLayerMessageHandler { #[remain::check] - fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque, (layer_metadata, document, ipp, font_cache): TransformData) { + fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque, (layer_metadata, document, ipp, render_data): TransformData) { use TransformLayerMessage::*; let selected_layers = layer_metadata.iter().filter_map(|(layer_path, data)| data.selected.then_some(layer_path)).collect::>(); @@ -39,7 +39,7 @@ impl<'a> MessageHandler> for TransformL selected.revert_operation(); typing.clear(); } else { - *selected.pivot = selected.mean_average_of_pivots(font_cache); + *selected.pivot = selected.mean_average_of_pivots(render_data); } *mouse_position = ipp.mouse.position; @@ -137,7 +137,7 @@ impl<'a> MessageHandler> for TransformL self.transform_operation.apply_transform_operation(&mut selected, self.snap); } TransformOperation::Rotating(rotation) => { - let selected_pivot = selected.mean_average_of_pivots(font_cache); + let selected_pivot = selected.mean_average_of_pivots(render_data); let angle = { let start_offset = self.mouse_position - selected_pivot; let end_offset = ipp.mouse.position - selected_pivot; diff --git a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs b/editor/src/messages/portfolio/document/utility_types/layer_panel.rs index 3a87c9c29..405719459 100644 --- a/editor/src/messages/portfolio/document/utility_types/layer_panel.rs +++ b/editor/src/messages/portfolio/document/utility_types/layer_panel.rs @@ -1,6 +1,5 @@ use document_legacy::layers::layer_info::{Layer, LayerData, LayerDataTypeDiscriminant}; -use document_legacy::layers::style::{RenderData, ViewMode}; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::RenderData; use document_legacy::LayerId; use glam::{DAffine2, DVec2}; @@ -65,7 +64,7 @@ pub struct LayerPanelEntry { } impl LayerPanelEntry { - pub fn new(layer_metadata: &LayerMetadata, transform: DAffine2, layer: &Layer, path: Vec, font_cache: &FontCache) -> Self { + pub fn new(layer_metadata: &LayerMetadata, transform: DAffine2, layer: &Layer, path: Vec, render_data: &RenderData) -> Self { let name = layer.name.clone().unwrap_or_else(|| String::from("")); let mut tooltip = name.clone(); @@ -75,11 +74,10 @@ impl LayerPanelEntry { tooltip = tooltip.trim().to_string(); } - let arr = layer.data.bounding_box(transform, font_cache).unwrap_or([DVec2::ZERO, DVec2::ZERO]); + let arr = layer.data.bounding_box(transform, render_data).unwrap_or([DVec2::ZERO, DVec2::ZERO]); let arr = arr.iter().map(|x| (*x).into()).collect::>(); let mut thumbnail = String::new(); let mut svg_defs = String::new(); - let render_data = RenderData::new(ViewMode::Normal, font_cache, None); layer.data.clone().render(&mut thumbnail, &mut svg_defs, &mut vec![transform], render_data); let transform = transform.to_cols_array().iter().map(ToString::to_string).collect::>().join(","); let thumbnail = if let [(x_min, y_min), (x_max, y_max)] = arr.as_slice() { diff --git a/editor/src/messages/portfolio/document/utility_types/transformation.rs b/editor/src/messages/portfolio/document/utility_types/transformation.rs index e01986768..c95ab0b81 100644 --- a/editor/src/messages/portfolio/document/utility_types/transformation.rs +++ b/editor/src/messages/portfolio/document/utility_types/transformation.rs @@ -2,7 +2,7 @@ use crate::consts::{ROTATE_SNAP_ANGLE, SCALE_SNAP_INTERVAL}; use crate::messages::prelude::*; use document_legacy::document::Document; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::RenderData; use document_legacy::LayerId; use document_legacy::Operation as DocumentOperation; @@ -206,20 +206,20 @@ impl<'a> Selected<'a> { } } - pub fn mean_average_of_pivots(&mut self, font_cache: &FontCache) -> DVec2 { - let xy_summation = self.selected.iter().filter_map(|path| self.document.pivot(path, font_cache)).reduce(|a, b| a + b).unwrap_or_default(); + pub fn mean_average_of_pivots(&mut self, render_data: &RenderData) -> DVec2 { + let xy_summation = self.selected.iter().filter_map(|path| self.document.pivot(path, render_data)).reduce(|a, b| a + b).unwrap_or_default(); xy_summation / self.selected.len() as f64 } - pub fn center_of_aabb(&mut self, font_cache: &FontCache) -> DVec2 { + pub fn center_of_aabb(&mut self, render_data: &RenderData) -> DVec2 { let [min, max] = self .selected .iter() .filter_map(|path| { let multiplied_transform = self.document.multiply_transforms(path).unwrap(); - self.document.layer(path).unwrap().aabb_for_transform(multiplied_transform, font_cache) + self.document.layer(path).unwrap().aabb_for_transform(multiplied_transform, render_data) }) .reduce(|a, b| [a[0].min(b[0]), a[1].max(b[1])]) .unwrap_or_default(); diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index ab4a4c392..286d5c64a 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -14,6 +14,7 @@ use crate::messages::prelude::*; use crate::messages::tool::utility_types::{HintData, HintGroup}; use document_legacy::document::pick_safe_imaginate_resolution; use document_legacy::layers::layer_info::{LayerDataType, LayerDataTypeDiscriminant}; +use document_legacy::layers::style::RenderData; use document_legacy::layers::text_layer::Font; use document_legacy::{LayerId, Operation as DocumentOperation}; use graph_craft::document::value::TaggedValue; @@ -635,19 +636,21 @@ impl PortfolioMessageHandler { } } - // TODO Fix how this doesn't preserve tab order upon loading new document from *File > Load* + // TODO: Fix how this doesn't preserve tab order upon loading new document from *File > Load* fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, responses: &mut VecDeque) { + let render_data = RenderData::new(&self.persistent_data.font_cache, new_document.view_mode, None); + self.document_ids.push(document_id); responses.extend( new_document .layer_metadata .keys() - .filter_map(|path| new_document.layer_panel_entry_from_path(path, &self.persistent_data.font_cache)) + .filter_map(|path| new_document.layer_panel_entry_from_path(path, &render_data)) .map(|entry| FrontendMessage::UpdateDocumentLayerDetails { data: entry }.into()) .collect::>(), ); - new_document.update_layer_tree_options_bar_widgets(responses, &self.persistent_data.font_cache); + new_document.update_layer_tree_options_bar_widgets(responses, &render_data); self.documents.insert(document_id, new_document); diff --git a/editor/src/messages/tool/common_functionality/path_outline.rs b/editor/src/messages/tool/common_functionality/path_outline.rs index e210efa5b..077fdeb38 100644 --- a/editor/src/messages/tool/common_functionality/path_outline.rs +++ b/editor/src/messages/tool/common_functionality/path_outline.rs @@ -4,8 +4,7 @@ use crate::messages::prelude::*; use document_legacy::intersection::Quad; use document_legacy::layers::layer_info::LayerDataType; -use document_legacy::layers::style::{self, Fill, Stroke}; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::{self, Fill, RenderData, Stroke}; use document_legacy::{LayerId, Operation}; use graphene_std::vector::subpath::Subpath; @@ -26,7 +25,7 @@ impl PathOutline { overlay_path: Option>, document: &DocumentMessageHandler, responses: &mut VecDeque, - font_cache: &FontCache, + render_data: &RenderData, ) -> Option> { // Get layer data let document_layer = document.document_legacy.layer(&document_layer_path).ok()?; @@ -35,8 +34,8 @@ impl PathOutline { // Get the bezpath from the shape or text let subpath = match &document_layer.data { LayerDataType::Shape(layer_shape) => Some(layer_shape.shape.clone()), - LayerDataType::Text(text) => Some(text.to_subpath_nonmut(font_cache)), - _ => document_layer.aabb_for_transform(DAffine2::IDENTITY, font_cache).map(|[p1, p2]| Subpath::new_rect(p1, p2)), + LayerDataType::Text(text) => Some(text.to_subpath_nonmut(render_data)), + _ => document_layer.aabb_for_transform(DAffine2::IDENTITY, render_data).map(|[p1, p2]| Subpath::new_rect(p1, p2)), }?; // Generate a new overlay layer if necessary @@ -74,16 +73,16 @@ impl PathOutline { /// Creates an outline of a layer either with a pre-existing overlay or by generating a new one /// - /// Creates an outline, discarding the overlay on failiure + /// Creates an outline, discarding the overlay on failure fn create_outline( document_layer_path: Vec, overlay_path: Option>, document: &DocumentMessageHandler, responses: &mut VecDeque, - font_cache: &FontCache, + render_data: &RenderData, ) -> Option> { let copied_overlay_path = overlay_path.clone(); - let result = Self::try_create_outline(document_layer_path, overlay_path, document, responses, font_cache); + let result = Self::try_create_outline(document_layer_path, overlay_path, document, responses, render_data); if result.is_none() { // Discard the overlay layer if it exists if let Some(overlay_path) = copied_overlay_path { @@ -104,17 +103,17 @@ impl PathOutline { } /// Performs an intersect test and generates a hovered overlay if necessary - pub fn intersect_test_hovered(&mut self, input: &InputPreprocessorMessageHandler, document: &DocumentMessageHandler, responses: &mut VecDeque, font_cache: &FontCache) { + pub fn intersect_test_hovered(&mut self, input: &InputPreprocessorMessageHandler, document: &DocumentMessageHandler, responses: &mut VecDeque, render_data: &RenderData) { // Get the layer the user is hovering over let tolerance = DVec2::splat(SELECTION_TOLERANCE); let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]); - let mut intersection = document.document_legacy.intersects_quad_root(quad, font_cache); + let mut intersection = document.document_legacy.intersects_quad_root(quad, render_data); // If the user is hovering over a layer they have not already selected, then update outline if let Some(path) = intersection.pop() { if !document.selected_visible_layers().any(|visible| visible == path.as_slice()) { // Updates the overlay, generating a new one if necessary - self.hovered_overlay_path = Self::create_outline(path.clone(), self.hovered_overlay_path.take(), document, responses, font_cache); + self.hovered_overlay_path = Self::create_outline(path.clone(), self.hovered_overlay_path.take(), document, responses, render_data); if self.hovered_overlay_path.is_none() { self.clear_hovered(responses); } @@ -137,11 +136,11 @@ impl PathOutline { } /// Updates the selected overlays, generating or removing overlays if necessary - pub fn update_selected<'a>(&mut self, selected: impl Iterator, document: &DocumentMessageHandler, responses: &mut VecDeque, font_cache: &FontCache) { + pub fn update_selected<'a>(&mut self, selected: impl Iterator, document: &DocumentMessageHandler, responses: &mut VecDeque, render_data: &RenderData) { let mut old_overlay_paths = std::mem::take(&mut self.selected_overlay_paths); for document_layer_path in selected { - if let Some(overlay_path) = Self::create_outline(document_layer_path.to_vec(), old_overlay_paths.pop(), document, responses, font_cache) { + if let Some(overlay_path) = Self::create_outline(document_layer_path.to_vec(), old_overlay_paths.pop(), document, responses, render_data) { self.selected_overlay_paths.push(overlay_path); } } diff --git a/editor/src/messages/tool/common_functionality/pivot.rs b/editor/src/messages/tool/common_functionality/pivot.rs index 1f8515c69..34e12b737 100644 --- a/editor/src/messages/tool/common_functionality/pivot.rs +++ b/editor/src/messages/tool/common_functionality/pivot.rs @@ -5,8 +5,7 @@ use crate::consts::{COLOR_ACCENT, PIVOT_INNER, PIVOT_OUTER, PIVOT_OUTER_OUTLINE_ use crate::messages::layout::utility_types::widgets::assist_widgets::PivotPosition; use crate::messages::prelude::*; -use document_legacy::layers::style; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::{self, RenderData}; use document_legacy::{LayerId, Operation}; use glam::{DAffine2, DVec2}; @@ -40,8 +39,8 @@ impl Default for Pivot { impl Pivot { /// Calculates the transform that gets from normalized pivot to viewspace. - fn get_layer_pivot_transform(layer_path: &[LayerId], layer: &document_legacy::layers::layer_info::Layer, document: &DocumentMessageHandler, font_cache: &FontCache) -> DAffine2 { - let [mut min, max] = layer.aabb_for_transform(DAffine2::IDENTITY, font_cache).unwrap_or([DVec2::ZERO, DVec2::ONE]); + fn get_layer_pivot_transform(layer_path: &[LayerId], layer: &document_legacy::layers::layer_info::Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> DAffine2 { + let [mut min, max] = layer.aabb_for_transform(DAffine2::IDENTITY, render_data).unwrap_or([DVec2::ZERO, DVec2::ONE]); // If the layer bounds are 0 in either axis then set them to one (to avoid div 0) if (max.x - min.x) < f64::EPSILON * 1000. { @@ -56,7 +55,7 @@ impl Pivot { } /// Recomputes the pivot position and transform. - fn recalculate_pivot(&mut self, document: &DocumentMessageHandler, font_cache: &FontCache) { + fn recalculate_pivot(&mut self, document: &DocumentMessageHandler, render_data: &RenderData) { let mut layers = document.selected_visible_layers(); if let Some(first) = layers.next() { // Add one because the first item is consumed above. @@ -66,20 +65,20 @@ impl Pivot { if selected_layers_count == 1 { if let Ok(layer) = document.document_legacy.layer(first) { self.normalized_pivot = layer.pivot; - self.transform_from_normalized = Self::get_layer_pivot_transform(first, layer, document, font_cache); + self.transform_from_normalized = Self::get_layer_pivot_transform(first, layer, document, render_data); self.pivot = Some(self.transform_from_normalized.transform_point2(layer.pivot)); } } else { // If more than one layer is selected we use the AABB with the mean of the pivots let xy_summation = document .selected_visible_layers() - .filter_map(|path| document.document_legacy.pivot(path, font_cache)) + .filter_map(|path| document.document_legacy.pivot(path, render_data)) .reduce(|a, b| a + b) .unwrap_or_default(); let pivot = xy_summation / selected_layers_count as f64; self.pivot = Some(pivot); - let [min, max] = document.selected_visible_layers_bounding_box(font_cache).unwrap_or([DVec2::ZERO, DVec2::ONE]); + let [min, max] = document.selected_visible_layers_bounding_box(render_data).unwrap_or([DVec2::ZERO, DVec2::ONE]); self.normalized_pivot = (pivot - min) / (max - min); self.transform_from_normalized = DAffine2::from_translation(min) * DAffine2::from_scale(max - min); @@ -147,8 +146,8 @@ impl Pivot { responses.push_back(DocumentMessage::Overlays(Operation::TransformLayerInViewport { path: inner, transform }.into()).into()); } - pub fn update_pivot(&mut self, document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque) { - self.recalculate_pivot(document, font_cache); + pub fn update_pivot(&mut self, document: &DocumentMessageHandler, render_data: &RenderData, responses: &mut VecDeque) { + self.recalculate_pivot(document, render_data); self.redraw_pivot(responses); } @@ -165,10 +164,10 @@ impl Pivot { } /// Sets the viewport position of the pivot for all selected layers. - pub fn set_viewport_position(&self, position: DVec2, document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque) { + pub fn set_viewport_position(&self, position: DVec2, document: &DocumentMessageHandler, render_data: &RenderData, responses: &mut VecDeque) { for layer_path in document.selected_visible_layers() { if let Ok(layer) = document.document_legacy.layer(layer_path) { - let transform = Self::get_layer_pivot_transform(layer_path, layer, document, font_cache); + let transform = Self::get_layer_pivot_transform(layer_path, layer, document, render_data); let pivot = transform.inverse().transform_point2(position); // Only update the pivot when computed position is finite. Infinite can happen when scale is 0. if pivot.is_finite() { @@ -180,8 +179,8 @@ impl Pivot { } /// Set the pivot using the normalized transform that is set above. - pub fn set_normalized_position(&self, position: DVec2, document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque) { - self.set_viewport_position(self.transform_from_normalized.transform_point2(position), document, font_cache, responses); + pub fn set_normalized_position(&self, position: DVec2, document: &DocumentMessageHandler, render_data: &RenderData, responses: &mut VecDeque) { + self.set_viewport_position(self.transform_from_normalized.transform_point2(position), document, render_data, responses); } /// Answers if the pointer is currently positioned over the pivot. diff --git a/editor/src/messages/tool/common_functionality/resize.rs b/editor/src/messages/tool/common_functionality/resize.rs index af3d869bd..697876db9 100644 --- a/editor/src/messages/tool/common_functionality/resize.rs +++ b/editor/src/messages/tool/common_functionality/resize.rs @@ -3,7 +3,7 @@ use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; use crate::messages::prelude::*; use crate::messages::tool::common_functionality::snapping::SnapManager; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::RenderData; use document_legacy::LayerId; use document_legacy::Operation; @@ -18,8 +18,8 @@ pub struct Resize { impl Resize { /// Starts a resize, assigning the snap targets and snapping the starting position. - pub fn start(&mut self, responses: &mut VecDeque, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, font_cache: &FontCache) { - self.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); + pub fn start(&mut self, responses: &mut VecDeque, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, render_data: &RenderData) { + self.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); self.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); let root_transform = document.document_legacy.root.transform; self.drag_start = root_transform.inverse().transform_point2(self.snap_manager.snap_position(responses, document, input.mouse.position)); diff --git a/editor/src/messages/tool/tool_message_handler.rs b/editor/src/messages/tool/tool_message_handler.rs index 0b1ed7049..74c02c210 100644 --- a/editor/src/messages/tool/tool_message_handler.rs +++ b/editor/src/messages/tool/tool_message_handler.rs @@ -7,6 +7,7 @@ use crate::messages::prelude::*; use crate::messages::tool::utility_types::ToolType; use document_legacy::color::Color; +use document_legacy::layers::style::RenderData; #[derive(Debug, Default)] pub struct ToolMessageHandler { @@ -21,6 +22,8 @@ impl MessageHandler, (document, document_id, input, persistent_data): (&DocumentMessageHandler, u64, &InputPreprocessorMessageHandler, &PersistentData), ) { + let render_data = RenderData::new(&persistent_data.font_cache, document.view_mode, None); + #[remain::sorted] match message { // Messages @@ -73,12 +76,12 @@ impl MessageHandler { let tool_data = &mut self.tool_state.tool_data; @@ -196,7 +199,7 @@ impl MessageHandler, ) -> Self { if let ToolMessage::Artboard(event) = event { match (self, event) { (state, ArtboardToolMessage::DocumentIsDirty) if state != ArtboardToolFsmState::Drawing => { - let current_artboard = tool_data.selected_artboard.and_then(|path| document.artboard_bounding_box_and_transform(&[path], font_cache)); + let current_artboard = tool_data.selected_artboard.and_then(|path| document.artboard_bounding_box_and_transform(&[path], render_data)); match (current_artboard, tool_data.bounding_box_overlays.take()) { (None, Some(bounding_box_overlays)) => bounding_box_overlays.delete(responses), (Some((bounds, transform)), paths) => { @@ -173,11 +173,11 @@ impl Fsm for ArtboardToolFsmState { let artboard = tool_data.selected_artboard.unwrap(); tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(None, Some(artboard), font_cache), snap_x, snap_y); + .start_snap(document, input, document.bounding_boxes(None, Some(artboard), render_data), snap_x, snap_y); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); if let Some(bounds) = &mut tool_data.bounding_box_overlays { - let pivot = document.artboard_message_handler.artboards_document.pivot(&[artboard], font_cache).unwrap_or_default(); + let pivot = document.artboard_message_handler.artboards_document.pivot(&[artboard], render_data).unwrap_or_default(); let root = document.document_legacy.root.transform; let pivot = root.inverse().transform_point2(pivot); bounds.center_of_transformation = pivot; @@ -188,7 +188,7 @@ impl Fsm for ArtboardToolFsmState { responses.push_back(DocumentMessage::StartTransaction.into()); let tolerance = DVec2::splat(SELECTION_TOLERANCE); let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]); - let intersection = document.artboard_message_handler.artboards_document.intersects_quad_root(quad, font_cache); + let intersection = document.artboard_message_handler.artboards_document.intersects_quad_root(quad, render_data); responses.push_back(BroadcastEvent::DocumentIsDirty.into()); if let Some(intersection) = intersection.last() { @@ -196,7 +196,7 @@ impl Fsm for ArtboardToolFsmState { tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(None, Some(intersection[0]), font_cache), true, true); + .start_snap(document, input, document.bounding_boxes(None, Some(intersection[0]), render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); responses.push_back( @@ -304,7 +304,7 @@ impl Fsm for ArtboardToolFsmState { let id = generate_uuid(); tool_data.selected_artboard = Some(id); - tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, Some(id), font_cache), true, true); + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, Some(id), render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); responses.push_back( diff --git a/editor/src/messages/tool/tool_messages/ellipse_tool.rs b/editor/src/messages/tool/tool_messages/ellipse_tool.rs index 04c8d4f3c..10bda09d9 100644 --- a/editor/src/messages/tool/tool_messages/ellipse_tool.rs +++ b/editor/src/messages/tool/tool_messages/ellipse_tool.rs @@ -100,7 +100,7 @@ impl Fsm for EllipseToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -112,7 +112,7 @@ impl Fsm for EllipseToolFsmState { if let ToolMessage::Ellipse(event) = event { match (self, event) { (Ready, DragStart) => { - shape_data.start(responses, document, input, font_cache); + shape_data.start(responses, document, input, render_data); responses.push_back(DocumentMessage::StartTransaction.into()); shape_data.path = Some(document.get_path_for_new_layer()); responses.push_back(DocumentMessage::DeselectAllLayers.into()); diff --git a/editor/src/messages/tool/tool_messages/eyedropper_tool.rs b/editor/src/messages/tool/tool_messages/eyedropper_tool.rs index 63f2c509d..d7b08b472 100644 --- a/editor/src/messages/tool/tool_messages/eyedropper_tool.rs +++ b/editor/src/messages/tool/tool_messages/eyedropper_tool.rs @@ -87,7 +87,7 @@ impl Fsm for EyedropperToolFsmState { self, event: ToolMessage, _tool_data: &mut Self::ToolData, - (_document, _document_id, global_tool_data, input, _font_cache): ToolActionHandlerData, + (_document, _document_id, global_tool_data, input, _render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { diff --git a/editor/src/messages/tool/tool_messages/fill_tool.rs b/editor/src/messages/tool/tool_messages/fill_tool.rs index 9d0be1350..6b420872e 100644 --- a/editor/src/messages/tool/tool_messages/fill_tool.rs +++ b/editor/src/messages/tool/tool_messages/fill_tool.rs @@ -84,7 +84,7 @@ impl Fsm for FillToolFsmState { self, event: ToolMessage, _tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -98,7 +98,7 @@ impl Fsm for FillToolFsmState { let tolerance = DVec2::splat(SELECTION_TOLERANCE); let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]); - if let Some(path) = document.document_legacy.intersects_quad_root(quad, font_cache).last() { + if let Some(path) = document.document_legacy.intersects_quad_root(quad, render_data).last() { let color = match lmb_or_rmb { LeftPointerDown => global_tool_data.primary_color, RightPointerDown => global_tool_data.secondary_color, diff --git a/editor/src/messages/tool/tool_messages/freehand_tool.rs b/editor/src/messages/tool/tool_messages/freehand_tool.rs index d393b8f0d..cf4c93707 100644 --- a/editor/src/messages/tool/tool_messages/freehand_tool.rs +++ b/editor/src/messages/tool/tool_messages/freehand_tool.rs @@ -137,7 +137,7 @@ impl Fsm for FreehandToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, _font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, _render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index c067eb167..08e44a23f 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -12,11 +12,10 @@ use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use document_legacy::color::Color; use document_legacy::intersection::Quad; use document_legacy::layers::layer_info::Layer; -use document_legacy::layers::style::{Fill, Gradient, GradientType, PathStyle, Stroke}; +use document_legacy::layers::style::{Fill, Gradient, GradientType, PathStyle, RenderData, Stroke}; use document_legacy::LayerId; use document_legacy::Operation; -use document_legacy::layers::text_layer::FontCache; use glam::{DAffine2, DVec2}; use serde::{Deserialize, Serialize}; @@ -130,8 +129,8 @@ enum GradientToolFsmState { } /// Computes the transform from gradient space to layer space (where gradient space is 0..1 in layer space) -fn gradient_space_transform(path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, font_cache: &FontCache) -> DAffine2 { - let bounds = layer.aabb_for_transform(DAffine2::IDENTITY, font_cache).unwrap(); +fn gradient_space_transform(path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> DAffine2 { + let bounds = layer.aabb_for_transform(DAffine2::IDENTITY, render_data).unwrap(); let bound_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]); let multiplied = document.document_legacy.multiply_transforms(path).unwrap(); @@ -195,9 +194,9 @@ impl GradientOverlay { layer: &Layer, document: &DocumentMessageHandler, responses: &mut VecDeque, - font_cache: &FontCache, + render_data: &RenderData, ) -> Self { - let transform = gradient_space_transform(path, layer, document, font_cache); + let transform = gradient_space_transform(path, layer, document, render_data); let Gradient { start, end, positions, .. } = fill; let [start, end] = [transform.transform_point2(*start), transform.transform_point2(*end)]; @@ -261,8 +260,8 @@ struct SelectedGradient { } impl SelectedGradient { - pub fn new(gradient: Gradient, path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, font_cache: &FontCache) -> Self { - let transform = gradient_space_transform(path, layer, document, font_cache); + pub fn new(gradient: Gradient, path: &[LayerId], layer: &Layer, document: &DocumentMessageHandler, render_data: &RenderData) -> Self { + let transform = gradient_space_transform(path, layer, document, render_data); Self { path: path.to_vec(), transform, @@ -272,7 +271,7 @@ impl SelectedGradient { } /// Update the selected gradient, checking for removal or change of gradient. - pub fn update(gradient: &mut Option, document: &DocumentMessageHandler, font_cache: &FontCache, responses: &mut VecDeque) { + pub fn update(gradient: &mut Option, document: &DocumentMessageHandler, render_data: &RenderData, responses: &mut VecDeque) { let Some(inner_gradient) = gradient else { return; }; @@ -285,7 +284,7 @@ impl SelectedGradient { }; // Update transform - inner_gradient.transform = gradient_space_transform(&inner_gradient.path, layer, document, font_cache); + inner_gradient.transform = gradient_space_transform(&inner_gradient.path, layer, document, render_data); // Clear if no longer a gradient let Some(gradient) = layer.style().ok().and_then(|style|style.fill().as_gradient()) else { @@ -384,8 +383,8 @@ struct GradientToolData { drag_start: DVec2, } -pub fn start_snap(snap_manager: &mut SnapManager, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, font_cache: &FontCache) { - snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); +pub fn start_snap(snap_manager: &mut SnapManager, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, render_data: &RenderData) { + snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); snap_manager.add_all_document_handles(document, input, &[], &[], &[]); } @@ -397,7 +396,7 @@ impl Fsm for GradientToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -409,7 +408,7 @@ impl Fsm for GradientToolFsmState { } if self != GradientToolFsmState::Drawing { - SelectedGradient::update(&mut tool_data.selected_gradient, document, font_cache, responses); + SelectedGradient::update(&mut tool_data.selected_gradient, document, render_data, responses); } for path in document.selected_visible_layers() { @@ -423,7 +422,9 @@ impl Fsm for GradientToolFsmState { .selected_gradient .as_ref() .and_then(|selected| if selected.path == path { Some(selected.dragging) } else { None }); - tool_data.gradient_overlays.push(GradientOverlay::new(gradient, dragging, path, layer, document, responses, font_cache)) + tool_data + .gradient_overlays + .push(GradientOverlay::new(gradient, dragging, path, layer, document, responses, render_data)) } } @@ -493,7 +494,7 @@ impl Fsm for GradientToolFsmState { let layer = document.document_legacy.layer(&overlay.path); if let Ok(layer) = layer { - let mut selected_gradient = SelectedGradient::new(gradient, &overlay.path, layer, document, font_cache); + let mut selected_gradient = SelectedGradient::new(gradient, &overlay.path, layer, document, render_data); // Select the new point selected_gradient.dragging = GradientDragTarget::Step(index); @@ -541,7 +542,7 @@ impl Fsm for GradientToolFsmState { ] { if pos.distance_squared(mouse) < tolerance { dragging = true; - start_snap(&mut tool_data.snap_manager, document, input, font_cache); + start_snap(&mut tool_data.snap_manager, document, input, render_data); tool_data.selected_gradient = Some(SelectedGradient { path: overlay.path.clone(), transform: overlay.transform, @@ -557,7 +558,7 @@ impl Fsm for GradientToolFsmState { } else { let tolerance = DVec2::splat(SELECTION_TOLERANCE); let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]); - let intersection = document.document_legacy.intersects_quad_root(quad, font_cache).pop(); + let intersection = document.document_legacy.intersects_quad_root(quad, render_data).pop(); if let Some(intersection) = intersection { if !document.selected_layers_contains(&intersection) { @@ -585,11 +586,11 @@ impl Fsm for GradientToolFsmState { tool_options.gradient_type, ) }; - let selected_gradient = SelectedGradient::new(gradient, &intersection, layer, document, font_cache).with_gradient_start(input.mouse.position); + let selected_gradient = SelectedGradient::new(gradient, &intersection, layer, document, render_data).with_gradient_start(input.mouse.position); tool_data.selected_gradient = Some(selected_gradient); - start_snap(&mut tool_data.snap_manager, document, input, font_cache); + start_snap(&mut tool_data.snap_manager, document, input, render_data); GradientToolFsmState::Drawing } else { diff --git a/editor/src/messages/tool/tool_messages/imaginate_tool.rs b/editor/src/messages/tool/tool_messages/imaginate_tool.rs index b6709c737..b9de5e824 100644 --- a/editor/src/messages/tool/tool_messages/imaginate_tool.rs +++ b/editor/src/messages/tool/tool_messages/imaginate_tool.rs @@ -100,7 +100,7 @@ impl Fsm for ImaginateToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, _global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, _global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -112,7 +112,7 @@ impl Fsm for ImaginateToolFsmState { if let ToolMessage::Imaginate(event) = event { match (self, event) { (Ready, DragStart) => { - shape_data.start(responses, document, input, font_cache); + shape_data.start(responses, document, input, render_data); responses.push_back(DocumentMessage::StartTransaction.into()); responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into()); shape_data.path = Some(document.get_path_for_new_layer()); diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index e64382753..692a1b318 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -137,7 +137,7 @@ impl Fsm for LineToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -147,7 +147,7 @@ impl Fsm for LineToolFsmState { if let ToolMessage::Line(event) = event { match (self, event) { (Ready, DragStart) => { - tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); tool_data.drag_start = tool_data.snap_manager.snap_position(responses, document, input.mouse.position); diff --git a/editor/src/messages/tool/tool_messages/navigate_tool.rs b/editor/src/messages/tool/tool_messages/navigate_tool.rs index a67f128f0..107753c99 100644 --- a/editor/src/messages/tool/tool_messages/navigate_tool.rs +++ b/editor/src/messages/tool/tool_messages/navigate_tool.rs @@ -105,7 +105,7 @@ impl Fsm for NavigateToolFsmState { self, message: ToolMessage, tool_data: &mut Self::ToolData, - (_document, _document_id, _global_tool_data, input, _font_cache): ToolActionHandlerData, + (_document, _document_id, _global_tool_data, input, _render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, messages: &mut VecDeque, ) -> Self { diff --git a/editor/src/messages/tool/tool_messages/node_graph_frame_tool.rs b/editor/src/messages/tool/tool_messages/node_graph_frame_tool.rs index 910187d62..4d5f93d91 100644 --- a/editor/src/messages/tool/tool_messages/node_graph_frame_tool.rs +++ b/editor/src/messages/tool/tool_messages/node_graph_frame_tool.rs @@ -99,7 +99,7 @@ impl Fsm for NodeGraphToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, _global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, _global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -111,7 +111,7 @@ impl Fsm for NodeGraphToolFsmState { if let ToolMessage::NodeGraphFrame(event) = event { match (self, event) { (Ready, DragStart) => { - shape_data.start(responses, document, input, font_cache); + shape_data.start(responses, document, input, render_data); responses.push_back(DocumentMessage::StartTransaction.into()); responses.push_back(NodeGraphMessage::SetDrawing { new_drawing: true }.into()); shape_data.path = Some(document.get_path_for_new_layer()); diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index 0883f4714..ce9d442e0 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -120,7 +120,7 @@ impl Fsm for PathToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, _global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, _global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -166,7 +166,7 @@ impl Fsm for PathToolFsmState { let ignore_document = tool_data.shape_editor.selected_layers().clone(); tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(Some(&ignore_document), None, font_cache), true, true); + .start_snap(document, input, document.bounding_boxes(Some(&ignore_document), None, render_data), true, true); // Do not snap against handles when anchor is selected let mut extension = Vec::new(); @@ -196,7 +196,7 @@ impl Fsm for PathToolFsmState { // Select shapes directly under our mouse let intersection = document .document_legacy - .intersects_quad_root(Quad::from_box([input.mouse.position - selection_size, input.mouse.position + selection_size]), font_cache); + .intersects_quad_root(Quad::from_box([input.mouse.position - selection_size, input.mouse.position + selection_size]), render_data); if !intersection.is_empty() { if toggle_add_to_selection { responses.push_back(DocumentMessage::AddSelectedLayers { additional_layers: intersection }.into()); diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index f21b68744..0cc6b9e23 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -158,7 +158,7 @@ impl Fsm for PenToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -190,7 +190,7 @@ impl Fsm for PenToolFsmState { responses.push_back(DocumentMessage::StartTransaction.into()); // Initialize snapping - tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); // Disable this tool's mirroring diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index 795ec791d..2e1fc37d2 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -100,7 +100,7 @@ impl Fsm for RectangleToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -112,7 +112,7 @@ impl Fsm for RectangleToolFsmState { if let ToolMessage::Rectangle(event) = event { match (self, event) { (Ready, DragStart) => { - shape_data.start(responses, document, input, font_cache); + shape_data.start(responses, document, input, render_data); responses.push_back(DocumentMessage::StartTransaction.into()); shape_data.path = Some(document.get_path_for_new_layer()); responses.push_back(DocumentMessage::DeselectAllLayers.into()); diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 90b852624..9fd58ca7d 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -285,7 +285,7 @@ impl Fsm for SelectToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, _global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, _global_tool_data, input, render_data): ToolActionHandlerData, _tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -295,7 +295,7 @@ impl Fsm for SelectToolFsmState { if let ToolMessage::Select(event) = event { match (self, event) { (_, DocumentIsDirty | SelectionChanged) => { - match (document.selected_visible_layers_bounding_box(font_cache), tool_data.bounding_box_overlays.take()) { + match (document.selected_visible_layers_bounding_box(render_data), tool_data.bounding_box_overlays.take()) { (None, Some(bounding_box_overlays)) => bounding_box_overlays.delete(responses), (Some(bounds), paths) => { let mut bounding_box_overlays = paths.unwrap_or_else(|| BoundingBoxOverlays::new(responses)); @@ -310,9 +310,9 @@ impl Fsm for SelectToolFsmState { (_, _) => {} }; - tool_data.path_outlines.update_selected(document.selected_visible_layers(), document, responses, font_cache); - tool_data.path_outlines.intersect_test_hovered(input, document, responses, font_cache); - tool_data.pivot.update_pivot(document, font_cache, responses); + tool_data.path_outlines.update_selected(document.selected_visible_layers(), document, responses, render_data); + tool_data.path_outlines.intersect_test_hovered(input, document, responses, render_data); + tool_data.pivot.update_pivot(document, render_data, responses); self } @@ -325,7 +325,7 @@ impl Fsm for SelectToolFsmState { let quad = Quad::from_box([mouse_pos - tolerance, mouse_pos + tolerance]); // Check the last (top most) intersection layer. - if let Some(intersect_layer_path) = document.document_legacy.intersects_quad_root(quad, font_cache).last() { + if let Some(intersect_layer_path) = document.document_legacy.intersects_quad_root(quad, render_data).last() { if let Ok(intersect) = document.document_legacy.layer(intersect_layer_path) { match intersect.data { LayerDataType::Text(_) => { @@ -376,7 +376,7 @@ impl Fsm for SelectToolFsmState { let mut selected: Vec<_> = document.selected_visible_layers().map(|path| path.to_vec()).collect(); let quad = tool_data.selection_quad(); - let mut intersection = document.document_legacy.intersects_quad_root(quad, font_cache); + let mut intersection = document.document_legacy.intersects_quad_root(quad, render_data); // If the user is dragging the bounding box bounds, go into ResizingBounds mode. // If the user is dragging the rotate trigger, go into RotatingBounds mode. // If the user clicks on a layer that is in their current selection, go into the dragging mode. @@ -385,7 +385,7 @@ impl Fsm for SelectToolFsmState { let state = if tool_data.pivot.is_over(input.mouse.position) { responses.push_back(DocumentMessage::StartTransaction.into()); - tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); DraggingPivot @@ -397,7 +397,7 @@ impl Fsm for SelectToolFsmState { tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(Some(&selected), None, font_cache), snap_x, snap_y); + .start_snap(document, input, document.bounding_boxes(Some(&selected), None, render_data), snap_x, snap_y); tool_data .snap_manager .add_all_document_handles(document, input, &[], &selected.iter().map(|x| x.as_slice()).collect::>(), &[]); @@ -409,7 +409,7 @@ impl Fsm for SelectToolFsmState { let selected = &tool_data.layers_dragging.iter().collect::>(); let mut selected = Selected::new(&mut bounds.original_transforms, &mut bounds.center_of_transformation, selected, responses, document); - bounds.center_of_transformation = selected.mean_average_of_pivots(font_cache); + bounds.center_of_transformation = selected.mean_average_of_pivots(render_data); } ResizingBounds @@ -420,7 +420,7 @@ impl Fsm for SelectToolFsmState { let selected = selected.iter().collect::>(); let mut selected = Selected::new(&mut bounds.original_transforms, &mut bounds.center_of_transformation, &selected, responses, &document.document_legacy); - bounds.center_of_transformation = selected.mean_average_of_pivots(font_cache); + bounds.center_of_transformation = selected.mean_average_of_pivots(render_data); } tool_data.layers_dragging = selected; @@ -433,7 +433,7 @@ impl Fsm for SelectToolFsmState { tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, font_cache), true, true); + .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, render_data), true, true); Dragging } else { @@ -449,7 +449,7 @@ impl Fsm for SelectToolFsmState { tool_data.layers_dragging.append(&mut selected); tool_data .snap_manager - .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, font_cache), true, true); + .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, render_data), true, true); Dragging } else { @@ -472,7 +472,7 @@ impl Fsm for SelectToolFsmState { let snap = tool_data .layers_dragging .iter() - .filter_map(|path| document.document_legacy.viewport_bounding_box(path, font_cache).ok()?) + .filter_map(|path| document.document_legacy.viewport_bounding_box(path, render_data).ok()?) .flat_map(snapping::expand_bounds) .collect(); @@ -546,7 +546,7 @@ impl Fsm for SelectToolFsmState { (DraggingPivot, PointerMove { .. }) => { let mouse_position = input.mouse.position; let snapped_mouse_position = tool_data.snap_manager.snap_position(responses, document, mouse_position); - tool_data.pivot.set_viewport_position(snapped_mouse_position, document, font_cache, responses); + tool_data.pivot.set_viewport_position(snapped_mouse_position, document, render_data, responses); DraggingPivot } @@ -575,7 +575,7 @@ impl Fsm for SelectToolFsmState { // Generate the select outline (but not if the user is going to use the bound overlays) if cursor == MouseCursorIcon::Default { - tool_data.path_outlines.intersect_test_hovered(input, document, responses, font_cache); + tool_data.path_outlines.intersect_test_hovered(input, document, responses, render_data); } else { tool_data.path_outlines.clear_hovered(responses); } @@ -639,7 +639,7 @@ impl Fsm for SelectToolFsmState { let quad = tool_data.selection_quad(); responses.push_front( DocumentMessage::AddSelectedLayers { - additional_layers: document.document_legacy.intersects_quad_root(quad, font_cache), + additional_layers: document.document_legacy.intersects_quad_root(quad, render_data), } .into(), ); @@ -708,7 +708,7 @@ impl Fsm for SelectToolFsmState { responses.push_back(DocumentMessage::StartTransaction.into()); let pos: Option = position.into(); - tool_data.pivot.set_normalized_position(pos.unwrap(), document, font_cache, responses); + tool_data.pivot.set_normalized_position(pos.unwrap(), document, render_data, responses); self } diff --git a/editor/src/messages/tool/tool_messages/shape_tool.rs b/editor/src/messages/tool/tool_messages/shape_tool.rs index a51f93a92..28c66511d 100644 --- a/editor/src/messages/tool/tool_messages/shape_tool.rs +++ b/editor/src/messages/tool/tool_messages/shape_tool.rs @@ -139,7 +139,7 @@ impl Fsm for ShapeToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -151,7 +151,7 @@ impl Fsm for ShapeToolFsmState { if let ToolMessage::Shape(event) = event { match (self, event) { (Ready, DragStart) => { - shape_data.start(responses, document, input, font_cache); + shape_data.start(responses, document, input, render_data); responses.push_back(DocumentMessage::StartTransaction.into()); shape_data.path = Some(document.get_path_for_new_layer()); responses.push_back(DocumentMessage::DeselectAllLayers.into()); diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index ced62619e..394a9ea78 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -146,7 +146,7 @@ impl Fsm for SplineToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -162,7 +162,7 @@ impl Fsm for SplineToolFsmState { responses.push_back(DocumentMessage::DeselectAllLayers.into()); tool_data.path = Some(document.get_path_for_new_layer()); - tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, font_cache), true, true); + tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(None, None, render_data), true, true); tool_data.snap_manager.add_all_document_handles(document, input, &[], &[], &[]); let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position); diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 82f4409ea..c1c4a1225 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -10,8 +10,7 @@ use crate::messages::tool::utility_types::{EventToMessageMap, Fsm, ToolActionHan use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo}; use document_legacy::intersection::Quad; -use document_legacy::layers::style::{self, Fill, Stroke}; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::{self, Fill, RenderData, Stroke}; use document_legacy::LayerId; use document_legacy::Operation; @@ -213,7 +212,7 @@ fn resize_overlays(overlays: &mut Vec>, responses: &mut VecDeque, font_cache: &FontCache) { +fn update_overlays(document: &DocumentMessageHandler, tool_data: &mut TextToolData, responses: &mut VecDeque, render_data: &RenderData) { let visible_text_layers = document.selected_visible_text_layers().collect::>(); resize_overlays(&mut tool_data.overlays, responses, visible_text_layers.len()); @@ -225,7 +224,7 @@ fn update_overlays(document: &DocumentMessageHandler, tool_data: &mut TextToolDa .document_legacy .layer(layer_path) .unwrap() - .aabb_for_transform(document.document_legacy.multiply_transforms(layer_path).unwrap(), font_cache) + .aabb_for_transform(document.document_legacy.multiply_transforms(layer_path).unwrap(), render_data) .map(|bounds| (bounds, overlay_path)) }) .collect::>(); @@ -250,7 +249,7 @@ impl Fsm for TextToolFsmState { self, event: ToolMessage, tool_data: &mut Self::ToolData, - (document, _document_id, global_tool_data, input, font_cache): ToolActionHandlerData, + (document, _document_id, global_tool_data, input, render_data): ToolActionHandlerData, tool_options: &Self::ToolOptions, responses: &mut VecDeque, ) -> Self { @@ -260,7 +259,7 @@ impl Fsm for TextToolFsmState { if let ToolMessage::Text(event) = event { match (self, event) { (state, DocumentIsDirty) => { - update_overlays(document, tool_data, responses, font_cache); + update_overlays(document, tool_data, responses, render_data); state } @@ -272,7 +271,7 @@ impl Fsm for TextToolFsmState { // Check if the user has selected an existing text layer let new_state = if let Some(clicked_text_layer_path) = document .document_legacy - .intersects_quad_root(quad, font_cache) + .intersects_quad_root(quad, render_data) .last() .filter(|l| document.document_legacy.layer(l).map(|l| l.as_text().is_ok()).unwrap_or(false)) { @@ -367,7 +366,7 @@ impl Fsm for TextToolFsmState { (Editing, UpdateBounds { new_text }) => { resize_overlays(&mut tool_data.overlays, responses, 1); let text = document.document_legacy.layer(&tool_data.layer_path).unwrap().as_text().unwrap(); - let quad = text.bounding_box(&new_text, text.load_face(font_cache)); + let quad = text.bounding_box(&new_text, text.load_face(render_data)); let transformed_quad = document.document_legacy.multiply_transforms(&tool_data.layer_path).unwrap() * quad; let bounds = transformed_quad.bounding_box(); diff --git a/editor/src/messages/tool/utility_types.rs b/editor/src/messages/tool/utility_types.rs index 350770a1c..cadd85ebc 100644 --- a/editor/src/messages/tool/utility_types.rs +++ b/editor/src/messages/tool/utility_types.rs @@ -10,12 +10,12 @@ use crate::messages::layout::utility_types::widgets::label_widgets::{Separator, use crate::messages::prelude::*; use document_legacy::color::Color; -use document_legacy::layers::text_layer::FontCache; +use document_legacy::layers::style::RenderData; use serde::{Deserialize, Serialize}; use std::fmt::{self, Debug}; -pub type ToolActionHandlerData<'a> = (&'a DocumentMessageHandler, u64, &'a DocumentToolData, &'a InputPreprocessorMessageHandler, &'a FontCache); +pub type ToolActionHandlerData<'a> = (&'a DocumentMessageHandler, u64, &'a DocumentToolData, &'a InputPreprocessorMessageHandler, &'a RenderData<'a>); pub trait ToolCommon: for<'a> MessageHandler> + PropertyHolder + ToolTransition + ToolMetadata {} impl ToolCommon for T where T: for<'a> MessageHandler> + PropertyHolder + ToolTransition + ToolMetadata {}