[librsvg: 3/7] mask: move generate_cairo_mask in drawing_ctx
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 3/7] mask: move generate_cairo_mask in drawing_ctx
- Date: Sun, 5 Jan 2020 22:56:36 +0000 (UTC)
commit 1757fb4cf633434d13726fe5fe177c346cd07c05
Author: Paolo Borelli <pborelli gnome org>
Date: Thu Jan 2 12:10:56 2020 +0100
mask: move generate_cairo_mask in drawing_ctx
This is another small step forward decoupling nodes from cairo
specifics.
rsvg_internals/src/drawing_ctx.rs | 118 ++++++++++++++++++++++++++++++--------
rsvg_internals/src/mask.rs | 103 +++++----------------------------
2 files changed, 109 insertions(+), 112 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 1f53e4ce..61db8250 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -23,15 +23,10 @@ use crate::paint_server::{PaintServer, PaintSource};
use crate::pattern::Pattern;
use crate::properties::ComputedValues;
use crate::property_defs::{
- ClipRule,
- FillRule,
- ShapeRendering,
- StrokeDasharray,
- StrokeLinecap,
- StrokeLinejoin,
+ ClipRule, FillRule, Opacity, ShapeRendering, StrokeDasharray, StrokeLinecap, StrokeLinejoin,
};
-use crate::rect::Rect;
-use crate::surface_utils::shared_surface::SharedImageSurface;
+use crate::rect::{Rect, TransformRect};
+use crate::surface_utils::{shared_surface::SharedImageSurface, shared_surface::SurfaceType};
use crate::unit_interval::UnitInterval;
use crate::viewbox::ViewBox;
@@ -408,6 +403,83 @@ impl DrawingCtx {
}
}
+ fn generate_cairo_mask(
+ &mut self,
+ mask: &Mask,
+ mask_node: &RsvgNode,
+ affine: cairo::Matrix,
+ bbox: &BoundingBox,
+ ) -> Result<Option<cairo::ImageSurface>, RenderingError> {
+ if bbox.rect.is_none() {
+ // The node being masked is empty / doesn't have a
+ // bounding box, so there's nothing to mask!
+ return Ok(None);
+ }
+
+ let bbox_rect = bbox.rect.as_ref().unwrap();
+ let (bb_x, bb_y) = (bbox_rect.x0, bbox_rect.y0);
+ let (bb_w, bb_h) = bbox_rect.size();
+
+ let cascaded = CascadedValues::new_from_node(mask_node);
+ let values = cascaded.get();
+
+ let mask_units = mask.get_units();
+
+ let mask_rect = {
+ let params = if mask_units == CoordUnits::ObjectBoundingBox {
+ self.push_view_box(1.0, 1.0)
+ } else {
+ self.get_view_params()
+ };
+
+ mask.get_rect(&values, ¶ms)
+ };
+
+ let mask_affine = cairo::Matrix::multiply(&mask_node.borrow().get_transform(), &affine);
+
+ let mask_content_surface = self.create_surface_for_toplevel_viewport()?;
+
+ // Use a scope because mask_cr needs to release the
+ // reference to the surface before we access the pixels
+ {
+ let mask_cr = cairo::Context::new(&mask_content_surface);
+ mask_cr.set_matrix(mask_affine);
+
+ let bbtransform = cairo::Matrix::new(bb_w, 0.0, 0.0, bb_h, bb_x, bb_y);
+
+ self.push_cairo_context(mask_cr);
+
+ if mask_units == CoordUnits::ObjectBoundingBox {
+ self.clip(bbtransform.transform_rect(&mask_rect));
+ } else {
+ self.clip(mask_rect);
+ }
+
+ let _params = if mask.get_content_units() == CoordUnits::ObjectBoundingBox {
+ self.get_cairo_context().transform(bbtransform);
+ self.push_view_box(1.0, 1.0)
+ } else {
+ self.get_view_params()
+ };
+
+ let res = self.with_discrete_layer(mask_node, values, false, &mut |dc| {
+ mask_node.draw_children(&cascaded, dc, false)
+ });
+
+ self.pop_cairo_context();
+
+ res?;
+ }
+
+ let Opacity(opacity) = values.opacity;
+
+ let mask = SharedImageSurface::new(mask_content_surface, SurfaceType::SRgb)?
+ .to_mask(u8::from(opacity))?
+ .into_image_surface()?;
+
+ Ok(Some(mask))
+ }
+
pub fn with_discrete_layer(
&mut self,
node: &RsvgNode,
@@ -507,24 +579,22 @@ impl DrawingCtx {
if let Some(fragment) = mask {
if let Ok(acquired) = dc.acquire_node(fragment, &[NodeType::Mask]) {
let mask_node = acquired.get();
- let mask_affine = cairo::Matrix::multiply(
- &mask_node.borrow().get_transform(),
- &affines.for_temporary_surface,
- );
res = res.and_then(|bbox| {
- mask_node
- .borrow()
- .get_impl::<Mask>()
- .generate_cairo_mask(&mask_node, mask_affine, dc, &bbox)
- .and_then(|mask_surf| {
- if let Some(surf) = mask_surf {
- dc.cr.set_matrix(affines.compositing);
- dc.cr.mask_surface(&surf, 0.0, 0.0);
- }
- Ok(())
- })
- .map(|_: ()| bbox)
+ dc.generate_cairo_mask(
+ &mask_node.borrow().get_impl::<Mask>(),
+ &mask_node,
+ affines.for_temporary_surface,
+ &bbox,
+ )
+ .and_then(|mask_surf| {
+ if let Some(surf) = mask_surf {
+ dc.cr.set_matrix(affines.compositing);
+ dc.cr.mask_surface(&surf, 0.0, 0.0);
+ }
+ Ok(())
+ })
+ .map(|_: ()| bbox)
});
} else {
rsvg_log!(
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index c83da849..5395bad8 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -1,19 +1,15 @@
//! The `mask` element.
-use cairo;
use markup5ever::{expanded_name, local_name, namespace_url, ns};
-use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
-use crate::drawing_ctx::DrawingCtx;
-use crate::error::RenderingError;
+use crate::drawing_ctx::ViewParams;
use crate::length::*;
-use crate::node::{CascadedValues, NodeDraw, NodeResult, NodeTrait, RsvgNode};
+use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
+use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
-use crate::property_defs::Opacity;
use crate::rect::Rect;
-use crate::surface_utils::{shared_surface::SharedImageSurface, shared_surface::SurfaceType};
coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);
@@ -44,90 +40,21 @@ impl Default for Mask {
}
impl Mask {
- pub fn generate_cairo_mask(
- &self,
- mask_node: &RsvgNode,
- affine: cairo::Matrix,
- draw_ctx: &mut DrawingCtx,
- bbox: &BoundingBox,
- ) -> Result<Option<cairo::ImageSurface>, RenderingError> {
- if bbox.rect.is_none() {
- // The node being masked is empty / doesn't have a
- // bounding box, so there's nothing to mask!
- return Ok(None);
- }
-
- let bbox_rect = bbox.rect.as_ref().unwrap();
- let (bb_x, bb_y) = (bbox_rect.x0, bbox_rect.y0);
- let (bb_w, bb_h) = bbox_rect.size();
-
- let cascaded = CascadedValues::new_from_node(mask_node);
- let values = cascaded.get();
-
- let mask_units = CoordUnits::from(self.units);
- let content_units = CoordUnits::from(self.content_units);
-
- let mask_rect = {
- let params = if mask_units == CoordUnits::ObjectBoundingBox {
- draw_ctx.push_view_box(1.0, 1.0)
- } else {
- draw_ctx.get_view_params()
- };
-
- let x = self.x.normalize(&values, ¶ms);
- let y = self.y.normalize(&values, ¶ms);
- let w = self.width.normalize(&values, ¶ms);
- let h = self.height.normalize(&values, ¶ms);
-
- let (x, y, w, h) = if mask_units == CoordUnits::ObjectBoundingBox {
- (x * bb_w + bb_x, y * bb_h + bb_y, w * bb_w, h * bb_h)
- } else {
- (x, y, w, h)
- };
-
- Rect::new(x, y, x + w, y + h)
- };
-
- let mask_content_surface = draw_ctx.create_surface_for_toplevel_viewport()?;
-
- // Use a scope because mask_cr needs to release the
- // reference to the surface before we access the pixels
- {
- let mask_cr = cairo::Context::new(&mask_content_surface);
- mask_cr.set_matrix(affine);
-
- draw_ctx.push_cairo_context(mask_cr);
-
- draw_ctx.clip(mask_rect);
-
- {
- let _params = if content_units == CoordUnits::ObjectBoundingBox {
- let bbtransform = cairo::Matrix::new(bb_w, 0.0, 0.0, bb_h, bb_x, bb_y);
-
- draw_ctx.get_cairo_context().transform(bbtransform);
-
- draw_ctx.push_view_box(1.0, 1.0)
- } else {
- draw_ctx.get_view_params()
- };
-
- let res = draw_ctx.with_discrete_layer(mask_node, values, false, &mut |dc| {
- mask_node.draw_children(&cascaded, dc, false)
- });
-
- draw_ctx.pop_cairo_context();
-
- res
- }
- }?;
+ pub fn get_units(&self) -> CoordUnits {
+ CoordUnits::from(self.content_units)
+ }
- let Opacity(opacity) = values.opacity;
+ pub fn get_content_units(&self) -> CoordUnits {
+ CoordUnits::from(self.content_units)
+ }
- let mask = SharedImageSurface::new(mask_content_surface, SurfaceType::SRgb)?
- .to_mask(u8::from(opacity))?
- .into_image_surface()?;
+ pub fn get_rect(&self, values: &ComputedValues, params: &ViewParams) -> Rect {
+ let x = self.x.normalize(&values, ¶ms);
+ let y = self.y.normalize(&values, ¶ms);
+ let w = self.width.normalize(&values, ¶ms);
+ let h = self.height.normalize(&values, ¶ms);
- Ok(Some(mask))
+ Rect::new(x, y, x + w, y + h)
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]