@@ -24,7 +24,9 @@ pub struct TextTool {
2424}
2525
2626pub struct TextOptions {
27- font_size : u32 ,
27+ font_size : f64 ,
28+ line_height_ratio : f64 ,
29+ character_spacing : f64 ,
2830 font_name : String ,
2931 font_style : String ,
3032 fill : ToolColorOptions ,
@@ -33,7 +35,9 @@ pub struct TextOptions {
3335impl Default for TextOptions {
3436 fn default ( ) -> Self {
3537 Self {
36- font_size : 24 ,
38+ font_size : 24. ,
39+ line_height_ratio : 1.2 ,
40+ character_spacing : 1. ,
3741 font_name : graphene_core:: consts:: DEFAULT_FONT_FAMILY . into ( ) ,
3842 font_style : graphene_core:: consts:: DEFAULT_FONT_STYLE . into ( ) ,
3943 fill : ToolColorOptions :: new_primary ( ) ,
@@ -63,7 +67,9 @@ pub enum TextOptionsUpdate {
6367 FillColor ( Option < Color > ) ,
6468 FillColorType ( ToolColorType ) ,
6569 Font { family : String , style : String } ,
66- FontSize ( u32 ) ,
70+ FontSize ( f64 ) ,
71+ LineHeightRatio ( f64 ) ,
72+ CharacterSpacing ( f64 ) ,
6773 WorkingColors ( Option < Color > , Option < Color > ) ,
6874}
6975
@@ -100,20 +106,40 @@ fn create_text_widgets(tool: &TextTool) -> Vec<WidgetHolder> {
100106 . into ( )
101107 } )
102108 . widget_holder ( ) ;
103- let size = NumberInput :: new ( Some ( tool. options . font_size as f64 ) )
109+ let size = NumberInput :: new ( Some ( tool. options . font_size ) )
104110 . unit ( " px" )
105111 . label ( "Size" )
106112 . int ( )
107113 . min ( 1. )
108114 . max ( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 )
109- . on_update ( |number_input : & NumberInput | TextToolMessage :: UpdateOptions ( TextOptionsUpdate :: FontSize ( number_input. value . unwrap ( ) as u32 ) ) . into ( ) )
115+ . on_update ( |number_input : & NumberInput | TextToolMessage :: UpdateOptions ( TextOptionsUpdate :: FontSize ( number_input. value . unwrap ( ) ) ) . into ( ) )
116+ . widget_holder ( ) ;
117+ let line_height_ratio = NumberInput :: new ( Some ( tool. options . line_height_ratio ) )
118+ . label ( "Line Height" )
119+ . int ( )
120+ . min ( 0. )
121+ . max ( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 )
122+ . step ( 0.1 )
123+ . on_update ( |number_input : & NumberInput | TextToolMessage :: UpdateOptions ( TextOptionsUpdate :: LineHeightRatio ( number_input. value . unwrap ( ) ) ) . into ( ) )
124+ . widget_holder ( ) ;
125+ let character_spacing = NumberInput :: new ( Some ( tool. options . character_spacing ) )
126+ . label ( "Character Spacing" )
127+ . int ( )
128+ . min ( 0. )
129+ . max ( ( 1_u64 << f64:: MANTISSA_DIGITS ) as f64 )
130+ . step ( 0.1 )
131+ . on_update ( |number_input : & NumberInput | TextToolMessage :: UpdateOptions ( TextOptionsUpdate :: CharacterSpacing ( number_input. value . unwrap ( ) ) ) . into ( ) )
110132 . widget_holder ( ) ;
111133 vec ! [
112134 font,
113135 Separator :: new( SeparatorType :: Related ) . widget_holder( ) ,
114136 style,
115137 Separator :: new( SeparatorType :: Related ) . widget_holder( ) ,
116138 size,
139+ Separator :: new( SeparatorType :: Related ) . widget_holder( ) ,
140+ line_height_ratio,
141+ Separator :: new( SeparatorType :: Related ) . widget_holder( ) ,
142+ character_spacing,
117143 ]
118144}
119145
@@ -149,6 +175,8 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for TextToo
149175 self . send_layout ( responses, LayoutTarget :: ToolOptions ) ;
150176 }
151177 TextOptionsUpdate :: FontSize ( font_size) => self . options . font_size = font_size,
178+ TextOptionsUpdate :: LineHeightRatio ( line_height_ratio) => self . options . line_height_ratio = line_height_ratio,
179+ TextOptionsUpdate :: CharacterSpacing ( character_spacing) => self . options . character_spacing = character_spacing,
152180 TextOptionsUpdate :: FillColor ( color) => {
153181 self . options . fill . custom_color = color;
154182 self . options . fill . color_type = ToolColorType :: Custom ;
@@ -200,6 +228,8 @@ pub struct EditingText {
200228 text : String ,
201229 font : Font ,
202230 font_size : f64 ,
231+ line_height_ratio : f64 ,
232+ character_spacing : f64 ,
203233 color : Option < Color > ,
204234 transform : DAffine2 ,
205235}
@@ -233,11 +263,13 @@ impl TextToolData {
233263 fn load_layer_text_node ( & mut self , document : & DocumentMessageHandler ) -> Option < ( ) > {
234264 let transform = document. metadata ( ) . transform_to_viewport ( self . layer ) ;
235265 let color = graph_modification_utils:: get_fill_color ( self . layer , & document. network_interface ) . unwrap_or ( Color :: BLACK ) ;
236- let ( text, font, font_size) = graph_modification_utils:: get_text ( self . layer , & document. network_interface ) ?;
266+ let ( text, font, font_size, line_height_ratio , character_spacing ) = graph_modification_utils:: get_text ( self . layer , & document. network_interface ) ?;
237267 self . editing_text = Some ( EditingText {
238268 text : text. clone ( ) ,
239269 font : font. clone ( ) ,
240270 font_size,
271+ line_height_ratio,
272+ character_spacing,
241273 color : Some ( color) ,
242274 transform,
243275 } ) ;
@@ -295,6 +327,8 @@ impl TextToolData {
295327 text : String :: new ( ) ,
296328 font : editing_text. font . clone ( ) ,
297329 size : editing_text. font_size ,
330+ line_height_ratio : editing_text. line_height_ratio ,
331+ character_spacing : editing_text. character_spacing ,
298332 parent : document. new_layer_parent ( true ) ,
299333 insert_index : 0 ,
300334 } ) ;
@@ -364,7 +398,14 @@ impl Fsm for TextToolFsmState {
364398 } ) ;
365399 if let Some ( editing_text) = tool_data. editing_text . as_ref ( ) {
366400 let buzz_face = font_cache. get ( & editing_text. font ) . map ( |data| load_face ( data) ) ;
367- let far = graphene_core:: text:: bounding_box ( & tool_data. new_text , buzz_face, editing_text. font_size , None ) ;
401+ let far = graphene_core:: text:: bounding_box (
402+ & tool_data. new_text ,
403+ buzz_face,
404+ editing_text. font_size ,
405+ editing_text. line_height_ratio ,
406+ editing_text. character_spacing ,
407+ None ,
408+ ) ;
368409 if far. x != 0. && far. y != 0. {
369410 let quad = Quad :: from_box ( [ DVec2 :: ZERO , far] ) ;
370411 let transformed_quad = document. metadata ( ) . transform_to_viewport ( tool_data. layer ) * quad;
@@ -376,11 +417,11 @@ impl Fsm for TextToolFsmState {
376417 }
377418 ( _, TextToolMessage :: Overlays ( mut overlay_context) ) => {
378419 for layer in document. network_interface . selected_nodes ( & [ ] ) . unwrap ( ) . selected_layers ( document. metadata ( ) ) {
379- let Some ( ( text, font, font_size) ) = graph_modification_utils:: get_text ( layer, & document. network_interface ) else {
420+ let Some ( ( text, font, font_size, line_height_ratio , character_spacing ) ) = graph_modification_utils:: get_text ( layer, & document. network_interface ) else {
380421 continue ;
381422 } ;
382423 let buzz_face = font_cache. get ( font) . map ( |data| load_face ( data) ) ;
383- let far = graphene_core:: text:: bounding_box ( text, buzz_face, font_size, None ) ;
424+ let far = graphene_core:: text:: bounding_box ( text, buzz_face, font_size, line_height_ratio , character_spacing , None ) ;
384425 let quad = Quad :: from_box ( [ DVec2 :: ZERO , far] ) ;
385426 let multiplied = document. metadata ( ) . transform_to_viewport ( layer) * quad;
386427 overlay_context. quad ( multiplied, None ) ;
@@ -392,7 +433,9 @@ impl Fsm for TextToolFsmState {
392433 tool_data. editing_text = Some ( EditingText {
393434 text : String :: new ( ) ,
394435 transform : DAffine2 :: from_translation ( input. mouse . position ) ,
395- font_size : tool_options. font_size as f64 ,
436+ font_size : tool_options. font_size ,
437+ line_height_ratio : tool_options. line_height_ratio ,
438+ character_spacing : tool_options. character_spacing ,
396439 font : Font :: new ( tool_options. font_name . clone ( ) , tool_options. font_style . clone ( ) ) ,
397440 color : tool_options. fill . active_color ( ) ,
398441 } ) ;
0 commit comments