mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Use presentation hints correctly for the dimensions of <img>
.
Mostly straightforward; includes some extra fixes to make `<canvas>` work the same way as `<img>` for reflow.
This commit is contained in:
parent
b188cb542e
commit
7b671d13a0
56 changed files with 5505 additions and 853 deletions
|
@ -34,7 +34,6 @@ use std::cmp::{max, min};
|
|||
use std::collections::LinkedList;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use string_cache::Atom;
|
||||
use style::computed_values::content::ContentItem;
|
||||
use style::computed_values::{border_collapse, clear, display, mix_blend_mode, overflow_wrap};
|
||||
use style::computed_values::{overflow_x, position, text_decoration, transform_style};
|
||||
|
@ -312,28 +311,38 @@ pub struct CanvasFragmentInfo {
|
|||
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
|
||||
pub renderer_id: Option<usize>,
|
||||
pub ipc_renderer: Option<Arc<Mutex<IpcSender<CanvasMsg>>>>,
|
||||
pub dom_width: Au,
|
||||
pub dom_height: Au,
|
||||
}
|
||||
|
||||
impl CanvasFragmentInfo {
|
||||
pub fn new<'ln, N: ThreadSafeLayoutNode<'ln>>(node: &N, data: HTMLCanvasData) -> CanvasFragmentInfo {
|
||||
CanvasFragmentInfo {
|
||||
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
|
||||
Some(Au::from_px(data.width as i32)),
|
||||
Some(Au::from_px(data.height as i32))),
|
||||
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node),
|
||||
renderer_id: data.renderer_id,
|
||||
ipc_renderer: data.ipc_renderer
|
||||
.map(|renderer| Arc::new(Mutex::new(renderer))),
|
||||
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 canvas.
|
||||
pub fn canvas_inline_size(&self) -> Au {
|
||||
self.replaced_image_fragment_info.dom_inline_size.unwrap_or(Au(0))
|
||||
if self.replaced_image_fragment_info.writing_mode_is_vertical {
|
||||
self.dom_height
|
||||
} else {
|
||||
self.dom_width
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the original block-size of the canvas.
|
||||
pub fn canvas_block_size(&self) -> Au {
|
||||
self.replaced_image_fragment_info.dom_block_size.unwrap_or(Au(0))
|
||||
if self.replaced_image_fragment_info.writing_mode_is_vertical {
|
||||
self.dom_width
|
||||
} else {
|
||||
self.dom_height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,14 +363,6 @@ impl ImageFragmentInfo {
|
|||
/// sense to me.
|
||||
pub fn new<'ln, N: ThreadSafeLayoutNode<'ln>>(node: &N, url: Option<Url>,
|
||||
layout_context: &LayoutContext) -> ImageFragmentInfo {
|
||||
fn convert_length<'ln, N>(node: &N, name: &Atom) -> Option<Au>
|
||||
where N: ThreadSafeLayoutNode<'ln> {
|
||||
let element = node.as_element();
|
||||
element.get_attr(&ns!(), name)
|
||||
.and_then(|string| string.parse().ok())
|
||||
.map(Au::from_px)
|
||||
}
|
||||
|
||||
let image_or_metadata = url.and_then(|url| {
|
||||
layout_context.get_or_request_image_or_meta(url, UsePlaceholder::Yes)
|
||||
});
|
||||
|
@ -379,9 +380,7 @@ impl ImageFragmentInfo {
|
|||
};
|
||||
|
||||
ImageFragmentInfo {
|
||||
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
|
||||
convert_length(node, &atom!("width")),
|
||||
convert_length(node, &atom!("height"))),
|
||||
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node),
|
||||
image: image,
|
||||
metadata: metadata,
|
||||
}
|
||||
|
@ -436,30 +435,16 @@ impl ImageFragmentInfo {
|
|||
pub struct ReplacedImageFragmentInfo {
|
||||
pub computed_inline_size: Option<Au>,
|
||||
pub computed_block_size: Option<Au>,
|
||||
pub dom_inline_size: Option<Au>,
|
||||
pub dom_block_size: Option<Au>,
|
||||
pub writing_mode_is_vertical: bool,
|
||||
}
|
||||
|
||||
impl ReplacedImageFragmentInfo {
|
||||
pub fn new<'ln, N>(node: &N,
|
||||
dom_width: Option<Au>,
|
||||
dom_height: Option<Au>) -> ReplacedImageFragmentInfo
|
||||
pub fn new<'ln, N>(node: &N) -> ReplacedImageFragmentInfo
|
||||
where N: ThreadSafeLayoutNode<'ln> {
|
||||
let is_vertical = node.style().writing_mode.is_vertical();
|
||||
ReplacedImageFragmentInfo {
|
||||
computed_inline_size: None,
|
||||
computed_block_size: None,
|
||||
dom_inline_size: if is_vertical {
|
||||
dom_height
|
||||
} else {
|
||||
dom_width
|
||||
},
|
||||
dom_block_size: if is_vertical {
|
||||
dom_width
|
||||
} else {
|
||||
dom_height
|
||||
},
|
||||
writing_mode_is_vertical: is_vertical,
|
||||
}
|
||||
}
|
||||
|
@ -479,20 +464,18 @@ impl ReplacedImageFragmentInfo {
|
|||
// `dom_length`: inline-size or block-size as specified in the `img` tag.
|
||||
// `style_length`: inline-size as given in the CSS
|
||||
pub fn style_length(style_length: LengthOrPercentageOrAuto,
|
||||
dom_length: Option<Au>,
|
||||
container_size: Option<Au>) -> MaybeAuto {
|
||||
match (style_length, dom_length, container_size) {
|
||||
(LengthOrPercentageOrAuto::Length(length), _, _) => MaybeAuto::Specified(length),
|
||||
(LengthOrPercentageOrAuto::Percentage(pc), _, Some(container_size)) => {
|
||||
match (style_length, container_size) {
|
||||
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
|
||||
(LengthOrPercentageOrAuto::Percentage(pc), Some(container_size)) => {
|
||||
MaybeAuto::Specified(container_size.scale_by(pc))
|
||||
}
|
||||
(LengthOrPercentageOrAuto::Percentage(_), _, None) => MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAuto::Calc(calc), _, Some(container_size)) => {
|
||||
(LengthOrPercentageOrAuto::Percentage(_), None) => MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => {
|
||||
MaybeAuto::Specified(calc.length() + container_size.scale_by(calc.percentage()))
|
||||
}
|
||||
(LengthOrPercentageOrAuto::Calc(_), _, None) => MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAuto::Auto, Some(dom_length), _) => MaybeAuto::Specified(dom_length),
|
||||
(LengthOrPercentageOrAuto::Auto, None, _) => MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAuto::Calc(_), None) => MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +496,6 @@ impl ReplacedImageFragmentInfo {
|
|||
// TODO(ksh8281): compute border,margin
|
||||
let inline_size = ReplacedImageFragmentInfo::style_length(
|
||||
style_inline_size,
|
||||
self.dom_inline_size,
|
||||
Some(container_inline_size));
|
||||
|
||||
let inline_size = match inline_size {
|
||||
|
@ -528,7 +510,6 @@ impl ReplacedImageFragmentInfo {
|
|||
|
||||
let specified_height = ReplacedImageFragmentInfo::style_length(
|
||||
style_block_size,
|
||||
self.dom_block_size,
|
||||
None);
|
||||
let specified_height = match specified_height {
|
||||
MaybeAuto::Auto => intrinsic_height,
|
||||
|
@ -568,7 +549,6 @@ impl ReplacedImageFragmentInfo {
|
|||
let inline_size = self.computed_inline_size();
|
||||
let block_size = ReplacedImageFragmentInfo::style_length(
|
||||
style_block_size,
|
||||
self.dom_block_size,
|
||||
containing_block_block_size);
|
||||
|
||||
let block_size = match block_size {
|
||||
|
@ -1342,17 +1322,13 @@ impl Fragment {
|
|||
result.union_block(&block_flow.base.intrinsic_inline_sizes)
|
||||
}
|
||||
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
|
||||
// FIXME(pcwalton): Shouldn't `width` and `height` be preshints?
|
||||
let image_inline_size = match (image_fragment_info.replaced_image_fragment_info
|
||||
.dom_inline_size,
|
||||
self.style.content_inline_size()) {
|
||||
(None, LengthOrPercentageOrAuto::Auto) |
|
||||
(None, LengthOrPercentageOrAuto::Percentage(_)) => {
|
||||
let image_inline_size = match self.style.content_inline_size() {
|
||||
LengthOrPercentageOrAuto::Auto |
|
||||
LengthOrPercentageOrAuto::Percentage(_) => {
|
||||
image_fragment_info.image_inline_size()
|
||||
}
|
||||
(Some(dom_inline_size), _) => dom_inline_size,
|
||||
(None, LengthOrPercentageOrAuto::Length(length)) => length,
|
||||
(None, LengthOrPercentageOrAuto::Calc(calc)) => calc.length(),
|
||||
LengthOrPercentageOrAuto::Length(length) => length,
|
||||
LengthOrPercentageOrAuto::Calc(calc) => calc.length(),
|
||||
};
|
||||
result.union_block(&IntrinsicISizes {
|
||||
minimum_inline_size: image_inline_size,
|
||||
|
@ -1360,11 +1336,18 @@ impl Fragment {
|
|||
});
|
||||
}
|
||||
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
|
||||
let canvas_inline_size = canvas_fragment_info.canvas_inline_size();
|
||||
let canvas_inline_size = match self.style.content_inline_size() {
|
||||
LengthOrPercentageOrAuto::Auto |
|
||||
LengthOrPercentageOrAuto::Percentage(_) => {
|
||||
canvas_fragment_info.canvas_inline_size()
|
||||
}
|
||||
LengthOrPercentageOrAuto::Length(length) => length,
|
||||
LengthOrPercentageOrAuto::Calc(calc) => calc.length(),
|
||||
};
|
||||
result.union_block(&IntrinsicISizes {
|
||||
minimum_inline_size: canvas_inline_size,
|
||||
preferred_inline_size: canvas_inline_size,
|
||||
})
|
||||
});
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
||||
let range = &text_fragment_info.range;
|
||||
|
@ -1876,6 +1859,16 @@ impl Fragment {
|
|||
ascent: computed_block_size + self.border_padding.block_start,
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
|
||||
let computed_block_size = canvas_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 text_fragment) => {
|
||||
// See CSS 2.1 § 10.8.1.
|
||||
let line_height = self.calculate_line_height(layout_context);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue