diff options
author | Federico Mena Quintero <federico@gnome.org> | 2023-03-28 21:21:33 -0600 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-03-30 22:38:06 +0000 |
commit | 8d678639b274014f0ccc3d422e7ae9bd6eb286ab (patch) | |
tree | 41841be67093e2defc3810272db907923126272d | |
parent | 63c5f8b7812a27cbdb7ef35334bf94057cd6c419 (diff) | |
download | librsvg-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.rs | 308 | ||||
-rw-r--r-- | src/element.rs | 9 | ||||
-rw-r--r-- | src/filter.rs | 11 | ||||
-rw-r--r-- | src/image.rs | 8 | ||||
-rw-r--r-- | src/marker.rs | 18 | ||||
-rw-r--r-- | src/node.rs | 9 | ||||
-rw-r--r-- | src/shapes.rs | 23 | ||||
-rw-r--r-- | src/structure.rs | 39 | ||||
-rw-r--r-- | src/text.rs | 8 |
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(¶ms) }; @@ -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, - ¶ms, + viewport, &filter.normalize_values, )); let fill_paint_source = Rc::new(filter.fill_paint_source.to_user_space( &bbox.rect, - ¶ms, + 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, - ¶ms.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(¶ms); let y = values.y().0.to_user(¶ms); @@ -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(¶ms); let marker_height = self.height.to_user(¶ms); @@ -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(¶ms, 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, ¤t_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(¶ms); 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) } } |