[librsvg: 1/2] DrawingCtx::draw_path - clear/recalculate path only when needed




commit 008ddce3dc506e002a4a1ebc162860104963482f
Author: John Ledbetter <john ledbetter gmail com>
Date:   Wed Sep 2 09:36:54 2020 -0400

    DrawingCtx::draw_path - clear/recalculate path only when needed
    
    In the default 'Fill, Stroke, Markers' paint order, there's no need
    to regenerate the draw path in between each step, only once at the start.
    We only need to re-generate the path if the paint-order specifies that the
    Markers step comes between Fill and Stroke.
    
    Adjust fill & stroke to preserve the cairo path, only creating a new one
    if it has been unset to paint markers.
    
    * Remove redundant 'if clipping' check when painting; we never get to this
      match if we're clipping.
    * Convert clipping if/else to an early return to help de-indent the painting
      block.

 rsvg_internals/src/drawing_ctx.rs | 61 ++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 23 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index e73d134c..ead30f4b 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -1178,7 +1178,7 @@ impl DrawingCtx {
         )
         .map(|had_paint_server| {
             if had_paint_server {
-                cr.stroke();
+                cr.stroke_preserve();
             }
         })?;
 
@@ -1203,7 +1203,7 @@ impl DrawingCtx {
         )
         .map(|had_paint_server| {
             if had_paint_server {
-                cr.fill();
+                cr.fill_preserve();
             }
         })?;
 
@@ -1230,39 +1230,54 @@ impl DrawingCtx {
             if clipping {
                 cr.set_fill_rule(cairo::FillRule::from(values.clip_rule()));
                 path.to_cairo(&cr, is_square_linecap)?;
-                Ok(dc.empty_bbox())
-            } else {
-                let current_color = values.color().0;
+                return Ok(dc.empty_bbox());
+            }
 
-                cr.set_antialias(cairo::Antialias::from(values.shape_rendering()));
-                dc.setup_cr_for_stroke(&cr, values);
+            let current_color = values.color().0;
 
-                cr.set_fill_rule(cairo::FillRule::from(values.fill_rule()));
-                path.to_cairo(&cr, is_square_linecap)?;
-                let bbox = compute_stroke_and_fill_box(&cr, &values);
-                cr.new_path();
+            cr.set_antialias(cairo::Antialias::from(values.shape_rendering()));
+            dc.setup_cr_for_stroke(&cr, values);
 
-                for &target in &values.paint_order().targets {
-                    match target {
-                        PaintTarget::Fill if !clipping => {
+            cr.set_fill_rule(cairo::FillRule::from(values.fill_rule()));
+
+            let mut bounding_box: Option<BoundingBox> = None;
+            let mut has_path = false;
+            cr.new_path();
+
+            for &target in &values.paint_order().targets {
+                // fill and stroke operations will preserve the path.
+                // markers operation will clear the path.
+                match target {
+                    PaintTarget::Fill | PaintTarget::Stroke => {
+                        if !has_path {
                             path.to_cairo(&cr, is_square_linecap)?;
-                            dc.fill(&cr, an, values, &bbox, current_color)?;
-                            cr.new_path();
+                            has_path = true;
                         }
-                        PaintTarget::Stroke if !clipping => {
-                            path.to_cairo(&cr, is_square_linecap)?;
+                        let bbox = bounding_box
+                            .get_or_insert_with(|| compute_stroke_and_fill_box(&cr, &values));
+
+                        if target == PaintTarget::Stroke {
                             dc.stroke(&cr, an, values, &bbox, current_color)?;
-                            cr.new_path();
+                        } else {
+                            dc.fill(&cr, an, values, &bbox, current_color)?;
                         }
-                        PaintTarget::Markers if markers == Markers::Yes => {
-                            marker::render_markers_for_path(path, dc, an, values, clipping)?;
+                    }
+                    PaintTarget::Markers if markers == Markers::Yes => {
+                        if has_path {
+                            cr.new_path();
+                            has_path = false;
                         }
-                        _ => {}
+                        marker::render_markers_for_path(path, dc, an, values, clipping)?;
                     }
+                    _ => {}
                 }
+            }
 
-                Ok(bbox)
+            if has_path {
+                cr.new_path();
             }
+
+            Ok(bounding_box.unwrap())
         })
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]