summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2023-03-28 21:21:33 -0600
committerMarge Bot <marge-bot@gnome.org>2023-03-30 22:38:06 +0000
commit8d678639b274014f0ccc3d422e7ae9bd6eb286ab (patch)
tree41841be67093e2defc3810272db907923126272d
parent63c5f8b7812a27cbdb7ef35334bf94057cd6c419 (diff)
downloadlibrsvg-8d678639b274014f0ccc3d422e7ae9bd6eb286ab.tar.gz
Pass the current Viewport around as arguments to the drawing functions
- All the drawing functions get a new argument of type &Viewport. The idea is that the caller computes a new Viewport and just passes a reference to it. The viewport stack is implied by the call stack, instead of being represented as mutable state in DrawingCtx. This removes DrawingCtx::get_viewport() and ::get_top_viewport(). - Rename Svg::push_viewport() to make_svg_viewport(). - Remove DrawingCtx::get_viewport_for_units(); replace it with Viewport::from_units(). - Remove DrawingCtx::push_coord_units(), which was just being called in generate_cairo_mask() - this takes care of the TODO that mentioned exactly that goal. - Remove DrawingCtx::push_view_box(); replace it with Viewport::with_view_box(). Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/821>
-rw-r--r--src/drawing_ctx.rs308
-rw-r--r--src/element.rs9
-rw-r--r--src/filter.rs11
-rw-r--r--src/image.rs8
-rw-r--r--src/marker.rs18
-rw-r--r--src/node.rs9
-rw-r--r--src/shapes.rs23
-rw-r--r--src/structure.rs39
-rw-r--r--src/text.rs8
9 files changed, 239 insertions, 194 deletions
diff --git a/src/drawing_ctx.rs b/src/drawing_ctx.rs
index 0597bea3..92860630 100644
--- a/src/drawing_ctx.rs
+++ b/src/drawing_ctx.rs
@@ -146,6 +146,16 @@ impl Viewport {
}
}
+ /// 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 {
@@ -163,6 +173,16 @@ impl Viewport {
},
}
}
+
+ /// 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,
+ viewport_stack: None,
+ }
+ }
}
pub struct DrawingCtx {
@@ -198,7 +218,7 @@ pub fn draw_tree(
session: Session,
mode: DrawingMode,
cr: &cairo::Context,
- viewport: Rect,
+ viewport_rect: Rect,
user_language: &UserLanguage,
dpi: Dpi,
measuring: bool,
@@ -232,7 +252,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
@@ -241,13 +261,18 @@ 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,
+ viewport_stack: None,
+ };
let mut draw_ctx = DrawingCtx::new(
session,
cr,
- transform,
- viewport,
+ &initial_viewport,
user_language.clone(),
dpi,
measuring,
@@ -255,7 +280,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);
@@ -289,27 +320,18 @@ 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 {
- dpi,
- vbox,
- transform,
- viewport_stack: None,
- };
-
let viewport_stack = vec![initial_viewport.clone()];
DrawingCtx {
session,
- initial_viewport,
+ initial_viewport: initial_viewport.clone(),
dpi,
cr_stack: Rc::new(RefCell::new(Vec::new())),
cr: cr.clone(),
@@ -432,90 +454,6 @@ impl DrawingCtx {
)?)
}
- fn get_top_viewport(&self) -> Viewport {
- let viewport_stack = self.viewport_stack.borrow();
- let viewport = viewport_stack
- .last()
- .expect("viewport_stack must never be empty!");
- Viewport {
- viewport_stack: None,
- ..*viewport
- }
- }
-
- // Same as `push_coord_units` but doesn't leave the coordinate space pushed
- pub fn get_viewport_for_units(&self, units: CoordUnits) -> Viewport {
- let transform = self.get_top_viewport().transform;
-
- match units {
- CoordUnits::ObjectBoundingBox => Viewport {
- dpi: self.dpi,
- vbox: ViewBox::from(Rect::from_size(1.0, 1.0)),
- transform,
- viewport_stack: None,
- },
-
- CoordUnits::UserSpaceOnUse => Viewport {
- dpi: self.dpi,
- vbox: self.get_top_viewport().vbox,
- transform,
- viewport_stack: None,
- },
- }
- }
-
- pub fn push_coord_units(&self, units: CoordUnits) -> Viewport {
- 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.
- pub fn get_viewport(&self) -> Viewport {
- self.get_top_viewport()
- }
-
- fn push_viewport(&self, viewport: Viewport) -> Viewport {
- let vbox = viewport.vbox;
- let transform = viewport.transform;
-
- self.viewport_stack.borrow_mut().push(viewport);
-
- Viewport {
- dpi: self.dpi,
- vbox,
- transform,
- viewport_stack: Some(Rc::downgrade(&self.viewport_stack)),
- }
- }
-
- /// Pushes a viewport size for normalizing `Length` values.
- ///
- /// With the returned `Viewport`, 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
- /// [`DrawingCtx::get_viewport()`], until the returned `Viewport` is dropped.
- pub fn push_view_box(&self, width: f64, height: f64) -> Viewport {
- let top_viewport = self.get_top_viewport();
-
- let vbox = ViewBox::from(Rect::from_size(width, height));
- let viewport = Viewport {
- dpi: top_viewport.dpi,
- vbox,
- transform: top_viewport.transform,
- viewport_stack: None,
- };
- self.push_viewport(viewport)
- }
-
/// 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
@@ -524,6 +462,7 @@ impl DrawingCtx {
/// inside `with_saved_cr` or `draw_ctx.with_discrete_layer`.
pub fn push_new_viewport(
&self,
+ current_viewport: &Viewport,
vbox: Option<ViewBox>,
viewport_rect: Rect,
preserve_aspect_ratio: AspectRatio,
@@ -556,14 +495,12 @@ impl DrawingCtx {
.map(|t| {
self.cr.transform(t.into());
- let top_viewport = self.get_top_viewport();
-
- self.push_viewport(Viewport {
+ Viewport {
dpi: self.dpi,
- vbox: vbox.unwrap_or(top_viewport.vbox),
- transform: top_viewport.transform.post_transform(&t),
+ vbox: vbox.unwrap_or(current_viewport.vbox),
+ transform: current_viewport.transform.post_transform(&t),
viewport_stack: None,
- })
+ }
})
}
@@ -571,6 +508,7 @@ impl DrawingCtx {
&mut self,
clip_node: &Option<Node>,
acquired_nodes: &mut AcquiredNodes<'_>,
+ viewport: &Viewport,
bbox: &BoundingBox,
) -> Result<(), RenderingError> {
if clip_node.is_none() {
@@ -596,6 +534,7 @@ impl DrawingCtx {
child.draw(
acquired_nodes,
&CascadedValues::clone_with_node(&cascaded, &child),
+ viewport,
self,
true,
)?;
@@ -612,6 +551,7 @@ impl DrawingCtx {
fn generate_cairo_mask(
&mut self,
mask_node: &Node,
+ viewport: &Viewport,
transform: Transform,
bbox: &BoundingBox,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -643,7 +583,7 @@ impl DrawingCtx {
let mask_units = mask.get_units();
let mask_rect = {
- let params = NormalizeParams::new(values, &self.get_viewport_for_units(mask_units));
+ let params = NormalizeParams::new(values, &viewport.with_units(mask_units));
mask.get_rect(&params)
};
@@ -684,11 +624,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 Viewport 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);
@@ -703,9 +639,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?;
@@ -727,6 +664,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(
@@ -759,6 +697,7 @@ impl DrawingCtx {
self.clip_to_node(
&stacking_ctx.clip_in_user_space,
acquired_nodes,
+ viewport,
&self.empty_bbox(),
)?;
@@ -806,18 +745,16 @@ impl DrawingCtx {
.unwrap(),
)?;
- let params = temporary_draw_ctx.get_viewport();
-
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,
));
@@ -827,11 +764,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,
@@ -862,7 +800,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
@@ -870,6 +813,7 @@ impl DrawingCtx {
res = res.and_then(|bbox| {
self.generate_cairo_mask(
mask_node,
+ viewport,
affines.for_temporary_surface,
&bbox,
acquired_nodes,
@@ -959,6 +903,7 @@ impl DrawingCtx {
fn run_filters(
&mut self,
+ viewport: &Viewport,
surface_to_filter: SharedImageSurface,
filter: &Filter,
acquired_nodes: &mut AcquiredNodes<'_>,
@@ -984,6 +929,7 @@ impl DrawingCtx {
acquired_nodes,
user_space_params,
filter.current_color,
+ viewport,
self,
node_name,
)
@@ -1115,13 +1061,22 @@ 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,
+ viewport_stack: None,
+ };
+
pattern_draw_ctx
.with_alpha(pattern.opacity, &mut |dc| {
let pattern_cascaded = CascadedValues::new_from_node(pattern_node);
@@ -1140,9 +1095,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(|_| ())?;
@@ -1272,17 +1236,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,
+ ),
}
}
@@ -1292,6 +1269,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());
@@ -1300,6 +1278,7 @@ impl DrawingCtx {
self.with_discrete_layer(
stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -1361,7 +1340,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,
+ )?;
}
}
}
@@ -1404,6 +1385,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();
@@ -1432,13 +1414,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)?;
}
@@ -1554,10 +1541,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| {
@@ -1629,7 +1618,6 @@ impl DrawingCtx {
) -> Result<SharedImageSurface, RenderingError> {
let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
- let save_initial_viewport = self.initial_viewport.clone();
let save_cr = self.cr.clone();
{
@@ -1637,18 +1625,17 @@ 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))),
viewport_stack: None,
};
- 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)?)
}
@@ -1658,6 +1645,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();
@@ -1669,7 +1657,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())
};
@@ -1689,6 +1677,7 @@ impl DrawingCtx {
use_rect: Rect,
link: &NodeId,
clipping: bool,
+ viewport: &Viewport,
fill_paint: Arc<PaintSource>,
stroke_paint: Arc<PaintSource>,
) -> Result<BoundingBox, RenderingError> {
@@ -1793,23 +1782,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 {
@@ -1826,6 +1824,7 @@ impl DrawingCtx {
self.with_discrete_layer(
&stacking_ctx,
acquired_nodes,
+ viewport,
clipping,
None,
&mut |an, dc| {
@@ -1837,6 +1836,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 ba2ebb14..7347b331 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -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,
@@ -139,10 +141,10 @@ struct ViewportGen {
}
impl ViewportGen {
- pub fn new(draw_ctx: &DrawingCtx) -> Self {
+ pub fn new(viewport: &Viewport) -> Self {
ViewportGen {
- object_bounding_box: draw_ctx.get_viewport_for_units(CoordUnits::ObjectBoundingBox),
- user_space_on_use: draw_ctx.get_viewport_for_units(CoordUnits::UserSpaceOnUse),
+ object_bounding_box: viewport.with_units(CoordUnits::ObjectBoundingBox),
+ user_space_on_use: viewport.with_units(CoordUnits::UserSpaceOnUse),
}
}
@@ -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 = ViewportGen::new(draw_ctx);
+ let filter_view_params = ViewportGen::new(viewport);
acquired_nodes
.acquire(node_id)
diff --git a/src/image.rs b/src/image.rs
index 1d85c98f..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 viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &viewport);
+ 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/marker.rs b/src/marker.rs
index 73b5a6aa..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 viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &viewport);
+ let params = NormalizeParams::new(values, viewport);
let marker_width = self.width.to_user(&params);
let marker_height = self.height.to_user(&params);
@@ -163,9 +163,9 @@ 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_viewport);
@@ -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/shapes.rs b/src/shapes.rs
index a06d277b..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 viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &viewport);
+ 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, &viewport, &normalize_values);
- let fill_paint = fill_paint.to_user_space(&extents, &viewport, &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 ad06253b..7e09ed1a 100644
--- a/src/structure.rs
+++ b/src/structure.rs
@@ -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<Viewport> {
let values = cascaded.get();
- let current_viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &current_viewport);
+ 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 viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &viewport);
+ 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 203bb490..a0e51fc6 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -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 viewport = draw_ctx.get_viewport();
- let params = NormalizeParams::new(values, &viewport);
+ 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(),
- viewport,
+ viewport: viewport.clone(),
session: draw_ctx.session().clone(),
};
@@ -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)
}
}