diff --git a/components/layout/block.rs b/components/layout/block.rs index f1ef7aa9423..1d9f85b4672 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -29,9 +29,9 @@ use app_units::{Au, MAX_AU}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; -use display_list_builder::StackingContextCollectionState; +use display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode}; +use display_list::{DisplayListBuildState, StackingContextCollectionFlags}; +use display_list::StackingContextCollectionState; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use floats::{ClearType, FloatKind, Floats, PlacementInfo}; use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag, GetBaseFlow}; diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs new file mode 100644 index 00000000000..57e79625633 --- /dev/null +++ b/components/layout/display_list/background.rs @@ -0,0 +1,549 @@ +/* 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/. */ + +//! Calculations for CSS images and CSS backgrounds. + +#![deny(unsafe_code)] + +// FIXME(rust-lang/rust#26264): Remove GenericEndingShape and GenericGradientItem. + +use app_units::Au; +use display_list::ToGfxColor; +use euclid::{Point2D, Size2D, Vector2D}; +use gfx::display_list; +use model::MaybeAuto; +use style::values::computed::{Angle, GradientItem}; +use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, Percentage}; +use style::values::computed::Position; +use style::values::computed::image::{EndingShape, LineDirection}; +use style::values::generics::background::BackgroundSize; +use style::values::generics::image::{Circle, Ellipse, ShapeExtent}; +use style::values::generics::image::EndingShape as GenericEndingShape; +use style::values::generics::image::GradientItem as GenericGradientItem; +use style::values::specified::background::RepeatKeyword; +use style::values::specified::position::{X, Y}; +use webrender_api::GradientStop; + +/// A helper data structure for gradients. +#[derive(Clone, Copy)] +struct StopRun { + start_offset: f32, + end_offset: f32, + start_index: usize, + stop_count: usize, +} + +/// For a given area and an image compute how big the +/// image should be displayed on the background. +pub fn compute_background_image_size( + bg_size: BackgroundSize, + bounds_size: Size2D, + intrinsic_size: Option>, +) -> Size2D { + match intrinsic_size { + None => match bg_size { + BackgroundSize::Cover | BackgroundSize::Contain => bounds_size, + BackgroundSize::Explicit { width, height } => Size2D::new( + MaybeAuto::from_style(width, bounds_size.width) + .specified_or_default(bounds_size.width), + MaybeAuto::from_style(height, bounds_size.height) + .specified_or_default(bounds_size.height), + ), + }, + Some(own_size) => { + // If `image_aspect_ratio` < `bounds_aspect_ratio`, the image is tall; otherwise, it is + // wide. + let image_aspect_ratio = own_size.width.to_f32_px() / own_size.height.to_f32_px(); + let bounds_aspect_ratio = + bounds_size.width.to_f32_px() / bounds_size.height.to_f32_px(); + match (bg_size, image_aspect_ratio < bounds_aspect_ratio) { + (BackgroundSize::Contain, false) | (BackgroundSize::Cover, true) => Size2D::new( + bounds_size.width, + bounds_size.width.scale_by(image_aspect_ratio.recip()), + ), + (BackgroundSize::Contain, true) | (BackgroundSize::Cover, false) => Size2D::new( + bounds_size.height.scale_by(image_aspect_ratio), + bounds_size.height, + ), + ( + BackgroundSize::Explicit { + width, + height: LengthOrPercentageOrAuto::Auto, + }, + _, + ) => { + let width = MaybeAuto::from_style(width, bounds_size.width) + .specified_or_default(own_size.width); + Size2D::new(width, width.scale_by(image_aspect_ratio.recip())) + }, + ( + BackgroundSize::Explicit { + width: LengthOrPercentageOrAuto::Auto, + height, + }, + _, + ) => { + let height = MaybeAuto::from_style(height, bounds_size.height) + .specified_or_default(own_size.height); + Size2D::new(height.scale_by(image_aspect_ratio), height) + }, + (BackgroundSize::Explicit { width, height }, _) => Size2D::new( + MaybeAuto::from_style(width, bounds_size.width) + .specified_or_default(own_size.width), + MaybeAuto::from_style(height, bounds_size.height) + .specified_or_default(own_size.height), + ), + } + }, + } +} + +fn tile_image_round( + position: &mut Au, + size: &mut Au, + absolute_anchor_origin: Au, + image_size: &mut Au, +) { + if *size == Au(0) || *image_size == Au(0) { + *position = Au(0); + *size = Au(0); + return; + } + + let number_of_tiles = (size.to_f32_px() / image_size.to_f32_px()).round().max(1.0); + *image_size = *size / (number_of_tiles as i32); + tile_image(position, size, absolute_anchor_origin, *image_size); +} + +fn tile_image_spaced( + position: &mut Au, + size: &mut Au, + tile_spacing: &mut Au, + absolute_anchor_origin: Au, + image_size: Au, +) { + if *size == Au(0) || image_size == Au(0) { + *position = Au(0); + *size = Au(0); + *tile_spacing = Au(0); + return; + } + + // Per the spec, if the space available is not enough for two images, just tile as + // normal but only display a single tile. + if image_size * 2 >= *size { + tile_image(position, size, absolute_anchor_origin, image_size); + *tile_spacing = Au(0); + *size = image_size; + return; + } + + // Take the box size, remove room for two tiles on the edges, and then calculate how many + // other tiles fit in between them. + let size_remaining = *size - (image_size * 2); + let num_middle_tiles = (size_remaining.to_f32_px() / image_size.to_f32_px()).floor() as i32; + + // Allocate the remaining space as padding between tiles. background-position is ignored + // as per the spec, so the position is just the box origin. We are also ignoring + // background-attachment here, which seems unspecced when combined with + // background-repeat: space. + let space_for_middle_tiles = image_size * num_middle_tiles; + *tile_spacing = (size_remaining - space_for_middle_tiles) / (num_middle_tiles + 1); +} + +/// Tile an image +fn tile_image(position: &mut Au, size: &mut Au, absolute_anchor_origin: Au, image_size: Au) { + // Avoid division by zero below! + // Images with a zero width or height are not displayed. + // Therefore the positions do not matter and can be left unchanged. + // NOTE: A possible optimization is not to build + // display items in this case at all. + if image_size == Au(0) { + return; + } + + let delta_pixels = absolute_anchor_origin - *position; + let image_size_px = image_size.to_f32_px(); + let tile_count = ((delta_pixels.to_f32_px() + image_size_px - 1.0) / image_size_px).floor(); + let offset = image_size * (tile_count as i32); + let new_position = absolute_anchor_origin - offset; + *size = *position - new_position + *size; + *position = new_position; +} + +/// For either the x or the y axis ajust various values to account for tiling. +/// +/// This is done separately for both axes because the repeat keywords may differ. +pub fn tile_image_axis( + repeat: RepeatKeyword, + position: &mut Au, + size: &mut Au, + tile_size: &mut Au, + tile_spacing: &mut Au, + offset: Au, + clip_origin: Au, + clip_size: Au, +) { + let absolute_anchor_origin = *position + offset; + match repeat { + RepeatKeyword::NoRepeat => { + *position += offset; + *size = *tile_size; + }, + RepeatKeyword::Repeat => { + *position = clip_origin; + *size = clip_size; + tile_image(position, size, absolute_anchor_origin, *tile_size); + }, + RepeatKeyword::Space => { + tile_image_spaced( + position, + size, + tile_spacing, + absolute_anchor_origin, + *tile_size, + ); + let combined_tile_size = *tile_size + *tile_spacing; + *position = clip_origin; + *size = clip_size; + tile_image(position, size, absolute_anchor_origin, combined_tile_size); + }, + RepeatKeyword::Round => { + tile_image_round(position, size, absolute_anchor_origin, tile_size); + *position = clip_origin; + *size = clip_size; + tile_image(position, size, absolute_anchor_origin, *tile_size); + }, + } +} + +/// Determines the radius of a circle if it was not explictly provided. +/// +fn convert_circle_size_keyword( + keyword: ShapeExtent, + size: &Size2D, + center: &Point2D, +) -> Size2D { + let radius = match keyword { + ShapeExtent::ClosestSide | ShapeExtent::Contain => { + let dist = get_distance_to_sides(size, center, ::std::cmp::min); + ::std::cmp::min(dist.width, dist.height) + }, + ShapeExtent::FarthestSide => { + let dist = get_distance_to_sides(size, center, ::std::cmp::max); + ::std::cmp::max(dist.width, dist.height) + }, + ShapeExtent::ClosestCorner => get_distance_to_corner(size, center, ::std::cmp::min), + ShapeExtent::FarthestCorner | ShapeExtent::Cover => { + get_distance_to_corner(size, center, ::std::cmp::max) + }, + }; + Size2D::new(radius, radius) +} + +/// Returns the radius for an ellipse with the same ratio as if it was matched to the sides. +fn get_ellipse_radius(size: &Size2D, center: &Point2D, cmp: F) -> Size2D +where + F: Fn(Au, Au) -> Au, +{ + let dist = get_distance_to_sides(size, center, cmp); + Size2D::new( + dist.width.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0), + dist.height + .scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0), + ) +} + +/// Determines the radius of an ellipse if it was not explictly provided. +/// +fn convert_ellipse_size_keyword( + keyword: ShapeExtent, + size: &Size2D, + center: &Point2D, +) -> Size2D { + match keyword { + ShapeExtent::ClosestSide | ShapeExtent::Contain => { + get_distance_to_sides(size, center, ::std::cmp::min) + }, + ShapeExtent::FarthestSide => get_distance_to_sides(size, center, ::std::cmp::max), + ShapeExtent::ClosestCorner => get_ellipse_radius(size, center, ::std::cmp::min), + ShapeExtent::FarthestCorner | ShapeExtent::Cover => { + get_ellipse_radius(size, center, ::std::cmp::max) + }, + } +} + +fn convert_gradient_stops(gradient_items: &[GradientItem], total_length: Au) -> Vec { + // Determine the position of each stop per CSS-IMAGES § 3.4. + + // Only keep the color stops, discard the color interpolation hints. + let mut stop_items = gradient_items + .iter() + .filter_map(|item| match *item { + GenericGradientItem::ColorStop(ref stop) => Some(*stop), + _ => None, + }) + .collect::>(); + + assert!(stop_items.len() >= 2); + + // Run the algorithm from + // https://drafts.csswg.org/css-images-3/#color-stop-syntax + + // Step 1: + // If the first color stop does not have a position, set its position to 0%. + { + let first = stop_items.first_mut().unwrap(); + if first.position.is_none() { + first.position = Some(LengthOrPercentage::Percentage(Percentage(0.0))); + } + } + // If the last color stop does not have a position, set its position to 100%. + { + let last = stop_items.last_mut().unwrap(); + if last.position.is_none() { + last.position = Some(LengthOrPercentage::Percentage(Percentage(1.0))); + } + } + + // Step 2: Move any stops placed before earlier stops to the + // same position as the preceding stop. + let mut last_stop_position = stop_items.first().unwrap().position.unwrap(); + for stop in stop_items.iter_mut().skip(1) { + if let Some(pos) = stop.position { + if position_to_offset(last_stop_position, total_length) > + position_to_offset(pos, total_length) + { + stop.position = Some(last_stop_position); + } + last_stop_position = stop.position.unwrap(); + } + } + + // Step 3: Evenly space stops without position. + // Note: Remove the + 2 if fix_gradient_stops is changed. + let mut stops = Vec::with_capacity(stop_items.len() + 2); + let mut stop_run = None; + for (i, stop) in stop_items.iter().enumerate() { + let offset = match stop.position { + None => { + if stop_run.is_none() { + // Initialize a new stop run. + // `unwrap()` here should never fail because this is the beginning of + // a stop run, which is always bounded by a length or percentage. + let start_offset = + position_to_offset(stop_items[i - 1].position.unwrap(), total_length); + // `unwrap()` here should never fail because this is the end of + // a stop run, which is always bounded by a length or percentage. + let (end_index, end_stop) = stop_items[(i + 1)..] + .iter() + .enumerate() + .find(|&(_, ref stop)| stop.position.is_some()) + .unwrap(); + let end_offset = position_to_offset(end_stop.position.unwrap(), total_length); + stop_run = Some(StopRun { + start_offset: start_offset, + end_offset: end_offset, + start_index: i - 1, + stop_count: end_index, + }) + } + + let stop_run = stop_run.unwrap(); + let stop_run_length = stop_run.end_offset - stop_run.start_offset; + stop_run.start_offset + + stop_run_length * (i - stop_run.start_index) as f32 / + ((2 + stop_run.stop_count) as f32) + }, + Some(position) => { + stop_run = None; + position_to_offset(position, total_length) + }, + }; + assert!(offset.is_finite()); + stops.push(GradientStop { + offset: offset, + color: stop.color.to_gfx_color(), + }) + } + stops +} + +pub fn convert_linear_gradient( + size: Size2D, + stops: &[GradientItem], + direction: LineDirection, + repeating: bool, +) -> display_list::Gradient { + let angle = match direction { + LineDirection::Angle(angle) => angle.radians(), + LineDirection::Horizontal(x) => match x { + X::Left => Angle::Deg(270.).radians(), + X::Right => Angle::Deg(90.).radians(), + }, + LineDirection::Vertical(y) => match y { + Y::Top => Angle::Deg(0.).radians(), + Y::Bottom => Angle::Deg(180.).radians(), + }, + LineDirection::Corner(horizontal, vertical) => { + // This the angle for one of the diagonals of the box. Our angle + // will either be this one, this one + PI, or one of the other + // two perpendicular angles. + let atan = (size.height.to_f32_px() / size.width.to_f32_px()).atan(); + match (horizontal, vertical) { + (X::Right, Y::Bottom) => ::std::f32::consts::PI - atan, + (X::Left, Y::Bottom) => ::std::f32::consts::PI + atan, + (X::Right, Y::Top) => atan, + (X::Left, Y::Top) => -atan, + } + }, + }; + + // Get correct gradient line length, based on: + // https://drafts.csswg.org/css-images-3/#linear-gradients + let dir = Point2D::new(angle.sin(), -angle.cos()); + + let line_length = + (dir.x * size.width.to_f32_px()).abs() + (dir.y * size.height.to_f32_px()).abs(); + + let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt(); + + // This is the vector between the center and the ending point; i.e. half + // of the distance between the starting point and the ending point. + let delta = Vector2D::new( + Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0), + Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0), + ); + + // This is the length of the gradient line. + let length = Au::from_f32_px((delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); + + let mut stops = convert_gradient_stops(stops, length); + + // Only clamped gradients need to be fixed because in repeating gradients + // there is no "first" or "last" stop because they repeat infinitly in + // both directions, so the rendering is always correct. + if !repeating { + fix_gradient_stops(&mut stops); + } + + let center = Point2D::new(size.width / 2, size.height / 2); + + display_list::Gradient { + start_point: center - delta, + end_point: center + delta, + stops: stops, + repeating: repeating, + } +} + +pub fn convert_radial_gradient( + size: Size2D, + stops: &[GradientItem], + shape: EndingShape, + center: Position, + repeating: bool, +) -> display_list::RadialGradient { + let center = Point2D::new( + center.horizontal.to_used_value(size.width), + center.vertical.to_used_value(size.height), + ); + let radius = match shape { + GenericEndingShape::Circle(Circle::Radius(length)) => { + let length = Au::from(length); + Size2D::new(length, length) + }, + GenericEndingShape::Circle(Circle::Extent(extent)) => { + convert_circle_size_keyword(extent, &size, ¢er) + }, + GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => { + Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height)) + }, + GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => { + convert_ellipse_size_keyword(extent, &size, ¢er) + }, + }; + + let mut stops = convert_gradient_stops(stops, radius.width); + // Repeating gradients have no last stops that can be ignored. So + // fixup is not necessary but may actually break the gradient. + if !repeating { + fix_gradient_stops(&mut stops); + } + + display_list::RadialGradient { + center: center, + radius: radius, + stops: stops, + repeating: repeating, + } +} + +#[inline] +/// Duplicate the first and last stops if necessary. +/// +/// Explanation by pyfisch: +/// If the last stop is at the same position as the previous stop the +/// last color is ignored by webrender. This differs from the spec +/// (I think so). The implementations of Chrome and Firefox seem +/// to have the same problem but work fine if the position of the last +/// stop is smaller than 100%. (Otherwise they ignore the last stop.) +/// +/// Similarly the first stop is duplicated if it is not placed +/// at the start of the virtual gradient ray. +fn fix_gradient_stops(stops: &mut Vec) { + if stops.first().unwrap().offset > 0.0 { + let color = stops.first().unwrap().color; + stops.insert( + 0, + GradientStop { + offset: 0.0, + color: color, + }, + ) + } + if stops.last().unwrap().offset < 1.0 { + let color = stops.last().unwrap().color; + stops.push(GradientStop { + offset: 1.0, + color: color, + }) + } +} + +/// Returns the the distance to the nearest or farthest corner depending on the comperator. +fn get_distance_to_corner(size: &Size2D, center: &Point2D, cmp: F) -> Au +where + F: Fn(Au, Au) -> Au, +{ + let dist = get_distance_to_sides(size, center, cmp); + Au::from_f32_px(dist.width.to_f32_px().hypot(dist.height.to_f32_px())) +} + +/// Returns the distance to the nearest or farthest sides depending on the comparator. +/// +/// The first return value is horizontal distance the second vertical distance. +fn get_distance_to_sides(size: &Size2D, center: &Point2D, cmp: F) -> Size2D +where + F: Fn(Au, Au) -> Au, +{ + let top_side = center.y; + let right_side = size.width - center.x; + let bottom_side = size.height - center.y; + let left_side = center.x; + Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side)) +} + +fn position_to_offset(position: LengthOrPercentage, total_length: Au) -> f32 { + if total_length == Au(0) { + return 0.0; + } + match position { + LengthOrPercentage::Length(l) => l.to_i32_au() as f32 / total_length.0 as f32, + LengthOrPercentage::Percentage(percentage) => percentage.0 as f32, + LengthOrPercentage::Calc(calc) => { + calc.to_used_value(Some(total_length)).unwrap().0 as f32 / total_length.0 as f32 + }, + } +} diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list/builder.rs similarity index 84% rename from components/layout/display_list_builder.rs rename to components/layout/display_list/builder.rs index 05413836acc..5eac20ccbd3 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list/builder.rs @@ -14,6 +14,9 @@ use app_units::{Au, AU_PER_PX}; use block::{BlockFlow, BlockStackingContextType}; use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg}; use context::LayoutContext; +use display_list::background::{compute_background_image_size, tile_image_axis}; +use display_list::background::{convert_linear_gradient, convert_radial_gradient}; +use display_list::webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedRect, TypedSize2D, Vector2D}; use flex::FlexFlow; use flow::{BaseFlow, Flow, FlowFlags}; @@ -64,25 +67,17 @@ use style::properties::longhands::border_image_repeat::computed_value::RepeatKey use style::properties::style_structs; use style::servo::restyle_damage::ServoRestyleDamage; use style::values::{Either, RGBA}; -use style::values::computed::{Angle, Gradient, GradientItem, LengthOrPercentage, Percentage}; -use style::values::computed::{LengthOrPercentageOrAuto, NumberOrPercentage, Position}; +use style::values::computed::{Gradient, NumberOrPercentage}; use style::values::computed::effects::SimpleShadow; -use style::values::computed::image::{EndingShape, LineDirection}; use style::values::generics::background::BackgroundSize; use style::values::generics::effects::Filter; -use style::values::generics::image::{Circle, Ellipse, EndingShape as GenericEndingShape}; -use style::values::generics::image::{GradientItem as GenericGradientItem, GradientKind}; -use style::values::generics::image::{Image, ShapeExtent}; -use style::values::generics::image::PaintWorklet; -use style::values::specified::background::RepeatKeyword as BackgroundRepeatKeyword; -use style::values::specified::position::{X, Y}; +use style::values::generics::image::{GradientKind, Image, PaintWorklet}; use style_traits::CSSPixel; use style_traits::ToCss; use style_traits::cursor::Cursor; use table_cell::CollapsedBordersForCell; -use webrender_api::{ClipId, ClipMode, ColorF, ComplexClipRegion, GradientStop, LineStyle}; +use webrender_api::{ClipId, ClipMode, ColorF, ComplexClipRegion, LineStyle}; use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, StickyOffsetBounds}; -use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle}; trait ResolvePercentage { fn resolve(&self, length: u32) -> u32; @@ -525,12 +520,6 @@ impl<'a> DisplayListBuildState<'a> { /// The logical width of an insertion point: at the moment, a one-pixel-wide line. const INSERTION_POINT_LOGICAL_WIDTH: Au = Au(1 * AU_PER_PX); -pub enum IdType { - StackingContext, - OverflowClip, - CSSClip, -} - pub trait FragmentDisplayListBuilding { fn collect_stacking_contexts_for_blocklike_fragment( &mut self, @@ -721,7 +710,7 @@ pub trait FragmentDisplayListBuilding { parent_clipping_and_scrolling: ClippingAndScrolling, ) -> StackingContext; - fn unique_id(&self, id_type: IdType) -> u64; + fn unique_id(&self) -> u64; fn fragment_type(&self) -> FragmentType; } @@ -824,323 +813,6 @@ fn build_inner_border_box_for_border_rect( inner_border_box } -fn convert_gradient_stops(gradient_items: &[GradientItem], total_length: Au) -> Vec { - // Determine the position of each stop per CSS-IMAGES § 3.4. - - // Only keep the color stops, discard the color interpolation hints. - let mut stop_items = gradient_items - .iter() - .filter_map(|item| match *item { - GenericGradientItem::ColorStop(ref stop) => Some(*stop), - _ => None, - }) - .collect::>(); - - assert!(stop_items.len() >= 2); - - // Run the algorithm from - // https://drafts.csswg.org/css-images-3/#color-stop-syntax - - // Step 1: - // If the first color stop does not have a position, set its position to 0%. - { - let first = stop_items.first_mut().unwrap(); - if first.position.is_none() { - first.position = Some(LengthOrPercentage::Percentage(Percentage(0.0))); - } - } - // If the last color stop does not have a position, set its position to 100%. - { - let last = stop_items.last_mut().unwrap(); - if last.position.is_none() { - last.position = Some(LengthOrPercentage::Percentage(Percentage(1.0))); - } - } - - // Step 2: Move any stops placed before earlier stops to the - // same position as the preceding stop. - let mut last_stop_position = stop_items.first().unwrap().position.unwrap(); - for stop in stop_items.iter_mut().skip(1) { - if let Some(pos) = stop.position { - if position_to_offset(last_stop_position, total_length) > - position_to_offset(pos, total_length) - { - stop.position = Some(last_stop_position); - } - last_stop_position = stop.position.unwrap(); - } - } - - // Step 3: Evenly space stops without position. - // Note: Remove the + 2 if fix_gradient_stops is changed. - let mut stops = Vec::with_capacity(stop_items.len() + 2); - let mut stop_run = None; - for (i, stop) in stop_items.iter().enumerate() { - let offset = match stop.position { - None => { - if stop_run.is_none() { - // Initialize a new stop run. - // `unwrap()` here should never fail because this is the beginning of - // a stop run, which is always bounded by a length or percentage. - let start_offset = - position_to_offset(stop_items[i - 1].position.unwrap(), total_length); - // `unwrap()` here should never fail because this is the end of - // a stop run, which is always bounded by a length or percentage. - let (end_index, end_stop) = stop_items[(i + 1)..] - .iter() - .enumerate() - .find(|&(_, ref stop)| stop.position.is_some()) - .unwrap(); - let end_offset = position_to_offset(end_stop.position.unwrap(), total_length); - stop_run = Some(StopRun { - start_offset: start_offset, - end_offset: end_offset, - start_index: i - 1, - stop_count: end_index, - }) - } - - let stop_run = stop_run.unwrap(); - let stop_run_length = stop_run.end_offset - stop_run.start_offset; - stop_run.start_offset + - stop_run_length * (i - stop_run.start_index) as f32 / - ((2 + stop_run.stop_count) as f32) - }, - Some(position) => { - stop_run = None; - position_to_offset(position, total_length) - }, - }; - assert!(offset.is_finite()); - stops.push(GradientStop { - offset: offset, - color: stop.color.to_gfx_color(), - }) - } - stops -} - -fn convert_linear_gradient( - size: Size2D, - stops: &[GradientItem], - direction: LineDirection, - repeating: bool, -) -> display_list::Gradient { - let angle = match direction { - LineDirection::Angle(angle) => angle.radians(), - LineDirection::Horizontal(x) => match x { - X::Left => Angle::Deg(270.).radians(), - X::Right => Angle::Deg(90.).radians(), - }, - LineDirection::Vertical(y) => match y { - Y::Top => Angle::Deg(0.).radians(), - Y::Bottom => Angle::Deg(180.).radians(), - }, - LineDirection::Corner(horizontal, vertical) => { - // This the angle for one of the diagonals of the box. Our angle - // will either be this one, this one + PI, or one of the other - // two perpendicular angles. - let atan = (size.height.to_f32_px() / size.width.to_f32_px()).atan(); - match (horizontal, vertical) { - (X::Right, Y::Bottom) => f32::consts::PI - atan, - (X::Left, Y::Bottom) => f32::consts::PI + atan, - (X::Right, Y::Top) => atan, - (X::Left, Y::Top) => -atan, - } - }, - }; - - // Get correct gradient line length, based on: - // https://drafts.csswg.org/css-images-3/#linear-gradients - let dir = Point2D::new(angle.sin(), -angle.cos()); - - let line_length = - (dir.x * size.width.to_f32_px()).abs() + (dir.y * size.height.to_f32_px()).abs(); - - let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt(); - - // This is the vector between the center and the ending point; i.e. half - // of the distance between the starting point and the ending point. - let delta = Vector2D::new( - Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0), - Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0), - ); - - // This is the length of the gradient line. - let length = Au::from_f32_px((delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0)); - - let mut stops = convert_gradient_stops(stops, length); - - // Only clamped gradients need to be fixed because in repeating gradients - // there is no "first" or "last" stop because they repeat infinitly in - // both directions, so the rendering is always correct. - if !repeating { - fix_gradient_stops(&mut stops); - } - - let center = Point2D::new(size.width / 2, size.height / 2); - - display_list::Gradient { - start_point: center - delta, - end_point: center + delta, - stops: stops, - repeating: repeating, - } -} - -fn convert_radial_gradient( - size: Size2D, - stops: &[GradientItem], - shape: EndingShape, - center: Position, - repeating: bool, -) -> display_list::RadialGradient { - let center = Point2D::new( - center.horizontal.to_used_value(size.width), - center.vertical.to_used_value(size.height), - ); - let radius = match shape { - GenericEndingShape::Circle(Circle::Radius(length)) => { - let length = Au::from(length); - Size2D::new(length, length) - }, - GenericEndingShape::Circle(Circle::Extent(extent)) => { - convert_circle_size_keyword(extent, &size, ¢er) - }, - GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => { - Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height)) - }, - GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => { - convert_ellipse_size_keyword(extent, &size, ¢er) - }, - }; - - let mut stops = convert_gradient_stops(stops, radius.width); - // Repeating gradients have no last stops that can be ignored. So - // fixup is not necessary but may actually break the gradient. - if !repeating { - fix_gradient_stops(&mut stops); - } - - display_list::RadialGradient { - center: center, - radius: radius, - stops: stops, - repeating: repeating, - } -} - -#[inline] -/// Duplicate the first and last stops if necessary. -/// -/// Explanation by pyfisch: -/// If the last stop is at the same position as the previous stop the -/// last color is ignored by webrender. This differs from the spec -/// (I think so). The implementations of Chrome and Firefox seem -/// to have the same problem but work fine if the position of the last -/// stop is smaller than 100%. (Otherwise they ignore the last stop.) -/// -/// Similarly the first stop is duplicated if it is not placed -/// at the start of the virtual gradient ray. -fn fix_gradient_stops(stops: &mut Vec) { - if stops.first().unwrap().offset > 0.0 { - let color = stops.first().unwrap().color; - stops.insert( - 0, - GradientStop { - offset: 0.0, - color: color, - }, - ) - } - if stops.last().unwrap().offset < 1.0 { - let color = stops.last().unwrap().color; - stops.push(GradientStop { - offset: 1.0, - color: color, - }) - } -} - -/// Returns the the distance to the nearest or farthest corner depending on the comperator. -fn get_distance_to_corner(size: &Size2D, center: &Point2D, cmp: F) -> Au -where - F: Fn(Au, Au) -> Au, -{ - let dist = get_distance_to_sides(size, center, cmp); - Au::from_f32_px(dist.width.to_f32_px().hypot(dist.height.to_f32_px())) -} - -/// Returns the distance to the nearest or farthest sides depending on the comparator. -/// -/// The first return value is horizontal distance the second vertical distance. -fn get_distance_to_sides(size: &Size2D, center: &Point2D, cmp: F) -> Size2D -where - F: Fn(Au, Au) -> Au, -{ - let top_side = center.y; - let right_side = size.width - center.x; - let bottom_side = size.height - center.y; - let left_side = center.x; - Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side)) -} - -/// Returns the radius for an ellipse with the same ratio as if it was matched to the sides. -fn get_ellipse_radius(size: &Size2D, center: &Point2D, cmp: F) -> Size2D -where - F: Fn(Au, Au) -> Au, -{ - let dist = get_distance_to_sides(size, center, cmp); - Size2D::new( - dist.width.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0), - dist.height - .scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0), - ) -} - -/// Determines the radius of a circle if it was not explictly provided. -/// -fn convert_circle_size_keyword( - keyword: ShapeExtent, - size: &Size2D, - center: &Point2D, -) -> Size2D { - let radius = match keyword { - ShapeExtent::ClosestSide | ShapeExtent::Contain => { - let dist = get_distance_to_sides(size, center, ::std::cmp::min); - ::std::cmp::min(dist.width, dist.height) - }, - ShapeExtent::FarthestSide => { - let dist = get_distance_to_sides(size, center, ::std::cmp::max); - ::std::cmp::max(dist.width, dist.height) - }, - ShapeExtent::ClosestCorner => get_distance_to_corner(size, center, ::std::cmp::min), - ShapeExtent::FarthestCorner | ShapeExtent::Cover => { - get_distance_to_corner(size, center, ::std::cmp::max) - }, - }; - Size2D::new(radius, radius) -} - -/// Determines the radius of an ellipse if it was not explictly provided. -/// -fn convert_ellipse_size_keyword( - keyword: ShapeExtent, - size: &Size2D, - center: &Point2D, -) -> Size2D { - match keyword { - ShapeExtent::ClosestSide | ShapeExtent::Contain => { - get_distance_to_sides(size, center, ::std::cmp::min) - }, - ShapeExtent::FarthestSide => get_distance_to_sides(size, center, ::std::cmp::max), - ShapeExtent::ClosestCorner => get_ellipse_radius(size, center, ::std::cmp::min), - ShapeExtent::FarthestCorner | ShapeExtent::Cover => { - get_ellipse_radius(size, center, ::std::cmp::max) - }, - } -} - /// Subtract offsets from a bounding box. /// /// As an example if the bounds are the border-box and the border @@ -1171,194 +843,6 @@ fn calculate_inner_border_radii( radii } -/// For a given area and an image compute how big the -/// image should be displayed on the background. -fn compute_background_image_size( - bg_size: BackgroundSize, - bounds_size: Size2D, - intrinsic_size: Option>, -) -> Size2D { - match intrinsic_size { - None => match bg_size { - BackgroundSize::Cover | BackgroundSize::Contain => bounds_size, - BackgroundSize::Explicit { width, height } => Size2D::new( - MaybeAuto::from_style(width, bounds_size.width) - .specified_or_default(bounds_size.width), - MaybeAuto::from_style(height, bounds_size.height) - .specified_or_default(bounds_size.height), - ), - }, - Some(own_size) => { - // If `image_aspect_ratio` < `bounds_aspect_ratio`, the image is tall; otherwise, it is - // wide. - let image_aspect_ratio = own_size.width.to_f32_px() / own_size.height.to_f32_px(); - let bounds_aspect_ratio = - bounds_size.width.to_f32_px() / bounds_size.height.to_f32_px(); - match (bg_size, image_aspect_ratio < bounds_aspect_ratio) { - (BackgroundSize::Contain, false) | (BackgroundSize::Cover, true) => Size2D::new( - bounds_size.width, - bounds_size.width.scale_by(image_aspect_ratio.recip()), - ), - - (BackgroundSize::Contain, true) | (BackgroundSize::Cover, false) => Size2D::new( - bounds_size.height.scale_by(image_aspect_ratio), - bounds_size.height, - ), - - ( - BackgroundSize::Explicit { - width, - height: LengthOrPercentageOrAuto::Auto, - }, - _, - ) => { - let width = MaybeAuto::from_style(width, bounds_size.width) - .specified_or_default(own_size.width); - Size2D::new(width, width.scale_by(image_aspect_ratio.recip())) - }, - - ( - BackgroundSize::Explicit { - width: LengthOrPercentageOrAuto::Auto, - height, - }, - _, - ) => { - let height = MaybeAuto::from_style(height, bounds_size.height) - .specified_or_default(own_size.height); - Size2D::new(height.scale_by(image_aspect_ratio), height) - }, - - (BackgroundSize::Explicit { width, height }, _) => Size2D::new( - MaybeAuto::from_style(width, bounds_size.width) - .specified_or_default(own_size.width), - MaybeAuto::from_style(height, bounds_size.height) - .specified_or_default(own_size.height), - ), - } - }, - } -} - -fn tile_image_round( - position: &mut Au, - size: &mut Au, - absolute_anchor_origin: Au, - image_size: &mut Au, -) { - if *size == Au(0) || *image_size == Au(0) { - *position = Au(0); - *size = Au(0); - return; - } - - let number_of_tiles = (size.to_f32_px() / image_size.to_f32_px()).round().max(1.0); - *image_size = *size / (number_of_tiles as i32); - tile_image(position, size, absolute_anchor_origin, *image_size); -} - -fn tile_image_spaced( - position: &mut Au, - size: &mut Au, - tile_spacing: &mut Au, - absolute_anchor_origin: Au, - image_size: Au, -) { - if *size == Au(0) || image_size == Au(0) { - *position = Au(0); - *size = Au(0); - *tile_spacing = Au(0); - return; - } - - // Per the spec, if the space available is not enough for two images, just tile as - // normal but only display a single tile. - if image_size * 2 >= *size { - tile_image(position, size, absolute_anchor_origin, image_size); - *tile_spacing = Au(0); - *size = image_size; - return; - } - - // Take the box size, remove room for two tiles on the edges, and then calculate how many - // other tiles fit in between them. - let size_remaining = *size - (image_size * 2); - let num_middle_tiles = (size_remaining.to_f32_px() / image_size.to_f32_px()).floor() as i32; - - // Allocate the remaining space as padding between tiles. background-position is ignored - // as per the spec, so the position is just the box origin. We are also ignoring - // background-attachment here, which seems unspecced when combined with - // background-repeat: space. - let space_for_middle_tiles = image_size * num_middle_tiles; - *tile_spacing = (size_remaining - space_for_middle_tiles) / (num_middle_tiles + 1); -} - -/// Tile an image -fn tile_image(position: &mut Au, size: &mut Au, absolute_anchor_origin: Au, image_size: Au) { - // Avoid division by zero below! - // Images with a zero width or height are not displayed. - // Therefore the positions do not matter and can be left unchanged. - // NOTE: A possible optimization is not to build - // display items in this case at all. - if image_size == Au(0) { - return; - } - - let delta_pixels = absolute_anchor_origin - *position; - let image_size_px = image_size.to_f32_px(); - let tile_count = ((delta_pixels.to_f32_px() + image_size_px - 1.0) / image_size_px).floor(); - let offset = image_size * (tile_count as i32); - let new_position = absolute_anchor_origin - offset; - *size = *position - new_position + *size; - *position = new_position; -} - -/// For either the x or the y axis ajust various values to account for tiling. -/// -/// This is done separately for both axes because the repeat keywords may differ. -fn tile_image_axis( - repeat: BackgroundRepeatKeyword, - position: &mut Au, - size: &mut Au, - tile_size: &mut Au, - tile_spacing: &mut Au, - offset: Au, - clip_origin: Au, - clip_size: Au, -) { - let absolute_anchor_origin = *position + offset; - match repeat { - BackgroundRepeatKeyword::NoRepeat => { - *position += offset; - *size = *tile_size; - }, - BackgroundRepeatKeyword::Repeat => { - *position = clip_origin; - *size = clip_size; - tile_image(position, size, absolute_anchor_origin, *tile_size); - }, - BackgroundRepeatKeyword::Space => { - tile_image_spaced( - position, - size, - tile_spacing, - absolute_anchor_origin, - *tile_size, - ); - let combined_tile_size = *tile_size + *tile_spacing; - *position = clip_origin; - *size = clip_size; - tile_image(position, size, absolute_anchor_origin, combined_tile_size); - }, - BackgroundRepeatKeyword::Round => { - tile_image_round(position, size, absolute_anchor_origin, tile_size); - *position = clip_origin; - *size = clip_size; - tile_image(position, size, absolute_anchor_origin, *tile_size); - }, - } -} - impl FragmentDisplayListBuilding for Fragment { fn collect_stacking_contexts_for_blocklike_fragment( &mut self, @@ -1907,48 +1391,39 @@ impl FragmentDisplayListBuilding for Fragment { }))); }, Either::Second(Image::Gradient(ref gradient)) => { - match gradient.kind { + let border_widths = border.to_physical(style.writing_mode); + let details = match gradient.kind { GradientKind::Linear(angle_or_corner) => { - let grad = convert_linear_gradient( - bounds.size, - &gradient.items[..], - angle_or_corner, - gradient.repeating, - ); - - state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { - base: base, - border_widths: border.to_physical(style.writing_mode), - details: BorderDetails::Gradient(display_list::GradientBorder { - gradient: grad, - - // TODO(gw): Support border-image-outset - outset: SideOffsets2D::zero(), - }), - }))); + BorderDetails::Gradient(display_list::GradientBorder { + gradient: convert_linear_gradient( + bounds.size, + &gradient.items[..], + angle_or_corner, + gradient.repeating, + ), + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }) }, GradientKind::Radial(shape, center, _angle) => { - let grad = convert_radial_gradient( - bounds.size, - &gradient.items[..], - shape, - center, - gradient.repeating, - ); - state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { - base: base, - border_widths: border.to_physical(style.writing_mode), - details: BorderDetails::RadialGradient( - display_list::RadialGradientBorder { - gradient: grad, - - // TODO(gw): Support border-image-outset - outset: SideOffsets2D::zero(), - }, + BorderDetails::RadialGradient(display_list::RadialGradientBorder { + gradient: convert_radial_gradient( + bounds.size, + &gradient.items[..], + shape, + center, + gradient.repeating, ), - }))); + // TODO(gw): Support border-image-outset + outset: SideOffsets2D::zero(), + }) }, - } + }; + state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem { + base, + border_widths, + details, + }))); }, Either::Second(Image::PaintWorklet(ref paint_worklet)) => { // TODO: this size should be increased by border-image-outset @@ -2796,12 +2271,9 @@ impl FragmentDisplayListBuilding for Fragment { }))); } - fn unique_id(&self, id_type: IdType) -> u64 { + fn unique_id(&self) -> u64 { let fragment_type = self.fragment_type(); - let id = match id_type { - IdType::StackingContext | IdType::OverflowClip => self.node.id() as usize, - IdType::CSSClip => self as *const _ as usize, - }; + let id = self.node.id() as usize; combine_id_with_fragment_type(id, fragment_type) as u64 } @@ -3265,7 +2737,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow { // when fragments map to more than one flow, such as in the case of table // wrappers. We just accept the first scroll root in that case. let new_clip_scroll_node_id = ClipId::new( - self.fragment.unique_id(IdType::OverflowClip), + self.fragment.unique_id(), state.pipeline_id.to_webrender(), ); @@ -3711,28 +3183,6 @@ impl ComputedValuesCursorUtility for ComputedValues { } } -// A helper data structure for gradients. -#[derive(Clone, Copy)] -struct StopRun { - start_offset: f32, - end_offset: f32, - start_index: usize, - stop_count: usize, -} - -fn position_to_offset(position: LengthOrPercentage, total_length: Au) -> f32 { - if total_length == Au(0) { - return 0.0; - } - match position { - LengthOrPercentage::Length(l) => l.to_i32_au() as f32 / total_length.0 as f32, - LengthOrPercentage::Percentage(percentage) => percentage.0 as f32, - LengthOrPercentage::Calc(calc) => { - calc.to_used_value(Some(total_length)).unwrap().0 as f32 / total_length.0 as f32 - }, - } -} - /// Adjusts `content_rect` as necessary for the given spread, and blur so that the resulting /// bounding rect contains all of a shadow's ink. fn shadow_bounds(content_rect: &Rect, blur: Au, spread: Au) -> Rect { diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs new file mode 100644 index 00000000000..3f733f783a6 --- /dev/null +++ b/components/layout/display_list/mod.rs @@ -0,0 +1,18 @@ +/* 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/. */ + +pub use self::builder::BlockFlowDisplayListBuilding; +pub use self::builder::BorderPaintingMode; +pub use self::builder::DisplayListBuildState; +pub use self::builder::FlexFlowDisplayListBuilding; +pub use self::builder::InlineFlowDisplayListBuilding; +pub use self::builder::ListItemFlowDisplayListBuilding; +pub use self::builder::StackingContextCollectionFlags; +pub use self::builder::StackingContextCollectionState; +pub use self::builder::ToGfxColor; +pub use self::webrender_helpers::WebRenderDisplayListConverter; + +mod background; +mod builder; +mod webrender_helpers; diff --git a/components/layout/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs similarity index 100% rename from components/layout/webrender_helpers.rs rename to components/layout/display_list/webrender_helpers.rs diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 5cbb80263ac..58abdee6c52 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -9,8 +9,8 @@ use app_units::{Au, MAX_AU}; use block::{AbsoluteAssignBSizesTraversal, BlockFlow, MarginsMayCollapseFlag}; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, FlexFlowDisplayListBuilding}; -use display_list_builder::StackingContextCollectionState; +use display_list::{DisplayListBuildState, FlexFlowDisplayListBuilding}; +use display_list::StackingContextCollectionState; use euclid::Point2D; use floats::FloatKind; use flow::{Flow, FlowClass, GetBaseFlow, ImmutableFlowUtils, OpaqueFlow, FlowFlags}; diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 894c7f1e528..c16dd37ebf0 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -28,7 +28,7 @@ use app_units::Au; use block::{BlockFlow, FormattingContextType}; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; +use display_list::{DisplayListBuildState, StackingContextCollectionState}; use euclid::{Transform3D, Point2D, Vector2D, Rect, Size2D}; use flex::FlexFlow; use floats::{Floats, SpeculatedFloatPlacement}; diff --git a/components/layout/inline.rs b/components/layout/inline.rs index b52b2f7fe45..a96d3586999 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -8,8 +8,8 @@ use ServoArc; use app_units::{Au, MIN_AU}; use block::AbsoluteAssignBSizesTraversal; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, InlineFlowDisplayListBuilding}; -use display_list_builder::StackingContextCollectionState; +use display_list::{DisplayListBuildState, InlineFlowDisplayListBuilding}; +use display_list::StackingContextCollectionState; use euclid::{Point2D, Size2D}; use floats::{FloatKind, Floats, PlacementInfo}; use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag}; diff --git a/components/layout/lib.rs b/components/layout/lib.rs index f5e850c6da1..e19a5f81c9d 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -51,7 +51,7 @@ mod block; pub mod construct; pub mod context; pub mod data; -pub mod display_list_builder; +pub mod display_list; mod flex; mod floats; pub mod flow; @@ -79,7 +79,6 @@ mod table_rowgroup; mod table_wrapper; mod text; pub mod traversal; -pub mod webrender_helpers; pub mod wrapper; // For unit tests: diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 9ff6bee9057..0fddde1494a 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -10,8 +10,8 @@ use app_units::Au; use block::BlockFlow; use context::{LayoutContext, with_thread_local_font_context}; -use display_list_builder::{DisplayListBuildState, ListItemFlowDisplayListBuilding}; -use display_list_builder::StackingContextCollectionState; +use display_list::{DisplayListBuildState, ListItemFlowDisplayListBuilding}; +use display_list::StackingContextCollectionState; use euclid::Point2D; use floats::FloatKind; use flow::{Flow, FlowClass, OpaqueFlow}; diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 327c475fefe..8851fb1836c 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -10,7 +10,7 @@ use ServoArc; use app_units::Au; use block::BlockFlow; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; +use display_list::{DisplayListBuildState, StackingContextCollectionState}; use euclid::{Point2D, Vector2D}; use floats::FloatKind; use flow::{Flow, FlowClass, OpaqueFlow, FragmentationContext, GetBaseFlow}; diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index 02f876c35ae..4270929c5e7 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -6,7 +6,7 @@ use app_units::Au; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; +use display_list::{DisplayListBuildState, StackingContextCollectionState}; use euclid::{Point2D, Vector2D}; use floats::SpeculatedFloatPlacement; use flow::{Flow, ImmutableFlowUtils, FlowFlags, GetBaseFlow}; diff --git a/components/layout/table.rs b/components/layout/table.rs index 512db136b0c..8dd2443ae09 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -10,8 +10,8 @@ use app_units::Au; use block::{BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer}; use block::{ISizeConstraintInput, ISizeConstraintSolution}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState}; +use display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode}; +use display_list::{DisplayListBuildState, StackingContextCollectionFlags, StackingContextCollectionState}; use euclid::Point2D; use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow}; use flow_list::MutFlowListIterator; diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index c6425e93b4e..63292cfbb55 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -9,8 +9,8 @@ use app_units::Au; use block::BlockFlow; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState}; -use display_list_builder::{StackingContextCollectionFlags, StackingContextCollectionState}; +use display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState}; +use display_list::{StackingContextCollectionFlags, StackingContextCollectionState}; use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 81f9e32661a..438e30d96fe 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -9,9 +9,9 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; -use display_list_builder::StackingContextCollectionState; +use display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode}; +use display_list::{DisplayListBuildState, StackingContextCollectionFlags}; +use display_list::StackingContextCollectionState; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; use flow::{Flow, FlowClass, FlowFlags, GetBaseFlow, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index fdd430aebc6..a341a611404 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -8,7 +8,7 @@ use app_units::Au; use context::LayoutContext; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionState}; +use display_list::{DisplayListBuildState, StackingContextCollectionState}; use euclid::Point2D; use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo}; diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 6f2212176f7..a1c91417cd7 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -9,9 +9,9 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use display_list_builder::{DisplayListBuildState, StackingContextCollectionFlags}; -use display_list_builder::StackingContextCollectionState; +use display_list::{BlockFlowDisplayListBuilding, BorderPaintingMode}; +use display_list::{DisplayListBuildState, StackingContextCollectionFlags}; +use display_list::StackingContextCollectionState; use euclid::Point2D; use flow::{EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, GetBaseFlow, OpaqueFlow}; use flow_list::MutFlowListIterator; diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index e5fe72d25a6..7ce2205c745 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -9,8 +9,8 @@ use app_units::Au; use block::{BlockFlow, ISizeAndMarginsComputer}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState}; -use display_list_builder::{StackingContextCollectionFlags, StackingContextCollectionState}; +use display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState}; +use display_list::{StackingContextCollectionFlags, StackingContextCollectionState}; use euclid::Point2D; use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index ef9ffbc9e66..7336efa41e9 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -17,8 +17,8 @@ use app_units::Au; use block::{AbsoluteNonReplaced, BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput}; use block::{ISizeConstraintSolution, MarginsMayCollapseFlag}; use context::LayoutContext; -use display_list_builder::{BlockFlowDisplayListBuilding, DisplayListBuildState, StackingContextCollectionFlags}; -use display_list_builder::StackingContextCollectionState; +use display_list::{BlockFlowDisplayListBuilding, DisplayListBuildState, StackingContextCollectionFlags}; +use display_list::StackingContextCollectionState; use euclid::Point2D; use floats::FloatKind; use flow::{Flow, FlowClass, ImmutableFlowUtils, FlowFlags, OpaqueFlow}; diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index f1729f01b0f..78cb8d741f3 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -6,7 +6,7 @@ use construct::FlowConstructor; use context::LayoutContext; -use display_list_builder::DisplayListBuildState; +use display_list::DisplayListBuildState; use flow::{FlowFlags, Flow, GetBaseFlow, ImmutableFlowUtils}; use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use servo_config::opts; diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index b89df5f6fa7..af99ec99c73 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -69,7 +69,7 @@ use layout::context::LayoutContext; use layout::context::RegisteredPainter; use layout::context::RegisteredPainters; use layout::context::malloc_size_of_persistent_local_context; -use layout::display_list_builder::ToGfxColor; +use layout::display_list::{ToGfxColor, WebRenderDisplayListConverter}; use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; use layout::incremental::{LayoutDamageComputation, RelayoutMode, SpecialRestyleDamage}; @@ -81,7 +81,6 @@ use layout::query::{process_node_geometry_request, process_node_scroll_area_requ use layout::query::{process_node_scroll_root_id_request, process_offset_parent_query}; use layout::sequential; use layout::traversal::{ComputeStackingRelativePositions, PreorderFlowTraversal, RecalcStyleAndConstructFlows}; -use layout::webrender_helpers::WebRenderDisplayListConverter; use layout::wrapper::LayoutNodeLayoutData; use layout_traits::LayoutThreadFactory; use libc::c_void;