@@ -12,11 +12,10 @@ use graph_craft::document::value::TaggedValue;
1212use graph_craft:: document:: { NodeId , NodeInput } ;
1313use graphene_std:: Color ;
1414use graphene_std:: renderer:: Quad ;
15- use graphene_std:: renderer:: convert_usvg_path:: convert_usvg_path;
15+ use graphene_std:: renderer:: convert_usvg_path:: { convert_tiny_skia_path , convert_usvg_path} ;
1616use graphene_std:: table:: Table ;
17- use graphene_std:: text:: { Font , TypesettingConfig } ;
17+ use graphene_std:: text:: { Font , TextAnchor , TypesettingConfig } ;
1818use graphene_std:: vector:: style:: { Fill , Gradient , GradientStop , GradientStops , GradientType , PaintOrder , Stroke , StrokeAlign , StrokeCap , StrokeJoin } ;
19-
2019#[ derive( ExtractField ) ]
2120pub struct GraphOperationMessageContext < ' a > {
2221 pub network_interface : & ' a mut NodeNetworkInterface ,
@@ -394,7 +393,14 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
394393 insert_index,
395394 center,
396395 } => {
397- let tree = match usvg:: Tree :: from_str ( & svg, & usvg:: Options :: default ( ) ) {
396+ let mut options = usvg:: Options :: default ( ) ;
397+ options. fontdb_mut ( ) . load_font_data ( include_bytes ! ( "../../../../font.ttf" ) . to_vec ( ) ) ;
398+ options. font_family = "Source Sans Pro" . to_string ( ) ;
399+
400+ let svg = svg. replace ( "font-family=\" sans-serif\" " , "font-family=\" Source Sans Pro\" " ) ;
401+ let svg = svg. replace ( "font-family='sans-serif'" , "font-family='Source Sans Pro'" ) ;
402+
403+ let tree = match usvg:: Tree :: from_str ( & svg, & options) {
398404 Ok ( t) => t,
399405 Err ( e) => {
400406 responses. add ( DialogMessage :: DisplayDialogError {
@@ -546,6 +552,7 @@ fn import_usvg_node(
546552 insert_index : usize ,
547553 graphite_gradient_stops : & HashMap < String , GradientStops > ,
548554) {
555+ log:: error!( "DIAGNOSTIC: Visiting node root: {:?}" , node) ;
549556 let layer = modify_inputs. create_layer ( id) ;
550557
551558 modify_inputs. network_interface . move_layer_to_stack ( layer, parent, insert_index, & [ ] ) ;
@@ -590,9 +597,7 @@ fn import_usvg_node(
590597 warn ! ( "Skip image" ) ;
591598 }
592599 usvg:: Node :: Text ( text) => {
593- let font = Font :: new ( graphene_std:: consts:: DEFAULT_FONT_FAMILY . to_string ( ) , graphene_std:: consts:: DEFAULT_FONT_STYLE . to_string ( ) ) ;
594- modify_inputs. insert_text ( text. chunks ( ) . iter ( ) . map ( |chunk| chunk. text ( ) ) . collect ( ) , font, TypesettingConfig :: default ( ) , layer) ;
595- modify_inputs. fill_set ( Fill :: Solid ( Color :: BLACK ) ) ;
600+ import_usvg_text ( modify_inputs, text, node. abs_transform ( ) , layer) ;
596601 }
597602 }
598603}
@@ -633,24 +638,21 @@ fn import_usvg_node_inner(
633638 group_extents_map. insert ( layer, child_extents) ;
634639 total_extent
635640 }
636- usvg:: Node :: Path ( path) => {
637- import_usvg_path ( modify_inputs, node, path, layer, graphite_gradient_stops) ;
638- 0
639- }
640641 usvg:: Node :: Image ( _image) => {
641642 warn ! ( "Skip image" ) ;
642643 0
643644 }
644645 usvg:: Node :: Text ( text) => {
645- let font = Font :: new ( graphene_std:: consts:: DEFAULT_FONT_FAMILY . to_string ( ) , graphene_std:: consts:: DEFAULT_FONT_STYLE . to_string ( ) ) ;
646- modify_inputs. insert_text ( text. chunks ( ) . iter ( ) . map ( |chunk| chunk. text ( ) ) . collect ( ) , font, TypesettingConfig :: default ( ) , layer) ;
647- modify_inputs. fill_set ( Fill :: Solid ( Color :: BLACK ) ) ;
646+ import_usvg_text ( modify_inputs, text, node. abs_transform ( ) , layer) ;
647+ 0
648+ }
649+ usvg:: Node :: Path ( path) => {
650+ import_usvg_path ( modify_inputs, node, path, layer, graphite_gradient_stops) ;
648651 0
649652 }
650653 }
651654}
652655
653- /// Helper to apply path data (vector geometry, fill, stroke, transform) to a layer.
654656fn import_usvg_path ( modify_inputs : & mut ModifyInputsContext , node : & usvg:: Node , path : & usvg:: Path , layer : LayerNodeIdentifier , graphite_gradient_stops : & HashMap < String , GradientStops > ) {
655657 let subpaths = convert_usvg_path ( path) ;
656658 let bounds = subpaths. iter ( ) . filter_map ( |subpath| subpath. bounding_box ( ) ) . reduce ( Quad :: combine_bounds) . unwrap_or_default ( ) ;
@@ -674,6 +676,53 @@ fn import_usvg_path(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node,
674676 }
675677}
676678
679+ fn import_usvg_text ( modify_inputs : & mut ModifyInputsContext , text : & usvg:: Text , transform : usvg:: Transform , layer : LayerNodeIdentifier ) {
680+ use graphene_std:: text:: TextAnchor ;
681+ let font_family = text
682+ . chunks ( )
683+ . first ( )
684+ . and_then ( |chunk| chunk. spans ( ) . first ( ) )
685+ . and_then ( |span| span. font ( ) . families ( ) . first ( ) . map ( |f| f. to_string ( ) ) )
686+ . unwrap_or_else ( || graphene_std:: consts:: DEFAULT_FONT_FAMILY . to_string ( ) ) ;
687+ let font_style = graphene_std:: consts:: DEFAULT_FONT_STYLE . to_string ( ) ;
688+ let font = Font :: new ( font_family, font_style) ;
689+
690+ let full_text: String = text. chunks ( ) . iter ( ) . map ( |chunk| chunk. text ( ) ) . collect ( ) ;
691+
692+ // Check if any chunk uses text-on-path (TextFlow::Path)
693+ let text_path_chunk = text. chunks ( ) . iter ( ) . find ( |chunk| matches ! ( chunk. text_flow( ) , usvg:: TextFlow :: Path ( _) ) ) ;
694+
695+ if let Some ( chunk) = text_path_chunk {
696+ if let usvg:: TextFlow :: Path ( text_path) = chunk. text_flow ( ) {
697+ let path_subpaths = convert_tiny_skia_path ( text_path. path ( ) ) ;
698+ let start_offset = text_path. start_offset ( ) as f64 ;
699+ let anchor = match chunk. anchor ( ) {
700+ usvg:: TextAnchor :: Start => TextAnchor :: Start ,
701+ usvg:: TextAnchor :: Middle => TextAnchor :: Middle ,
702+ usvg:: TextAnchor :: End => TextAnchor :: End ,
703+ } ;
704+ let font_size = chunk. spans ( ) . first ( ) . map ( |s| s. font_size ( ) . get ( ) ) . unwrap_or ( 24.0 ) as f64 ;
705+ let letter_spacing = chunk. spans ( ) . first ( ) . map ( |s| s. letter_spacing ( ) ) . unwrap_or ( 0.0 ) as f64 ;
706+
707+ let affine = DAffine2 :: from_cols_array ( & [
708+ transform. sx as f64 ,
709+ transform. ky as f64 ,
710+ transform. kx as f64 ,
711+ transform. sy as f64 ,
712+ transform. tx as f64 ,
713+ transform. ty as f64 ,
714+ ] ) ;
715+ modify_inputs. insert_text_on_path ( full_text, font, font_size, letter_spacing, path_subpaths, start_offset, anchor, affine, layer) ;
716+ modify_inputs. fill_set ( Fill :: Solid ( Color :: BLACK ) ) ;
717+ return ;
718+ }
719+ }
720+
721+ // Fallback: regular text
722+ modify_inputs. insert_text ( full_text, font, TypesettingConfig :: default ( ) , layer) ;
723+ modify_inputs. fill_set ( Fill :: Solid ( Color :: BLACK ) ) ;
724+ }
725+
677726/// Set correct positions for all imported layers in a single top-down O(n) pass.
678727///
679728/// For each group's child stack:
0 commit comments