aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/block.rs1
-rw-r--r--components/layout/construct.rs9
-rw-r--r--components/layout/display_list_builder.rs3
-rw-r--r--components/layout/fragment.rs109
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
}
}