@@ -363,10 +363,12 @@ impl Engine {
363363 }
364364
365365 /// Insert an SVG image as a VectorImage stroke.
366+ /// If `typst_source` is provided, it will be stored with the image for later editing.
366367 pub fn insert_svg_image (
367368 & mut self ,
368369 svg_data : String ,
369370 pos : na:: Vector2 < f64 > ,
371+ typst_source : Option < String > ,
370372 ) -> WidgetFlags {
371373 let mut widget_flags = WidgetFlags :: default ( ) ;
372374
@@ -376,7 +378,10 @@ impl Engine {
376378
377379 // Create VectorImage from SVG
378380 match VectorImage :: from_svg_str ( & svg_data, pos, ImageSizeOption :: RespectOriginalSize ) {
379- Ok ( vectorimage) => {
381+ Ok ( mut vectorimage) => {
382+ // Store the Typst source if provided
383+ vectorimage. typst_source = typst_source;
384+
380385 let stroke = Stroke :: VectorImage ( vectorimage) ;
381386 let stroke_key = self . store . insert_stroke ( stroke, None ) ;
382387
@@ -399,6 +404,81 @@ impl Engine {
399404 widget_flags
400405 }
401406
407+ /// Update an existing Typst stroke with new SVG data and source code.
408+ pub fn update_typst_stroke (
409+ & mut self ,
410+ stroke_key : StrokeKey ,
411+ svg_data : String ,
412+ typst_source : String ,
413+ ) -> WidgetFlags {
414+ let mut widget_flags = WidgetFlags :: default ( ) ;
415+
416+ if let Some ( Stroke :: VectorImage ( vectorimage) ) = self . store . get_stroke_mut ( stroke_key) {
417+ // Store the old intrinsic size, cuboid size, and transform
418+ let old_cuboid_size = vectorimage. rectangle . cuboid . half_extents * 2.0 ;
419+ let old_transform = vectorimage. rectangle . transform . clone ( ) ;
420+
421+ // Create new VectorImage to get the new intrinsic size
422+ match VectorImage :: from_svg_str (
423+ & svg_data,
424+ na:: Vector2 :: zeros ( ) ,
425+ ImageSizeOption :: RespectOriginalSize ,
426+ ) {
427+ Ok ( mut new_vectorimage) => {
428+ let new_intrinsic_size = new_vectorimage. intrinsic_size ;
429+
430+ // Calculate width scale factor based on old cuboid width vs new intrinsic width
431+ let width_scale_factor = if new_intrinsic_size[ 0 ] > 0.0 {
432+ old_cuboid_size[ 0 ] / new_intrinsic_size[ 0 ]
433+ } else {
434+ 1.0
435+ } ;
436+
437+ // Apply the scale factor to both dimensions to maintain aspect ratio
438+ let new_cuboid_size = na:: vector![
439+ new_intrinsic_size[ 0 ] * width_scale_factor,
440+ new_intrinsic_size[ 1 ] * width_scale_factor
441+ ] ;
442+
443+ // Calculate height difference to adjust position
444+ let height_diff = new_cuboid_size[ 1 ] - old_cuboid_size[ 1 ] ;
445+
446+ // Set the new cuboid size
447+ new_vectorimage. rectangle . cuboid = p2d:: shape:: Cuboid :: new ( new_cuboid_size * 0.5 ) ;
448+
449+ // Restore the original transform and adjust for height change
450+ new_vectorimage. rectangle . transform = old_transform;
451+ // Adjust y position to make it look like text was written further
452+ new_vectorimage. rectangle . transform . append_translation_mut ( na:: vector![ 0.0 , height_diff * 0.5 ] ) ;
453+
454+ // Store the Typst source
455+ new_vectorimage. typst_source = Some ( typst_source) ;
456+
457+ // Update the stroke
458+ * vectorimage = new_vectorimage;
459+
460+ self . store . regenerate_rendering_for_stroke (
461+ stroke_key,
462+ self . camera . viewport ( ) ,
463+ self . camera . image_scale ( ) ,
464+ ) ;
465+
466+ widget_flags |= self . store . record ( Instant :: now ( ) ) ;
467+ widget_flags. resize = true ;
468+ widget_flags. redraw = true ;
469+ widget_flags. store_modified = true ;
470+ }
471+ Err ( e) => {
472+ error ! ( "Failed to update Typst stroke: {e:?}" ) ;
473+ }
474+ }
475+ } else {
476+ error ! ( "Failed to update Typst stroke: stroke not found or not a VectorImage" ) ;
477+ }
478+
479+ widget_flags
480+ }
481+
402482 /// Insert the stroke content.
403483 ///
404484 /// The data usually comes from the clipboard, drag-and-drop, ..
0 commit comments