diff options
Diffstat (limited to 'components/layout')
-rw-r--r-- | components/layout/display_list_builder.rs | 287 | ||||
-rw-r--r-- | components/layout/sequential.rs | 4 | ||||
-rw-r--r-- | components/layout/webrender_helpers.rs | 4 |
3 files changed, 172 insertions, 123 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index db9373e84f2..3bc3d101f06 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -29,7 +29,7 @@ use gfx::display_list::{GradientDisplayItem}; use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem, LayeredItem, LayerInfo}; use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem}; use gfx::display_list::{StackingContext, StackingContextId, StackingContextType}; -use gfx::display_list::{TextDisplayItem, TextOrientation, DisplayListEntry, WebRenderImageInfo}; +use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo}; use gfx::paint_thread::THREAD_TINT_COLORS; use gfx::text::glyph::CharIndex; use gfx_traits::{color, ScrollPolicy}; @@ -46,8 +46,8 @@ use std::{cmp, f32}; use style::computed_values::filter::Filter; use style::computed_values::{_servo_overflow_clip_box as overflow_clip_box}; use style::computed_values::{background_attachment, background_clip, background_origin}; -use style::computed_values::{background_repeat, background_size}; -use style::computed_values::{border_style, image_rendering, overflow_x, position}; +use style::computed_values::{background_repeat, background_size, border_style}; +use style::computed_values::{cursor, image_rendering, overflow_x, pointer_events, position}; use style::computed_values::{transform, transform_style, visibility}; use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use style::properties::style_structs::ServoBorder; @@ -63,7 +63,7 @@ use util::opts; pub struct DisplayListBuildState<'a> { pub layout_context: &'a LayoutContext<'a>, - pub items: Vec<DisplayListEntry>, + pub items: Vec<DisplayItem>, pub stacking_context_id_stack: Vec<StackingContextId>, } @@ -77,14 +77,8 @@ impl<'a> DisplayListBuildState<'a> { } } - fn add_display_item(&mut self, display_item: DisplayItem, section: DisplayListSection) { - let stacking_context_id = self.stacking_context_id(); - self.items.push( - DisplayListEntry { - stacking_context_id: stacking_context_id, - section: section, - item: display_item - }); + fn add_display_item(&mut self, display_item: DisplayItem) { + self.items.push(display_item); } fn stacking_context_id(&self) -> StackingContextId { @@ -99,6 +93,23 @@ impl<'a> DisplayListBuildState<'a> { self.stacking_context_id_stack.pop(); assert!(!self.stacking_context_id_stack.is_empty()); } + + fn create_base_display_item(&self, + bounds: &Rect<Au>, + clip: &ClippingRegion, + node: OpaqueNode, + cursor: Option<Cursor>, + section: DisplayListSection) + -> BaseDisplayItem { + BaseDisplayItem::new(&bounds, + DisplayItemMetadata { + node: node, + pointing: cursor, + }, + &clip, + section, + self.stacking_context_id()) + } } /// The logical width of an insertion point: at the moment, a one-pixel-wide line. @@ -365,15 +376,16 @@ impl FragmentDisplayListBuilding for Fragment { } } + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + display_list_section); state.add_display_item( DisplayItem::SolidColorClass(box SolidColorDisplayItem { - base: BaseDisplayItem::new(&bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - &clip), + base: base, color: background_color.to_gfx_color(), - }), display_list_section); + })); // The background image is painted on top of the background color. // Implements background image, per spec: @@ -556,17 +568,18 @@ impl FragmentDisplayListBuilding for Fragment { }; // Create the image display item. + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + display_list_section); state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem { - base: BaseDisplayItem::new(&bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - &clip), + base: base, webrender_image: webrender_image, image_data: image_data.map(Arc::new), stretch_size: Size2D::new(image_size.width, image_size.height), image_rendering: style.get_inheritedbox().image_rendering.clone(), - }), display_list_section); + })); } } @@ -676,18 +689,19 @@ impl FragmentDisplayListBuilding for Fragment { let center = Point2D::new(absolute_bounds.origin.x + absolute_bounds.size.width / 2, absolute_bounds.origin.y + absolute_bounds.size.height / 2); + let base = state.create_base_display_item(absolute_bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + display_list_section); let gradient_display_item = DisplayItem::GradientClass(box GradientDisplayItem { - base: BaseDisplayItem::new(absolute_bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - &clip), + base: base, start_point: center - delta, end_point: center + delta, stops: stops, }); - state.add_display_item(gradient_display_item, display_list_section); + state.add_display_item(gradient_display_item); } fn build_display_list_for_box_shadow_if_applicable(&self, @@ -705,12 +719,13 @@ impl FragmentDisplayListBuilding for Fragment { box_shadow.spread_radius); // TODO(pcwalton): Multiple border radii; elliptical border radii. + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + display_list_section); state.add_display_item(DisplayItem::BoxShadowClass(box BoxShadowDisplayItem { - base: BaseDisplayItem::new(&bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - clip), + base: base, box_bounds: *absolute_bounds, color: style.resolve_color(box_shadow.color).to_gfx_color(), offset: Point2D::new(box_shadow.offset_x, box_shadow.offset_y), @@ -724,7 +739,7 @@ impl FragmentDisplayListBuilding for Fragment { } else { BoxShadowClipMode::Outset }, - }), display_list_section); + })); } } @@ -776,12 +791,13 @@ impl FragmentDisplayListBuilding for Fragment { } // Append the border to the display list. + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + display_list_section); state.add_display_item(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(&bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - clip), + base: base, border_widths: border.to_physical(style.writing_mode), color: SideOffsets2D::new(colors.top.to_gfx_color(), colors.right.to_gfx_color(), @@ -789,7 +805,7 @@ impl FragmentDisplayListBuilding for Fragment { colors.left.to_gfx_color()), style: border_style, radius: build_border_radius(&bounds, border_style_struct), - }), display_list_section); + })); } fn build_display_list_for_outline_if_applicable(&self, @@ -818,17 +834,18 @@ impl FragmentDisplayListBuilding for Fragment { // Append the outline to the display list. let color = style.resolve_color(style.get_outline().outline_color).to_gfx_color(); + let base = state.create_base_display_item(&bounds, + &clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Outlines); state.add_display_item(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(&bounds, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - clip), + base: base, border_widths: SideOffsets2D::new_all_same(width), color: SideOffsets2D::new_all_same(color), style: SideOffsets2D::new_all_same(outline_style), radius: Default::default(), - }), DisplayListSection::Outlines); + })); } fn build_debug_borders_around_text_fragments(&self, @@ -842,17 +859,18 @@ impl FragmentDisplayListBuilding for Fragment { let container_size = Size2D::zero(); // Compute the text fragment bounds and draw a border surrounding them. + let base = state.create_base_display_item(stacking_relative_border_box, + clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(stacking_relative_border_box, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - clip), + base: base, border_widths: SideOffsets2D::new_all_same(Au::from_px(1)), color: SideOffsets2D::new_all_same(color::rgb(0, 0, 200)), style: SideOffsets2D::new_all_same(border_style::T::solid), radius: Default::default(), - }), DisplayListSection::Content); + })); // Draw a rectangle representing the baselines. let mut baseline = LogicalRect::from_physical(self.style.writing_mode, @@ -862,15 +880,16 @@ impl FragmentDisplayListBuilding for Fragment { baseline.size.block = Au(0); let baseline = baseline.to_physical(self.style.writing_mode, container_size); + let base = state.create_base_display_item(&baseline, + clip, + self.node, + style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::LineClass(box LineDisplayItem { - base: BaseDisplayItem::new(&baseline, - DisplayItemMetadata::new(self.node, - style, - Cursor::DefaultCursor), - clip), + base: base, color: color::rgb(0, 200, 0), style: border_style::T::dashed, - }), DisplayListSection::Content); + })); } fn build_debug_borders_around_fragment(&self, @@ -878,17 +897,18 @@ impl FragmentDisplayListBuilding for Fragment { stacking_relative_border_box: &Rect<Au>, clip: &ClippingRegion) { // This prints a debug border around the border of this fragment. + let base = state.create_base_display_item(stacking_relative_border_box, + clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(stacking_relative_border_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - clip), + base: base, border_widths: SideOffsets2D::new_all_same(Au::from_px(1)), color: SideOffsets2D::new_all_same(color::rgb(0, 0, 200)), style: SideOffsets2D::new_all_same(border_style::T::solid), radius: Default::default(), - }), DisplayListSection::Content); + })); } fn adjust_clip_for_style(&self, @@ -928,15 +948,16 @@ impl FragmentDisplayListBuilding for Fragment { if scanned_text_fragment_info.selected() { let style = self.selected_style(); let background_color = style.resolve_color(style.get_background().background_color); + let base = state.create_base_display_item(stacking_relative_border_box, + &clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + display_list_section); state.add_display_item( DisplayItem::SolidColorClass(box SolidColorDisplayItem { - base: BaseDisplayItem::new(stacking_relative_border_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - &clip), + base: base, color: background_color.to_gfx_color(), - }), display_list_section); + })); } // Draw a caret at the insertion point. @@ -965,12 +986,15 @@ impl FragmentDisplayListBuilding for Fragment { cursor = Cursor::VerticalTextCursor; }; + let base = state.create_base_display_item(&insertion_point_bounds, + &clip, + self.node, + self.style.get_cursor(cursor), + display_list_section); state.add_display_item(DisplayItem::SolidColorClass(box SolidColorDisplayItem { - base: BaseDisplayItem::new(&insertion_point_bounds, - DisplayItemMetadata::new(self.node, &*self.style, cursor), - &clip), + base: base, color: self.style().get_color().color.to_gfx_color(), - }), display_list_section); + })); } fn build_display_list(&mut self, @@ -1175,18 +1199,19 @@ impl FragmentDisplayListBuilding for Fragment { } SpecificFragmentInfo::Iframe(ref fragment_info) => { if !stacking_relative_content_box.is_empty() { + let base = state.create_base_display_item( + &stacking_relative_content_box, + clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); let item = DisplayItem::IframeClass(box IframeDisplayItem { - base: BaseDisplayItem::new( - &stacking_relative_content_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - clip), + base: base, iframe: fragment_info.pipeline_id, }); if opts::get().use_webrender { - state.add_display_item(item, DisplayListSection::Content); + state.add_display_item(item); } else { state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem { item: item, @@ -1194,24 +1219,26 @@ impl FragmentDisplayListBuilding for Fragment { ScrollPolicy::Scrollable, Some(fragment_info.pipeline_id), color::transparent()), - }), DisplayListSection::Content); + })); } } } SpecificFragmentInfo::Image(ref mut image_fragment) => { // Place the image into the display list. if let Some(ref image) = image_fragment.image { + let base = state.create_base_display_item( + &stacking_relative_content_box, + clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::ImageClass(box ImageDisplayItem { - base: BaseDisplayItem::new(&stacking_relative_content_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - clip), + base: base, webrender_image: WebRenderImageInfo::from_image(image), image_data: Some(Arc::new(image.bytes.clone())), stretch_size: stacking_relative_content_box.size, image_rendering: self.style.get_inheritedbox().image_rendering.clone(), - }), DisplayListSection::Content); + })); } } SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => { @@ -1235,14 +1262,16 @@ impl FragmentDisplayListBuilding for Fragment { }), }; + let base = state.create_base_display_item( + &stacking_relative_content_box, + clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); let display_item = match canvas_data { CanvasData::Pixels(canvas_data) => { DisplayItem::ImageClass(box ImageDisplayItem { - base: BaseDisplayItem::new(&stacking_relative_content_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - clip), + base: base, image_data: Some(Arc::new(canvas_data.image_data)), webrender_image: WebRenderImageInfo { width: width as u32, @@ -1256,18 +1285,14 @@ impl FragmentDisplayListBuilding for Fragment { } CanvasData::WebGL(context_id) => { DisplayItem::WebGLClass(box WebGLDisplayItem { - base: BaseDisplayItem::new(&stacking_relative_content_box, - DisplayItemMetadata::new(self.node, - &*self.style, - Cursor::DefaultCursor), - clip), + base: base, context_id: context_id, }) } }; if opts::get().use_webrender { - state.add_display_item(display_item, DisplayListSection::Content); + state.add_display_item(display_item); } else { state.add_display_item(DisplayItem::LayeredItemClass(box LayeredItem { item: display_item, @@ -1275,7 +1300,7 @@ impl FragmentDisplayListBuilding for Fragment { ScrollPolicy::Scrollable, None, color::transparent()), - }), DisplayListSection::Content); + })); } } } @@ -1532,17 +1557,20 @@ impl FragmentDisplayListBuilding for Fragment { container_size); // Create the text display item. + let base = state.create_base_display_item(&stacking_relative_content_box, + clip, + self.node, + self.style().get_cursor(cursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::TextClass(box TextDisplayItem { - base: BaseDisplayItem::new(&stacking_relative_content_box, - DisplayItemMetadata::new(self.node, self.style(), cursor), - clip), + base: base, text_run: text_fragment.run.clone(), range: text_fragment.range, text_color: text_color.to_gfx_color(), orientation: orientation, baseline_origin: baseline_origin, blur_radius: shadow_blur_radius.unwrap_or(Au(0)), - }), DisplayListSection::Content); + })); // Create display items for text decorations. let mut text_decorations = self.style() @@ -1608,11 +1636,14 @@ impl FragmentDisplayListBuilding for Fragment { let container_size = Size2D::zero(); let stacking_relative_box = stacking_relative_box.to_physical(self.style.writing_mode, container_size); - let metadata = DisplayItemMetadata::new(self.node, &*self.style, Cursor::DefaultCursor); + let base = state.create_base_display_item( + &shadow_bounds(&stacking_relative_box, blur_radius, Au(0)), + clip, + self.node, + self.style.get_cursor(Cursor::DefaultCursor), + DisplayListSection::Content); state.add_display_item(DisplayItem::BoxShadowClass(box BoxShadowDisplayItem { - base: BaseDisplayItem::new(&shadow_bounds(&stacking_relative_box, blur_radius, Au(0)), - metadata, - clip), + base: base, box_bounds: stacking_relative_box, color: color.to_gfx_color(), offset: Point2D::zero(), @@ -1620,7 +1651,7 @@ impl FragmentDisplayListBuilding for Fragment { spread_radius: Au(0), border_radius: Au(0), clip_mode: BoxShadowClipMode::None, - }), DisplayListSection::Content); + })); } } @@ -1927,19 +1958,37 @@ impl BaseFlowDisplayListBuilding for BaseFlow { let mut color = THREAD_TINT_COLORS[thread_id as usize % THREAD_TINT_COLORS.len()]; color.a = 1.0; + let base = state.create_base_display_item( + &stacking_context_relative_bounds.inflate(Au::from_px(2), Au::from_px(2)), + &self.clip, + node, + None, + DisplayListSection::Content); state.add_display_item(DisplayItem::BorderClass(box BorderDisplayItem { - base: BaseDisplayItem::new(&stacking_context_relative_bounds.inflate(Au::from_px(2), - Au::from_px(2)), - DisplayItemMetadata { - node: node, - pointing: None, - }, - &self.clip), + base: base, border_widths: SideOffsets2D::new_all_same(Au::from_px(2)), color: SideOffsets2D::new_all_same(color), style: SideOffsets2D::new_all_same(border_style::T::solid), radius: BorderRadii::all_same(Au(0)), - }), DisplayListSection::Content); + })); + } +} + +trait ServoComputedValuesCursorUtility { + fn get_cursor(&self, default_cursor: Cursor) -> Option<Cursor>; +} + +impl ServoComputedValuesCursorUtility for ServoComputedValues { + /// Gets the cursor to use given the specific ServoComputedValues. `default_cursor` specifies + /// the cursor to use if `cursor` is `auto`. Typically, this will be `PointerCursor`, but for + /// text display items it may be `TextCursor` or `VerticalTextCursor`. + #[inline] + fn get_cursor(&self, default_cursor: Cursor) -> Option<Cursor> { + match (self.get_pointing().pointer_events, self.get_pointing().cursor) { + (pointer_events::T::none, _) => None, + (pointer_events::T::auto, cursor::T::AutoCursor) => Some(default_cursor), + (pointer_events::T::auto, cursor::T::SpecifiedCursor(cursor)) => Some(cursor), + } } } diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index bc4668f33c6..16aa0d5f277 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -15,7 +15,7 @@ use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtil use flow_ref::{self, FlowRef}; use fragment::FragmentBorderBoxIterator; use generated_content::ResolveGeneratedContent; -use gfx::display_list::{DisplayListEntry, StackingContext}; +use gfx::display_list::{DisplayItem, StackingContext}; use incremental::{REFLOW, STORE_OVERFLOW}; use style::dom::TNode; use style::traversal::DomTraversalContext; @@ -82,7 +82,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef, pub fn build_display_list_for_subtree(root: &mut FlowRef, root_stacking_context: &mut StackingContext, shared_layout_context: &SharedLayoutContext) - -> Vec<DisplayListEntry> { + -> Vec<DisplayItem> { let flow_root = flow_ref::deref_mut(root); let layout_context = LayoutContext::new(shared_layout_context); flow_root.traverse_preorder(&ComputeAbsolutePositions { layout_context: &layout_context }); diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index f52685501e9..1c7dc11785c 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -264,7 +264,7 @@ impl WebRenderStackingContextConverter for StackingContext { _force_positioned_stacking_level: bool) { for child in self.children.iter() { while let Some(item) = traversal.advance(self) { - item.item.convert_to_webrender(builder, frame_builder); + item.convert_to_webrender(builder, frame_builder); } if child.context_type == StackingContextType::Real { @@ -290,7 +290,7 @@ impl WebRenderStackingContextConverter for StackingContext { } while let Some(item) = traversal.advance(self) { - item.item.convert_to_webrender(builder, frame_builder); + item.convert_to_webrender(builder, frame_builder); } } |