Files
Graphite/node-graph/nodes/gstd/src/text.rs
Jatin Bharti 5f100946f2 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>
2026-06-19 19:39:52 +00:00

106 lines
3.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use core_types::consts::{DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT};
use core_types::list::List;
use core_types::{ATTR_FONT, ATTR_FONT_SIZE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_TEXT_ALIGN, Ctx};
use graph_craft::application_io::resource::Resource;
use graphic_types::Vector;
pub use text_nodes::*;
/// Produces a styled `String[]` carrying all typographic attributes.
///
/// Use the **Text to Vector** node to convert this into vector geometry if desired.
#[node_macro::node(category("Text"))]
fn text(
_: impl Ctx,
_primary: (),
/// The text content to be drawn.
#[widget(ParsedWidgetOverride::Custom = "text_area")]
#[default("Lorem ipsum")]
text: String,
/// The loaded font file used to draw the text. The editor resolves the chosen typeface to these bytes via the resource system.
#[widget(ParsedWidgetOverride::Custom = "text_font")]
font: Resource,
/// The font size used to draw the text.
#[unit(" px")]
#[default(24.)]
#[hard_min(1.)]
size: f64,
/// The line height ratio, relative to the font size. Each line is drawn lower than its previous line by the distance of *Size* × *Line Height*.
///
/// 0 means all lines overlap. 1 means all lines are spaced by just the font size. 1.2 is a common default for readable text. 2 means double-spaced text.
#[unit("x")]
#[hard_min(0.)]
#[step(0.1)]
#[default(1.2)]
line_height: f64,
/// Additional spacing, in pixels, added between each character.
#[unit(" px")]
#[step(0.1)]
letter_spacing: f64,
/// The angle of faux italic slant applied to each glyph.
#[unit("°")]
#[hard_min(-85.)]
#[hard_max(85.)]
letter_tilt: f64,
/// Enables the maximum width constraint so lines can wrap.
#[widget(ParsedWidgetOverride::Hidden)]
has_max_width: bool,
/// The maximum width that the text block can occupy before wrapping to a new line. Otherwise, lines do not wrap.
#[unit(" px")]
#[hard_min(1.)]
#[widget(ParsedWidgetOverride::Custom = "optional_f64")]
max_width: f64,
/// Whether the *Max Height* property is enabled so that lines beyond it are not drawn.
#[widget(ParsedWidgetOverride::Hidden)]
has_max_height: bool,
/// The maximum height that the text block can occupy. Excess lines are not drawn.
#[unit(" px")]
#[hard_min(1.)]
#[widget(ParsedWidgetOverride::Custom = "optional_f64")]
max_height: f64,
/// The horizontal alignment of each line of text within its surrounding box. To have an effect on a single line of text, *Max Width* must be set.
#[widget(ParsedWidgetOverride::Custom = "text_align")]
align: TextAlign,
) -> List<String> {
let mut list = List::new_from_element(text);
if font != Resource::default() {
list.set_attribute(ATTR_FONT, 0, font);
}
if (size - DEFAULT_FONT_SIZE).abs() > f64::EPSILON {
list.set_attribute(ATTR_FONT_SIZE, 0, size);
}
if (line_height - DEFAULT_LINE_HEIGHT).abs() > f64::EPSILON {
list.set_attribute(ATTR_LINE_HEIGHT, 0, line_height);
}
if letter_spacing != 0. {
list.set_attribute(ATTR_LETTER_SPACING, 0, letter_spacing);
}
if letter_tilt != 0. {
list.set_attribute(ATTR_LETTER_TILT, 0, letter_tilt);
}
if has_max_width {
list.set_attribute(ATTR_MAX_WIDTH, 0, Some(max_width));
}
if has_max_height {
list.set_attribute(ATTR_MAX_HEIGHT, 0, Some(max_height));
}
if align != TextAlign::default() {
list.set_attribute(ATTR_TEXT_ALIGN, 0, align);
}
list
}
/// Converts a styled `String[]` into vector geometry.
#[node_macro::node(category("Text"), name("Text to Vector"))]
fn text_to_vector(
_: impl Ctx,
/// A styled list of text strings produced by the **Text** node (or any other `String[]` source).
#[implementations(List<String>)]
strings: List<String>,
/// Whether to split every letterform into its own vector item. Otherwise, a single vector compound path is produced.
separate_glyphs: bool,
) -> List<Vector> {
shape_text_list(&strings, separate_glyphs)
}