Open Bug 402473 Opened 17 years ago Updated 2 years ago

DTRT with OpenType font-metrics, frame ascent/descent, bounding boxes, and line heights.

Categories

(Core :: Layout: Text and Fonts, defect)

x86
All
defect

Tracking

()

ASSIGNED

People

(Reporter: karlt, Assigned: karlt)

References

Details

Attachments

(1 file)

Currently we use the same font-metrics for frame ascent/descent as for
bounding boxes, but I think we can do better.

Currently the metrics used are different on different platforms even if the
same font is used.  It would be nice to be as consistent as possible.


OpenType fonts provide a number of metrics to choose from here:

The font header contains xMin, yMin, xMax, yMax of all glyph bounding boxes.
 http://www.microsoft.com/typography/otspec/head.htm

sTypoAscender/sTypoDescender/sTypoLineGap are in the OS/2 table.
 (These correspond to the Adobe Font Metrics ascender and descender, but not
  those in the hhea table.)

 http://www.microsoft.com/typography/otspec/os2.htm#sta

 "These new metrics, when combined with the character design widths, will
  allow applications to lay out documents in a typographically correct and
  portable fashion."

 http://www.microsoft.com/typography/otspec/recom.htm#tad

 "sTypoAscender is used to determine the optimum offset from the top of a
  text frame to the first baseline. sTypoDescender is used to determine the
  optimum offset from the last baseline to the bottom of the text frame. The
  value of (sTypoAscender - sTypoDescender) is recommended to equal one em."

 "sTypoAscender, sTypoDescender and sTypoLineGap specify the recommended line
  spacing for single-spaced horizontal text."

usWinAscent/usWinDescent are also in the OS/2 table

 http://www.microsoft.com/typography/otspec/os2.htm#wa

 "usWinAscent is computed as the yMax for all characters in the Windows ANSI
  character set. usWinAscent is used to compute the Windows font height and
  default line spacing. For platform 3 encoding 0 fonts, it is the same as
  yMax. Windows will clip the bitmap of any portion of a glyph that appears
  above this value. Some applications use this value to determine default line
  spacing. This is strongly discouraged. The typographic ascender, descender
  and line gap fields in conjunction with unitsPerEm should be used for this
  purpose."

 In practice the use of these metrics as bounds sometimes ends up being
 compromised by line spacing issues:

 "if a developer desires to provide appropriate default line spacing using
  this field, for those applications that continue to use this field for doing
  so (against OpenType recommendations), then the value should be set
  appropriately. In such a case, it may result in some glyph bitmaps being
  clipped."

The hhea table contains metrics for Ascender, Descender, and LineGap.

 I'm not sure of the precise meaning of these, but it looks like they should
 generally be somewhere between the typographical values and bounding metrics.

 http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6hhea.html

 "The values for ascent, descent and lineGap represent the design intentions
  of the font's creator rather than any computed value."

 http://www.microsoft.com/typography/otspec/recom.htm#tad
 (scroll down to the section Baseline to Baseline Distances)

 For (historical?) Macintosh implementations these can affect vertical
 scaling: "If pixels extend above the ascent or below the descent, the
  character will be squashed in the vertical direction so that all pixels fit
  within these limitations; this is true for screen display only."


Current Implementation:

 Windows

  Both the frame and bounding ascent/descent values are set from
  usWinAscent/usWinDescent.  This causes bug 381815.

  Normal line height is set from either these values or the hhea values using
  MAX(usWinAscent + usWinDescent, Ascender - Descender + LineGap).

 Mac

  Both the frame and bounding ascent/descent values are set from hhea
  Ascender/Descender.  This can cause unexpected clipping of characters.

  Normal line height is set from Ascender - Descender + LineGap.

 Linux

  Both the frame and bounding ascent/descent values are set from hhea
  Ascender/Descender. (same as Mac)

  Normal line height is set from Ascender - Descender (without including
  LineGap).  This causes line height to be too short.


Content height:

 CSS is a bit vague on how the height of the content area depends on the font.

 http://www.w3.org/TR/CSS21/visudet.html#inline-non-replaced
 CSS 2.1 Recommendation 19 July 2007

 * hints that "A UA may, e.g., use the em-box or the maximum ascender and
   descender of the font."

 * but notes "level 3 of CSS will probably include a property to select which
   measure of the font is used for the content height."

 http://www.w3.org/TR/css3-linebox/#inline1
 The latest (15 May 2002) Working Draft for CSS3 module: line provides the
 text-height property to clarify (a little).

  Possible values include:

   font-size: "The block-progression dimension is based on the em square as
    determined by the element font-size."

   text-size: "The block-progression dimension is based on the cell-height
    (ascender + descender) related to the element font-size.

    I don't know what is meant by cell-height here and (so) I'm not clear
    which ascender/descender this is.

  The initial value is auto, which means the user agent chooses between
  font-size and text-size.


Proposal:

 1) Use yMin/yMax for the bounding box.

    This could be stored in the maxAscent/maxDescent fields of
    gfxFont::Metrics.  Or we could change the names to yMax/yMin to be more
    specific.

 2) Use sTypoAscender - sTypoDescender + sTypoLineGap for normal line height.

    This could be done by setting internalLeading and externalLeading
    appropriately in gfxFont::Metrics.

 3) Use sTypoAscender/sTypoDescender for frame ascent/descent (and height).

    For OpenType fonts following the recommendations the font-size and
    text-size values for text-height would be equivalent.

    If sTypoAscender - sTypoDescender is not 1 em then perhaps these could
    be scaled such that frame heights are 1 em.

    These could be stored in the emAscent/emDescent fields or if the values
    are not forced to be one em, the names of these fields could be changed to
    Ascender/Descender.

 4) Store xMax/xMin in gfxFont::Metrics for use in calculating the mBoundingBox
    of RunMetrics when aTightBoundingBox is not set.
Bug 13072 is related.
(recording where I got up to)

Without other modifications, this change is not appealing.
Issues are:

1) Selection areas and carets are apparently based on the frame height and so
   look too short.
   These would look better if they either depended on the line height,
   overflow rect, or em-height multiplied by some factor > 1.

2) XUL boxes (nsTextBoxFrame maybe et al) position the text too high.
   It seems that MaxAscent/Descent is used to size the XUL box and leading and
   baseline positioning are often not considered when positioning the text
   frame.
Blocks: 279032
Blocks: 426435
Since OpenType Version 1.5 (May 2008) there is a flag to strongly recommend using OS/2 typo metrics to calculate the line height. See https://www.microsoft.com/typography/otspec/os2.htm#fss
It might be more appropriate to do the following:

1) Use font head yMin and yMax for the bounding box.

2) If the font OS/2 fsSelection USE_TYPO_METRICS bit flag is on then use font OS/2 sTypoAscender - sTypoDescender + sTypoLineGap for the line height. Otherwise use the hhea Ascender + Descender + LineGap.

3) Use line height for the frame.
(In reply to Denis Jacquerye from comment #3)
> Since OpenType Version 1.5 (May 2008) there is a flag to strongly recommend
> using OS/2 typo metrics to calculate the line height. See
> https://www.microsoft.com/typography/otspec/os2.htm#fss

In the latest release (Gecko 41), the USE_TYPO_METRICS bit is taken into account on all platforms.
(In reply to Frédéric Wang (:fredw) from comment #4)
> 
> In the latest release (Gecko 41), the USE_TYPO_METRICS bit is taken into
> account on all platforms.

Good to know. But it seems the same fonts still behave differently depending on the platform.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: