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

View file

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

View file

@ -1,12 +1,16 @@
use super::{sprite_cache::SpriteCache, window::RenderContext}; use super::{sprite_cache::SpriteCache, window::RenderContext};
use crate::{ use crate::{
color::ColorU, color::ColorU,
geometry::vector::{vec2i, Vector2I}, geometry::{
rect::RectF,
vector::{vec2f, vec2i, Vector2I},
},
platform, platform,
scene::Layer, scene::Layer,
Scene, Scene,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use cocoa::foundation::NSUInteger;
use metal::{MTLResourceOptions, NSRange}; use metal::{MTLResourceOptions, NSRange};
use shaders::{ToFloat2 as _, ToUchar4 as _}; use shaders::{ToFloat2 as _, ToUchar4 as _};
use std::{collections::HashMap, ffi::c_void, mem, sync::Arc}; use std::{collections::HashMap, ffi::c_void, mem, sync::Arc};
@ -96,12 +100,26 @@ impl Renderer {
let mut offset = 0; let mut offset = 0;
for layer in scene.layers() { for layer in scene.layers() {
self.clip(scene, layer, ctx);
self.render_shadows(scene, layer, &mut offset, ctx); self.render_shadows(scene, layer, &mut offset, ctx);
self.render_quads(scene, layer, &mut offset, ctx); self.render_quads(scene, layer, &mut offset, ctx);
self.render_sprites(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( fn render_shadows(
&mut self, &mut self,
scene: &Scene, scene: &Scene,

View file

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

View file

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