Comparion of LogicalFontInstance::ImplGetGlyphBoundRect() between platforms

Chris Sherlock chris.sherlock79 at
Sat Oct 15 09:12:48 UTC 2022

I've done some testing of LogicalFontInstance::GetGlyphBoundRect(). Each
platform seems to give different values!

The commit in gerrit is:

(many thanks to Hossein for some suggestions in a different gerrit patch
about some things around unit tests I didn't know - see comments at

Ultimately, the differences boil down to the pure function
LogicalFontInstance::ImplGetGlyphBoundRect(), which each platform must
implement to get the glyph's bounding rect.

To try to understand the differences, I've looked at each platform's
implementation with some notes, if this is at all helpful. Any comments
would be appreciated! I'd love to standardize this function :-)


Comparion of LogicalFontInstance::ImplGetGlyphBoundRect() between platforms


ImplGetGlyphBoundRect() is implemented in WinFontInstance, derived by
from LogicalFontInstance

Located in vcl/win/gdi/salfont.cxx


Step 1: select the font

1. Get the HDC of the current graphics
2. Get the current GDI font's HFONT
3. Get the the HFONT of the font referenced by the WinFontInstance
4. If the current GDI HFONT is not the WinFontInstance's HFONT then
   explicitly select the WinFontInstance's HFONT
5. Setup a guard to restore the original font after
   ImplGetGlyphBoundRect() finishes

Step 2: Setup transformation matrix

MAT2 is a 3x3 transformation matrix

If using horizontal text, setup an identity matrix (means that nothing
happens when applying the matrix)

If using vertical writing then matrix appropriately rotates the glyph

Step 3: Setup to get the glyph's bounding rect

1. Set the flag for GetGlyphOutlineW to use GGO_METRICS and

   - GGO_METRICS indicates to retrieve the GLYPHMETRICS structure
   - GGO_GLYPH_INDEX indicates that we use the TrueType glyph index
     instead of the character code

2. Zero initialize the GLYPHMETRICS fields

3. Call on GetGlyphOutlineW using the transformation matrix to
   populate the glyph metrics

Step 4: Get the bounding rect of the glyph

The next bit takes the glyph metrics from the previous step.

1. Populate the glyph rectangle with the origin being the x- and y-
   coords of the upper left corner of the smallest rectangle that
   completely encloses the glyph, and the width and height of the
   glyph's "black box", which is the smallest rectangle that
   encloses the glyph

2. Scale the bounding rectangle, adding a point to the right and
   bottom coords of the rectangle


Basically, we call on Win32's GetGlyphOutlineW() to get the GLYPHMETRICS.
It is important to quote Microsoft on this structure:

   The GLYPHMETRICS structure specifies the width of the character cell
   and the location of a glyph within the character cell. The origin of
   the character cell is located at the left side of the cell at the
   baseline of the font. The location of the glyph origin is relative to
   the character cell origin. The height of a character cell, the
   baseline, and other metrics global to the font are given by the


ImplGetGlyphBoundRect() is implemented in CoreTextStyle, derived from

Located in vcl/quartz/ctfont.cxx


Step 1: Get the glyph rectangle

1. Set the CGGlyph variable nCGGlyph the glyph index
2. Get the font by looking up the mpStyleDict dictionary for the
   kCTFontAttributeName, which gives the font of the text to
   which this attribute applies

Note: Currently does not handle vertical text

3. Get the glyph rectangle in a CGRect by calling on
4. Apply any font rotation for horizontal text

Step 2: Return the tools::Rectangle bounding rect

1. std::floor() the origin x, y (i.e. the top left)
2. std::ceil() the bottom right of the rectangle
   i.e. to get this, aCGRect.origin.x + aCGRect.size.width
                     aCGRect.origin.y + aCGRect.size.height

3. so the rectangle gets the positive x origin and a negative y origin (???)
   and for the bottom left a positive x and a negative y (???)


Use CTFontGetBoundRectsForGlyphs() to get the bounding rect of
the glyph.

Note that the Core Text documentation says the following:

  The bounding rectangles of the individual glyphs are returned through
  the boundingRects parameter. These are the design metrics from the
  font transformed in font space.


Note there are two variants: Qt and Freetype


ImplGetGlyphBoundRect() is implemented in QtFont, derived from

Located in vcl/qt5/QtFont.cxx


Literally gets the font, then gets the glyph bounding rect, which it
converts to a tools::Rectangle


Kind of opaque - not sure how Qt derives the bounding rect. Qt's
documentation has one line to describe it, which is:

   Returns the smallest rectangle containing the glyph with the given


ImplGetGlyphBoundRect() is implmeneted in FreetypeFontInstance, derived
from LogicalFontInstance. This is, however, merely a wrapper
around FreeTypeFont::GetGlyphBoundRect() via member mxFreeTypeFont.

FreeTypeFont::GetGlyphBoundRect() is defined in


Step 1: Load the font

1. activates the size of the font face via FT_Activate_Size() for
2. loads the glyph (see below)

Step 2: Get the glyph

1. embolden the glyph if needed
2. loads the glyph
3. applies a tranform to the glyph is needed

Step 3: Get the bounds box of the glyph

1. Load the glyph's control box, which encloses the outlines
   points, via FT_Glyph_Get_CBox(), using the flag
2. destroys the glyph via FT_Done_Glyph()
3. Creates a tools::Rectangle via:

   tools::Rectangle aRect(aBbox.xMin, -aBbox.yMax, aBbox.xMax, -aBbox.yMin);

4. Calculates bounding rectangle of rotated glyph if necessary


A few things to note - firstly the font is loaded via the flags

The second thing is: a FT_BBox has a very specific format in turns of
negative yMin, yMax, xMin and xMax values. We seem to ignore these! (see



   Corresponding to 0, this value is used as the default glyph load
   operation. In this case, the following happens:

   1. FreeType looks for a bitmap for the glyph corresponding to the
      face's current size. If one is found, the function returns. The
      bitmap data can be accessed from the glyph slot (see note

   2. If no embedded bitmap is searched for or found, FreeType looks for
      a scalable outline. If one is found, it is loaded from the font
      file, scaled to device pixels, then ‘hinted’ to the pixel grid in
      order to optimize it. The outline data can be accessed from the
      glyph slot (see note below).

   Note that by default the glyph loader doesn't render outlines into


   Ignore the transform matrix set by FT_Set_Transform.



   Defined in FT_IMAGE_H (freetype/ftimage.h).

   typedef struct  FT_BBox_
      FT_Pos  xMin, yMin;
      FT_Pos  xMax, yMax;
   } FT_BBox;

   A structure used to hold an outline's bounding box, i.e., the
   coordinates of its extrema in the horizontal and vertical

      xMin: The horizontal minimum (left-most).
      yMin: The vertical minimum (bottom-most).
      xMax: The horizontal maximum (right-most).
      yMax: The vertical maximum (top-most).


   The bounding box is specified with the coordinates of the lower left
   and the upper right corner. In PostScript, those values are often
   called (llx,lly) and (urx,ury), respectively.

   If yMin is negative, this value gives the glyph's descender. Otherwise,
   the glyph doesn't descend below the baseline. Similarly, if yMax is
   positive, this value gives the glyph's ascender.

   xMin gives the horizontal distance from the glyph's origin to the left
   edge of the glyph's bounding box. If xMin is negative, the glyph
   extends to the left of the origin.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the LibreOffice mailing list