mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
add SVG fragment (SpecificFragmentInfo::Svg)
This commit is contained in:
parent
9876020c22
commit
14934a42d7
4 changed files with 116 additions and 6 deletions
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue