@@ -15,6 +15,7 @@ use graphene_std::math::quad::Quad;
1515use graphene_std:: subpath:: Subpath ;
1616use graphene_std:: vector:: click_target:: ClickTargetType ;
1717use graphene_std:: vector:: misc:: { dvec2_to_point, point_to_dvec2} ;
18+ use graphene_std:: vector:: style:: Stroke ;
1819use graphene_std:: vector:: { PointId , SegmentId , Vector } ;
1920use kurbo:: { self , Affine , CubicBez , ParamCurve , PathSeg } ;
2021use std:: collections:: HashMap ;
@@ -30,57 +31,72 @@ pub fn empty_provider() -> OverlayProvider {
3031/// Types of overlays used by DocumentMessage to enable/disable the selected set of viewport overlays.
3132#[ derive( PartialEq , Clone , Debug , serde:: Serialize , serde:: Deserialize , specta:: Type ) ]
3233pub enum OverlaysType {
34+ // =======
35+ // General
36+ // =======
3337 ArtboardName ,
34- CompassRose ,
35- QuickMeasurement ,
3638 TransformMeasurement ,
39+ // ===========
40+ // Select Tool
41+ // ===========
42+ QuickMeasurement ,
3743 TransformCage ,
44+ CompassRose ,
45+ Pivot ,
46+ Origin ,
3847 HoverOutline ,
3948 SelectionOutline ,
4049 LayerOriginCross ,
41- Pivot ,
42- Origin ,
50+ // ================
51+ // Pen & Path Tools
52+ // ================
4353 Path ,
4454 Anchors ,
4555 Handles ,
56+ // =========
57+ // Fill Tool
58+ // =========
59+ FillableIndicator ,
4660}
4761
4862#[ derive( PartialEq , Copy , Clone , Debug , serde:: Serialize , serde:: Deserialize , specta:: Type ) ]
49- #[ serde( default ) ]
63+ #[ serde( default = "OverlaysVisibilitySettings::default" ) ]
5064pub struct OverlaysVisibilitySettings {
5165 pub all : bool ,
5266 pub artboard_name : bool ,
53- pub compass_rose : bool ,
54- pub quick_measurement : bool ,
5567 pub transform_measurement : bool ,
68+ pub quick_measurement : bool ,
5669 pub transform_cage : bool ,
70+ pub compass_rose : bool ,
71+ pub pivot : bool ,
72+ pub origin : bool ,
5773 pub hover_outline : bool ,
5874 pub selection_outline : bool ,
5975 pub layer_origin_cross : bool ,
60- pub pivot : bool ,
61- pub origin : bool ,
6276 pub path : bool ,
6377 pub anchors : bool ,
6478 pub handles : bool ,
79+ pub fillable_indicator : bool ,
6580}
6681
6782impl Default for OverlaysVisibilitySettings {
6883 fn default ( ) -> Self {
6984 Self {
7085 all : true ,
7186 artboard_name : true ,
72- compass_rose : true ,
73- quick_measurement : true ,
7487 transform_measurement : true ,
88+ quick_measurement : true ,
7589 transform_cage : true ,
90+ compass_rose : true ,
91+ pivot : true ,
92+ origin : true ,
7693 hover_outline : true ,
7794 selection_outline : true ,
7895 layer_origin_cross : true ,
79- pivot : true ,
80- origin : true ,
8196 path : true ,
8297 anchors : true ,
8398 handles : true ,
99+ fillable_indicator : true ,
84100 }
85101 }
86102}
@@ -141,6 +157,10 @@ impl OverlaysVisibilitySettings {
141157 pub fn handles ( & self ) -> bool {
142158 self . all && self . anchors && self . handles
143159 }
160+
161+ pub fn fillable_indicator ( & self ) -> bool {
162+ self . all && self . fillable_indicator
163+ }
144164}
145165
146166#[ derive( PartialEq , Clone , Debug , serde:: Serialize , serde:: Deserialize , specta:: Type ) ]
@@ -805,8 +825,7 @@ impl OverlayContext {
805825 self . text ( & text, COLOR_OVERLAY_BLUE , None , transform, 16. , [ Pivot :: Middle , Pivot :: Middle ] ) ;
806826 }
807827
808- /// Used by the Pen and Path tools to outline the path of the shape.
809- pub fn outline_vector ( & mut self , vector : & Vector , transform : DAffine2 ) {
828+ pub fn draw_path_from_vector_data ( & mut self , vector : & Vector , transform : DAffine2 ) {
810829 self . start_dpi_aware_transform ( ) ;
811830
812831 self . render_context . begin_path ( ) ;
@@ -818,6 +837,12 @@ impl OverlayContext {
818837 self . bezier_command ( bezier, transform, move_to) ;
819838 }
820839
840+ self . end_dpi_aware_transform ( ) ;
841+ }
842+
843+ /// Used by the Pen and Path tools to outline the path of the shape.
844+ pub fn outline_vector ( & mut self , vector : & Vector , transform : DAffine2 ) {
845+ self . draw_path_from_vector_data ( vector, transform) ;
821846 self . render_context . set_stroke_style_str ( COLOR_OVERLAY_BLUE ) ;
822847 self . render_context . stroke ( ) ;
823848
@@ -882,7 +907,7 @@ impl OverlayContext {
882907 self . end_dpi_aware_transform ( ) ;
883908 }
884909
885- fn push_path ( & mut self , subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > , transform : DAffine2 ) {
910+ pub fn draw_path_from_subpaths ( & mut self , subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > , transform : DAffine2 ) {
886911 self . start_dpi_aware_transform ( ) ;
887912
888913 self . render_context . begin_path ( ) ;
@@ -943,7 +968,7 @@ impl OverlayContext {
943968 } ) ;
944969
945970 if !subpaths. is_empty ( ) {
946- self . push_path ( subpaths. iter ( ) , transform) ;
971+ self . draw_path_from_subpaths ( subpaths. iter ( ) , transform) ;
947972
948973 let color = color. unwrap_or ( COLOR_OVERLAY_BLUE ) ;
949974 self . render_context . set_stroke_style_str ( color) ;
@@ -952,18 +977,8 @@ impl OverlayContext {
952977 }
953978 }
954979
955- /// Fills the area inside the path. Assumes `color` is in gamma space.
956- /// Used by the Pen tool to show the path being closed.
957- pub fn fill_path ( & mut self , subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > , transform : DAffine2 , color : & str ) {
958- self . push_path ( subpaths, transform) ;
959-
960- self . render_context . set_fill_style_str ( color) ;
961- self . render_context . fill ( ) ;
962- }
963-
964- /// Fills the area inside the path with a pattern. Assumes `color` is in gamma space.
965- /// Used by the fill tool to show the area to be filled.
966- pub fn fill_path_pattern ( & mut self , subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > , transform : DAffine2 , color : & Color ) {
980+ /// Default canvas pattern used for filling stroke or fill of a path.
981+ fn fill_canvas_pattern ( & self , color : & Color ) -> web_sys:: CanvasPattern {
967982 const PATTERN_WIDTH : usize = 4 ;
968983 const PATTERN_HEIGHT : usize = 4 ;
969984
@@ -992,12 +1007,61 @@ impl OverlayContext {
9921007
9931008 let image_data = web_sys:: ImageData :: new_with_u8_clamped_array_and_sh ( wasm_bindgen:: Clamped ( & data) , PATTERN_WIDTH as u32 , PATTERN_HEIGHT as u32 ) . unwrap ( ) ;
9941009 pattern_context. put_image_data ( & image_data, 0. , 0. ) . unwrap ( ) ;
995- let pattern = self . render_context . create_pattern_with_offscreen_canvas ( & pattern_canvas, "repeat" ) . unwrap ( ) . unwrap ( ) ;
996-
997- self . push_path ( subpaths, transform) ;
1010+ return self . render_context . create_pattern_with_offscreen_canvas ( & pattern_canvas, "repeat" ) . unwrap ( ) . unwrap ( ) ;
1011+ }
9981012
999- self . render_context . set_fill_style_canvas_pattern ( & pattern) ;
1013+ /// Fills the area inside the path (with an optional pattern). Assumes `color` is in gamma space.
1014+ /// Used by the Pen tool to show the path being closed and by the Fill tool to show the area to be filled with a pattern.
1015+ pub fn fill_path (
1016+ & mut self ,
1017+ subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > ,
1018+ transform : DAffine2 ,
1019+ color : & Color ,
1020+ with_pattern : bool ,
1021+ clear_stroke_part : bool ,
1022+ stroke_width : Option < f64 > ,
1023+ ) {
1024+ self . render_context . save ( ) ;
1025+ self . render_context . set_line_width ( stroke_width. unwrap_or ( 1. ) ) ;
1026+ self . draw_path_from_subpaths ( subpaths, transform) ;
1027+
1028+ if with_pattern {
1029+ self . render_context . set_fill_style_canvas_pattern ( & self . fill_canvas_pattern ( color) ) ;
1030+ } else {
1031+ let color_str = format ! ( "#{:?}" , color. to_rgba_hex_srgb( ) ) ;
1032+ self . render_context . set_fill_style_str ( & color_str. as_str ( ) ) ;
1033+ }
10001034 self . render_context . fill ( ) ;
1035+
1036+ // Make the stroke transparent and erase the fill area overlapping the stroke.
1037+ if clear_stroke_part {
1038+ self . render_context . set_global_composite_operation ( "destination-out" ) . expect ( "Failed to set global composite operation" ) ;
1039+ self . render_context . set_stroke_style_str ( & "#000000" ) ;
1040+ self . render_context . stroke ( ) ;
1041+ }
1042+
1043+ self . render_context . restore ( ) ;
1044+ }
1045+
1046+ pub fn fill_stroke ( & mut self , subpaths : impl Iterator < Item = impl Borrow < Subpath < PointId > > > , overlay_stroke : & Stroke ) {
1047+ self . render_context . save ( ) ;
1048+
1049+ // debug!("overlay_stroke.weight * ptz.zoom(): {:?}", overlay_stroke.weight);
1050+ self . render_context . set_line_width ( overlay_stroke. weight ) ;
1051+ self . draw_path_from_subpaths ( subpaths, overlay_stroke. transform ) ;
1052+
1053+ self . render_context
1054+ . set_stroke_style_canvas_pattern ( & self . fill_canvas_pattern ( & overlay_stroke. color . expect ( "Color should be set for fill_stroke()" ) ) ) ;
1055+ self . render_context . set_line_cap ( overlay_stroke. cap . html_canvas_name ( ) . as_str ( ) ) ;
1056+ self . render_context . set_line_join ( overlay_stroke. join . html_canvas_name ( ) . as_str ( ) ) ;
1057+ self . render_context . set_miter_limit ( overlay_stroke. join_miter_limit ) ;
1058+ self . render_context . stroke ( ) ;
1059+
1060+ self . render_context . restore ( ) ;
1061+ }
1062+
1063+ pub fn get_width ( & self , text : & str ) -> f64 {
1064+ self . render_context . measure_text ( text) . expect ( "Failed to measure text dimensions" ) . width ( )
10011065 }
10021066
10031067 pub fn text ( & self , text : & str , font_color : & str , background_color : Option < & str > , transform : DAffine2 , padding : f64 , pivot : [ Pivot ; 2 ] ) {
0 commit comments