summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarge Bot <marge-bot@gnome.org>2023-03-30 22:51:53 +0000
committerMarge Bot <marge-bot@gnome.org>2023-03-30 22:51:53 +0000
commitd597831ff93b09cc41ce4768a833bc6407c95184 (patch)
treea94f21b95b21483c5e9d1bb331d3dc7836901cb9
parentc2a06bb9feee23b8ff455a340bdb2522705065c9 (diff)
parente41f4d64330c68f5bbe138c68b1cec87b5d99f0b (diff)
downloadlibrsvg-d597831ff93b09cc41ce4768a833bc6407c95184.tar.gz
Merge branch 'unify-viewport' into 'main'
Remove the current viewport as mutable state from DrawingCtx See merge request GNOME/librsvg!821
-rw-r--r--devel-docs/render_tree.rst21
-rw-r--r--src/drawing_ctx.rs403
-rw-r--r--src/element.rs9
-rw-r--r--src/filter.rs31
-rw-r--r--src/gradient.rs6
-rw-r--r--src/handle.rs4
-rw-r--r--src/image.rs8
-rw-r--r--src/length.rs24
-rw-r--r--src/marker.rs22
-rw-r--r--src/node.rs9
-rw-r--r--src/paint_server.rs8
-rw-r--r--src/pattern.rs6
-rw-r--r--src/shapes.rs23
-rw-r--r--src/structure.rs43
-rw-r--r--src/text.rs26
15 files changed, 343 insertions, 300 deletions
diff --git a/devel-docs/render_tree.rst b/devel-docs/render_tree.rst
index 1dee8710..3805f514 100644
--- a/devel-docs/render_tree.rst
+++ b/devel-docs/render_tree.rst
@@ -194,19 +194,21 @@ The most critical function in librsvg is probably
<https://gnome.pages.gitlab.gnome.org/librsvg/internals/librsvg/drawing_ctx/struct.DrawingCtx.html#method.with_discrete_layer>`_;
it implements this drawing model.
-Current state
--------------
+Current state (2023/03/30)
+--------------------------
``layout.rs`` has the beginnings of the render tree. It's probably mis-named? It contains this:
-- A primitive for path-based shapes.
-
-- A primitive for text.
+- A `LayerKind` with primitives for path-based shapes, text, and images.
- A `stacking context
<https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex>`_,
which indicates each layer's opacity/clip/mask/filters.
+- A `Layer` which composes the previous two. The `StackingContext`
+ provides the compositing/masking/filtering parameters, while the
+ `LayerKind` determines the primitive contents of the layer.
+
- Various ancillary structures that try to have only user-space
coordinates (e.g. a number of CSS pixels instead of ``5cm``) and no
references to other things.
@@ -267,6 +269,15 @@ probably called ``layer``, with something like this:
That is, every stacking context should contain the thing that it will
draw, and that thing may be a shape/text or another stacking context!
+As of 2023/03/30, the "current viewport" is no longer part of
+`DrawingCtx`'s mutable state. Instead, a `Viewport` struct is passed
+down the call chain via a function argument. This is not complete
+yet, since the code modifies the current `cr`'s transform apart from
+the current viewport's transform. The goal is to have the current
+viewport actually have the full transform to be applied to the object
+being rendered. This should simplify gnarly code paths like the one
+for rendering ``<pattern>``.
+
Bounding boxes
--------------
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 46c98d5b..0bf726c3 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -10,7 +10,7 @@ use std::borrow::Cow;
use std::cell::RefCell;
use std::convert::TryFrom;
use std::f64::consts::*;
-use std::rc::{Rc, Weak};
+use std::rc::Rc;
use std::sync::Arc;
use crate::accept_language::UserLanguage;
@@ -47,58 +47,6 @@ use crate::transform::{Transform, ValidTransform};
use crate::unit_interval::UnitInterval;
use crate::viewbox::ViewBox;
-/// Holds values that are required to normalize `CssLength` values to a current viewport.
-///
-/// This struct is created by calling `DrawingCtx::push_view_box()` or
-/// `DrawingCtx::get_view_params()`.
-///
-/// This struct holds the size of the current viewport in the user's coordinate system. A
-/// viewport pushed with `DrawingCtx::push_view_box()` will remain in place until the
-/// returned `ViewParams` is dropped; at that point, the `DrawingCtx` will resume using its
-/// previous viewport.
-pub struct ViewParams {
- pub dpi: Dpi,
- pub vbox: ViewBox,
- viewport_stack: Option<Weak<RefCell<Vec<Viewport>>>>,
-}
-
-impl ViewParams {
- pub fn new(dpi: Dpi, view_box_width: f64, view_box_height: f64) -> ViewParams {
- ViewParams {
- dpi,
- vbox: ViewBox::from(Rect::from_size(view_box_width, view_box_height)),
- viewport_stack: None,
- }
- }
-
- pub fn with_units(&self, units: CoordUnits) -> ViewParams {
- match units {
- CoordUnits::ObjectBoundingBox => ViewParams {
- dpi: self.dpi,
- vbox: ViewBox::from(Rect::from_size(1.0, 1.0)),
- viewport_stack: None,
- },
-
- CoordUnits::UserSpaceOnUse => ViewParams {
- dpi: self.dpi,
- vbox: self.vbox,
- viewport_stack: None,
- },
- }
- }
-}
-
-impl Drop for ViewParams {
- fn drop(&mut self) {
- if let Some(ref weak_stack) = self.viewport_stack {
- let stack = weak_stack
- .upgrade()
- .expect("A ViewParams was dropped after its DrawingCtx!?");
- stack.borrow_mut().pop();
- }
- }
-}
-
/// Opaque font options for a DrawingCtx.
///
/// This is used for DrawingCtx::create_pango_context.
@@ -161,13 +109,63 @@ impl<'a> PathHelper<'a> {
}
}
-#[derive(Copy, Clone)]
-struct Viewport {
+/// Holds the size of the current viewport in the user's coordinate system.
+#[derive(Clone)]
+pub struct Viewport {
+ pub dpi: Dpi,
+
+ /// Corners of the current coordinate space.
+ pub vbox: ViewBox,
+
/// The viewport's coordinate system, or "user coordinate system" in SVG terms.
transform: Transform,
+}
- /// Corners of the current coordinate space.
- vbox: ViewBox,
+impl Viewport {
+ /// FIXME: this is just used in Handle::with_height_to_user(), and in length.rs's test suite.
+ /// Find a way to do this without involving a default identity transform.
+ pub fn new(dpi: Dpi, view_box_width: f64, view_box_height: f64) -> Viewport {
+ Viewport {
+ dpi,
+ vbox: ViewBox::from(Rect::from_size(view_box_width, view_box_height)),
+ transform: Default::default(),
+ }
+ }
+
+ /// Creates a new viewport suitable for a certain kind of units.
+ ///
+ /// For `objectBoundingBox`, CSS lengths which are in percentages
+ /// refer to the size of the current viewport. Librsvg implements
+ /// that by keeping the same current transformation matrix, and
+ /// setting a viewport size of (1.0, 1.0).
+ ///
+ /// For `userSpaceOnUse`, we just duplicate the current viewport,
+ /// since that kind of units means to use the current coordinate
+ /// system unchanged.
+ pub fn with_units(&self, units: CoordUnits) -> Viewport {
+ match units {
+ CoordUnits::ObjectBoundingBox => Viewport {
+ dpi: self.dpi,
+ vbox: ViewBox::from(Rect::from_size(1.0, 1.0)),
+ transform: self.transform,
+ },
+
+ CoordUnits::UserSpaceOnUse => Viewport {
+ dpi: self.dpi,
+ vbox: self.vbox,
+ transform: self.transform,
+ },
+ }
+ }
+
+ /// Returns a viewport with a new size for normalizing `Length` values.
+ pub fn with_view_box(&self, width: f64, height: f64) -> Viewport {
+ Viewport {
+ dpi: self.dpi,
+ vbox: ViewBox::from(Rect::from_size(width, height)),
+ transform: self.transform,
+ }
+ }
}
pub struct DrawingCtx {
@@ -182,8 +180,6 @@ pub struct DrawingCtx {
user_language: UserLanguage,
- viewport_stack: Rc<RefCell<Vec<Viewport>>>,
-
drawsub_stack: Vec<Node>,
measuring: bool,
@@ -203,7 +199,7 @@ pub fn draw_tree(
session: Session,
mode: DrawingMode,
cr: &cairo::Context,
- viewport: Rect,
+ viewport_rect: Rect,
user_language: &UserLanguage,
dpi: Dpi,
measuring: bool,
@@ -237,7 +233,7 @@ pub fn draw_tree(
// the top/left of the viewport"
// Translate so (0, 0) is at the viewport's upper-left corner.
- let transform = user_transform.pre_translate(viewport.x0, viewport.y0);
+ let transform = user_transform.pre_translate(viewport_rect.x0, viewport_rect.y0);
// Here we exit immediately if the transform is not valid, since we are in the
// toplevel drawing function. Downstream cases would simply not render the current
@@ -246,13 +242,17 @@ pub fn draw_tree(
cr.set_matrix(valid_transform.into());
// Per the spec, so the viewport has (0, 0) as upper-left.
- let viewport = viewport.translate((-viewport.x0, -viewport.y0));
+ let viewport_rect = viewport_rect.translate((-viewport_rect.x0, -viewport_rect.y0));
+ let initial_viewport = Viewport {
+ dpi,
+ vbox: ViewBox::from(viewport_rect),
+ transform,
+ };
let mut draw_ctx = DrawingCtx::new(
session,
cr,
- transform,
- viewport,
+ &initial_viewport,
user_language.clone(),
dpi,
measuring,
@@ -260,7 +260,13 @@ pub fn draw_tree(
drawsub_stack,
);
- let content_bbox = draw_ctx.draw_node_from_stack(&node, acquired_nodes, &cascaded, false)?;
+ let content_bbox = draw_ctx.draw_node_from_stack(
+ &node,
+ acquired_nodes,
+ &cascaded,
+ &initial_viewport,
+ false,
+ )?;
user_bbox.insert(&content_bbox);
@@ -294,27 +300,20 @@ impl DrawingCtx {
fn new(
session: Session,
cr: &cairo::Context,
- transform: Transform,
- viewport: Rect,
+ initial_viewport: &Viewport,
user_language: UserLanguage,
dpi: Dpi,
measuring: bool,
testing: bool,
drawsub_stack: Vec<Node>,
) -> DrawingCtx {
- let vbox = ViewBox::from(viewport);
- let initial_viewport = Viewport { transform, vbox };
-
- let viewport_stack = vec![initial_viewport];
-
DrawingCtx {
session,
- initial_viewport,
+ initial_viewport: initial_viewport.clone(),
dpi,
cr_stack: Rc::new(RefCell::new(Vec::new())),
cr: cr.clone(),
user_language,
- viewport_stack: Rc::new(RefCell::new(viewport_stack)),
drawsub_stack,
measuring,
testing,
@@ -334,12 +333,11 @@ impl DrawingCtx {
DrawingCtx {
session: self.session.clone(),
- initial_viewport: self.initial_viewport,
+ initial_viewport: self.initial_viewport.clone(),
dpi: self.dpi,
cr_stack,
cr,
user_language: self.user_language.clone(),
- viewport_stack: self.viewport_stack.clone(),
drawsub_stack: self.drawsub_stack.clone(),
measuring: self.measuring,
testing: self.testing,
@@ -432,99 +430,26 @@ impl DrawingCtx {
)?)
}
- fn get_top_viewport(&self) -> Viewport {
- let viewport_stack = self.viewport_stack.borrow();
- *viewport_stack
- .last()
- .expect("viewport_stack must never be empty!")
- }
-
- // Same as `push_coord_units` but doesn't leave the coordinate space pushed
- pub fn get_view_params_for_units(&self, units: CoordUnits) -> ViewParams {
- match units {
- CoordUnits::ObjectBoundingBox => ViewParams {
- dpi: self.dpi,
- vbox: ViewBox::from(Rect::from_size(1.0, 1.0)),
- viewport_stack: None,
- },
-
- CoordUnits::UserSpaceOnUse => ViewParams {
- dpi: self.dpi,
- vbox: self.get_top_viewport().vbox,
- viewport_stack: None,
- },
- }
- }
-
- pub fn push_coord_units(&self, units: CoordUnits) -> ViewParams {
- match units {
- CoordUnits::ObjectBoundingBox => self.push_view_box(1.0, 1.0),
-
- CoordUnits::UserSpaceOnUse => {
- // Duplicate the topmost viewport;
- let viewport = self.get_top_viewport();
- self.push_viewport(viewport)
- }
- }
- }
-
- /// Gets the viewport that was last pushed with `push_view_box()`.
- pub fn get_view_params(&self) -> ViewParams {
- let viewport = self.get_top_viewport();
-
- ViewParams {
- dpi: self.dpi,
- vbox: viewport.vbox,
- viewport_stack: None,
- }
- }
-
- fn push_viewport(&self, viewport: Viewport) -> ViewParams {
- let vbox = viewport.vbox;
-
- self.viewport_stack.borrow_mut().push(viewport);
-
- ViewParams {
- dpi: self.dpi,
- vbox,
- viewport_stack: Some(Rc::downgrade(&self.viewport_stack)),
- }
- }
-
- /// Pushes a viewport size for normalizing `Length` values.
- ///
- /// With the returned `ViewParams`, plus a `ComputedValues`, you can create a
- /// `NormalizeParams` that can be used with calls to `CssLength.to_user()` that
- /// correspond to this viewport.
- ///
- /// The viewport will stay in place, and will be the one returned by
- /// `get_view_params()`, until the returned `ViewParams` is dropped.
- pub fn push_view_box(&self, width: f64, height: f64) -> ViewParams {
- let Viewport { transform, .. } = self.get_top_viewport();
-
- let vbox = ViewBox::from(Rect::from_size(width, height));
- self.push_viewport(Viewport { transform, vbox })
- }
-
/// Creates a new coordinate space inside a viewport and sets a clipping rectangle.
///
/// Note that this actually changes the `draw_ctx.cr`'s transformation to match
/// the new coordinate space, but the old one is not restored after the
- /// result's `ViewParams` is dropped. Thus, this function must be called
+ /// result's `Viewport` is dropped. Thus, this function must be called
/// inside `with_saved_cr` or `draw_ctx.with_discrete_layer`.
pub fn push_new_viewport(
&self,
+ current_viewport: &Viewport,
vbox: Option<ViewBox>,
- viewport: Rect,
+ viewport_rect: Rect,
preserve_aspect_ratio: AspectRatio,
clip_mode: ClipMode,
- ) -> Option<ViewParams> {
+ ) -> Option<Viewport> {
if let ClipMode::ClipToViewport = clip_mode {
- clip_to_rectangle(&self.cr, &viewport);
+ clip_to_rectangle(&self.cr, &viewport_rect);
}
preserve_aspect_ratio
- .viewport_to_viewbox_transform(vbox, &viewport)
+ .viewport_to_viewbox_transform(vbox, &viewport_rect)
.unwrap_or_else(|_e| {
match vbox {
None => unreachable!(
@@ -546,12 +471,11 @@ impl DrawingCtx {
.map(|t| {
self.cr.transform(t.into());
- let top_viewport = self.get_top_viewport();
-
- self.push_viewport(Viewport {
- transform: top_viewport.transform.post_transform(&t),
- vbox: vbox.unwrap_or(top_viewport.vbox),
- })
+ Viewport {
+ dpi: self.dpi,
+ vbox: vbox.unwrap_or(current_viewport.vbox),
+ transform: current_viewport.transform.post_transform(&t),
+ }
})
}
@@ -559,6 +483,7 @@ impl DrawingCtx {
&mut self,
clip_node: &Option<Node>,
acquired_nodes: &mut AcquiredNodes<'_>,
+ viewport: &Viewport,
bbox: &BoundingBox,
) -> Result<(), RenderingError> {
if clip_node.is_none() {
@@ -584,6 +509,7 @@ impl DrawingCtx {
child.draw(
acquired_nodes,
&CascadedValues::clone_with_node(&cascaded, &child),
+ viewport,
self,
true,
)?;
@@ -600,6 +526,7 @@ impl DrawingCtx {
fn generate_cairo_mask(
&mut self,
mask_node: &Node,
+ viewport: &Viewport,
transform: Transform,
bbox: &BoundingBox,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -631,7 +558,7 @@ impl DrawingCtx {
let mask_units = mask.get_units();
let mask_rect = {
- let params = NormalizeParams::new(values, &self.get_view_params_for_units(mask_units));
+ let params = NormalizeParams::new(values, &viewport.with_units(mask_units));
mask.get_rect(&params)
};
@@ -672,11 +599,7 @@ impl DrawingCtx {
mask_cr.transform(ValidTransform::try_from(bbtransform)?.into());
}
- // TODO: this is the last place where push_coord_units() is called. The call to
- // draw_children below assumes that the new coordinate system is in place. Can we
- // pass the ViewParams to with_discrete_layer / Node::draw instead of having them
- // assume the viewport from the DrawingCtx?
- let _params = self.push_coord_units(mask.get_content_units());
+ let mask_viewport = viewport.with_units(mask.get_content_units());
let mut mask_draw_ctx = self.nested(mask_cr);
@@ -691,9 +614,10 @@ impl DrawingCtx {
let res = mask_draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ &mask_viewport,
false,
None,
- &mut |an, dc| mask_node.draw_children(an, &cascaded, dc, false),
+ &mut |an, dc| mask_node.draw_children(an, &cascaded, &mask_viewport, dc, false),
);
res?;
@@ -715,6 +639,7 @@ impl DrawingCtx {
&mut self,
stacking_ctx: &StackingContext,
acquired_nodes: &mut AcquiredNodes<'_>,
+ viewport: &Viewport,
clipping: bool,
clip_rect: Option<Rect>,
draw_fn: &mut dyn FnMut(
@@ -747,6 +672,7 @@ impl DrawingCtx {
self.clip_to_node(
&stacking_ctx.clip_in_user_space,
acquired_nodes,
+ viewport,
&self.empty_bbox(),
)?;
@@ -794,18 +720,16 @@ impl DrawingCtx {
.unwrap(),
)?;
- let params = temporary_draw_ctx.get_view_params();
-
let stroke_paint_source =
Rc::new(filter.stroke_paint_source.to_user_space(
&bbox.rect,
- &params,
+ viewport,
&filter.normalize_values,
));
let fill_paint_source =
Rc::new(filter.fill_paint_source.to_user_space(
&bbox.rect,
- &params,
+ viewport,
&filter.normalize_values,
));
@@ -815,11 +739,12 @@ impl DrawingCtx {
// here and pass them down.
let user_space_params = NormalizeParams::from_values(
&filter.normalize_values,
- &params.with_units(CoordUnits::UserSpaceOnUse),
+ &viewport.with_units(CoordUnits::UserSpaceOnUse),
);
let filtered_surface = temporary_draw_ctx
.run_filters(
+ viewport,
surface_to_filter,
filter,
acquired_nodes,
@@ -850,7 +775,12 @@ impl DrawingCtx {
self.cr.set_matrix(
ValidTransform::try_from(affines.outside_temporary_surface)?.into(),
);
- self.clip_to_node(&stacking_ctx.clip_in_object_space, acquired_nodes, &bbox)?;
+ self.clip_to_node(
+ &stacking_ctx.clip_in_object_space,
+ acquired_nodes,
+ viewport,
+ &bbox,
+ )?;
// Mask
@@ -858,6 +788,7 @@ impl DrawingCtx {
res = res.and_then(|bbox| {
self.generate_cairo_mask(
mask_node,
+ viewport,
affines.for_temporary_surface,
&bbox,
acquired_nodes,
@@ -947,6 +878,7 @@ impl DrawingCtx {
fn run_filters(
&mut self,
+ viewport: &Viewport,
surface_to_filter: SharedImageSurface,
filter: &Filter,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -972,6 +904,7 @@ impl DrawingCtx {
acquired_nodes,
user_space_params,
filter.current_color,
+ viewport,
self,
node_name,
)
@@ -1103,13 +1036,21 @@ impl DrawingCtx {
let cr_pattern = cairo::Context::new(&surface)?;
// Set up transformations to be determined by the contents units
- cr_pattern.set_matrix(ValidTransform::try_from(caffine)?.into());
+
+ let transform = ValidTransform::try_from(caffine)?;
+ cr_pattern.set_matrix(transform.into());
// Draw everything
{
let mut pattern_draw_ctx = self.nested(cr_pattern);
+ let pattern_viewport = Viewport {
+ dpi: self.dpi,
+ vbox: ViewBox::from(Rect::from_size(pattern.width, pattern.height)),
+ transform: *transform,
+ };
+
pattern_draw_ctx
.with_alpha(pattern.opacity, &mut |dc| {
let pattern_cascaded = CascadedValues::new_from_node(pattern_node);
@@ -1128,9 +1069,18 @@ impl DrawingCtx {
dc.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ &pattern_viewport,
false,
None,
- &mut |an, dc| pattern_node.draw_children(an, &pattern_cascaded, dc, false),
+ &mut |an, dc| {
+ pattern_node.draw_children(
+ an,
+ &pattern_cascaded,
+ &pattern_viewport,
+ dc,
+ false,
+ )
+ },
)
})
.map(|_| ())?;
@@ -1260,17 +1210,30 @@ impl DrawingCtx {
layer: &Layer,
acquired_nodes: &mut AcquiredNodes<'_>,
clipping: bool,
+ viewport: &Viewport,
) -> Result<BoundingBox, RenderingError> {
match &layer.kind {
- LayerKind::Shape(shape) => {
- self.draw_shape(shape, &layer.stacking_ctx, acquired_nodes, clipping)
- }
- LayerKind::Text(text) => {
- self.draw_text(text, &layer.stacking_ctx, acquired_nodes, clipping)
- }
- LayerKind::Image(image) => {
- self.draw_image(image, &layer.stacking_ctx, acquired_nodes, clipping)
- }
+ LayerKind::Shape(shape) => self.draw_shape(
+ shape,
+ &layer.stacking_ctx,
+ acquired_nodes,
+ clipping,
+ viewport,
+ ),
+ LayerKind::Text(text) => self.draw_text(
+ text,
+ &layer.stacking_ctx,
+ acquired_nodes,
+ clipping,
+ viewport,
+ ),
+ LayerKind::Image(image) => self.draw_image(
+ image,
+ &layer.stacking_ctx,
+ acquired_nodes,
+ clipping,
+ viewport,
+ ),
}
}
@@ -1280,6 +1243,7 @@ impl DrawingCtx {
stacking_ctx: &StackingContext,
acquired_nodes: &mut AcquiredNodes<'_>,
clipping: bool,
+ viewport: &Viewport,
) -> Result<BoundingBox, RenderingError> {
if shape.extents.is_none() {
return Ok(self.empty_bbox());
@@ -1288,6 +1252,7 @@ impl DrawingCtx {
self.with_discrete_layer(
stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -1349,7 +1314,9 @@ impl DrawingCtx {
PaintTarget::Markers => {
path_helper.unset();
- marker::render_markers_for_shape(shape, dc, an, clipping)?;
+ marker::render_markers_for_shape(
+ shape, viewport, dc, an, clipping,
+ )?;
}
}
}
@@ -1392,6 +1359,7 @@ impl DrawingCtx {
stacking_ctx: &StackingContext,
acquired_nodes: &mut AcquiredNodes<'_>,
clipping: bool,
+ viewport: &Viewport,
) -> Result<BoundingBox, RenderingError> {
let image_width = image.surface.width();
let image_height = image.surface.height();
@@ -1420,13 +1388,18 @@ impl DrawingCtx {
self.with_discrete_layer(
stacking_ctx,
acquired_nodes,
+ viewport, // FIXME: should this be the push_new_viewport below?
clipping,
None,
&mut |_an, dc| {
with_saved_cr(&dc.cr.clone(), || {
- if let Some(_params) =
- dc.push_new_viewport(Some(vbox), image.rect, image.aspect, clip_mode)
- {
+ if let Some(_params) = dc.push_new_viewport(
+ viewport,
+ Some(vbox),
+ image.rect,
+ image.aspect,
+ clip_mode,
+ ) {
dc.paint_surface(&image.surface, image_width, image_height)?;
}
@@ -1542,10 +1515,12 @@ impl DrawingCtx {
stacking_ctx: &StackingContext,
acquired_nodes: &mut AcquiredNodes<'_>,
clipping: bool,
+ viewport: &Viewport,
) -> Result<BoundingBox, RenderingError> {
self.with_discrete_layer(
stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -1617,7 +1592,6 @@ impl DrawingCtx {
) -> Result<SharedImageSurface, RenderingError> {
let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
- let save_initial_viewport = self.initial_viewport;
let save_cr = self.cr.clone();
{
@@ -1625,16 +1599,16 @@ impl DrawingCtx {
cr.set_matrix(ValidTransform::try_from(affine)?.into());
self.cr = cr;
- self.initial_viewport = Viewport {
+ let viewport = Viewport {
+ dpi: self.dpi,
transform: affine,
vbox: ViewBox::from(Rect::from_size(f64::from(width), f64::from(height))),
};
- let _ = self.draw_node_from_stack(node, acquired_nodes, cascaded, false)?;
+ let _ = self.draw_node_from_stack(node, acquired_nodes, cascaded, &viewport, false)?;
}
self.cr = save_cr;
- self.initial_viewport = save_initial_viewport;
Ok(SharedImageSurface::wrap(surface, SurfaceType::SRgb)?)
}
@@ -1644,6 +1618,7 @@ impl DrawingCtx {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
let stack_top = self.drawsub_stack.pop();
@@ -1655,7 +1630,7 @@ impl DrawingCtx {
};
let res = if draw {
- node.draw(acquired_nodes, cascaded, self, clipping)
+ node.draw(acquired_nodes, cascaded, viewport, self, clipping)
} else {
Ok(self.empty_bbox())
};
@@ -1675,6 +1650,7 @@ impl DrawingCtx {
use_rect: Rect,
link: &NodeId,
clipping: bool,
+ viewport: &Viewport,
fill_paint: Arc<PaintSource>,
stroke_paint: Arc<PaintSource>,
) -> Result<BoundingBox, RenderingError> {
@@ -1779,23 +1755,32 @@ impl DrawingCtx {
self.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport, // FIXME: should this be the child_viewport from below?
clipping,
None,
&mut |an, dc| {
- let _params =
- dc.push_new_viewport(viewbox, use_rect, preserve_aspect_ratio, clip_mode);
-
- child.draw_children(
- an,
- &CascadedValues::new_from_values(
- child,
- values,
- Some(fill_paint.clone()),
- Some(stroke_paint.clone()),
- ),
- dc,
- clipping,
- )
+ if let Some(child_viewport) = dc.push_new_viewport(
+ viewport,
+ viewbox,
+ use_rect,
+ preserve_aspect_ratio,
+ clip_mode,
+ ) {
+ child.draw_children(
+ an,
+ &CascadedValues::new_from_values(
+ child,
+ values,
+ Some(fill_paint.clone()),
+ Some(stroke_paint.clone()),
+ ),
+ &child_viewport,
+ dc,
+ clipping,
+ )
+ } else {
+ Ok(dc.empty_bbox())
+ }
},
)
} else {
@@ -1812,6 +1797,7 @@ impl DrawingCtx {
self.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -1823,6 +1809,7 @@ impl DrawingCtx {
Some(fill_paint.clone()),
Some(stroke_paint.clone()),
),
+ viewport,
dc,
clipping,
)
diff --git a/src/element.rs b/src/element.rs
index ca1c0ee4..77e5539c 100644
--- a/src/element.rs
+++ b/src/element.rs
@@ -10,7 +10,7 @@ use crate::bbox::BoundingBox;
use crate::cond::{RequiredExtensions, RequiredFeatures, SystemLanguage};
use crate::css::{Declaration, Origin};
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::error::*;
use crate::filter::Filter;
use crate::filters::{
@@ -63,6 +63,7 @@ pub trait ElementTrait {
_node: &Node,
_acquired_nodes: &mut AcquiredNodes<'_>,
_cascaded: &CascadedValues<'_>,
+ _viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
_clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -372,13 +373,14 @@ impl Element {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
let values = cascaded.get();
if values.is_displayed() {
self.element_data
- .draw(node, acquired_nodes, cascaded, draw_ctx, clipping)
+ .draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
} else {
Ok(draw_ctx.empty_bbox())
}
@@ -393,6 +395,7 @@ impl ElementData {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -454,7 +457,7 @@ impl ElementData {
FeTurbulence(d) => &**d,
};
- data.draw(node, acquired_nodes, cascaded, draw_ctx, clipping)
+ data.draw(node, acquired_nodes, cascaded, viewport, draw_ctx, clipping)
}
}
diff --git a/src/filter.rs b/src/filter.rs
index 05aad8ac..7347b331 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -6,7 +6,7 @@ use std::slice::Iter;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
-use crate::drawing_ctx::{DrawingCtx, ViewParams};
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::ValueErrorKind;
use crate::filter_func::FilterFunction;
@@ -106,12 +106,14 @@ impl FilterValue {
acquired_nodes: &mut AcquiredNodes<'_>,
user_space_params: &NormalizeParams,
current_color: RGBA,
+ viewport: &Viewport,
draw_ctx: &DrawingCtx,
node_being_filtered_name: &str,
) -> Result<FilterSpec, FilterResolveError> {
match *self {
FilterValue::Url(ref node_id) => filter_spec_from_filter_node(
acquired_nodes,
+ viewport,
draw_ctx,
node_id,
node_being_filtered_name,
@@ -131,22 +133,22 @@ impl FilterValue {
/// pre-compute both cases and pass them around.
///
/// This struct needs a better name; I didn't want to make it seem specific to filters by
-/// calling `FiltersViewParams` or `FilterCollectionProcessViewParams`. Maybe the
-/// original [`ViewParams`] should be this struct, with both cases included...
-pub struct ViewParamsGen {
- object_bounding_box: ViewParams,
- user_space_on_use: ViewParams,
+/// calling `FiltersViewport` or `FilterCollectionProcessViewport`. Maybe the
+/// original [`Viewport`] should be this struct, with both cases included...
+struct ViewportGen {
+ object_bounding_box: Viewport,
+ user_space_on_use: Viewport,
}
-impl ViewParamsGen {
- pub fn new(draw_ctx: &DrawingCtx) -> Self {
- ViewParamsGen {
- object_bounding_box: draw_ctx.get_view_params_for_units(CoordUnits::ObjectBoundingBox),
- user_space_on_use: draw_ctx.get_view_params_for_units(CoordUnits::UserSpaceOnUse),
+impl ViewportGen {
+ pub fn new(viewport: &Viewport) -> Self {
+ ViewportGen {
+ object_bounding_box: viewport.with_units(CoordUnits::ObjectBoundingBox),
+ user_space_on_use: viewport.with_units(CoordUnits::UserSpaceOnUse),
}
}
- fn get(&self, units: CoordUnits) -> &ViewParams {
+ fn get(&self, units: CoordUnits) -> &Viewport {
match units {
CoordUnits::ObjectBoundingBox => &self.object_bounding_box,
CoordUnits::UserSpaceOnUse => &self.user_space_on_use,
@@ -158,7 +160,7 @@ fn extract_filter_from_filter_node(
filter_node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
session: &Session,
- filter_view_params: &ViewParamsGen,
+ filter_view_params: &ViewportGen,
) -> Result<FilterSpec, FilterResolveError> {
assert!(is_element_of_type!(filter_node, Filter));
@@ -220,13 +222,14 @@ fn extract_filter_from_filter_node(
fn filter_spec_from_filter_node(
acquired_nodes: &mut AcquiredNodes<'_>,
+ viewport: &Viewport,
draw_ctx: &DrawingCtx,
node_id: &NodeId,
node_being_filtered_name: &str,
) -> Result<FilterSpec, FilterResolveError> {
let session = draw_ctx.session().clone();
- let filter_view_params = ViewParamsGen::new(draw_ctx);
+ let filter_view_params = ViewportGen::new(viewport);
acquired_nodes
.acquire(node_id)
diff --git a/src/gradient.rs b/src/gradient.rs
index 04420400..311343cb 100644
--- a/src/gradient.rs
+++ b/src/gradient.rs
@@ -7,7 +7,7 @@ use markup5ever::{
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId, NodeStack};
-use crate::drawing_ctx::ViewParams;
+use crate::drawing_ctx::Viewport;
use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -654,12 +654,12 @@ impl ResolvedGradient {
pub fn to_user_space(
&self,
object_bbox: &Option<Rect>,
- current_params: &ViewParams,
+ viewport: &Viewport,
values: &NormalizeValues,
) -> Option<UserSpaceGradient> {
let units = self.units.0;
let transform = rect_to_transform(object_bbox, units).ok()?;
- let view_params = current_params.with_units(units);
+ let view_params = viewport.with_units(units);
let params = NormalizeParams::from_values(values, &view_params);
let gradient_transform = self.transform.to_transform();
diff --git a/src/handle.rs b/src/handle.rs
index 36de859d..86428008 100644
--- a/src/handle.rs
+++ b/src/handle.rs
@@ -9,7 +9,7 @@ use crate::bbox::BoundingBox;
use crate::css::{Origin, Stylesheet};
use crate::document::{AcquiredNodes, Document, NodeId};
use crate::dpi::Dpi;
-use crate::drawing_ctx::{draw_tree, with_saved_cr, DrawingMode, ViewParams};
+use crate::drawing_ctx::{draw_tree, with_saved_cr, DrawingMode, Viewport};
use crate::error::{DefsLookupErrorKind, LoadingError, RenderingError};
use crate::length::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
@@ -124,7 +124,7 @@ impl Handle {
let width = dimensions.width;
let height = dimensions.height;
- let view_params = ViewParams::new(dpi, 0.0, 0.0);
+ let view_params = Viewport::new(dpi, 0.0, 0.0);
let root = self.document.root();
let cascaded = CascadedValues::new_from_node(&root);
let values = cascaded.get();
diff --git a/src/image.rs b/src/image.rs
index 282bb3e4..ece7f741 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -5,7 +5,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::aspect_ratio::AspectRatio;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::element::{set_attribute, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -50,6 +50,7 @@ impl ElementTrait for Image {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -71,8 +72,7 @@ impl ElementTrait for Image {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, viewport);
let x = values.x().0.to_user(&params);
let y = values.y().0.to_user(&params);
@@ -114,6 +114,6 @@ impl ElementTrait for Image {
stacking_ctx,
};
- draw_ctx.draw_layer(&layer, acquired_nodes, clipping)
+ draw_ctx.draw_layer(&layer, acquired_nodes, clipping, viewport)
}
}
diff --git a/src/length.rs b/src/length.rs
index 5d91b166..56156d41 100644
--- a/src/length.rs
+++ b/src/length.rs
@@ -48,7 +48,7 @@ use std::fmt;
use std::marker::PhantomData;
use crate::dpi::Dpi;
-use crate::drawing_ctx::ViewParams;
+use crate::drawing_ctx::Viewport;
use crate::error::*;
use crate::parsers::{finite_f32, Parse};
use crate::properties::{ComputedValues, FontSize};
@@ -327,17 +327,17 @@ pub struct NormalizeParams {
impl NormalizeParams {
/// Extracts the information needed to normalize [`Length`] values from a set of
- /// [`ComputedValues`] and the viewport size in [`ViewParams`].
- pub fn new(values: &ComputedValues, params: &ViewParams) -> NormalizeParams {
+ /// [`ComputedValues`] and the viewport size in [`Viewport`].
+ pub fn new(values: &ComputedValues, viewport: &Viewport) -> NormalizeParams {
let v = NormalizeValues::new(values);
- NormalizeParams::from_values(&v, params)
+ NormalizeParams::from_values(&v, viewport)
}
- pub fn from_values(v: &NormalizeValues, params: &ViewParams) -> NormalizeParams {
+ pub fn from_values(v: &NormalizeValues, viewport: &Viewport) -> NormalizeParams {
NormalizeParams {
- vbox: params.vbox,
- font_size: font_size_from_values(v, params.dpi),
- dpi: params.dpi,
+ vbox: viewport.vbox,
+ font_size: font_size_from_values(v, viewport.dpi),
+ dpi: viewport.dpi,
}
}
@@ -641,7 +641,7 @@ mod tests {
#[test]
fn normalize_default_works() {
- let view_params = ViewParams::new(Dpi::new(40.0, 40.0), 100.0, 100.0);
+ let view_params = Viewport::new(Dpi::new(40.0, 40.0), 100.0, 100.0);
let values = ComputedValues::default();
let params = NormalizeParams::new(&values, &view_params);
@@ -653,7 +653,7 @@ mod tests {
#[test]
fn normalize_absolute_units_works() {
- let view_params = ViewParams::new(Dpi::new(40.0, 50.0), 100.0, 100.0);
+ let view_params = Viewport::new(Dpi::new(40.0, 50.0), 100.0, 100.0);
let values = ComputedValues::default();
let params = NormalizeParams::new(&values, &view_params);
@@ -686,7 +686,7 @@ mod tests {
#[test]
fn normalize_percent_works() {
- let view_params = ViewParams::new(Dpi::new(40.0, 40.0), 100.0, 200.0);
+ let view_params = Viewport::new(Dpi::new(40.0, 40.0), 100.0, 200.0);
let values = ComputedValues::default();
let params = NormalizeParams::new(&values, &view_params);
@@ -702,7 +702,7 @@ mod tests {
#[test]
fn normalize_font_em_ex_works() {
- let view_params = ViewParams::new(Dpi::new(40.0, 40.0), 100.0, 200.0);
+ let view_params = Viewport::new(Dpi::new(40.0, 40.0), 100.0, 200.0);
let values = ComputedValues::default();
let params = NormalizeParams::new(&values, &view_params);
diff --git a/src/marker.rs b/src/marker.rs
index 63b5843f..ba2006c6 100644
--- a/src/marker.rs
+++ b/src/marker.rs
@@ -10,7 +10,7 @@ use crate::angle::Angle;
use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::element::{set_attribute, ElementTrait};
use crate::error::*;
use crate::float_eq_cairo::ApproxEqCairo;
@@ -106,6 +106,7 @@ impl Marker {
&self,
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
xpos: f64,
ypos: f64,
@@ -121,8 +122,7 @@ impl Marker {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, viewport);
let marker_width = self.width.to_user(&params);
let marker_height = self.height.to_user(&params);
@@ -151,7 +151,7 @@ impl Marker {
transform = transform.pre_scale(line_width, line_width);
}
- let content_view_params = if let Some(vbox) = self.vbox {
+ let content_viewport = if let Some(vbox) = self.vbox {
if vbox.is_empty() {
return Ok(draw_ctx.empty_bbox());
}
@@ -163,12 +163,12 @@ impl Marker {
let (vb_width, vb_height) = vbox.size();
transform = transform.pre_scale(r.width() / vb_width, r.height() / vb_height);
- draw_ctx.push_view_box(vb_width, vb_height)
+ viewport.with_view_box(vb_width, vb_height)
} else {
- draw_ctx.push_view_box(marker_width, marker_height)
+ viewport.with_view_box(marker_width, marker_height)
};
- let content_params = NormalizeParams::new(values, &content_view_params);
+ let content_params = NormalizeParams::new(values, &content_viewport);
transform = transform.pre_translate(
-self.ref_x.to_user(&content_params),
@@ -188,12 +188,14 @@ impl Marker {
let stacking_ctx =
StackingContext::new(draw_ctx.session(), acquired_nodes, &elt, transform, values);
+ // FIXME: use content_viewport
draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ &content_viewport,
clipping,
clip,
- &mut |an, dc| node.draw_children(an, &cascaded, dc, clipping),
+ &mut |an, dc| node.draw_children(an, &cascaded, &content_viewport, dc, clipping),
)
}
}
@@ -578,6 +580,7 @@ enum MarkerType {
}
fn emit_marker_by_node(
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
acquired_nodes: &mut AcquiredNodes<'_>,
marker: &layout::Marker,
@@ -597,6 +600,7 @@ fn emit_marker_by_node(
marker_elt.render(
node,
acquired_nodes,
+ viewport,
draw_ctx,
xpos,
ypos,
@@ -645,6 +649,7 @@ where
pub fn render_markers_for_shape(
shape: &Shape,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
acquired_nodes: &mut AcquiredNodes<'_>,
clipping: bool,
@@ -672,6 +677,7 @@ pub fn render_markers_for_shape(
if marker.node_ref.is_some() {
emit_marker_by_node(
+ viewport,
draw_ctx,
acquired_nodes,
marker,
diff --git a/src/node.rs b/src/node.rs
index 1eab97a0..1db4ea52 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -14,7 +14,7 @@ use std::sync::Arc;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::element::*;
use crate::error::*;
use crate::paint_server::PaintSource;
@@ -307,6 +307,7 @@ pub trait NodeDraw {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError>;
@@ -315,6 +316,7 @@ pub trait NodeDraw {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError>;
@@ -325,12 +327,13 @@ impl NodeDraw for Node {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
match *self.borrow() {
NodeData::Element(ref e) => {
- match e.draw(self, acquired_nodes, cascaded, draw_ctx, clipping) {
+ match e.draw(self, acquired_nodes, cascaded, viewport, draw_ctx, clipping) {
Ok(bbox) => Ok(bbox),
// https://www.w3.org/TR/css-transforms-1/#transform-function-lists
@@ -352,6 +355,7 @@ impl NodeDraw for Node {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -362,6 +366,7 @@ impl NodeDraw for Node {
&child,
acquired_nodes,
&CascadedValues::clone_with_node(cascaded, &child),
+ viewport,
clipping,
)?;
bbox.insert(&child_bbox);
diff --git a/src/paint_server.rs b/src/paint_server.rs
index aa4a1768..01393b8d 100644
--- a/src/paint_server.rs
+++ b/src/paint_server.rs
@@ -5,7 +5,7 @@ use std::sync::Arc;
use cssparser::Parser;
use crate::document::{AcquiredNodes, NodeId};
-use crate::drawing_ctx::ViewParams;
+use crate::drawing_ctx::Viewport;
use crate::element::ElementData;
use crate::error::{AcquireError, NodeIdError, ParseError, ValueErrorKind};
use crate::gradient::{ResolvedGradient, UserSpaceGradient};
@@ -243,7 +243,7 @@ impl PaintSource {
pub fn to_user_space(
&self,
object_bbox: &Option<Rect>,
- current_params: &ViewParams,
+ viewport: &Viewport,
values: &NormalizeValues,
) -> UserSpacePaintSource {
match *self {
@@ -251,7 +251,7 @@ impl PaintSource {
PaintSource::SolidColor(c) => UserSpacePaintSource::SolidColor(c),
PaintSource::Gradient(ref g, c) => {
- match (g.to_user_space(object_bbox, current_params, values), c) {
+ match (g.to_user_space(object_bbox, viewport, values), c) {
(Some(gradient), c) => UserSpacePaintSource::Gradient(gradient, c),
(None, Some(c)) => UserSpacePaintSource::SolidColor(c),
(None, None) => UserSpacePaintSource::None,
@@ -259,7 +259,7 @@ impl PaintSource {
}
PaintSource::Pattern(ref p, c) => {
- match (p.to_user_space(object_bbox, current_params, values), c) {
+ match (p.to_user_space(object_bbox, viewport, values), c) {
(Some(pattern), c) => UserSpacePaintSource::Pattern(pattern, c),
(None, Some(c)) => UserSpacePaintSource::SolidColor(c),
(None, None) => UserSpacePaintSource::None,
diff --git a/src/pattern.rs b/src/pattern.rs
index 922df110..8a10317f 100644
--- a/src/pattern.rs
+++ b/src/pattern.rs
@@ -5,7 +5,7 @@ use markup5ever::{expanded_name, local_name, namespace_url, ns};
use crate::aspect_ratio::*;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNode, AcquiredNodes, NodeId, NodeStack};
-use crate::drawing_ctx::ViewParams;
+use crate::drawing_ctx::Viewport;
use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -353,12 +353,12 @@ impl ResolvedPattern {
pub fn to_user_space(
&self,
object_bbox: &Option<Rect>,
- current_params: &ViewParams,
+ viewport: &Viewport,
values: &NormalizeValues,
) -> Option<UserSpacePattern> {
let node_with_children = self.node_with_children()?;
- let view_params = current_params.with_units(self.units.0);
+ let view_params = viewport.with_units(self.units.0);
let params = NormalizeParams::from_values(values, &view_params);
let rect = self.get_rect(&params);
diff --git a/src/shapes.rs b/src/shapes.rs
index ef01ed4d..2aabd174 100644
--- a/src/shapes.rs
+++ b/src/shapes.rs
@@ -8,7 +8,7 @@ use std::rc::Rc;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
-use crate::drawing_ctx::DrawingCtx;
+use crate::drawing_ctx::{DrawingCtx, Viewport};
use crate::element::{set_attribute, ElementTrait};
use crate::error::*;
use crate::iri::Iri;
@@ -47,12 +47,12 @@ fn draw_basic_shape(
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, viewport);
let shape_def = basic_shape.make_shape(&params, values);
let is_visible = values.is_visible();
@@ -120,8 +120,8 @@ fn draw_basic_shape(
let normalize_values = NormalizeValues::new(values);
- let stroke_paint = stroke_paint.to_user_space(&extents, &view_params, &normalize_values);
- let fill_paint = fill_paint.to_user_space(&extents, &view_params, &normalize_values);
+ let stroke_paint = stroke_paint.to_user_space(&extents, viewport, &normalize_values);
+ let fill_paint = fill_paint.to_user_space(&extents, viewport, &normalize_values);
let shape = Box::new(Shape {
path: shape_def.path,
@@ -153,7 +153,7 @@ fn draw_basic_shape(
stacking_ctx,
};
- draw_ctx.draw_layer(&layer, acquired_nodes, clipping)
+ draw_ctx.draw_layer(&layer, acquired_nodes, clipping, viewport)
}
macro_rules! impl_draw {
@@ -163,10 +163,19 @@ macro_rules! impl_draw {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
- draw_basic_shape(self, node, acquired_nodes, cascaded, draw_ctx, clipping)
+ draw_basic_shape(
+ self,
+ node,
+ acquired_nodes,
+ cascaded,
+ viewport,
+ draw_ctx,
+ clipping,
+ )
}
};
}
diff --git a/src/structure.rs b/src/structure.rs
index 8700bcb4..7e09ed1a 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -6,7 +6,7 @@ use crate::aspect_ratio::*;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::{AcquiredNodes, NodeId};
-use crate::drawing_ctx::{ClipMode, DrawingCtx, ViewParams};
+use crate::drawing_ctx::{ClipMode, DrawingCtx, Viewport};
use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::href::{is_href, set_href};
@@ -29,6 +29,7 @@ impl ElementTrait for Group {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -46,9 +47,10 @@ impl ElementTrait for Group {
draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
- &mut |an, dc| node.draw_children(an, cascaded, dc, clipping),
+ &mut |an, dc| node.draw_children(an, cascaded, viewport, dc, clipping),
)
}
}
@@ -72,6 +74,7 @@ impl ElementTrait for Switch {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -89,6 +92,7 @@ impl ElementTrait for Switch {
draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -99,6 +103,7 @@ impl ElementTrait for Switch {
child.draw(
an,
&CascadedValues::clone_with_node(cascaded, &child),
+ viewport,
dc,
clipping,
)
@@ -214,16 +219,16 @@ impl Svg {
self.preserve_aspect_ratio
}
- fn push_viewport(
+ fn make_svg_viewport(
&self,
node: &Node,
cascaded: &CascadedValues<'_>,
+ current_viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
- ) -> Option<ViewParams> {
+ ) -> Option<Viewport> {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, current_viewport);
let has_parent = node.parent().is_some();
@@ -262,7 +267,13 @@ impl Svg {
)
};
- draw_ctx.push_new_viewport(vbox, viewport, self.preserve_aspect_ratio, clip_mode)
+ draw_ctx.push_new_viewport(
+ current_viewport,
+ vbox,
+ viewport,
+ self.preserve_aspect_ratio,
+ clip_mode,
+ )
}
}
@@ -286,6 +297,7 @@ impl ElementTrait for Svg {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -303,11 +315,15 @@ impl ElementTrait for Svg {
draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport, // FIXME: should this be the svg_viewport from below?
clipping,
None,
&mut |an, dc| {
- let _params = self.push_viewport(node, cascaded, dc);
- node.draw_children(an, cascaded, dc, clipping)
+ if let Some(svg_viewport) = self.make_svg_viewport(node, cascaded, viewport, dc) {
+ node.draw_children(an, cascaded, &svg_viewport, dc, clipping)
+ } else {
+ Ok(dc.empty_bbox())
+ }
},
)
}
@@ -376,13 +392,13 @@ impl ElementTrait for Use {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
if let Some(link) = self.link.as_ref() {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, viewport);
let rect = self.get_rect(&params);
let stroke_paint = values.stroke().0.resolve(
@@ -410,6 +426,7 @@ impl ElementTrait for Use {
rect,
link,
clipping,
+ viewport,
fill_paint,
stroke_paint,
)
@@ -569,6 +586,7 @@ impl ElementTrait for Link {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
@@ -605,9 +623,10 @@ impl ElementTrait for Link {
draw_ctx.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
- &mut |an, dc| node.draw_children(an, &cascaded, dc, clipping),
+ &mut |an, dc| node.draw_children(an, &cascaded, viewport, dc, clipping),
)
}
}
diff --git a/src/text.rs b/src/text.rs
index a47c2de4..a0e51fc6 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -9,7 +9,7 @@ use std::sync::Arc;
use crate::bbox::BoundingBox;
use crate::document::{AcquiredNodes, NodeId};
-use crate::drawing_ctx::{create_pango_context, DrawingCtx, FontOptions, ViewParams};
+use crate::drawing_ctx::{create_pango_context, DrawingCtx, FontOptions, Viewport};
use crate::element::{set_attribute, ElementData, ElementTrait};
use crate::error::*;
use crate::layout::{self, FontProperties, Layer, LayerKind, StackingContext, Stroke, TextSpan};
@@ -39,7 +39,7 @@ struct LayoutContext {
font_options: FontOptions,
/// For normalizing lengths.
- view_params: ViewParams,
+ viewport: Viewport,
/// Session metadata for the document
session: Session,
@@ -193,7 +193,7 @@ impl PositionedChunk {
let mut chunk_bounds: Option<Rect> = None;
for mspan in &measured.spans {
- let params = NormalizeParams::new(&mspan.values, &layout_context.view_params);
+ let params = NormalizeParams::new(&mspan.values, &layout_context.viewport);
let layout = mspan.layout.clone();
let layout_size = mspan.layout_size;
@@ -359,7 +359,7 @@ impl MeasuredSpan {
fn from_span(layout_context: &LayoutContext, span: &Span) -> Option<MeasuredSpan> {
let values = span.values.clone();
- let params = NormalizeParams::new(&values, &layout_context.view_params);
+ let params = NormalizeParams::new(&values, &layout_context.viewport);
let properties = FontProperties::new(&values, &params);
@@ -454,7 +454,7 @@ impl PositionedSpan {
layout_context: &LayoutContext,
acquired_nodes: &mut AcquiredNodes<'_>,
) -> LayoutSpan {
- let params = NormalizeParams::new(&self.values, &layout_context.view_params);
+ let params = NormalizeParams::new(&self.values, &layout_context.viewport);
let layout = self.layout.clone();
let is_visible = self.values.is_visible();
@@ -726,7 +726,7 @@ impl Text {
let mut chunks = Vec::new();
let values = cascaded.get();
- let params = NormalizeParams::new(values, &layout_context.view_params);
+ let params = NormalizeParams::new(values, &layout_context.viewport);
chunks.push(Chunk::new(values, Some(x), Some(y)));
@@ -766,12 +766,12 @@ impl ElementTrait for Text {
node: &Node,
acquired_nodes: &mut AcquiredNodes<'_>,
cascaded: &CascadedValues<'_>,
+ viewport: &Viewport,
draw_ctx: &mut DrawingCtx,
clipping: bool,
) -> Result<BoundingBox, RenderingError> {
let values = cascaded.get();
- let view_params = draw_ctx.get_view_params();
- let params = NormalizeParams::new(values, &view_params);
+ let params = NormalizeParams::new(values, viewport);
let elt = node.borrow_element();
@@ -790,7 +790,7 @@ impl ElementTrait for Text {
writing_mode: values.writing_mode(),
transform,
font_options: draw_ctx.get_font_options(),
- view_params,
+ viewport: viewport.clone(),
session: draw_ctx.session().clone(),
};
@@ -841,12 +841,12 @@ impl ElementTrait for Text {
let stroke_paint = span.stroke_paint.to_user_space(
&text_bbox.rect,
- &layout_context.view_params,
+ &layout_context.viewport,
&normalize_values,
);
let fill_paint = span.fill_paint.to_user_space(
&text_bbox.rect,
- &layout_context.view_params,
+ &layout_context.viewport,
&normalize_values,
);
@@ -876,7 +876,7 @@ impl ElementTrait for Text {
stacking_ctx,
};
- draw_ctx.draw_layer(&layer, acquired_nodes, clipping)
+ draw_ctx.draw_layer(&layer, acquired_nodes, clipping, viewport)
}
}
@@ -977,7 +977,7 @@ impl TSpan {
return;
}
- let params = NormalizeParams::new(values, &layout_context.view_params);
+ let params = NormalizeParams::new(values, &layout_context.viewport);
let x = self.x.map(|l| l.to_user(&params));
let y = self.y.map(|l| l.to_user(&params));