mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-28 12:45:27 +00:00
servo: Merge #4272 - gfx: Update Azure and Skia, and rewrite broken clipping logic (from pcwalton:upgrade-azure); r=mrobinson
This exposed some problems in our clipping logic, which was never properly rewritten for the stacking context reform. The clipping code worked in terms of a stack of clips, but the new stacking context code has no concept of a stack of clip regions. Fixing that in turn exposed some flaky/incorrect tests: * `borders` had an incorrect reference image, as far as I can tell. * `negative_margins` had some stray pixels, fixed by changing the text. r? @mrobinson Source-Repo: https://github.com/servo/servo Source-Revision: 40c706b42d9d29ef58913f22da49159796e1b81b
This commit is contained in:
parent
40deabd7f7
commit
c02b013483
@ -176,8 +176,8 @@ impl StackingContext {
|
|||||||
pub fn optimize_and_draw_into_context(&self,
|
pub fn optimize_and_draw_into_context(&self,
|
||||||
paint_context: &mut PaintContext,
|
paint_context: &mut PaintContext,
|
||||||
tile_bounds: &Rect<AzFloat>,
|
tile_bounds: &Rect<AzFloat>,
|
||||||
current_transform: &Matrix2D<AzFloat>,
|
transform: &Matrix2D<AzFloat>,
|
||||||
current_clip_stack: &mut Vec<Rect<Au>>) {
|
clip_rect: Option<&Rect<Au>>) {
|
||||||
let temporary_draw_target =
|
let temporary_draw_target =
|
||||||
paint_context.get_or_create_temporary_draw_target(self.opacity);
|
paint_context.get_or_create_temporary_draw_target(self.opacity);
|
||||||
{
|
{
|
||||||
@ -186,7 +186,7 @@ impl StackingContext {
|
|||||||
font_ctx: &mut *paint_context.font_ctx,
|
font_ctx: &mut *paint_context.font_ctx,
|
||||||
page_rect: paint_context.page_rect,
|
page_rect: paint_context.page_rect,
|
||||||
screen_rect: paint_context.screen_rect,
|
screen_rect: paint_context.screen_rect,
|
||||||
..*paint_context
|
transient_clip_rect: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Optimize the display list to throw out out-of-bounds display items and so forth.
|
// Optimize the display list to throw out out-of-bounds display items and so forth.
|
||||||
@ -201,11 +201,17 @@ impl StackingContext {
|
|||||||
positioned_children.as_slice_mut()
|
positioned_children.as_slice_mut()
|
||||||
.sort_by(|this, other| this.z_index.cmp(&other.z_index));
|
.sort_by(|this, other| this.z_index.cmp(&other.z_index));
|
||||||
|
|
||||||
|
// Set up our clip rect and transform.
|
||||||
|
match clip_rect {
|
||||||
|
None => {}
|
||||||
|
Some(clip_rect) => paint_subcontext.draw_push_clip(clip_rect),
|
||||||
|
}
|
||||||
|
let old_transform = paint_subcontext.draw_target.get_transform();
|
||||||
|
paint_subcontext.draw_target.set_transform(transform);
|
||||||
|
|
||||||
// Steps 1 and 2: Borders and background for the root.
|
// Steps 1 and 2: Borders and background for the root.
|
||||||
for display_item in display_list.background_and_borders.iter() {
|
for display_item in display_list.background_and_borders.iter() {
|
||||||
display_item.draw_into_context(&mut paint_subcontext,
|
display_item.draw_into_context(&mut paint_subcontext)
|
||||||
current_transform,
|
|
||||||
current_clip_stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Positioned descendants with negative z-indices.
|
// Step 3: Positioned descendants with negative z-indices.
|
||||||
@ -215,41 +221,39 @@ impl StackingContext {
|
|||||||
}
|
}
|
||||||
if positioned_kid.layer.is_none() {
|
if positioned_kid.layer.is_none() {
|
||||||
let new_transform =
|
let new_transform =
|
||||||
current_transform.translate(positioned_kid.bounds.origin.x.to_nearest_px()
|
transform.translate(positioned_kid.bounds
|
||||||
as AzFloat,
|
.origin
|
||||||
positioned_kid.bounds.origin.y.to_nearest_px()
|
.x
|
||||||
as AzFloat);
|
.to_nearest_px() as AzFloat,
|
||||||
|
positioned_kid.bounds
|
||||||
|
.origin
|
||||||
|
.y
|
||||||
|
.to_nearest_px() as AzFloat);
|
||||||
let new_tile_rect =
|
let new_tile_rect =
|
||||||
self.compute_tile_rect_for_child_stacking_context(tile_bounds,
|
self.compute_tile_rect_for_child_stacking_context(tile_bounds,
|
||||||
&**positioned_kid);
|
&**positioned_kid);
|
||||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||||
&new_tile_rect,
|
&new_tile_rect,
|
||||||
&new_transform,
|
&new_transform,
|
||||||
current_clip_stack);
|
Some(&positioned_kid.clip_rect))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4: Block backgrounds and borders.
|
// Step 4: Block backgrounds and borders.
|
||||||
for display_item in display_list.block_backgrounds_and_borders.iter() {
|
for display_item in display_list.block_backgrounds_and_borders.iter() {
|
||||||
display_item.draw_into_context(&mut paint_subcontext,
|
display_item.draw_into_context(&mut paint_subcontext)
|
||||||
current_transform,
|
|
||||||
current_clip_stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5: Floats.
|
// Step 5: Floats.
|
||||||
for display_item in display_list.floats.iter() {
|
for display_item in display_list.floats.iter() {
|
||||||
display_item.draw_into_context(&mut paint_subcontext,
|
display_item.draw_into_context(&mut paint_subcontext)
|
||||||
current_transform,
|
|
||||||
current_clip_stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Step 6: Inlines that generate stacking contexts.
|
// TODO(pcwalton): Step 6: Inlines that generate stacking contexts.
|
||||||
|
|
||||||
// Step 7: Content.
|
// Step 7: Content.
|
||||||
for display_item in display_list.content.iter() {
|
for display_item in display_list.content.iter() {
|
||||||
display_item.draw_into_context(&mut paint_subcontext,
|
display_item.draw_into_context(&mut paint_subcontext)
|
||||||
current_transform,
|
|
||||||
current_clip_stack)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Steps 8 and 9: Positioned descendants with nonnegative z-indices.
|
// Steps 8 and 9: Positioned descendants with nonnegative z-indices.
|
||||||
@ -260,25 +264,38 @@ impl StackingContext {
|
|||||||
|
|
||||||
if positioned_kid.layer.is_none() {
|
if positioned_kid.layer.is_none() {
|
||||||
let new_transform =
|
let new_transform =
|
||||||
current_transform.translate(positioned_kid.bounds.origin.x.to_nearest_px()
|
transform.translate(positioned_kid.bounds
|
||||||
as AzFloat,
|
.origin
|
||||||
positioned_kid.bounds.origin.y.to_nearest_px()
|
.x
|
||||||
as AzFloat);
|
.to_nearest_px() as AzFloat,
|
||||||
|
positioned_kid.bounds
|
||||||
|
.origin
|
||||||
|
.y
|
||||||
|
.to_nearest_px() as AzFloat);
|
||||||
let new_tile_rect =
|
let new_tile_rect =
|
||||||
self.compute_tile_rect_for_child_stacking_context(tile_bounds,
|
self.compute_tile_rect_for_child_stacking_context(tile_bounds,
|
||||||
&**positioned_kid);
|
&**positioned_kid);
|
||||||
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext,
|
||||||
&new_tile_rect,
|
&new_tile_rect,
|
||||||
&new_transform,
|
&new_transform,
|
||||||
current_clip_stack);
|
Some(&positioned_kid.clip_rect))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(pcwalton): Step 10: Outlines.
|
// TODO(pcwalton): Step 10: Outlines.
|
||||||
|
|
||||||
|
// Undo our clipping and transform.
|
||||||
|
if paint_subcontext.transient_clip_rect.is_some() {
|
||||||
|
paint_subcontext.draw_pop_clip();
|
||||||
|
paint_subcontext.transient_clip_rect = None
|
||||||
|
}
|
||||||
|
paint_subcontext.draw_target.set_transform(&old_transform);
|
||||||
|
if clip_rect.is_some() {
|
||||||
|
paint_subcontext.draw_pop_clip()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paint_context.draw_temporary_draw_target_if_necessary(&temporary_draw_target,
|
paint_context.draw_temporary_draw_target_if_necessary(&temporary_draw_target, self.opacity)
|
||||||
self.opacity)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translate the given tile rect into the coordinate system of a child stacking context.
|
/// Translate the given tile rect into the coordinate system of a child stacking context.
|
||||||
@ -560,24 +577,17 @@ impl<'a> Iterator<&'a DisplayItem> for DisplayItemIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayItem {
|
impl DisplayItem {
|
||||||
/// Paints this display item into the given paint context.
|
/// Paints this display item into the given painting context.
|
||||||
fn draw_into_context(&self,
|
fn draw_into_context(&self, paint_context: &mut PaintContext) {
|
||||||
paint_context: &mut PaintContext,
|
let this_clip_rect = self.base().clip_rect;
|
||||||
current_transform: &Matrix2D<AzFloat>,
|
if paint_context.transient_clip_rect != Some(this_clip_rect) {
|
||||||
current_clip_stack: &mut Vec<Rect<Au>>) {
|
if paint_context.transient_clip_rect.is_some() {
|
||||||
// TODO(pcwalton): This will need some tweaking to deal with more complex clipping regions.
|
|
||||||
let clip_rect = &self.base().clip_rect;
|
|
||||||
if current_clip_stack.len() == 0 || current_clip_stack.last().unwrap() != clip_rect {
|
|
||||||
while current_clip_stack.len() != 0 {
|
|
||||||
paint_context.draw_pop_clip();
|
paint_context.draw_pop_clip();
|
||||||
drop(current_clip_stack.pop());
|
|
||||||
}
|
}
|
||||||
paint_context.draw_push_clip(clip_rect);
|
paint_context.draw_push_clip(&this_clip_rect);
|
||||||
current_clip_stack.push(*clip_rect);
|
paint_context.transient_clip_rect = Some(this_clip_rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
paint_context.draw_target.set_transform(current_transform);
|
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
SolidColorDisplayItemClass(ref solid_color) => {
|
SolidColorDisplayItemClass(ref solid_color) => {
|
||||||
paint_context.draw_solid_color(&solid_color.base.bounds, solid_color.color)
|
paint_context.draw_solid_color(&solid_color.base.bounds, solid_color.color)
|
||||||
@ -585,7 +595,7 @@ impl DisplayItem {
|
|||||||
|
|
||||||
TextDisplayItemClass(ref text) => {
|
TextDisplayItemClass(ref text) => {
|
||||||
debug!("Drawing text at {}.", text.base.bounds);
|
debug!("Drawing text at {}.", text.base.bounds);
|
||||||
paint_context.draw_text(&**text, current_transform);
|
paint_context.draw_text(&**text);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDisplayItemClass(ref image_item) => {
|
ImageDisplayItemClass(ref image_item) => {
|
||||||
|
@ -40,6 +40,10 @@ pub struct PaintContext<'a> {
|
|||||||
pub page_rect: Rect<f32>,
|
pub page_rect: Rect<f32>,
|
||||||
/// The rectangle that this context encompasses in screen coordinates (pixels).
|
/// The rectangle that this context encompasses in screen coordinates (pixels).
|
||||||
pub screen_rect: Rect<uint>,
|
pub screen_rect: Rect<uint>,
|
||||||
|
/// The current transient clipping rect, if any. A "transient clipping rect" is the clipping
|
||||||
|
/// rect used by the last display item. We cache the last value so that we avoid pushing and
|
||||||
|
/// popping clip rects unnecessarily.
|
||||||
|
pub transient_clip_rect: Option<Rect<Au>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Direction {
|
enum Direction {
|
||||||
@ -130,11 +134,11 @@ impl<'a> PaintContext<'a> {
|
|||||||
size,
|
size,
|
||||||
stride as i32,
|
stride as i32,
|
||||||
source_format);
|
source_format);
|
||||||
let source_rect = Rect(Point2D(0u as AzFloat, 0u as AzFloat),
|
let source_rect = Rect(Point2D(0.0, 0.0),
|
||||||
Size2D(image.width as AzFloat, image.height as AzFloat));
|
Size2D(image.width as AzFloat, image.height as AzFloat));
|
||||||
let dest_rect = bounds.to_azure_rect();
|
let dest_rect = bounds.to_azure_rect();
|
||||||
let draw_surface_options = DrawSurfaceOptions::new(Linear, true);
|
let draw_surface_options = DrawSurfaceOptions::new(Linear, true);
|
||||||
let draw_options = DrawOptions::new(1.0f64 as AzFloat, 0);
|
let draw_options = DrawOptions::new(1.0, 0);
|
||||||
draw_target_ref.draw_surface(azure_surface,
|
draw_target_ref.draw_surface(azure_surface,
|
||||||
dest_rect,
|
dest_rect,
|
||||||
source_rect,
|
source_rect,
|
||||||
@ -628,9 +632,9 @@ impl<'a> PaintContext<'a> {
|
|||||||
self.draw_border_path(&original_bounds, direction, border, radius, scaled_color);
|
self.draw_border_path(&original_bounds, direction, border, radius, scaled_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_text(&mut self,
|
pub fn draw_text(&mut self, text: &TextDisplayItem) {
|
||||||
text: &TextDisplayItem,
|
let current_transform = self.draw_target.get_transform();
|
||||||
current_transform: &Matrix2D<AzFloat>) {
|
|
||||||
// Optimization: Don’t set a transform matrix for upright text, and pass a start point to
|
// Optimization: Don’t set a transform matrix for upright text, and pass a start point to
|
||||||
// `draw_text_into_context`.
|
// `draw_text_into_context`.
|
||||||
//
|
//
|
||||||
@ -669,7 +673,7 @@ impl<'a> PaintContext<'a> {
|
|||||||
|
|
||||||
// Undo the transform, only when we did one.
|
// Undo the transform, only when we did one.
|
||||||
if text.orientation != Upright {
|
if text.orientation != Upright {
|
||||||
self.draw_target.set_transform(current_transform)
|
self.draw_target.set_transform(¤t_transform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +509,7 @@ impl WorkerThread {
|
|||||||
font_ctx: &mut self.font_context,
|
font_ctx: &mut self.font_context,
|
||||||
page_rect: tile.page_rect,
|
page_rect: tile.page_rect,
|
||||||
screen_rect: tile.screen_rect,
|
screen_rect: tile.screen_rect,
|
||||||
|
transient_clip_rect: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply the translation to paint the tile we want.
|
// Apply the translation to paint the tile we want.
|
||||||
@ -518,18 +519,15 @@ impl WorkerThread {
|
|||||||
let matrix = matrix.translate(-tile_bounds.origin.x as AzFloat,
|
let matrix = matrix.translate(-tile_bounds.origin.x as AzFloat,
|
||||||
-tile_bounds.origin.y as AzFloat);
|
-tile_bounds.origin.y as AzFloat);
|
||||||
|
|
||||||
paint_context.draw_target.set_transform(&matrix);
|
|
||||||
|
|
||||||
// Clear the buffer.
|
// Clear the buffer.
|
||||||
paint_context.clear();
|
paint_context.clear();
|
||||||
|
|
||||||
// Draw the display list.
|
// Draw the display list.
|
||||||
profile(time::PaintingPerTileCategory, None, self.time_profiler_sender.clone(), || {
|
profile(time::PaintingPerTileCategory, None, self.time_profiler_sender.clone(), || {
|
||||||
let mut clip_stack = Vec::new();
|
|
||||||
stacking_context.optimize_and_draw_into_context(&mut paint_context,
|
stacking_context.optimize_and_draw_into_context(&mut paint_context,
|
||||||
&tile.page_rect,
|
&tile.page_rect,
|
||||||
&matrix,
|
&matrix,
|
||||||
&mut clip_stack);
|
None);
|
||||||
paint_context.draw_target.flush();
|
paint_context.draw_target.flush();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
6
servo/components/servo/Cargo.lock
generated
6
servo/components/servo/Cargo.lock
generated
@ -25,7 +25,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "azure"
|
name = "azure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-azure#d323c3c7c248d3d5a2d46a6a5ee61c6e92aec0b0"
|
source = "git+https://github.com/servo/rust-azure#452939480f5ef7640714f16c6a9e5d02e0e2d147"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||||
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
||||||
@ -34,7 +34,7 @@ dependencies = [
|
|||||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
||||||
"geom 0.1.0 (git+https://github.com/servo/rust-geom)",
|
"geom 0.1.0 (git+https://github.com/servo/rust-geom)",
|
||||||
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
|
"layers 0.1.0 (git+https://github.com/servo/rust-layers)",
|
||||||
"skia-sys 0.0.20130412 (git+https://github.com/servo/skia)",
|
"skia-sys 0.0.20130412 (git+https://github.com/servo/skia?ref=upstream-2014-06-16)",
|
||||||
"xlib 0.1.0 (git+https://github.com/servo/rust-xlib)",
|
"xlib 0.1.0 (git+https://github.com/servo/rust-xlib)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -600,7 +600,7 @@ source = "git+https://github.com/rust-lang/semver#7dca047a9cd40e929a4545b37a1917
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "skia-sys"
|
name = "skia-sys"
|
||||||
version = "0.0.20130412"
|
version = "0.0.20130412"
|
||||||
source = "git+https://github.com/servo/skia#79aa9354837bc195b83fa041b9632ea628e6f7d0"
|
source = "git+https://github.com/servo/skia?ref=upstream-2014-06-16#c3dd8cacbddbfc20b0dae9b456ac1545b0402cff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"expat-sys 2.1.0 (git+https://github.com/servo/libexpat)",
|
"expat-sys 2.1.0 (git+https://github.com/servo/libexpat)",
|
||||||
"freetype-sys 2.4.11 (git+https://github.com/servo/libfreetype2)",
|
"freetype-sys 2.4.11 (git+https://github.com/servo/libfreetype2)",
|
||||||
|
Loading…
Reference in New Issue
Block a user