Skip to content

Instantly share code, notes, and snippets.

@squarewave
Last active October 16, 2018 15:06
Show Gist options
  • Save squarewave/53e8c5e563b2a47b43ed4853af7a9983 to your computer and use it in GitHub Desktop.
Save squarewave/53e8c5e563b2a47b43ed4853af7a9983 to your computer and use it in GitHub Desktop.
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate euclid;
extern crate gleam;
extern crate glutin;
extern crate webrender;
extern crate winit;
#[path = "common/boilerplate.rs"]
mod boilerplate;
use boilerplate::Example;
use euclid::TypedScale;
use webrender::api::*;
// This example creates multiple documents overlapping each other with
// specified layer indices.
struct Document {
id: DocumentId,
pipeline_id: PipelineId,
sub_pipeline_id: PipelineId,
content_rect: LayoutRect,
color: ColorF,
skip: bool,
}
struct App {
documents: Vec<Document>,
}
impl App {
fn init(
&mut self,
api: &RenderApi,
framebuffer_size: DeviceUintSize,
device_pixel_ratio: f32,
) {
let init_data = vec![
(
PipelineId(1, 0),
PipelineId(1, 1),
-1,
ColorF::new(0.0, 1.0, 0.0, 1.0),
DeviceUintPoint::new(0, 0),
),
(
PipelineId(2, 0),
PipelineId(2, 1),
-2,
ColorF::new(1.0, 1.0, 0.0, 1.0),
DeviceUintPoint::new(150, 0),
),
(
PipelineId(3, 0),
PipelineId(3, 1),
-3,
ColorF::new(1.0, 0.0, 0.0, 1.0),
DeviceUintPoint::new(150, 150),
),
(
PipelineId(4, 0),
PipelineId(4, 1),
-4,
ColorF::new(1.0, 0.0, 1.0, 1.0),
DeviceUintPoint::new(0, 150),
),
];
for (pipeline_id, sub_pipeline_id, layer, color, offset) in init_data {
let size = DeviceUintSize::new(250, 250);
let bounds = DeviceUintRect::new(offset, size);
let document_id = api.add_document(size, layer);
let mut txn = Transaction::new();
txn.set_window_parameters(framebuffer_size, bounds, device_pixel_ratio);
txn.set_root_pipeline(pipeline_id);
api.send_transaction(document_id, txn);
self.documents.push(Document {
id: document_id,
pipeline_id,
sub_pipeline_id,
content_rect: bounds.to_f32() / TypedScale::new(device_pixel_ratio),
color,
skip: false,
});
}
}
}
impl Example for App {
fn on_event(
&mut self,
event: winit::WindowEvent,
_api: &RenderApi,
_document_id: DocumentId
) -> bool {
match event {
winit::WindowEvent::KeyboardInput {
input: winit::KeyboardInput {
state: winit::ElementState::Pressed,
virtual_keycode: Some(key),
..
},
..
} => {
match key {
winit::VirtualKeyCode::Key3 => {
self.documents[0].skip = !self.documents[0].skip;
}
winit::VirtualKeyCode::Key4 => {
self.documents[1].skip = !self.documents[1].skip;
}
winit::VirtualKeyCode::Key5 => {
self.documents[2].skip = !self.documents[2].skip;
}
winit::VirtualKeyCode::Key6 => {
self.documents[3].skip = !self.documents[3].skip;
}
_ => {}
};
}
_ => (),
}
true
}
fn render(
&mut self,
api: &RenderApi,
base_builder: &mut DisplayListBuilder,
_txn: &mut Transaction,
framebuffer_size: DeviceUintSize,
_: PipelineId,
_: DocumentId,
) {
if self.documents.is_empty() {
let device_pixel_ratio = framebuffer_size.width as f32 /
base_builder.content_size().width;
// this is the first run, hack around the boilerplate,
// which assumes an example only needs one document
self.init(api, framebuffer_size, device_pixel_ratio);
}
for doc in &self.documents {
if doc.skip {
continue;
}
let mut builder = DisplayListBuilder::new(
doc.pipeline_id,
doc.content_rect.size,
);
let local_rect = LayoutRect::new(
LayoutPoint::zero(),
doc.content_rect.size,
);
let mut sub_builder = DisplayListBuilder::new(
doc.sub_pipeline_id,
doc.content_rect.size,
);
sub_builder.push_stacking_context(
&LayoutPrimitiveInfo::new(local_rect),
None,
TransformStyle::Flat,
MixBlendMode::Normal,
Vec::new(),
RasterSpace::Screen,
);
sub_builder.push_rect(
&LayoutPrimitiveInfo::new(local_rect),
doc.color,
);
sub_builder.pop_stacking_context();
let mut txn = Transaction::new();
txn.set_display_list(
Epoch(0),
None,
doc.content_rect.size,
sub_builder.finalize(),
true,
);
api.send_transaction(doc.id, txn);
builder.push_stacking_context(
&LayoutPrimitiveInfo::new(doc.content_rect),
None,
TransformStyle::Flat,
MixBlendMode::Normal,
Vec::new(),
RasterSpace::Screen,
);
// white rect under the iframe: if this is visible, things have gone wrong
builder.push_rect(&LayoutPrimitiveInfo::new(local_rect), ColorF::new(1.0, 1.0, 1.0, 1.0));
builder.push_iframe(&LayoutPrimitiveInfo::new(local_rect), doc.sub_pipeline_id, true);
builder.pop_stacking_context();
let mut txn = Transaction::new();
txn.set_display_list(
Epoch(0),
None,
doc.content_rect.size,
builder.finalize(),
true,
);
txn.generate_frame();
api.send_transaction(doc.id, txn);
}
}
}
fn main() {
let mut app = App {
documents: Vec::new(),
};
boilerplate::main_wrapper(&mut app, None);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment