Fix text per-glyph instance overlays and click target issues

This commit is contained in:
Keavon Chambers 2025-07-14 14:36:39 -07:00
parent 112efe88c2
commit 99966d848d
6 changed files with 24 additions and 10 deletions

View File

@ -974,8 +974,11 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
let mut node_template = resolve_document_node_type(reference)?.default_node_template();
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
document.network_interface.add_import(TaggedValue::None, false, 0, "Primary", "", &[*node_id]);
document.network_interface.add_import(TaggedValue::U32(0), false, 1, "Loop Level", "TODO", &[*node_id]);
let mut node_path = network_path.to_vec();
node_path.push(*node_id);
document.network_interface.add_import(TaggedValue::None, false, 0, "Primary", "", &node_path);
document.network_interface.add_import(TaggedValue::U32(0), false, 1, "Loop Level", "TODO", &node_path);
}
// ==================================

View File

@ -357,7 +357,7 @@ pub fn get_text_id(layer: LayerNodeIdentifier, network_interface: &NodeNetworkIn
}
/// Gets properties from the Text node
pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(&String, &Font, TypesettingConfig)> {
pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(&String, &Font, TypesettingConfig, bool)> {
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs("Text")?;
let Some(TaggedValue::String(text)) = &inputs[1].as_value() else { return None };
@ -368,6 +368,9 @@ pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInter
let Some(&TaggedValue::OptionalF64(max_width)) = inputs[6].as_value() else { return None };
let Some(&TaggedValue::OptionalF64(max_height)) = inputs[7].as_value() else { return None };
let Some(&TaggedValue::F64(tilt)) = inputs[8].as_value() else { return None };
let Some(TaggedValue::Bool(per_glyph_instances)) = &inputs[9].as_value() else {
return None;
};
let typesetting = TypesettingConfig {
font_size,
@ -377,7 +380,7 @@ pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInter
max_height,
tilt,
};
Some((text, font, typesetting))
Some((text, font, typesetting, *per_glyph_instances))
}
pub fn get_stroke_width(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<f64> {

View File

@ -66,14 +66,22 @@ where
/// Calculates the bounding box of the layer's text, based on the settings for max width and height specified in the typesetting config.
pub fn text_bounding_box(layer: LayerNodeIdentifier, document: &DocumentMessageHandler, font_cache: &FontCache) -> Quad {
let Some((text, font, typesetting)) = get_text(layer, &document.network_interface) else {
let Some((text, font, typesetting, per_glyph_instances)) = get_text(layer, &document.network_interface) else {
return Quad::from_box([DVec2::ZERO, DVec2::ZERO]);
};
let font_data = font_cache.get(font).map(|data| load_font(data));
let far = graphene_std::text::bounding_box(text, font_data, typesetting, false);
Quad::from_box([DVec2::ZERO, far])
// TODO: Once the instances refactor is complete and per_glyph_instances can be removed (since it'll be the default),
// TODO: remove this because the top of the dashed bounding overlay should no longer be based on the first line's baseline.
let vertical_offset = if per_glyph_instances {
DVec2::NEG_Y * typesetting.font_size * (1. + (typesetting.line_height_ratio - 1.) / 2.)
} else {
DVec2::ZERO
};
Quad::from_box([DVec2::ZERO + vertical_offset, far + vertical_offset])
}
pub fn calculate_segment_angle(anchor: PointId, segment: SegmentId, vector_data: &VectorData, prefer_handle_direction: bool) -> Option<f64> {

View File

@ -329,7 +329,7 @@ impl TextToolData {
fn load_layer_text_node(&mut self, document: &DocumentMessageHandler) -> Option<()> {
let transform = document.metadata().transform_to_viewport(self.layer);
let color = graph_modification_utils::get_fill_color(self.layer, &document.network_interface).unwrap_or(Color::BLACK);
let (text, font, typesetting) = graph_modification_utils::get_text(self.layer, &document.network_interface)?;
let (text, font, typesetting, _) = graph_modification_utils::get_text(self.layer, &document.network_interface)?;
self.editing_text = Some(EditingText {
text: text.clone(),
font: font.clone(),
@ -524,7 +524,7 @@ impl Fsm for TextToolFsmState {
bounding_box_manager.render_quad(&mut overlay_context);
// Draw red overlay if text is clipped
let transformed_quad = layer_transform * bounds;
if let Some((text, font, typesetting)) = graph_modification_utils::get_text(layer.unwrap(), &document.network_interface) {
if let Some((text, font, typesetting, _)) = graph_modification_utils::get_text(layer.unwrap(), &document.network_interface) {
let font_data = font_cache.get(font).map(|data| load_font(data));
if lines_clipping(text.as_str(), font_data, typesetting) {
overlay_context.line(transformed_quad.0[2], transformed_quad.0[3], Some(COLOR_OVERLAY_RED), Some(3.));

View File

@ -181,7 +181,7 @@ fn layout_text(str: &str, font_data: Option<Blob<u8>>, typesetting: TypesettingC
})?;
const DISPLAY_SCALE: f32 = 1.;
let mut builder = layout_cx.ranged_builder(&mut font_cx, str, DISPLAY_SCALE, true);
let mut builder = layout_cx.ranged_builder(&mut font_cx, str, DISPLAY_SCALE, false);
builder.push_default(StyleProperty::FontSize(typesetting.font_size as f32));
builder.push_default(StyleProperty::LetterSpacing(typesetting.character_spacing as f32));

View File

@ -756,7 +756,7 @@ impl GraphicElementRendered for VectorDataTable {
.chain(single_anchors_targets.into_iter())
.collect::<Vec<ClickTarget>>();
metadata.click_targets.insert(element_id, click_targets);
metadata.click_targets.entry(element_id).or_insert(click_targets);
}
if let Some(upstream_graphic_group) = &instance.upstream_graphic_group {