Remove DrawingCtx::pop_view_box() in favor of an impl Drop for it

ViewParams and DrawingCtx now store an Rc<RefCell<...>> of the
view_box_stack.

Thanks to Antoni Boucher for the suggestion on how to avoid lifetimes here.
parent 52f0d851
......@@ -48,6 +48,7 @@ pub struct ViewParams {
dpi_y: f64,
view_box_width: f64,
view_box_height: f64,
view_box_stack: Option<Rc<RefCell<Vec<ViewBox>>>>,
}
impl ViewParams {
......@@ -58,6 +59,7 @@ impl ViewParams {
dpi_y,
view_box_width,
view_box_height,
view_box_stack: None,
}
}
......@@ -78,6 +80,14 @@ impl ViewParams {
}
}
impl Drop for ViewParams {
fn drop(&mut self) {
if let Some(ref stack) = self.view_box_stack {
stack.borrow_mut().pop();
}
}
}
pub enum RsvgDrawingCtx {}
pub struct DrawingCtx<'a> {
......@@ -103,7 +113,7 @@ pub struct DrawingCtx<'a> {
surfaces_stack: Vec<cairo::ImageSurface>,
view_box_stack: RefCell<Vec<ViewBox>>,
view_box_stack: Rc<RefCell<Vec<ViewBox>>>,
bbox: BoundingBox,
bbox_stack: Vec<BoundingBox>,
......@@ -160,7 +170,7 @@ impl<'a> DrawingCtx<'a> {
cr: cr.clone(),
initial_cr: cr.clone(),
surfaces_stack: Vec::new(),
view_box_stack: RefCell::new(view_box_stack),
view_box_stack: Rc::new(RefCell::new(view_box_stack)),
bbox: BoundingBox::new(&affine),
bbox_stack: Vec::new(),
drawsub_stack: Vec::new(),
......@@ -211,33 +221,32 @@ impl<'a> DrawingCtx<'a> {
}
}
// FIXME: the result of this is only valid within a
// push_view_box() / pop_view_box() pair. How do we make this
// safe?
pub fn get_view_params(&self) -> ViewParams {
let view_box_stack = self.view_box_stack.borrow();
let last = view_box_stack.len() - 1;
let stack_top = &view_box_stack[last];
ViewParams {
dpi_x: self.dpi_x,
dpi_y: self.dpi_y,
view_box_width: view_box_stack[last].0.width,
view_box_height: view_box_stack[last].0.height,
view_box_width: stack_top.0.width,
view_box_height: stack_top.0.height,
view_box_stack: None,
}
}
pub fn push_view_box(&self, width: f64, height: f64) -> ViewParams {
{
let mut view_box_stack = self.view_box_stack.borrow_mut();
self.view_box_stack
.borrow_mut()
.push(ViewBox::new(0.0, 0.0, width, height));
view_box_stack.push(ViewBox::new(0.0, 0.0, width, height));
ViewParams {
dpi_x: self.dpi_x,
dpi_y: self.dpi_y,
view_box_width: width,
view_box_height: height,
view_box_stack: Some(self.view_box_stack.clone()),
}
self.get_view_params()
}
pub fn pop_view_box(&self) {
self.view_box_stack.borrow_mut().pop();
}
pub fn insert_bbox(&mut self, bbox: &BoundingBox) {
......
......@@ -149,10 +149,6 @@ fn compute_effects_region(
}
};
if filter.filterunits.get() == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
let other_bbox = BoundingBox::new(&affine).with_rect(Some(rect));
// At this point all of the previous viewbox and matrix business gets converted to pixel
......@@ -447,7 +443,6 @@ impl FilterContext {
if filter.primitiveunits.get() == CoordUnits::ObjectBoundingBox {
let _params = draw_ctx.push_view_box(1.0, 1.0);
let rv = f(Box::new(Length::get_unitless));
draw_ctx.pop_view_box();
rv
} else {
......
......@@ -516,10 +516,6 @@ fn set_linear_gradient_on_pattern(
y2.as_ref().unwrap().normalize(values, &params),
);
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
}
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
}
} else {
......@@ -603,10 +599,6 @@ fn set_radial_gradient_on_pattern(
let mut pattern = cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r);
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
}
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
}
} else {
......
......@@ -195,8 +195,6 @@ impl NodeMarker {
node.draw_children(&cascaded, dc, clipping)
});
draw_ctx.pop_view_box();
cr.restore();
res
......
......@@ -95,10 +95,6 @@ impl NodeMask {
let w = self.width.get().normalize(&values, &params);
let h = self.height.get().normalize(&values, &params);
if mask_units == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
(x, y, w, h)
};
......@@ -156,10 +152,6 @@ impl NodeMask {
node.draw_children(&cascaded, dc, false)
});
if content_units == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
draw_ctx.set_cairo_context(&save_cr);
res
......
......@@ -280,10 +280,6 @@ fn set_pattern_on_draw_context(
let pattern_width = pattern.width.unwrap().normalize(values, &params);
let pattern_height = pattern.height.unwrap().normalize(values, &params);
if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
}
(pattern_x, pattern_y, pattern_width, pattern_height)
};
......@@ -366,9 +362,7 @@ fn set_pattern_on_draw_context(
caffine = cairo::Matrix::new(w / vbox.0.width, 0.0, 0.0, h / vbox.0.height, x, y);
let params = draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
pushed_view_box = true;
params
draw_ctx.push_view_box(vbox.0.width, vbox.0.height)
} else if content_units == PatternContentUnits(CoordUnits::ObjectBoundingBox) {
// If coords are in terms of the bounding box, use them
let bbrect = bbox.rect.unwrap();
......@@ -376,12 +370,9 @@ fn set_pattern_on_draw_context(
caffine = cairo::Matrix::identity();
caffine.scale(bbrect.width, bbrect.height);
let params = draw_ctx.push_view_box(1.0, 1.0);
pushed_view_box = true;
params
draw_ctx.push_view_box(1.0, 1.0)
} else {
caffine = cairo::Matrix::identity();
pushed_view_box = false;
draw_ctx.get_view_params()
};
......@@ -425,10 +416,6 @@ fn set_pattern_on_draw_context(
draw_ctx.set_cairo_context(&cr_save);
if pushed_view_box {
draw_ctx.pop_view_box();
}
// Set the final surface as a Cairo pattern into the Cairo context
let surface_pattern = cairo::SurfacePattern::create(&surface);
......
......@@ -82,8 +82,6 @@ pub fn draw_in_viewport(
let res = draw_fn(dc);
dc.pop_view_box();
res
})
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment