DrawingCtx::push_view_box(): Return a ViewParams object

We will later make this object pop the viewbox when dropped.
parent 62097afe
......@@ -191,9 +191,11 @@ impl<'a> DrawingCtx<'a> {
}
}
pub fn push_view_box(&mut self, width: f64, height: f64) {
pub fn push_view_box(&mut self, width: f64, height: f64) -> ViewParams {
self.vb_stack.push(self.vb);
self.vb = ViewBox::new(0.0, 0.0, width, height);
self.get_view_params()
}
pub fn pop_view_box(&mut self) {
......
......@@ -125,9 +125,11 @@ fn compute_effects_region(
// It's done this way because with ObjectBoundingBox, non-percentage values are supposed to
// represent the fractions of the referenced node, and with width and height = 1, 1 this
// works out exactly like that.
if filter.filterunits.get() == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0);
}
let params = if filter.filterunits.get() == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
// With filterunits == ObjectBoundingBox, lengths represent fractions or percentages of the
// referencing node. No units are allowed (it's checked during attribute parsing).
......@@ -139,8 +141,6 @@ fn compute_effects_region(
height: filter.height.get().get_unitless(),
}
} else {
let params = draw_ctx.get_view_params();
cairo::Rectangle {
x: filter.x.get().normalize(values, &params),
y: filter.y.get().normalize(values, &params),
......@@ -445,7 +445,7 @@ impl FilterContext {
// See comments in compute_effects_region() for how this works.
if filter.primitiveunits.get() == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0);
let _params = draw_ctx.push_view_box(1.0, 1.0);
let rv = f(Box::new(Length::get_unitless));
draw_ctx.pop_view_box();
......
......@@ -502,24 +502,26 @@ fn set_linear_gradient_on_pattern(
if let GradientVariant::Linear { x1, y1, x2, y2 } = gradient.variant {
let units = gradient.common.units.unwrap();
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0);
}
{
let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
let params = draw_ctx.get_view_params();
let mut pattern = cairo::LinearGradient::new(
x1.as_ref().unwrap().normalize(values, &params),
y1.as_ref().unwrap().normalize(values, &params),
x2.as_ref().unwrap().normalize(values, &params),
y2.as_ref().unwrap().normalize(values, &params),
);
let mut pattern = cairo::LinearGradient::new(
x1.as_ref().unwrap().normalize(values, &params),
y1.as_ref().unwrap().normalize(values, &params),
x2.as_ref().unwrap().normalize(values, &params),
y2.as_ref().unwrap().normalize(values, &params),
);
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
}
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
}
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
} else {
unreachable!();
}
......@@ -584,27 +586,29 @@ fn set_radial_gradient_on_pattern(
if let GradientVariant::Radial { cx, cy, r, fx, fy } = gradient.variant {
let units = gradient.common.units.unwrap();
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0);
}
{
let params = if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
let params = draw_ctx.get_view_params();
let n_cx = cx.as_ref().unwrap().normalize(values, &params);
let n_cy = cy.as_ref().unwrap().normalize(values, &params);
let n_r = r.as_ref().unwrap().normalize(values, &params);
let n_fx = fx.as_ref().unwrap().normalize(values, &params);
let n_fy = fy.as_ref().unwrap().normalize(values, &params);
let n_cx = cx.as_ref().unwrap().normalize(values, &params);
let n_cy = cy.as_ref().unwrap().normalize(values, &params);
let n_r = r.as_ref().unwrap().normalize(values, &params);
let n_fx = fx.as_ref().unwrap().normalize(values, &params);
let n_fy = fy.as_ref().unwrap().normalize(values, &params);
let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
let (new_fx, new_fy) = fix_focus_point(n_fx, n_fy, n_cx, n_cy, n_r);
let mut pattern = cairo::RadialGradient::new(new_fx, new_fy, 0.0, n_cx, n_cy, n_r);
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();
}
if units == GradientUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
}
set_common_on_pattern(gradient, draw_ctx, &mut pattern, bbox, opacity);
} else {
unreachable!();
}
......
......@@ -159,7 +159,7 @@ impl NodeMarker {
affine.scale(line_width, line_width);
}
if let Some(vbox) = self.vbox.get() {
let params = if let Some(vbox) = self.vbox.get() {
let (_, _, w, h) = self.aspect.get().compute(
vbox.0.width,
vbox.0.height,
......@@ -171,12 +171,10 @@ impl NodeMarker {
affine.scale(w / vbox.0.width, h / vbox.0.height);
draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
draw_ctx.push_view_box(vbox.0.width, vbox.0.height)
} else {
draw_ctx.push_view_box(marker_width, marker_height);
}
let params = draw_ctx.get_view_params();
draw_ctx.push_view_box(marker_width, marker_height)
};
affine.translate(
-self.ref_x.get().normalize(&values, &params),
......
......@@ -83,20 +83,24 @@ impl NodeMask {
let mask_units = CoordUnits::from(self.units.get());
let content_units = CoordUnits::from(self.content_units.get());
if mask_units == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0);
}
let (x, y, w, h) = {
let params = if mask_units == CoordUnits::ObjectBoundingBox {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
let params = draw_ctx.get_view_params();
let x = self.x.get().normalize(&values, &params);
let y = self.y.get().normalize(&values, &params);
let w = self.width.get().normalize(&values, &params);
let h = self.height.get().normalize(&values, &params);
let x = self.x.get().normalize(&values, &params);
let y = self.y.get().normalize(&values, &params);
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();
}
if mask_units == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
(x, y, w, h)
};
// Use a scope because mask_cr needs to release the
// reference to the surface before we access the pixels
......@@ -130,32 +134,36 @@ impl NodeMask {
draw_ctx.clip(x, y, w, h);
}
if content_units == CoordUnits::ObjectBoundingBox {
let bbtransform = cairo::Matrix::new(
bbox_rect.width,
0.0,
0.0,
bbox_rect.height,
bbox_rect.x,
bbox_rect.y,
);
{
let _params = if content_units == CoordUnits::ObjectBoundingBox {
let bbtransform = cairo::Matrix::new(
bbox_rect.width,
0.0,
0.0,
bbox_rect.height,
bbox_rect.x,
bbox_rect.y,
);
mask_cr.transform(bbtransform);
mask_cr.transform(bbtransform);
draw_ctx.push_view_box(1.0, 1.0);
}
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
node.draw_children(&cascaded, dc, false)
});
let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
node.draw_children(&cascaded, dc, false)
});
if content_units == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
if content_units == CoordUnits::ObjectBoundingBox {
draw_ctx.pop_view_box();
}
draw_ctx.set_cairo_context(&save_cr);
draw_ctx.set_cairo_context(&save_cr);
res
res
}
}?;
let opacity = {
......
......@@ -268,20 +268,24 @@ fn set_pattern_on_draw_context(
let vbox = pattern.vbox.unwrap();
let preserve_aspect_ratio = pattern.preserve_aspect_ratio.unwrap();
if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0);
}
let (pattern_x, pattern_y, pattern_width, pattern_height) = {
let params = if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.push_view_box(1.0, 1.0)
} else {
draw_ctx.get_view_params()
};
let params = draw_ctx.get_view_params();
let pattern_x = pattern.x.unwrap().normalize(values, &params);
let pattern_y = pattern.y.unwrap().normalize(values, &params);
let pattern_width = pattern.width.unwrap().normalize(values, &params);
let pattern_height = pattern.height.unwrap().normalize(values, &params);
let pattern_x = pattern.x.unwrap().normalize(values, &params);
let pattern_y = pattern.y.unwrap().normalize(values, &params);
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();
}
if units == PatternUnits(CoordUnits::ObjectBoundingBox) {
draw_ctx.pop_view_box();
}
(pattern_x, pattern_y, pattern_width, pattern_height)
};
// Work out the size of the rectangle so it takes into account the object bounding box
......@@ -346,7 +350,7 @@ fn set_pattern_on_draw_context(
let pushed_view_box: bool;
// Create the pattern contents coordinate system
if let Some(vbox) = vbox {
let _params = if let Some(vbox) = vbox {
// If there is a vbox, use that
let (mut x, mut y, w, h) = preserve_aspect_ratio.compute(
vbox.0.width,
......@@ -362,8 +366,9 @@ fn set_pattern_on_draw_context(
caffine = cairo::Matrix::new(w / vbox.0.width, 0.0, 0.0, h / vbox.0.height, x, y);
draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
let params = draw_ctx.push_view_box(vbox.0.width, vbox.0.height);
pushed_view_box = true;
params
} else if content_units == PatternContentUnits(CoordUnits::ObjectBoundingBox) {
// If coords are in terms of the bounding box, use them
let bbrect = bbox.rect.unwrap();
......@@ -371,12 +376,14 @@ fn set_pattern_on_draw_context(
caffine = cairo::Matrix::identity();
caffine.scale(bbrect.width, bbrect.height);
draw_ctx.push_view_box(1.0, 1.0);
let params = draw_ctx.push_view_box(1.0, 1.0);
pushed_view_box = true;
params
} else {
caffine = cairo::Matrix::identity();
pushed_view_box = false;
}
draw_ctx.get_view_params()
};
if !scwscale.approx_eq_cairo(&1.0) || !schscale.approx_eq_cairo(&1.0) {
let mut scalematrix = cairo::Matrix::identity();
......
......@@ -47,7 +47,7 @@ pub fn draw_in_viewport(
dc.clip(vx, vy, vw, vh);
}
if let Some(vbox) = vbox {
let _params = if let Some(vbox) = vbox {
// the preserveAspectRatio attribute is only used if viewBox is specified
// https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute
......@@ -57,7 +57,7 @@ pub fn draw_in_viewport(
return Ok(());
}
dc.push_view_box(vbox.0.width, vbox.0.height);
let params = dc.push_view_box(vbox.0.width, vbox.0.height);
let (x, y, w, h) =
preserve_aspect_ratio.compute(vbox.0.width, vbox.0.height, vx, vy, vw, vh);
......@@ -71,11 +71,14 @@ pub fn draw_in_viewport(
if do_clip && clip_mode == ClipMode::ClipToVbox {
dc.clip(vbox.0.x, vbox.0.y, vbox.0.width, vbox.0.height);
}
params
} else {
dc.push_view_box(vw, vh);
let params = dc.push_view_box(vw, vh);
affine.translate(vx, vy);
dc.get_cairo_context().set_matrix(affine);
}
params
};
let res = draw_fn(dc);
......
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