diff options
-rw-r--r-- | components/layout/block.rs | 1 | ||||
-rw-r--r-- | components/layout/construct.rs | 9 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 3 | ||||
-rw-r--r-- | components/layout/fragment.rs | 109 |
4 files changed, 116 insertions, 6 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs index 7de8f379560..e28e85d139a 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -678,6 +678,7 @@ impl BlockFlow { fn is_replaced_content(&self) -> bool { match self.fragment.specific { SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::InlineBlock(_) => true, diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 8a463ded66a..ae77f4d7751 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -22,7 +22,7 @@ use floats::FloatKind; use flow::{self, AbsoluteDescendants, IS_ABSOLUTELY_POSITIONED, ImmutableFlowUtils}; use flow::{CAN_BE_FRAGMENTED, MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::{self, FlowRef}; -use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo}; +use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; @@ -335,6 +335,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let data = node.canvas_data().unwrap(); SpecificFragmentInfo::Canvas(box CanvasFragmentInfo::new(node, data, self.style_context())) } + Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => { + let data = node.svg_data().unwrap(); + SpecificFragmentInfo::Svg(box SvgFragmentInfo::new(node, data, self.style_context())) + } _ => { // This includes pseudo-elements. SpecificFragmentInfo::Generic @@ -1701,7 +1705,8 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode Some(LayoutNodeType::Document) | Some(LayoutNodeType::Element(LayoutElementType::HTMLImageElement)) | Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) | - Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) => true, + Some(LayoutNodeType::Element(LayoutElementType::HTMLCanvasElement)) | + Some(LayoutNodeType::Element(LayoutElementType::SVGSVGElement)) => true, Some(LayoutNodeType::Element(LayoutElementType::HTMLObjectElement)) => self.has_object_data(), Some(LayoutNodeType::Element(_)) => false, None => self.get_pseudo_element_type().is_replaced_content(), diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index c62518a9977..74ed84b2ef7 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1239,7 +1239,8 @@ impl FragmentDisplayListBuilding for Fragment { SpecificFragmentInfo::MulticolColumn | SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | - SpecificFragmentInfo::InlineAbsolute(_) => { + SpecificFragmentInfo::InlineAbsolute(_) | + SpecificFragmentInfo::Svg(_) => { if opts::get().show_debug_fragment_borders { self.build_debug_borders_around_fragment(state, stacking_relative_border_box, diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 698ed517772..6bd43a5b3fa 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -30,6 +30,7 @@ use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder}; use range::*; use rustc_serialize::{Encodable, Encoder}; use script_layout_interface::HTMLCanvasData; +use script_layout_interface::SVGSVGData; use script_layout_interface::restyle_damage::{RECONSTRUCT_FLOW, RestyleDamage}; use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; use std::borrow::ToOwned; @@ -155,6 +156,7 @@ pub enum SpecificFragmentInfo { Iframe(IframeFragmentInfo), Image(Box<ImageFragmentInfo>), Canvas(Box<CanvasFragmentInfo>), + Svg(Box<SvgFragmentInfo>), /// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was /// declared with `display: inline;`. @@ -186,6 +188,7 @@ impl SpecificFragmentInfo { SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableColumn(_) | @@ -216,6 +219,7 @@ impl SpecificFragmentInfo { } SpecificFragmentInfo::InlineBlock(_) => "SpecificFragmentInfo::InlineBlock", SpecificFragmentInfo::ScannedText(_) => "SpecificFragmentInfo::ScannedText", + SpecificFragmentInfo::Svg(_) => "SpecificFragmentInfo::Svg", SpecificFragmentInfo::Table => "SpecificFragmentInfo::Table", SpecificFragmentInfo::TableCell => "SpecificFragmentInfo::TableCell", SpecificFragmentInfo::TableColumn(_) => "SpecificFragmentInfo::TableColumn", @@ -356,6 +360,44 @@ impl CanvasFragmentInfo { } } +#[derive(Clone)] +pub struct SvgFragmentInfo { + pub replaced_image_fragment_info: ReplacedImageFragmentInfo, + pub dom_width: Au, + pub dom_height: Au, +} + +impl SvgFragmentInfo { + pub fn new<N: ThreadSafeLayoutNode>(node: &N, + data: SVGSVGData, + ctx: &SharedStyleContext) + -> SvgFragmentInfo { + SvgFragmentInfo { + replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node, ctx), + dom_width: Au::from_px(data.width as i32), + dom_height: Au::from_px(data.height as i32), + } + } + + /// Returns the original inline-size of the SVG element. + pub fn svg_inline_size(&self) -> Au { + if self.replaced_image_fragment_info.writing_mode_is_vertical { + self.dom_height + } else { + self.dom_width + } + } + + /// Returns the original block-size of the SVG element. + pub fn svg_block_size(&self) -> Au { + if self.replaced_image_fragment_info.writing_mode_is_vertical { + self.dom_width + } else { + self.dom_height + } + } +} + /// A fragment that represents a replaced content image and its accompanying borders, shadows, etc. #[derive(Clone)] @@ -1007,7 +1049,8 @@ impl Fragment { SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::InlineAbsolute(_) | - SpecificFragmentInfo::Multicol => { + SpecificFragmentInfo::Multicol | + SpecificFragmentInfo::Svg(_) => { QuantitiesIncludedInIntrinsicInlineSizes::all() } SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell => { @@ -1509,6 +1552,26 @@ impl Fragment { preferred_inline_size: canvas_inline_size, }); } + SpecificFragmentInfo::Svg(ref mut svg_fragment_info) => { + let mut svg_inline_size = match self.style.content_inline_size() { + LengthOrPercentageOrAuto::Auto | + LengthOrPercentageOrAuto::Percentage(_) => { + svg_fragment_info.svg_inline_size() + } + LengthOrPercentageOrAuto::Length(length) => length, + LengthOrPercentageOrAuto::Calc(calc) => calc.length(), + }; + + svg_inline_size = max(model::specified(self.style.min_inline_size(), Au(0)), svg_inline_size); + if let Some(max) = model::specified_or_none(self.style.max_inline_size(), Au(0)) { + svg_inline_size = min(svg_inline_size, max) + } + + result.union_block(&IntrinsicISizes { + minimum_inline_size: svg_inline_size, + preferred_inline_size: svg_inline_size, + }); + } SpecificFragmentInfo::ScannedText(ref text_fragment_info) => { let range = &text_fragment_info.range; @@ -1596,6 +1659,9 @@ impl Fragment { SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => { canvas_fragment_info.replaced_image_fragment_info.computed_inline_size() } + SpecificFragmentInfo::Svg(ref svg_fragment_info) => { + svg_fragment_info.replaced_image_fragment_info.computed_inline_size() + } SpecificFragmentInfo::Image(ref image_fragment_info) => { image_fragment_info.replaced_image_fragment_info.computed_inline_size() } @@ -1885,7 +1951,8 @@ impl Fragment { SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::InlineAbsolute(_) | - SpecificFragmentInfo::ScannedText(_) => {} + SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) => {} }; let style = &*self.style; @@ -1945,6 +2012,18 @@ impl Fragment { fragment_inline_size, fragment_block_size); } + SpecificFragmentInfo::Svg(ref mut svg_fragment_info) => { + let fragment_inline_size = svg_fragment_info.svg_inline_size(); + let fragment_block_size = svg_fragment_info.svg_block_size(); + self.border_box.size.inline = + svg_fragment_info.replaced_image_fragment_info + .calculate_replaced_inline_size(style, + noncontent_inline_size, + container_inline_size, + container_block_size, + fragment_inline_size, + fragment_block_size); + } SpecificFragmentInfo::Iframe(ref iframe_fragment_info) => { self.border_box.size.inline = iframe_fragment_info.calculate_replaced_inline_size(style, @@ -1981,7 +2060,8 @@ impl Fragment { SpecificFragmentInfo::InlineBlock(_) | SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::InlineAbsolute(_) | - SpecificFragmentInfo::ScannedText(_) => {} + SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) => {} } let style = &*self.style; @@ -2010,6 +2090,17 @@ impl Fragment { fragment_inline_size, fragment_block_size); } + SpecificFragmentInfo::Svg(ref mut svg_fragment_info) => { + let fragment_inline_size = svg_fragment_info.svg_inline_size(); + let fragment_block_size = svg_fragment_info.svg_block_size(); + self.border_box.size.block = + svg_fragment_info.replaced_image_fragment_info + .calculate_replaced_block_size(style, + noncontent_block_size, + containing_block_block_size, + fragment_inline_size, + fragment_block_size); + } SpecificFragmentInfo::ScannedText(ref info) => { // Scanned text fragments' content block-sizes are calculated by the text run // scanner during flow construction. @@ -2065,6 +2156,16 @@ impl Fragment { ascent: computed_block_size + self.border_padding.block_start, } } + SpecificFragmentInfo::Svg(ref svg_fragment_info) => { + let computed_block_size = svg_fragment_info.replaced_image_fragment_info + .computed_block_size(); + InlineMetrics { + block_size_above_baseline: computed_block_size + + self.border_padding.block_start, + depth_below_baseline: self.border_padding.block_end, + ascent: computed_block_size + self.border_padding.block_start, + } + } SpecificFragmentInfo::ScannedText(ref info) => { // Fragments with no glyphs don't contribute any inline metrics. // TODO: Filter out these fragments during flow construction? @@ -2213,6 +2314,7 @@ impl Fragment { SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableColumn(_) | @@ -2699,6 +2801,7 @@ impl Fragment { SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | + SpecificFragmentInfo::Svg(_) | SpecificFragmentInfo::UnscannedText(_) => true } } |