Add String[] as a graphic type for typography (#4141)

* feat: Render List<String> as raw paths in SVG and Vell mode

* chore: code review

* chore: change the hardcoded layout bounds to parley's

* chore: code review

* feat: Split text node to text_layer and text_to_vector node

* fix: CI fail because of difference in nature of Mac and github action

* chore: fix

* chore: replace FontStack as it got removed in parley 0.9

* chore: fmt

* chore: migrate the rendering as of new resource architechture

* chore: add text_layer node to text tool for testing

* code review

* Make boolean ops support the Text type

* chore: Move fallback_font_resource authority from editor to text node

* Fix 'Text Layer' node missing font dropdown

* Change node doc comments from Vec<T> to T[]

* Add migrations from the old Text node to Text -> Text to Vector

* Consolidate

* Rename the text attributes and reorder tilt to come before max_width/height

* Detect legacy Text nodes in the split migration by their trailing separate_glyphs input

* Code review

* Frame Text layer thumbnails by laying out their text for bounds

* Give Text layers click targets and selection outlines via collect_metadata

* Route Text tool through Text to Vector with fill, fixing editing-preview placement

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Jatin Bharti
2026-06-20 01:09:52 +05:30
committed by GitHub
parent 13abf9fa8c
commit 5f100946f2
39 changed files with 967 additions and 204 deletions

View File

@@ -9,7 +9,7 @@ use graph_craft::document::{NodeId, NodeNetwork};
use graph_craft::graphene_compiler::Compiler;
use graph_craft::proto::GraphErrors;
use graphene_std::application_io::{ApplicationIo, ExportFormat, ImageTexture, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
use graphene_std::bounds::{BoundingBox, RenderBoundingBox};
use graphene_std::bounds::RenderBoundingBox;
use graphene_std::list::List;
use graphene_std::memo::IORecord;
use graphene_std::ops::Convert;
@@ -414,10 +414,10 @@ impl NodeRuntime {
continue;
};
// Graphic list: thumbnail
// Graphic list: thumbnail (text-aware bounds, since the `BoundingBox` trait can't lay out `Graphic::Text` content)
if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<Graphic>>>() {
if update_thumbnails {
let bounds = io.output.thumbnail_bounding_box(DAffine2::IDENTITY, true);
let bounds = graphene_std::renderer::graphic_list_bounding_box(&io.output, DAffine2::IDENTITY);
Self::render_thumbnail(&mut self.thumbnail_renders, parent_network_node_id, &io.output, bounds, responses)
}
}
@@ -434,6 +434,13 @@ impl NodeRuntime {
// Insert the vector modify
self.vector_modify.insert(parent_network_node_id, io.output.element(0).cloned().unwrap_or_default());
}
// String list: thumbnail (bounds need text layout, which the `BoundingBox` trait can't do for a bare `String`)
else if let Some(io) = introspected_data.downcast_ref::<IORecord<Context, List<String>>>() {
if update_thumbnails {
let bounds = graphene_std::renderer::text_list_bounding_box(&io.output, DAffine2::IDENTITY);
Self::render_thumbnail(&mut self.thumbnail_renders, parent_network_node_id, &io.output, bounds, responses)
}
}
// Other
else {
log::warn!("Failed to downcast monitor node output {parent_network_node_id:?}");