Introduce layer clipping

This commit is contained in:
Antonio Scandurra 2021-03-26 10:28:05 +01:00
parent 63f9719c99
commit 61d4da9934
5 changed files with 47 additions and 17 deletions

View file

@ -1,6 +1,7 @@
use crate::{
geometry::vector::Vector2F, AfterLayoutContext, Element, ElementBox, Event, EventContext,
LayoutContext, PaintContext, SizeConstraint,
geometry::{rect::RectF, vector::Vector2F},
AfterLayoutContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
SizeConstraint,
};
pub struct Stack {
@ -44,12 +45,12 @@ impl Element for Stack {
fn paint(
&mut self,
bounds: pathfinder_geometry::rect::RectF,
bounds: RectF,
_: &mut Self::LayoutState,
ctx: &mut PaintContext,
) -> Self::PaintState {
for child in &mut self.children {
ctx.scene.push_layer();
ctx.scene.push_layer(None);
child.paint(bounds.origin(), ctx);
ctx.scene.pop_layer();
}
@ -58,7 +59,7 @@ impl Element for Stack {
fn dispatch_event(
&mut self,
event: &Event,
_: pathfinder_geometry::rect::RectF,
_: RectF,
_: &mut Self::LayoutState,
_: &mut Self::PaintState,
ctx: &mut EventContext,

View file

@ -195,10 +195,7 @@ where
layout: &mut Self::LayoutState,
ctx: &mut PaintContext,
) -> Self::PaintState {
// ctx.canvas.save();
// let mut clip_path = Path2D::new();
// clip_path.rect(RectF::new(origin, self.size.unwrap()));
// ctx.canvas.clip_path(clip_path, FillRule::Winding);
ctx.scene.push_layer(Some(bounds));
let mut item_origin =
bounds.origin() - vec2f(0.0, self.state.scroll_top() % layout.item_height);
@ -207,7 +204,8 @@ where
item.paint(item_origin, ctx);
item_origin += vec2f(0.0, layout.item_height);
}
// ctx.canvas.restore();
ctx.scene.pop_layer();
}
fn dispatch_event(

View file

@ -1,12 +1,16 @@
use super::{sprite_cache::SpriteCache, window::RenderContext};
use crate::{
color::ColorU,
geometry::vector::{vec2i, Vector2I},
geometry::{
rect::RectF,
vector::{vec2f, vec2i, Vector2I},
},
platform,
scene::Layer,
Scene,
};
use anyhow::{anyhow, Result};
use cocoa::foundation::NSUInteger;
use metal::{MTLResourceOptions, NSRange};
use shaders::{ToFloat2 as _, ToUchar4 as _};
use std::{collections::HashMap, ffi::c_void, mem, sync::Arc};
@ -96,12 +100,26 @@ impl Renderer {
let mut offset = 0;
for layer in scene.layers() {
self.clip(scene, layer, ctx);
self.render_shadows(scene, layer, &mut offset, ctx);
self.render_quads(scene, layer, &mut offset, ctx);
self.render_sprites(scene, layer, &mut offset, ctx);
}
}
fn clip(&mut self, scene: &Scene, layer: &Layer, ctx: &RenderContext) {
let clip_bounds = layer.clip_bounds().unwrap_or(RectF::new(
vec2f(0., 0.),
ctx.drawable_size / scene.scale_factor(),
)) * scene.scale_factor();
ctx.command_encoder.set_scissor_rect(metal::MTLScissorRect {
x: clip_bounds.origin_x() as NSUInteger,
y: clip_bounds.origin_y() as NSUInteger,
width: clip_bounds.width() as NSUInteger,
height: clip_bounds.height() as NSUInteger,
});
}
fn render_shadows(
&mut self,
scene: &Scene,

View file

@ -57,7 +57,7 @@ impl Scene {
pub fn new(scale_factor: f32) -> Self {
Scene {
scale_factor,
layers: vec![Layer::default()],
layers: vec![Layer::new(None)],
active_layer_stack: vec![0],
}
}
@ -70,9 +70,9 @@ impl Scene {
self.layers.as_slice()
}
pub fn push_layer(&mut self) {
pub fn push_layer(&mut self, clip_bounds: Option<RectF>) {
let ix = self.layers.len();
self.layers.push(Layer::default());
self.layers.push(Layer::new(clip_bounds));
self.active_layer_stack.push(ix);
}
@ -99,6 +99,19 @@ impl Scene {
}
impl Layer {
pub fn new(clip_bounds: Option<RectF>) -> Self {
Self {
clip_bounds,
quads: Vec::new(),
shadows: Vec::new(),
glyphs: Vec::new(),
}
}
pub fn clip_bounds(&self) -> Option<RectF> {
self.clip_bounds
}
fn push_quad(&mut self, quad: Quad) {
self.quads.push(quad);
}

View file

@ -168,7 +168,7 @@ impl BufferElement {
let line_height = view.line_height(ctx.font_cache);
let scroll_top = view.scroll_position().y() * line_height;
ctx.scene.push_layer();
ctx.scene.push_layer(Some(rect));
ctx.scene.push_quad(Quad {
bounds: rect,
background: Some(ColorU::white()),
@ -202,7 +202,7 @@ impl BufferElement {
let max_glyph_width = view.em_width(ctx.font_cache);
let scroll_left = view.scroll_position().x() * max_glyph_width;
ctx.scene.push_layer();
ctx.scene.push_layer(Some(bounds));
ctx.scene.push_quad(Quad {
bounds,
background: Some(ColorU::white()),
@ -290,7 +290,7 @@ impl BufferElement {
);
}
ctx.scene.push_layer();
ctx.scene.push_layer(Some(bounds));
for cursor in cursors {
cursor.paint(ctx);
}