diff options
author | Marge Bot <marge-bot@gnome.org> | 2023-03-30 22:51:53 +0000 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-03-30 22:51:53 +0000 |
commit | d597831ff93b09cc41ce4768a833bc6407c95184 (patch) | |
tree | a94f21b95b21483c5e9d1bb331d3dc7836901cb9 | |
parent | c2a06bb9feee23b8ff455a340bdb2522705065c9 (diff) | |
parent | e41f4d64330c68f5bbe138c68b1cec87b5d99f0b (diff) | |
download | librsvg-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.rst | 21 | ||||
-rw-r--r-- | src/drawing_ctx.rs | 403 | ||||
-rw-r--r-- | src/element.rs | 9 | ||||
-rw-r--r-- | src/filter.rs | 31 | ||||
-rw-r--r-- | src/gradient.rs | 6 | ||||
-rw-r--r-- | src/handle.rs | 4 | ||||
-rw-r--r-- | src/image.rs | 8 | ||||
-rw-r--r-- | src/length.rs | 24 | ||||
-rw-r--r-- | src/marker.rs | 22 | ||||
-rw-r--r-- | src/node.rs | 9 | ||||
-rw-r--r-- | src/paint_server.rs | 8 | ||||
-rw-r--r-- | src/pattern.rs | 6 | ||||
-rw-r--r-- | src/shapes.rs | 23 | ||||
-rw-r--r-- | src/structure.rs | 43 | ||||
-rw-r--r-- | src/text.rs | 26 |
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(¶ms) }; @@ -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, - ¶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, )); @@ -815,11 +739,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, @@ -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(¶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/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(¶ms); let marker_height = self.height.to_user(¶ms); @@ -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(¶ms); 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(¶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, &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(¶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 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, ¶ms); @@ -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(¶ms)); let y = self.y.map(|l| l.to_user(¶ms)); |