Add max width/height to text layers and draggable text boxes to the Text tool (#2118)

* Make progress in text tool

* Add line_width to gcore and gstd

* minor fix

* Dragging sets line_width correctly

* Get draw overlay to work

* Typo fix

* Make progress in text tool

* Add line_width to gcore and gstd

* minor fix

* Dragging sets line_width correctly

* Get draw overlay to work

* Typo fix

* Improve text bounding box

* Add toggle for editing line width

* Take absolute value of drag

* Fix optional properties

* Code review

* Attempt to add box height and abort with keys

* Attempt to add key modifiers and snap manager

* Use resize for improved dragging

* Refactor typesetting configuration into a struct

* Fix missing px unit in frontend

* Remove lines on rendered text

* Fix backwards compatibility

* Refactor lenient slection as an associate function in tool data

* Add dashed quad to text nodes

* Use correct names for max height and width

* Additional renames and reorder

* ReResolve conflict

* Code review and improvements

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Nitish Choudhary
2024-12-31 20:50:47 -08:00
committed by GitHub
co-authored by hypercube Keavon Chambers
parent f225756655
commit 66357540bb
34 changed files with 529 additions and 271 deletions
@@ -4,7 +4,7 @@ use crate::messages::prelude::*;
use bezier_rs::Subpath;
use graph_craft::document::{value::TaggedValue, NodeId, NodeInput};
use graphene_core::raster::{BlendMode, ImageFrame};
use graphene_core::text::Font;
use graphene_core::text::{Font, TypesettingConfig};
use graphene_core::vector::style::Gradient;
use graphene_core::vector::PointId;
use graphene_core::Color;
@@ -127,7 +127,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, f64, f64, f64)> {
pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(&String, &Font, TypesettingConfig)> {
let inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs("Text")?;
let Some(TaggedValue::String(text)) = &inputs[1].as_value() else { return None };
@@ -135,8 +135,17 @@ pub fn get_text(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInter
let Some(&TaggedValue::F64(font_size)) = inputs[3].as_value() else { return None };
let Some(&TaggedValue::F64(line_height_ratio)) = inputs[4].as_value() else { return None };
let Some(&TaggedValue::F64(character_spacing)) = inputs[5].as_value() else { return None };
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 };
Some((text, font, font_size, line_height_ratio, character_spacing))
let typesetting = TypesettingConfig {
font_size,
line_height_ratio,
max_width,
character_spacing,
max_height,
};
Some((text, font, typesetting))
}
pub fn get_stroke_width(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<f64> {
@@ -1,15 +1,13 @@
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::prelude::*;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::common_functionality::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnapTypeConfiguration};
use crate::messages::{input_mapper::utility_types::input_keyboard::Key, portfolio::document::graph_operation::utility_types::TransformIn};
use glam::{DAffine2, DVec2, Vec2Swizzles};
use super::snapping::{SnapCandidatePoint, SnapConstraint, SnapData, SnapTypeConfiguration};
#[derive(Clone, Debug, Default)]
pub struct Resize {
drag_start: ViewportPosition,
/// Stored as a document position so the start doesn't move if the canvas is panned.
drag_start: DVec2,
pub layer: Option<LayerNodeIdentifier>,
pub snap_manager: SnapManager,
}
@@ -29,6 +27,8 @@ impl Resize {
root_transform.transform_point2(self.drag_start)
}
/// Compute the drag start and end based on the current mouse position. If the layer doesn't exist, returns [`None`].
/// If you want to draw even without a layer, use [`Resize::calculate_points_ignore_layer`].
pub fn calculate_points(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key) -> Option<[DVec2; 2]> {
let layer = self.layer?;
@@ -41,7 +41,12 @@ impl Resize {
self.layer.take();
return None;
}
Some(self.calculate_points_ignore_layer(document, input, center, lock_ratio))
}
/// Compute the drag start and end based on the current mouse position. Ignores the state of the layer.
/// If you want to only draw whilst a layer exists, use [`Resize::calculate_points`].
pub fn calculate_points_ignore_layer(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key) -> [DVec2; 2] {
let start = self.viewport_drag_start(document);
let mouse = input.mouse.position;
let document_to_viewport = document.navigation_handler.calculate_offset_transform(input.viewport_bounds.center(), &document.document_ptz);
@@ -88,7 +93,7 @@ impl Resize {
self.snap_manager.update_indicator(snapped);
}
Some(points_viewport)
points_viewport
}
pub fn calculate_transform(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, center: Key, lock_ratio: Key, skip_rerender: bool) -> Option<Message> {