Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit e4d7dd9

Browse files
author
Mats Palmgren
committed
Bug 1542807 part 3 - Add some style quirks for legacy ::markers created from list-style-type/list-style-image. r=emilio
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
1 parent 19f1737 commit e4d7dd9

12 files changed

Lines changed: 273 additions & 1 deletion

File tree

‎layout/style/res/Mozilla_Bullet.bf‎

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
2+
<font>
3+
<format>2.2</format>
4+
5+
<postscript_name>Mozilla Bullet</postscript_name>
6+
<name>Bullet</name>
7+
<subfamily>Regular</subfamily>
8+
<bold>false</bold>
9+
<italic>false</italic>
10+
<full_name>Mozilla Bullet</full_name>
11+
<unique_identifier>Mozilla Bullet</unique_identifier>
12+
<version>Version 1.0</version>
13+
<description></description>
14+
<copyright></copyright>
15+
<license></license>
16+
<license_url></license_url>
17+
<weight>400</weight>
18+
<units_per_em>1024</units_per_em>
19+
<trademark></trademark>
20+
<manufacturer>Mozilla</manufacturer>
21+
<designer>Mats Palmgren</designer>
22+
<vendor_url></vendor_url>
23+
<designer_url></designer_url>
24+
25+
<horizontal>
26+
<top_limit>84.0000000000</top_limit>
27+
<top_position>66.0000000000</top_position>
28+
<x-height>62.0000000000</x-height>
29+
<base_line>4.0000000000</base_line>
30+
<bottom_position>0.0000000000</bottom_position>
31+
<bottom_limit>0.0000000000</bottom_limit>
32+
<custom_guide label="center">130.5577907913</custom_guide>
33+
<custom_guide label="middle">34.0000000000</custom_guide>
34+
</horizontal>
35+
36+
<grid width="1.0000"/>
37+
<grid width="2.0000"/>
38+
<grid width="4.0000"/>
39+
<grid width="1.0000"/>
40+
<grid width="1.0000"/>
41+
<grid width="2.0000"/>
42+
<grid width="4.0000"/>
43+
<grid width="1.0000"/>
44+
<grid width="2.0000"/>
45+
<grid width="1.0000"/>
46+
<grid width="2.0000"/>
47+
<grid width="4.0000"/>
48+
<grid width="1.0000"/>
49+
<grid width="2.0000"/>
50+
<grid width="4.0000"/>
51+
<grid width="1.0000"/>
52+
<grid width="2.0000"/>
53+
<grid width="4.0000"/>
54+
<grid width="1.0000"/>
55+
<grid width="1.0000"/>
56+
<grid width="2.0000"/>
57+
<grid width="4.0000"/>
58+
<grid width="1.0000"/>
59+
<grid width="2.0000"/>
60+
<grid width="1.0000"/>
61+
<grid width="2.0000"/>
62+
<grid width="4.0000"/>
63+
<grid width="1.0000"/>
64+
<grid width="2.0000"/>
65+
<grid width="4.0000"/>
66+
<background scale="1" />
67+
68+
<collection unicode="U+20">
69+
<selected id="0"/>
70+
<glyph id="0" left="0" right="40">
71+
</glyph>
72+
</collection>
73+
74+
<collection unicode="U+2022">
75+
<selected id="1"/>
76+
<glyph id="1" left="0" right="56.054687999999999">
77+
<layer name= "Layer" visible="true">
78+
<path data="S 39.8340571477,21.8512253642 Q 37.5859284387,19.6030966550 34.3912193480,18.3015483276 Q 31.1965114690,17.0000000000 28.0018023784,17.0000000000 Q 24.8070932877,17.0000000000 21.6123841971,18.3015483276 Q 18.4176751064,19.6030966550 16.1695476089,21.8512253642 Q 13.8030966551,24.0993528616 12.5015483276,27.2940619523 Q 11.2000000000,30.4887710429 11.2000000000,33.6834789219 Q 11.2000000000,36.8781880126 12.5015483276,40.0728971032 Q 13.8030966551,43.2676061939 16.1695476089,45.5157349029 Q 18.4176751064,47.7638624004 21.6123841971,49.1837329728 Q 24.8070932877,50.4852813003 28.0018023784,50.4852813003 Q 31.1965114690,50.4852813003 34.3912193480,49.1837329728 Q 37.5859284387,47.7638624004 39.8340571477,45.5157349029 Q 42.0821846453,43.2676061939 43.3837329728,40.0728971032 Q 44.6852813003,36.8781880126 44.6852813003,33.6834789219 Q 44.6852813003,30.4887710429 43.3837329728,27.2940619523 Q 42.0821846453,24.0993528616 39.8340571477,21.8512253642" />
79+
</layer>
80+
</glyph>
81+
</collection>
82+
83+
<collection unicode="U+25aa">
84+
<selected id="1"/>
85+
<glyph id="1" left="0" right="56.054687999999999">
86+
<layer name= "Layer" visible="true">
87+
<path data="B 12.0000000000,49.8262327578 M 43.9762327578,49.8262327578 M 43.9762327578,17.8500000000 M 12.0000000000,17.8500000000 M 12.0000000000,49.8262327578" />
88+
</layer>
89+
</glyph>
90+
</collection>
91+
92+
<collection unicode="U+25b8">
93+
<selected id="0"/>
94+
<glyph id="0" left="-24" right="24">
95+
<layer name= "Layer" visible="true">
96+
<path data="S -22.3181299324,34.0373543359 L -22.3181299324,57.9301041570 L 25.4673697100,34.0373543359 L -22.3181299324,10.1446045147 L -22.3181299324,34.0373543359" />
97+
</layer>
98+
</glyph>
99+
</collection>
100+
101+
<collection unicode="U+25be">
102+
<selected id="1"/>
103+
<glyph id="0" left="-28" right="28">
104+
<layer name= "Layer" visible="true">
105+
</layer>
106+
</glyph>
107+
<glyph id="1" left="-24" right="24">
108+
<layer name= "Layer" visible="true">
109+
<path data="S -0.0072501788,57.9301041570 L 23.8854996423,57.9301041570 L -0.0072501788,10.1446045146 L -23.9000000000,57.9301041570 L -0.0072501788,57.9301041570" />
110+
</layer>
111+
</glyph>
112+
</collection>
113+
114+
<collection unicode="U+25c2">
115+
<selected id="1"/>
116+
<glyph id="0" left="-28" right="28">
117+
<layer name= "Layer" visible="true">
118+
</layer>
119+
</glyph>
120+
<glyph id="1" left="-24" right="24">
121+
<layer name= "Layer" visible="true">
122+
<path data="S 22.1854996424,34.0373543358 L 22.1854996424,10.1446045147 L -25.6000000000,34.0373543358 L 22.1854996424,57.9301041570 L 22.1854996424,34.0373543358" />
123+
</layer>
124+
</glyph>
125+
</collection>
126+
127+
<collection unicode="U+25e6">
128+
<selected id="0"/>
129+
<glyph id="0" left="0" right="56.054687999999999">
130+
<layer name= "Layer" visible="true">
131+
<path stroke="2.3999999999999999" data="B 40.0833461228,23.2212841662 C 37.0522303130,20.1901683563 32.4889602320,18.3000000000 28.2023151445,18.3000000000 T C 23.9156700571,18.3000000000 19.3523999761,20.1901683563 16.3212841662,23.2212841662 T C 13.2901683563,26.2523999761 11.4000000000,30.8156700570 11.4000000000,35.1023151445 T C 11.4000000000,39.3889602320 13.2901683564,43.9522303130 16.3212841662,46.9833461228 T C 19.3523999761,50.0144619327 23.9156700571,51.9046302890 28.2023151445,51.9046302890 T C 32.4889602320,51.9046302890 37.0522303129,50.0144619326 40.0833461228,46.9833461228 T C 43.1144619327,43.9522303130 45.0046302890,39.3889602320 45.0046302890,35.1023151445 T C 45.0046302890,30.8156700570 43.1144619327,26.2523999760 40.0833461228,23.2212841662 T" />
132+
</layer>
133+
</glyph>
134+
</collection>
135+
136+
137+
138+
139+
</font>

‎layout/style/res/Mozilla_Bullet.ttf‎

Whitespace-only changes.

‎layout/style/res/Mozilla_Bullet.woff2‎

Whitespace-only changes.

‎layout/style/res/html.css‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
66
@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
77

8+
@font-face {
9+
font-family: -moz-bullet-font;
10+
src: url("data:font/woff2;base64,d09GMgABAAAAAARYAAwAAAAACqAAAAQFAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cBmAAgwIRCAqKDIcYATYCJAMsCxgABCAFg2AHIBtDCFGUrM0MyM/DGJyndUclpZwnU8QPQ6wsFOHO+/yHNvV9IEqSQgsVJW2p+uZkohKbVExPEz/JUW7zk6rzYH9723UJ/4DzBII8CSzwgFMOOE4KW2rjAmh4qQWSiid60f7Y9FsXScfUpeluagFqTTQYyoQaQSubXil0lHRsBehAI9KofG/6ogF9/Hl6lBd920LmeTxj8JXBfFWKwYAY3QsAAXD17ZAB4M6Ocv/nsZlkaTl0gLipewIQEMB2d9lKDAT1ZjP/F7jmWsQ3wn8AZvZFgIIC7ESh4AP1iFb4nPnfWyJgcQArpUWqW9W96j71kHr/L9a/dNRbj+8/ujXLWCMMFYVYiXoEaZQ4YOC/E7Dkz3JEjaokxAP6i3hIUjv9fwYyE6I3yIozKkaGN63fP36aeLJmxlRZwZiFziPrMVvOlnCF98SQJfGO/Xllv/FnWAcEjrMqaMCPwVmktCDO5zzxcXqeKS+QFxYnvJLFVzKZAFcKnlZRwHEPVM3mXxNt2gdZEpkKaIAG9gbgDTU5SOYDcmX7Rr61evEA1U+1/3SMb6FFtUqh55nYleE95j2zPNxzdlnGoR5xu/PxQKzb7bFaFLvl79Z54Lx9OH+g0/PPYlcsNo/nwP2V2vsHUHsV4KqEsd+e2r6Fu2v7abkfvsb65b41uwvRvqewH25kTntqolbYsEr5DAqrX97a0jrBLjFRExVHR2dH1Za6unyZfCVZHqQP0BtYjuUYlg9J6SurcrTEiOr26m5xcuTW4Sp3ljkUYWJ9+/iVmzbzPpcuXnGeqU3U7IKjz/qeKSSCltyhuSoxkqqTZX+DXt/OMmAikC8SzVD0jg3dbhIE0eUqc04UFFrxCSXzFxgHclzRMPe0ocOjiKRoSZISE0OtpkBjECdxkkRM1KiaJV0ed0V5umBP1wyUPL2ZBGLSDh5itIHahHRF0CY5nZMGib6T3cOmDvcTSZKuPiFJFpPRGNTIOq7jl5OjDiGIoo6qEE0QtfQJ3VYUD2RZvbm5uWWCWOgR4HXAk5GxLEO0izhLdvPTfpTV3xeOnOfT96uR53CdPrPq+P9HZvzO4QCMmDr7lTcNZorT6iMOYgI+IxClMzeCspeoLt5ABGSpta6gRZmQSnzk9e9jmOAYKC7RsyGMYaB6MpbNKMiRq2U6vI0yPZuTMiODFytMrGEBi7pjGgkAMoaNLGOFSoYceaZMx1+XTC/UNpmRzY1nmwT7AIcK+fK5lYNjz893lwMTuXlD2AKl8Md+24AxitRaLH/MUMqd9z862owy/bZTuZUqs1iRQop0KdLgZwPc9JS0lprnkef1gitBCRhjgV+vjGK8BfIV8CrlVghj1vIyZfyC/AJvqbsQYAEA/v+IAQA=");
11+
}
12+
813
/* bidi */
914

1015
:-moz-has-dir-attr {

‎servo/components/style/properties/cascade.rs‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,34 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
794794
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING);
795795
}
796796

797+
if self
798+
.author_specified
799+
.contains(LonghandId::FontFamily)
800+
{
801+
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY);
802+
}
803+
804+
if self
805+
.author_specified
806+
.contains(LonghandId::LetterSpacing)
807+
{
808+
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING);
809+
}
810+
811+
if self
812+
.author_specified
813+
.contains(LonghandId::WordSpacing)
814+
{
815+
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING);
816+
}
817+
818+
if self
819+
.author_specified
820+
.contains(LonghandId::FontSynthesis)
821+
{
822+
builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS);
823+
}
824+
797825
#[cfg(feature = "servo")]
798826
{
799827
if let Some(font) = builder.get_font_if_mutated() {

‎servo/components/style/properties/computed_value_flags.rs‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ bitflags! {
1212
/// If we ever want to add some flags that shouldn't inherit for them,
1313
/// we might want to add a function to handle this.
1414
#[repr(C)]
15-
pub struct ComputedValueFlags: u16 {
15+
pub struct ComputedValueFlags: u32 {
1616
/// Whether the style or any of the ancestors has a text-decoration-line
1717
/// property that should get propagated to descendants.
1818
///
@@ -89,6 +89,18 @@ bitflags! {
8989
/// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see
9090
/// https://github.com/w3c/csswg-drafts/issues/4777
9191
const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 15;
92+
93+
/// Whether there are author-specified rules for `font-family`.
94+
const HAS_AUTHOR_SPECIFIED_FONT_FAMILY = 1 << 16;
95+
96+
/// Whether there are author-specified rules for `font-synthesis`.
97+
const HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS = 1 << 17;
98+
99+
/// Whether there are author-specified rules for `letter-spacing`.
100+
const HAS_AUTHOR_SPECIFIED_LETTER_SPACING = 1 << 18;
101+
102+
/// Whether there are author-specified rules for `word-spacing`.
103+
const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19;
92104
}
93105
}
94106

‎servo/components/style/style_adjuster.rs‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,52 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
817817
}
818818
}
819819

820+
/// A legacy ::marker (i.e. no 'content') without an author-specified 'font-family'
821+
/// and 'list-style-type:disc|circle|square|disclosure-closed|disclosure-open'
822+
/// is assigned 'font-family:-moz-bullet-font'. (This is for <ul><li> etc.)
823+
/// We don't want synthesized italic/bold for this font, so turn that off too.
824+
/// Likewise for 'letter/word-spacing' -- unless the author specified it then reset
825+
/// them to their initial value because traditionally we never added such spacing
826+
/// between a legacy bullet and the list item's content, so we keep that behavior
827+
/// for web-compat reasons.
828+
/// We intentionally don't check 'list-style-image' below since we want it to use
829+
/// the same font as its fallback ('list-style-type') in case it fails to load.
830+
#[cfg(feature = "gecko")]
831+
fn adjust_for_marker_pseudo(&mut self) {
832+
use crate::values::computed::font::{FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSynthesis, SingleFontFamily};
833+
use crate::values::computed::text::{LetterSpacing, WordSpacing};
834+
835+
let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) &&
836+
self.style.get_counters().ineffective_content_property() &&
837+
self.style.get_list().clone_list_style_type().is_bullet();
838+
if !is_legacy_marker {
839+
return;
840+
}
841+
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) {
842+
let moz_bullet_font_family = FontFamily {
843+
families: FontFamilyList::new(Box::new([SingleFontFamily::FamilyName(FamilyName {
844+
name: atom!("-moz-bullet-font"),
845+
syntax: FontFamilyNameSyntax::Identifiers,
846+
})])),
847+
is_system_font: false,
848+
};
849+
self.style.mutate_font().set_font_family(moz_bullet_font_family);
850+
851+
// FIXME(mats): We can remove this if support for font-synthesis is added to @font-face rules.
852+
// Then we can add it to the @font-face rule in html.css instead.
853+
// https://github.com/w3c/csswg-drafts/issues/6081
854+
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS) {
855+
self.style.mutate_font().set_font_synthesis(FontSynthesis::none());
856+
}
857+
}
858+
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING) {
859+
self.style.mutate_inherited_text().set_letter_spacing(LetterSpacing::normal());
860+
}
861+
if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING) {
862+
self.style.mutate_inherited_text().set_word_spacing(WordSpacing::normal());
863+
}
864+
}
865+
820866
/// Adjusts the style to account for various fixups that don't fit naturally
821867
/// into the cascade.
822868
///
@@ -882,6 +928,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
882928
{
883929
self.adjust_for_appearance(element);
884930
self.adjust_for_inert();
931+
self.adjust_for_marker_pseudo();
885932
}
886933
self.set_bits();
887934
}

‎servo/components/style/values/computed/text.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ impl ToComputedValue for specified::WordSpacing {
110110
/// A computed value for the `line-height` property.
111111
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
112112

113+
impl WordSpacing {
114+
/// Return the `normal` computed value, which is just zero.
115+
#[inline]
116+
pub fn normal() -> Self {
117+
LengthPercentage::zero()
118+
}
119+
}
120+
113121
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
114122
#[repr(C)]
115123
/// text-overflow.

‎servo/components/style/values/generics/mod.rs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ impl CounterStyle {
9595
pub fn decimal() -> Self {
9696
CounterStyle::Name(CustomIdent(atom!("decimal")))
9797
}
98+
99+
/// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`)
100+
#[inline]
101+
pub fn is_bullet(&self) -> bool {
102+
match self {
103+
CounterStyle::Name(CustomIdent(ref name)) => {
104+
name == &atom!("disc") ||
105+
name == &atom!("circle") ||
106+
name == &atom!("square") ||
107+
name == &atom!("disclosure-closed") ||
108+
name == &atom!("disclosure-open")
109+
}
110+
_ => false,
111+
}
112+
}
98113
}
99114

100115
impl Parse for CounterStyle {

‎servo/components/style/values/specified/font.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,14 @@ impl FontSynthesis {
19721972
style: true,
19731973
}
19741974
}
1975+
#[inline]
1976+
/// Get the 'none' value of font-synthesis
1977+
pub fn none() -> Self {
1978+
FontSynthesis {
1979+
weight: false,
1980+
style: false,
1981+
}
1982+
}
19751983
}
19761984

19771985
impl Parse for FontSynthesis {

0 commit comments

Comments
 (0)