[librsvg: 4/6] drawing-ctx: move stroke_and_fill method to drawing ctx
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 4/6] drawing-ctx: move stroke_and_fill method to drawing ctx
- Date: Tue, 26 Jun 2018 02:03:24 +0000 (UTC)
commit a4ffab2fa8ddc7165f44be768fb6ecb1be4a2890
Author: Paolo Borelli <pborelli gnome org>
Date: Mon Jun 25 23:05:55 2018 +0200
drawing-ctx: move stroke_and_fill method to drawing ctx
rsvg_internals/src/draw.rs | 203 +-------------------------------------
rsvg_internals/src/drawing_ctx.rs | 200 ++++++++++++++++++++++++++++++++++++-
2 files changed, 199 insertions(+), 204 deletions(-)
---
diff --git a/rsvg_internals/src/draw.rs b/rsvg_internals/src/draw.rs
index 07a3f03b..eef90bce 100644
--- a/rsvg_internals/src/draw.rs
+++ b/rsvg_internals/src/draw.rs
@@ -1,21 +1,9 @@
use cairo;
-use cairo_sys;
-use glib::translate::*;
-use bbox::BoundingBox;
use drawing_ctx::DrawingCtx;
-use paint_server;
-use paint_server::PaintServer;
use path_builder::PathBuilder;
use state::{
- ClipRule,
- CompOp,
ComputedValues,
- FillRule,
- ShapeRendering,
- StrokeLinecap,
- StrokeLinejoin,
- TextRendering,
};
pub fn draw_path_builder(
@@ -34,196 +22,7 @@ pub fn draw_path_builder(
} else {
cr.set_fill_rule(cairo::FillRule::from(values.fill_rule));
- stroke_and_fill(&cr, draw_ctx, values);
+ draw_ctx.stroke_and_fill(&cr, values);
}
}
-fn stroke_and_fill(cr: &cairo::Context, draw_ctx: &mut DrawingCtx, values: &ComputedValues) {
- cr.set_antialias(cairo::Antialias::from(values.shape_rendering));
-
- draw_ctx.setup_cr_for_stroke(cr, values);
-
- // Update the bbox in the rendering context. Below, we actually set the
- // fill/stroke patterns on the cairo_t. That process requires the
- // rendering context to have an updated bbox; for example, for the
- // coordinate system in patterns.
- let bbox = compute_stroke_and_fill_box(cr, values);
- draw_ctx.insert_bbox(&bbox);
-
- let current_color = &values.color.0;
-
- let fill_opacity = &values.fill_opacity.0;
-
- if paint_server::set_source_paint_server(
- draw_ctx,
- &values.fill.0,
- fill_opacity,
- &bbox,
- current_color,
- ) {
- if values.stroke.0 == PaintServer::None {
- cr.fill();
- } else {
- cr.fill_preserve();
- }
- }
-
- let stroke_opacity = values.stroke_opacity.0;
-
- if paint_server::set_source_paint_server(
- draw_ctx,
- &values.stroke.0,
- &stroke_opacity,
- &bbox,
- ¤t_color,
- ) {
- cr.stroke();
- }
-
- // clear the path in case stroke == fill == None; otherwise
- // we leave it around from computing the bounding box
- cr.new_path();
-}
-
-impl From<StrokeLinejoin> for cairo::LineJoin {
- fn from(j: StrokeLinejoin) -> cairo::LineJoin {
- match j {
- StrokeLinejoin::Miter => cairo::LineJoin::Miter,
- StrokeLinejoin::Round => cairo::LineJoin::Round,
- StrokeLinejoin::Bevel => cairo::LineJoin::Bevel,
- }
- }
-}
-
-impl From<StrokeLinecap> for cairo::LineCap {
- fn from(j: StrokeLinecap) -> cairo::LineCap {
- match j {
- StrokeLinecap::Butt => cairo::LineCap::Butt,
- StrokeLinecap::Round => cairo::LineCap::Round,
- StrokeLinecap::Square => cairo::LineCap::Square,
- }
- }
-}
-
-impl From<CompOp> for cairo::Operator {
- fn from(op: CompOp) -> cairo::Operator {
- match op {
- CompOp::Clear => cairo::Operator::Clear,
- CompOp::Src => cairo::Operator::Source,
- CompOp::Dst => cairo::Operator::Dest,
- CompOp::SrcOver => cairo::Operator::Over,
- CompOp::DstOver => cairo::Operator::DestOver,
- CompOp::SrcIn => cairo::Operator::In,
- CompOp::DstIn => cairo::Operator::DestIn,
- CompOp::SrcOut => cairo::Operator::Out,
- CompOp::DstOut => cairo::Operator::DestOut,
- CompOp::SrcAtop => cairo::Operator::Atop,
- CompOp::DstAtop => cairo::Operator::DestAtop,
- CompOp::Xor => cairo::Operator::Xor,
- CompOp::Plus => cairo::Operator::Add,
- CompOp::Multiply => cairo::Operator::Multiply,
- CompOp::Screen => cairo::Operator::Screen,
- CompOp::Overlay => cairo::Operator::Overlay,
- CompOp::Darken => cairo::Operator::Darken,
- CompOp::Lighten => cairo::Operator::Lighten,
- CompOp::ColorDodge => cairo::Operator::ColorDodge,
- CompOp::ColorBurn => cairo::Operator::ColorBurn,
- CompOp::HardLight => cairo::Operator::HardLight,
- CompOp::SoftLight => cairo::Operator::SoftLight,
- CompOp::Difference => cairo::Operator::Difference,
- CompOp::Exclusion => cairo::Operator::Exclusion,
- }
- }
-}
-
-impl From<ClipRule> for cairo::FillRule {
- fn from(c: ClipRule) -> cairo::FillRule {
- match c {
- ClipRule::NonZero => cairo::FillRule::Winding,
- ClipRule::EvenOdd => cairo::FillRule::EvenOdd,
- }
- }
-}
-
-impl From<FillRule> for cairo::FillRule {
- fn from(f: FillRule) -> cairo::FillRule {
- match f {
- FillRule::NonZero => cairo::FillRule::Winding,
- FillRule::EvenOdd => cairo::FillRule::EvenOdd,
- }
- }
-}
-
-impl From<ShapeRendering> for cairo::Antialias {
- fn from(sr: ShapeRendering) -> cairo::Antialias {
- match sr {
- ShapeRendering::Auto | ShapeRendering::GeometricPrecision => cairo::Antialias::Default,
- ShapeRendering::OptimizeSpeed | ShapeRendering::CrispEdges => cairo::Antialias::None,
- }
- }
-}
-
-impl From<TextRendering> for cairo::Antialias {
- fn from(tr: TextRendering) -> cairo::Antialias {
- match tr {
- TextRendering::Auto
- | TextRendering::OptimizeLegibility
- | TextRendering::GeometricPrecision => cairo::Antialias::Default,
- TextRendering::OptimizeSpeed => cairo::Antialias::None,
- }
- }
-}
-
-// remove this binding once cairo-rs has Context::path_extents()
-fn path_extents(cr: &cairo::Context) -> (f64, f64, f64, f64) {
- let mut x1: f64 = 0.0;
- let mut y1: f64 = 0.0;
- let mut x2: f64 = 0.0;
- let mut y2: f64 = 0.0;
-
- unsafe {
- cairo_sys::cairo_path_extents(cr.to_glib_none().0, &mut x1, &mut y1, &mut x2, &mut y2);
- }
- (x1, y1, x2, y2)
-}
-
-fn compute_stroke_and_fill_box(cr: &cairo::Context, values: &ComputedValues) -> BoundingBox {
- let affine = cr.get_matrix();
-
- let mut bbox = BoundingBox::new(&affine);
-
- // Dropping the precision of cairo's bezier subdivision, yielding 2x
- // _rendering_ time speedups, are these rather expensive operations
- // really needed here? */
- let backup_tolerance = cr.get_tolerance();
- cr.set_tolerance(1.0);
-
- // Bounding box for fill
- //
- // Unlike the case for stroke, for fills we always compute the bounding box.
- // In GNOME we have SVGs for symbolic icons where each icon has a bounding
- // rectangle with no fill and no stroke, and inside it there are the actual
- // paths for the icon's shape. We need to be able to compute the bounding
- // rectangle's extents, even when it has no fill nor stroke.
-
- let fb = BoundingBox::new(&affine).with_ink_extents(cr.fill_extents());
- bbox.insert(&fb);
-
- // Bounding box for stroke
-
- if values.stroke.0 != PaintServer::None {
- let sb = BoundingBox::new(&affine).with_ink_extents(cr.stroke_extents());
- bbox.insert(&sb);
- }
-
- // objectBoundingBox
-
- let ob = BoundingBox::new(&affine).with_extents(path_extents(cr));
- bbox.insert(&ob);
-
- // restore tolerance
-
- cr.set_tolerance(backup_tolerance);
-
- bbox
-}
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 9c28819e..331072d3 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -19,13 +19,19 @@ use float_eq_cairo::ApproxEqCairo;
use length::Dasharray;
use mask::NodeMask;
use node::{rc_node_ptr_eq, CascadedValues, NodeType, RsvgNode};
-use paint_server;
+use paint_server::{self, PaintServer};
use rect::RectangleExt;
use state::{
+ ClipRule,
CompOp,
ComputedValues,
EnableBackground,
+ FillRule,
+ ShapeRendering,
StrokeDasharray,
+ StrokeLinecap,
+ StrokeLinejoin,
+ TextRendering,
};
use unitinterval::UnitInterval;
use viewbox::ViewBox;
@@ -502,7 +508,7 @@ impl<'a> DrawingCtx {
cr.restore();
}
- pub fn setup_cr_for_stroke(&self, cr: &cairo::Context, values: &ComputedValues) {
+ fn setup_cr_for_stroke(&self, cr: &cairo::Context, values: &ComputedValues) {
cr.set_line_width(values.stroke_width.0.normalize(values, self));
cr.set_miter_limit(values.stroke_miterlimit.0);
cr.set_line_cap(cairo::LineCap::from(values.stroke_line_cap));
@@ -523,6 +529,53 @@ impl<'a> DrawingCtx {
}
}
+ pub fn stroke_and_fill(&mut self, cr: &cairo::Context, values: &ComputedValues) {
+ cr.set_antialias(cairo::Antialias::from(values.shape_rendering));
+
+ self.setup_cr_for_stroke(cr, values);
+
+ // Update the bbox in the rendering context. Below, we actually set the
+ // fill/stroke patterns on the cairo_t. That process requires the
+ // rendering context to have an updated bbox; for example, for the
+ // coordinate system in patterns.
+ let bbox = compute_stroke_and_fill_box(cr, values);
+ self.insert_bbox(&bbox);
+
+ let current_color = &values.color.0;
+
+ let fill_opacity = &values.fill_opacity.0;
+
+ if paint_server::set_source_paint_server(
+ self,
+ &values.fill.0,
+ fill_opacity,
+ &bbox,
+ current_color,
+ ) {
+ if values.stroke.0 == PaintServer::None {
+ cr.fill();
+ } else {
+ cr.fill_preserve();
+ }
+ }
+
+ let stroke_opacity = values.stroke_opacity.0;
+
+ if paint_server::set_source_paint_server(
+ self,
+ &values.stroke.0,
+ &stroke_opacity,
+ &bbox,
+ ¤t_color,
+ ) {
+ cr.stroke();
+ }
+
+ // clear the path in case stroke == fill == None; otherwise
+ // we leave it around from computing the bounding box
+ cr.new_path();
+ }
+
pub fn set_affine_on_cr(&self, cr: &cairo::Context) {
let (x0, y0) = self.get_offset();
let affine = cr.get_matrix();
@@ -674,6 +727,149 @@ fn compute_text_bbox(
bbox
}
+fn compute_stroke_and_fill_box(cr: &cairo::Context, values: &ComputedValues) -> BoundingBox {
+ let affine = cr.get_matrix();
+
+ let mut bbox = BoundingBox::new(&affine);
+
+ // Dropping the precision of cairo's bezier subdivision, yielding 2x
+ // _rendering_ time speedups, are these rather expensive operations
+ // really needed here? */
+ let backup_tolerance = cr.get_tolerance();
+ cr.set_tolerance(1.0);
+
+ // Bounding box for fill
+ //
+ // Unlike the case for stroke, for fills we always compute the bounding box.
+ // In GNOME we have SVGs for symbolic icons where each icon has a bounding
+ // rectangle with no fill and no stroke, and inside it there are the actual
+ // paths for the icon's shape. We need to be able to compute the bounding
+ // rectangle's extents, even when it has no fill nor stroke.
+
+ let fb = BoundingBox::new(&affine).with_ink_extents(cr.fill_extents());
+ bbox.insert(&fb);
+
+ // Bounding box for stroke
+
+ if values.stroke.0 != PaintServer::None {
+ let sb = BoundingBox::new(&affine).with_ink_extents(cr.stroke_extents());
+ bbox.insert(&sb);
+ }
+
+ // objectBoundingBox
+
+ let ob = BoundingBox::new(&affine).with_extents(path_extents(cr));
+ bbox.insert(&ob);
+
+ // restore tolerance
+
+ cr.set_tolerance(backup_tolerance);
+
+ bbox
+}
+
+// remove this binding once cairo-rs has Context::path_extents()
+fn path_extents(cr: &cairo::Context) -> (f64, f64, f64, f64) {
+ let mut x1: f64 = 0.0;
+ let mut y1: f64 = 0.0;
+ let mut x2: f64 = 0.0;
+ let mut y2: f64 = 0.0;
+
+ unsafe {
+ cairo_sys::cairo_path_extents(cr.to_glib_none().0, &mut x1, &mut y1, &mut x2, &mut y2);
+ }
+ (x1, y1, x2, y2)
+}
+
+impl From<StrokeLinejoin> for cairo::LineJoin {
+ fn from(j: StrokeLinejoin) -> cairo::LineJoin {
+ match j {
+ StrokeLinejoin::Miter => cairo::LineJoin::Miter,
+ StrokeLinejoin::Round => cairo::LineJoin::Round,
+ StrokeLinejoin::Bevel => cairo::LineJoin::Bevel,
+ }
+ }
+}
+
+impl From<StrokeLinecap> for cairo::LineCap {
+ fn from(j: StrokeLinecap) -> cairo::LineCap {
+ match j {
+ StrokeLinecap::Butt => cairo::LineCap::Butt,
+ StrokeLinecap::Round => cairo::LineCap::Round,
+ StrokeLinecap::Square => cairo::LineCap::Square,
+ }
+ }
+}
+
+impl From<CompOp> for cairo::Operator {
+ fn from(op: CompOp) -> cairo::Operator {
+ match op {
+ CompOp::Clear => cairo::Operator::Clear,
+ CompOp::Src => cairo::Operator::Source,
+ CompOp::Dst => cairo::Operator::Dest,
+ CompOp::SrcOver => cairo::Operator::Over,
+ CompOp::DstOver => cairo::Operator::DestOver,
+ CompOp::SrcIn => cairo::Operator::In,
+ CompOp::DstIn => cairo::Operator::DestIn,
+ CompOp::SrcOut => cairo::Operator::Out,
+ CompOp::DstOut => cairo::Operator::DestOut,
+ CompOp::SrcAtop => cairo::Operator::Atop,
+ CompOp::DstAtop => cairo::Operator::DestAtop,
+ CompOp::Xor => cairo::Operator::Xor,
+ CompOp::Plus => cairo::Operator::Add,
+ CompOp::Multiply => cairo::Operator::Multiply,
+ CompOp::Screen => cairo::Operator::Screen,
+ CompOp::Overlay => cairo::Operator::Overlay,
+ CompOp::Darken => cairo::Operator::Darken,
+ CompOp::Lighten => cairo::Operator::Lighten,
+ CompOp::ColorDodge => cairo::Operator::ColorDodge,
+ CompOp::ColorBurn => cairo::Operator::ColorBurn,
+ CompOp::HardLight => cairo::Operator::HardLight,
+ CompOp::SoftLight => cairo::Operator::SoftLight,
+ CompOp::Difference => cairo::Operator::Difference,
+ CompOp::Exclusion => cairo::Operator::Exclusion,
+ }
+ }
+}
+
+impl From<ClipRule> for cairo::FillRule {
+ fn from(c: ClipRule) -> cairo::FillRule {
+ match c {
+ ClipRule::NonZero => cairo::FillRule::Winding,
+ ClipRule::EvenOdd => cairo::FillRule::EvenOdd,
+ }
+ }
+}
+
+impl From<FillRule> for cairo::FillRule {
+ fn from(f: FillRule) -> cairo::FillRule {
+ match f {
+ FillRule::NonZero => cairo::FillRule::Winding,
+ FillRule::EvenOdd => cairo::FillRule::EvenOdd,
+ }
+ }
+}
+
+impl From<ShapeRendering> for cairo::Antialias {
+ fn from(sr: ShapeRendering) -> cairo::Antialias {
+ match sr {
+ ShapeRendering::Auto | ShapeRendering::GeometricPrecision => cairo::Antialias::Default,
+ ShapeRendering::OptimizeSpeed | ShapeRendering::CrispEdges => cairo::Antialias::None,
+ }
+ }
+}
+
+impl From<TextRendering> for cairo::Antialias {
+ fn from(tr: TextRendering) -> cairo::Antialias {
+ match tr {
+ TextRendering::Auto
+ | TextRendering::OptimizeLegibility
+ | TextRendering::GeometricPrecision => cairo::Antialias::Default,
+ TextRendering::OptimizeSpeed => cairo::Antialias::None,
+ }
+ }
+}
+
#[no_mangle]
pub extern "C" fn rsvg_drawing_ctx_draw_node_from_stack(
raw_draw_ctx: *mut RsvgDrawingCtx,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]