From 100b23a037b1f78d75e10d3b5ccbd2fb6bb62719 Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 21 May 2026 01:34:52 +0000 Subject: [PATCH 1/3] WIP 1 --- .../document/graph_operation/utility_types.rs | 3 +- .../document/node_graph/node_properties.rs | 21 +++- .../overlays/source-sans-pro-regular.ttf | Bin 119080 -> 0 bytes .../document/overlays/utility_functions.rs | 16 +-- .../document/overlays/utility_types_native.rs | 6 +- .../portfolio/document/utility_types/mod.rs | 1 + .../utility_types/text_resource_resolution.rs | 99 ++++++++++++++++++ .../messages/portfolio/document_migration.rs | 16 +++ .../portfolio/portfolio_message_handler.rs | 24 ++++- .../common_functionality/utility_functions.rs | 5 +- .../messages/tool/tool_messages/text_tool.rs | 41 ++++++-- editor/src/node_graph_executor.rs | 5 - editor/src/node_graph_executor/runtime.rs | 22 +--- node-graph/graphene-cli/src/main.rs | 2 - .../libraries/application-io/src/lib.rs | 10 +- node-graph/nodes/gstd/src/text.rs | 35 +++++-- .../text/assets/source-sans-pro-regular.ttf | Bin 0 -> 254076 bytes .../nodes/text/src/{font_cache.rs => font.rs} | 60 ++--------- node-graph/nodes/text/src/lib.rs | 5 +- node-graph/nodes/text/src/text_context.rs | 43 +++----- node-graph/nodes/text/src/to_path.rs | 14 +-- 21 files changed, 269 insertions(+), 159 deletions(-) delete mode 100644 editor/src/messages/portfolio/document/overlays/source-sans-pro-regular.ttf create mode 100644 editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs create mode 100644 node-graph/nodes/text/assets/source-sans-pro-regular.ttf rename node-graph/nodes/text/src/{font_cache.rs => font.rs} (53%) diff --git a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs index fcfe128492..90a8936ed5 100644 --- a/editor/src/messages/portfolio/document/graph_operation/utility_types.rs +++ b/editor/src/messages/portfolio/document/graph_operation/utility_types.rs @@ -251,9 +251,10 @@ impl<'a> ModifyInputsContext<'a> { let text = resolve_proto_node_type(graphene_std::text::text::IDENTIFIER) .expect("Text node does not exist") .node_template_input_override([ - Some(NodeInput::scope("editor-api")), + None, Some(NodeInput::value(TaggedValue::String(text), false)), Some(NodeInput::value(TaggedValue::Font(font), false)), + Some(NodeInput::value(TaggedValue::None, false)), Some(NodeInput::value(TaggedValue::F64(typesetting.font_size), false)), Some(NodeInput::value(TaggedValue::F64(typesetting.line_height_ratio), false)), Some(NodeInput::value(TaggedValue::F64(typesetting.character_spacing), false)), diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index a58576c408..273e15f242 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -867,11 +867,19 @@ pub fn font_inputs(parameter_widgets_info: ParameterWidgetsInfo) -> (Vec::INDEX, + value: TaggedValue::None, + } + .into(), + PortfolioMessage::LoadFontData { font: load_font }.into(), ]), } } @@ -925,11 +933,18 @@ pub fn font_inputs(parameter_widgets_info: ParameterWidgetsInfo) -> (Vec::INDEX, + value: TaggedValue::None, + } + .into(), + PortfolioMessage::LoadFontData { font: load_font }.into(), ]), } } diff --git a/editor/src/messages/portfolio/document/overlays/source-sans-pro-regular.ttf b/editor/src/messages/portfolio/document/overlays/source-sans-pro-regular.ttf deleted file mode 100644 index ffe27865aaa6eaf96fefe0800afe02a3be71cb2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119080 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 = LazyLock::new(|| { - let mut font_cache = FontCache::default(); - // Initialize with the hardcoded font used by overlay text - const FONT_DATA: &[u8] = include_bytes!("source-sans-pro-regular.ttf"); - let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string()); - font_cache.insert(font, FONT_DATA.to_vec()); - font_cache -}); +// Global lazy initialized font data and text context used for overlay text measurement. +// Reuses the embedded backup font bytes from the text node so we don't ship a second copy of the file. +pub static OVERLAY_FONT_BLOB: LazyLock> = LazyLock::new(|| load_font(DEFAULT_FONT_BYTES)); pub static GLOBAL_TEXT_CONTEXT: LazyLock> = LazyLock::new(|| Mutex::new(TextContext::default())); @@ -249,7 +243,7 @@ pub fn text_width(text: &str, font_size: f64) -> f64 { // TODO: And maybe use the WOFF2 version (if it's supported) for its smaller, compressed file size. let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string()); let mut text_context = GLOBAL_TEXT_CONTEXT.lock().expect("Failed to lock global text context"); - let bounds = text_context.bounding_box(text, &font, &GLOBAL_FONT_CACHE, typesetting, false); + let bounds = text_context.bounding_box(text, &font, &OVERLAY_FONT_BLOB, typesetting, false); bounds.x } diff --git a/editor/src/messages/portfolio/document/overlays/utility_types_native.rs b/editor/src/messages/portfolio/document/overlays/utility_types_native.rs index acda35d859..80145d1f72 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_types_native.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_types_native.rs @@ -3,7 +3,7 @@ use crate::consts::{ COLOR_OVERLAY_YELLOW_DULL, COMPASS_ROSE_ARROW_SIZE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, DOWEL_PIN_RADIUS, GRADIENT_MIDPOINT_DIAMOND_RADIUS, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, RESIZE_HANDLE_SIZE, SKEW_TRIANGLE_OFFSET, SKEW_TRIANGLE_SIZE, }; -use crate::messages::portfolio::document::overlays::utility_functions::{GLOBAL_FONT_CACHE, GLOBAL_TEXT_CONTEXT, hex_to_rgba_u8}; +use crate::messages::portfolio::document::overlays::utility_functions::{GLOBAL_TEXT_CONTEXT, OVERLAY_FONT_BLOB, hex_to_rgba_u8}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::prelude::Message; use crate::messages::prelude::ViewportMessageHandler; @@ -1122,14 +1122,14 @@ impl OverlayContextInternal { // Get text dimensions directly from layout let mut text_context = GLOBAL_TEXT_CONTEXT.lock().expect("Failed to lock global text context"); - let text_size = text_context.bounding_box(text, &font, &GLOBAL_FONT_CACHE, typesetting, false); + let text_size = text_context.bounding_box(text, &font, &OVERLAY_FONT_BLOB, typesetting, false); let text_width = text_size.x; let text_height = text_size.y; // Create a rect from the size (assuming text starts at origin) let text_bounds = kurbo::Rect::new(0., 0., text_width, text_height); // Convert text to vector paths for rendering - let text_list = text_context.to_path(text, &font, &GLOBAL_FONT_CACHE, typesetting, false); + let text_list = text_context.to_path(text, &font, &OVERLAY_FONT_BLOB, typesetting, false); // Calculate position based on pivot let mut position = DVec2::ZERO; diff --git a/editor/src/messages/portfolio/document/utility_types/mod.rs b/editor/src/messages/portfolio/document/utility_types/mod.rs index 93d3e8b552..645776ee58 100644 --- a/editor/src/messages/portfolio/document/utility_types/mod.rs +++ b/editor/src/messages/portfolio/document/utility_types/mod.rs @@ -5,5 +5,6 @@ pub mod error; pub mod misc; pub mod network_interface; pub mod nodes; +pub mod text_resource_resolution; pub mod transformation; pub mod wires; diff --git a/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs b/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs new file mode 100644 index 0000000000..178066cfac --- /dev/null +++ b/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs @@ -0,0 +1,99 @@ +//! Helpers that bridge the editor's font catalog/cache with the hidden `font_resource` input on Text nodes. +//! +//! Each Text node carries two inputs that describe its typeface: the visible `Font` (family + style) and a +//! hidden `font_resource` which is either `()` (use the embedded default font) or a `Resource` wrapping the +//! loaded font bytes. The editor is responsible for keeping the hidden input in sync with the editor-side +//! `FontCache` so the graph picks up newly loaded fonts on the next run. + +use crate::messages::portfolio::document::utility_types::network_interface::{InputConnector, NodeNetworkInterface}; +use graph_craft::application_io::ResourceHash; +use graph_craft::document::value::TaggedValue; +use graph_craft::document::{DocumentNodeImplementation, NodeId, NodeInput, NodeNetwork}; +use graphene_std::NodeInputDecleration; +use graphene_std::text::{Font, FontCache}; + +const TEXT_NODE_FONT_RESOURCE_INPUT_INDEX: usize = 3; + +pub fn patch_text_nodes_with_loaded_font(network_interface: &mut NodeNetworkInterface, target_font: &Font, hash: ResourceHash) -> bool { + let updates = collect_text_node_updates(network_interface.document_network(), &[], &mut |font, current| { + if font != target_font { + return false; + } + !matches!(current, TaggedValue::Resource(existing) if *existing == hash) + }); + + let patched_any = !updates.is_empty(); + for (network_path, node_id, _font) in updates { + network_interface.set_input( + &InputConnector::node(node_id, TEXT_NODE_FONT_RESOURCE_INPUT_INDEX), + NodeInput::value(TaggedValue::Resource(hash), false), + &network_path, + ); + } + patched_any +} + +pub fn refresh_text_node_font_resources(network_interface: &mut NodeNetworkInterface, font_cache: &FontCache) -> Vec { + let updates = collect_text_node_updates(network_interface.document_network(), &[], &mut |_font, _current| true); + + let mut needs_loading = Vec::new(); + for (network_path, node_id, font) in updates { + let current_input = network_interface + .input_from_connector(&InputConnector::node(node_id, TEXT_NODE_FONT_RESOURCE_INPUT_INDEX), &network_path) + .cloned(); + + let current_value = current_input.as_ref().and_then(|input| input.as_value()); + + if font_cache.contains(&font) { + if matches!(current_value, Some(TaggedValue::None)) { + if !needs_loading.contains(&font) { + needs_loading.push(font); + } + } + } else { + if !matches!(current_value, Some(TaggedValue::None)) { + network_interface.set_input( + &InputConnector::node(node_id, TEXT_NODE_FONT_RESOURCE_INPUT_INDEX), + NodeInput::value(TaggedValue::None, false), + &network_path, + ); + } + if !needs_loading.contains(&font) { + needs_loading.push(font); + } + } + } + + needs_loading +} + +fn collect_text_node_updates(network: &NodeNetwork, parent_path: &[NodeId], predicate: &mut dyn FnMut(&Font, &TaggedValue) -> bool) -> Vec<(Vec, NodeId, Font)> { + let mut out = Vec::new(); + for (node_id, node) in network.nodes.iter() { + if let DocumentNodeImplementation::Network(nested) = &node.implementation { + let mut path = parent_path.to_vec(); + path.push(*node_id); + out.extend(collect_text_node_updates(nested, &path, predicate)); + continue; + } + + let is_text_node = matches!(&node.implementation, DocumentNodeImplementation::ProtoNode(identifier) if *identifier == graphene_std::text::text::IDENTIFIER); + if !is_text_node { + continue; + } + + let Some(NodeInput::Value { tagged_value, .. }) = node.inputs.get(graphene_std::text::text::FontInput::INDEX) else { + continue; + }; + let TaggedValue::Font(font) = (**tagged_value).clone() else { continue }; + + let Some(NodeInput::Value { tagged_value: resource_value, .. }) = node.inputs.get(TEXT_NODE_FONT_RESOURCE_INPUT_INDEX) else { + continue; + }; + + if predicate(&font, resource_value) { + out.push((parent_path.to_vec(), *node_id, font)); + } + } + out +} diff --git a/editor/src/messages/portfolio/document_migration.rs b/editor/src/messages/portfolio/document_migration.rs index 72fd196138..83ef25cc5c 100644 --- a/editor/src/messages/portfolio/document_migration.rs +++ b/editor/src/messages/portfolio/document_migration.rs @@ -1501,6 +1501,22 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], for i in 10..=12 { document.network_interface.set_input(&InputConnector::node(*node_id, i), old_inputs[i - 2].clone(), network_path); } + + inputs_count = 13; + } + + // Convert text nodes to use resource for loading font data. + if reference == DefinitionIdentifier::ProtoNode(graphene_std::text::text::IDENTIFIER) && inputs_count == 13 && matches!(node.inputs.first(), Some(NodeInput::Scope(_))) { + let mut template: NodeTemplate = resolve_document_node_type(&reference)?.default_node_template(); + document.network_interface.replace_implementation(node_id, network_path, &mut template); + let old_inputs = document.network_interface.replace_inputs(node_id, network_path, &mut template)?; + + document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path); + document.network_interface.set_input(&InputConnector::node(*node_id, 2), old_inputs[2].clone(), network_path); + #[allow(clippy::needless_range_loop)] + for i in 3..=12 { + document.network_interface.set_input(&InputConnector::node(*node_id, i + 1), old_inputs[i].clone(), network_path); + } } // Upgrade Sine, Cosine, and Tangent nodes to include a boolean input for whether the output should be in radians, which was previously the only option but is now not the default diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 219c05d06c..5f9d3b704c 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -391,15 +391,33 @@ impl MessageHandler> for Portfolio if let Some(style) = self.cached_data.font_catalog.find_font_style_in_catalog(&font) { let font = Font::new(font.font_family, style.to_named_style()); - if !self.cached_data.font_cache.loaded_font(&font) { + if let Some(blob) = self.cached_data.font_cache.get(&font) { + let bytes = Arc::<[u8]>::from(blob.data()); + let hash = graph_craft::application_io::ResourceHash::from(bytes.as_ref()); + responses.add(ResourceMessage::Write { data: bytes }); + let mut patched_any = false; + for document in self.documents.values_mut() { + patched_any |= + crate::messages::portfolio::document::utility_types::text_resource_resolution::patch_text_nodes_with_loaded_font(&mut document.network_interface, &font, hash); + } + if patched_any { + responses.add(NodeGraphMessage::RunDocumentGraph); + } + } else { responses.add(FrontendMessage::TriggerFontDataLoad { font, url: style.url }); } } } PortfolioMessage::FontLoaded { font_family, font_style, data } => { let font = Font::new(font_family, font_style); - self.cached_data.font_cache.insert(font, data); - self.executor.update_font_cache(self.cached_data.font_cache.clone()); + let hash = graph_craft::application_io::ResourceHash::from(data.as_slice()); + self.cached_data.font_cache.insert(font.clone(), data.clone()); + + responses.add(ResourceMessage::Write { data: Arc::<[u8]>::from(data) }); + + for document in self.documents.values_mut() { + crate::messages::portfolio::document::utility_types::text_resource_resolution::patch_text_nodes_with_loaded_font(&mut document.network_interface, &font, hash); + } for document_id in self.document_ids.iter() { let node_to_inspect = self.node_to_inspect(); diff --git a/editor/src/messages/tool/common_functionality/utility_functions.rs b/editor/src/messages/tool/common_functionality/utility_functions.rs index 567672498c..c1af7514f2 100644 --- a/editor/src/messages/tool/common_functionality/utility_functions.rs +++ b/editor/src/messages/tool/common_functionality/utility_functions.rs @@ -16,7 +16,7 @@ use graph_craft::document::value::TaggedValue; use graphene_std::list::List; use graphene_std::renderer::Quad; use graphene_std::subpath::{Bezier, BezierHandles}; -use graphene_std::text::FontCache; +use graphene_std::text::{FontCache, FontSource}; use graphene_std::vector::algorithms::bezpath_algorithms::pathseg_compute_lookup_table; use graphene_std::vector::misc::{HandleId, ManipulatorPointId, dvec2_to_point}; use graphene_std::vector::{HandleExt, PointId, SegmentId, Vector, VectorModification, VectorModificationType}; @@ -73,7 +73,8 @@ pub fn text_bounding_box(layer: LayerNodeIdentifier, document: &DocumentMessageH let Some((text, font, typesetting, _)) = get_text(layer, &document.network_interface) else { return Quad::from_box([DVec2::ZERO, DVec2::ZERO]); }; - let far = graphene_std::text::bounding_box(text, font, font_cache, typesetting, false); + let blob = font_cache.get(font).unwrap_or_else(|| ().font_blob()); + let far = graphene_std::text::bounding_box(text, font, &blob, typesetting, false); Quad::from_box([DVec2::ZERO, far]) } diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 7c94b8d82c..d97a127e58 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -22,7 +22,7 @@ use graph_craft::document::{NodeId, NodeInput}; use graphene_std::choice_type::ChoiceTypeStatic; use graphene_std::color::SRGBA8; use graphene_std::renderer::Quad; -use graphene_std::text::{Font, FontCache, TextAlign, TypesettingConfig, lines_clipping}; +use graphene_std::text::{Font, FontCache, FontSource, TextAlign, TypesettingConfig, lines_clipping}; use graphene_std::vector::style::{Fill, FillChoice, FillChoiceUI}; use graphene_std::{Color, NodeInputDecleration}; @@ -126,8 +126,20 @@ fn create_text_widgets(tool: &TextTool, font_catalog: &FontCatalog, document: &D } }; let preview_font = move |new_font: Font| -> Message { + let mut messages: Vec = vec![apply_font(new_font.clone())]; + if let Some(node_id) = text_node_id { + messages.push( + NodeGraphMessage::SetInputValue { + node_id, + input_index: graphene_std::text::text::FontResourceInput::<()>::INDEX, + value: TaggedValue::None, + } + .into(), + ); + } + messages.push(PortfolioMessage::LoadFontData { font: new_font }.into()); Message::Batched { - messages: Box::new([PortfolioMessage::LoadFontData { font: new_font.clone() }.into(), apply_font(new_font)]), + messages: messages.into_boxed_slice(), } }; let commit_font = move |new_font: Font| -> Message { @@ -499,7 +511,7 @@ impl TextToolData { line_height_ratio: editing_text.typesetting.line_height_ratio, font_size: editing_text.typesetting.font_size, color: editing_text.color.map_or("#000000".to_string(), |color| SRGBA8::from(color).to_css_hex()), - font_data: font_cache.get(&editing_text.font).map(|(data, _)| data.clone()).unwrap_or_default().into(), + font_data: font_cache.get(&editing_text.font).map(|blob| blob.data().to_vec()).unwrap_or_default().into(), transform: editing_text.transform.to_cols_array(), max_width: editing_text.typesetting.max_width, max_height: editing_text.typesetting.max_height, @@ -550,7 +562,10 @@ impl TextToolData { responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![self.layer.to_node()] }); // Make the rendered text invisible while editing responses.add(NodeGraphMessage::SetInput { - input_connector: InputConnector::node(graph_modification_utils::get_text_id(self.layer, &document.network_interface).unwrap(), 1), + input_connector: InputConnector::node( + graph_modification_utils::get_text_id(self.layer, &document.network_interface).unwrap(), + graphene_std::text::text::TextInput::INDEX, + ), input: NodeInput::value(TaggedValue::String("".to_string()), false), }); responses.add(NodeGraphMessage::RunDocumentGraph); @@ -564,7 +579,6 @@ impl TextToolData { self.layer = LayerNodeIdentifier::new_unchecked(NodeId::new()); - responses.add(PortfolioMessage::LoadFontData { font: editing_text.font.clone() }); responses.add(GraphOperationMessage::NewTextLayer { id: self.layer.to_node(), text: String::new(), @@ -573,6 +587,7 @@ impl TextToolData { parent: document.new_layer_parent(true), insert_index: 0, }); + responses.add(PortfolioMessage::LoadFontData { font: editing_text.font.clone() }); responses.add(GraphOperationMessage::FillSet { layer: self.layer, fill: if let Some(color) = editing_text.color { Fill::Solid(color) } else { Fill::None }, @@ -667,7 +682,8 @@ impl Fsm for TextToolFsmState { let transform = document.metadata().transform_to_viewport(tool_data.layer).to_cols_array(); responses.add(FrontendMessage::DisplayEditableTextboxTransform { transform }); if let Some(editing_text) = tool_data.editing_text.as_mut() { - let far = graphene_std::text::bounding_box(&tool_data.new_text, &editing_text.font, font_cache, editing_text.typesetting, false); + let blob = font_cache.get(&editing_text.font).unwrap_or_else(|| ().font_blob()); + let far = graphene_std::text::bounding_box(&tool_data.new_text, &editing_text.font, &blob, editing_text.typesetting, false); if far.x != 0. && far.y != 0. { let quad = Quad::from_box([DVec2::ZERO, far]); let transformed_quad = document.metadata().transform_to_viewport(tool_data.layer) * quad; @@ -711,8 +727,10 @@ impl Fsm for TextToolFsmState { // Draw red overlay if text is clipped let transformed_quad = layer_transform * bounds; if let Some((text, font, typesetting, _)) = graph_modification_utils::get_text(layer.unwrap(), &document.network_interface) - && lines_clipping(text.as_str(), font, font_cache, typesetting) - { + && { + let blob = font_cache.get(font).unwrap_or_else(|| ().font_blob()); + lines_clipping(text.as_str(), font, &blob, typesetting) + } { overlay_context.line(transformed_quad.0[2], transformed_quad.0[3], Some(COLOR_OVERLAY_RED), Some(3.)); } @@ -1014,7 +1032,7 @@ impl Fsm for TextToolFsmState { (TextToolFsmState::Editing, TextToolMessage::RefreshEditingFontData) => { let font = Font::new(tool_options.font.font_family.clone(), tool_options.font.font_style.clone()); responses.add(FrontendMessage::DisplayEditableTextboxUpdateFontData { - font_data: font_cache.get(&font).map(|(data, _)| data.clone()).unwrap_or_default().into(), + font_data: font_cache.get(&font).map(|blob| blob.data().to_vec()).unwrap_or_default().into(), }); TextToolFsmState::Editing @@ -1026,7 +1044,10 @@ impl Fsm for TextToolFsmState { tool_data.set_editing(false, font_cache, responses); responses.add(NodeGraphMessage::SetInput { - input_connector: InputConnector::node(graph_modification_utils::get_text_id(tool_data.layer, &document.network_interface).unwrap(), 1), + input_connector: InputConnector::node( + graph_modification_utils::get_text_id(tool_data.layer, &document.network_interface).unwrap(), + graphene_std::text::text::TextInput::INDEX, + ), input: NodeInput::value(TaggedValue::String(tool_data.new_text.clone()), false), }); responses.add(NodeGraphMessage::RunDocumentGraph); diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 30bcf64f1f..8b6b3d1b51 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -9,7 +9,6 @@ use graphene_std::application_io::{NodeGraphUpdateMessage, RenderConfig, TimingI use graphene_std::color::SRGBA8; use graphene_std::raster::{CPU, Raster}; use graphene_std::renderer::RenderMetadata; -use graphene_std::text::FontCache; use graphene_std::transform::Footprint; use graphene_std::vector::Vector; use interpreted_executor::dynamic_executor::ResolvedDocumentNodeTypesDelta; @@ -95,10 +94,6 @@ impl NodeGraphExecutor { execution_id } - pub fn update_font_cache(&self, font_cache: FontCache) { - self.runtime_io.send(GraphRuntimeRequest::FontCacheUpdate(font_cache)).expect("Failed to send font cache update"); - } - pub fn update_editor_preferences(&self, editor_preferences: EditorPreferences) { self.runtime_io .send(GraphRuntimeRequest::EditorPreferencesUpdate(editor_preferences)) diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index 660fa6d2a4..023f0ea1b7 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -16,7 +16,6 @@ use graphene_std::ops::Convert; use graphene_std::platform_application_io::canvas_utils::{Canvas, CanvasSurface, CanvasSurfaceHandle}; use graphene_std::raster_types::Raster; use graphene_std::renderer::{Render, RenderParams, RenderSvgSegmentList, SvgRender, SvgSegment}; -use graphene_std::text::FontCache; use graphene_std::transform::RenderQuality; use graphene_std::vector::Vector; use graphene_std::vector::style::RenderMode; @@ -69,7 +68,6 @@ pub struct NodeRuntime { pub enum GraphRuntimeRequest { GraphUpdate(GraphUpdate), ExecutionRequest(ExecutionRequest), - FontCacheUpdate(FontCache), EditorPreferencesUpdate(EditorPreferences), } @@ -130,7 +128,6 @@ impl NodeRuntime { update_thumbnails: true, editor_api: PlatformEditorApi { - font_cache: FontCache::default(), editor_preferences: Box::new(EditorPreferences::default()), node_graph_message_sender: Box::new(InternalNodeGraphUpdateSender(sender)), @@ -158,7 +155,6 @@ impl NodeRuntime { } pub async fn run(&mut self) -> Option { - let mut font = None; let mut preferences = None; let mut graph = None; let mut eyedropper = None; @@ -182,7 +178,6 @@ impl NodeRuntime { break; } } - GraphRuntimeRequest::FontCacheUpdate(_) => font = Some(request), GraphRuntimeRequest::EditorPreferencesUpdate(_) => preferences = Some(request), } } @@ -195,27 +190,13 @@ impl NodeRuntime { eyedropper.render_config.pointer = execution.render_config.pointer; } - let requests = [font, preferences, graph, eyedropper, execution].into_iter().flatten(); + let requests = [preferences, graph, eyedropper, execution].into_iter().flatten(); for request in requests { match request { - GraphRuntimeRequest::FontCacheUpdate(font_cache) => { - self.editor_api = PlatformEditorApi { - font_cache, - application_io: self.editor_api.application_io.clone(), - node_graph_message_sender: Box::new(self.sender.clone()), - editor_preferences: Box::new(self.editor_preferences.clone()), - } - .into(); - if let Some(graph) = self.old_graph.clone() { - // We ignore this result as compilation errors should have been reported in an earlier iteration - let _ = self.update_network(graph).await; - } - } GraphRuntimeRequest::EditorPreferencesUpdate(preferences) => { self.editor_preferences = preferences.clone(); self.editor_api = PlatformEditorApi { - font_cache: self.editor_api.font_cache.clone(), application_io: self.editor_api.application_io.clone(), node_graph_message_sender: Box::new(self.sender.clone()), editor_preferences: Box::new(preferences), @@ -576,7 +557,6 @@ pub(crate) fn replace_application_io(application_io: PlatformApplicationIo) { impl NodeRuntime { pub(crate) fn replace_application_io(&mut self, application_io: PlatformApplicationIo) { self.editor_api = PlatformEditorApi { - font_cache: self.editor_api.font_cache.clone(), application_io: Some(application_io.into()), node_graph_message_sender: Box::new(self.sender.clone()), editor_preferences: Box::new(self.editor_preferences.clone()), diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index bf89c743fd..3f44e81f28 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -10,7 +10,6 @@ use graph_craft::graphene_compiler::Compiler; use graph_craft::proto::ProtoNetwork; use graph_craft::util::load_network; use graphene_std::application_io::{ApplicationIo, NodeGraphUpdateMessage, NodeGraphUpdateSender}; -use graphene_std::text::FontCache; use interpreted_executor::dynamic_executor::DynamicExecutor; use interpreted_executor::util::wrap_network_in_scope; use std::error::Error; @@ -133,7 +132,6 @@ async fn main() -> Result<(), Box> { max_render_region_size: EditorPreferences::default().max_render_region_size, }; let editor_api = Arc::new(PlatformEditorApi { - font_cache: FontCache::default(), application_io: Some(application_io_for_api), node_graph_message_sender: Box::new(UpdateLogger {}), editor_preferences: Box::new(preferences), diff --git a/node-graph/libraries/application-io/src/lib.rs b/node-graph/libraries/application-io/src/lib.rs index 6da4bc1b79..8967f7645f 100644 --- a/node-graph/libraries/application-io/src/lib.rs +++ b/node-graph/libraries/application-io/src/lib.rs @@ -6,7 +6,6 @@ use std::hash::{Hash, Hasher}; use std::ptr::addr_of; use std::sync::Arc; use std::time::Duration; -use text_nodes::FontCache; use vector_types::vector::style::RenderMode; pub mod resource; @@ -128,8 +127,6 @@ impl GetEditorPreferences for DummyPreferences { } pub struct EditorApi { - /// Font data (for rendering text) made available to the graph through the `PlatformEditorApi`. - pub font_cache: FontCache, /// Gives access to APIs like resources. pub application_io: Option>, pub node_graph_message_sender: Box, @@ -142,7 +139,6 @@ impl Eq for EditorApi {} impl Default for EditorApi { fn default() -> Self { Self { - font_cache: FontCache::default(), application_io: None, node_graph_message_sender: Box::new(Logger), editor_preferences: Box::new(DummyPreferences), @@ -152,7 +148,6 @@ impl Default for EditorApi { impl Hash for EditorApi { fn hash(&self, state: &mut H) { - self.font_cache.hash(state); self.application_io.as_ref().map_or(0, |io| io as *const _ as usize).hash(state); (self.node_graph_message_sender.as_ref() as *const dyn NodeGraphUpdateSender).hash(state); (self.editor_preferences.as_ref() as *const dyn GetEditorPreferences).hash(state); @@ -167,8 +162,7 @@ impl core_types::graphene_hash::CacheHash for EditorApi { impl PartialEq for EditorApi { fn eq(&self, other: &Self) -> bool { - self.font_cache == other.font_cache - && self.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) == other.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) + self.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) == other.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) && std::ptr::eq(self.node_graph_message_sender.as_ref() as *const _, other.node_graph_message_sender.as_ref() as *const _) && std::ptr::eq(self.editor_preferences.as_ref() as *const _, other.editor_preferences.as_ref() as *const _) } @@ -176,7 +170,7 @@ impl PartialEq for EditorApi { impl Debug for EditorApi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("EditorApi").field("font_cache", &self.font_cache).finish() + f.debug_struct("EditorApi").finish() } } diff --git a/node-graph/nodes/gstd/src/text.rs b/node-graph/nodes/gstd/src/text.rs index 89c557e7ca..35d5d6a270 100644 --- a/node-graph/nodes/gstd/src/text.rs +++ b/node-graph/nodes/gstd/src/text.rs @@ -1,16 +1,16 @@ +use std::sync::LazyLock; + use core_types::Ctx; use core_types::list::List; -use graph_craft::application_io::PlatformEditorApi; +use graph_craft::application_io::Resource; use graphic_types::Vector; pub use text_nodes::*; /// Draws a text string as vector geometry with a choice of font and styling. #[node_macro::node(category("Text"))] -fn text<'i: 'n>( +fn text( _: impl Ctx, - /// The Graphite editor's source for global font resources. - #[scope("editor-api")] - editor_resources: &'i PlatformEditorApi, + _primary: (), /// The text content to be drawn. #[widget(ParsedWidgetOverride::Custom = "text_area")] #[default("Lorem ipsum")] @@ -18,6 +18,10 @@ fn text<'i: 'n>( /// The typeface used to draw the text. #[widget(ParsedWidgetOverride::Custom = "text_font")] font: Font, + /// Hidden input that carries the loaded font bytes as a resource. `()` means use the default embedded font; the editor patches this to a `Resource` once the requested font has been loaded. + #[widget(ParsedWidgetOverride::Hidden)] + #[implementations((), Resource)] + font_resource: F, /// The font size used to draw the text. #[unit(" px")] #[default(24.)] @@ -73,5 +77,24 @@ fn text<'i: 'n>( align, }; - to_path(&text, &font, &editor_resources.font_cache, typesetting, separate_glyphs) + let blob = font_resource.font_blob(); + to_path(&text, &font, &blob, typesetting, separate_glyphs) +} + +pub trait FontSource: Send + Sync { + fn font_blob(&self) -> Blob; +} + +static DEFAULT_FONT_BLOB: LazyLock> = LazyLock::new(|| Blob::new(std::sync::Arc::new(DEFAULT_FONT_BYTES))); + +impl FontSource for () { + fn font_blob(&self) -> Blob { + DEFAULT_FONT_BLOB.clone() + } +} + +impl FontSource for Resource { + fn font_blob(&self) -> Blob { + Blob::new(self.into()) + } } diff --git a/node-graph/nodes/text/assets/source-sans-pro-regular.ttf b/node-graph/nodes/text/assets/source-sans-pro-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a8eae164ea11967a4c12fabab6ef9169a797f1bc GIT binary patch literal 254076 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

$mi!mFVL0u}A-QzTH) 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 literal 0 HcmV?d00001 diff --git a/node-graph/nodes/text/src/font_cache.rs b/node-graph/nodes/text/src/font.rs similarity index 53% rename from node-graph/nodes/text/src/font_cache.rs rename to node-graph/nodes/text/src/font.rs index 258452ebc4..6f462a3c4e 100644 --- a/node-graph/nodes/text/src/font_cache.rs +++ b/node-graph/nodes/text/src/font.rs @@ -1,9 +1,11 @@ use core_types::graphene_hash::CacheHash; use dyn_any::DynAny; use parley::fontique::Blob; -use std::collections::HashMap; use std::sync::Arc; +/// Default font bytes (Source Sans Pro Regular) embedded so the editor can always render text without a frontend font fetch. +pub const DEFAULT_FONT_BYTES: &[u8] = include_bytes!("../assets/source-sans-pro-regular.ttf"); + /// A font type (storing font family and font style and an optional preview URL) #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] #[derive(Debug, Clone, Eq, DynAny)] @@ -21,7 +23,6 @@ impl std::hash::Hash for Font { fn hash(&self, state: &mut H) { self.font_family.hash(state); self.font_style.hash(state); - // Don't consider `font_style_to_restore` in the HashMaps } } @@ -29,13 +30,11 @@ impl CacheHash for Font { fn cache_hash(&self, state: &mut H) { self.font_family.cache_hash(state); self.font_style.cache_hash(state); - // Don't consider `font_style_to_restore` in the HashMaps } } impl PartialEq for Font { fn eq(&self, other: &Self) -> bool { - // Don't consider `font_style_to_restore` in the HashMaps self.font_family == other.font_family && self.font_style == other.font_style } } @@ -66,72 +65,35 @@ impl Font { } } } + impl Default for Font { fn default() -> Self { Self::new(core_types::consts::DEFAULT_FONT_FAMILY.into(), core_types::consts::DEFAULT_FONT_STYLE.into()) } } -/// A cache of all loaded font data and preview urls along with the default font (send from `init_app` in `editor_api.rs`) #[derive(Clone, Default, DynAny)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FontCache { - /// Actual font file data used for rendering a font - font_file_data: HashMap>, + font_blobs: std::collections::HashMap>, } impl std::fmt::Debug for FontCache { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("FontCache").field("font_file_data", &self.font_file_data.keys().collect::>()).finish() - } -} - -impl std::hash::Hash for FontCache { - fn hash(&self, state: &mut H) { - self.font_file_data.len().hash(state); - self.font_file_data.keys().for_each(|font| font.hash(state)); - } -} - -impl PartialEq for FontCache { - fn eq(&self, other: &Self) -> bool { - if self.font_file_data.len() != other.font_file_data.len() { - return false; - } - self.font_file_data.keys().all(|font| other.font_file_data.contains_key(font)) + f.debug_struct("FontCache").field("fonts", &self.font_blobs.keys().collect::>()).finish() } } impl FontCache { - /// Returns the font family name if the font is cached, otherwise returns the fallback font family name if that is cached - pub fn resolve_font<'a>(&'a self, font: &'a Font) -> Option<&'a Font> { - if self.font_file_data.contains_key(font) { - Some(font) - } else { - self.font_file_data - .keys() - .find(|font| font.font_family == core_types::consts::DEFAULT_FONT_FAMILY && font.font_style == core_types::consts::DEFAULT_FONT_STYLE) - } - } - - /// Try to get the bytes for a font - pub fn get<'a>(&'a self, font: &'a Font) -> Option<(&'a Vec, &'a Font)> { - self.resolve_font(font).and_then(|font| self.font_file_data.get(font).map(|data| (data, font))) - } - - /// Get font data as a Blob for use with parley/skrifa - pub fn get_blob<'a>(&'a self, font: &'a Font) -> Option<(Blob, &'a Font)> { - self.get(font).map(|(data, font)| (Blob::new(Arc::new(data.clone())), font)) + pub fn get(&self, font: &Font) -> Option> { + self.font_blobs.get(font).cloned() } - /// Check if the font is already loaded - pub fn loaded_font(&self, font: &Font) -> bool { - self.font_file_data.contains_key(font) + pub fn contains(&self, font: &Font) -> bool { + self.font_blobs.contains_key(font) } - /// Insert a new font into the cache pub fn insert(&mut self, font: Font, data: Vec) { - self.font_file_data.insert(font.clone(), data); + self.font_blobs.insert(font, Blob::new(Arc::new(data))); } } diff --git a/node-graph/nodes/text/src/lib.rs b/node-graph/nodes/text/src/lib.rs index 99f2968b1d..ed91407d06 100644 --- a/node-graph/nodes/text/src/lib.rs +++ b/node-graph/nodes/text/src/lib.rs @@ -1,4 +1,4 @@ -mod font_cache; +mod font; pub mod json; mod path_builder; pub mod regex; @@ -16,7 +16,8 @@ use unicode_segmentation::UnicodeSegmentation; // Re-export for convenience pub use core_types as gcore; -pub use font_cache::*; +pub use font::*; +pub use parley::fontique::Blob; pub use text_context::TextContext; pub use to_path::*; pub use vector_types; diff --git a/node-graph/nodes/text/src/text_context.rs b/node-graph/nodes/text/src/text_context.rs index ec9bf95a17..063a848069 100644 --- a/node-graph/nodes/text/src/text_context.rs +++ b/node-graph/nodes/text/src/text_context.rs @@ -1,4 +1,4 @@ -use super::{Font, FontCache, TypesettingConfig}; +use super::{Font, TypesettingConfig}; use core::cell::RefCell; use core_types::list::List; use glam::DVec2; @@ -19,8 +19,8 @@ thread_local! { pub struct TextContext { font_context: FontContext, layout_context: LayoutContext<()>, - /// Cached font metadata for performance optimization - font_info_cache: HashMap, + /// Cached font metadata for performance optimization. + font_info_cache: HashMap<(Font, usize), (FamilyId, FontInfo)>, } impl TextContext { @@ -32,40 +32,31 @@ impl TextContext { THREAD_TEXT.with_borrow_mut(f) } - /// Resolve a font and return its data as a Blob if available - fn resolve_font_data<'a>(&self, font: &'a Font, font_cache: &'a FontCache) -> Option<(Blob, &'a Font)> { - font_cache.get_blob(font) - } - - /// Get or cache font information for a given font + /// Get or cache font information for a given font and its loaded bytes. fn get_font_info(&mut self, font: &Font, font_data: &Blob) -> Option<(String, FontInfo)> { - // Check if we already have the font info cached - if let Some((family_id, font_info)) = self.font_info_cache.get(font) + let cache_key = (font.clone(), font_data.as_ref().as_ptr() as usize); + + if let Some((family_id, font_info)) = self.font_info_cache.get(&cache_key) && let Some(family_name) = self.font_context.collection.family_name(*family_id) { return Some((family_name.to_string(), font_info.clone())); } - // Register the font and cache the info let families = self.font_context.collection.register_fonts(font_data.clone(), None); families.first().and_then(|(family_id, fonts_info)| { fonts_info.first().and_then(|font_info| { self.font_context.collection.family_name(*family_id).map(|family_name| { - // Cache the font info for future use - self.font_info_cache.insert(font.clone(), (*family_id, font_info.clone())); + self.font_info_cache.insert(cache_key.clone(), (*family_id, font_info.clone())); (family_name.to_string(), font_info.clone()) }) }) }) } - /// Create a text layout using the specified font and typesetting configuration - fn layout_text(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig) -> Option> { - // Note that the actual_font may not be the desired font if that font is not yet loaded. - // It is important not to cache the default font under the name of another font. - let (font_data, actual_font) = self.resolve_font_data(font, font_cache)?; - let (font_family, font_info) = self.get_font_info(actual_font, &font_data)?; + /// Create a text layout using the specified font, font bytes, and typesetting configuration + fn layout_text(&mut self, text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig) -> Option> { + let (font_family, font_info) = self.get_font_info(font, font_data)?; const DISPLAY_SCALE: f32 = 1.; let mut builder = self.layout_context.ranged_builder(&mut self.font_context, text, DISPLAY_SCALE, false); @@ -89,8 +80,8 @@ impl TextContext { } /// Convert text to vector paths using the specified font and typesetting configuration - pub fn to_path(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_items: bool) -> List { - let Some(layout) = self.layout_text(text, font, font_cache, typesetting) else { + pub fn to_path(&mut self, text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig, per_glyph_items: bool) -> List { + let Some(layout) = self.layout_text(text, font, font_data, typesetting) else { return List::new_from_element(Vector::default()); }; @@ -162,8 +153,8 @@ impl TextContext { } /// Calculate the bounding box of text using the specified font and typesetting configuration - pub fn bounding_box(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, for_clipping_test: bool) -> DVec2 { - let Some(layout) = self.layout_text(text, font, font_cache, typesetting) else { + pub fn bounding_box(&mut self, text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig, for_clipping_test: bool) -> DVec2 { + let Some(layout) = self.layout_text(text, font, font_data, typesetting) else { return DVec2::ZERO; }; @@ -181,9 +172,9 @@ impl TextContext { } /// Check if text lines are being clipped due to height constraints - pub fn lines_clipping(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig) -> bool { + pub fn lines_clipping(&mut self, text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig) -> bool { let Some(max_height) = typesetting.max_height else { return false }; - let bounds = self.bounding_box(text, font, font_cache, typesetting, true); + let bounds = self.bounding_box(text, font, font_data, typesetting, true); max_height < bounds.y } } diff --git a/node-graph/nodes/text/src/to_path.rs b/node-graph/nodes/text/src/to_path.rs index d8ba556c17..9c6d070492 100644 --- a/node-graph/nodes/text/src/to_path.rs +++ b/node-graph/nodes/text/src/to_path.rs @@ -1,23 +1,23 @@ use super::text_context::TextContext; -use super::{Font, FontCache, TypesettingConfig}; +use super::{Font, TypesettingConfig}; use core_types::list::List; use glam::DVec2; use parley::fontique::Blob; use std::sync::Arc; use vector_types::Vector; -pub fn to_path(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_items: bool) -> List { - TextContext::with_thread_local(|ctx| ctx.to_path(text, font, font_cache, typesetting, per_glyph_items)) +pub fn to_path(text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig, per_glyph_items: bool) -> List { + TextContext::with_thread_local(|ctx| ctx.to_path(text, font, font_data, typesetting, per_glyph_items)) } -pub fn bounding_box(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, for_clipping_test: bool) -> DVec2 { - TextContext::with_thread_local(|ctx| ctx.bounding_box(text, font, font_cache, typesetting, for_clipping_test)) +pub fn bounding_box(text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig, for_clipping_test: bool) -> DVec2 { + TextContext::with_thread_local(|ctx| ctx.bounding_box(text, font, font_data, typesetting, for_clipping_test)) } pub fn load_font(data: &[u8]) -> Blob { Blob::new(Arc::new(data.to_vec())) } -pub fn lines_clipping(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig) -> bool { - TextContext::with_thread_local(|ctx| ctx.lines_clipping(text, font, font_cache, typesetting)) +pub fn lines_clipping(text: &str, font: &Font, font_data: &Blob, typesetting: TypesettingConfig) -> bool { + TextContext::with_thread_local(|ctx| ctx.lines_clipping(text, font, font_data, typesetting)) } From bb3f16f06dca746a8c9d2ded30ede9e0e8708283 Mon Sep 17 00:00:00 2001 From: Timon Date: Thu, 21 May 2026 01:34:52 +0000 Subject: [PATCH 2/3] WIP 2 --- .../document/document_message_handler.rs | 12 +------- .../document/overlays/utility_functions.rs | 6 ++-- .../utility_types/text_resource_resolution.rs | 16 +++++++++-- .../portfolio/portfolio_message_handler.rs | 8 +++--- node-graph/nodes/gstd/src/text.rs | 6 ++-- node-graph/nodes/text/src/font.rs | 28 +++++++++++++------ 6 files changed, 45 insertions(+), 31 deletions(-) diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 4a6cc18d2a..330de1be35 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -2663,17 +2663,7 @@ impl DocumentMessageHandler { /// Loads all of the fonts in the document. pub fn load_layer_resources(&self, responses: &mut VecDeque) { - let mut fonts_to_load = HashSet::new(); - - for (_, node, _) in self.document_network().recursive_nodes() { - for input in &node.inputs { - if let Some(TaggedValue::Font(font)) = input.as_value() { - fonts_to_load.insert(font.clone()); - } - } - } - - for font in fonts_to_load { + for font in super::utility_types::text_resource_resolution::fonts_missing_text_resources(self.document_network()) { responses.add(PortfolioMessage::LoadFontData { font }); } } diff --git a/editor/src/messages/portfolio/document/overlays/utility_functions.rs b/editor/src/messages/portfolio/document/overlays/utility_functions.rs index 1510b8d467..e6b5f58f2e 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_functions.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_functions.rs @@ -6,7 +6,7 @@ use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerSta use crate::messages::tool::tool_messages::tool_prelude::DocumentMessageHandler; use glam::{DAffine2, DVec2}; use graphene_std::subpath::{Bezier, BezierHandles}; -use graphene_std::text::{Blob, DEFAULT_FONT_BYTES, Font, TextAlign, TextContext, TypesettingConfig, load_font}; +use graphene_std::text::{Blob, FALLBACK_FONT_BYTES, Font, TextAlign, TextContext, TypesettingConfig, load_font}; use graphene_std::vector::misc::ManipulatorPointId; use graphene_std::vector::{PointId, SegmentId, Vector}; use std::collections::HashMap; @@ -222,8 +222,8 @@ pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: & } // Global lazy initialized font data and text context used for overlay text measurement. -// Reuses the embedded backup font bytes from the text node so we don't ship a second copy of the file. -pub static OVERLAY_FONT_BLOB: LazyLock> = LazyLock::new(|| load_font(DEFAULT_FONT_BYTES)); +// Reuses the embedded fallback font bytes from the text node so we don't ship a second copy of the file. +pub static OVERLAY_FONT_BLOB: LazyLock> = LazyLock::new(|| load_font(FALLBACK_FONT_BYTES)); pub static GLOBAL_TEXT_CONTEXT: LazyLock> = LazyLock::new(|| Mutex::new(TextContext::default())); diff --git a/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs b/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs index 178066cfac..7d89fc4335 100644 --- a/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs +++ b/editor/src/messages/portfolio/document/utility_types/text_resource_resolution.rs @@ -1,7 +1,7 @@ //! Helpers that bridge the editor's font catalog/cache with the hidden `font_resource` input on Text nodes. //! //! Each Text node carries two inputs that describe its typeface: the visible `Font` (family + style) and a -//! hidden `font_resource` which is either `()` (use the embedded default font) or a `Resource` wrapping the +//! hidden `font_resource` which is either `()` (use the embedded fallback font) or a `Resource` wrapping the //! loaded font bytes. The editor is responsible for keeping the hidden input in sync with the editor-side //! `FontCache` so the graph picks up newly loaded fonts on the next run. @@ -19,7 +19,7 @@ pub fn patch_text_nodes_with_loaded_font(network_interface: &mut NodeNetworkInte if font != target_font { return false; } - !matches!(current, TaggedValue::Resource(existing) if *existing == hash) + matches!(current, TaggedValue::None) }); let patched_any = !updates.is_empty(); @@ -33,6 +33,18 @@ pub fn patch_text_nodes_with_loaded_font(network_interface: &mut NodeNetworkInte patched_any } +pub fn fonts_missing_text_resources(network: &NodeNetwork) -> Vec { + let updates = collect_text_node_updates(network, &[], &mut |_font, current| matches!(current, TaggedValue::None)); + + let mut fonts = Vec::new(); + for (_network_path, _node_id, font) in updates { + if !fonts.contains(&font) { + fonts.push(font); + } + } + fonts +} + pub fn refresh_text_node_font_resources(network_interface: &mut NodeNetworkInterface, font_cache: &FontCache) -> Vec { let updates = collect_text_node_updates(network_interface.document_network(), &[], &mut |_font, _current| true); diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 5f9d3b704c..d654a0e89b 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -391,8 +391,7 @@ impl MessageHandler> for Portfolio if let Some(style) = self.cached_data.font_catalog.find_font_style_in_catalog(&font) { let font = Font::new(font.font_family, style.to_named_style()); - if let Some(blob) = self.cached_data.font_cache.get(&font) { - let bytes = Arc::<[u8]>::from(blob.data()); + if let Some(bytes) = self.cached_data.font_cache.get_data(&font) { let hash = graph_craft::application_io::ResourceHash::from(bytes.as_ref()); responses.add(ResourceMessage::Write { data: bytes }); let mut patched_any = false; @@ -410,10 +409,11 @@ impl MessageHandler> for Portfolio } PortfolioMessage::FontLoaded { font_family, font_style, data } => { let font = Font::new(font_family, font_style); - let hash = graph_craft::application_io::ResourceHash::from(data.as_slice()); + let data = Arc::<[u8]>::from(data); + let hash = graph_craft::application_io::ResourceHash::from(data.as_ref()); self.cached_data.font_cache.insert(font.clone(), data.clone()); - responses.add(ResourceMessage::Write { data: Arc::<[u8]>::from(data) }); + responses.add(ResourceMessage::Write { data }); for document in self.documents.values_mut() { crate::messages::portfolio::document::utility_types::text_resource_resolution::patch_text_nodes_with_loaded_font(&mut document.network_interface, &font, hash); diff --git a/node-graph/nodes/gstd/src/text.rs b/node-graph/nodes/gstd/src/text.rs index 35d5d6a270..61069de873 100644 --- a/node-graph/nodes/gstd/src/text.rs +++ b/node-graph/nodes/gstd/src/text.rs @@ -18,7 +18,7 @@ fn text( /// The typeface used to draw the text. #[widget(ParsedWidgetOverride::Custom = "text_font")] font: Font, - /// Hidden input that carries the loaded font bytes as a resource. `()` means use the default embedded font; the editor patches this to a `Resource` once the requested font has been loaded. + /// Hidden input that carries the loaded font bytes as a resource. `()` means use the embedded fallback font; the editor patches this to a `Resource` once the requested font has been loaded. #[widget(ParsedWidgetOverride::Hidden)] #[implementations((), Resource)] font_resource: F, @@ -85,11 +85,11 @@ pub trait FontSource: Send + Sync { fn font_blob(&self) -> Blob; } -static DEFAULT_FONT_BLOB: LazyLock> = LazyLock::new(|| Blob::new(std::sync::Arc::new(DEFAULT_FONT_BYTES))); +static FALLBACK_FONT_BLOB: LazyLock> = LazyLock::new(|| Blob::new(std::sync::Arc::new(FALLBACK_FONT_BYTES))); impl FontSource for () { fn font_blob(&self) -> Blob { - DEFAULT_FONT_BLOB.clone() + FALLBACK_FONT_BLOB.clone() } } diff --git a/node-graph/nodes/text/src/font.rs b/node-graph/nodes/text/src/font.rs index 6f462a3c4e..77c5eff73c 100644 --- a/node-graph/nodes/text/src/font.rs +++ b/node-graph/nodes/text/src/font.rs @@ -3,8 +3,8 @@ use dyn_any::DynAny; use parley::fontique::Blob; use std::sync::Arc; -/// Default font bytes (Source Sans Pro Regular) embedded so the editor can always render text without a frontend font fetch. -pub const DEFAULT_FONT_BYTES: &[u8] = include_bytes!("../assets/source-sans-pro-regular.ttf"); +/// Fallback font bytes (Source Sans Pro Regular) embedded so text can render without a frontend font fetch. +pub const FALLBACK_FONT_BYTES: &[u8] = include_bytes!("../assets/source-sans-pro-regular.ttf"); /// A font type (storing font family and font style and an optional preview URL) #[cfg_attr(feature = "wasm", derive(tsify::Tsify))] @@ -74,26 +74,38 @@ impl Default for Font { #[derive(Clone, Default, DynAny)] pub struct FontCache { - font_blobs: std::collections::HashMap>, + font_data: std::collections::HashMap>, +} + +struct FontData(Arc<[u8]>); + +impl AsRef<[u8]> for FontData { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } } impl std::fmt::Debug for FontCache { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("FontCache").field("fonts", &self.font_blobs.keys().collect::>()).finish() + f.debug_struct("FontCache").field("fonts", &self.font_data.keys().collect::>()).finish() } } impl FontCache { pub fn get(&self, font: &Font) -> Option> { - self.font_blobs.get(font).cloned() + self.font_data.get(font).cloned().map(|data| Blob::new(data)) + } + + pub fn get_data(&self, font: &Font) -> Option> { + self.font_data.get(font).map(|data| data.0.clone()) } pub fn contains(&self, font: &Font) -> bool { - self.font_blobs.contains_key(font) + self.font_data.contains_key(font) } - pub fn insert(&mut self, font: Font, data: Vec) { - self.font_blobs.insert(font, Blob::new(Arc::new(data))); + pub fn insert(&mut self, font: Font, data: Arc<[u8]>) { + self.font_data.insert(font, Arc::new(FontData(data))); } } From b9fcfef8fe40614321a82096c5518cabb601e2ec Mon Sep 17 00:00:00 2001 From: Timon Date: Sat, 23 May 2026 16:30:22 +0000 Subject: [PATCH 3/3] WIP 3 --- .../wrapper/src/intercept_frontend_message.rs | 3 +- .../src/messages/frontend/frontend_message.rs | 8 ++- editor/src/messages/frontend/mod.rs | 2 +- editor/src/messages/frontend/utility_types.rs | 16 ++--- .../utility_types/widgets/input_widgets.rs | 1 + .../document/document_message_handler.rs | 3 +- .../document/node_graph/node_properties.rs | 7 +- .../utility_types/text_resource_resolution.rs | 16 ++--- .../messages/portfolio/portfolio_message.rs | 8 +++ .../portfolio/portfolio_message_handler.rs | 65 +++++++------------ .../src/messages/portfolio/utility_types.rs | 56 +++++++++++++--- editor/src/messages/prelude.rs | 2 +- .../common_functionality/utility_functions.rs | 4 +- .../messages/tool/tool_messages/text_tool.rs | 45 +++++++++---- .../components/floating-menus/MenuList.svelte | 29 +++------ frontend/src/managers/fonts.ts | 12 ++++ frontend/wrapper/src/editor_wrapper.rs | 2 +- .../libraries/core-types/src/resource.rs | 6 ++ node-graph/nodes/text/src/font.rs | 39 ----------- 19 files changed, 169 insertions(+), 155 deletions(-) diff --git a/desktop/wrapper/src/intercept_frontend_message.rs b/desktop/wrapper/src/intercept_frontend_message.rs index f32ea1ccc3..4e141046cc 100644 --- a/desktop/wrapper/src/intercept_frontend_message.rs +++ b/desktop/wrapper/src/intercept_frontend_message.rs @@ -8,8 +8,7 @@ use super::messages::{DesktopFrontendMessage, FileFilter, OpenFileDialogContext, pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: FrontendMessage) -> Option { match message { FrontendMessage::Await { future } => { - let message = futures::executor::block_on(async move { future.await }); - return intercept_frontend_message(dispatcher, message); + dispatcher.queue_editor_message(futures::executor::block_on(async move { future.await })); } FrontendMessage::RenderOverlays { context } => { dispatcher.respond(DesktopFrontendMessage::UpdateOverlays(context.take_scene())); diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 52ec511d1d..eecc563f48 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -1,7 +1,7 @@ use super::IconName; use super::utility_types::{MouseCursorIcon, PersistedState}; use crate::messages::app_window::app_window_message_handler::AppWindowPlatform; -use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage, FrontendMessageFuture}; +use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage, MessageFuture}; use crate::messages::input_mapper::utility_types::misc::ActionShortcut; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::node_graph::utility_types::{ @@ -31,7 +31,7 @@ pub enum FrontendMessage { #[serde(skip, default)] #[derivative(Debug = "ignore", PartialEq = "ignore")] #[cfg_attr(feature = "wasm", tsify(type = "unknown"))] - future: FrontendMessageFuture, + future: MessageFuture, }, // Display prefix: make the frontend show something, like a dialog @@ -123,6 +123,10 @@ pub enum FrontendMessage { font: Font, url: String, }, + TriggerFontRegister { + name: String, + data: serde_bytes::ByteBuf, + }, TriggerPersistenceReadState, TriggerPersistenceReadDocument { #[serde(rename = "documentId")] diff --git a/editor/src/messages/frontend/mod.rs b/editor/src/messages/frontend/mod.rs index 03ffecbc2b..28ba98c7b7 100644 --- a/editor/src/messages/frontend/mod.rs +++ b/editor/src/messages/frontend/mod.rs @@ -4,7 +4,7 @@ pub mod utility_types; #[doc(inline)] pub use frontend_message::{FrontendMessage, FrontendMessageDiscriminant}; -pub use utility_types::FrontendMessageFuture; +pub use utility_types::MessageFuture; // TODO: Make this an enum with the actual icon names, somehow derived from or tied to the frontend icon set. // TODO: Then remove `#[widget_builder(string)]` from all icon fields. diff --git a/editor/src/messages/frontend/utility_types.rs b/editor/src/messages/frontend/utility_types.rs index 32a4ccf40b..76539623f3 100644 --- a/editor/src/messages/frontend/utility_types.rs +++ b/editor/src/messages/frontend/utility_types.rs @@ -87,23 +87,23 @@ pub struct EyedropperPreviewImage { } #[derive(Clone, Default)] -pub struct FrontendMessageFuture { - inner: Arc>>, +pub struct MessageFuture { + inner: Arc>>, } -impl FrontendMessageFuture { - pub fn new(future: impl Future + Send + 'static) -> Self { +impl MessageFuture { + pub fn new(future: impl Future + Send + 'static) -> Self { Self { inner: Arc::new(Mutex::new(Some(Box::pin(future)))), } } } -type InnerFrontendMessageFuture = Pin + Send + 'static>>; +type InnerMessageFuture = Pin + Send + 'static>>; -impl IntoFuture for FrontendMessageFuture { - type Output = FrontendMessage; - type IntoFuture = InnerFrontendMessageFuture; +impl IntoFuture for MessageFuture { + type Output = Message; + type IntoFuture = InnerMessageFuture; fn into_future(self) -> Self::IntoFuture { self.inner diff --git a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs index a19aac95bf..06eff3ebc5 100644 --- a/editor/src/messages/layout/utility_types/widgets/input_widgets.rs +++ b/editor/src/messages/layout/utility_types/widgets/input_widgets.rs @@ -147,6 +147,7 @@ impl std::hash::Hash for MenuListEntry { self.label.hash(state); self.icon.hash(state); self.disabled.hash(state); + self.font.hash(state); } } diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 330de1be35..5934e9f1a2 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -931,7 +931,7 @@ impl MessageHandler> for DocumentMes let name = format!("{}.{}", self.name.clone(), FILE_EXTENSION); responses.add(FrontendMessage::Await { - future: FrontendMessageFuture::new(async move { + future: MessageFuture::new(async move { let loads = resource_hashes .into_iter() .map(|hash| { @@ -950,6 +950,7 @@ impl MessageHandler> for DocumentMes folder, content: content.into_bytes().into(), } + .into() }), }); } diff --git a/editor/src/messages/portfolio/document/node_graph/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_properties.rs index 273e15f242..465325d392 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_properties.rs @@ -850,7 +850,12 @@ pub fn font_inputs(parameter_widgets_info: ParameterWidgetsInfo) -> (Vec

{/if} - {#if entry.font} - { - document.fonts.load(`16px "${entry.value}"`).then(() => { - loadedFonts.add(entry.value); - loadedFontsGeneration += 1; // Modify the dirty trigger - }); - }} - /> - {/if} - diff --git a/frontend/src/managers/fonts.ts b/frontend/src/managers/fonts.ts index 043f7ae18e..8c0ff98160 100644 --- a/frontend/src/managers/fonts.ts +++ b/frontend/src/managers/fonts.ts @@ -1,3 +1,4 @@ +import { tick } from "svelte"; import type { SubscriptionsRouter } from "/src/subscriptions-router"; import type { EditorWrapper } from "/wrapper/pkg/graphite_wasm_wrapper"; @@ -58,6 +59,16 @@ export function createFontsManager(subscriptions: SubscriptionsRouter, editor: E console.error("Failed to load font:", error); } }); + + subscriptions.subscribeFrontendMessage("TriggerFontRegister", async (data) => { + await tick(); + + if (data.data.length > 0 && data.data.buffer instanceof ArrayBuffer) { + const fontView = new Uint8Array(data.data.buffer, data.data.byteOffset, data.data.byteLength); + const face = new FontFace(data.name, fontView); + window.document.fonts.add(face); + } + }); } export function destroyFontsManager() { @@ -67,6 +78,7 @@ export function destroyFontsManager() { abortController?.abort(); subscriptions.unsubscribeFrontendMessage("TriggerFontCatalogLoad"); subscriptions.unsubscribeFrontendMessage("TriggerFontDataLoad"); + subscriptions.unsubscribeFrontendMessage("TriggerFontRegister"); } // Self-accepting HMR: tear down the old instance and re-create with the new module's code diff --git a/frontend/wrapper/src/editor_wrapper.rs b/frontend/wrapper/src/editor_wrapper.rs index 7982ece916..e8c6e3ec90 100644 --- a/frontend/wrapper/src/editor_wrapper.rs +++ b/frontend/wrapper/src/editor_wrapper.rs @@ -146,7 +146,7 @@ impl EditorWrapper { if let FrontendMessage::Await { future } = message { let wrapper = self.clone(); wasm_bindgen_futures::spawn_local(async move { - wrapper.send_frontend_message_to_js(future.await); + wrapper.dispatch(future.await); }); return; } diff --git a/node-graph/libraries/core-types/src/resource.rs b/node-graph/libraries/core-types/src/resource.rs index 9121f55456..58b990470b 100644 --- a/node-graph/libraries/core-types/src/resource.rs +++ b/node-graph/libraries/core-types/src/resource.rs @@ -15,6 +15,12 @@ impl Resource { } } +impl Default for Resource { + fn default() -> Self { + Self { inner: Arc::new(Vec::new()) } + } +} + impl From<&Resource> for Arc + Send + Sync> { fn from(val: &Resource) -> Self { val.inner.clone() diff --git a/node-graph/nodes/text/src/font.rs b/node-graph/nodes/text/src/font.rs index 77c5eff73c..64b56f0496 100644 --- a/node-graph/nodes/text/src/font.rs +++ b/node-graph/nodes/text/src/font.rs @@ -1,7 +1,5 @@ use core_types::graphene_hash::CacheHash; use dyn_any::DynAny; -use parley::fontique::Blob; -use std::sync::Arc; /// Fallback font bytes (Source Sans Pro Regular) embedded so text can render without a frontend font fetch. pub const FALLBACK_FONT_BYTES: &[u8] = include_bytes!("../assets/source-sans-pro-regular.ttf"); @@ -72,43 +70,6 @@ impl Default for Font { } } -#[derive(Clone, Default, DynAny)] -pub struct FontCache { - font_data: std::collections::HashMap>, -} - -struct FontData(Arc<[u8]>); - -impl AsRef<[u8]> for FontData { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl std::fmt::Debug for FontCache { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("FontCache").field("fonts", &self.font_data.keys().collect::>()).finish() - } -} - -impl FontCache { - pub fn get(&self, font: &Font) -> Option> { - self.font_data.get(font).cloned().map(|data| Blob::new(data)) - } - - pub fn get_data(&self, font: &Font) -> Option> { - self.font_data.get(font).map(|data| data.0.clone()) - } - - pub fn contains(&self, font: &Font) -> bool { - self.font_data.contains_key(font) - } - - pub fn insert(&mut self, font: Font, data: Arc<[u8]>) { - self.font_data.insert(font, Arc::new(FontData(data))); - } -} - // TODO: Eventually remove this migration document upgrade code fn migrate_font_style<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result { use serde::Deserialize;