mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 20:08:12 +08:00
Refactor font_cache into render_data; delete image layer type
This commit is contained in:
@@ -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<LayerId>,
|
||||
}
|
||||
|
||||
impl MessageHandler<ArtboardMessage, &FontCache> for ArtboardMessageHandler {
|
||||
impl MessageHandler<ArtboardMessage, &PersistentData> for ArtboardMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque<Message>, font_cache: &FontCache) {
|
||||
fn process_message(&mut self, message: ArtboardMessage, responses: &mut VecDeque<Message>, 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<ArtboardMessage, &FontCache> 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(),
|
||||
);
|
||||
|
||||
@@ -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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
) {
|
||||
use DocumentMessage::*;
|
||||
|
||||
let render_data = RenderData::new(&persistent_data.font_cache, self.view_mode, Some(ipp.document_bounds()));
|
||||
|
||||
#[remain::sorted]
|
||||
match message {
|
||||
// Sub-messages
|
||||
#[remain::unsorted]
|
||||
DispatchOperation(op) => 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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
}
|
||||
#[remain::unsorted]
|
||||
Overlays(message) => {
|
||||
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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
}
|
||||
AddSelectedLayers { additional_layers } => {
|
||||
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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
AlignAxis::Y => 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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
|
||||
// Calculate the bounding box of the region to be exported
|
||||
let bounds = match bounds {
|
||||
ExportBounds::AllArtwork => 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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
FlipAxis::X => 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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
);
|
||||
}
|
||||
LayerChanged { affected_layer_path } => {
|
||||
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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
}
|
||||
RenameLayer { layer_path, new_name } => 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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
let scale = 0.5 + ASYMPTOTIC_EFFECT + document_transform_scale * SCALE_EFFECT;
|
||||
let viewport_size = ipp.viewport_bounds.size();
|
||||
let viewport_mid = ipp.viewport_bounds.center();
|
||||
let [bounds1, bounds2] = self.document_bounds(&persistent_data.font_cache).unwrap_or([viewport_mid; 2]);
|
||||
let [bounds1, bounds2] = self.document_bounds(&render_data).unwrap_or([viewport_mid; 2]);
|
||||
let bounds1 = bounds1.min(viewport_mid) - viewport_size * scale;
|
||||
let bounds2 = bounds2.max(viewport_mid) + viewport_size * scale;
|
||||
let bounds_length = (bounds2 - bounds1) * (1. + SCROLLBAR_SPACING);
|
||||
@@ -782,7 +779,6 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
responses.push_back(FrontendMessage::TriggerRevokeBlobUrl { url: url.clone() }.into());
|
||||
}
|
||||
}
|
||||
LayerDataType::Image(_) => {}
|
||||
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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
responses.push_back(LayerChanged { affected_layer_path: layer_path }.into())
|
||||
}
|
||||
SetLayerName { layer_path, name } => {
|
||||
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<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
||||
responses.push_front(NavigationMessage::SetCanvasZoom { zoom_factor: 2. }.into());
|
||||
}
|
||||
ZoomCanvasToFitAll => {
|
||||
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<Message> {
|
||||
fn select_layer(&mut self, path: &[LayerId], render_data: &RenderData) -> Option<Message> {
|
||||
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<Item = &[LayerId]> {
|
||||
@@ -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<Vec<LayerId>>>, ignore_artboard: Option<LayerId>, font_cache: &'a FontCache) -> impl Iterator<Item = [DVec2; 2]> + 'a {
|
||||
pub fn bounding_boxes<'a>(&'a self, ignore_document: Option<&'a Vec<Vec<LayerId>>>, ignore_artboard: Option<LayerId>, render_data: &'a RenderData) -> impl Iterator<Item = [DVec2; 2]> + '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<LayerId>, font_cache: &FontCache) -> Result<LayerPanelEntry, EditorError> {
|
||||
pub fn layer_panel_entry(&mut self, path: Vec<LayerId>, render_data: &RenderData) -> Result<LayerPanelEntry, EditorError> {
|
||||
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<Vec<LayerPanelEntry>, EditorError> {
|
||||
pub fn layer_panel(&mut self, path: &[LayerId], render_data: &RenderData) -> Result<Vec<LayerPanelEntry>, EditorError> {
|
||||
let folder = self.document_legacy.folder(path)?;
|
||||
let paths: Vec<Vec<LayerId>> = 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<LayerPanelEntry> {
|
||||
pub fn layer_panel_entry_from_path(&self, path: &[LayerId], render_data: &RenderData) -> Option<LayerPanelEntry> {
|
||||
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<Message>, font_cache: &FontCache) {
|
||||
pub fn update_layer_tree_options_bar_widgets(&self, responses: &mut VecDeque<Message>, 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| {
|
||||
|
||||
@@ -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<OverlaysMessage, (bool, &FontCache, &InputPreprocessorMessageHandler)> for OverlaysMessageHandler {
|
||||
impl MessageHandler<OverlaysMessage, (bool, &PersistentData, &InputPreprocessorMessageHandler)> for OverlaysMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: OverlaysMessage, responses: &mut VecDeque<Message>, (overlays_visible, font_cache, ipp): (bool, &FontCache, &InputPreprocessorMessageHandler)) {
|
||||
fn process_message(&mut self, message: OverlaysMessage, responses: &mut VecDeque<Message>, (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<OverlaysMessage, (bool, &FontCache, &InputPreprocessorMessag
|
||||
responses.push_back(
|
||||
FrontendMessage::UpdateDocumentOverlays {
|
||||
svg: if overlays_visible {
|
||||
let render_data = RenderData::new(ViewMode::Normal, font_cache, Some(ipp.document_bounds()));
|
||||
self.overlays_document.render_root(render_data)
|
||||
let render_data = RenderData::new(&persistent_data.font_cache, ViewMode::Normal, Some(ipp.document_bounds()));
|
||||
self.overlays_document.render_root(&render_data)
|
||||
} else {
|
||||
String::from("")
|
||||
},
|
||||
|
||||
+6
-2
@@ -8,6 +8,7 @@ use crate::messages::portfolio::utility_types::PersistentData;
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
use document_legacy::layers::layer_info::LayerDataTypeDiscriminant;
|
||||
use document_legacy::layers::style::{RenderData, ViewMode};
|
||||
use document_legacy::{LayerId, Operation};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -20,6 +21,8 @@ pub struct PropertiesPanelMessageHandler {
|
||||
impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPanelMessageHandlerData<'a>)> for PropertiesPanelMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: PropertiesPanelMessage, responses: &mut VecDeque<Message>, (persistent_data, data): (&PersistentData, PropertiesPanelMessageHandlerData)) {
|
||||
use PropertiesPanelMessage::*;
|
||||
|
||||
let PropertiesPanelMessageHandlerData {
|
||||
artwork_document,
|
||||
artboard_document,
|
||||
@@ -30,7 +33,8 @@ impl<'a> MessageHandler<PropertiesPanelMessage, (&PersistentData, PropertiesPane
|
||||
TargetDocument::Artboard => 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<PropertiesPanelMessage, (&PersistentData, PropertiesPane
|
||||
let (path, target_document) = self.active_selection.as_ref().expect("Received update for properties panel with no active layer");
|
||||
let layer = get_document(*target_document).layer(path).unwrap();
|
||||
|
||||
let transform = apply_transform_operation(layer, transform_op, value, &persistent_data.font_cache);
|
||||
let transform = apply_transform_operation(layer, transform_op, value, &render_data);
|
||||
|
||||
self.create_document_operation(Operation::SetLayerTransform { path: path.clone(), transform }, true, responses);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ use crate::messages::prelude::*;
|
||||
use document_legacy::color::Color;
|
||||
use document_legacy::document::Document;
|
||||
use document_legacy::layers::layer_info::{Layer, LayerDataType, LayerDataTypeDiscriminant};
|
||||
use document_legacy::layers::style::{Fill, Gradient, GradientType, LineCap, LineJoin, Stroke};
|
||||
use document_legacy::layers::text_layer::{FontCache, TextLayer};
|
||||
use document_legacy::layers::style::{Fill, Gradient, GradientType, LineCap, LineJoin, RenderData, Stroke, ViewMode};
|
||||
use document_legacy::layers::text_layer::TextLayer;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use std::f64::consts::PI;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub fn apply_transform_operation(layer: &Layer, transform_op: TransformOp, value: f64, font_cache: &FontCache) -> [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| {
|
||||
|
||||
+5
-5
@@ -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<Vec<LayerId>, LayerMetadata>, &'a mut Document, &'a InputPreprocessorMessageHandler, &'a FontCache);
|
||||
type TransformData<'a> = (&'a mut HashMap<Vec<LayerId>, LayerMetadata>, &'a mut Document, &'a InputPreprocessorMessageHandler, &'a RenderData<'a>);
|
||||
impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> for TransformLayerMessageHandler {
|
||||
#[remain::check]
|
||||
fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque<Message>, (layer_metadata, document, ipp, font_cache): TransformData) {
|
||||
fn process_message(&mut self, message: TransformLayerMessage, responses: &mut VecDeque<Message>, (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::<Vec<_>>();
|
||||
@@ -39,7 +39,7 @@ impl<'a> MessageHandler<TransformLayerMessage, TransformData<'a>> 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<TransformLayerMessage, TransformData<'a>> 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;
|
||||
|
||||
@@ -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<LayerId>, font_cache: &FontCache) -> Self {
|
||||
pub fn new(layer_metadata: &LayerMetadata, transform: DAffine2, layer: &Layer, path: Vec<LayerId>, 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::<Vec<(f64, f64)>>();
|
||||
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::<Vec<_>>().join(",");
|
||||
let thumbnail = if let [(x_min, y_min), (x_max, y_max)] = arr.as_slice() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user