@@ -18,8 +18,7 @@ use graphic_types::vector_types::subpath::Subpath;
1818use graphic_types:: vector_types:: vector:: click_target:: { ClickTarget , FreePoint } ;
1919use graphic_types:: vector_types:: vector:: style:: { Fill , PaintOrder , RenderMode , Stroke , StrokeAlign } ;
2020use graphic_types:: { Artboard , Graphic } ;
21- use kurbo:: Affine ;
22- use kurbo:: Shape ;
21+ use kurbo:: { Affine , Cap , Join , Shape } ;
2322use num_traits:: Zero ;
2423use std:: collections:: { HashMap , HashSet } ;
2524use std:: fmt:: Write ;
@@ -262,6 +261,36 @@ pub fn to_transform(transform: DAffine2) -> usvg::Transform {
262261 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 )
263262}
264263
264+ fn get_outline_styles ( render_params : & RenderParams ) -> ( kurbo:: Stroke , peniko:: Color ) {
265+ use core_types:: consts:: LAYER_OUTLINE_STROKE_WEIGHT ;
266+
267+ let outline_stroke = kurbo:: Stroke {
268+ width : LAYER_OUTLINE_STROKE_WEIGHT / if render_params. viewport_zoom > 0. { render_params. viewport_zoom } else { 1. } ,
269+ miter_limit : 4. ,
270+ join : Join :: Miter ,
271+ start_cap : Cap :: Butt ,
272+ end_cap : Cap :: Butt ,
273+ dash_pattern : Default :: default ( ) ,
274+ dash_offset : 0. ,
275+ } ;
276+
277+ let outline_color = black_or_white_for_best_contrast ( render_params. artboard_background ) ;
278+ let outline_color_peniko = peniko:: Color :: new ( [ outline_color. r ( ) , outline_color. g ( ) , outline_color. b ( ) , outline_color. a ( ) ] ) ;
279+
280+ ( outline_stroke, outline_color_peniko)
281+ }
282+
283+ fn draw_raster_outline ( scene : & mut Scene , outline_transform : & DAffine2 , render_params : & RenderParams ) {
284+ use graphic_types:: vector_types:: vector:: PointId ;
285+
286+ let ( outline_stroke, outline_color_peniko) = get_outline_styles ( render_params) ;
287+
288+ let mut outline_path = Subpath :: < PointId > :: new_rectangle ( DVec2 :: ZERO , DVec2 :: ONE ) . to_bezpath ( ) ;
289+ outline_path. apply_affine ( Affine :: new ( outline_transform. to_cols_array ( ) ) ) ;
290+
291+ scene. stroke ( & outline_stroke, Affine :: IDENTITY , outline_color_peniko, None , & outline_path) ;
292+ }
293+
265294// TODO: Click targets can be removed from the render output, since the vector data is available in the vector modify data from Monitor nodes.
266295// This will require that the transform for child layers into that layer space be calculated, or it could be returned from the RenderOutput instead of click targets.
267296#[ derive( Debug , Default , Clone , PartialEq , DynAny , serde:: Serialize , serde:: Deserialize ) ]
@@ -935,10 +964,7 @@ impl Render for Table<Vector> {
935964 }
936965
937966 fn render_to_vello ( & self , scene : & mut Scene , parent_transform : DAffine2 , _context : & mut RenderContext , render_params : & RenderParams ) {
938- use core_types:: consts:: LAYER_OUTLINE_STROKE_WEIGHT ;
939967 use graphic_types:: vector_types:: vector:: style:: { GradientType , StrokeCap , StrokeJoin } ;
940- use vello:: kurbo:: { Cap , Join } ;
941- use vello:: peniko;
942968
943969 for row in self . iter ( ) {
944970 use graphic_types:: vector_types:: vector;
@@ -1111,20 +1137,9 @@ impl Render for Table<Vector> {
11111137 // Render the path
11121138 match render_params. render_mode {
11131139 RenderMode :: Outline => {
1114- let outline_stroke = kurbo:: Stroke {
1115- width : LAYER_OUTLINE_STROKE_WEIGHT / if render_params. viewport_zoom > 0. { render_params. viewport_zoom } else { 1. } ,
1116- miter_limit : 4. ,
1117- join : Join :: Miter ,
1118- start_cap : Cap :: Butt ,
1119- end_cap : Cap :: Butt ,
1120- dash_pattern : Default :: default ( ) ,
1121- dash_offset : 0. ,
1122- } ;
1123-
1124- let outline_color = black_or_white_for_best_contrast ( render_params. artboard_background ) ;
1125- let outline_color = peniko:: Color :: new ( [ outline_color. r ( ) , outline_color. g ( ) , outline_color. b ( ) , outline_color. a ( ) ] ) ;
1140+ let ( outline_stroke, outline_color_peniko) = get_outline_styles ( render_params) ;
11261141
1127- scene. stroke ( & outline_stroke, kurbo:: Affine :: new ( element_transform. to_cols_array ( ) ) , outline_color , None , & path) ;
1142+ scene. stroke ( & outline_stroke, kurbo:: Affine :: new ( element_transform. to_cols_array ( ) ) , outline_color_peniko , None , & path) ;
11281143 }
11291144 _ => {
11301145 if use_layer {
@@ -1375,8 +1390,6 @@ impl Render for Table<Raster<CPU>> {
13751390 }
13761391
13771392 fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , _: & mut RenderContext , render_params : & RenderParams ) {
1378- use vello:: peniko;
1379-
13801393 for row in self . iter ( ) {
13811394 let image = & row. element ;
13821395 if image. data . is_empty ( ) {
@@ -1389,7 +1402,7 @@ impl Render for Table<Raster<CPU>> {
13891402 let opacity = alpha_blending. opacity ( render_params. for_mask ) ;
13901403 let mut layer = false ;
13911404
1392- if ( opacity < 1. || alpha_blending. blend_mode != BlendMode :: default ( ) )
1405+ if ( opacity < 1. || ( render_params . render_mode != RenderMode :: Outline && alpha_blending. blend_mode != BlendMode :: default ( ) ) )
13931406 && let RenderBoundingBox :: Rectangle ( bounds) = self . bounding_box ( transform, false )
13941407 {
13951408 let blending = peniko:: BlendMode :: new ( blend_mode, peniko:: Compose :: SrcOver ) ;
@@ -1398,6 +1411,19 @@ impl Render for Table<Raster<CPU>> {
13981411 layer = true ;
13991412 }
14001413
1414+ if let RenderMode :: Outline = render_params. render_mode {
1415+ let outline_transform = transform * * row. transform ;
1416+ draw_raster_outline ( scene, & outline_transform, render_params) ;
1417+
1418+ if layer {
1419+ scene. pop_layer ( ) ;
1420+ }
1421+
1422+ continue ;
1423+ }
1424+
1425+ let image_transform = transform * * row. transform * DAffine2 :: from_scale ( 1. / DVec2 :: new ( image. width as f64 , image. height as f64 ) ) ;
1426+
14011427 let image_brush = peniko:: ImageBrush :: new ( peniko:: ImageData {
14021428 data : image. to_flat_u8 ( ) . 0 . into ( ) ,
14031429 format : peniko:: ImageFormat :: Rgba8 ,
@@ -1406,7 +1432,6 @@ impl Render for Table<Raster<CPU>> {
14061432 alpha_type : peniko:: ImageAlphaType :: Alpha ,
14071433 } )
14081434 . with_extend ( peniko:: Extend :: Repeat ) ;
1409- let image_transform = transform * * row. transform * DAffine2 :: from_scale ( 1. / DVec2 :: new ( image. width as f64 , image. height as f64 ) ) ;
14101435
14111436 scene. draw_image ( & image_brush, kurbo:: Affine :: new ( image_transform. to_cols_array ( ) ) ) ;
14121437
@@ -1441,21 +1466,36 @@ impl Render for Table<Raster<GPU>> {
14411466 log:: warn!( "tried to render texture as an svg" ) ;
14421467 }
14431468
1444- fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext , _render_params : & RenderParams ) {
1445- use vello:: peniko;
1446-
1469+ fn render_to_vello ( & self , scene : & mut Scene , transform : DAffine2 , context : & mut RenderContext , render_params : & RenderParams ) {
14471470 for row in self . iter ( ) {
1448- let blend_mode = * row. alpha_blending ;
1471+ let alpha_blending = * row. alpha_blending ;
1472+ let blend_mode = match render_params. render_mode {
1473+ RenderMode :: Outline => peniko:: Mix :: Normal ,
1474+ _ => alpha_blending. blend_mode . to_peniko ( ) ,
1475+ } ;
1476+
14491477 let mut layer = false ;
1450- if blend_mode != Default :: default ( )
1478+
1479+ if ( render_params. render_mode != RenderMode :: Outline && alpha_blending != Default :: default ( ) )
14511480 && let RenderBoundingBox :: Rectangle ( bounds) = self . bounding_box ( transform, true )
14521481 {
1453- let blending = peniko:: BlendMode :: new ( blend_mode. blend_mode . to_peniko ( ) , peniko:: Compose :: SrcOver ) ;
1482+ let blending = peniko:: BlendMode :: new ( blend_mode, peniko:: Compose :: SrcOver ) ;
14541483 let rect = kurbo:: Rect :: new ( bounds[ 0 ] . x , bounds[ 0 ] . y , bounds[ 1 ] . x , bounds[ 1 ] . y ) ;
1455- scene. push_layer ( peniko:: Fill :: NonZero , blending, blend_mode . opacity , kurbo:: Affine :: IDENTITY , & rect) ;
1484+ scene. push_layer ( peniko:: Fill :: NonZero , blending, alpha_blending . opacity , kurbo:: Affine :: IDENTITY , & rect) ;
14561485 layer = true ;
14571486 }
14581487
1488+ if let RenderMode :: Outline = render_params. render_mode {
1489+ let outline_transform = transform * * row. transform ;
1490+ draw_raster_outline ( scene, & outline_transform, render_params) ;
1491+
1492+ if layer {
1493+ scene. pop_layer ( ) ;
1494+ }
1495+
1496+ continue ;
1497+ }
1498+
14591499 let width = row. element . data ( ) . width ( ) ;
14601500 let height = row. element . data ( ) . height ( ) ;
14611501 let image = peniko:: ImageBrush :: new ( peniko:: ImageData {
0 commit comments