mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Add some style quirks for legacy ::markers created from list-style-type/list-style-image
Specifically: For "bullets", i.e. 'list-style-type:disc|circle|square| disclosure-closed|disclosure-open', we use a built-in font (-moz-bullet-font, which has glyphs for those symbols + space) to retain mostly backwards compatible rendering for those. Authors may override that with an explicit 'font-family' ::marker style though. We also use this font for 'list-style-image' in case it would fallback to one of the above when the image fails to load (so that we get the same width space). When the -moz-bullet-font is used we also set 'font-synthesis' to avoid synthesizing italic/bold for this font. Authors may override this with an explicit ::marker declaration. We also set 'letter-spacing' and 'word-spacing' to the initial value for bullets for web-compat reasons. Again, authors may override this with an explicit ::marker declaration. (This breaks backwards- compat slightly but makes us compatible with Chrome. We used to ignore these for list-style-type:<string> too.) Differential Revision: https://phabricator.services.mozilla.com/D111693
This commit is contained in:
parent
d2a7ebf789
commit
d7e00ba03d
7 changed files with 128 additions and 1 deletions
|
@ -786,6 +786,34 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
|
||||||
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING);
|
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self
|
||||||
|
.author_specified
|
||||||
|
.contains(LonghandId::FontFamily)
|
||||||
|
{
|
||||||
|
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self
|
||||||
|
.author_specified
|
||||||
|
.contains(LonghandId::LetterSpacing)
|
||||||
|
{
|
||||||
|
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self
|
||||||
|
.author_specified
|
||||||
|
.contains(LonghandId::WordSpacing)
|
||||||
|
{
|
||||||
|
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self
|
||||||
|
.author_specified
|
||||||
|
.contains(LonghandId::FontSynthesis)
|
||||||
|
{
|
||||||
|
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
{
|
{
|
||||||
if let Some(font) = builder.get_font_if_mutated() {
|
if let Some(font) = builder.get_font_if_mutated() {
|
||||||
|
|
|
@ -12,7 +12,7 @@ bitflags! {
|
||||||
/// If we ever want to add some flags that shouldn't inherit for them,
|
/// If we ever want to add some flags that shouldn't inherit for them,
|
||||||
/// we might want to add a function to handle this.
|
/// we might want to add a function to handle this.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct ComputedValueFlags: u16 {
|
pub struct ComputedValueFlags: u32 {
|
||||||
/// Whether the style or any of the ancestors has a text-decoration-line
|
/// Whether the style or any of the ancestors has a text-decoration-line
|
||||||
/// property that should get propagated to descendants.
|
/// property that should get propagated to descendants.
|
||||||
///
|
///
|
||||||
|
@ -89,6 +89,18 @@ bitflags! {
|
||||||
/// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see
|
/// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see
|
||||||
/// https://github.com/w3c/csswg-drafts/issues/4777
|
/// https://github.com/w3c/csswg-drafts/issues/4777
|
||||||
const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 15;
|
const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 15;
|
||||||
|
|
||||||
|
/// Whether there are author-specified rules for `font-family`.
|
||||||
|
const HAS_AUTHOR_SPECIFIED_FONT_FAMILY = 1 << 16;
|
||||||
|
|
||||||
|
/// Whether there are author-specified rules for `font-synthesis`.
|
||||||
|
const HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS = 1 << 17;
|
||||||
|
|
||||||
|
/// Whether there are author-specified rules for `letter-spacing`.
|
||||||
|
const HAS_AUTHOR_SPECIFIED_LETTER_SPACING = 1 << 18;
|
||||||
|
|
||||||
|
/// Whether there are author-specified rules for `word-spacing`.
|
||||||
|
const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -818,6 +818,52 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A legacy ::marker (i.e. no 'content') without an author-specified 'font-family'
|
||||||
|
/// and 'list-style-type:disc|circle|square|disclosure-closed|disclosure-open'
|
||||||
|
/// is assigned 'font-family:-moz-bullet-font'. (This is for <ul><li> etc.)
|
||||||
|
/// We don't want synthesized italic/bold for this font, so turn that off too.
|
||||||
|
/// Likewise for 'letter/word-spacing' -- unless the author specified it then reset
|
||||||
|
/// them to their initial value because traditionally we never added such spacing
|
||||||
|
/// between a legacy bullet and the list item's content, so we keep that behavior
|
||||||
|
/// for web-compat reasons.
|
||||||
|
/// We intentionally don't check 'list-style-image' below since we want it to use
|
||||||
|
/// the same font as its fallback ('list-style-type') in case it fails to load.
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn adjust_for_marker_pseudo(&mut self) {
|
||||||
|
use crate::values::computed::font::{FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSynthesis, SingleFontFamily};
|
||||||
|
use crate::values::computed::text::{LetterSpacing, WordSpacing};
|
||||||
|
|
||||||
|
let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) &&
|
||||||
|
self.style.get_counters().ineffective_content_property() &&
|
||||||
|
self.style.get_list().clone_list_style_type().is_bullet();
|
||||||
|
if !is_legacy_marker {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) {
|
||||||
|
let moz_bullet_font_family = FontFamily {
|
||||||
|
families: FontFamilyList::new(Box::new([SingleFontFamily::FamilyName(FamilyName {
|
||||||
|
name: atom!("-moz-bullet-font"),
|
||||||
|
syntax: FontFamilyNameSyntax::Identifiers,
|
||||||
|
})])),
|
||||||
|
is_system_font: false,
|
||||||
|
};
|
||||||
|
self.style.mutate_font().set_font_family(moz_bullet_font_family);
|
||||||
|
|
||||||
|
// FIXME(mats): We can remove this if support for font-synthesis is added to @font-face rules.
|
||||||
|
// Then we can add it to the @font-face rule in html.css instead.
|
||||||
|
// https://github.com/w3c/csswg-drafts/issues/6081
|
||||||
|
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS) {
|
||||||
|
self.style.mutate_font().set_font_synthesis(FontSynthesis::none());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING) {
|
||||||
|
self.style.mutate_inherited_text().set_letter_spacing(LetterSpacing::normal());
|
||||||
|
}
|
||||||
|
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING) {
|
||||||
|
self.style.mutate_inherited_text().set_word_spacing(WordSpacing::normal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Adjusts the style to account for various fixups that don't fit naturally
|
/// Adjusts the style to account for various fixups that don't fit naturally
|
||||||
/// into the cascade.
|
/// into the cascade.
|
||||||
///
|
///
|
||||||
|
@ -883,6 +929,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
{
|
{
|
||||||
self.adjust_for_appearance(element);
|
self.adjust_for_appearance(element);
|
||||||
self.adjust_for_inert();
|
self.adjust_for_inert();
|
||||||
|
self.adjust_for_marker_pseudo();
|
||||||
}
|
}
|
||||||
self.set_bits();
|
self.set_bits();
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,14 @@ impl ToComputedValue for specified::WordSpacing {
|
||||||
/// A computed value for the `line-height` property.
|
/// A computed value for the `line-height` property.
|
||||||
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
|
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
|
||||||
|
|
||||||
|
impl WordSpacing {
|
||||||
|
/// Return the `normal` computed value, which is just zero.
|
||||||
|
#[inline]
|
||||||
|
pub fn normal() -> Self {
|
||||||
|
LengthPercentage::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
/// text-overflow.
|
/// text-overflow.
|
||||||
|
|
|
@ -95,6 +95,21 @@ impl CounterStyle {
|
||||||
pub fn decimal() -> Self {
|
pub fn decimal() -> Self {
|
||||||
CounterStyle::Name(CustomIdent(atom!("decimal")))
|
CounterStyle::Name(CustomIdent(atom!("decimal")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
|
||||||
|
#[inline]
|
||||||
|
pub fn is_bullet(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CounterStyle::Name(CustomIdent(ref name)) => {
|
||||||
|
name == &atom!("disc") ||
|
||||||
|
name == &atom!("circle") ||
|
||||||
|
name == &atom!("square") ||
|
||||||
|
name == &atom!("disclosure-closed") ||
|
||||||
|
name == &atom!("disclosure-open")
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CounterStyle {
|
impl Parse for CounterStyle {
|
||||||
|
|
|
@ -2005,6 +2005,14 @@ impl FontSynthesis {
|
||||||
style: true,
|
style: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
/// Get the 'none' value of font-synthesis
|
||||||
|
pub fn none() -> Self {
|
||||||
|
FontSynthesis {
|
||||||
|
weight: false,
|
||||||
|
style: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for FontSynthesis {
|
impl Parse for FontSynthesis {
|
||||||
|
|
|
@ -67,6 +67,15 @@ impl ListStyleType {
|
||||||
_ => unreachable!("Unknown counter style keyword value"),
|
_ => unreachable!("Unknown counter style keyword value"),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
|
||||||
|
#[inline]
|
||||||
|
pub fn is_bullet(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
ListStyleType::CounterStyle(ref style) => style.is_bullet(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue