mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 14:58:05 +08:00
* Revamp the syntax to #[hard(a..b)] and #[soft(a..b)] bounds on node definitions * Address review feedback: error on empty bounds ranges and remove redundant count clamps * Fix NaN transform from Repeat Array with a count of 1 * Remove redundant manual clamps already enforced by #[hard(...)] bounds
105 lines
3.8 KiB
Rust
105 lines
3.8 KiB
Rust
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(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(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(-85..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(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(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)
|
||
}
|