mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1898887. Implement parsing of CSS 'inset-area' property. r=emilio,firefox-style-system-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D211955
This commit is contained in:
parent
d4a8bd78d9
commit
745b6de9a7
@ -98,6 +98,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"ime-mode",
|
||||
"-moz-inert",
|
||||
"initial-letter",
|
||||
"inset-area",
|
||||
"isolation",
|
||||
"justify-content",
|
||||
"justify-items",
|
||||
|
@ -107,7 +107,7 @@ use.counter:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 2329 use counter metrics (excludes denominators).
|
||||
# Total of 2343 use counter metrics (excludes denominators).
|
||||
# Total of 364 'page' use counters.
|
||||
use.counter.page:
|
||||
svgsvgelement_getelementbyid:
|
||||
@ -14177,7 +14177,7 @@ use.counter.worker.service:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 50 'deprecated operations (page)' use counters.
|
||||
# Total of 56 'deprecated operations (page)' use counters.
|
||||
use.counter.deprecated_ops.page:
|
||||
domsubtree_modified:
|
||||
type: counter
|
||||
@ -15131,7 +15131,7 @@ use.counter.deprecated_ops.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 50 'deprecated operations (document)' use counters.
|
||||
# Total of 56 'deprecated operations (document)' use counters.
|
||||
use.counter.deprecated_ops.doc:
|
||||
domsubtree_modified:
|
||||
type: counter
|
||||
@ -16085,7 +16085,7 @@ use.counter.deprecated_ops.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 701 'CSS (page)' use counters.
|
||||
# Total of 702 'CSS (page)' use counters.
|
||||
use.counter.css.page:
|
||||
css_align_content:
|
||||
type: counter
|
||||
@ -16903,6 +16903,23 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_inset_area:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page used the CSS property inset-area.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_isolation:
|
||||
type: counter
|
||||
description: >
|
||||
@ -28004,7 +28021,7 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 701 'CSS (document)' use counters.
|
||||
# Total of 702 'CSS (document)' use counters.
|
||||
use.counter.css.doc:
|
||||
css_align_content:
|
||||
type: counter
|
||||
@ -28822,6 +28839,23 @@ use.counter.css.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_inset_area:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document used the CSS property inset-area.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_isolation:
|
||||
type: counter
|
||||
description: >
|
||||
@ -39922,4 +39956,3 @@ use.counter.css.doc:
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
|
@ -627,6 +627,7 @@ cbindgen-types = [
|
||||
{ gecko = "StyleAnchorScope", servo = "crate::values::computed::position::AnchorScope" },
|
||||
{ gecko = "StylePositionAnchor", servo = "crate::values::computed::position::PositionAnchor" },
|
||||
{ gecko = "StylePositionVisibility", servo = "crate::values::computed::position::PositionVisibility" },
|
||||
{ gecko = "StyleInsetArea", servo = "crate::values::computed::position::InsetArea" },
|
||||
{ gecko = "StyleFontVariantEastAsian", servo = "crate::values::computed::font::FontVariantEastAsian" },
|
||||
{ gecko = "StyleFontVariantLigatures", servo = "crate::values::computed::font::FontVariantLigatures" },
|
||||
{ gecko = "StyleFontVariantNumeric", servo = "crate::values::computed::font::FontVariantNumeric" },
|
||||
|
@ -1051,6 +1051,8 @@ nsStylePosition::nsStylePosition()
|
||||
mMaxHeight(StyleMaxSize::None()),
|
||||
mPositionAnchor(StylePositionAnchor::Auto()),
|
||||
mPositionVisibility(StylePositionVisibility::ALWAYS),
|
||||
mInsetArea(StyleInsetArea{StyleInsetAreaKeyword::None,
|
||||
StyleInsetAreaKeyword::None}),
|
||||
mFlexBasis(StyleFlexBasis::Size(StyleSize::Auto())),
|
||||
mAspectRatio(StyleAspectRatio::Auto()),
|
||||
mGridAutoFlow(StyleGridAutoFlow::ROW),
|
||||
@ -1101,6 +1103,7 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
|
||||
mMaxHeight(aSource.mMaxHeight),
|
||||
mPositionAnchor(aSource.mPositionAnchor),
|
||||
mPositionVisibility(aSource.mPositionVisibility),
|
||||
mInsetArea(aSource.mInsetArea),
|
||||
mFlexBasis(aSource.mFlexBasis),
|
||||
mGridAutoColumns(aSource.mGridAutoColumns),
|
||||
mGridAutoRows(aSource.mGridAutoRows),
|
||||
@ -1285,7 +1288,8 @@ nsChangeHint nsStylePosition::CalcDifference(
|
||||
hint |= nsChangeHint_NeutralChange;
|
||||
}
|
||||
|
||||
if (mPositionVisibility != aNewData.mPositionVisibility) {
|
||||
if (mPositionVisibility != aNewData.mPositionVisibility ||
|
||||
mInsetArea != aNewData.mInsetArea) {
|
||||
hint |= nsChangeHint_NeutralChange;
|
||||
}
|
||||
|
||||
|
@ -747,6 +747,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition {
|
||||
// element.
|
||||
mozilla::StylePositionAnchor mPositionAnchor;
|
||||
mozilla::StylePositionVisibility mPositionVisibility;
|
||||
mozilla::StyleInsetArea mInsetArea;
|
||||
|
||||
mozilla::StyleFlexBasis mFlexBasis;
|
||||
StyleImplicitGridTracks mGridAutoColumns;
|
||||
|
@ -13338,6 +13338,85 @@ if (IsCSSPropertyPrefEnabled("layout.css.anchor-positioning.enabled")) {
|
||||
],
|
||||
};
|
||||
|
||||
gCSSProperties["inset-area"] = {
|
||||
domProp: "insetArea",
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: ["none"],
|
||||
other_values: [
|
||||
"center",
|
||||
"span-all",
|
||||
"left",
|
||||
"right",
|
||||
"span-left",
|
||||
"span-right",
|
||||
"x-start",
|
||||
"x-end",
|
||||
"span-x-start",
|
||||
"span-x-end",
|
||||
"x-self-start",
|
||||
"x-self-end",
|
||||
"span-x-self-start",
|
||||
"span-x-self-end",
|
||||
"top",
|
||||
"bottom",
|
||||
"span-top",
|
||||
"span-bottom",
|
||||
"y-start",
|
||||
"y-end",
|
||||
"span-y-start",
|
||||
"span-y-end",
|
||||
"y-self-start",
|
||||
"y-self-end",
|
||||
"span-y-self-start",
|
||||
"span-y-self-end",
|
||||
"block-start",
|
||||
"block-end",
|
||||
"span-block-start",
|
||||
"span-block-end",
|
||||
"inline-start",
|
||||
"inline-end",
|
||||
"span-inline-start",
|
||||
"span-inline-end",
|
||||
"self-block-start",
|
||||
"self-block-end",
|
||||
"span-self-block-start",
|
||||
"span-self-block-end",
|
||||
"self-inline-start",
|
||||
"self-inline-end",
|
||||
"span-self-inline-start",
|
||||
"span-self-inline-end",
|
||||
"start",
|
||||
"end",
|
||||
"span-start",
|
||||
"span-end",
|
||||
"self-start",
|
||||
"self-end",
|
||||
"span-self-start",
|
||||
"span-self-end",
|
||||
"center span-all",
|
||||
"left center",
|
||||
"span-left bottom",
|
||||
"span-block-end inline-start",
|
||||
"span-inline-start block-end",
|
||||
"self-block-end span-self-inline-start",
|
||||
"start center",
|
||||
"span-start span-end",
|
||||
"self-end span-self-start",
|
||||
],
|
||||
invalid_values: [
|
||||
"auto",
|
||||
"none left",
|
||||
"left self-top",
|
||||
"right block-end",
|
||||
"top self-end",
|
||||
"y-self-end x-end",
|
||||
"inline-start self-block-end",
|
||||
"span-self-inline-start start",
|
||||
"end span-self-start",
|
||||
],
|
||||
};
|
||||
|
||||
gCSSProperties["position-anchor"] = {
|
||||
domProp: "positionAnchor",
|
||||
inherited: false,
|
||||
|
@ -566,6 +566,8 @@ class Longhand(Property):
|
||||
"ImageRendering",
|
||||
"InitialLetter",
|
||||
"Integer",
|
||||
"InsetArea",
|
||||
"InsetAreaKeyword",
|
||||
"JustifyContent",
|
||||
"JustifyItems",
|
||||
"JustifySelf",
|
||||
|
@ -354,6 +354,18 @@ ${helpers.predefined_type(
|
||||
affects="layout",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"inset-area",
|
||||
"InsetArea",
|
||||
"computed::InsetArea::none()",
|
||||
engines="gecko",
|
||||
initial_specified_value="specified::InsetArea::none()",
|
||||
animation_value_type="discrete",
|
||||
gecko_pref="layout.css.anchor-positioning.enabled",
|
||||
spec="https://drafts.csswg.org/css-anchor-position-1/#typedef-inset-area",
|
||||
affects="layout",
|
||||
)}
|
||||
|
||||
${helpers.single_keyword(
|
||||
"box-sizing",
|
||||
"content-box border-box",
|
||||
|
@ -92,6 +92,7 @@ pub use self::position::AnchorName;
|
||||
pub use self::position::AnchorScope;
|
||||
pub use self::position::PositionAnchor;
|
||||
pub use self::position::PositionVisibility;
|
||||
pub use self::position::{InsetArea, InsetAreaKeyword};
|
||||
pub use self::position::AspectRatio;
|
||||
pub use self::position::{
|
||||
GridAutoFlow, GridTemplateAreas, MasonryAutoFlow, Position, PositionOrAuto, ZIndex,
|
||||
|
@ -14,7 +14,7 @@ use crate::values::generics::position::PositionComponent as GenericPositionCompo
|
||||
use crate::values::generics::position::PositionOrAuto as GenericPositionOrAuto;
|
||||
use crate::values::generics::position::ZIndex as GenericZIndex;
|
||||
pub use crate::values::specified::position::{GridAutoFlow, GridTemplateAreas, MasonryAutoFlow};
|
||||
pub use crate::values::specified::position::{AnchorName, AnchorScope, PositionAnchor, PositionVisibility};
|
||||
pub use crate::values::specified::position::{AnchorName, AnchorScope, InsetArea, InsetAreaKeyword, PositionAnchor, PositionVisibility};
|
||||
use crate::Zero;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
@ -83,6 +83,7 @@ pub use self::percentage::{NonNegativePercentage, Percentage};
|
||||
pub use self::position::AspectRatio;
|
||||
pub use self::position::AnchorName;
|
||||
pub use self::position::AnchorScope;
|
||||
pub use self::position::{InsetArea, InsetAreaKeyword};
|
||||
pub use self::position::PositionAnchor;
|
||||
pub use self::position::PositionVisibility;
|
||||
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto};
|
||||
|
@ -535,6 +535,345 @@ impl PositionVisibility {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
Parse,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[allow(missing_docs)]
|
||||
#[repr(u8)]
|
||||
/// Possible values for the `inset-area` preperty's keywords.
|
||||
/// https://drafts.csswg.org/css-anchor-position-1/#propdef-inset-area
|
||||
pub enum InsetAreaKeyword {
|
||||
None,
|
||||
|
||||
// Common (shared) keywords:
|
||||
Center,
|
||||
SpanAll,
|
||||
|
||||
// Horizontal keywords:
|
||||
Left,
|
||||
Right,
|
||||
SpanLeft,
|
||||
SpanRight,
|
||||
XStart,
|
||||
XEnd,
|
||||
SpanXStart,
|
||||
SpanXEnd,
|
||||
XSelfStart,
|
||||
XSelfEnd,
|
||||
SpanXSelfStart,
|
||||
SpanXSelfEnd,
|
||||
// Vertical keywords:
|
||||
Top,
|
||||
Bottom,
|
||||
SpanTop,
|
||||
SpanBottom,
|
||||
YStart,
|
||||
YEnd,
|
||||
SpanYStart,
|
||||
SpanYEnd,
|
||||
YSelfStart,
|
||||
YSelfEnd,
|
||||
SpanYSelfStart,
|
||||
SpanYSelfEnd,
|
||||
|
||||
// Block keywords:
|
||||
BlockStart,
|
||||
BlockEnd,
|
||||
SpanBlockStart,
|
||||
SpanBlockEnd,
|
||||
// Inline keywords:
|
||||
InlineStart,
|
||||
InlineEnd,
|
||||
SpanInlineStart,
|
||||
SpanInlineEnd,
|
||||
|
||||
// "Self" block keywords:
|
||||
SelfBlockStart,
|
||||
SelfBlockEnd,
|
||||
SpanSelfBlockStart,
|
||||
SpanSelfBlockEnd,
|
||||
// "Self" inline keywords:
|
||||
SelfInlineStart,
|
||||
SelfInlineEnd,
|
||||
SpanSelfInlineStart,
|
||||
SpanSelfInlineEnd,
|
||||
|
||||
// Inferred axis keywords:
|
||||
Start,
|
||||
End,
|
||||
SpanStart,
|
||||
SpanEnd,
|
||||
|
||||
// "Self" inferred axis keywords:
|
||||
SelfStart,
|
||||
SelfEnd,
|
||||
SpanSelfStart,
|
||||
SpanSelfEnd,
|
||||
}
|
||||
|
||||
impl Default for InsetAreaKeyword {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl InsetAreaKeyword {
|
||||
#[inline]
|
||||
pub fn none() -> Self {
|
||||
Self::None
|
||||
}
|
||||
|
||||
pub fn is_none(&self) -> bool {
|
||||
*self == Self::None
|
||||
}
|
||||
|
||||
/// Is a value that's common to all compatible keyword groupings.
|
||||
pub fn is_common(&self) -> bool {
|
||||
*self == Self::Center || *self == Self::SpanAll
|
||||
}
|
||||
|
||||
pub fn is_horizontal(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Left |
|
||||
Self::Right |
|
||||
Self::SpanLeft |
|
||||
Self::SpanRight |
|
||||
Self::XStart |
|
||||
Self::XEnd |
|
||||
Self::SpanXStart |
|
||||
Self::SpanXEnd |
|
||||
Self::XSelfStart |
|
||||
Self::XSelfEnd |
|
||||
Self::SpanXSelfStart |
|
||||
Self::SpanXSelfEnd
|
||||
)
|
||||
}
|
||||
pub fn is_vertical(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Top |
|
||||
Self::Bottom |
|
||||
Self::SpanTop |
|
||||
Self::SpanBottom |
|
||||
Self::YStart |
|
||||
Self::YEnd |
|
||||
Self::SpanYStart |
|
||||
Self::SpanYEnd |
|
||||
Self::YSelfStart |
|
||||
Self::YSelfEnd |
|
||||
Self::SpanYSelfStart |
|
||||
Self::SpanYSelfEnd
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_block(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::BlockStart | Self::BlockEnd | Self::SpanBlockStart | Self::SpanBlockEnd
|
||||
)
|
||||
}
|
||||
pub fn is_inline(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::InlineStart | Self::InlineEnd | Self::SpanInlineStart | Self::SpanInlineEnd
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_self_block(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::SelfBlockStart |
|
||||
Self::SelfBlockEnd |
|
||||
Self::SpanSelfBlockStart |
|
||||
Self::SpanSelfBlockEnd
|
||||
)
|
||||
}
|
||||
pub fn is_self_inline(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::SelfInlineStart |
|
||||
Self::SelfInlineEnd |
|
||||
Self::SpanSelfInlineStart |
|
||||
Self::SpanSelfInlineEnd
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_inferred_logical(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Start | Self::End | Self::SpanStart | Self::SpanEnd
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_self_inferred_logical(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::SelfStart | Self::SelfEnd | Self::SpanSelfStart | Self::SpanSelfEnd
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_compatible_pairing(first: InsetAreaKeyword, second: InsetAreaKeyword) -> bool {
|
||||
if first.is_none() || second.is_none() {
|
||||
// `none` is not allowed as one of the keywords when two keywords are
|
||||
// provided.
|
||||
return false;
|
||||
}
|
||||
if first.is_common() || second.is_common() {
|
||||
return true;
|
||||
}
|
||||
if first.is_horizontal() {
|
||||
return second.is_vertical();
|
||||
}
|
||||
if first.is_vertical() {
|
||||
return second.is_horizontal();
|
||||
}
|
||||
if first.is_block() {
|
||||
return second.is_inline();
|
||||
}
|
||||
if first.is_inline() {
|
||||
return second.is_block();
|
||||
}
|
||||
if first.is_self_block() {
|
||||
return second.is_self_inline();
|
||||
}
|
||||
if first.is_self_inline() {
|
||||
return second.is_self_block();
|
||||
}
|
||||
if first.is_inferred_logical() {
|
||||
return second.is_inferred_logical();
|
||||
}
|
||||
if first.is_self_inferred_logical() {
|
||||
return second.is_self_inferred_logical();
|
||||
}
|
||||
|
||||
debug_assert!(false, "Not reached");
|
||||
|
||||
// Return false to increase the chances of this being reported to us if we
|
||||
// ever were to get here.
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(C)]
|
||||
/// https://drafts.csswg.org/css-anchor-position-1/#propdef-inset-area
|
||||
pub struct InsetArea {
|
||||
/// First keyword, if any.
|
||||
pub first: InsetAreaKeyword,
|
||||
/// Second keyword, if any.
|
||||
#[css(skip_if = "InsetAreaKeyword::is_none")]
|
||||
pub second: InsetAreaKeyword,
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
impl InsetArea {
|
||||
#[inline]
|
||||
pub fn none() -> Self {
|
||||
Self {
|
||||
first: InsetAreaKeyword::None,
|
||||
second: InsetAreaKeyword::None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_none(&self) -> bool {
|
||||
self.first.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for InsetArea {
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let mut first = InsetAreaKeyword::parse(input)?;
|
||||
if first.is_none() {
|
||||
return Ok(Self::none());
|
||||
}
|
||||
|
||||
let location = input.current_source_location();
|
||||
let second = input.try_parse(InsetAreaKeyword::parse);
|
||||
if let Ok(InsetAreaKeyword::None) = second {
|
||||
// `none` is only allowed as a single value
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
let mut second = second.unwrap_or(InsetAreaKeyword::None);
|
||||
if second.is_none() {
|
||||
// Either there was no second keyword and try_parse returned a
|
||||
// BasicParseErrorKind::EndOfInput, or else the second "keyword"
|
||||
// was invalid. We assume the former case here, and if it's the
|
||||
// latter case then our caller detects the error (try_parse will,
|
||||
// have rewound, leaving an unparsed token).
|
||||
return Ok(Self { first, second });
|
||||
}
|
||||
|
||||
if !is_compatible_pairing(first, second) {
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
|
||||
// Normalize by applying the shortest serialization principle:
|
||||
// https://drafts.csswg.org/cssom/#serializing-css-values
|
||||
if first.is_inferred_logical() ||
|
||||
second.is_inferred_logical() ||
|
||||
first.is_self_inferred_logical() ||
|
||||
second.is_self_inferred_logical() ||
|
||||
(first.is_common() && second.is_common())
|
||||
{
|
||||
// In these cases we must not change the order of the keywords
|
||||
// since their meaning is inferred from their order. However, if
|
||||
// both keywords are the same, only one should be set.
|
||||
if first == second {
|
||||
second = InsetAreaKeyword::None;
|
||||
}
|
||||
} else if second == InsetAreaKeyword::SpanAll {
|
||||
// Span-all is the default behavior, so specifying `span-all` is
|
||||
// superfluous.
|
||||
second = InsetAreaKeyword::None;
|
||||
} else if first == InsetAreaKeyword::SpanAll {
|
||||
// Same here, but the non-superfluous keyword must come first.
|
||||
first = second;
|
||||
second = InsetAreaKeyword::None;
|
||||
} else if first.is_vertical() ||
|
||||
second.is_horizontal() ||
|
||||
first.is_inline() ||
|
||||
second.is_block() ||
|
||||
first.is_self_inline() ||
|
||||
second.is_self_block()
|
||||
{
|
||||
// Canonical order is horizontal before vertical, block before inline.
|
||||
std::mem::swap(&mut first, &mut second);
|
||||
}
|
||||
|
||||
Ok(Self { first, second })
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a side, either horizontal or vertical, of a CSS position.
|
||||
pub trait Side {
|
||||
/// Returns the start side.
|
||||
|
@ -105,6 +105,8 @@ include = [
|
||||
"FontVariantEastAsian",
|
||||
"FontVariantLigatures",
|
||||
"FontVariantNumeric",
|
||||
"InsetArea",
|
||||
"InsetAreaKeyword",
|
||||
"ComputedFontStretchRange",
|
||||
"ComputedFontStyleDescriptor",
|
||||
"ComputedFontWeightRange",
|
||||
|
Loading…
Reference in New Issue
Block a user