[css3-fonts][cssom] proposal for revised definition of CSSFontFaceRule

I mentioned it briefly on the call yesterday but I wanted to bring up the
issue of CSSFontFaceRule.  This was originally defined in CSS2 OM spec as:

  interface CSSFontFaceRule : CSSRule {
    attribute CSSStyleDeclaration style;
  }

The CSSStyleDeclaration interface [1] is the general getter/setter
interface used for style rules:

  interface CSSStyleDeclaration {
    attribute DOMString  cssText;
   
    DOMString getPropertyValue(in DOMString propertyName);
    CSSValue getPropertyCSSValue(in DOMString propertyName);
    DOMString removeProperty(in DOMString propertyName)
  
    DOMString getPropertyPriority(in DOMString propertyName);
    void setProperty(in DOMString propertyName, 
                     in DOMString value, 
                     in DOMString priority)
  
    readonly attribute unsigned long    length;
    DOMString          item(in unsigned long index);
    readonly attribute CSSRule          parentRule;
  };

But CSS2 also defined the "extended" version of this, the
CSS2Properties interface [2], that includes direct accessors for all
style properties:

interface CSS2Properties {
  attribute DOMString azimuth;
  attribute DOMString background;
  attribute DOMString backgroundAttachment;
  attribute DOMString backgroundColor;
  attribute DOMString backgroundImage;
  attribute DOMString backgroundPosition;
  attribute DOMString backgroundRepeat;
  attribute DOMString border;
  attribute DOMString borderCollapse;
  attribute DOMString borderColor;
  ...
  [ all style properties in CSS ]
  ...
};

Implementations have typically combined the two, such that given a
style rule, either style.fontFamily or style.getPropertyValue("font-family")
will return the setting for 'font-family', if defined in the rule.

In the context of @font-face rules, there's some crossover between the
set of descriptors defined for @font-face rules and for style rules
(e.g. "font-family", "font-weight", "font-style", etc.) but several of
descriptors are unique to @font-face rules (e.g. "unicode-range",
"src").  This makes use the CSSStyleDeclaration interface for
@font-face rules very odd.  There are also some subtle differences,
the "font-family" descriptor for @font-face rules only takes a
*single* name, not the list of multiple names allowed for the
"font-family" property in style rules.

I put together some tests that show some of the problems with using
the CSSStyleDeclaration/CSS2Properties as a way to access descriptions
in @font-face rules.

  http://people.mozilla.org/~jdaggett/tests/fontfacedom.html

Details of the differences are included at the end of this post.

I think it might make sense to define a new, simpler interface for accessing
descriptors in @-rules and simply define CSSFontFactRule as an interface
containing descriptors that implements that interface.

  [NoInterfaceObject] interface DescriptorAccess {
    DOMString GetDescriptorValue(DOMString descName);
    void SetDescriptorValue(DOMString descName, DOMString value);
  
    readonly attribute unsigned long length;
    DOMString item(unsigned long index);
  };
  
  interface CSSFontFaceRule : CSSRule {
  
    // descriptors
    attribute DOMString fontFamily;
    attribute DOMString src;
    attribute DOMString fontWeight;
    attribute DOMString fontStyle;
    attribute DOMString fontStretch;
    attribute DOMString fontVariant;
    attribute DOMString fontFeatureSettings;
    attribute DOMString unicodeRange;
  
    // load state - whether the font is loaded or not
    readonly attribute boolean loaded;
  
  };
  
  interface CSSFontFaceRule implements DescriptorAccess;
  
If there's concern about the existing rule.style.xxx accessors,
implementations could alias those to the properties above.  Other
rules, such as the @counter-style rule, could follow this model,
rather than using CSSStyleDeclaration as a global property bucket.

Thoughts?

Regards,

John Daggett
Mozilla Japan

[1] http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
[2] http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSS2Properties


OM access of @font-face rule details
================================================

While all the browsers that implement @font-face rules allow access to
@font-face rules via this interface, the differences are striking and
there are several very interesting bugs in current implementations.

Tests:
  http://people.mozilla.org/~jdaggett/tests/fontfacedom.html

Example 1: If 'rule' is a CSSFontFaceRule object, what should 
           the code below do?

    rule.style.font = "bold italic 12px test57";

  Both Webkit and IE9 parse this as a shorthand and set the relevant
  descriptors (e.g. "font-weight", "font-style") but also set
  "line-height" and "font-size" and it makes a mess of
  rule.style.cssText.  Opera is smarter, the line above has no effect
  on the descriptor values.  Firefox throws an error on all attempts
  to access rule.style.xxx in @font-face rules (I think Boris
  mentioned that the CSS2Properties isn't used with these, I haven't
  dug into the code just yet).

Example 2: What should the code below do?

    rule.style.fontFamily = "test1, test2";

  Here the problem is that only a single name is allowed for the
  "font-family" descriptor of @font-face rules.  Here again, Webkit
  and IE accept it but Opera rejects it.

Example 3: What should the call below return?

    var src = rule.style.getPropertyValue("src");

  All implementations return the value of the "src" descriptor for the @font-face
  rule.

Example 4: What should the value of the two variables below be?

    var ur1 = rule.style.src;
    var ur2 = rule.style.getPropertyValue("src");

  In Webkit and Opera, both return the value of the "src" descriptor
  of the @font-face rule.  Firefox returns 'undefined' for ur1 and the
  descriptor value for the second. IE9 returns 'undefined' for the first, a
  null string for the second.

Example 5: Should the three values below be equal or not?

    var ur = el.style.unicodeRange;
    var unk = el.style.unknownProperty;

  For unknown properties, the result in both cases should be
  "undefined", since "unicode-range" is not a property associated with
  style rules.  However, to make access to "unicode-range" available
  within @font-face rules, the Webkit implementation addds
  "unicodeRange" to the CSS2Properties struct which means that all
  elements expose access to this.  IE9 and Firefox return "undefined"
  for both of these.  Opera returns a null string for the first and
  "undefined" for the second.

Received on Thursday, 13 September 2012 07:47:03 UTC