[librsvg/wip/dimensions-api] Abstract the "establish a new viewport" construct from SVG into DrawingCtx
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/wip/dimensions-api] Abstract the "establish a new viewport" construct from SVG into DrawingCtx
- Date: Tue, 12 Feb 2019 02:31:32 +0000 (UTC)
commit 3145105cfd8e19f04b7954000aaf0b8c5c0b5089
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Feb 11 20:26:05 2019 -0600
Abstract the "establish a new viewport" construct from SVG into DrawingCtx
This commit does three things:
1. Adds AspectRatio::viewport_to_viewbox_transform(), which returns a
Matrix.
2. Moves most of draw_in_viewport() into a new
DrawingCtx::push_new_viewport().
3. Leaves draw_in_viewport() as just the thing that checks viewport
sizes and calls draw_ctx.with_discrete_layer().
rsvg_internals/src/aspect_ratio.rs | 30 ++++++++++++++++++++++++-
rsvg_internals/src/drawing_ctx.rs | 45 ++++++++++++++++++++++++++++++++++++++
rsvg_internals/src/viewport.rs | 39 +--------------------------------
3 files changed, 75 insertions(+), 39 deletions(-)
---
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index 8af83ed3..7c1352b8 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -22,10 +22,11 @@
use std::ops::Deref;
-use cairo;
+use cairo::{self, MatrixTrait};
use cssparser::{CowRcStr, Parser};
use error::ValueErrorKind;
+use float_eq_cairo::ApproxEqCairo;
use parsers::Parse;
use parsers::ParseError;
use viewbox::ViewBox;
@@ -146,6 +147,33 @@ impl AspectRatio {
}
}
}
+
+ // Computes the viewport to viewbox transformation, or returns None
+ // if the vbox has 0 width or height.
+ pub fn viewport_to_viewbox_transform(
+ &self,
+ vbox: Option<ViewBox>,
+ viewport: &cairo::Rectangle,
+ ) -> Option<cairo::Matrix> {
+ if let Some(vbox) = vbox {
+ if vbox.width.approx_eq_cairo(&0.0) || vbox.height.approx_eq_cairo(&0.0) {
+ // Width or height of 0 for the viewBox disables rendering of the element
+ // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+ None
+ } else {
+ let (x, y, w, h) = self.compute(&vbox, viewport);
+ let mut matrix = cairo::Matrix::identity();
+ matrix.translate(x, y);
+ matrix.scale(w / vbox.width, h / vbox.height);
+ matrix.translate(-vbox.x, -vbox.y);
+ Some(matrix)
+ }
+ } else {
+ let mut matrix = cairo::Matrix::identity();
+ matrix.translate(viewport.x, viewport.y);
+ Some(matrix)
+ }
+ }
}
fn parse_align_xy(ident: &CowRcStr) -> Result<Option<(X, Y)>, ValueErrorKind> {
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index 4a4662fb..be7ba65e 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -6,6 +6,7 @@ use std::cell::RefCell;
use std::rc::{Rc, Weak};
use allowed_url::Fragment;
+use aspect_ratio::AspectRatio;
use bbox::BoundingBox;
use clip_path::{ClipPathUnits, NodeClipPath};
use coord_units::CoordUnits;
@@ -33,6 +34,7 @@ use surface_utils::shared_surface::SharedImageSurface;
use svg::Svg;
use unit_interval::UnitInterval;
use viewbox::ViewBox;
+use viewport::ClipMode;
/// Holds values that are required to normalize `Length` values to a current viewport.
///
@@ -225,6 +227,49 @@ impl DrawingCtx {
}
}
+ pub fn push_new_viewport(
+ &self,
+ vbox: Option<ViewBox>,
+ viewport: &cairo::Rectangle,
+ preserve_aspect_ratio: AspectRatio,
+ clip_mode: Option<ClipMode>,
+ ) -> Option<ViewParams> {
+ if let Some(ref clip) = clip_mode {
+ if *clip == ClipMode::ClipToViewport {
+ self.clip(viewport.x, viewport.y, viewport.width, viewport.height);
+ }
+ }
+
+ if let Some(vbox) = vbox {
+ // the preserveAspectRatio attribute is only used if viewBox is specified
+ // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
+
+ if let Some(matrix) =
+ preserve_aspect_ratio.viewport_to_viewbox_transform(Some(vbox), viewport)
+ {
+ let params = self.push_view_box(vbox.width, vbox.height);
+
+ self.cr.transform(matrix);
+
+ if let Some(ref clip) = clip_mode {
+ if *clip == ClipMode::ClipToVbox {
+ self.clip(vbox.x, vbox.y, vbox.width, vbox.height);
+ }
+ }
+
+ Some(params)
+ } else {
+ // Width or height of 0 for the viewBox disables rendering of the element
+ // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+ return None;
+ }
+ } else {
+ let params = self.push_view_box(viewport.width, viewport.height);
+ self.cr.translate(viewport.x, viewport.y);
+ Some(params)
+ }
+ }
+
pub fn insert_bbox(&mut self, bbox: &BoundingBox) {
self.bbox.insert(bbox);
}
diff --git a/rsvg_internals/src/viewport.rs b/rsvg_internals/src/viewport.rs
index 928ab449..679d5e14 100644
--- a/rsvg_internals/src/viewport.rs
+++ b/rsvg_internals/src/viewport.rs
@@ -36,44 +36,7 @@ pub fn draw_in_viewport(
}
draw_ctx.with_discrete_layer(node, values, clipping, &mut |dc| {
- let cr = dc.get_cairo_context();
-
- if let Some(ref clip) = clip_mode {
- if *clip == ClipMode::ClipToViewport {
- dc.clip(viewport.x, viewport.y, viewport.width, viewport.height);
- }
- }
-
- let _params = if let Some(vbox) = vbox {
- // the preserveAspectRatio attribute is only used if viewBox is specified
- // https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
-
- if vbox.width.approx_eq_cairo(&0.0) || vbox.height.approx_eq_cairo(&0.0) {
- // Width or height of 0 for the viewBox disables rendering of the element
- // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
- return Ok(());
- }
-
- let params = dc.push_view_box(vbox.width, vbox.height);
-
- let (x, y, w, h) = preserve_aspect_ratio.compute(&vbox, viewport);
-
- cr.translate(x, y);
- cr.scale(w / vbox.width, h / vbox.height);
- cr.translate(-vbox.x, -vbox.y);
-
- if let Some(ref clip) = clip_mode {
- if *clip == ClipMode::ClipToVbox {
- dc.clip(vbox.x, vbox.y, vbox.width, vbox.height);
- }
- }
-
- params
- } else {
- let params = dc.push_view_box(viewport.width, viewport.height);
- cr.translate(viewport.x, viewport.y);
- params
- };
+ let _params = dc.push_new_viewport(vbox, viewport, preserve_aspect_ratio, clip_mode);
let res = draw_fn(dc);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]