mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
style: Do not snap -webkit-text-stroke-width to dev pixels
Introduce LineWidth (which doesn't snap) and let BorderSideWidth wrap it and actually do the snapping. Differential Revision: https://phabricator.services.mozilla.com/D180688
This commit is contained in:
parent
127e00e48a
commit
77c541b38a
8 changed files with 108 additions and 56 deletions
|
@ -44,7 +44,7 @@ ${helpers.predefined_type(
|
||||||
"BorderSideWidth",
|
"BorderSideWidth",
|
||||||
"app_units::Au::from_px(3)",
|
"app_units::Au::from_px(3)",
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
initial_specified_value="specified::BorderSideWidth::Medium",
|
initial_specified_value="specified::BorderSideWidth::medium()",
|
||||||
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
|
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
|
||||||
animation_value_type="NonNegativeLength",
|
animation_value_type="NonNegativeLength",
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -283,10 +283,10 @@ ${helpers.predefined_type(
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"-webkit-text-stroke-width",
|
"-webkit-text-stroke-width",
|
||||||
"BorderSideWidth",
|
"LineWidth",
|
||||||
"app_units::Au(0)",
|
"app_units::Au(0)",
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
initial_specified_value="specified::BorderSideWidth::zero()",
|
initial_specified_value="specified::LineWidth::zero()",
|
||||||
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
|
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -36,7 +36,7 @@ ${helpers.predefined_type(
|
||||||
"BorderSideWidth",
|
"BorderSideWidth",
|
||||||
"app_units::Au::from_px(3)",
|
"app_units::Au::from_px(3)",
|
||||||
engines="gecko servo",
|
engines="gecko servo",
|
||||||
initial_specified_value="specified::BorderSideWidth::Medium",
|
initial_specified_value="specified::BorderSideWidth::medium()",
|
||||||
animation_value_type="NonNegativeLength",
|
animation_value_type="NonNegativeLength",
|
||||||
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width",
|
spec="https://drafts.csswg.org/css-ui/#propdef-outline-width",
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub fn parse_border<'i, 't>(
|
||||||
if !any {
|
if !any {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
}
|
}
|
||||||
Ok((color.unwrap_or(Color::CurrentColor), style.unwrap_or(BorderStyle::None), width.unwrap_or(BorderSideWidth::Medium)))
|
Ok((color.unwrap_or(Color::CurrentColor), style.unwrap_or(BorderStyle::None), width.unwrap_or(BorderSideWidth::medium())))
|
||||||
}
|
}
|
||||||
|
|
||||||
% for side, logical in ALL_SIDES:
|
% for side, logical in ALL_SIDES:
|
||||||
|
|
|
@ -19,6 +19,9 @@ use app_units::Au;
|
||||||
|
|
||||||
pub use crate::values::specified::border::BorderImageRepeat;
|
pub use crate::values::specified::border::BorderImageRepeat;
|
||||||
|
|
||||||
|
/// A computed value for -webkit-text-stroke-width.
|
||||||
|
pub type LineWidth = Au;
|
||||||
|
|
||||||
/// A computed value for border-width (and the like).
|
/// A computed value for border-width (and the like).
|
||||||
pub type BorderSideWidth = Au;
|
pub type BorderSideWidth = Au;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||||
pub use self::basic_shape::FillRule;
|
pub use self::basic_shape::FillRule;
|
||||||
pub use self::border::{
|
pub use self::border::{
|
||||||
BorderCornerRadius, BorderImageRepeat, BorderImageSideWidth, BorderImageSlice,
|
BorderCornerRadius, BorderImageRepeat, BorderImageSideWidth, BorderImageSlice,
|
||||||
BorderImageWidth, BorderRadius, BorderSideWidth, BorderSpacing,
|
BorderImageWidth, BorderRadius, BorderSideWidth, BorderSpacing, LineWidth,
|
||||||
};
|
};
|
||||||
pub use self::box_::{
|
pub use self::box_::{
|
||||||
Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain, ContainIntrinsicSize,
|
Appearance, BaselineSource, BreakBetween, BreakWithin, Clear, Contain, ContainIntrinsicSize,
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
//! Specified types for CSS values related to borders.
|
//! Specified types for CSS values related to borders.
|
||||||
|
|
||||||
use app_units::Au;
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
use crate::values::computed::{Context, ToComputedValue};
|
use crate::values::computed::{Context, ToComputedValue};
|
||||||
use crate::values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
use crate::values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
|
||||||
|
@ -14,10 +13,11 @@ use crate::values::generics::border::BorderRadius as GenericBorderRadius;
|
||||||
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
|
||||||
use crate::values::generics::rect::Rect;
|
use crate::values::generics::rect::Rect;
|
||||||
use crate::values::generics::size::Size2D;
|
use crate::values::generics::size::Size2D;
|
||||||
use crate::values::specified::length::{NonNegativeLength, NonNegativeLengthPercentage};
|
use crate::values::specified::length::{Length, NonNegativeLength, NonNegativeLengthPercentage};
|
||||||
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
use crate::values::specified::{AllowQuirks, NonNegativeNumber, NonNegativeNumberOrPercentage};
|
||||||
use crate::values::specified::Color;
|
use crate::values::specified::Color;
|
||||||
use crate::Zero;
|
use crate::Zero;
|
||||||
|
use app_units::Au;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, ToCss, values::SequenceWriter};
|
use style_traits::{CssWriter, ParseError, ToCss, values::SequenceWriter};
|
||||||
|
@ -67,19 +67,6 @@ impl BorderStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A specified value for a single side of the `border-width` property.
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
|
||||||
pub enum BorderSideWidth {
|
|
||||||
/// `thin`
|
|
||||||
Thin,
|
|
||||||
/// `medium`
|
|
||||||
Medium,
|
|
||||||
/// `thick`
|
|
||||||
Thick,
|
|
||||||
/// `<length>`
|
|
||||||
Length(NonNegativeLength),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A specified value for the `border-image-width` property.
|
/// A specified value for the `border-image-width` property.
|
||||||
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
|
pub type BorderImageWidth = Rect<BorderImageSideWidth>;
|
||||||
|
|
||||||
|
@ -110,11 +97,87 @@ impl BorderImageSlice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorderSideWidth {
|
/// https://drafts.csswg.org/css-backgrounds-3/#typedef-line-width
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||||
|
pub enum LineWidth {
|
||||||
|
/// `thin`
|
||||||
|
Thin,
|
||||||
|
/// `medium`
|
||||||
|
Medium,
|
||||||
|
/// `thick`
|
||||||
|
Thick,
|
||||||
|
/// `<length>`
|
||||||
|
Length(NonNegativeLength),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineWidth {
|
||||||
/// Returns the `0px` value.
|
/// Returns the `0px` value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
BorderSideWidth::Length(NonNegativeLength::zero())
|
Self::Length(NonNegativeLength::zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_quirky<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
allow_quirks: AllowQuirks,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
if let Ok(length) =
|
||||||
|
input.try_parse(|i| NonNegativeLength::parse_quirky(context, i, allow_quirks))
|
||||||
|
{
|
||||||
|
return Ok(Self::Length(length));
|
||||||
|
}
|
||||||
|
Ok(try_match_ident_ignore_ascii_case! { input,
|
||||||
|
"thin" => Self::Thin,
|
||||||
|
"medium" => Self::Medium,
|
||||||
|
"thick" => Self::Thick,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for LineWidth {
|
||||||
|
fn parse<'i>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, '_>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for LineWidth {
|
||||||
|
type ComputedValue = app_units::Au;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
|
match *self {
|
||||||
|
// https://drafts.csswg.org/css-backgrounds-3/#line-width
|
||||||
|
Self::Thin => Au::from_px(1),
|
||||||
|
Self::Medium => Au::from_px(3),
|
||||||
|
Self::Thick => Au::from_px(5),
|
||||||
|
Self::Length(ref length) => Au::from_f32_px(length.to_computed_value(context).px()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
|
Self::Length(NonNegativeLength::from_px(computed.to_f32_px()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A specified value for a single side of the `border-width` property. The difference between this
|
||||||
|
/// and LineWidth is whether we snap to device pixels or not.
|
||||||
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||||
|
pub struct BorderSideWidth(LineWidth);
|
||||||
|
|
||||||
|
impl BorderSideWidth {
|
||||||
|
/// Returns the `medium` value.
|
||||||
|
pub fn medium() -> Self {
|
||||||
|
Self(LineWidth::Medium)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a bare px value from the argument.
|
||||||
|
pub fn from_px(px: f32) -> Self {
|
||||||
|
Self(LineWidth::Length(Length::from_px(px).into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses, with quirks.
|
/// Parses, with quirks.
|
||||||
|
@ -123,23 +186,14 @@ impl BorderSideWidth {
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
allow_quirks: AllowQuirks,
|
allow_quirks: AllowQuirks,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
if let Ok(length) =
|
Ok(Self(LineWidth::parse_quirky(context, input, allow_quirks)?))
|
||||||
input.try_parse(|i| NonNegativeLength::parse_quirky(context, i, allow_quirks))
|
|
||||||
{
|
|
||||||
return Ok(BorderSideWidth::Length(length));
|
|
||||||
}
|
|
||||||
try_match_ident_ignore_ascii_case! { input,
|
|
||||||
"thin" => Ok(BorderSideWidth::Thin),
|
|
||||||
"medium" => Ok(BorderSideWidth::Medium),
|
|
||||||
"thick" => Ok(BorderSideWidth::Thick),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BorderSideWidth {
|
impl Parse for BorderSideWidth {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, '_>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
Self::parse_quirky(context, input, AllowQuirks::No)
|
Self::parse_quirky(context, input, AllowQuirks::No)
|
||||||
}
|
}
|
||||||
|
@ -150,14 +204,7 @@ impl ToComputedValue for BorderSideWidth {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||||
let width = match *self {
|
let width = self.0.to_computed_value(context);
|
||||||
// https://drafts.csswg.org/css-backgrounds-3/#line-width
|
|
||||||
BorderSideWidth::Thin => Au::from_px(1),
|
|
||||||
BorderSideWidth::Medium => Au::from_px(3),
|
|
||||||
BorderSideWidth::Thick => Au::from_px(5),
|
|
||||||
BorderSideWidth::Length(ref length) => Au::from_f32_px(length.to_computed_value(context).px()),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Round `width` down to the nearest device pixel, but any non-zero value that would round
|
// Round `width` down to the nearest device pixel, but any non-zero value that would round
|
||||||
// down to zero is clamped to 1 device pixel.
|
// down to zero is clamped to 1 device pixel.
|
||||||
if width == Au(0) {
|
if width == Au(0) {
|
||||||
|
@ -165,12 +212,15 @@ impl ToComputedValue for BorderSideWidth {
|
||||||
}
|
}
|
||||||
|
|
||||||
let au_per_dev_px = context.device().app_units_per_device_pixel();
|
let au_per_dev_px = context.device().app_units_per_device_pixel();
|
||||||
std::cmp::max(Au(au_per_dev_px), Au(width.0 / au_per_dev_px * au_per_dev_px))
|
std::cmp::max(
|
||||||
|
Au(au_per_dev_px),
|
||||||
|
Au(width.0 / au_per_dev_px * au_per_dev_px),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
BorderSideWidth::Length(NonNegativeLength::from_px(computed.to_f32_px()))
|
Self(LineWidth::from_computed_value(computed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,17 @@ pub use self::animation::{AnimationIterationCount, AnimationName, AnimationTimel
|
||||||
pub use self::animation::{ScrollAxis, ScrollTimelineName, TransitionProperty, ViewTimelineInset};
|
pub use self::animation::{ScrollAxis, ScrollTimelineName, TransitionProperty, ViewTimelineInset};
|
||||||
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||||
pub use self::basic_shape::FillRule;
|
pub use self::basic_shape::FillRule;
|
||||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
pub use self::border::{
|
||||||
pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
|
BorderCornerRadius, BorderImageRepeat, BorderImageSideWidth, BorderImageSlice,
|
||||||
pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle};
|
BorderImageWidth, BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle, LineWidth,
|
||||||
pub use self::box_::{Appearance, BreakBetween, BreakWithin, ContainerName, ContainerType};
|
};
|
||||||
pub use self::box_::{BaselineSource, TouchAction, VerticalAlign, WillChange};
|
pub use self::box_::{
|
||||||
pub use self::box_::{
|
Appearance, BreakBetween, BaselineSource, BreakWithin, Contain, ContainerName, ContainerType,
|
||||||
Clear, ContainIntrinsicSize, ContentVisibility, Float, LineClamp, Overflow, OverflowAnchor,
|
Clear, ContainIntrinsicSize, ContentVisibility, Display, Float, LineClamp, Overflow,
|
||||||
|
OverflowAnchor, OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter,
|
||||||
|
ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, ScrollSnapType,
|
||||||
|
TouchAction, VerticalAlign, WillChange,
|
||||||
};
|
};
|
||||||
pub use self::box_::{Contain, Display};
|
|
||||||
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter};
|
|
||||||
pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop};
|
|
||||||
pub use self::box_::{ScrollSnapStrictness, ScrollSnapType};
|
|
||||||
pub use self::color::{
|
pub use self::color::{
|
||||||
Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust,
|
Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue