mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #25299 - emilio:gecko-sync, r=emilio,nox
style: Sync changes from mozilla-central. See individual commits for details.
This commit is contained in:
commit
a8b8f46476
80 changed files with 770 additions and 450 deletions
69
Cargo.lock
generated
69
Cargo.lock
generated
|
@ -887,7 +887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -947,7 +947,7 @@ dependencies = [
|
|||
"proc-macro2 1.0.1",
|
||||
"quote 1.0.2",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"syn 1.0.3",
|
||||
]
|
||||
|
||||
|
@ -1102,6 +1102,17 @@ dependencies = [
|
|||
"syn 0.15.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.1",
|
||||
"quote 1.0.2",
|
||||
"syn 1.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "device"
|
||||
version = "0.0.1"
|
||||
|
@ -1387,7 +1398,7 @@ name = "fallible"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"hashglobe",
|
||||
"smallvec",
|
||||
"smallvec 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1609,7 +1620,7 @@ dependencies = [
|
|||
"servo_arc",
|
||||
"servo_atoms",
|
||||
"servo_url",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"style",
|
||||
"time",
|
||||
"truetype",
|
||||
|
@ -1646,7 +1657,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"spirv_cross",
|
||||
"winapi",
|
||||
"wio",
|
||||
|
@ -1665,7 +1676,7 @@ dependencies = [
|
|||
"log",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"spirv_cross",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1702,7 +1713,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"spirv_cross",
|
||||
"storage-map",
|
||||
]
|
||||
|
@ -1722,7 +1733,7 @@ dependencies = [
|
|||
"log",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"winapi",
|
||||
"x11",
|
||||
]
|
||||
|
@ -1735,7 +1746,7 @@ checksum = "7c88981665c780447bb08eb099e1ded330754a7246719bab927ee4a949c0ba7f"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2706,7 +2717,7 @@ dependencies = [
|
|||
"servo_geometry",
|
||||
"servo_url",
|
||||
"size_of_test",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"style",
|
||||
"style_traits",
|
||||
"unicode-bidi",
|
||||
|
@ -2938,7 +2949,7 @@ dependencies = [
|
|||
"rust-webvr",
|
||||
"servo-egl",
|
||||
"simpleservo",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
]
|
||||
|
@ -3137,7 +3148,7 @@ dependencies = [
|
|||
"serde_bytes",
|
||||
"servo_arc",
|
||||
"smallbitvec",
|
||||
"smallvec",
|
||||
"smallvec 1.0.0",
|
||||
"string_cache",
|
||||
"thin-slice",
|
||||
"time",
|
||||
|
@ -3812,7 +3823,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -4307,7 +4318,7 @@ dependencies = [
|
|||
"gfx-hal",
|
||||
"log",
|
||||
"relevant",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4322,7 +4333,7 @@ dependencies = [
|
|||
"log",
|
||||
"relevant",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4514,7 +4525,7 @@ dependencies = [
|
|||
"servo_geometry",
|
||||
"servo_rand",
|
||||
"servo_url",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"sparkle",
|
||||
"style",
|
||||
"style_traits",
|
||||
|
@ -4633,7 +4644,7 @@ version = "0.21.0"
|
|||
dependencies = [
|
||||
"bitflags",
|
||||
"cssparser",
|
||||
"derive_more",
|
||||
"derive_more 0.99.2",
|
||||
"fxhash",
|
||||
"log",
|
||||
"matches",
|
||||
|
@ -4641,7 +4652,7 @@ dependencies = [
|
|||
"phf_codegen",
|
||||
"precomputed-hash",
|
||||
"servo_arc",
|
||||
"smallvec",
|
||||
"smallvec 1.0.0",
|
||||
"thin-slice",
|
||||
"to_shmem",
|
||||
"to_shmem_derive",
|
||||
|
@ -4836,7 +4847,7 @@ dependencies = [
|
|||
"servo-media-player",
|
||||
"servo-media-traits",
|
||||
"servo_media_derive",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5223,6 +5234,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
version = "0.4.6"
|
||||
|
@ -5351,7 +5368,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"crossbeam-channel",
|
||||
"cssparser",
|
||||
"derive_more",
|
||||
"derive_more 0.99.2",
|
||||
"encoding_rs",
|
||||
"euclid",
|
||||
"fallible",
|
||||
|
@ -5384,7 +5401,7 @@ dependencies = [
|
|||
"servo_config",
|
||||
"servo_url",
|
||||
"smallbitvec",
|
||||
"smallvec",
|
||||
"smallvec 1.0.0",
|
||||
"string_cache",
|
||||
"style_derive",
|
||||
"style_traits",
|
||||
|
@ -5689,7 +5706,7 @@ dependencies = [
|
|||
"cssparser",
|
||||
"servo_arc",
|
||||
"smallbitvec",
|
||||
"smallvec",
|
||||
"smallvec 1.0.0",
|
||||
"string_cache",
|
||||
"thin-slice",
|
||||
]
|
||||
|
@ -6279,7 +6296,7 @@ dependencies = [
|
|||
"malloc_size_of",
|
||||
"serde",
|
||||
"servo_config",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"wgpu-core",
|
||||
]
|
||||
|
||||
|
@ -6314,7 +6331,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"svg_fmt",
|
||||
"thread_profiler",
|
||||
"time",
|
||||
|
@ -6334,7 +6351,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"derive_more",
|
||||
"derive_more 0.13.0",
|
||||
"euclid",
|
||||
"malloc_size_of_derive",
|
||||
"peek-poke",
|
||||
|
@ -6443,7 +6460,7 @@ dependencies = [
|
|||
"rendy-descriptor",
|
||||
"rendy-memory",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"smallvec 0.6.10",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ name = "fallible"
|
|||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
smallvec = "0.6"
|
||||
smallvec = "1.0"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
|
||||
# This crate effectively does nothing except if the `known_system_malloc`
|
||||
|
|
|
@ -131,7 +131,7 @@ impl<'a> From<&'a FontStyleStruct> for FontDescriptor {
|
|||
FontDescriptor {
|
||||
template_descriptor: FontTemplateDescriptor::from(style),
|
||||
variant: style.font_variant_caps,
|
||||
pt_size: style.font_size.size(),
|
||||
pt_size: Au::from_f32_px(style.font_size.size().px()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ impl<S: FontSource> FontContext<S> {
|
|||
self.expire_font_caches_if_necessary();
|
||||
|
||||
let cache_key = FontGroupCacheKey {
|
||||
size: style.font_size.size(),
|
||||
size: Au::from_f32_px(style.font_size.size().px()),
|
||||
style,
|
||||
};
|
||||
|
||||
|
|
|
@ -2029,7 +2029,7 @@ impl BlockFlow {
|
|||
// If `max-width` is set, then don't perform this speculation. We guess that the
|
||||
// page set `max-width` in order to avoid hitting floats. The search box on Google
|
||||
// SERPs falls into this category.
|
||||
if self.fragment.style.max_inline_size() != MaxSize::None {
|
||||
if !matches!(self.fragment.style.max_inline_size(), MaxSize::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2548,8 +2548,16 @@ impl Flow for BlockFlow {
|
|||
.base
|
||||
.flags
|
||||
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) &&
|
||||
self.fragment.style().logical_position().inline_start == LengthPercentageOrAuto::Auto &&
|
||||
self.fragment.style().logical_position().inline_end == LengthPercentageOrAuto::Auto
|
||||
self.fragment
|
||||
.style()
|
||||
.logical_position()
|
||||
.inline_start
|
||||
.is_auto() &&
|
||||
self.fragment
|
||||
.style()
|
||||
.logical_position()
|
||||
.inline_end
|
||||
.is_auto()
|
||||
{
|
||||
self.base.position.start.i = inline_position
|
||||
}
|
||||
|
@ -2560,8 +2568,12 @@ impl Flow for BlockFlow {
|
|||
.base
|
||||
.flags
|
||||
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) &&
|
||||
self.fragment.style().logical_position().block_start == LengthPercentageOrAuto::Auto &&
|
||||
self.fragment.style().logical_position().block_end == LengthPercentageOrAuto::Auto
|
||||
self.fragment
|
||||
.style()
|
||||
.logical_position()
|
||||
.block_start
|
||||
.is_auto() &&
|
||||
self.fragment.style().logical_position().block_end.is_auto()
|
||||
{
|
||||
self.base.position.start.b = block_position
|
||||
}
|
||||
|
@ -2848,16 +2860,15 @@ pub trait ISizeAndMarginsComputer {
|
|||
parent_flow_inline_size: Au,
|
||||
shared_context: &SharedStyleContext,
|
||||
) -> MaybeAuto {
|
||||
let inline_size =
|
||||
self.containing_block_inline_size(block, parent_flow_inline_size, shared_context);
|
||||
|
||||
MaybeAuto::from_option(
|
||||
block
|
||||
.fragment()
|
||||
.style()
|
||||
.content_inline_size()
|
||||
.to_used_value(self.containing_block_inline_size(
|
||||
block,
|
||||
parent_flow_inline_size,
|
||||
shared_context,
|
||||
)),
|
||||
.to_used_value(inline_size),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ pub fn get_cyclic<T>(arr: &[T], index: usize) -> &T {
|
|||
/// For a given area and an image compute how big the
|
||||
/// image should be displayed on the background.
|
||||
fn compute_background_image_size(
|
||||
bg_size: BackgroundSize,
|
||||
bg_size: &BackgroundSize,
|
||||
bounds_size: Size2D<Au>,
|
||||
intrinsic_size: Option<Size2D<Au>>,
|
||||
) -> Size2D<Au> {
|
||||
|
@ -156,7 +156,7 @@ pub fn placement(
|
|||
let bg_position_x = get_cyclic(&bg.background_position_x.0, index);
|
||||
let bg_position_y = get_cyclic(&bg.background_position_y.0, index);
|
||||
let bg_repeat = get_cyclic(&bg.background_repeat.0, index);
|
||||
let bg_size = *get_cyclic(&bg.background_size.0, index);
|
||||
let bg_size = get_cyclic(&bg.background_size.0, index);
|
||||
|
||||
let (clip_rect, clip_radii) = clip(
|
||||
bg_clip,
|
||||
|
|
|
@ -25,7 +25,7 @@ use webrender_api::{BorderRadius, BorderSide, BorderStyle, ColorF, NormalBorder}
|
|||
///
|
||||
/// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius
|
||||
fn corner_radius(
|
||||
radius: BorderCornerRadius,
|
||||
radius: &BorderCornerRadius,
|
||||
containing_size: UntypedSize2D<Au>,
|
||||
) -> UntypedSize2D<Au> {
|
||||
let w = radius.0.width().to_used_value(containing_size.width);
|
||||
|
@ -91,13 +91,13 @@ pub fn radii(abs_bounds: Rect<Au>, border_style: &Border) -> BorderRadius {
|
|||
overlapping_radii(
|
||||
abs_bounds.size.to_layout(),
|
||||
BorderRadius {
|
||||
top_left: corner_radius(border_style.border_top_left_radius, abs_bounds.size)
|
||||
top_left: corner_radius(&border_style.border_top_left_radius, abs_bounds.size)
|
||||
.to_layout(),
|
||||
top_right: corner_radius(border_style.border_top_right_radius, abs_bounds.size)
|
||||
top_right: corner_radius(&border_style.border_top_right_radius, abs_bounds.size)
|
||||
.to_layout(),
|
||||
bottom_right: corner_radius(border_style.border_bottom_right_radius, abs_bounds.size)
|
||||
bottom_right: corner_radius(&border_style.border_bottom_right_radius, abs_bounds.size)
|
||||
.to_layout(),
|
||||
bottom_left: corner_radius(border_style.border_bottom_left_radius, abs_bounds.size)
|
||||
bottom_left: corner_radius(&border_style.border_bottom_left_radius, abs_bounds.size)
|
||||
.to_layout(),
|
||||
},
|
||||
)
|
||||
|
@ -161,7 +161,7 @@ pub fn image_outset(
|
|||
}
|
||||
|
||||
fn side_image_width(
|
||||
border_image_width: BorderImageSideWidth,
|
||||
border_image_width: &BorderImageSideWidth,
|
||||
border_width: f32,
|
||||
total_length: Au,
|
||||
) -> f32 {
|
||||
|
@ -178,10 +178,10 @@ pub fn image_width(
|
|||
border_area: UntypedSize2D<Au>,
|
||||
) -> LayoutSideOffsets {
|
||||
LayoutSideOffsets::new(
|
||||
side_image_width(width.0, border.top, border_area.height),
|
||||
side_image_width(width.1, border.right, border_area.width),
|
||||
side_image_width(width.2, border.bottom, border_area.height),
|
||||
side_image_width(width.3, border.left, border_area.width),
|
||||
side_image_width(&width.0, border.top, border_area.height),
|
||||
side_image_width(&width.1, border.right, border_area.width),
|
||||
side_image_width(&width.2, border.bottom, border_area.height),
|
||||
side_image_width(&width.3, border.left, border_area.width),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -995,7 +995,7 @@ impl Fragment {
|
|||
};
|
||||
DisplayItem::Gradient(CommonDisplayItem::with_data(base, item, stops))
|
||||
},
|
||||
GradientKind::Radial(shape, center) => {
|
||||
GradientKind::Radial(ref shape, ref center) => {
|
||||
let (gradient, stops) = gradient::radial(
|
||||
style,
|
||||
placement.tile_size,
|
||||
|
@ -1238,7 +1238,7 @@ impl Fragment {
|
|||
stops = linear_stops;
|
||||
NinePatchBorderSource::Gradient(wr_gradient)
|
||||
},
|
||||
GradientKind::Radial(shape, center) => {
|
||||
GradientKind::Radial(ref shape, ref center) => {
|
||||
let (wr_gradient, radial_stops) = gradient::radial(
|
||||
style,
|
||||
border_image_area,
|
||||
|
|
|
@ -91,9 +91,12 @@ fn convert_gradient_stops(
|
|||
color,
|
||||
position: None,
|
||||
}),
|
||||
GradientItem::ComplexColorStop { color, position } => Some(ColorStop {
|
||||
GradientItem::ComplexColorStop {
|
||||
color,
|
||||
position: Some(position),
|
||||
ref position,
|
||||
} => Some(ColorStop {
|
||||
color,
|
||||
position: Some(position.clone()),
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
|
@ -122,15 +125,24 @@ fn convert_gradient_stops(
|
|||
|
||||
// Step 2: Move any stops placed before earlier stops to the
|
||||
// same position as the preceding stop.
|
||||
let mut last_stop_position = stop_items.first().unwrap().position.unwrap();
|
||||
//
|
||||
// FIXME(emilio): Once we know the offsets, it seems like converting the
|
||||
// positions to absolute at once then process that would be cheaper.
|
||||
let mut last_stop_position = stop_items
|
||||
.first()
|
||||
.unwrap()
|
||||
.position
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.clone();
|
||||
for stop in stop_items.iter_mut().skip(1) {
|
||||
if let Some(pos) = stop.position {
|
||||
if position_to_offset(last_stop_position, total_length) >
|
||||
if let Some(ref pos) = stop.position {
|
||||
if position_to_offset(&last_stop_position, total_length) >
|
||||
position_to_offset(pos, total_length)
|
||||
{
|
||||
stop.position = Some(last_stop_position);
|
||||
}
|
||||
last_stop_position = stop.position.unwrap();
|
||||
last_stop_position = stop.position.as_ref().unwrap().clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,8 +156,10 @@ fn convert_gradient_stops(
|
|||
// Initialize a new stop run.
|
||||
// `unwrap()` here should never fail because this is the beginning of
|
||||
// a stop run, which is always bounded by a length or percentage.
|
||||
let start_offset =
|
||||
position_to_offset(stop_items[i - 1].position.unwrap(), total_length);
|
||||
let start_offset = position_to_offset(
|
||||
stop_items[i - 1].position.as_ref().unwrap(),
|
||||
total_length,
|
||||
);
|
||||
// `unwrap()` here should never fail because this is the end of
|
||||
// a stop run, which is always bounded by a length or percentage.
|
||||
let (end_index, end_stop) = stop_items[(i + 1)..]
|
||||
|
@ -153,7 +167,8 @@ fn convert_gradient_stops(
|
|||
.enumerate()
|
||||
.find(|&(_, ref stop)| stop.position.is_some())
|
||||
.unwrap();
|
||||
let end_offset = position_to_offset(end_stop.position.unwrap(), total_length);
|
||||
let end_offset =
|
||||
position_to_offset(end_stop.position.as_ref().unwrap(), total_length);
|
||||
stop_run = Some(StopRun {
|
||||
start_offset,
|
||||
end_offset,
|
||||
|
@ -168,7 +183,7 @@ fn convert_gradient_stops(
|
|||
stop_run_length * (i - stop_run.start_index) as f32 /
|
||||
((2 + stop_run.stop_count) as f32)
|
||||
},
|
||||
Some(position) => {
|
||||
Some(ref position) => {
|
||||
stop_run = None;
|
||||
position_to_offset(position, total_length)
|
||||
},
|
||||
|
@ -212,7 +227,7 @@ where
|
|||
Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side))
|
||||
}
|
||||
|
||||
fn position_to_offset(position: LengthPercentage, total_length: Au) -> f32 {
|
||||
fn position_to_offset(position: &LengthPercentage, total_length: Au) -> f32 {
|
||||
if total_length == Au(0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -289,8 +304,8 @@ pub fn radial(
|
|||
style: &ComputedValues,
|
||||
size: Size2D<Au>,
|
||||
stops: &[GradientItem],
|
||||
shape: EndingShape,
|
||||
center: Position,
|
||||
shape: &EndingShape,
|
||||
center: &Position,
|
||||
repeating: bool,
|
||||
) -> (RadialGradient, Vec<GradientStop>) {
|
||||
let center = Point2D::new(
|
||||
|
@ -299,15 +314,15 @@ pub fn radial(
|
|||
);
|
||||
let radius = match shape {
|
||||
EndingShape::Circle(Circle::Radius(length)) => {
|
||||
let length = Au::from(length);
|
||||
let length = Au::from(*length);
|
||||
Size2D::new(length, length)
|
||||
},
|
||||
EndingShape::Circle(Circle::Extent(extent)) => circle_size_keyword(extent, &size, ¢er),
|
||||
EndingShape::Circle(Circle::Extent(extent)) => circle_size_keyword(*extent, &size, ¢er),
|
||||
EndingShape::Ellipse(Ellipse::Radii(x, y)) => {
|
||||
Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height))
|
||||
},
|
||||
EndingShape::Ellipse(Ellipse::Extent(extent)) => {
|
||||
ellipse_size_keyword(extent, &size, ¢er)
|
||||
ellipse_size_keyword(*extent, &size, ¢er)
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ enum AxisSize {
|
|||
impl AxisSize {
|
||||
/// Generate a new available cross or main axis size from the specified size of the container,
|
||||
/// containing block size, min constraint, and max constraint
|
||||
pub fn new(size: Size, content_size: Option<Au>, min: Size, max: MaxSize) -> AxisSize {
|
||||
pub fn new(size: &Size, content_size: Option<Au>, min: &Size, max: &MaxSize) -> AxisSize {
|
||||
match size {
|
||||
Size::Auto => AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None)),
|
||||
Size::LengthPercentage(ref lp) => match lp.maybe_to_used_value(content_size) {
|
||||
|
@ -58,10 +58,10 @@ impl AxisSize {
|
|||
/// and the container size, then return the used value of flex basis. it can be used to help
|
||||
/// determining the flex base size and to indicate whether the main size of the item
|
||||
/// is definite after flex size resolving.
|
||||
fn from_flex_basis(flex_basis: FlexBasis, main_length: Size, containing_length: Au) -> MaybeAuto {
|
||||
fn from_flex_basis(flex_basis: &FlexBasis, main_length: &Size, containing_length: Au) -> MaybeAuto {
|
||||
let width = match flex_basis {
|
||||
FlexBasis::Content => return MaybeAuto::Auto,
|
||||
FlexBasis::Size(width) => width,
|
||||
FlexBasis::Size(ref width) => width,
|
||||
};
|
||||
|
||||
let width = match width {
|
||||
|
@ -135,7 +135,7 @@ impl FlexItem {
|
|||
// https://drafts.csswg.org/css-flexbox-1/#min-size-auto
|
||||
Direction::Inline => {
|
||||
let basis = from_flex_basis(
|
||||
block.fragment.style.get_position().flex_basis,
|
||||
&block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_inline_size(),
|
||||
containing_length,
|
||||
);
|
||||
|
@ -170,7 +170,7 @@ impl FlexItem {
|
|||
},
|
||||
Direction::Block => {
|
||||
let basis = from_flex_basis(
|
||||
block.fragment.style.get_position().flex_basis,
|
||||
&block.fragment.style.get_position().flex_basis,
|
||||
block.fragment.style.content_block_size(),
|
||||
containing_length,
|
||||
);
|
||||
|
@ -452,7 +452,7 @@ impl FlexFlow {
|
|||
fn inline_mode_bubble_inline_sizes(&mut self) {
|
||||
// FIXME(emilio): This doesn't handle at all writing-modes.
|
||||
let fixed_width =
|
||||
!model::style_length(self.block_flow.fragment.style().get_position().width, None)
|
||||
!model::style_length(&self.block_flow.fragment.style().get_position().width, None)
|
||||
.is_auto();
|
||||
|
||||
let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes();
|
||||
|
@ -478,7 +478,7 @@ impl FlexFlow {
|
|||
// stripped out.
|
||||
fn block_mode_bubble_inline_sizes(&mut self) {
|
||||
let fixed_width =
|
||||
!model::style_length(self.block_flow.fragment.style().get_position().width, None)
|
||||
!model::style_length(&self.block_flow.fragment.style().get_position().width, None)
|
||||
.is_auto();
|
||||
|
||||
let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes();
|
||||
|
@ -960,9 +960,9 @@ impl Flow for FlexFlow {
|
|||
let style = &self.block_flow.fragment.style;
|
||||
let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical()
|
||||
{
|
||||
(style.get_position().width, style.get_position().height)
|
||||
(&style.get_position().width, &style.get_position().height)
|
||||
} else {
|
||||
(style.get_position().height, style.get_position().width)
|
||||
(&style.get_position().height, &style.get_position().width)
|
||||
};
|
||||
|
||||
let available_inline_size = AxisSize::new(
|
||||
|
|
|
@ -64,7 +64,6 @@ use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
|||
use style::properties::ComputedValues;
|
||||
use style::selector_parser::RestyleDamage;
|
||||
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||
use style::values::computed::LengthPercentageOrAuto;
|
||||
use webrender_api::units::LayoutTransform;
|
||||
|
||||
/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field
|
||||
|
@ -1020,13 +1019,13 @@ impl BaseFlow {
|
|||
flags.insert(FlowFlags::IS_ABSOLUTELY_POSITIONED);
|
||||
|
||||
let logical_position = style.logical_position();
|
||||
if logical_position.inline_start == LengthPercentageOrAuto::Auto &&
|
||||
logical_position.inline_end == LengthPercentageOrAuto::Auto
|
||||
if logical_position.inline_start.is_auto() &&
|
||||
logical_position.inline_end.is_auto()
|
||||
{
|
||||
flags.insert(FlowFlags::INLINE_POSITION_IS_STATIC);
|
||||
}
|
||||
if logical_position.block_start == LengthPercentageOrAuto::Auto &&
|
||||
logical_position.block_end == LengthPercentageOrAuto::Auto
|
||||
if logical_position.block_start.is_auto() &&
|
||||
logical_position.block_end.is_auto()
|
||||
{
|
||||
flags.insert(FlowFlags::BLOCK_POSITION_IS_STATIC);
|
||||
}
|
||||
|
@ -1113,13 +1112,12 @@ impl BaseFlow {
|
|||
let logical_position = style.logical_position();
|
||||
self.flags.set(
|
||||
FlowFlags::INLINE_POSITION_IS_STATIC,
|
||||
logical_position.inline_start == LengthPercentageOrAuto::Auto &&
|
||||
logical_position.inline_end == LengthPercentageOrAuto::Auto,
|
||||
logical_position.inline_start.is_auto() &&
|
||||
logical_position.inline_end.is_auto(),
|
||||
);
|
||||
self.flags.set(
|
||||
FlowFlags::BLOCK_POSITION_IS_STATIC,
|
||||
logical_position.block_start == LengthPercentageOrAuto::Auto &&
|
||||
logical_position.block_end == LengthPercentageOrAuto::Auto,
|
||||
logical_position.block_start.is_auto() && logical_position.block_end.is_auto(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,10 +61,9 @@ use style::selector_parser::RestyleDamage;
|
|||
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||
use style::str::char_is_whitespace;
|
||||
use style::values::computed::counters::ContentItem;
|
||||
use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, Size, VerticalAlign};
|
||||
use style::values::computed::{Size, VerticalAlign};
|
||||
use style::values::generics::box_::{Perspective, VerticalAlignKeyword};
|
||||
use style::values::generics::transform;
|
||||
use style::Zero;
|
||||
use webrender_api;
|
||||
use webrender_api::units::LayoutTransform;
|
||||
|
||||
|
@ -1329,13 +1328,17 @@ impl Fragment {
|
|||
return;
|
||||
},
|
||||
_ => {
|
||||
let margin = self.style().logical_margin();
|
||||
self.margin.inline_start =
|
||||
MaybeAuto::from_style(margin.inline_start, containing_block_inline_size)
|
||||
.specified_or_zero();
|
||||
self.margin.inline_end =
|
||||
MaybeAuto::from_style(margin.inline_end, containing_block_inline_size)
|
||||
.specified_or_zero();
|
||||
let (inline_start, inline_end) = {
|
||||
let margin = self.style().logical_margin();
|
||||
(
|
||||
MaybeAuto::from_style(margin.inline_start, containing_block_inline_size)
|
||||
.specified_or_zero(),
|
||||
MaybeAuto::from_style(margin.inline_end, containing_block_inline_size)
|
||||
.specified_or_zero(),
|
||||
)
|
||||
};
|
||||
self.margin.inline_start = inline_start;
|
||||
self.margin.inline_end = inline_end;
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1384,13 +1387,17 @@ impl Fragment {
|
|||
_ => {
|
||||
// NB: Percentages are relative to containing block inline-size (not block-size)
|
||||
// per CSS 2.1.
|
||||
let margin = self.style().logical_margin();
|
||||
self.margin.block_start =
|
||||
MaybeAuto::from_style(margin.block_start, containing_block_inline_size)
|
||||
.specified_or_zero();
|
||||
self.margin.block_end =
|
||||
MaybeAuto::from_style(margin.block_end, containing_block_inline_size)
|
||||
.specified_or_zero();
|
||||
let (block_start, block_end) = {
|
||||
let margin = self.style().logical_margin();
|
||||
(
|
||||
MaybeAuto::from_style(margin.block_start, containing_block_inline_size)
|
||||
.specified_or_zero(),
|
||||
MaybeAuto::from_style(margin.block_end, containing_block_inline_size)
|
||||
.specified_or_zero(),
|
||||
)
|
||||
};
|
||||
self.margin.block_start = block_start;
|
||||
self.margin.block_end = block_end;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1458,14 +1465,14 @@ impl Fragment {
|
|||
pub fn relative_position(&self, containing_block_size: &LogicalSize<Au>) -> LogicalSize<Au> {
|
||||
fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>) -> LogicalSize<Au> {
|
||||
let offsets = style.logical_position();
|
||||
let offset_i = if offsets.inline_start != LengthPercentageOrAuto::Auto {
|
||||
let offset_i = if !offsets.inline_start.is_auto() {
|
||||
MaybeAuto::from_style(offsets.inline_start, container_size.inline)
|
||||
.specified_or_zero()
|
||||
} else {
|
||||
-MaybeAuto::from_style(offsets.inline_end, container_size.inline)
|
||||
.specified_or_zero()
|
||||
};
|
||||
let offset_b = if offsets.block_start != LengthPercentageOrAuto::Auto {
|
||||
let offset_b = if !offsets.block_start.is_auto() {
|
||||
MaybeAuto::from_style(offsets.block_start, container_size.block).specified_or_zero()
|
||||
} else {
|
||||
-MaybeAuto::from_style(offsets.block_end, container_size.block).specified_or_zero()
|
||||
|
@ -2520,13 +2527,19 @@ impl Fragment {
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if inline_context_node.style.logical_margin().inline_end !=
|
||||
LengthPercentageOrAuto::zero()
|
||||
if !inline_context_node
|
||||
.style
|
||||
.logical_margin()
|
||||
.inline_end
|
||||
.is_definitely_zero()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if inline_context_node.style.logical_padding().inline_end !=
|
||||
LengthPercentage::zero()
|
||||
if !inline_context_node
|
||||
.style
|
||||
.logical_padding()
|
||||
.inline_end
|
||||
.is_definitely_zero()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -2546,13 +2559,19 @@ impl Fragment {
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if inline_context_node.style.logical_margin().inline_start !=
|
||||
LengthPercentageOrAuto::zero()
|
||||
if !inline_context_node
|
||||
.style
|
||||
.logical_margin()
|
||||
.inline_start
|
||||
.is_definitely_zero()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if inline_context_node.style.logical_padding().inline_start !=
|
||||
LengthPercentage::zero()
|
||||
if !inline_context_node
|
||||
.style
|
||||
.logical_padding()
|
||||
.inline_start
|
||||
.is_definitely_zero()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -3193,7 +3212,7 @@ impl Fragment {
|
|||
) -> Option<LayoutTransform> {
|
||||
match self.style().get_box().perspective {
|
||||
Perspective::Length(length) => {
|
||||
let perspective_origin = self.style().get_box().perspective_origin;
|
||||
let perspective_origin = &self.style().get_box().perspective_origin;
|
||||
let perspective_origin = Point2D::new(
|
||||
perspective_origin
|
||||
.horizontal
|
||||
|
|
|
@ -1275,7 +1275,7 @@ impl InlineFlow {
|
|||
&mut line_metrics,
|
||||
&inline_metrics,
|
||||
style.get_box().display,
|
||||
VerticalAlign::baseline(),
|
||||
&VerticalAlign::baseline(),
|
||||
&mut largest_block_size_for_top_fragments,
|
||||
&mut largest_block_size_for_bottom_fragments,
|
||||
);
|
||||
|
@ -1296,7 +1296,7 @@ impl InlineFlow {
|
|||
&mut line_metrics,
|
||||
&inline_metrics,
|
||||
node.style.get_box().display,
|
||||
node.style.get_box().vertical_align,
|
||||
&node.style.get_box().vertical_align,
|
||||
&mut largest_block_size_for_top_fragments,
|
||||
&mut largest_block_size_for_bottom_fragments,
|
||||
);
|
||||
|
@ -1318,7 +1318,7 @@ impl InlineFlow {
|
|||
line_metrics: &mut LineMetrics,
|
||||
inline_metrics: &InlineMetrics,
|
||||
display_value: Display,
|
||||
vertical_align_value: VerticalAlign,
|
||||
vertical_align_value: &VerticalAlign,
|
||||
largest_block_size_for_top_fragments: &mut Au,
|
||||
largest_block_size_for_bottom_fragments: &mut Au,
|
||||
) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(matches_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
|
|
@ -437,7 +437,7 @@ pub enum MaybeAuto {
|
|||
|
||||
impl MaybeAuto {
|
||||
#[inline]
|
||||
pub fn from_style(length: LengthPercentageOrAuto, containing_length: Au) -> MaybeAuto {
|
||||
pub fn from_style(length: &LengthPercentageOrAuto, containing_length: Au) -> MaybeAuto {
|
||||
match length {
|
||||
LengthPercentageOrAuto::Auto => MaybeAuto::Auto,
|
||||
LengthPercentageOrAuto::LengthPercentage(ref lp) => {
|
||||
|
@ -498,7 +498,7 @@ impl MaybeAuto {
|
|||
/// Receive an optional container size and return used value for width or height.
|
||||
///
|
||||
/// `style_length`: content size as given in the CSS.
|
||||
pub fn style_length(style_length: Size, container_size: Option<Au>) -> MaybeAuto {
|
||||
pub fn style_length(style_length: &Size, container_size: Option<Au>) -> MaybeAuto {
|
||||
match style_length {
|
||||
Size::Auto => MaybeAuto::Auto,
|
||||
Size::LengthPercentage(ref lp) => {
|
||||
|
@ -546,10 +546,10 @@ pub fn specified_margin_from_style(
|
|||
LogicalMargin::from_physical(
|
||||
writing_mode,
|
||||
SideOffsets2D::new(
|
||||
MaybeAuto::from_style(margin_style.margin_top, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(margin_style.margin_right, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(margin_style.margin_bottom, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(margin_style.margin_left, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(&margin_style.margin_top, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(&margin_style.margin_right, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(&margin_style.margin_bottom, Au(0)).specified_or_zero(),
|
||||
MaybeAuto::from_style(&margin_style.margin_left, Au(0)).specified_or_zero(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -568,8 +568,8 @@ impl SizeConstraint {
|
|||
/// Create a `SizeConstraint` for an axis.
|
||||
pub fn new(
|
||||
container_size: Option<Au>,
|
||||
min_size: Size,
|
||||
max_size: MaxSize,
|
||||
min_size: &Size,
|
||||
max_size: &MaxSize,
|
||||
border: Option<Au>,
|
||||
) -> SizeConstraint {
|
||||
let mut min_size = match min_size {
|
||||
|
|
|
@ -102,14 +102,14 @@ impl Flow for MulticolFlow {
|
|||
let column_width;
|
||||
{
|
||||
let style = &self.block_flow.fragment.style;
|
||||
let column_gap = match style.get_position().column_gap {
|
||||
NonNegativeLengthPercentageOrNormal::LengthPercentage(len) => {
|
||||
len.0.to_pixel_length(content_inline_size).into()
|
||||
let column_gap = Au::from(match style.get_position().column_gap {
|
||||
NonNegativeLengthPercentageOrNormal::LengthPercentage(ref len) => {
|
||||
len.0.to_pixel_length(content_inline_size)
|
||||
},
|
||||
NonNegativeLengthPercentageOrNormal::Normal => {
|
||||
self.block_flow.fragment.style.get_font().font_size.size()
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
let column_style = style.get_column();
|
||||
let mut column_count;
|
||||
|
|
|
@ -76,7 +76,7 @@ impl Flow for TableColGroupFlow {
|
|||
// Retrieve the specified value from the appropriate CSS property.
|
||||
let inline_size = fragment.style().content_inline_size();
|
||||
for _ in 0..fragment.column_span() {
|
||||
self.inline_sizes.push(inline_size)
|
||||
self.inline_sizes.push(inline_size.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,11 +403,6 @@ impl Flow for TableRowFlow {
|
|||
let child_row_span;
|
||||
{
|
||||
let child_table_cell = kid.as_mut_table_cell();
|
||||
child_specified_inline_size = child_table_cell
|
||||
.block_flow
|
||||
.fragment
|
||||
.style
|
||||
.content_inline_size();
|
||||
child_column_span = child_table_cell.column_span;
|
||||
child_row_span = child_table_cell.row_span;
|
||||
|
||||
|
@ -422,6 +417,13 @@ impl Flow for TableRowFlow {
|
|||
&mut self.preliminary_collapsed_borders,
|
||||
)
|
||||
}
|
||||
|
||||
child_specified_inline_size = child_table_cell
|
||||
.block_flow
|
||||
.fragment
|
||||
.style
|
||||
.content_inline_size()
|
||||
.clone();
|
||||
}
|
||||
|
||||
// Collect minimum and preferred inline-sizes of the cell for automatic table layout
|
||||
|
|
|
@ -519,7 +519,7 @@ pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) ->
|
|||
let font_size = style.get_font().font_size.size();
|
||||
match style.get_inherited_text().line_height {
|
||||
LineHeight::Normal => Au::from(metrics.line_gap),
|
||||
LineHeight::Number(l) => font_size.scale_by(l.0),
|
||||
LineHeight::Number(l) => Au::from(font_size * l.0),
|
||||
LineHeight::Length(l) => Au::from(l),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,13 +175,18 @@ impl flow_relative::Vec2<MaxSize<LengthPercentage>> {
|
|||
containing_block: &ContainingBlock,
|
||||
) -> flow_relative::Vec2<Option<Length>> {
|
||||
flow_relative::Vec2 {
|
||||
inline: self
|
||||
.inline
|
||||
.to_option()
|
||||
.map(|lp| lp.percentage_relative_to(containing_block.inline_size)),
|
||||
block: self.block.to_option().and_then(|olp| {
|
||||
olp.maybe_percentage_relative_to(containing_block.block_size.non_auto())
|
||||
}),
|
||||
inline: match self.inline {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => {
|
||||
Some(lp.percentage_relative_to(containing_block.inline_size))
|
||||
},
|
||||
},
|
||||
block: match self.block {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => {
|
||||
lp.maybe_percentage_relative_to(containing_block.block_size.non_auto())
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ pub(crate) struct HoistedAbsolutelyPositionedBox<'box_tree> {
|
|||
box_offsets: Vec2<AbsoluteBoxOffsets>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum AbsoluteBoxOffsets {
|
||||
StaticStart {
|
||||
start: Length,
|
||||
|
@ -113,13 +113,13 @@ impl AbsolutelyPositionedBox {
|
|||
box_offsets: Vec2 {
|
||||
inline: absolute_box_offsets(
|
||||
initial_start_corner.inline,
|
||||
box_offsets.inline_start,
|
||||
box_offsets.inline_end,
|
||||
box_offsets.inline_start.clone(),
|
||||
box_offsets.inline_end.clone(),
|
||||
),
|
||||
block: absolute_box_offsets(
|
||||
initial_start_corner.block,
|
||||
box_offsets.block_start,
|
||||
box_offsets.block_end,
|
||||
box_offsets.block_start.clone(),
|
||||
box_offsets.block_end.clone(),
|
||||
),
|
||||
},
|
||||
}
|
||||
|
@ -372,20 +372,20 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> {
|
|||
let inline_axis = solve_axis(
|
||||
cbis,
|
||||
pb.inline_sum(),
|
||||
computed_margin.inline_start,
|
||||
computed_margin.inline_end,
|
||||
computed_margin.inline_start.clone(),
|
||||
computed_margin.inline_end.clone(),
|
||||
/* avoid_negative_margin_start */ true,
|
||||
self.box_offsets.inline,
|
||||
self.box_offsets.inline.clone(),
|
||||
size.inline,
|
||||
);
|
||||
|
||||
let block_axis = solve_axis(
|
||||
cbis,
|
||||
pb.block_sum(),
|
||||
computed_margin.block_start,
|
||||
computed_margin.block_end,
|
||||
computed_margin.block_start.clone(),
|
||||
computed_margin.block_end.clone(),
|
||||
/* avoid_negative_margin_start */ false,
|
||||
self.box_offsets.block,
|
||||
self.box_offsets.block.clone(),
|
||||
size.block,
|
||||
);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use crate::style_ext::ComputedValuesExt;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthPercentage, Percentage};
|
||||
use style::values::generics::length::MaxSize;
|
||||
use style::Zero;
|
||||
|
||||
/// Which min/max-content values should be computed during box construction
|
||||
|
@ -114,11 +115,10 @@ impl BoxContentSizes {
|
|||
.inline
|
||||
.percentage_relative_to(Length::zero())
|
||||
.auto_is(Length::zero);
|
||||
let max_inline_size = style
|
||||
.max_box_size()
|
||||
.inline
|
||||
.to_option()
|
||||
.and_then(|lp| lp.as_length());
|
||||
let max_inline_size = match style.max_box_size().inline {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => lp.as_length(),
|
||||
};
|
||||
let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size);
|
||||
|
||||
// Percentages for 'width' are treated as 'auto'
|
||||
|
|
|
@ -55,9 +55,9 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn inline_size_is_length(&self) -> bool {
|
||||
let position = self.get_position();
|
||||
let size = if self.writing_mode.is_horizontal() {
|
||||
position.width
|
||||
&position.width
|
||||
} else {
|
||||
position.height
|
||||
&position.height
|
||||
};
|
||||
matches!(size, Size::LengthPercentage(lp) if lp.0.as_length().is_some())
|
||||
}
|
||||
|
@ -65,21 +65,21 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn inline_box_offsets_are_both_non_auto(&self) -> bool {
|
||||
let position = self.get_position();
|
||||
let (a, b) = if self.writing_mode.is_horizontal() {
|
||||
(position.left, position.right)
|
||||
(&position.left, &position.right)
|
||||
} else {
|
||||
(position.top, position.bottom)
|
||||
(&position.top, &position.bottom)
|
||||
};
|
||||
a != LengthPercentageOrAuto::Auto && b != LengthPercentageOrAuto::Auto
|
||||
!a.is_auto() && !b.is_auto()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
physical::Sides {
|
||||
top: position.top,
|
||||
left: position.left,
|
||||
bottom: position.bottom,
|
||||
right: position.right,
|
||||
top: position.top.clone(),
|
||||
left: position.left.clone(),
|
||||
bottom: position.bottom.clone(),
|
||||
right: position.right.clone(),
|
||||
}
|
||||
.to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -88,8 +88,8 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
physical::Vec2 {
|
||||
x: size_to_length(position.width),
|
||||
y: size_to_length(position.height),
|
||||
x: size_to_length(position.width.clone()),
|
||||
y: size_to_length(position.height.clone()),
|
||||
}
|
||||
.size_to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -98,8 +98,8 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
physical::Vec2 {
|
||||
x: size_to_length(position.min_width),
|
||||
y: size_to_length(position.min_height),
|
||||
x: size_to_length(position.min_width.clone()),
|
||||
y: size_to_length(position.min_height.clone()),
|
||||
}
|
||||
.size_to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ impl ComputedValuesExt for ComputedValues {
|
|||
};
|
||||
let position = self.get_position();
|
||||
physical::Vec2 {
|
||||
x: unwrap(position.max_width),
|
||||
y: unwrap(position.max_height),
|
||||
x: unwrap(position.max_width.clone()),
|
||||
y: unwrap(position.max_height.clone()),
|
||||
}
|
||||
.size_to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -122,10 +122,10 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn padding(&self) -> flow_relative::Sides<LengthPercentage> {
|
||||
let padding = self.get_padding();
|
||||
physical::Sides {
|
||||
top: padding.padding_top.0,
|
||||
left: padding.padding_left.0,
|
||||
bottom: padding.padding_bottom.0,
|
||||
right: padding.padding_right.0,
|
||||
top: padding.padding_top.0.clone(),
|
||||
left: padding.padding_left.0.clone(),
|
||||
bottom: padding.padding_bottom.0.clone(),
|
||||
right: padding.padding_right.0.clone(),
|
||||
}
|
||||
.to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -144,10 +144,10 @@ impl ComputedValuesExt for ComputedValues {
|
|||
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
|
||||
let margin = self.get_margin();
|
||||
physical::Sides {
|
||||
top: margin.margin_top,
|
||||
left: margin.margin_left,
|
||||
bottom: margin.margin_bottom,
|
||||
right: margin.margin_right,
|
||||
top: margin.margin_top.clone(),
|
||||
left: margin.margin_left.clone(),
|
||||
bottom: margin.margin_bottom.clone(),
|
||||
right: margin.margin_right.clone(),
|
||||
}
|
||||
.to_flow_relative(self.writing_mode)
|
||||
}
|
||||
|
@ -180,7 +180,9 @@ impl From<stylo::Display> for Display {
|
|||
|
||||
fn size_to_length(size: Size) -> LengthPercentageOrAuto {
|
||||
match size {
|
||||
Size::LengthPercentage(length) => LengthPercentageOrAuto::LengthPercentage(length.0),
|
||||
Size::LengthPercentage(length) => {
|
||||
LengthPercentageOrAuto::LengthPercentage(length.0.clone())
|
||||
},
|
||||
Size::Auto => LengthPercentageOrAuto::Auto,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ serde = { version = "1.0.27", optional = true }
|
|||
serde_bytes = { version = "0.11", optional = true }
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "2.3.0"
|
||||
smallvec = "0.6"
|
||||
smallvec = "1.0"
|
||||
string_cache = { version = "0.8", optional = true }
|
||||
thin-slice = "0.1.0"
|
||||
time = { version = "0.1.17", optional = true }
|
||||
|
|
|
@ -23,13 +23,13 @@ bench = []
|
|||
bitflags = "1.0"
|
||||
matches = "0.1"
|
||||
cssparser = "0.27"
|
||||
derive_more = "0.13"
|
||||
derive_more = "0.99"
|
||||
log = "0.4"
|
||||
fxhash = "0.2"
|
||||
phf = "0.8"
|
||||
precomputed-hash = "0.1"
|
||||
servo_arc = { version = "0.1", path = "../servo_arc" }
|
||||
smallvec = "0.6"
|
||||
smallvec = "1.0"
|
||||
thin-slice = "0.1.0"
|
||||
to_shmem = { path = "../to_shmem" }
|
||||
to_shmem_derive = { path = "../to_shmem_derive" }
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
//! is non-trivial. This module encapsulates those details and presents an
|
||||
//! easy-to-use API for the parser.
|
||||
|
||||
use crate::parser::{Combinator, Component, SelectorImpl};
|
||||
use crate::parser::{Combinator, Component, NonTSPseudoClass, SelectorImpl};
|
||||
use crate::sink::Push;
|
||||
use servo_arc::{Arc, HeaderWithLength, ThinArc};
|
||||
use smallvec::{self, SmallVec};
|
||||
|
@ -142,7 +142,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
|
|||
let iter = SelectorBuilderIter {
|
||||
current_simple_selectors: current.iter(),
|
||||
rest_of_simple_selectors: rest,
|
||||
combinators: self.combinators.drain().rev(),
|
||||
combinators: self.combinators.drain(..).rev(),
|
||||
};
|
||||
|
||||
Arc::into_thin(Arc::from_header_and_iter(header, iter))
|
||||
|
@ -152,7 +152,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
|
|||
struct SelectorBuilderIter<'a, Impl: SelectorImpl> {
|
||||
current_simple_selectors: slice::Iter<'a, Component<Impl>>,
|
||||
rest_of_simple_selectors: &'a [Component<Impl>],
|
||||
combinators: iter::Rev<smallvec::Drain<'a, (Combinator, usize)>>,
|
||||
combinators: iter::Rev<smallvec::Drain<'a, [(Combinator, usize); 16]>>,
|
||||
}
|
||||
|
||||
impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> {
|
||||
|
@ -322,10 +322,14 @@ where
|
|||
Component::NthLastOfType(..) |
|
||||
Component::FirstOfType |
|
||||
Component::LastOfType |
|
||||
Component::OnlyOfType |
|
||||
Component::NonTSPseudoClass(..) => {
|
||||
Component::OnlyOfType => {
|
||||
specificity.class_like_selectors += 1;
|
||||
},
|
||||
Component::NonTSPseudoClass(ref pseudo) => {
|
||||
if !pseudo.has_zero_specificity() {
|
||||
specificity.class_like_selectors += 1;
|
||||
}
|
||||
},
|
||||
Component::ExplicitUniversalType |
|
||||
Component::ExplicitAnyNamespace |
|
||||
Component::ExplicitNoNamespace |
|
||||
|
|
|
@ -52,6 +52,9 @@ pub trait NonTSPseudoClass: Sized + ToCss {
|
|||
///
|
||||
/// https://drafts.csswg.org/selectors-4/#useraction-pseudos
|
||||
fn is_user_action_state(&self) -> bool;
|
||||
|
||||
/// Whether this pseudo-class has zero specificity.
|
||||
fn has_zero_specificity(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
|
||||
|
@ -2336,6 +2339,11 @@ pub mod tests {
|
|||
fn is_user_action_state(&self) -> bool {
|
||||
self.is_active_or_hover()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_zero_specificity(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for PseudoClass {
|
||||
|
|
|
@ -35,7 +35,7 @@ bitflags = "1.0"
|
|||
byteorder = "1.0"
|
||||
cssparser = "0.27"
|
||||
crossbeam-channel = { version = "0.3", optional = true }
|
||||
derive_more = "0.13"
|
||||
derive_more = "0.99"
|
||||
new_debug_unreachable = "1.0"
|
||||
encoding_rs = {version = "0.8", optional = true}
|
||||
euclid = "0.20"
|
||||
|
@ -66,7 +66,7 @@ servo_arc = { path = "../servo_arc" }
|
|||
servo_atoms = {path = "../atoms", optional = true}
|
||||
servo_config = {path = "../config", optional = true}
|
||||
smallbitvec = "2.3.0"
|
||||
smallvec = "0.6.6"
|
||||
smallvec = "1.0"
|
||||
string_cache = { version = "0.8", optional = true }
|
||||
style_derive = {path = "../style_derive"}
|
||||
style_traits = {path = "../style_traits"}
|
||||
|
|
|
@ -216,7 +216,7 @@ impl<E: TElement> StyleBloom<E> {
|
|||
self.filter.clear();
|
||||
self.pushed_hashes.clear();
|
||||
} else {
|
||||
for hash in self.pushed_hashes.drain() {
|
||||
for hash in self.pushed_hashes.drain(..) {
|
||||
self.filter.remove_hash(hash);
|
||||
}
|
||||
debug_assert!(self.filter.is_zeroed());
|
||||
|
@ -233,7 +233,7 @@ impl<E: TElement> StyleBloom<E> {
|
|||
element = parent;
|
||||
}
|
||||
|
||||
for parent in parents_to_insert.drain().rev() {
|
||||
for parent in parents_to_insert.drain(..).rev() {
|
||||
self.push(parent);
|
||||
}
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ impl<E: TElement> StyleBloom<E> {
|
|||
|
||||
// Now the parents match, so insert the stack of elements we have been
|
||||
// collecting so far.
|
||||
for parent in parents_to_insert.drain().rev() {
|
||||
for parent in parents_to_insert.drain(..).rev() {
|
||||
self.push(parent);
|
||||
}
|
||||
|
||||
|
|
|
@ -807,6 +807,9 @@ pub trait TElement:
|
|||
/// data if it comes from Shadow DOM.
|
||||
///
|
||||
/// Returns whether normal document author rules should apply.
|
||||
///
|
||||
/// TODO(emilio): We could separate the invalidation data for elements
|
||||
/// matching in other scopes to avoid over-invalidation.
|
||||
fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool
|
||||
where
|
||||
Self: 'a,
|
||||
|
@ -841,11 +844,42 @@ pub trait TElement:
|
|||
// Slots can only have assigned nodes when in a shadow tree.
|
||||
let shadow = slot.containing_shadow().unwrap();
|
||||
if let Some(data) = shadow.style_data() {
|
||||
f(data, shadow.host());
|
||||
if data.any_slotted_rule() {
|
||||
f(data, shadow.host());
|
||||
}
|
||||
}
|
||||
current = slot.assigned_slot();
|
||||
}
|
||||
|
||||
if target.has_part_attr() {
|
||||
if let Some(mut inner_shadow) = target.containing_shadow() {
|
||||
loop {
|
||||
let inner_shadow_host = inner_shadow.host();
|
||||
match inner_shadow_host.containing_shadow() {
|
||||
Some(shadow) => {
|
||||
if let Some(data) = shadow.style_data() {
|
||||
if data.any_part_rule() {
|
||||
f(data, shadow.host())
|
||||
}
|
||||
}
|
||||
// TODO: Could be more granular.
|
||||
if !shadow.host().exports_any_part() {
|
||||
break;
|
||||
}
|
||||
inner_shadow = shadow;
|
||||
},
|
||||
None => {
|
||||
// TODO(emilio): Should probably distinguish with
|
||||
// MatchesDocumentRules::{No,Yes,IfPart} or
|
||||
// something so that we could skip some work.
|
||||
doc_rules_apply = true;
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_rules_apply
|
||||
}
|
||||
|
||||
|
|
|
@ -7,17 +7,17 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
use crate::context::SharedStyleContext;
|
||||
use crate::values::computed::Length;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
|
||||
/// Represents the font metrics that style needs from a font to compute the
|
||||
/// value of certain CSS units like `ex`.
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct FontMetrics {
|
||||
/// The x-height of the font.
|
||||
pub x_height: Option<Au>,
|
||||
pub x_height: Option<Length>,
|
||||
/// The zero advance. This is usually writing mode dependent
|
||||
pub zero_advance_measure: Option<Au>,
|
||||
pub zero_advance_measure: Option<Length>,
|
||||
}
|
||||
|
||||
/// Type of font metrics to retrieve.
|
||||
|
@ -47,7 +47,7 @@ pub trait FontMetricsProvider {
|
|||
&self,
|
||||
font_name: &Atom,
|
||||
font_family: crate::values::computed::font::GenericFontFamily,
|
||||
) -> Au;
|
||||
) -> Length;
|
||||
|
||||
/// Construct from a shared style context
|
||||
fn create_from(context: &SharedStyleContext) -> Self
|
||||
|
@ -70,7 +70,7 @@ impl FontMetricsProvider for ServoMetricsProvider {
|
|||
ServoMetricsProvider
|
||||
}
|
||||
|
||||
fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Au {
|
||||
fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Length {
|
||||
unreachable!("Dummy provider should never be used to compute font size")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,9 @@ use crate::gecko_bindings::structs;
|
|||
use crate::media_queries::MediaType;
|
||||
use crate::properties::ComputedValues;
|
||||
use crate::string_cache::Atom;
|
||||
use crate::values::computed::font::FontSize;
|
||||
use crate::values::specified::font::FONT_MEDIUM_PX;
|
||||
use crate::values::{CustomIdent, KeyframesName};
|
||||
use app_units::Au;
|
||||
use app_units::AU_PER_PX;
|
||||
use app_units::{Au, AU_PER_PX};
|
||||
use cssparser::RGBA;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::Scale;
|
||||
|
@ -87,7 +86,7 @@ impl Device {
|
|||
document,
|
||||
default_values: ComputedValues::default_values(doc),
|
||||
// FIXME(bz): Seems dubious?
|
||||
root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
|
||||
root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX as i32).0 as isize),
|
||||
body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize),
|
||||
used_root_font_size: AtomicBool::new(false),
|
||||
used_viewport_size: AtomicBool::new(false),
|
||||
|
|
|
@ -48,8 +48,7 @@ macro_rules! apply_non_ts_list {
|
|||
("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _),
|
||||
("-moz-devtools-highlighted", MozDevtoolsHighlighted, mozDevtoolsHighlighted, IN_DEVTOOLS_HIGHLIGHTED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, mozStyleeditorTransitioning, IN_STYLEEDITOR_TRANSITIONING_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
|
||||
("-moz-full-screen", MozFullScreen, mozFullScreen, IN_FULLSCREEN_STATE, _),
|
||||
("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _),
|
||||
// TODO(emilio): This is inconsistently named (the capital R).
|
||||
("-moz-focusring", MozFocusRing, mozFocusRing, IN_FOCUSRING_STATE, _),
|
||||
("-moz-broken", MozBroken, mozBroken, IN_BROKEN_STATE, _),
|
||||
|
@ -94,6 +93,7 @@ macro_rules! apply_non_ts_list {
|
|||
("-moz-last-node", MozLastNode, lastNode, _, _),
|
||||
("-moz-only-whitespace", MozOnlyWhitespace, mozOnlyWhitespace, _, _),
|
||||
("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-native-anonymous-no-specificity", MozNativeAnonymousNoSpecificity, mozNativeAnonymousNoSpecificity, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS),
|
||||
("-moz-is-html", MozIsHTML, mozIsHTML, _, _),
|
||||
("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _),
|
||||
|
|
|
@ -193,18 +193,18 @@ impl PseudoElement {
|
|||
% for pseudo in SIMPLE_PSEUDOS:
|
||||
"${pseudo.value[1:]}" => {
|
||||
return Some(${pseudo_element_variant(pseudo)})
|
||||
}
|
||||
},
|
||||
% endfor
|
||||
// Alias some legacy prefixed pseudos to their standardized name at parse time:
|
||||
"-moz-selection" => {
|
||||
return Some(PseudoElement::Selection);
|
||||
}
|
||||
},
|
||||
"-moz-placeholder" => {
|
||||
return Some(PseudoElement::Placeholder);
|
||||
}
|
||||
},
|
||||
"-moz-list-bullet" | "-moz-list-number" => {
|
||||
return Some(PseudoElement::Marker);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
if starts_with_ignore_ascii_case(name, "-moz-tree-") {
|
||||
return PseudoElement::tree_pseudo_element(name, Box::new([]))
|
||||
|
|
|
@ -137,6 +137,7 @@ impl NonTSPseudoClass {
|
|||
([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => {
|
||||
match_ignore_ascii_case! { &name,
|
||||
$($css => Some(NonTSPseudoClass::$name),)*
|
||||
"-moz-full-screen" => Some(NonTSPseudoClass::Fullscreen),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -169,16 +170,9 @@ impl NonTSPseudoClass {
|
|||
}
|
||||
|
||||
/// Returns whether the pseudo-class is enabled in content sheets.
|
||||
#[inline]
|
||||
fn is_enabled_in_content(&self) -> bool {
|
||||
match *self {
|
||||
// For pseudo-classes with pref, the availability in content
|
||||
// depends on the pref.
|
||||
NonTSPseudoClass::Fullscreen => static_prefs::pref!("full-screen-api.unprefix.enabled"),
|
||||
// Otherwise, a pseudo-class is enabled in content when it
|
||||
// doesn't have any enabled flag.
|
||||
_ => !self
|
||||
.has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
|
||||
}
|
||||
!self.has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME)
|
||||
}
|
||||
|
||||
/// Get the state flag associated with a pseudo-class, if any.
|
||||
|
@ -233,6 +227,9 @@ impl NonTSPseudoClass {
|
|||
// across all the elements involved and the latter is already
|
||||
// checked for by our caching precondtions.
|
||||
NonTSPseudoClass::MozIsHTML |
|
||||
// We prevent style sharing for NAC.
|
||||
NonTSPseudoClass::MozNativeAnonymous |
|
||||
NonTSPseudoClass::MozNativeAnonymousNoSpecificity |
|
||||
// :-moz-placeholder is parsed but never matches.
|
||||
NonTSPseudoClass::MozPlaceholder |
|
||||
// :-moz-locale-dir and :-moz-window-inactive depend only on
|
||||
|
@ -275,6 +272,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass {
|
|||
NonTSPseudoClass::Hover | NonTSPseudoClass::Active | NonTSPseudoClass::Focus
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_zero_specificity(&self) -> bool {
|
||||
matches!(*self, NonTSPseudoClass::MozNativeAnonymousNoSpecificity)
|
||||
}
|
||||
}
|
||||
|
||||
/// The dummy struct we use to implement our selector parsing.
|
||||
|
@ -394,7 +396,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
|||
parser,
|
||||
)?.into()
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => return Err(parser.new_custom_error(
|
||||
SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone())
|
||||
))
|
||||
|
|
|
@ -71,7 +71,7 @@ impl GeckoElementSnapshot {
|
|||
}
|
||||
|
||||
/// Returns true if the snapshot recorded an attribute change which isn't a
|
||||
/// class or id change.
|
||||
/// class / id
|
||||
#[inline]
|
||||
pub fn other_attr_changed(&self) -> bool {
|
||||
self.mOtherAttributeChanged()
|
||||
|
|
|
@ -68,6 +68,7 @@ use crate::shared_lock::Locked;
|
|||
use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use crate::stylist::CascadeData;
|
||||
use crate::values::computed::font::GenericFontFamily;
|
||||
use crate::values::computed::Length;
|
||||
use crate::values::specified::length::FontBaseSize;
|
||||
use crate::CaseSensitivityExt;
|
||||
use app_units::Au;
|
||||
|
@ -929,7 +930,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
GeckoFontMetricsProvider::new()
|
||||
}
|
||||
|
||||
fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au {
|
||||
fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Length {
|
||||
let mut cache = self.font_size_cache.borrow_mut();
|
||||
if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
|
||||
return sizes.1.size_for_generic(font_family);
|
||||
|
@ -950,7 +951,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
None => return Default::default(),
|
||||
};
|
||||
|
||||
let size = base_size.resolve(context);
|
||||
let size = Au::from(base_size.resolve(context));
|
||||
let style = context.style();
|
||||
|
||||
let (wm, font) = match base_size {
|
||||
|
@ -977,9 +978,9 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
)
|
||||
};
|
||||
FontMetrics {
|
||||
x_height: Some(Au(gecko_metrics.mXSize)),
|
||||
x_height: Some(Au(gecko_metrics.mXSize).into()),
|
||||
zero_advance_measure: if gecko_metrics.mChSize >= 0 {
|
||||
Some(Au(gecko_metrics.mChSize))
|
||||
Some(Au(gecko_metrics.mChSize).into())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
@ -988,7 +989,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
|
|||
}
|
||||
|
||||
impl structs::FontSizePrefs {
|
||||
fn size_for_generic(&self, font_family: GenericFontFamily) -> Au {
|
||||
fn size_for_generic(&self, font_family: GenericFontFamily) -> Length {
|
||||
Au(match font_family {
|
||||
GenericFontFamily::None => self.mDefaultVariableSize,
|
||||
GenericFontFamily::Serif => self.mDefaultSerifSize,
|
||||
|
@ -1000,6 +1001,7 @@ impl structs::FontSizePrefs {
|
|||
"Should never get here, since this doesn't (yet) appear on font family"
|
||||
),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2045,7 +2047,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
NonTSPseudoClass::Disabled |
|
||||
NonTSPseudoClass::Checked |
|
||||
NonTSPseudoClass::Fullscreen |
|
||||
NonTSPseudoClass::MozFullScreen |
|
||||
NonTSPseudoClass::Indeterminate |
|
||||
NonTSPseudoClass::PlaceholderShown |
|
||||
NonTSPseudoClass::Target |
|
||||
|
@ -2130,7 +2131,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
}
|
||||
true
|
||||
},
|
||||
NonTSPseudoClass::MozNativeAnonymous => self.is_in_native_anonymous_subtree(),
|
||||
NonTSPseudoClass::MozNativeAnonymous |
|
||||
NonTSPseudoClass::MozNativeAnonymousNoSpecificity => {
|
||||
self.is_in_native_anonymous_subtree()
|
||||
},
|
||||
NonTSPseudoClass::MozUseShadowTreeRoot => self.is_root_of_use_element_shadow_tree(),
|
||||
NonTSPseudoClass::MozTableBorderNonzero => unsafe {
|
||||
bindings::Gecko_IsTableBorderNonzero(self.0)
|
||||
|
|
|
@ -89,9 +89,11 @@ impl<T> nsTArray<T> {
|
|||
pub unsafe fn set_len(&mut self, len: u32) {
|
||||
// this can leak
|
||||
debug_assert!(len >= self.len() as u32);
|
||||
if self.len() == len as usize {
|
||||
return;
|
||||
}
|
||||
self.ensure_capacity(len as usize);
|
||||
let header = self.header_mut();
|
||||
header.mLength = len;
|
||||
self.header_mut().mLength = len;
|
||||
}
|
||||
|
||||
/// Resizes an array containing only POD elements
|
||||
|
@ -103,6 +105,9 @@ impl<T> nsTArray<T> {
|
|||
where
|
||||
T: Copy,
|
||||
{
|
||||
if self.len() == len as usize {
|
||||
return;
|
||||
}
|
||||
self.ensure_capacity(len as usize);
|
||||
let header = self.header_mut();
|
||||
header.mLength = len;
|
||||
|
|
|
@ -142,6 +142,19 @@ pub struct DocumentStateDependency {
|
|||
pub state: DocumentState,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// A set of flags that denote whether any invalidations have occurred
|
||||
/// for a particular attribute selector.
|
||||
#[derive(MallocSizeOf)]
|
||||
#[repr(C)]
|
||||
pub struct InvalidationMapFlags : u8 {
|
||||
/// Whether [class] or such is used.
|
||||
const HAS_CLASS_ATTR_SELECTOR = 1 << 0;
|
||||
/// Whether [id] or such is used.
|
||||
const HAS_ID_ATTR_SELECTOR = 1 << 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// A map where we store invalidations.
|
||||
///
|
||||
/// This is slightly different to a SelectorMap, in the sense of that the same
|
||||
|
@ -164,16 +177,9 @@ pub struct InvalidationMap {
|
|||
pub document_state_selectors: Vec<DocumentStateDependency>,
|
||||
/// A map of other attribute affecting selectors.
|
||||
pub other_attribute_affecting_selectors: SelectorMap<Dependency>,
|
||||
/// Whether there are attribute rules of the form `[class~="foo"]` that may
|
||||
/// match. In that case, we need to look at
|
||||
/// `other_attribute_affecting_selectors` too even if only the `class` has
|
||||
/// changed.
|
||||
pub has_class_attribute_selectors: bool,
|
||||
/// Whether there are attribute rules of the form `[id|="foo"]` that may
|
||||
/// match. In that case, we need to look at
|
||||
/// `other_attribute_affecting_selectors` too even if only the `id` has
|
||||
/// changed.
|
||||
pub has_id_attribute_selectors: bool,
|
||||
/// A set of flags that contain whether various special attributes are used
|
||||
/// in this invalidation map.
|
||||
pub flags: InvalidationMapFlags,
|
||||
}
|
||||
|
||||
impl InvalidationMap {
|
||||
|
@ -185,8 +191,7 @@ impl InvalidationMap {
|
|||
state_affecting_selectors: SelectorMap::new(),
|
||||
document_state_selectors: Vec::new(),
|
||||
other_attribute_affecting_selectors: SelectorMap::new(),
|
||||
has_class_attribute_selectors: false,
|
||||
has_id_attribute_selectors: false,
|
||||
flags: InvalidationMapFlags::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,8 +215,7 @@ impl InvalidationMap {
|
|||
self.state_affecting_selectors.clear();
|
||||
self.document_state_selectors.clear();
|
||||
self.other_attribute_affecting_selectors.clear();
|
||||
self.has_id_attribute_selectors = false;
|
||||
self.has_class_attribute_selectors = false;
|
||||
self.flags = InvalidationMapFlags::empty();
|
||||
}
|
||||
|
||||
/// Adds a selector to this `InvalidationMap`. Returns Err(..) to
|
||||
|
@ -238,8 +242,7 @@ impl InvalidationMap {
|
|||
state: ElementState::empty(),
|
||||
document_state: &mut document_state,
|
||||
other_attributes: false,
|
||||
has_id_attribute_selectors: false,
|
||||
has_class_attribute_selectors: false,
|
||||
flags: &mut self.flags,
|
||||
};
|
||||
|
||||
// Visit all the simple selectors in this sequence.
|
||||
|
@ -255,9 +258,6 @@ impl InvalidationMap {
|
|||
index += 1; // Account for the simple selector.
|
||||
}
|
||||
|
||||
self.has_id_attribute_selectors |= compound_visitor.has_id_attribute_selectors;
|
||||
self.has_class_attribute_selectors |= compound_visitor.has_class_attribute_selectors;
|
||||
|
||||
for class in compound_visitor.classes {
|
||||
self.class_to_selector
|
||||
.try_entry(class, quirks_mode)?
|
||||
|
@ -349,11 +349,8 @@ struct CompoundSelectorDependencyCollector<'a> {
|
|||
/// [id] attribute selectors).
|
||||
other_attributes: bool,
|
||||
|
||||
/// Whether there were attribute selectors with the id attribute.
|
||||
has_id_attribute_selectors: bool,
|
||||
|
||||
/// Whether there were attribute selectors with the class attribute.
|
||||
has_class_attribute_selectors: bool,
|
||||
/// The invalidation map flags, that we set when some attribute selectors are present.
|
||||
flags: &'a mut InvalidationMapFlags,
|
||||
}
|
||||
|
||||
impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> {
|
||||
|
@ -398,8 +395,13 @@ impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> {
|
|||
};
|
||||
|
||||
if may_match_in_no_namespace {
|
||||
self.has_id_attribute_selectors |= *local_name_lower == local_name!("id");
|
||||
self.has_class_attribute_selectors |= *local_name_lower == local_name!("class");
|
||||
if *local_name_lower == local_name!("id") {
|
||||
self.flags
|
||||
.insert(InvalidationMapFlags::HAS_ID_ATTR_SELECTOR)
|
||||
} else if *local_name_lower == local_name!("class") {
|
||||
self.flags
|
||||
.insert(InvalidationMapFlags::HAS_CLASS_ATTR_SELECTOR)
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
|
|
|
@ -698,7 +698,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
sibling_invalidations.extend(new_sibling_invalidations.drain());
|
||||
sibling_invalidations.extend(new_sibling_invalidations.drain(..));
|
||||
invalidated_self
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ where
|
|||
descendant_invalidations: &'a mut DescendantInvalidationLists<'selectors>,
|
||||
sibling_invalidations: &'a mut InvalidationVector<'selectors>,
|
||||
invalidates_self: bool,
|
||||
attr_selector_flags: InvalidationMapFlags,
|
||||
}
|
||||
|
||||
/// An invalidation processor for style changes due to state and attribute
|
||||
|
@ -155,6 +156,8 @@ where
|
|||
return false;
|
||||
}
|
||||
|
||||
let mut attr_selector_flags = InvalidationMapFlags::empty();
|
||||
|
||||
// If we the visited state changed, we force a restyle here. Matching
|
||||
// doesn't depend on the actual visited state at all, so we can't look
|
||||
// at matching results to decide what to do for this case.
|
||||
|
@ -172,6 +175,7 @@ where
|
|||
let mut classes_removed = SmallVec::<[Atom; 8]>::new();
|
||||
let mut classes_added = SmallVec::<[Atom; 8]>::new();
|
||||
if snapshot.class_changed() {
|
||||
attr_selector_flags.insert(InvalidationMapFlags::HAS_CLASS_ATTR_SELECTOR);
|
||||
// TODO(emilio): Do this more efficiently!
|
||||
snapshot.each_class(|c| {
|
||||
if !element.has_class(c, CaseSensitivity::CaseSensitive) {
|
||||
|
@ -189,6 +193,7 @@ where
|
|||
let mut id_removed = None;
|
||||
let mut id_added = None;
|
||||
if snapshot.id_changed() {
|
||||
attr_selector_flags.insert(InvalidationMapFlags::HAS_ID_ATTR_SELECTOR);
|
||||
let old_id = snapshot.id_attr();
|
||||
let current_id = element.id();
|
||||
|
||||
|
@ -199,7 +204,10 @@ where
|
|||
}
|
||||
|
||||
if log_enabled!(::log::Level::Debug) {
|
||||
debug!("Collecting changes for: {:?}", element);
|
||||
debug!(
|
||||
"Collecting changes for: {:?}, flags {:?}",
|
||||
element, attr_selector_flags
|
||||
);
|
||||
if !state_changes.is_empty() {
|
||||
debug!(" > state: {:?}", state_changes);
|
||||
}
|
||||
|
@ -247,6 +255,7 @@ where
|
|||
descendant_invalidations,
|
||||
sibling_invalidations,
|
||||
invalidates_self: false,
|
||||
attr_selector_flags,
|
||||
};
|
||||
|
||||
let document_origins = if !matches_document_author_rules {
|
||||
|
@ -356,9 +365,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let should_examine_attribute_selector_map = self.snapshot.other_attr_changed() ||
|
||||
(self.snapshot.class_changed() && map.has_class_attribute_selectors) ||
|
||||
(self.snapshot.id_changed() && map.has_id_attribute_selectors);
|
||||
let should_examine_attribute_selector_map =
|
||||
self.snapshot.other_attr_changed() || map.flags.intersects(self.attr_selector_flags);
|
||||
|
||||
if should_examine_attribute_selector_map {
|
||||
self.collect_dependencies_in_map(&map.other_attribute_affecting_selectors)
|
||||
|
|
|
@ -468,7 +468,7 @@ impl<T: Zero> LogicalSize<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> LogicalSize<T> {
|
||||
impl<T> LogicalSize<T> {
|
||||
#[inline]
|
||||
pub fn new(mode: WritingMode, inline: T, block: T) -> LogicalSize<T> {
|
||||
LogicalSize {
|
||||
|
@ -486,7 +486,9 @@ impl<T: Copy> LogicalSize<T> {
|
|||
LogicalSize::new(mode, size.width, size.height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> LogicalSize<T> {
|
||||
#[inline]
|
||||
pub fn width(&self, mode: WritingMode) -> T {
|
||||
self.debug_writing_mode.check(mode);
|
||||
|
@ -860,7 +862,7 @@ impl<T: Zero> LogicalMargin<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> LogicalMargin<T> {
|
||||
impl<T> LogicalMargin<T> {
|
||||
#[inline]
|
||||
pub fn new(
|
||||
mode: WritingMode,
|
||||
|
@ -878,11 +880,6 @@ impl<T: Copy> LogicalMargin<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> {
|
||||
LogicalMargin::new(mode, value, value, value, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_physical(mode: WritingMode, offsets: SideOffsets2D<T>) -> LogicalMargin<T> {
|
||||
let block_start;
|
||||
|
@ -917,6 +914,13 @@ impl<T: Copy> LogicalMargin<T> {
|
|||
}
|
||||
LogicalMargin::new(mode, block_start, inline_end, block_end, inline_start)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> LogicalMargin<T> {
|
||||
#[inline]
|
||||
pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> {
|
||||
LogicalMargin::new(mode, value, value, value, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn top(&self, mode: WritingMode) -> T {
|
||||
|
|
|
@ -715,7 +715,7 @@ pub trait MatchMethods: TElement {
|
|||
.map_or(true, |s| s.get_font().clone_font_size() != new_font_size)
|
||||
{
|
||||
debug_assert!(self.owner_doc_matches_for_testing(device));
|
||||
device.set_root_font_size(new_font_size.size());
|
||||
device.set_root_font_size(new_font_size.size().into());
|
||||
// If the root font-size changed since last time, and something
|
||||
// in the document did use rem units, ensure we recascade the
|
||||
// entire tree.
|
||||
|
|
|
@ -180,7 +180,7 @@ fn top_down_dom<'a, 'scope, E, D>(
|
|||
let mut traversal_data_copy = traversal_data.clone();
|
||||
traversal_data_copy.current_dom_depth += 1;
|
||||
traverse_nodes(
|
||||
discovered_child_nodes.drain(),
|
||||
discovered_child_nodes.drain(..),
|
||||
DispatchMode::NotTailCall,
|
||||
recursion_ok,
|
||||
root,
|
||||
|
@ -210,7 +210,7 @@ fn top_down_dom<'a, 'scope, E, D>(
|
|||
if !discovered_child_nodes.is_empty() {
|
||||
traversal_data.current_dom_depth += 1;
|
||||
traverse_nodes(
|
||||
discovered_child_nodes.drain(),
|
||||
discovered_child_nodes.drain(..),
|
||||
DispatchMode::TailCall,
|
||||
recursion_ok,
|
||||
root,
|
||||
|
|
|
@ -743,6 +743,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
fn recompute_keyword_font_size_if_needed(&mut self) {
|
||||
use crate::values::computed::ToComputedValue;
|
||||
use crate::values::specified;
|
||||
use app_units::Au;
|
||||
|
||||
if !self.seen.contains(LonghandId::XLang) &&
|
||||
!self.seen.contains(LonghandId::FontFamily) {
|
||||
|
@ -759,7 +760,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
if font.gecko().mScriptUnconstrainedSize == new_size.size().0 {
|
||||
if font.gecko().mScriptUnconstrainedSize == Au::from(new_size.size()).0 {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
# "offset-distance",
|
||||
# "offset-path",
|
||||
# "offset-rotate",
|
||||
# "offset"
|
||||
# "offset",
|
||||
# "text-underline-position",
|
||||
COUNTED_UNKNOWN_PROPERTIES = [
|
||||
"-webkit-font-smoothing",
|
||||
"-webkit-tap-highlight-color",
|
||||
|
@ -40,7 +41,6 @@ COUNTED_UNKNOWN_PROPERTIES = [
|
|||
"baseline-shift",
|
||||
"-webkit-hyphenate-character",
|
||||
"page",
|
||||
"text-underline-position",
|
||||
"-webkit-highlight",
|
||||
"background-repeat-x",
|
||||
"-webkit-padding-end",
|
||||
|
|
|
@ -385,6 +385,7 @@ class Longhand(object):
|
|||
"TextDecorationLine",
|
||||
"TextEmphasisPosition",
|
||||
"TextTransform",
|
||||
"TextUnderlinePosition",
|
||||
"TouchAction",
|
||||
"TransformStyle",
|
||||
"UserSelect",
|
||||
|
|
|
@ -1433,7 +1433,7 @@ fn report_css_errors(
|
|||
selectors: Option<&SelectorList<SelectorImpl>>,
|
||||
errors: &mut SmallParseErrorVec,
|
||||
) {
|
||||
for (error, slice, property) in errors.drain() {
|
||||
for (error, slice, property) in errors.drain(..) {
|
||||
report_one_css_error(context, Some(block), selectors, error, slice, property)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -426,7 +426,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
|
||||
self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
|
||||
self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}.clone();
|
||||
self.gecko.mContextFlags =
|
||||
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
|
||||
(other.gecko.mContextFlags & CONTEXT_VALUE);
|
||||
|
@ -442,7 +442,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
|
||||
return SVGLength::ContextValue;
|
||||
}
|
||||
SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name})
|
||||
SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name}.clone())
|
||||
}
|
||||
</%def>
|
||||
|
||||
|
@ -563,7 +563,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
#[allow(non_snake_case)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
self.gecko.${gecko_ffi_name}.${index} =
|
||||
other.gecko.${gecko_ffi_name}.${index};
|
||||
other.gecko.${gecko_ffi_name}.${index}.clone();
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||
|
@ -572,7 +572,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
self.gecko.${gecko_ffi_name}.${index}
|
||||
self.gecko.${gecko_ffi_name}.${index}.clone()
|
||||
}
|
||||
</%def>
|
||||
|
||||
|
@ -601,7 +601,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
#[allow(non_snake_case)]
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
self.gecko.${gecko_ffi_name}.${corner} =
|
||||
other.gecko.${gecko_ffi_name}.${corner};
|
||||
other.gecko.${gecko_ffi_name}.${corner}.clone();
|
||||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn reset_${ident}(&mut self, other: &Self) {
|
||||
|
@ -609,7 +609,7 @@ def set_gecko_property(ffi_name, expr):
|
|||
}
|
||||
#[allow(non_snake_case)]
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
self.gecko.${gecko_ffi_name}.${corner}
|
||||
self.gecko.${gecko_ffi_name}.${corner}.clone()
|
||||
}
|
||||
</%def>
|
||||
|
||||
|
@ -1134,7 +1134,7 @@ fn static_assert() {
|
|||
pub fn set_font_size(&mut self, v: FontSize) {
|
||||
use crate::values::specified::font::KeywordSize;
|
||||
|
||||
let size = v.size();
|
||||
let size = Au::from(v.size());
|
||||
self.gecko.mScriptUnconstrainedSize = size.0;
|
||||
|
||||
// These two may be changed from Cascade::fixup_font_stuff.
|
||||
|
@ -1852,7 +1852,7 @@ fn static_assert() {
|
|||
for (layer, other) in self.gecko.${layers_field_name}.mLayers.iter_mut()
|
||||
.zip(other.gecko.${layers_field_name}.mLayers.iter())
|
||||
.take(count as usize) {
|
||||
layer.${field_name} = other.${field_name};
|
||||
layer.${field_name} = other.${field_name}.clone();
|
||||
}
|
||||
self.gecko.${layers_field_name}.${field_name}Count = count;
|
||||
}
|
||||
|
@ -2006,7 +2006,7 @@ fn static_assert() {
|
|||
for (layer, other) in self.gecko.${image_layers_field}.mLayers.iter_mut()
|
||||
.zip(other.gecko.${image_layers_field}.mLayers.iter())
|
||||
.take(count as usize) {
|
||||
layer.mPosition.${keyword} = other.mPosition.${keyword};
|
||||
layer.mPosition.${keyword} = other.mPosition.${keyword}.clone();
|
||||
}
|
||||
self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count = count;
|
||||
}
|
||||
|
@ -2020,7 +2020,7 @@ fn static_assert() {
|
|||
longhands::${shorthand}_position_${orientation}::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter()
|
||||
.take(self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count as usize)
|
||||
.map(|position| position.mPosition.${keyword})
|
||||
.map(|position| position.mPosition.${keyword}.clone())
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
@ -2054,7 +2054,7 @@ fn static_assert() {
|
|||
|
||||
pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T {
|
||||
longhands::${shorthand}_size::computed_value::List(
|
||||
self.gecko.${image_layers_field}.mLayers.iter().map(|layer| layer.mSize).collect()
|
||||
self.gecko.${image_layers_field}.mLayers.iter().map(|layer| layer.mSize.clone()).collect()
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ ${helpers.predefined_type(
|
|||
"border-image-source",
|
||||
"ImageLayer",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
initial_value="computed::ImageLayer::none()",
|
||||
initial_specified_value="specified::ImageLayer::none()",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image",
|
||||
|
@ -122,7 +121,6 @@ ${helpers.predefined_type(
|
|||
"border-image-outset",
|
||||
"NonNegativeLengthOrNumberRect",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
initial_value="generics::rect::Rect::all(computed::NonNegativeLengthOrNumber::zero())",
|
||||
initial_specified_value="generics::rect::Rect::all(specified::NonNegativeLengthOrNumber::zero())",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
|
||||
|
@ -135,7 +133,6 @@ ${helpers.predefined_type(
|
|||
"BorderImageRepeat",
|
||||
"computed::BorderImageRepeat::stretch()",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
initial_specified_value="specified::BorderImageRepeat::stretch()",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat",
|
||||
|
@ -145,7 +142,6 @@ ${helpers.predefined_type(
|
|||
"border-image-width",
|
||||
"BorderImageWidth",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
initial_value="computed::BorderImageWidth::all(computed::BorderImageSideWidth::one())",
|
||||
initial_specified_value="specified::BorderImageWidth::all(specified::BorderImageSideWidth::one())",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-width",
|
||||
|
@ -157,7 +153,6 @@ ${helpers.predefined_type(
|
|||
"border-image-slice",
|
||||
"BorderImageSlice",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
initial_value="computed::BorderImageSlice::hundred_percent()",
|
||||
initial_specified_value="specified::BorderImageSlice::hundred_percent()",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice",
|
||||
|
|
|
@ -24,7 +24,7 @@ ${helpers.single_keyword(
|
|||
"-moz-top-layer",
|
||||
"none top",
|
||||
engines="gecko",
|
||||
gecko_constant_prefix="NS_STYLE_TOP_LAYER",
|
||||
gecko_enum_prefix="StyleTopLayer",
|
||||
gecko_ffi_name="mTopLayer",
|
||||
animation_value_type="none",
|
||||
enabled_in="ua",
|
||||
|
@ -494,6 +494,7 @@ ${helpers.single_keyword(
|
|||
engines="gecko",
|
||||
spec="https://drafts.fxtf.org/compositing/#isolation",
|
||||
flags="CREATES_STACKING_CONTEXT",
|
||||
gecko_enum_prefix="StyleIsolation",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ ${helpers.single_keyword(
|
|||
gecko_ffi_name="mVisible",
|
||||
animation_value_type="ComputedValue",
|
||||
spec="https://drafts.csswg.org/css-box/#propdef-visibility",
|
||||
gecko_enum_prefix="StyleVisibility",
|
||||
)}
|
||||
|
||||
// CSS Writing Modes Level 3
|
||||
|
|
|
@ -53,7 +53,7 @@ ${helpers.single_keyword(
|
|||
"-moz-text-size-adjust",
|
||||
"auto none",
|
||||
engines="gecko",
|
||||
gecko_constant_prefix="NS_STYLE_TEXT_SIZE_ADJUST",
|
||||
gecko_enum_prefix="StyleTextSizeAdjust",
|
||||
gecko_ffi_name="mTextSizeAdjust",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-size-adjust/#adjustment-control",
|
||||
|
@ -332,6 +332,7 @@ ${helpers.single_keyword(
|
|||
"space-around start center space-between",
|
||||
engines="gecko",
|
||||
animation_value_type="discrete",
|
||||
gecko_enum_prefix="StyleRubyAlign",
|
||||
spec="https://drafts.csswg.org/css-ruby/#ruby-align-property",
|
||||
)}
|
||||
|
||||
|
@ -341,6 +342,7 @@ ${helpers.single_keyword(
|
|||
engines="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-ruby/#ruby-position-property",
|
||||
gecko_enum_prefix="StyleRubyPosition",
|
||||
)}
|
||||
|
||||
// CSS Writing Modes Module Level 3
|
||||
|
@ -389,6 +391,18 @@ ${helpers.predefined_type(
|
|||
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
|
||||
)}
|
||||
|
||||
// text underline position
|
||||
${helpers.predefined_type(
|
||||
"text-underline-position",
|
||||
"TextUnderlinePosition",
|
||||
"computed::TextUnderlinePosition::AUTO",
|
||||
engines="gecko",
|
||||
animation_value_type="discrete",
|
||||
gecko_pref="layout.css.text-underline-position.enabled",
|
||||
has_effect_on_gecko_scrollbars=False,
|
||||
spec="https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property",
|
||||
)}
|
||||
|
||||
// text decoration skip ink
|
||||
${helpers.predefined_type(
|
||||
"text-decoration-skip-ink",
|
||||
|
|
|
@ -26,6 +26,7 @@ ${helpers.single_keyword(
|
|||
animation_value_type="discrete",
|
||||
extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all",
|
||||
spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty",
|
||||
gecko_enum_prefix="StylePointerEvents",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
|
|
|
@ -3121,59 +3121,59 @@ impl ComputedValuesInner {
|
|||
|
||||
/// Get the logical computed inline size.
|
||||
#[inline]
|
||||
pub fn content_inline_size(&self) -> computed::Size {
|
||||
pub fn content_inline_size(&self) -> &computed::Size {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() {
|
||||
position_style.height
|
||||
&position_style.height
|
||||
} else {
|
||||
position_style.width
|
||||
&position_style.width
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the logical computed block size.
|
||||
#[inline]
|
||||
pub fn content_block_size(&self) -> computed::Size {
|
||||
pub fn content_block_size(&self) -> &computed::Size {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() { position_style.width } else { position_style.height }
|
||||
if self.writing_mode.is_vertical() { &position_style.width } else { &position_style.height }
|
||||
}
|
||||
|
||||
/// Get the logical computed min inline size.
|
||||
#[inline]
|
||||
pub fn min_inline_size(&self) -> computed::Size {
|
||||
pub fn min_inline_size(&self) -> &computed::Size {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width }
|
||||
if self.writing_mode.is_vertical() { &position_style.min_height } else { &position_style.min_width }
|
||||
}
|
||||
|
||||
/// Get the logical computed min block size.
|
||||
#[inline]
|
||||
pub fn min_block_size(&self) -> computed::Size {
|
||||
pub fn min_block_size(&self) -> &computed::Size {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height }
|
||||
if self.writing_mode.is_vertical() { &position_style.min_width } else { &position_style.min_height }
|
||||
}
|
||||
|
||||
/// Get the logical computed max inline size.
|
||||
#[inline]
|
||||
pub fn max_inline_size(&self) -> computed::MaxSize {
|
||||
pub fn max_inline_size(&self) -> &computed::MaxSize {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width }
|
||||
if self.writing_mode.is_vertical() { &position_style.max_height } else { &position_style.max_width }
|
||||
}
|
||||
|
||||
/// Get the logical computed max block size.
|
||||
#[inline]
|
||||
pub fn max_block_size(&self) -> computed::MaxSize {
|
||||
pub fn max_block_size(&self) -> &computed::MaxSize {
|
||||
let position_style = self.get_position();
|
||||
if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height }
|
||||
if self.writing_mode.is_vertical() { &position_style.max_width } else { &position_style.max_height }
|
||||
}
|
||||
|
||||
/// Get the logical computed padding for this writing mode.
|
||||
#[inline]
|
||||
pub fn logical_padding(&self) -> LogicalMargin<computed::LengthPercentage> {
|
||||
pub fn logical_padding(&self) -> LogicalMargin<<&computed::LengthPercentage> {
|
||||
let padding_style = self.get_padding();
|
||||
LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
|
||||
padding_style.padding_top.0,
|
||||
padding_style.padding_right.0,
|
||||
padding_style.padding_bottom.0,
|
||||
padding_style.padding_left.0,
|
||||
&padding_style.padding_top.0,
|
||||
&padding_style.padding_right.0,
|
||||
&padding_style.padding_bottom.0,
|
||||
&padding_style.padding_left.0,
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -3197,26 +3197,26 @@ impl ComputedValuesInner {
|
|||
|
||||
/// Gets the logical computed margin from this style.
|
||||
#[inline]
|
||||
pub fn logical_margin(&self) -> LogicalMargin<computed::LengthPercentageOrAuto> {
|
||||
pub fn logical_margin(&self) -> LogicalMargin<<&computed::LengthPercentageOrAuto> {
|
||||
let margin_style = self.get_margin();
|
||||
LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
|
||||
margin_style.margin_top,
|
||||
margin_style.margin_right,
|
||||
margin_style.margin_bottom,
|
||||
margin_style.margin_left,
|
||||
&margin_style.margin_top,
|
||||
&margin_style.margin_right,
|
||||
&margin_style.margin_bottom,
|
||||
&margin_style.margin_left,
|
||||
))
|
||||
}
|
||||
|
||||
/// Gets the logical position from this style.
|
||||
#[inline]
|
||||
pub fn logical_position(&self) -> LogicalMargin<computed::LengthPercentageOrAuto> {
|
||||
pub fn logical_position(&self) -> LogicalMargin<<&computed::LengthPercentageOrAuto> {
|
||||
// FIXME(SimonSapin): should be the writing mode of the containing block, maybe?
|
||||
let position_style = self.get_position();
|
||||
LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new(
|
||||
position_style.top,
|
||||
position_style.right,
|
||||
position_style.bottom,
|
||||
position_style.left,
|
||||
&position_style.top,
|
||||
&position_style.right,
|
||||
&position_style.bottom,
|
||||
&position_style.left,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -179,6 +179,16 @@ pub fn parse_border<'i, 't>(
|
|||
|
||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||
use crate::properties::longhands;
|
||||
|
||||
// If any of the border-image longhands differ from their initial specified values we should not
|
||||
// invoke serialize_directional_border(), so there is no point in continuing on to compute all_equal.
|
||||
% for name in "outset repeat slice source width".split():
|
||||
if *self.border_image_${name} != longhands::border_image_${name}::get_initial_specified_value() {
|
||||
return Ok(());
|
||||
}
|
||||
% endfor
|
||||
|
||||
let all_equal = {
|
||||
% for side in PHYSICAL_SIDES:
|
||||
let border_${side}_width = self.border_${side}_width;
|
||||
|
|
|
@ -348,7 +348,8 @@ where
|
|||
return;
|
||||
}
|
||||
|
||||
let outer_shadow = inner_shadow.host().containing_shadow();
|
||||
let inner_shadow_host = inner_shadow.host();
|
||||
let outer_shadow = inner_shadow_host.containing_shadow();
|
||||
let part_rules = match outer_shadow {
|
||||
Some(shadow) => shadow
|
||||
.style_data()
|
||||
|
@ -387,8 +388,6 @@ where
|
|||
shadow_cascade_order.inc();
|
||||
}
|
||||
|
||||
let inner_shadow_host = inner_shadow.host();
|
||||
|
||||
inner_shadow = match outer_shadow {
|
||||
Some(s) => s,
|
||||
None => break, // Nowhere to export to.
|
||||
|
|
|
@ -345,7 +345,7 @@ impl RuleTree {
|
|||
important_author.sort_by_key(|&(_, order)| -order);
|
||||
}
|
||||
|
||||
for (source, shadow_cascade_order) in important_author.drain() {
|
||||
for (source, shadow_cascade_order) in important_author.drain(..) {
|
||||
current = current.ensure_child(
|
||||
self.root.downgrade(),
|
||||
source,
|
||||
|
@ -355,11 +355,11 @@ impl RuleTree {
|
|||
);
|
||||
}
|
||||
|
||||
for source in important_user.drain() {
|
||||
for source in important_user.drain(..) {
|
||||
current = current.ensure_child(self.root.downgrade(), source, UserImportant);
|
||||
}
|
||||
|
||||
for source in important_ua.drain() {
|
||||
for source in important_ua.drain(..) {
|
||||
current = current.ensure_child(self.root.downgrade(), source, UAImportant);
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ impl RuleTree {
|
|||
guards: &StylesheetGuards,
|
||||
) -> StrongRuleNode {
|
||||
self.insert_ordered_rules_with_important(
|
||||
applicable_declarations.drain().map(|d| d.for_rule_tree()),
|
||||
applicable_declarations.drain(..).map(|d| d.for_rule_tree()),
|
||||
guards,
|
||||
)
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ impl RuleTree {
|
|||
|
||||
// Now the rule is in the relevant place, push the children as
|
||||
// necessary.
|
||||
let rule = self.insert_ordered_rules_from(current, children.drain().rev());
|
||||
let rule = self.insert_ordered_rules_from(current, children.drain(..).rev());
|
||||
Some(rule)
|
||||
}
|
||||
|
||||
|
@ -592,8 +592,8 @@ impl RuleTree {
|
|||
last = node;
|
||||
}
|
||||
|
||||
let rule =
|
||||
self.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain().rev());
|
||||
let rule = self
|
||||
.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain(..).rev());
|
||||
rule
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
|
|||
use crate::media_queries::media_feature_expression::RangeOrOperator;
|
||||
use crate::media_queries::MediaType;
|
||||
use crate::properties::ComputedValues;
|
||||
use crate::values::computed::font::FontSize;
|
||||
use crate::values::computed::CSSPixelLength;
|
||||
use crate::values::specified::font::FONT_MEDIUM_PX;
|
||||
use crate::values::KeyframesName;
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
|
@ -68,7 +68,7 @@ impl Device {
|
|||
viewport_size,
|
||||
device_pixel_ratio,
|
||||
// FIXME(bz): Seems dubious?
|
||||
root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
|
||||
root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX).0 as isize),
|
||||
used_root_font_size: AtomicBool::new(false),
|
||||
used_viewport_units: AtomicBool::new(false),
|
||||
environment: CssEnvironment,
|
||||
|
|
|
@ -309,6 +309,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass {
|
|||
NonTSPseudoClass::Active | NonTSPseudoClass::Hover | NonTSPseudoClass::Focus
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_zero_specificity(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for NonTSPseudoClass {
|
||||
|
|
|
@ -59,6 +59,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules};
|
|||
pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator};
|
||||
pub use self::style_rule::StyleRule;
|
||||
pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet};
|
||||
pub use self::stylesheet::{SanitizationData, SanitizationKind};
|
||||
pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets};
|
||||
pub use self::supports_rule::SupportsRule;
|
||||
pub use self::viewport_rule::ViewportRule;
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use crate::str::CssStringWriter;
|
||||
use crate::{Namespace, Prefix};
|
||||
use cssparser::SourceLocation;
|
||||
use cssparser::{self, SourceLocation};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
/// A `@namespace` rule.
|
||||
#[derive(Clone, Debug, PartialEq, ToShmem)]
|
||||
|
@ -27,13 +28,12 @@ impl ToCssWithGuard for NamespaceRule {
|
|||
fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
|
||||
dest.write_str("@namespace ")?;
|
||||
if let Some(ref prefix) = self.prefix {
|
||||
dest.write_str(&*prefix.to_string())?;
|
||||
let prefix = prefix.to_string();
|
||||
cssparser::serialize_identifier(&prefix, dest)?;
|
||||
dest.write_str(" ")?;
|
||||
}
|
||||
|
||||
// FIXME(emilio): Pretty sure this needs some escaping, or something?
|
||||
dest.write_str("url(\"")?;
|
||||
dest.write_str(&*self.url.to_string())?;
|
||||
dest.write_str("\");")
|
||||
dest.write_str("url(")?;
|
||||
self.url.to_string().to_css(&mut CssWriter::new(dest))?;
|
||||
dest.write_str(");")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ impl StylesheetContents {
|
|||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
use_counters: Option<&UseCounters>,
|
||||
sanitization_data: Option<&mut SanitizationData>,
|
||||
) -> Self {
|
||||
let namespaces = RwLock::new(Namespaces::default());
|
||||
let (rules, source_map_url, source_url) = Stylesheet::parse_rules(
|
||||
|
@ -94,6 +95,7 @@ impl StylesheetContents {
|
|||
quirks_mode,
|
||||
line_number_offset,
|
||||
use_counters,
|
||||
sanitization_data,
|
||||
);
|
||||
|
||||
Self {
|
||||
|
@ -341,6 +343,69 @@ impl StylesheetInDocument for DocumentStyleSheet {
|
|||
}
|
||||
}
|
||||
|
||||
/// The kind of sanitization to use when parsing a stylesheet.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum SanitizationKind {
|
||||
/// Perform no sanitization.
|
||||
None,
|
||||
/// Allow only @font-face, style rules, and @namespace.
|
||||
Standard,
|
||||
/// Allow everything but conditional rules.
|
||||
NoConditionalRules,
|
||||
}
|
||||
|
||||
impl SanitizationKind {
|
||||
fn allows(self, rule: &CssRule) -> bool {
|
||||
debug_assert_ne!(self, SanitizationKind::None);
|
||||
// NOTE(emilio): If this becomes more complex (not filtering just by
|
||||
// top-level rules), we should thread all the data through nested rules
|
||||
// and such. But this doesn't seem necessary at the moment.
|
||||
let is_standard = matches!(self, SanitizationKind::Standard);
|
||||
match *rule {
|
||||
CssRule::Document(..) |
|
||||
CssRule::Media(..) |
|
||||
CssRule::Supports(..) |
|
||||
CssRule::Import(..) => false,
|
||||
|
||||
CssRule::FontFace(..) | CssRule::Namespace(..) | CssRule::Style(..) => true,
|
||||
|
||||
CssRule::Keyframes(..) |
|
||||
CssRule::Page(..) |
|
||||
CssRule::FontFeatureValues(..) |
|
||||
CssRule::Viewport(..) |
|
||||
CssRule::CounterStyle(..) => !is_standard,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to hold the data relevant to style sheet sanitization.
|
||||
#[derive(Debug)]
|
||||
pub struct SanitizationData {
|
||||
kind: SanitizationKind,
|
||||
output: String,
|
||||
}
|
||||
|
||||
impl SanitizationData {
|
||||
/// Create a new input for sanitization.
|
||||
#[inline]
|
||||
pub fn new(kind: SanitizationKind) -> Option<Self> {
|
||||
if matches!(kind, SanitizationKind::None) {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
kind,
|
||||
output: String::new(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Take the sanitized output.
|
||||
#[inline]
|
||||
pub fn take(self) -> String {
|
||||
self.output
|
||||
}
|
||||
}
|
||||
|
||||
impl Stylesheet {
|
||||
/// Updates an empty stylesheet from a given string of text.
|
||||
pub fn update_from_str(
|
||||
|
@ -365,6 +430,7 @@ impl Stylesheet {
|
|||
existing.contents.quirks_mode,
|
||||
line_number_offset,
|
||||
/* use_counters = */ None,
|
||||
/* sanitization_data = */ None,
|
||||
);
|
||||
|
||||
*existing.contents.url_data.write() = url_data;
|
||||
|
@ -391,6 +457,7 @@ impl Stylesheet {
|
|||
quirks_mode: QuirksMode,
|
||||
line_number_offset: u32,
|
||||
use_counters: Option<&UseCounters>,
|
||||
mut sanitization_data: Option<&mut SanitizationData>,
|
||||
) -> (Vec<CssRule>, Option<String>, Option<String>) {
|
||||
let mut rules = Vec::new();
|
||||
let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset);
|
||||
|
@ -419,12 +486,24 @@ impl Stylesheet {
|
|||
{
|
||||
let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser);
|
||||
|
||||
while let Some(result) = iter.next() {
|
||||
loop {
|
||||
let rule_start = iter.input.position().byte_index();
|
||||
let result = match iter.next() {
|
||||
Some(result) => result,
|
||||
None => break,
|
||||
};
|
||||
match result {
|
||||
Ok(rule) => {
|
||||
// Use a fallible push here, and if it fails, just
|
||||
// fall out of the loop. This will cause the page to
|
||||
// be shown incorrectly, but it's better than OOMing.
|
||||
if let Some(ref mut data) = sanitization_data {
|
||||
if !data.kind.allows(&rule) {
|
||||
continue;
|
||||
}
|
||||
let end = iter.input.position().byte_index();
|
||||
data.output.push_str(&css[rule_start..end]);
|
||||
}
|
||||
// Use a fallible push here, and if it fails, just fall
|
||||
// out of the loop. This will cause the page to be
|
||||
// shown incorrectly, but it's better than OOMing.
|
||||
if rules.try_push(rule).is_err() {
|
||||
break;
|
||||
}
|
||||
|
@ -470,6 +549,7 @@ impl Stylesheet {
|
|||
quirks_mode,
|
||||
line_number_offset,
|
||||
/* use_counters = */ None,
|
||||
/* sanitized_output = */ None,
|
||||
);
|
||||
|
||||
Stylesheet {
|
||||
|
|
|
@ -1013,7 +1013,7 @@ impl Stylist {
|
|||
);
|
||||
if !declarations.is_empty() {
|
||||
let rule_node = self.rule_tree.insert_ordered_rules_with_important(
|
||||
declarations.drain().map(|a| a.for_rule_tree()),
|
||||
declarations.drain(..).map(|a| a.for_rule_tree()),
|
||||
guards,
|
||||
);
|
||||
if rule_node != *self.rule_tree.root() {
|
||||
|
@ -1889,18 +1889,33 @@ impl CascadeData {
|
|||
self.host_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||
}
|
||||
|
||||
/// Whether there's any host rule that could match in this scope.
|
||||
pub fn any_host_rules(&self) -> bool {
|
||||
self.host_rules.is_some()
|
||||
}
|
||||
|
||||
/// Returns the slotted rule map for a given pseudo-element.
|
||||
#[inline]
|
||||
pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> {
|
||||
self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||
}
|
||||
|
||||
/// Whether there's any ::slotted rule that could match in this scope.
|
||||
pub fn any_slotted_rule(&self) -> bool {
|
||||
self.slotted_rules.is_some()
|
||||
}
|
||||
|
||||
/// Returns the parts rule map for a given pseudo-element.
|
||||
#[inline]
|
||||
pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> {
|
||||
self.part_rules.as_ref().and_then(|d| d.rules(pseudo))
|
||||
}
|
||||
|
||||
/// Whether there's any ::part rule that could match in this scope.
|
||||
pub fn any_part_rule(&self) -> bool {
|
||||
self.part_rules.is_some()
|
||||
}
|
||||
|
||||
/// Collects all the applicable media query results into `results`.
|
||||
///
|
||||
/// This duplicates part of the logic in `add_stylesheet`, which is
|
||||
|
|
|
@ -1373,7 +1373,7 @@ impl ComputedTranslate {
|
|||
LengthPercentage::zero(),
|
||||
Length::zero(),
|
||||
),
|
||||
Translate::Translate(tx, ty, tz) => (tx, ty, tz),
|
||||
Translate::Translate(ref tx, ref ty, ref tz) => (tx.clone(), ty.clone(), tz.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ use crate::values::specified::font::{
|
|||
use crate::values::specified::length::{FontBaseSize, NoCalcLength};
|
||||
use crate::values::CSSFloat;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use cssparser::{serialize_identifier, CssStringWriter, Parser};
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -148,15 +147,16 @@ impl FontWeight {
|
|||
|
||||
impl FontSize {
|
||||
/// The actual computed font size.
|
||||
pub fn size(self) -> Au {
|
||||
self.size.into()
|
||||
#[inline]
|
||||
pub fn size(&self) -> Length {
|
||||
self.size.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Get default value of font size.
|
||||
pub fn medium() -> Self {
|
||||
Self {
|
||||
size: Au::from_px(specified::FONT_MEDIUM_PX).into(),
|
||||
size: NonNegative(Length::new(specified::FONT_MEDIUM_PX as CSSFloat)),
|
||||
keyword_info: Some(KeywordInfo::medium()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ pub use crate::values::specified::url::UrlOrNone;
|
|||
pub use crate::values::specified::{Angle, BorderStyle, Time};
|
||||
|
||||
impl ToComputedValue for specified::NoCalcLength {
|
||||
type ComputedValue = CSSPixelLength;
|
||||
type ComputedValue = Length;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
|
@ -75,9 +75,7 @@ impl ToComputedValue for specified::Length {
|
|||
///
|
||||
/// https://drafts.csswg.org/css-values-4/#typedef-length-percentage
|
||||
#[allow(missing_docs)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue,
|
||||
)]
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue)]
|
||||
#[repr(C)]
|
||||
pub struct LengthPercentage {
|
||||
length: Length,
|
||||
|
@ -543,14 +541,14 @@ impl ToAnimatedValue for NonNegativeLengthPercentage {
|
|||
impl From<NonNegativeLength> for NonNegativeLengthPercentage {
|
||||
#[inline]
|
||||
fn from(length: NonNegativeLength) -> Self {
|
||||
LengthPercentage::new(length.0, None).into()
|
||||
NonNegative(LengthPercentage::new(length.0, None))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LengthPercentage> for NonNegativeLengthPercentage {
|
||||
#[inline]
|
||||
fn from(lp: LengthPercentage) -> Self {
|
||||
NonNegative::<LengthPercentage>(lp)
|
||||
NonNegative(lp)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ pub use self::resolution::Resolution;
|
|||
pub use self::svg::MozContextProperties;
|
||||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::text::TextUnderlinePosition;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
|
||||
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
||||
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
||||
|
|
|
@ -19,6 +19,7 @@ use std::fmt::{self, Write};
|
|||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
||||
pub use crate::values::specified::TextUnderlinePosition;
|
||||
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
|
||||
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
|
||||
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
|
||||
|
|
|
@ -207,15 +207,6 @@ impl<LengthPercentage> MaxSize<LengthPercentage> {
|
|||
pub fn none() -> Self {
|
||||
MaxSize::None
|
||||
}
|
||||
|
||||
/// Convert
|
||||
#[cfg(not(feature = "gecko"))]
|
||||
pub fn to_option(self) -> Option<LengthPercentage> {
|
||||
match self {
|
||||
Self::LengthPercentage(lp) => Some(lp),
|
||||
Self::None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic `<length>` | `<number>` value for the `-moz-tab-size` property.
|
||||
|
|
|
@ -691,11 +691,11 @@ fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, Pars
|
|||
"first" => {
|
||||
input.expect_ident_matching("baseline")?;
|
||||
Ok(AlignFlags::BASELINE)
|
||||
}
|
||||
},
|
||||
"last" => {
|
||||
input.expect_ident_matching("baseline")?;
|
||||
Ok(AlignFlags::LAST_BASELINE)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,7 +794,7 @@ fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseE
|
|||
.unwrap_or(AlignFlags::empty());
|
||||
|
||||
return Ok(AlignFlags::LEGACY | flags)
|
||||
}
|
||||
},
|
||||
"left" => AlignFlags::LEFT,
|
||||
"right" => AlignFlags::RIGHT,
|
||||
"center" => AlignFlags::CENTER,
|
||||
|
|
|
@ -389,21 +389,10 @@ impl Display {
|
|||
};
|
||||
Display::from3(DisplayOutside::Block, inside, self.is_list_item())
|
||||
},
|
||||
// If this pref is true, then we'll blockify "-moz-inline-box" to
|
||||
// "-moz-box", and blockify "-moz-box" to itself. Otherwise, we
|
||||
// blockify both to "block".
|
||||
#[cfg(feature = "gecko")]
|
||||
DisplayOutside::XUL => {
|
||||
if static_prefs::pref!(
|
||||
"layout.css.xul-box-display-values.survive-blockification.enabled"
|
||||
) {
|
||||
match self.inside() {
|
||||
DisplayInside::MozInlineBox | DisplayInside::MozBox => Display::MozBox,
|
||||
_ => Display::Block,
|
||||
}
|
||||
} else {
|
||||
Display::Block
|
||||
}
|
||||
DisplayOutside::XUL => match self.inside() {
|
||||
DisplayInside::MozInlineBox | DisplayInside::MozBox => Display::MozBox,
|
||||
_ => Display::Block,
|
||||
},
|
||||
DisplayOutside::Block | DisplayOutside::None => *self,
|
||||
#[cfg(any(feature = "servo-layout-2013", feature = "gecko"))]
|
||||
|
|
|
@ -20,7 +20,6 @@ use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
|
|||
use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage};
|
||||
use crate::values::CustomIdent;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use cssparser::{Parser, Token};
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -773,18 +772,18 @@ impl ToComputedValue for KeywordSize {
|
|||
type ComputedValue = NonNegativeLength;
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> NonNegativeLength {
|
||||
let medium = Length::new(FONT_MEDIUM_PX as f32);
|
||||
// https://drafts.csswg.org/css-fonts-3/#font-size-prop
|
||||
match *self {
|
||||
KeywordSize::XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
|
||||
KeywordSize::XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
|
||||
KeywordSize::Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
|
||||
KeywordSize::Medium => Au::from_px(FONT_MEDIUM_PX),
|
||||
KeywordSize::Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
|
||||
KeywordSize::XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
|
||||
KeywordSize::XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2,
|
||||
KeywordSize::XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3,
|
||||
}
|
||||
.into()
|
||||
NonNegative(match *self {
|
||||
KeywordSize::XXSmall => medium * 3.0 / 5.0,
|
||||
KeywordSize::XSmall => medium * 3.0 / 4.0,
|
||||
KeywordSize::Small => medium * 8.0 / 9.0,
|
||||
KeywordSize::Medium => medium,
|
||||
KeywordSize::Large => medium * 6.0 / 5.0,
|
||||
KeywordSize::XLarge => medium * 3.0 / 2.0,
|
||||
KeywordSize::XXLarge => medium * 2.0,
|
||||
KeywordSize::XXXLarge => medium * 3.0,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -799,7 +798,6 @@ impl ToComputedValue for KeywordSize {
|
|||
#[inline]
|
||||
fn to_computed_value(&self, cx: &Context) -> NonNegativeLength {
|
||||
use crate::context::QuirksMode;
|
||||
use crate::values::specified::length::au_to_int_px;
|
||||
|
||||
// The tables in this function are originally from
|
||||
// nsRuleNode::CalcFontPointSize in Gecko:
|
||||
|
@ -850,22 +848,21 @@ impl ToComputedValue for KeywordSize {
|
|||
Atom::with(gecko_font.mLanguage.mRawPtr, |atom| {
|
||||
cx.font_metrics_provider
|
||||
.get_size(atom, gecko_font.mGenericID)
|
||||
.0
|
||||
})
|
||||
};
|
||||
|
||||
let base_size_px = au_to_int_px(base_size as f32);
|
||||
let base_size_px = base_size.px().round() as i32;
|
||||
let html_size = self.html_size() as usize;
|
||||
if base_size_px >= 9 && base_size_px <= 16 {
|
||||
NonNegative(if base_size_px >= 9 && base_size_px <= 16 {
|
||||
let mapping = if cx.quirks_mode == QuirksMode::Quirks {
|
||||
QUIRKS_FONT_SIZE_MAPPING
|
||||
} else {
|
||||
FONT_SIZE_MAPPING
|
||||
};
|
||||
Au::from_px(mapping[(base_size_px - 9) as usize][html_size]).into()
|
||||
Length::new(mapping[(base_size_px - 9) as usize][html_size] as f32)
|
||||
} else {
|
||||
Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into()
|
||||
}
|
||||
base_size * FONT_SIZE_FACTORS[html_size] as f32 / 100.0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -927,7 +924,7 @@ impl FontSize {
|
|||
// If the parent font was keyword-derived, this is too.
|
||||
// Tack the % onto the factor
|
||||
info = compose_keyword(pc.0);
|
||||
base_size.resolve(context).scale_by(pc.0).into()
|
||||
base_size.resolve(context) * pc.0
|
||||
},
|
||||
FontSize::Length(LengthPercentage::Calc(ref calc)) => {
|
||||
let parent = context.style().get_parent_font().clone_font_size();
|
||||
|
@ -964,7 +961,7 @@ impl FontSize {
|
|||
// others should reject negatives during parsing. But SMIL
|
||||
// allows parsing negatives, and relies on us _not_ doing that
|
||||
// clamping. That's so bonkers :(
|
||||
CSSPixelLength::from(calc.to_used_value(base_size.resolve(context)))
|
||||
calc.percentage_relative_to(base_size.resolve(context))
|
||||
.clamp_to_non_negative()
|
||||
},
|
||||
FontSize::Keyword(i) => {
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
//! Specified types for legacy Gecko-only properties.
|
||||
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::computed::length::CSSPixelLength;
|
||||
use crate::values::computed::{self, LengthPercentage};
|
||||
use crate::values::computed::{self, Length, LengthPercentage};
|
||||
use crate::values::generics::rect::Rect;
|
||||
use cssparser::{Parser, Token};
|
||||
use std::fmt;
|
||||
|
@ -24,7 +23,7 @@ fn parse_pixel_or_percent<'i, 't>(
|
|||
value, ref unit, ..
|
||||
} => {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)),
|
||||
"px" => Ok(LengthPercentage::new(Length::new(value), None)),
|
||||
_ => Err(()),
|
||||
}
|
||||
},
|
||||
|
|
|
@ -47,14 +47,6 @@ pub const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
|||
/// Number of app units per pica
|
||||
pub const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||
|
||||
/// Same as Gecko's AppUnitsToIntCSSPixels
|
||||
///
|
||||
/// Converts app units to integer pixel values,
|
||||
/// rounding during the conversion
|
||||
pub fn au_to_int_px(au: f32) -> i32 {
|
||||
(au / AU_PER_PX).round() as i32
|
||||
}
|
||||
|
||||
/// A font relative length.
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
|
||||
pub enum FontRelativeLength {
|
||||
|
@ -87,7 +79,7 @@ pub enum FontBaseSize {
|
|||
|
||||
impl FontBaseSize {
|
||||
/// Calculate the actual size for a given context
|
||||
pub fn resolve(&self, context: &Context) -> Au {
|
||||
pub fn resolve(&self, context: &Context) -> computed::Length {
|
||||
match *self {
|
||||
FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().size(),
|
||||
FontBaseSize::InheritedStyleButStripEmUnits | FontBaseSize::InheritedStyle => {
|
||||
|
@ -109,13 +101,13 @@ impl FontRelativeLength {
|
|||
}
|
||||
|
||||
/// Computes the font-relative length.
|
||||
pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> CSSPixelLength {
|
||||
use std::f32;
|
||||
pub fn to_computed_value(
|
||||
&self,
|
||||
context: &Context,
|
||||
base_size: FontBaseSize,
|
||||
) -> computed::Length {
|
||||
let (reference_size, length) = self.reference_font_size_and_length(context, base_size);
|
||||
let pixel = (length * reference_size.to_f32_px())
|
||||
.min(f32::MAX)
|
||||
.max(f32::MIN);
|
||||
CSSPixelLength::new(pixel)
|
||||
reference_size * length
|
||||
}
|
||||
|
||||
/// Return reference font size.
|
||||
|
@ -129,7 +121,7 @@ impl FontRelativeLength {
|
|||
&self,
|
||||
context: &Context,
|
||||
base_size: FontBaseSize,
|
||||
) -> (Au, CSSFloat) {
|
||||
) -> (computed::Length, CSSFloat) {
|
||||
fn query_font_metrics(
|
||||
context: &Context,
|
||||
base_size: FontBaseSize,
|
||||
|
@ -153,7 +145,7 @@ impl FontRelativeLength {
|
|||
}
|
||||
|
||||
if base_size == FontBaseSize::InheritedStyleButStripEmUnits {
|
||||
(Au(0), length)
|
||||
(Zero::zero(), length)
|
||||
} else {
|
||||
(reference_font_size, length)
|
||||
}
|
||||
|
@ -175,7 +167,7 @@ impl FontRelativeLength {
|
|||
// determine the x-height, a value of 0.5em must be
|
||||
// assumed.
|
||||
//
|
||||
reference_font_size.scale_by(0.5)
|
||||
reference_font_size * 0.5
|
||||
});
|
||||
(reference_size, length)
|
||||
},
|
||||
|
@ -210,7 +202,7 @@ impl FontRelativeLength {
|
|||
if wm.is_vertical() && wm.is_upright() {
|
||||
reference_font_size
|
||||
} else {
|
||||
reference_font_size.scale_by(0.5)
|
||||
reference_font_size * 0.5
|
||||
}
|
||||
});
|
||||
(reference_size, length)
|
||||
|
@ -225,7 +217,7 @@ impl FontRelativeLength {
|
|||
let reference_size = if context.is_root_element || context.in_media_query {
|
||||
reference_font_size
|
||||
} else {
|
||||
context.device().root_font_size()
|
||||
computed::Length::new(context.device().root_font_size().to_f32_px())
|
||||
};
|
||||
(reference_size, length)
|
||||
},
|
||||
|
@ -290,15 +282,14 @@ pub struct CharacterWidth(pub i32);
|
|||
|
||||
impl CharacterWidth {
|
||||
/// Computes the given character width.
|
||||
pub fn to_computed_value(&self, reference_font_size: Au) -> CSSPixelLength {
|
||||
// This applies the *converting a character width to pixels* algorithm as specified
|
||||
// in HTML5 § 14.5.4.
|
||||
pub fn to_computed_value(&self, reference_font_size: computed::Length) -> computed::Length {
|
||||
// This applies the *converting a character width to pixels* algorithm
|
||||
// as specified in HTML5 § 14.5.4.
|
||||
//
|
||||
// TODO(pcwalton): Find these from the font.
|
||||
let average_advance = reference_font_size.scale_by(0.5);
|
||||
let average_advance = reference_font_size * 0.5;
|
||||
let max_advance = reference_font_size;
|
||||
let au = average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance;
|
||||
au.into()
|
||||
average_advance * (self.0 as CSSFloat - 1.0) + max_advance
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ pub use self::svg::MozContextProperties;
|
|||
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint};
|
||||
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
|
||||
pub use self::svg_path::SVGPathData;
|
||||
pub use self::text::TextUnderlinePosition;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
|
||||
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
||||
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
||||
|
|
|
@ -77,7 +77,6 @@ impl ToComputedValue for LineHeight {
|
|||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
use crate::values::computed::Length as ComputedLength;
|
||||
use crate::values::specified::length::FontBaseSize;
|
||||
match *self {
|
||||
GenericLineHeight::Normal => GenericLineHeight::Normal,
|
||||
|
@ -97,16 +96,8 @@ impl ToComputedValue for LineHeight {
|
|||
LengthPercentage::Calc(ref calc) => {
|
||||
let computed_calc =
|
||||
calc.to_computed_value_zoomed(context, FontBaseSize::CurrentStyle);
|
||||
let font_relative_length =
|
||||
FontRelativeLength::Em(computed_calc.percentage())
|
||||
.to_computed_value(context, FontBaseSize::CurrentStyle)
|
||||
.px();
|
||||
|
||||
let absolute_length = computed_calc.unclamped_length().px();
|
||||
let pixel = computed_calc
|
||||
.clamping_mode
|
||||
.clamp(absolute_length + font_relative_length);
|
||||
ComputedLength::new(pixel)
|
||||
let base = context.style().get_font().clone_font_size().size();
|
||||
computed_calc.percentage_relative_to(base)
|
||||
},
|
||||
};
|
||||
GenericLineHeight::Length(result.into())
|
||||
|
@ -1054,3 +1045,98 @@ impl TextDecorationLength {
|
|||
matches!(*self, GenericTextDecorationLength::Auto)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||
#[value_info(other_values = "auto,under,left,right")]
|
||||
#[repr(C)]
|
||||
/// Specified keyword values for the text-underline-position property.
|
||||
/// (Non-exclusive, but not all combinations are allowed: only `under` may occur
|
||||
/// together with either `left` or `right`.)
|
||||
/// https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property
|
||||
pub struct TextUnderlinePosition: u8 {
|
||||
/// Use automatic positioning below the alphabetic baseline.
|
||||
const AUTO = 0;
|
||||
/// Below the glyph box.
|
||||
const UNDER = 1 << 0;
|
||||
/// In vertical mode, place to the left of the text.
|
||||
const LEFT = 1 << 1;
|
||||
/// In vertical mode, place to the right of the text.
|
||||
const RIGHT = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for TextUnderlinePosition {
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<TextUnderlinePosition, ParseError<'i>> {
|
||||
let mut result = TextUnderlinePosition::empty();
|
||||
|
||||
loop {
|
||||
let location = input.current_source_location();
|
||||
let ident = match input.next() {
|
||||
Ok(&Token::Ident(ref ident)) => ident,
|
||||
Ok(other) => return Err(location.new_unexpected_token_error(other.clone())),
|
||||
Err(..) => break,
|
||||
};
|
||||
|
||||
match_ignore_ascii_case! { ident,
|
||||
"auto" if result.is_empty() => {
|
||||
return Ok(result);
|
||||
},
|
||||
"under" if !result.intersects(TextUnderlinePosition::UNDER) => {
|
||||
result.insert(TextUnderlinePosition::UNDER);
|
||||
},
|
||||
"left" if !result.intersects(TextUnderlinePosition::LEFT |
|
||||
TextUnderlinePosition::RIGHT) => {
|
||||
result.insert(TextUnderlinePosition::LEFT);
|
||||
},
|
||||
"right" if !result.intersects(TextUnderlinePosition::LEFT |
|
||||
TextUnderlinePosition::RIGHT) => {
|
||||
result.insert(TextUnderlinePosition::RIGHT);
|
||||
},
|
||||
_ => return Err(location.new_custom_error(
|
||||
SelectorParseErrorKind::UnexpectedIdent(ident.clone())
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
if !result.is_empty() {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for TextUnderlinePosition {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return dest.write_str("auto");
|
||||
}
|
||||
|
||||
let mut writer = SequenceWriter::new(dest, " ");
|
||||
let mut any = false;
|
||||
|
||||
macro_rules! maybe_write {
|
||||
($ident:ident => $str:expr) => {
|
||||
if self.contains(TextUnderlinePosition::$ident) {
|
||||
any = true;
|
||||
writer.raw_item($str)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
maybe_write!(UNDER => "under");
|
||||
maybe_write!(LEFT => "left");
|
||||
maybe_write!(RIGHT => "right");
|
||||
|
||||
debug_assert!(any);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,6 @@ gecko = []
|
|||
cssparser = "0.27"
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "2.1.1"
|
||||
smallvec = "0.6.6"
|
||||
smallvec = "1.0"
|
||||
string_cache = { version = "0.8", optional = true }
|
||||
thin-slice = "0.1.0"
|
||||
|
|
|
@ -35,6 +35,12 @@ packages = [
|
|||
# https://github.com/servo/servo/pull/23288#issuecomment-494687746
|
||||
"gl_generator",
|
||||
|
||||
# Just needs a WR update.
|
||||
"derive_more",
|
||||
|
||||
# Lots of crates to update.
|
||||
"smallvec",
|
||||
|
||||
# https://github.com/servo/servo/issues/24421
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[border-shorthand-serialization.html]
|
||||
[Declaration with border longhands and border-image is not serialized to a border shorthand declaration.]
|
||||
expected: FAIL
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue