mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
servo: Merge #15533 - Stylo: Implement align-content and justify-content (from mbrubeck:align); r=Manishearth
This implements parsing and serialization of `align-content` and `justify-content` for Stylo. The implementation should match Gecko exactly (which means it's not exactly up-to-date with the latest draft spec). This is a Stylo-only change; it leaves the current Servo code (which matches an older spec) unchanged for now. r? @Manishearth - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix part of #15001 (github issue number if applicable). - [x] These changes do not require tests because they are stylo-only Source-Repo: https://github.com/servo/servo Source-Revision: 3b72a1f6d2b6b9676682e8fcabbcf66032531eac --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 16fb2db93df696e71f297149a17dc5390bcc3514
This commit is contained in:
parent
67516483ed
commit
370aca412d
@ -867,8 +867,8 @@ fn static_assert() {
|
||||
|
||||
<% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %>
|
||||
<%self:impl_trait style_struct_name="Position"
|
||||
skip_longhands="${skip_position_longhands} z-index box-sizing order">
|
||||
|
||||
skip_longhands="${skip_position_longhands} z-index box-sizing order align-content
|
||||
justify-content">
|
||||
% for side in SIDES:
|
||||
<% impl_split_style_coord("%s" % side.ident,
|
||||
"mOffset",
|
||||
@ -906,6 +906,18 @@ fn static_assert() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_align_content(&mut self, v: longhands::align_content::computed_value::T) {
|
||||
self.gecko.mAlignContent = v.bits()
|
||||
}
|
||||
|
||||
${impl_simple_copy('align_content', 'mAlignContent')}
|
||||
|
||||
pub fn set_justify_content(&mut self, v: longhands::justify_content::computed_value::T) {
|
||||
self.gecko.mJustifyContent = v.bits()
|
||||
}
|
||||
|
||||
${impl_simple_copy('justify_content', 'mJustifyContent')}
|
||||
|
||||
pub fn set_box_sizing(&mut self, v: longhands::box_sizing::computed_value::T) {
|
||||
use computed_values::box_sizing::T;
|
||||
use gecko_bindings::structs::StyleBoxSizing;
|
||||
|
@ -84,14 +84,20 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#flex-wrap-property",
|
||||
extra_prefixes="webkit", animatable=False)}
|
||||
|
||||
// FIXME(stshine): The type of 'justify-content' and 'align-content' is uint16_t in gecko
|
||||
// FIXME(stshine): Its higher bytes are used to store fallback value. Disable them in geckolib for now
|
||||
${helpers.single_keyword("justify-content", "flex-start flex-end center space-between space-around",
|
||||
gecko_constant_prefix="NS_STYLE_JUSTIFY",
|
||||
products="servo",
|
||||
extra_prefixes="webkit",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#justify-content-property",
|
||||
animatable=False)}
|
||||
% if product == "servo":
|
||||
// FIXME: Update Servo to support the same Syntax as Gecko.
|
||||
${helpers.single_keyword("justify-content", "stretch flex-start flex-end center space-between space-around",
|
||||
extra_prefixes="webkit",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#justify-content-property",
|
||||
animatable=False)}
|
||||
% else:
|
||||
${helpers.predefined_type(name="justify-content",
|
||||
type="AlignJustifyContent",
|
||||
initial_value="specified::AlignJustifyContent::auto()",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#justify-content-property",
|
||||
extra_prefixes="webkit",
|
||||
animatable=False)}
|
||||
% endif
|
||||
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-align-items
|
||||
// FIXME: This is a workaround for 'normal' value. We don't support the Gecko initial value 'normal' yet.
|
||||
@ -103,12 +109,20 @@ ${helpers.single_keyword("align-items", "stretch flex-start flex-end center base
|
||||
spec="https://drafts.csswg.org/css-flexbox/#align-items-property",
|
||||
animatable=False)}
|
||||
|
||||
${helpers.single_keyword("align-content", "stretch flex-start flex-end center space-between space-around",
|
||||
gecko_constant_prefix="NS_STYLE_ALIGN",
|
||||
products="servo",
|
||||
extra_prefixes="webkit",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#align-content-property",
|
||||
animatable=False)}
|
||||
% if product == "servo":
|
||||
// FIXME: Update Servo to support the same Syntax as Gecko.
|
||||
${helpers.single_keyword("align-content", "stretch flex-start flex-end center space-between space-around",
|
||||
extra_prefixes="webkit",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#align-content-property",
|
||||
animatable=False)}
|
||||
% else:
|
||||
${helpers.predefined_type(name="align-content",
|
||||
type="AlignJustifyContent",
|
||||
initial_value="specified::AlignJustifyContent::auto()",
|
||||
spec="https://drafts.csswg.org/css-flexbox/#align-content-property",
|
||||
extra_prefixes="webkit",
|
||||
animatable=False)}
|
||||
% endif
|
||||
|
||||
// Flex item properties
|
||||
${helpers.predefined_type("flex-grow", "Number",
|
||||
|
@ -16,6 +16,8 @@ pub use cssparser::Color as CSSColor;
|
||||
pub use self::image::{AngleOrCorner, EndingShape as GradientShape, Gradient, GradientKind, Image};
|
||||
pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||
pub use super::{Auto, Either, None_};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use super::specified::AlignJustifyContent;
|
||||
pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone};
|
||||
pub use super::specified::url::UrlExtraData;
|
||||
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
@ -120,6 +122,8 @@ impl ToComputedValue for specified::CSSColor {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ComputedValueAsSpecified for specified::AlignJustifyContent {}
|
||||
impl ComputedValueAsSpecified for specified::BorderStyle {}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
|
266
servo/components/style/values/specified/align.rs
Normal file
266
servo/components/style/values/specified/align.rs
Normal file
@ -0,0 +1,266 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Values for CSS Box Alignment properties
|
||||
//!
|
||||
//! https://drafts.csswg.org/css-align/
|
||||
|
||||
use cssparser::Parser;
|
||||
use gecko_bindings::structs;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::HasViewportPercentage;
|
||||
|
||||
bitflags! {
|
||||
/// Constants shared by multiple CSS Box Alignment properties
|
||||
///
|
||||
/// These constants match Gecko's `NS_STYLE_ALIGN_*` constants.
|
||||
pub flags AlignFlags: u8 {
|
||||
// Enumeration stored in the lower 5 bits:
|
||||
/// 'auto'
|
||||
const ALIGN_AUTO = structs::NS_STYLE_ALIGN_AUTO as u8,
|
||||
/// 'normal'
|
||||
const ALIGN_NORMAL = structs::NS_STYLE_ALIGN_NORMAL as u8,
|
||||
/// 'start'
|
||||
const ALIGN_START = structs::NS_STYLE_ALIGN_START as u8,
|
||||
/// 'end'
|
||||
const ALIGN_END = structs::NS_STYLE_ALIGN_END as u8,
|
||||
/// 'flex-start'
|
||||
const ALIGN_FLEX_START = structs::NS_STYLE_ALIGN_FLEX_START as u8,
|
||||
/// 'flex-end'
|
||||
const ALIGN_FLEX_END = structs::NS_STYLE_ALIGN_FLEX_END as u8,
|
||||
/// 'center'
|
||||
const ALIGN_CENTER = structs::NS_STYLE_ALIGN_CENTER as u8,
|
||||
/// 'left'
|
||||
const ALIGN_LEFT = structs::NS_STYLE_ALIGN_LEFT as u8,
|
||||
/// 'left'
|
||||
const ALIGN_RIGHT = structs::NS_STYLE_ALIGN_RIGHT as u8,
|
||||
/// 'right'
|
||||
const ALIGN_BASELINE = structs::NS_STYLE_ALIGN_BASELINE as u8,
|
||||
/// 'baseline'
|
||||
const ALIGN_LAST_BASELINE = structs::NS_STYLE_ALIGN_LAST_BASELINE as u8,
|
||||
/// 'stretch'
|
||||
const ALIGN_STRETCH = structs::NS_STYLE_ALIGN_STRETCH as u8,
|
||||
/// 'self-start'
|
||||
const ALIGN_SELF_START = structs::NS_STYLE_ALIGN_SELF_START as u8,
|
||||
/// 'self-end'
|
||||
const ALIGN_SELF_END = structs::NS_STYLE_ALIGN_SELF_END as u8,
|
||||
/// 'space-between'
|
||||
const ALIGN_SPACE_BETWEEN = structs::NS_STYLE_ALIGN_SPACE_BETWEEN as u8,
|
||||
/// 'space-around'
|
||||
const ALIGN_SPACE_AROUND = structs::NS_STYLE_ALIGN_SPACE_AROUND as u8,
|
||||
/// 'space-evenly'
|
||||
const ALIGN_SPACE_EVENLY = structs::NS_STYLE_ALIGN_SPACE_EVENLY as u8,
|
||||
|
||||
// Additional flags stored in the upper bits:
|
||||
/// 'legacy' (mutually exclusive w. SAFE & UNSAFE)
|
||||
const ALIGN_LEGACY = structs::NS_STYLE_ALIGN_LEGACY as u8,
|
||||
/// 'safe'
|
||||
const ALIGN_SAFE = structs::NS_STYLE_ALIGN_SAFE as u8,
|
||||
/// 'unsafe' (mutually exclusive w. SAFE)
|
||||
const ALIGN_UNSAFE = structs::NS_STYLE_ALIGN_UNSAFE as u8,
|
||||
|
||||
/// Mask for the additional flags above.
|
||||
const ALIGN_FLAG_BITS = structs::NS_STYLE_ALIGN_FLAG_BITS as u8,
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for AlignFlags {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
let s = match *self & !ALIGN_FLAG_BITS {
|
||||
ALIGN_AUTO => "auto",
|
||||
ALIGN_NORMAL => "normal",
|
||||
ALIGN_START => "start",
|
||||
ALIGN_END => "end",
|
||||
ALIGN_FLEX_START => "flex-start",
|
||||
ALIGN_FLEX_END => "flex-end",
|
||||
ALIGN_CENTER => "center",
|
||||
ALIGN_LEFT => "left",
|
||||
ALIGN_RIGHT => "left",
|
||||
ALIGN_BASELINE => "right",
|
||||
ALIGN_LAST_BASELINE => "baseline",
|
||||
ALIGN_STRETCH => "stretch",
|
||||
ALIGN_SELF_START => "self-start",
|
||||
ALIGN_SELF_END => "self-end",
|
||||
ALIGN_SPACE_BETWEEN => "space-between",
|
||||
ALIGN_SPACE_AROUND => "space-around",
|
||||
ALIGN_SPACE_EVENLY => "space-evenly",
|
||||
_ => unreachable!()
|
||||
};
|
||||
dest.write_str(s)?;
|
||||
|
||||
match *self & ALIGN_FLAG_BITS {
|
||||
ALIGN_LEGACY => { dest.write_str(" legacy")?; }
|
||||
ALIGN_SAFE => { dest.write_str(" safe")?; }
|
||||
ALIGN_UNSAFE => { dest.write_str(" unsafe")?; }
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Mask for a single AlignFlags value.
|
||||
const ALIGN_ALL_BITS: u16 = structs::NS_STYLE_ALIGN_ALL_BITS as u16;
|
||||
/// Number of bits to shift a fallback alignment.
|
||||
const ALIGN_ALL_SHIFT: u32 = structs::NS_STYLE_ALIGN_ALL_SHIFT;
|
||||
|
||||
/// Value of the `align-content` or `justify-content` property.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-align/#content-distribution
|
||||
///
|
||||
/// The 16-bit field stores the primary value in its lower 8 bits, and the optional fallback value
|
||||
/// in its upper 8 bits. This matches the representation of these properties in Gecko.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
||||
pub struct AlignJustifyContent(u16);
|
||||
|
||||
impl AlignJustifyContent {
|
||||
/// The initial value 'auto'
|
||||
#[inline]
|
||||
pub fn auto() -> Self {
|
||||
Self::new(ALIGN_AUTO)
|
||||
}
|
||||
|
||||
/// Construct a value with no fallback.
|
||||
#[inline]
|
||||
pub fn new(flags: AlignFlags) -> Self {
|
||||
AlignJustifyContent(flags.bits() as u16)
|
||||
}
|
||||
|
||||
/// Construct a value including a fallback alignment.
|
||||
///
|
||||
/// https://drafts.csswg.org/css-align/#fallback-alignment
|
||||
#[inline]
|
||||
pub fn with_fallback(flags: AlignFlags, fallback: AlignFlags) -> Self {
|
||||
AlignJustifyContent(flags.bits() as u16 | ((fallback.bits() as u16) << ALIGN_ALL_SHIFT))
|
||||
}
|
||||
|
||||
/// The combined 16-bit flags, for copying into a Gecko style struct.
|
||||
#[inline]
|
||||
pub fn bits(self) -> u16 { self.0 }
|
||||
|
||||
/// The primary alignment
|
||||
#[inline]
|
||||
pub fn primary(self) -> AlignFlags {
|
||||
AlignFlags::from_bits((self.0 & ALIGN_ALL_BITS) as u8)
|
||||
.expect("AlignJustifyContent must contain valid flags")
|
||||
}
|
||||
|
||||
/// The fallback alignment
|
||||
#[inline]
|
||||
pub fn fallback(self) -> AlignFlags {
|
||||
AlignFlags::from_bits((self.0 >> ALIGN_ALL_SHIFT) as u8)
|
||||
.expect("AlignJustifyContent must contain valid flags")
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for AlignJustifyContent {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
self.primary().to_css(dest)?;
|
||||
match self.fallback() {
|
||||
ALIGN_AUTO => {}
|
||||
fallback => {
|
||||
dest.write_str(" ")?;
|
||||
fallback.to_css(dest)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
no_viewport_percentage!(AlignJustifyContent);
|
||||
|
||||
impl Parse for AlignJustifyContent {
|
||||
// normal | <baseline-position> |
|
||||
// [ <content-distribution> || [ <overflow-position>? && <content-position> ] ]
|
||||
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
// normal | <baseline-position>
|
||||
if let Ok(value) = input.try(|input| parse_normal_or_baseline(input)) {
|
||||
return Ok(AlignJustifyContent::new(value))
|
||||
}
|
||||
|
||||
// <content-distribution> followed by optional <*-position>
|
||||
if let Ok(value) = input.try(|input| parse_content_distribution(input)) {
|
||||
if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input)) {
|
||||
return Ok(AlignJustifyContent::with_fallback(value, fallback))
|
||||
}
|
||||
return Ok(AlignJustifyContent::new(value))
|
||||
}
|
||||
|
||||
// <*-position> followed by optional <content-distribution>
|
||||
if let Ok(fallback) = input.try(|input| parse_overflow_content_position(input)) {
|
||||
if let Ok(value) = input.try(|input| parse_content_distribution(input)) {
|
||||
return Ok(AlignJustifyContent::with_fallback(value, fallback))
|
||||
}
|
||||
return Ok(AlignJustifyContent::new(fallback))
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// normal | <baseline-position>
|
||||
fn parse_normal_or_baseline(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { ident,
|
||||
"normal" => Ok(ALIGN_NORMAL),
|
||||
"baseline" => Ok(ALIGN_BASELINE),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// <content-distribution>
|
||||
fn parse_content_distribution(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { ident,
|
||||
"stretch" => Ok(ALIGN_STRETCH),
|
||||
"space_between" => Ok(ALIGN_SPACE_BETWEEN),
|
||||
"space_around" => Ok(ALIGN_SPACE_AROUND),
|
||||
"space_evenly" => Ok(ALIGN_SPACE_EVENLY),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// [ <overflow-position>? && <content-position> ]
|
||||
fn parse_overflow_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
// <content-position> followed by optional <overflow-position>
|
||||
if let Ok(mut content) = input.try(|input| parse_content_position(input)) {
|
||||
if let Ok(overflow) = input.try(|input| parse_overflow_position(input)) {
|
||||
content |= overflow;
|
||||
}
|
||||
return Ok(content)
|
||||
}
|
||||
// <overflow-position> followed by required <content-position>
|
||||
if let Ok(overflow) = input.try(|input| parse_overflow_position(input)) {
|
||||
if let Ok(content) = input.try(|input| parse_content_position(input)) {
|
||||
return Ok(overflow | content)
|
||||
}
|
||||
}
|
||||
return Err(())
|
||||
}
|
||||
|
||||
// <content-position>
|
||||
fn parse_content_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { ident,
|
||||
"start" => Ok(ALIGN_START),
|
||||
"end" => Ok(ALIGN_END),
|
||||
"flex-start" => Ok(ALIGN_FLEX_START),
|
||||
"flex-end" => Ok(ALIGN_FLEX_END),
|
||||
"center" => Ok(ALIGN_CENTER),
|
||||
"left" => Ok(ALIGN_LEFT),
|
||||
"right" => Ok(ALIGN_RIGHT),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
// <overflow-position>
|
||||
fn parse_overflow_position(input: &mut Parser) -> Result<AlignFlags, ()> {
|
||||
let ident = input.expect_ident()?;
|
||||
match_ignore_ascii_case! { ident,
|
||||
"safe" => Ok(ALIGN_SAFE),
|
||||
"unsafe" => Ok(ALIGN_UNSAFE),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
@ -20,6 +20,8 @@ use super::{Auto, CSSFloat, HasViewportPercentage, Either, None_};
|
||||
use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
|
||||
use super::computed::Shadow as ComputedShadow;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::align::AlignJustifyContent;
|
||||
pub use self::grid::GridLine;
|
||||
pub use self::image::{AngleOrCorner, ColorStop, EndingShape as GradientEndingShape, Gradient};
|
||||
pub use self::image::{GradientKind, HorizontalDirection, Image, LengthOrKeyword, LengthOrPercentageOrKeyword};
|
||||
@ -29,6 +31,8 @@ pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercent
|
||||
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength, CalcUnit};
|
||||
pub use self::position::{HorizontalPosition, Position, VerticalPosition};
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
pub mod align;
|
||||
pub mod basic_shape;
|
||||
pub mod grid;
|
||||
pub mod image;
|
||||
|
Loading…
Reference in New Issue
Block a user