mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
Previously, StackingContexts might have a PaintLayer. We switch the ownership, for several reasons: * We want PaintLayers to potentially contain something other than a StackingContext soon. * We want to delay the creation of PaintLayers until the last minute, so that we can synthesize new layers for sandwiched content. This commit also implements the second goal. Instead of creating PaintLayers during layout itself, wait until we are sorting and layerizing a completed DisplayList.
88 lines
4.4 KiB
Rust
88 lines
4.4 KiB
Rust
/* 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/. */
|
|
|
|
//! Transforms a display list to produce a visually-equivalent, but cheaper-to-paint, one.
|
|
|
|
use display_list::{DisplayItem, DisplayList, StackingContext};
|
|
|
|
use euclid::rect::Rect;
|
|
use euclid::{Matrix2D, Matrix4};
|
|
use std::collections::linked_list::LinkedList;
|
|
use std::sync::Arc;
|
|
use util::geometry::{self, Au};
|
|
|
|
/// Transforms a display list to produce a visually-equivalent, but cheaper-to-paint, one.
|
|
pub struct DisplayListOptimizer {
|
|
/// The visible rect in page coordinates.
|
|
visible_rect: Rect<Au>,
|
|
}
|
|
|
|
impl DisplayListOptimizer {
|
|
/// Creates a new display list optimizer object. `visible_rect` specifies the visible rect in
|
|
/// page coordinates.
|
|
pub fn new(visible_rect: &Rect<f32>) -> DisplayListOptimizer {
|
|
DisplayListOptimizer {
|
|
visible_rect: geometry::f32_rect_to_au_rect(*visible_rect),
|
|
}
|
|
}
|
|
|
|
/// Optimizes the given display list, returning an equivalent, but cheaper-to-paint, one.
|
|
pub fn optimize(self, display_list: &DisplayList) -> DisplayList {
|
|
let mut result = DisplayList::new();
|
|
self.add_in_bounds_display_items(&mut result.background_and_borders,
|
|
display_list.background_and_borders.iter());
|
|
self.add_in_bounds_display_items(&mut result.block_backgrounds_and_borders,
|
|
display_list.block_backgrounds_and_borders.iter());
|
|
self.add_in_bounds_display_items(&mut result.floats, display_list.floats.iter());
|
|
self.add_in_bounds_display_items(&mut result.content, display_list.content.iter());
|
|
self.add_in_bounds_display_items(&mut result.positioned_content,
|
|
display_list.positioned_content.iter());
|
|
self.add_in_bounds_display_items(&mut result.outlines,
|
|
display_list.outlines.iter());
|
|
self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter());
|
|
result
|
|
}
|
|
|
|
/// Adds display items that intersect the visible rect to `result_list`.
|
|
fn add_in_bounds_display_items<'a, I>(&self,
|
|
result_list: &mut LinkedList<DisplayItem>,
|
|
display_items: I)
|
|
where I: Iterator<Item=&'a DisplayItem> {
|
|
for display_item in display_items {
|
|
if self.visible_rect.intersects(&display_item.base().bounds) &&
|
|
display_item.base().clip.might_intersect_rect(&self.visible_rect) {
|
|
result_list.push_back((*display_item).clone())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Adds child stacking contexts whose boundaries intersect the visible rect to `result_list`.
|
|
fn add_in_bounds_stacking_contexts<'a, I>(&self,
|
|
result_list: &mut LinkedList<Arc<StackingContext>>,
|
|
stacking_contexts: I)
|
|
where I: Iterator<Item=&'a Arc<StackingContext>> {
|
|
for stacking_context in stacking_contexts {
|
|
// Transform this stacking context to get it into the same space as
|
|
// the parent stacking context.
|
|
let origin_x = stacking_context.bounds.origin.x.to_f32_px();
|
|
let origin_y = stacking_context.bounds.origin.y.to_f32_px();
|
|
|
|
let transform = Matrix4::identity().translate(origin_x,
|
|
origin_y,
|
|
0.0)
|
|
.mul(&stacking_context.transform);
|
|
let transform_2d = Matrix2D::new(transform.m11, transform.m12,
|
|
transform.m21, transform.m22,
|
|
transform.m41, transform.m42);
|
|
|
|
let overflow = geometry::au_rect_to_f32_rect(stacking_context.overflow);
|
|
let overflow = transform_2d.transform_rect(&overflow);
|
|
let overflow = geometry::f32_rect_to_au_rect(overflow);
|
|
|
|
if self.visible_rect.intersects(&overflow) {
|
|
result_list.push_back((*stacking_context).clone())
|
|
}
|
|
}
|
|
}
|
|
}
|