11mod quad;
22mod rect;
3+ use dyn_any:: DynAny ;
34pub use quad:: Quad ;
45pub use rect:: Rect ;
56
@@ -269,15 +270,24 @@ pub fn to_transform(transform: DAffine2) -> usvg::Transform {
269270 usvg:: Transform :: from_row ( cols[ 0 ] as f32 , cols[ 1 ] as f32 , cols[ 2 ] as f32 , cols[ 3 ] as f32 , cols[ 4 ] as f32 , cols[ 5 ] as f32 )
270271}
271272
273+ use dyn_any:: StaticType ;
274+ #[ derive( Debug , Clone , PartialEq , DynAny ) ]
275+ #[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
276+ pub struct RenderMetadata {
277+ pub footprints : HashMap < NodeId , ( Footprint , DAffine2 ) > ,
278+ pub click_targets : HashMap < NodeId , Vec < ClickTarget > > ,
279+ pub vector_data : HashMap < NodeId , VectorData > ,
280+ }
281+
272282pub trait GraphicElementRendered {
273283 fn render_svg ( & self , render : & mut SvgRender , render_params : & RenderParams ) ;
274284 fn bounding_box ( & self , transform : DAffine2 ) -> Option < [ DVec2 ; 2 ] > ;
275- fn add_click_targets ( & self , _click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , _element_id : Option < NodeId > ) { }
285+ // The upstream click targets for each layer are collected during the render so that they do not have to be calculated for each click detection
276286 fn add_upstream_click_targets ( & self , _click_targets : & mut Vec < ClickTarget > ) { }
277287 // TODO: Store all click targets in a vec which contains the AABB, click target, and path
278288 // fn add_click_targets(&self, click_targets: &mut Vec<([DVec2; 2], ClickTarget, Vec<NodeId>)>, current_path: Option<NodeId>) {}
279- fn add_vector_modify ( & self , _vector_modify : & mut HashMap < NodeId , VectorData > , _element_id : Option < NodeId > ) { }
280- fn add_footprints ( & self , _footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , _footprint : Footprint , _element_id : Option < NodeId > ) { }
289+ // Recursively iterate over data in the render (including groups upstream from vector data in the case of a boolean operation) to collect the footprints, click targets, and vector modify
290+ fn collect_metadata ( & self , _metadata : & mut RenderMetadata , _footprint : Footprint , _element_id : Option < NodeId > ) { }
281291 #[ cfg( feature = "vello" ) ]
282292 fn to_vello_scene ( & self , transform : DAffine2 , context : & mut RenderContext ) -> Scene {
283293 let mut scene = vello:: Scene :: new ( ) ;
@@ -322,18 +332,17 @@ impl GraphicElementRendered for GraphicGroup {
322332 self . iter ( ) . filter_map ( |( element, _) | element. bounding_box ( transform * self . transform ) ) . reduce ( Quad :: combine_bounds)
323333 }
324334
325- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
335+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , mut footprint : Footprint , element_id : Option < NodeId > ) {
336+ footprint. transform *= self . transform ;
326337 for ( element, element_id) in self . elements . iter ( ) {
327338 if let Some ( element_id) = element_id {
328- let mut new_click_targets = HashMap :: new ( ) ;
329- element. add_click_targets ( & mut new_click_targets, Some ( * element_id) ) ;
330- click_targets. extend ( new_click_targets) ;
339+ element. collect_metadata ( metadata, footprint, Some ( * element_id) ) ;
331340 }
332341 }
333342 if let Some ( graphic_group_id) = element_id {
334343 let mut all_upstream_click_targets = Vec :: new ( ) ;
335344 self . add_upstream_click_targets ( & mut all_upstream_click_targets) ;
336- click_targets. insert ( graphic_group_id, all_upstream_click_targets) ;
345+ metadata . click_targets . insert ( graphic_group_id, all_upstream_click_targets) ;
337346 }
338347 }
339348
@@ -348,23 +357,6 @@ impl GraphicElementRendered for GraphicGroup {
348357 }
349358 }
350359
351- fn add_vector_modify ( & self , vector_modify : & mut HashMap < NodeId , VectorData > , _element_id : Option < NodeId > ) {
352- for ( element, element_id) in self . elements . iter ( ) {
353- element. add_vector_modify ( vector_modify, * element_id) ;
354- }
355- }
356-
357- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , mut footprint : Footprint , _: Option < NodeId > ) {
358- footprint. transform *= self . transform ;
359- for ( element, optional_node_id) in self . elements . iter ( ) {
360- if let Some ( element_id) = optional_node_id {
361- let mut new_footprints = HashMap :: new ( ) ;
362- element. add_footprints ( & mut new_footprints, footprint, Some ( * element_id) ) ;
363- footprints. extend ( new_footprints) ;
364- }
365- }
366- }
367-
368360 #[ cfg( feature = "vello" ) ]
369361 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext ) {
370362 let child_transform = transform * self . transform ;
@@ -433,7 +425,7 @@ impl GraphicElementRendered for VectorData {
433425 self . bounding_box_with_transform ( transform * self . transform ) . map ( |[ a, b] | [ a - offset, b + offset] )
434426 }
435427
436- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
428+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , mut footprint : Footprint , element_id : Option < NodeId > ) {
437429 if let Some ( element_id) = element_id {
438430 let stroke_width = self . style . stroke ( ) . as_ref ( ) . map_or ( 0. , Stroke :: weight) ;
439431 let filled = self . style . fill ( ) != & Fill :: None ;
@@ -443,10 +435,14 @@ impl GraphicElementRendered for VectorData {
443435 }
444436 subpath
445437 } ;
446- click_targets. insert ( element_id, self . stroke_bezier_paths ( ) . map ( fill) . map ( |subpath| ClickTarget :: new ( subpath, stroke_width) ) . collect ( ) ) ;
438+ metadata
439+ . click_targets
440+ . insert ( element_id, self . stroke_bezier_paths ( ) . map ( fill) . map ( |subpath| ClickTarget :: new ( subpath, stroke_width) ) . collect ( ) ) ;
441+ metadata. vector_data . insert ( element_id, self . clone ( ) ) ;
447442 }
448443 if let Some ( upstream_graphic_group) = & self . upstream_graphic_group {
449- upstream_graphic_group. add_click_targets ( click_targets, None ) ;
444+ footprint. transform *= self . transform ;
445+ upstream_graphic_group. collect_metadata ( metadata, footprint, None ) ;
450446 }
451447 }
452448
@@ -462,22 +458,6 @@ impl GraphicElementRendered for VectorData {
462458 click_targets. extend ( self . stroke_bezier_paths ( ) . map ( fill) . map ( |subpath| ClickTarget :: new ( subpath, stroke_width) ) ) ;
463459 }
464460
465- fn add_vector_modify ( & self , vector_modify : & mut HashMap < NodeId , VectorData > , element_id : Option < NodeId > ) {
466- if let Some ( element_id) = element_id {
467- vector_modify. insert ( element_id, self . clone ( ) ) ;
468- }
469- if let Some ( upstream_graphic_group) = & self . upstream_graphic_group {
470- upstream_graphic_group. add_vector_modify ( vector_modify, None ) ;
471- }
472- }
473-
474- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , mut footprint : Footprint , _element_id : Option < NodeId > ) {
475- if let Some ( upstream_graphic_group) = & self . upstream_graphic_group {
476- footprint. transform *= self . transform ;
477- upstream_graphic_group. add_footprints ( footprints, footprint, None ) ;
478- }
479- }
480-
481461 #[ cfg( feature = "vello" ) ]
482462 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , _: & mut RenderContext ) {
483463 use crate :: vector:: style:: GradientType ;
@@ -651,12 +631,13 @@ impl GraphicElementRendered for Artboard {
651631 }
652632 }
653633
654- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
634+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , footprint : Footprint , element_id : Option < NodeId > ) {
655635 if let Some ( element_id) = element_id {
656636 let subpath = Subpath :: new_rect ( DVec2 :: ZERO , self . dimensions . as_dvec2 ( ) ) ;
657- click_targets. insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
637+ metadata. click_targets . insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
638+ metadata. footprints . insert ( element_id, ( footprint, DAffine2 :: from_translation ( self . location . as_dvec2 ( ) ) ) ) ;
658639 }
659- self . graphic_group . add_click_targets ( click_targets , None ) ;
640+ self . graphic_group . collect_metadata ( metadata , footprint , None ) ;
660641 }
661642
662643 fn add_upstream_click_targets ( & self , click_targets : & mut Vec < ClickTarget > ) {
@@ -665,17 +646,6 @@ impl GraphicElementRendered for Artboard {
665646 click_targets. push ( ClickTarget :: new ( subpath, 0. ) ) ;
666647 }
667648
668- fn add_vector_modify ( & self , vector_modify : & mut HashMap < NodeId , VectorData > , _element_id : Option < NodeId > ) {
669- self . graphic_group . add_vector_modify ( vector_modify, None ) ;
670- }
671-
672- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , footprint : Footprint , element_id : Option < NodeId > ) {
673- if let Some ( element_id) = element_id {
674- footprints. insert ( element_id, ( footprint, DAffine2 :: from_translation ( self . location . as_dvec2 ( ) ) ) ) ;
675- }
676- self . graphic_group . add_footprints ( footprints, footprint, None ) ;
677- }
678-
679649 #[ cfg( feature = "vello" ) ]
680650 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext ) {
681651 use vello:: peniko;
@@ -713,9 +683,9 @@ impl GraphicElementRendered for crate::ArtboardGroup {
713683 self . artboards . iter ( ) . filter_map ( |( element, _) | element. bounding_box ( transform) ) . reduce ( Quad :: combine_bounds)
714684 }
715685
716- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , _element_id : Option < NodeId > ) {
686+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , footprint : Footprint , _element_id : Option < NodeId > ) {
717687 for ( artboard, element_id) in & self . artboards {
718- artboard. add_click_targets ( click_targets , * element_id) ;
688+ artboard. collect_metadata ( metadata , footprint , * element_id) ;
719689 }
720690 }
721691
@@ -725,18 +695,6 @@ impl GraphicElementRendered for crate::ArtboardGroup {
725695 }
726696 }
727697
728- fn add_vector_modify ( & self , vector_modify : & mut HashMap < NodeId , VectorData > , _element_id : Option < NodeId > ) {
729- for ( artboard, _) in & self . artboards {
730- artboard. add_vector_modify ( vector_modify, None ) ;
731- }
732- }
733-
734- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , footprint : Footprint , _element_id : Option < NodeId > ) {
735- for ( artboard, element_id) in & self . artboards {
736- artboard. add_footprints ( footprints, footprint, * element_id) ;
737- }
738- }
739-
740698 #[ cfg( feature = "vello" ) ]
741699 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext ) {
742700 for ( artboard, _) in & self . artboards {
@@ -790,10 +748,11 @@ impl GraphicElementRendered for ImageFrame<Color> {
790748 ( transform. matrix2 != glam:: DMat2 :: ZERO ) . then ( || ( transform * Quad :: from_box ( [ DVec2 :: ZERO , DVec2 :: ONE ] ) ) . bounding_box ( ) )
791749 }
792750
793- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
751+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , footprint : Footprint , element_id : Option < NodeId > ) {
794752 if let Some ( element_id) = element_id {
795753 let subpath = Subpath :: new_rect ( DVec2 :: ZERO , DVec2 :: ONE ) ;
796- click_targets. insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
754+ metadata. click_targets . insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
755+ metadata. footprints . insert ( element_id, ( footprint, self . transform ) ) ;
797756 }
798757 }
799758
@@ -802,12 +761,6 @@ impl GraphicElementRendered for ImageFrame<Color> {
802761 click_targets. push ( ClickTarget :: new ( subpath, 0. ) ) ;
803762 }
804763
805- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , footprint : Footprint , element_id : Option < NodeId > ) {
806- if let Some ( element_id) = element_id {
807- footprints. insert ( element_id, ( footprint, self . transform ) ) ;
808- }
809- }
810-
811764 #[ cfg( feature = "vello" ) ]
812765 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , _: & mut RenderContext ) {
813766 use vello:: peniko;
@@ -873,10 +826,11 @@ impl GraphicElementRendered for Raster {
873826 ( transform. matrix2 != glam:: DMat2 :: ZERO ) . then ( || ( transform * Quad :: from_box ( [ DVec2 :: ZERO , DVec2 :: ONE ] ) ) . bounding_box ( ) )
874827 }
875828
876- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
829+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , footprint : Footprint , element_id : Option < NodeId > ) {
877830 if let Some ( element_id) = element_id {
878831 let subpath = Subpath :: new_rect ( DVec2 :: ZERO , DVec2 :: ONE ) ;
879- click_targets. insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
832+ metadata. click_targets . insert ( element_id, vec ! [ ClickTarget :: new( subpath, 0. ) ] ) ;
833+ metadata. footprints . insert ( element_id, ( footprint, self . transform ( ) ) ) ;
880834 }
881835 }
882836
@@ -885,12 +839,6 @@ impl GraphicElementRendered for Raster {
885839 click_targets. push ( ClickTarget :: new ( subpath, 0. ) ) ;
886840 }
887841
888- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , footprint : Footprint , element_id : Option < NodeId > ) {
889- if let Some ( element_id) = element_id {
890- footprints. insert ( element_id, ( footprint, self . transform ( ) ) ) ;
891- }
892- }
893-
894842 #[ cfg( feature = "vello" ) ]
895843 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext ) {
896844 use vello:: peniko;
@@ -948,11 +896,14 @@ impl GraphicElementRendered for GraphicElement {
948896 }
949897 }
950898
951- fn add_click_targets ( & self , click_targets : & mut HashMap < NodeId , Vec < ClickTarget > > , element_id : Option < NodeId > ) {
899+ fn collect_metadata ( & self , metadata : & mut RenderMetadata , footprint : Footprint , element_id : Option < NodeId > ) {
900+ if let Some ( element_id) = element_id {
901+ metadata. footprints . insert ( element_id, ( footprint, self . transform ( ) ) ) ;
902+ }
952903 match self {
953- GraphicElement :: VectorData ( vector_data) => vector_data. add_click_targets ( click_targets , element_id) ,
954- GraphicElement :: Raster ( raster) => raster. add_click_targets ( click_targets , element_id) ,
955- GraphicElement :: GraphicGroup ( graphic_group) => graphic_group. add_click_targets ( click_targets , element_id) ,
904+ GraphicElement :: VectorData ( vector_data) => vector_data. collect_metadata ( metadata , footprint , element_id) ,
905+ GraphicElement :: Raster ( raster) => raster. collect_metadata ( metadata , footprint , element_id) ,
906+ GraphicElement :: GraphicGroup ( graphic_group) => graphic_group. collect_metadata ( metadata , footprint , element_id) ,
956907 }
957908 }
958909
@@ -964,23 +915,6 @@ impl GraphicElementRendered for GraphicElement {
964915 }
965916 }
966917
967- fn add_vector_modify ( & self , vector_modify : & mut HashMap < NodeId , VectorData > , element_id : Option < NodeId > ) {
968- if let GraphicElement :: VectorData ( vector_data) = self {
969- vector_data. add_vector_modify ( vector_modify, element_id) ;
970- }
971- }
972-
973- fn add_footprints ( & self , footprints : & mut HashMap < NodeId , ( Footprint , DAffine2 ) > , footprint : Footprint , element_id : Option < NodeId > ) {
974- if let Some ( element_id) = element_id {
975- footprints. insert ( element_id, ( footprint, self . transform ( ) ) ) ;
976- }
977- match self {
978- GraphicElement :: VectorData ( vector_data) => vector_data. add_footprints ( footprints, footprint, None ) ,
979- GraphicElement :: Raster ( raster) => raster. add_footprints ( footprints, footprint, None ) ,
980- GraphicElement :: GraphicGroup ( graphic_group) => graphic_group. add_footprints ( footprints, footprint, None ) ,
981- }
982- }
983-
984918 #[ cfg( feature = "vello" ) ]
985919 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext ) {
986920 match self {
0 commit comments