[cairo] Counting semantics of cairo_ft_scaled_font_lock_face

David Turner david at freetype.org
Tue Feb 13 03:02:39 PST 2007

On Mon, 12 Feb 2007 12:20:57 -0800, "Carl Worth" <cworth at redhat.com> said:
> The work to remove those impacts probably wouldn't even be too
> severe. Though it's also not obvious to me if the impact is all
> negative. For example, might it not be better to maintain two separate
> FT_Face objects rather than thrashing back and forth with
> FT_Set_Transform on a shared FT_Face?

there are several problems there:

- first of all, a FT_Face object can be very large. Even when
  memory-mapping the font file, each one can take between 20 and
  250 KB (the latter is for multi-megabytes CJK fonts) of
  heap memory. I try to reduce these numbers in each new release
  of the library, but it's not always easy to do so without
  sacrificing performance or even binary compatibility with
  programs that access font engine internals directly (which I
  hope are rapidly disappearing).

  The worst offenders in this regards are Type 1 fonts and compressed
  pcf/bdf fonts, which is one of the reasons why I'd like to get rid
  of these ugly formats :-) However, this can be even noticeable with
  TrueType/OpenType fonts, depending on their design.

  this memory is never shared between processes, so it can add
  up pretty quickly on a typical desktop. Think about 30
  processes linked to Cairo, each one implementing its own cache
  of 16 FT_Face objects, plus its own glyph cache in heap memory.

  that's also exactly why FT_Size objects exist in the first place;
  each FT_Size holds state information related to a given
  character pixel sizes. By default, each FT_Face has a FT_Size,
  but you can create more FT_Size for the same FT_Face in order
  to save memory. And FT_Size objects are much smaller than
  a FT_Face (around 4-8 KB, the first FT_Size is accounted for
  in the size of the FT_Face).

  Also, switching between FT_Size objects (with FT_Activate_Size)
  is in certain cases a lot faster than calling FT_Set_Char_Size
  since it avoids recomputing many things (especially when the
  TrueType bytecode interpreter is used)

  It's true that FT_Set_Transform changes a FT_Face field, instead
  of a FT_Size one. That's probably my fault, but this isn't a
  real issue due the second point below.

- second, you assume that concurrent operations on two distinct
  FT_Face is not a problem. This is unfortunately totally
  untrue, since there are things shared internally by several objects
  especially to reduce the total heap usage of the library.
  For example, I guarantee you that you could encounter ugly race
  conditions when loading/rasterizing glyphs from two distinct
  FT_Faces from two distinct threads at the same time.

  The only correct way to use concurrent faces without locking in
  the client is to create each one of them in its own FT_Library,
  and then, your heap usage is going to increase significantly.

  And I want to be able to share even more data between these
  FT_Face objects in the future, all for the sake of memory
  footprint reduction.

  FreeType has never been designed to be used concurrently by
  multiple threads; locking from the client is required. And this
  feature has not, and will not, been pushed into the library for
  several good reasons.

Hope this helps,

- David Turner
- The FreeType Project  (www.freetype.org)

More information about the cairo mailing list