use core_types::consts::{DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT}; use core_types::list::{Item, 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 text 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: Item, /// 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: Item, /// The font size used to draw the text. #[unit(" px")] #[default(24.)] #[hard(1..)] size: Item, /// 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(0..)] #[step(0.1)] #[default(1.2)] line_height: Item, /// Additional spacing, in pixels, added between each character. #[unit(" px")] #[step(0.1)] letter_spacing: Item, /// The angle of faux italic slant applied to each glyph. #[unit("°")] #[hard(-85..85)] letter_tilt: Item, /// Enables the maximum width constraint so lines can wrap. #[widget(ParsedWidgetOverride::Hidden)] has_max_width: Item, /// The maximum width that the text block can occupy before wrapping to a new line. Otherwise, lines do not wrap. #[unit(" px")] #[hard(1..)] #[widget(ParsedWidgetOverride::Custom = "optional_f64")] max_width: Item, /// Whether the *Max Height* property is enabled so that lines beyond it are not drawn. #[widget(ParsedWidgetOverride::Hidden)] has_max_height: Item, /// The maximum height that the text block can occupy. Excess lines are not drawn. #[unit(" px")] #[hard(1..)] #[widget(ParsedWidgetOverride::Custom = "optional_f64")] max_height: Item, /// 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: Item, ) -> Item { let text = text.into_element(); let font = font.into_element(); let (size, line_height, letter_spacing, letter_tilt) = (*size.element(), *line_height.element(), *letter_spacing.element(), *letter_tilt.element()); let (has_max_width, max_width, has_max_height, max_height) = (*has_max_width.element(), *max_width.element(), *has_max_height.element(), *max_height.element()); let align = align.into_element(); let mut item = Item::new_from_element(text); if font != Resource::default() { item.set_attribute(ATTR_FONT, font); } if (size - DEFAULT_FONT_SIZE).abs() > f64::EPSILON { item.set_attribute(ATTR_FONT_SIZE, size); } if (line_height - DEFAULT_LINE_HEIGHT).abs() > f64::EPSILON { item.set_attribute(ATTR_LINE_HEIGHT, line_height); } if letter_spacing != 0. { item.set_attribute(ATTR_LETTER_SPACING, letter_spacing); } if letter_tilt != 0. { item.set_attribute(ATTR_LETTER_TILT, letter_tilt); } if has_max_width { item.set_attribute(ATTR_MAX_WIDTH, Some(max_width)); } if has_max_height { item.set_attribute(ATTR_MAX_HEIGHT, Some(max_height)); } if align != TextAlign::default() { item.set_attribute(ATTR_TEXT_ALIGN, align); } item } /// Converts a styled text string into a vector compound path. #[node_macro::node(category("Text"), name("Text to Vector"))] fn text_to_vector( _: impl Ctx, /// A styled text string produced by the **Text** node (or any other string source). string: Item, ) -> Item { shape_text_item(&string, false).into_iter().next().unwrap_or_default() } /// Splits a styled text string into a separate vector item for each of its glyphs (letterforms). #[node_macro::node(category("Text"), name("Text to Vector Glyphs"))] fn text_to_vector_glyphs( _: impl Ctx, /// A styled text string produced by the **Text** node (or any other string source). string: Item, ) -> List { shape_text_item(&string, true) }