mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 18:38:05 +08:00
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:
@@ -39,6 +39,7 @@ async fn render_intermediate<'a: 'n, T: 'static + Render + WasmNotSend + Send +
|
||||
Context -> List<Raster<CPU>>,
|
||||
Context -> List<Color>,
|
||||
Context -> List<GradientStops>,
|
||||
Context -> List<String>,
|
||||
)]
|
||||
data: impl Node<Context<'static>, Output = T>,
|
||||
) -> RenderIntermediate {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use core_types::Ctx;
|
||||
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::*;
|
||||
|
||||
/// Draws a text string as vector geometry with a choice of font and styling.
|
||||
/// 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,
|
||||
@@ -32,8 +35,13 @@ fn text(
|
||||
/// Additional spacing, in pixels, added between each character.
|
||||
#[unit(" px")]
|
||||
#[step(0.1)]
|
||||
character_spacing: f64,
|
||||
/// Whether the *Max Width* property is enabled so that lines can wrap to fit its specified block width.
|
||||
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.
|
||||
@@ -49,27 +57,49 @@ fn text(
|
||||
#[hard_min(1.)]
|
||||
#[widget(ParsedWidgetOverride::Custom = "optional_f64")]
|
||||
max_height: f64,
|
||||
/// The angle of faux italic slant applied to each glyph.
|
||||
#[unit("°")]
|
||||
#[hard_min(-85.)]
|
||||
#[hard_max(85.)]
|
||||
tilt: 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.
|
||||
/// 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> {
|
||||
let typesetting = TypesettingConfig {
|
||||
font_size: size,
|
||||
line_height_ratio: line_height,
|
||||
character_spacing,
|
||||
max_width: has_max_width.then_some(max_width),
|
||||
max_height: has_max_height.then_some(max_height),
|
||||
tilt,
|
||||
align,
|
||||
};
|
||||
|
||||
to_path(&text, &font, typesetting, separate_glyphs)
|
||||
shape_text_list(&strings, separate_glyphs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user