[librsvg: 1/5] drawing_ctx: move draw_image to drawing context
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/5] drawing_ctx: move draw_image to drawing context
- Date: Fri, 28 Aug 2020 15:30:34 +0000 (UTC)
commit d9cc81a925223f682a5052aed826647e33d781b2
Author: Paolo Borelli <pborelli gnome org>
Date: Fri Aug 28 12:46:25 2020 +0200
drawing_ctx: move draw_image to drawing context
This is consistent with draw_path and moves us toward the goal
of encapsulating cairo usage in the drawing ctx.
rsvg_internals/src/drawing_ctx.rs | 56 ++++++++++++++++++++++++++
rsvg_internals/src/image.rs | 85 ++++++++++-----------------------------
2 files changed, 78 insertions(+), 63 deletions(-)
---
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 83cde5bf..e725052e 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -1022,6 +1022,62 @@ impl DrawingCtx {
}
}
+ pub fn draw_image(
+ &mut self,
+ surface: &SharedImageSurface,
+ rect: Rect,
+ aspect: AspectRatio,
+ node: &Node,
+ acquired_nodes: &mut AcquiredNodes,
+ values: &ComputedValues,
+ clipping: bool,
+ ) -> Result<BoundingBox, RenderingError> {
+ let image_width = surface.width();
+ let image_height = surface.height();
+ if clipping || rect.is_empty() || image_width == 0 || image_height == 0 {
+ return Ok(self.empty_bbox());
+ }
+
+ let image_width = f64::from(image_width);
+ let image_height = f64::from(image_height);
+ let vbox = ViewBox(Rect::from_size(image_width, image_height));
+
+ let clip_mode = if !values.is_overflow() && aspect.is_slice() {
+ Some(ClipMode::ClipToViewport)
+ } else {
+ None
+ };
+
+ self.with_discrete_layer(node, acquired_nodes, values, clipping, &mut |_an, dc| {
+ dc.with_saved_cr(&mut |dc| {
+ if let Some(_params) = dc.push_new_viewport(Some(vbox), rect, aspect, clip_mode) {
+ let cr = dc.get_cairo_context();
+
+ // We need to set extend appropriately, so can't use cr.set_source_surface().
+ //
+ // If extend is left at its default value (None), then bilinear scaling uses
+ // transparency outside of the image producing incorrect results.
+ // For example, in svg1.1/filters-blend-01-b.svgthere's a completely
+ // opaque 100×1 image of a gradient scaled to 100×98 which ends up
+ // transparent almost everywhere without this fix (which it shouldn't).
+ let ptn = surface.to_cairo_pattern();
+ ptn.set_extend(cairo::Extend::Pad);
+ cr.set_source(&ptn);
+
+ // Clip is needed due to extend being set to pad.
+ cr.rectangle(0.0, 0.0, image_width, image_height);
+ cr.clip();
+
+ cr.paint();
+ }
+
+ // The bounding box for <image> is decided by the values of x, y, w, h
+ // and not by the final computed image bounds.
+ Ok(dc.empty_bbox().with_rect(rect))
+ })
+ })
+ }
+
pub fn get_snapshot(
&self,
width: i32,
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index f17f9467..979486ff 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -6,7 +6,7 @@ use crate::allowed_url::Href;
use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
+use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -16,7 +16,6 @@ use crate::parsers::ParseValue;
use crate::properties::ComputedValues;
use crate::property_bag::PropertyBag;
use crate::rect::Rect;
-use crate::viewbox::ViewBox;
#[derive(Default)]
pub struct Image {
@@ -68,18 +67,19 @@ impl Draw for Image {
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
- let values = cascaded.get();
- let params = draw_ctx.get_view_params();
-
- let rect = self.get_rect(values, ¶ms);
-
- if rect.is_empty() || self.href.is_none() {
+ if self.href.is_none() {
return Ok(draw_ctx.empty_bbox());
}
let href = self.href.as_ref().unwrap();
- let url = match *href {
- Href::PlainUrl(ref url) => url,
+ let surface = match *href {
+ Href::PlainUrl(ref url) => match acquired_nodes.lookup_image(url) {
+ Ok(surf) => surf,
+ Err(e) => {
+ rsvg_log!("could not load image \"{}\": {}", url, e);
+ return Ok(draw_ctx.empty_bbox());
+ }
+ },
Href::WithFragment(_) => {
rsvg_log!(
"not rendering {} because its href cannot contain a fragment identifier",
@@ -90,60 +90,19 @@ impl Draw for Image {
}
};
- draw_ctx.with_discrete_layer(node, acquired_nodes, values, clipping, &mut |an, dc| {
- let surface = match an.lookup_image(url) {
- Ok(surf) => surf,
- Err(e) => {
- rsvg_log!("could not load image \"{}\": {}", url, e);
- return Ok(dc.empty_bbox());
- }
- };
-
- let clip_mode = if !values.is_overflow() && self.aspect.is_slice() {
- Some(ClipMode::ClipToViewport)
- } else {
- None
- };
-
- let image_width = surface.width();
- let image_height = surface.height();
- if clipping || image_width == 0 || image_height == 0 {
- return Ok(dc.empty_bbox());
- }
-
- dc.with_saved_cr(&mut |dc| {
- let image_width = f64::from(image_width);
- let image_height = f64::from(image_height);
- let vbox = ViewBox(Rect::from_size(image_width, image_height));
-
- if let Some(_params) =
- dc.push_new_viewport(Some(vbox), rect, self.aspect, clip_mode)
- {
- let cr = dc.get_cairo_context();
-
- // We need to set extend appropriately, so can't use cr.set_source_surface().
- //
- // If extend is left at its default value (None), then bilinear scaling uses
- // transparency outside of the image producing incorrect results.
- // For example, in svg1.1/filters-blend-01-b.svgthere's a completely
- // opaque 100×1 image of a gradient scaled to 100×98 which ends up
- // transparent almost everywhere without this fix (which it shouldn't).
- let ptn = surface.to_cairo_pattern();
- ptn.set_extend(cairo::Extend::Pad);
- cr.set_source(&ptn);
-
- // Clip is needed due to extend being set to pad.
- cr.rectangle(0.0, 0.0, image_width, image_height);
- cr.clip();
-
- cr.paint();
- }
+ let values = cascaded.get();
+ let params = draw_ctx.get_view_params();
+ let rect = self.get_rect(values, ¶ms);
- // The bounding box for <image> is decided by the values of x, y, w, h
- // and not by the final computed image bounds.
- Ok(dc.empty_bbox().with_rect(rect))
- })
- })
+ draw_ctx.draw_image(
+ &surface,
+ rect,
+ self.aspect,
+ node,
+ acquired_nodes,
+ values,
+ clipping,
+ )
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]