Fix use of Clip inside a scrolled Flickable with the GL backend

We're using `Canvas::intersect_scissor` to combine the viewport clip of
the flickable with any child `Clip` element, for example. Unfortunately
`intersect_scissor` has a bug and this patch works around it by doing
the scissor intersection manually. This works because we don't apply a
global transform on the canvas -- all scaling and translation is done
locally in the draw functions.
This commit is contained in:
Simon Hausmann 2021-02-09 10:40:46 +01:00
parent ec90d0c525
commit de9a215a1c

View file

@ -589,7 +589,12 @@ impl GLRenderer {
canvas.clear_rect(0, 0, size.width, size.height, clear_color.into());
}
GLItemRenderer { shared_data: self.shared_data.clone(), scale_factor }
GLItemRenderer {
shared_data: self.shared_data.clone(),
scale_factor,
saved_scissor_rects: Vec::new(),
current_scissor_rect: None,
}
}
/// Complete the item rendering by calling this function. This will typically flush any remaining/pending
@ -649,6 +654,8 @@ impl GLRenderer {
pub struct GLItemRenderer {
shared_data: Rc<GLRendererData>,
scale_factor: f32,
saved_scissor_rects: Vec<Rect>,
current_scissor_rect: Option<Rect>,
}
fn rect_to_path(r: Rect) -> femtovg::Path {
@ -1102,19 +1109,30 @@ impl ItemRenderer for GLItemRenderer {
fn combine_clip(&mut self, pos: Point, rect: Rect) {
let clip_rect = rect.translate([pos.x, pos.y].into());
self.shared_data.canvas.borrow_mut().intersect_scissor(
clip_rect.min_x(),
clip_rect.min_y(),
clip_rect.width(),
clip_rect.height(),
// FIXME: Go back to using Canvas::intersect_scissor when https://github.com/femtovg/femtovg/pull/29 is merged
let final_clip_rect = if let Some(existing_clip) = self.current_scissor_rect {
existing_clip.intersection(&clip_rect).unwrap_or_default()
} else {
clip_rect
};
self.shared_data.canvas.borrow_mut().scissor(
final_clip_rect.min_x(),
final_clip_rect.min_y(),
final_clip_rect.width(),
final_clip_rect.height(),
);
self.current_scissor_rect = Some(final_clip_rect);
}
fn save_state(&mut self) {
if let Some(scissor_rect) = self.current_scissor_rect {
self.saved_scissor_rects.push(scissor_rect);
}
self.shared_data.canvas.borrow_mut().save();
}
fn restore_state(&mut self) {
self.current_scissor_rect = self.saved_scissor_rects.pop();
self.shared_data.canvas.borrow_mut().restore();
}