Closed Bug 1384398 Opened 7 years ago Closed 7 years ago

stylo: serialization of font-family doesn't match Gecko

Categories

(Core :: CSS Parsing and Computation, defect, P2)

defect

Tracking

()

RESOLVED FIXED
mozilla57
Tracking Status
firefox-esr52 --- unaffected
firefox55 --- wontfix
firefox56 --- wontfix
firefox57 --- fixed

People

(Reporter: heycam, Assigned: heycam)

References

Details

Attachments

(2 files, 1 obsolete file)

It looks like there are a couple of differences in how font-family values are serialized. Compare the attached test with stylo enabled and disabled: 1. Stylo serializes the space separated font names as a single identifier with backslashed-escaped spaces, but Gecko serializes them as three separate identifiers. 2. Stylo puts a space after the comma, and Gecko doesn't. (Stylo's behaviour seems preferable.) 3. If you open devtools, the two `:root { font-family: ... }` rules are displayed differently. In the style sheet without the following @supports rule, backslashes are not displayed, and in the style sheet with the following @supports rule, backslashes are displayed. That's pretty weird.
Did you meant to attach a test case?
Flags: needinfo?(cam)
Attached file test
Flags: needinfo?(cam)
(In reply to Cameron McCormack (:heycam) from comment #0) > 2. Stylo puts a space after the comma, and Gecko doesn't. (Stylo's > behaviour seems preferable.) Space after comma is speced, if I'm not mistaken. https://drafts.csswg.org/cssom/#serialize-a-string
(In reply to Cameron McCormack (:heycam) from comment #0) > 3. If you open devtools, the two `:root { font-family: ... }` rules are > displayed differently. In the style sheet without the following @supports > rule, backslashes are not displayed, and in the style sheet with the > following @supports rule, backslashes are displayed. That's pretty weird. I can't reproduce this one any more.
(In reply to Cameron McCormack (:heycam) from comment #0) > 1. Stylo serializes the space separated font names as a single identifier > with backslashed-escaped spaces, but Gecko serializes them as three separate > identifiers. For this I think the issue is that Servo's FamilyName type cannot distinguish between a sequence of identifiers (each of which individually must be escaped individually) and a single identifier.
(In reply to Cameron McCormack (:heycam) from comment #0) > 2. Stylo puts a space after the comma, and Gecko doesn't. (Stylo's > behaviour seems preferable.) This is a regression from bug 280443.
Assignee: nobody → cam
Status: NEW → ASSIGNED
Comment on attachment 8891724 [details] Bug 1384398 - style: Preserve font-family identifier sequence when serializing. https://reviewboard.mozilla.org/r/162786/#review168124 ::: servo/components/style/properties/gecko.mako.rs:1825 (Diff revision 1) > FontFamilyType::eFamily_moz_fixed => FontFamily::Generic(Atom::from("-moz-fixed")), > - FontFamilyType::eFamily_named => FontFamily::FamilyName(FamilyName { > - name: (&*gecko_font_family_name.mName).into(), > - quoted: false > - }), > + FontFamilyType::eFamily_named => { > + let name = Atom::from(&*gecko_font_family_name.mName); > + FontFamily::FamilyName(FamilyName { > + name: name.clone(), > + syntax: FamilyNameSyntax::Identifiers(vec![name]), hmm... So I don't really think this is correct... Why is it? Couldn't it be a sequence of identifiers? ::: servo/components/style/properties/longhand/font.mako.rs:106 (Diff revision 1) > + > + #[derive(Debug, PartialEq, Eq, Clone, Hash)] > + #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] > + pub enum FamilyNameSyntax { > + Quoted, > + Identifiers(Vec<Atom>), Instead of `Identifiers(Vec<Atom>)`, why not just `SpaceSeparatedIdentifiers`, and given we need to convert the name to a `String` anyway, we can split it during serialisation instead of keeping track of it this way. Would that work? If not, why not? ::: servo/components/style/properties/longhand/font.mako.rs:251 (Diff revision 1) > - write!(CssStringWriter::new(dest), "{}", self.name)?; > + write!(CssStringWriter::new(dest), "{}", self.name)?; > - dest.write_char('"') > + dest.write_char('"') > - } else { > - serialize_identifier(&*self.name.to_string(), dest) > - } > + } > + FamilyNameSyntax::Identifiers(ref identifiers) => { And if that works, a comment to mention that it's intentional and what problem it prevents would be quite on point.
Attachment #8891724 - Flags: review?(emilio+bugs)
Comment on attachment 8891725 [details] Bug 1384398 - Separate family names in font-family serialization with ", ". https://reviewboard.mozilla.org/r/162788/#review168126 r=me Apparently we had tests for this, but not the previous patch, any chance to write one?
Attachment #8891725 - Flags: review?(emilio+bugs) → review+
Comment on attachment 8891724 [details] Bug 1384398 - style: Preserve font-family identifier sequence when serializing. https://reviewboard.mozilla.org/r/162786/#review168124 > hmm... So I don't really think this is correct... Why is it? Couldn't it be a sequence of identifiers? The spec says (if I read it correctly) that sequences of identifiers should compute to a single string with all of the identifiers concatened with a single space in between. Gecko doesn't do that currently, and it just stores a single string with a quoted flag. So I figured I'd do the smallest change here and just worry about the specified value. (And yes, ideally we would have a separate specified and computed type for a family name list.) > Instead of `Identifiers(Vec<Atom>)`, why not just `SpaceSeparatedIdentifiers`, and given we need to convert the name to a `String` anyway, we can split it during serialisation instead of keeping track of it this way. > > Would that work? If not, why not? By this do you mean store a single String that is the serialization of the sequence of identifiers, and so would already take into account any backslash-escaping of individual identifiers?
Comment on attachment 8891724 [details] Bug 1384398 - style: Preserve font-family identifier sequence when serializing. https://reviewboard.mozilla.org/r/162786/#review168124 > The spec says (if I read it correctly) that sequences of identifiers should compute to a single string with all of the identifiers concatened with a single space in between. Gecko doesn't do that currently, and it just stores a single string with a quoted flag. So I figured I'd do the smallest change here and just worry about the specified value. (And yes, ideally we would have a separate specified and computed type for a family name list.) Right, but this effectively makes a value of: ``` Identifiers([foo, bar]), ``` Go to gecko as: ``` { name: "foo bar", quoted: false } ``` And return as: ``` Identifiers([foo bar]) ``` Which at least deserves a comment I think. > By this do you mean store a single String that is the serialization of the sequence of identifiers, and so would already take into account any backslash-escaping of individual identifiers? Nope, I mean the raw string as Gecko does, just instead of passing it down to serialize_identifier entirely, which would escape the spaces, do it ourselves splitting... I think it may work because it doesn't matter whether the original had any escaped space or not, I think. Basically, I was suggesting something like: ``` let name = self.name.to_string(); // We already do this conversion. let mut first = true; for ident in name.split(' ') { // This doesn't allocate or anything like that. if !first { dest.write_char(' ')?; } first = false; serialize_identifier(ident, dest)?; } ````
(In reply to Emilio Cobos Álvarez [:emilio] from comment #14) > > By this do you mean store a single String that is the serialization of the sequence of identifiers, and so would already take into account any backslash-escaping of individual identifiers? > > Nope, I mean the raw string as Gecko does, just instead of passing it down > to serialize_identifier entirely, which would escape the spaces, do it > ourselves splitting... I think it may work because it doesn't matter whether > the original had any escaped space or not, I think. > > Basically, I was suggesting something like: > > > ``` > let name = self.name.to_string(); // We already do this conversion. > > let mut first = true; > for ident in name.split(' ') { // This doesn't allocate or anything like > that. > if !first { > dest.write_char(' ')?; > } > first = false; > serialize_identifier(ident, dest)?; > } > ```` I don't think that would work when you have identifiers with backslash-escaped spaces in them, e.g. if you had p { font-family: A B\ \ C D; } then it should represent the family name "A B C D" but it would get incorrectly serialized as "A B C D" (which is equivalent to "A B C D"). If you like I would be happy to store the white space concatenated identifier-serialized identifiers in one Atom, and pass that to Gecko_FontFamilyList_AppendNamed with aQuoted = false. I guess that is closer to what Gecko does itself. Then serialization is just writing that Atom out.
(In reply to Cameron McCormack (:heycam) from comment #15) > I don't think that would work when you have identifiers with > backslash-escaped spaces in them, e.g. if you had > > p { font-family: A B\ \ C D; } > > then it should represent the family name "A B C D" but it would get > incorrectly serialized as "A B C D" (which is equivalent to "A B C D"). Hmm... Yeah, that's fair. > If you like I would be happy to store the white space concatenated > identifier-serialized identifiers in one Atom, and pass that to > Gecko_FontFamilyList_AppendNamed with aQuoted = false. I guess that is > closer to what Gecko does itself. Then serialization is just writing that > Atom out. That sounds great :)
Priority: P2 → --
Priority: -- → P2
Flags: needinfo?(cam)
Comment on attachment 8891724 [details] Bug 1384398 - style: Preserve font-family identifier sequence when serializing. https://reviewboard.mozilla.org/r/162786/#review170528 ::: servo/components/style/properties/longhand/font.mako.rs:260 (Diff revision 2) > - dest.write_char('"') > + dest.write_char('"') > - } else { > - serialize_identifier(&*self.name.to_string(), dest) > - } > + } > + FamilyNameSyntax::Identifiers(ref serialization) => { > + dest.write_str(&*serialization) nit: Maybe add a comment on here to note they're escaped already.
Attachment #8891724 - Flags: review?(emilio+bugs) → review+
Attachment #8891724 - Attachment is obsolete: true
Pushed by cmccormack@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/df230b4a8eb5 Separate family names in font-family serialization with ", ". r=emilio
Status: ASSIGNED → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla57
Is it expected that this patch produces a lot of stdout messages about fonts? It is polluting my system logs (linux).
Flags: needinfo?(emilio+bugs)
Flags: needinfo?(cam)
Yeah, Cameron accidentally left a debugging println! there, but that was removed in https://github.com/servo/servo/pull/17987 which should be in the next nightly. Sorry for the hassle!
Flags: needinfo?(emilio+bugs)
Flags: needinfo?(cam)
See Also: → 1434802
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: