mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Migrate attribute call sites from string keys to typed keys
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use core_types::list::{Item, List};
|
||||
use core_types::{ATTR_TYPE, Ctx};
|
||||
use core_types::{Ctx, attr};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::unescape_string;
|
||||
@@ -265,7 +265,7 @@ fn query_json_all(
|
||||
let mut results = Vec::new();
|
||||
resolve_all(&value, &segments, !*unquote_strings.element(), &mut results);
|
||||
|
||||
results.into_iter().map(|(text, ty)| Item::new_from_element(text).with_attribute(ATTR_TYPE, ty.to_string())).collect()
|
||||
results.into_iter().map(|(text, ty)| Item::new_from_element(text).with_attr::<attr::Type>(ty.to_string())).collect()
|
||||
}
|
||||
|
||||
/// A parsed segment of a JSON access path.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core_types::attr;
|
||||
use core_types::list::{Item, List};
|
||||
use core_types::{ATTR_EDITOR_CLICK_TARGET, ATTR_EDITOR_TEXT_FRAME, ATTR_TRANSFORM};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use parley::GlyphRun;
|
||||
use skrifa::GlyphId;
|
||||
@@ -15,13 +15,13 @@ pub struct PathBuilder {
|
||||
origin: DVec2,
|
||||
glyph_subpaths: Vec<Subpath<PointId>>,
|
||||
pub vector_list: List<Vector>,
|
||||
/// Per-glyph AABBs collected in single-item mode, published as `ATTR_EDITOR_CLICK_TARGET` in `finalize()`.
|
||||
/// Per-glyph AABBs collected in single-item mode, published as `vector_types::attr::editor::ClickTarget` in `finalize()`.
|
||||
merged_click_target_bboxes: Vec<[DVec2; 2]>,
|
||||
/// Per-glyph baselines, parallel to `merged_click_target_bboxes`. Groups glyphs by line for the widening pass.
|
||||
merged_click_target_baselines: Vec<f64>,
|
||||
/// Per-glyph AABBs in glyph-local space (multi-item mode), widened in `finalize()` to fill gaps.
|
||||
per_glyph_bboxes: Vec<Option<[DVec2; 2]>>,
|
||||
/// Text frame size, stamped per item as `ATTR_EDITOR_TEXT_FRAME` relative to each item's origin.
|
||||
/// Text frame size, stamped per item as `attr::editor::TextFrame` relative to each item's origin.
|
||||
text_frame_size: DVec2,
|
||||
/// First glyph's baseline offset (pre-height-filter). Used for the empty placeholder item so
|
||||
/// `local_transforms` stays stable when all glyphs are clipped during a resize drag.
|
||||
@@ -85,8 +85,8 @@ impl PathBuilder {
|
||||
let frame_in_item_local = DAffine2::from_scale_angle_translation(self.text_frame_size, 0., -glyph_offset);
|
||||
|
||||
let item = Item::new_from_element(Vector::from_subpaths(core::mem::take(&mut self.glyph_subpaths), false))
|
||||
.with_attribute(ATTR_TRANSFORM, DAffine2::from_translation(glyph_offset))
|
||||
.with_attribute(ATTR_EDITOR_TEXT_FRAME, frame_in_item_local);
|
||||
.with_attr::<attr::Transform>(DAffine2::from_translation(glyph_offset))
|
||||
.with_attr::<attr::editor::TextFrame>(frame_in_item_local);
|
||||
self.vector_list.push(item);
|
||||
|
||||
// Defer click target creation to `finalize()` where adjacent AABBs get widened
|
||||
@@ -170,8 +170,8 @@ impl PathBuilder {
|
||||
if self.vector_list.is_empty() {
|
||||
let frame_in_item_local = DAffine2::from_scale_angle_translation(self.text_frame_size, 0., -self.first_glyph_offset);
|
||||
let item = Item::new_from_element(Vector::default())
|
||||
.with_attribute(ATTR_TRANSFORM, DAffine2::from_translation(self.first_glyph_offset))
|
||||
.with_attribute(ATTR_EDITOR_TEXT_FRAME, frame_in_item_local);
|
||||
.with_attr::<attr::Transform>(DAffine2::from_translation(self.first_glyph_offset))
|
||||
.with_attr::<attr::editor::TextFrame>(frame_in_item_local);
|
||||
self.vector_list.push(item);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ impl PathBuilder {
|
||||
.enumerate()
|
||||
.filter_map(|(index, bbox)| {
|
||||
let bbox = (*bbox)?;
|
||||
let offset = self.vector_list.attribute_cloned_or_default::<DAffine2>(ATTR_TRANSFORM, index).translation;
|
||||
let offset = self.vector_list.attr_cloned_or_default::<attr::Transform>(index).translation;
|
||||
Some((index, offset, [bbox[0] + offset, bbox[1] + offset]))
|
||||
})
|
||||
.collect();
|
||||
@@ -197,7 +197,7 @@ impl PathBuilder {
|
||||
for (entry, widened) in entries.iter().zip(layer_bboxes.iter()) {
|
||||
let glyph_local = [widened[0] - entry.1, widened[1] - entry.1];
|
||||
let rect = Subpath::new_rectangle(glyph_local[0], glyph_local[1]);
|
||||
self.vector_list.set_attribute(ATTR_EDITOR_CLICK_TARGET, entry.0, Vector::from_subpaths([rect], false));
|
||||
self.vector_list.set_attr::<vector_types::attr::editor::ClickTarget>(entry.0, Vector::from_subpaths([rect], false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,14 +207,14 @@ impl PathBuilder {
|
||||
widen_horizontal_gaps(&mut bboxes, &self.merged_click_target_baselines);
|
||||
|
||||
let widened_subpaths: Vec<_> = bboxes.iter().map(|[min, max]| Subpath::new_rectangle(*min, *max)).collect();
|
||||
self.vector_list.set_attribute(ATTR_EDITOR_CLICK_TARGET, 0, Vector::from_subpaths(widened_subpaths, false));
|
||||
self.vector_list.set_attr::<vector_types::attr::editor::ClickTarget>(0, Vector::from_subpaths(widened_subpaths, false));
|
||||
}
|
||||
|
||||
// Fill in text frame for items that don't have one yet (single-item mode, where item 0 = identity)
|
||||
let frame = DAffine2::from_scale(self.text_frame_size);
|
||||
for index in 0..self.vector_list.len() {
|
||||
if self.vector_list.attribute::<DAffine2>(ATTR_EDITOR_TEXT_FRAME, index).is_none() {
|
||||
self.vector_list.set_attribute(ATTR_EDITOR_TEXT_FRAME, index, frame);
|
||||
if self.vector_list.attr::<attr::editor::TextFrame>(index).is_none() {
|
||||
self.vector_list.set_attr::<attr::editor::TextFrame>(index, frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use core_types::list::{Item, List};
|
||||
use core_types::registry::types::SignedInteger;
|
||||
use core_types::{ATTR_END, ATTR_NAME, ATTR_START, Ctx};
|
||||
use core_types::{Ctx, attr};
|
||||
|
||||
/// Checks whether the string contains a match for the given regular expression pattern. Optionally restricts the match to only the start and/or end of the string.
|
||||
#[node_macro::node(category("Text: Regex"))]
|
||||
@@ -159,10 +159,7 @@ fn regex_find(
|
||||
let start = captured.map_or(0_u64, |m| m.start() as u64);
|
||||
let end = captured.map_or(0_u64, |m| m.end() as u64);
|
||||
let name = capture_names.get(i).cloned().flatten().unwrap_or_default();
|
||||
Item::new_from_element(text)
|
||||
.with_attribute(ATTR_START, start)
|
||||
.with_attribute(ATTR_END, end)
|
||||
.with_attribute(ATTR_NAME, name)
|
||||
Item::new_from_element(text).with_attr::<attr::Start>(start).with_attr::<attr::End>(end).with_attr::<attr::Name>(name)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -208,8 +205,8 @@ fn regex_find_all(
|
||||
.filter_map(|m| m.ok())
|
||||
.map(|m| {
|
||||
Item::new_from_element(m.as_str().to_string())
|
||||
.with_attribute(ATTR_START, m.start() as u64)
|
||||
.with_attribute(ATTR_END, m.end() as u64)
|
||||
.with_attr::<attr::Start>(m.start() as u64)
|
||||
.with_attr::<attr::End>(m.end() as u64)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use super::TypesettingConfig;
|
||||
use super::text_context::TextContext;
|
||||
use core_types::blending::BlendMode;
|
||||
use core_types::list::{Item, List, NodeIdPath};
|
||||
use core_types::{
|
||||
ATTR_BLEND_MODE, ATTR_EDITOR_LAYER_PATH, ATTR_FONT, ATTR_FONT_SIZE, ATTR_LETTER_SPACING, ATTR_LETTER_TILT, ATTR_LINE_HEIGHT, ATTR_MAX_HEIGHT, ATTR_MAX_WIDTH, ATTR_OPACITY, ATTR_OPACITY_FILL,
|
||||
ATTR_TEXT_ALIGN, ATTR_TRANSFORM,
|
||||
};
|
||||
use core_types::attr;
|
||||
use core_types::list::{Item, List};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graphene_resource::Resource;
|
||||
use vector_types::Vector;
|
||||
@@ -33,45 +29,45 @@ pub fn shape_text_item(item: &Item<String>, separate_glyphs: bool) -> List<Vecto
|
||||
|
||||
// Use fallback font when none is explicitly attached.
|
||||
let font: Resource = {
|
||||
let font: Resource = item.attribute_cloned_or_default(ATTR_FONT);
|
||||
let font: Resource = item.attr_cloned_or_default::<crate::attr::Font>();
|
||||
if font.is_empty() { super::FALLBACK_FONT_RESOURCE.clone() } else { font }
|
||||
};
|
||||
|
||||
let defaults = TypesettingConfig::default();
|
||||
let typesetting = TypesettingConfig {
|
||||
font_size: item.attribute_cloned_or(ATTR_FONT_SIZE, defaults.font_size),
|
||||
line_height_ratio: item.attribute_cloned_or(ATTR_LINE_HEIGHT, defaults.line_height_ratio),
|
||||
letter_spacing: item.attribute_cloned_or(ATTR_LETTER_SPACING, defaults.letter_spacing),
|
||||
letter_tilt: item.attribute_cloned_or(ATTR_LETTER_TILT, defaults.letter_tilt),
|
||||
max_width: item.attribute_cloned_or::<Option<f64>>(ATTR_MAX_WIDTH, defaults.max_width),
|
||||
max_height: item.attribute_cloned_or::<Option<f64>>(ATTR_MAX_HEIGHT, defaults.max_height),
|
||||
align: item.attribute_cloned_or(ATTR_TEXT_ALIGN, defaults.align),
|
||||
font_size: item.attr_cloned_or::<attr::FontSize>(defaults.font_size),
|
||||
line_height_ratio: item.attr_cloned_or::<attr::LineHeight>(defaults.line_height_ratio),
|
||||
letter_spacing: item.attr_cloned_or::<attr::LetterSpacing>(defaults.letter_spacing),
|
||||
letter_tilt: item.attr_cloned_or::<attr::LetterTilt>(defaults.letter_tilt),
|
||||
max_width: item.attr_cloned_or::<attr::MaxWidth>(defaults.max_width),
|
||||
max_height: item.attr_cloned_or::<attr::MaxHeight>(defaults.max_height),
|
||||
align: item.attr_cloned_or::<crate::attr::TextAlign>(defaults.align),
|
||||
};
|
||||
|
||||
let vectors = to_path(text, &font, typesetting, separate_glyphs);
|
||||
let transform = item.attribute_cloned_or_default::<DAffine2>(ATTR_TRANSFORM);
|
||||
let layer_path = item.attribute::<NodeIdPath>(ATTR_EDITOR_LAYER_PATH).cloned();
|
||||
let blend_mode = item.attribute::<BlendMode>(ATTR_BLEND_MODE).copied();
|
||||
let opacity = item.attribute::<f64>(ATTR_OPACITY).copied();
|
||||
let opacity_fill = item.attribute::<f64>(ATTR_OPACITY_FILL).copied();
|
||||
let transform = item.attr_cloned_or_default::<attr::Transform>();
|
||||
let layer_path = item.attr::<attr::editor::LayerPath>().cloned();
|
||||
let blend_mode = item.attr::<attr::BlendMode>().copied();
|
||||
let opacity = item.attr::<attr::Opacity>().copied();
|
||||
let opacity_fill = item.attr::<attr::OpacityFill>().copied();
|
||||
|
||||
let mut result = List::new();
|
||||
for mut produced in vectors.into_iter() {
|
||||
if transform != DAffine2::IDENTITY {
|
||||
let local = produced.attribute_cloned_or_default::<DAffine2>(ATTR_TRANSFORM);
|
||||
produced.set_attribute(ATTR_TRANSFORM, transform * local);
|
||||
let local = produced.attr_cloned_or_default::<attr::Transform>();
|
||||
produced.set_attr::<attr::Transform>(transform * local);
|
||||
}
|
||||
if let Some(layer_path) = &layer_path {
|
||||
produced.set_attribute(ATTR_EDITOR_LAYER_PATH, layer_path.clone());
|
||||
produced.set_attr::<attr::editor::LayerPath>(layer_path.clone());
|
||||
}
|
||||
if let Some(blend_mode) = blend_mode {
|
||||
produced.set_attribute(ATTR_BLEND_MODE, blend_mode);
|
||||
produced.set_attr::<attr::BlendMode>(blend_mode);
|
||||
}
|
||||
if let Some(opacity) = opacity {
|
||||
produced.set_attribute(ATTR_OPACITY, opacity);
|
||||
produced.set_attr::<attr::Opacity>(opacity);
|
||||
}
|
||||
if let Some(opacity_fill) = opacity_fill {
|
||||
produced.set_attribute(ATTR_OPACITY_FILL, opacity_fill);
|
||||
produced.set_attr::<attr::OpacityFill>(opacity_fill);
|
||||
}
|
||||
result.push(produced);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user