[Fontconfig] SFNT TTF support in fontconfig

mpsuzuki at hiroshima-u.ac.jp mpsuzuki at hiroshima-u.ac.jp
Sun Aug 20 23:59:37 PDT 2006


Hi,

On Sat, 19 Aug 2006 12:51:29 -0400
"Qianqian Fang" <fangq at nmr.mgh.harvard.edu> wrote:
>I noticed that the fc-cache utility does not support SFNT ttf(or otf) 
>format well. It will output a fonts.cache-1 file with wrong font information.

I guess fontconfig is designed for outline font, and bitmap-only
fonts are left in the cold.

>http://prdownloads.sourceforge.net/wqy/wqy-bitmapfont-ttf-0.7.0-4.tar.gz?download

As the name tells, WQY fonts include collection of bitmap fonts
for 12/13/15/16 pixels, and its glyf table includes single glyph
only (for undefined character).

If you built fontconfig-2.2.3 with additional "-DCHECK" CFLAGS and
run fc-cache with debug environment variable (e.g. FC_DEBUG=9999),
you will receive following result:

        Scanning file cjk-bitmap/wqy-bsong.ttf..."WenQuanYi Bitmap Song" "medium" TT_Load_Simple_Glyph: Too many instructions!
	0x0000000d FT says 1 FC says 0
	0x00000021 FT says 1 FC says 0
	0x00000022 FT says 1 FC says 0

	[snip]

	0x0000ffe3 FT says 1 FC says 0
	0x0000ffe5 FT says 1 FC says 0
	33987 glyphs 4 encoded
	Bitmap missing char 0xd

	[snip]

	Bitmap missing char 0x2fd5
	done
	caching, 1 fonts, 0 dirs

"0x0000000d FT says 1 FC says 0" means that FreeType2 can load
glyph for UCS2 codepoint 0x000d, but fontconfig ignores it.

The line generating "0x00000022 FT says 1 FC says 0" is here:
fcfreetype.c
  1704  #ifdef CHECK
  1705              for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
  1706              {
  1707                  FcBool      FT_Has, FC_Has;
  1708  
  1709                  FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
  1710                  FC_Has = FcCharSetHasChar (fcs, ucs4);
  1711                  if (FT_Has != FC_Has)
  1712                  {
  1713                      printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
  1714                  }
  1715              }
  1716  #endif

FT_Get_Char_Index() returns glyphID for given charcode, but it
does not care about outline or bitmap. Therefore, "FT_Has" means
if the font has anything to render "ucs4" (outline or bitmap).

On the other hand, FcCharSetHasChar() checks whether given charcode
is registered in fontconfig's charset database "fcs". Yes, you
can remind "charset=" entry in fonts.cache-1.

Where "fcs" comes from? Check FcFreeTypeCharSetAndSpacing().

  1592  FcCharSet *
  1593  FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
  1594  {

  ...

  1668              while (gindex)
  1669              {
  1670                  page = ucs4 >> 8;
  1671                  leaf = 0;
  1672                  while ((ucs4 >> 8) == page)
  1673                  {
  1674                      glyph = FT_Get_Char_Index (face, ucs4);
  1675                      if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
  1676                                                         glyph, blanks, &advance))

  ...

What FcFreeTypeCharSetAndSpacing() does?

fcfreetype.c
  1537  FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, 
  1538                        FT_UInt glyph, FcBlanks *blanks,
  1539                        FT_Pos *advance)
  1540  {
  1541      FT_Int          load_flags = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
  1542      FT_GlyphSlot    slot;
  1543      
  1544      /*
  1545       * When using scalable fonts, only report those glyphs
  1546       * which can be scaled; otherwise those fonts will
  1547       * only be available at some sizes, and never when
  1548       * transformed.  Avoid this by simply reporting bitmap-only
  1549       * glyphs as missing
  1550       */
  1551      if (face->face_flags & FT_FACE_FLAG_SCALABLE)
  1552          load_flags |= FT_LOAD_NO_BITMAP;

Here is the important part. face->face_flags is set by FreeType2
to notice the information about font, the detail of flags are found
at:

	http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_FACE_FLAG_XXX

You can find that FT_FACE_FLAG_SCALABLE means that the font includes
vector glyph data (with no care about how many). Since WQY font has
glyf table, the condition at #1551 is true. Then, load_cflags is
set to ignore included bitmap data. Why? The reason is noted in above.
The fontconfig designer wanted to avoid following scenario:

1. fontconfig make fc-charset info as superset of outline & bitmap data.

2. application expects as all character in fc-charset were scalable.

3. application tries to load a glyph image at arbitrary pixel size,
   but the font does not include vector data for the glyph and
   application is forced to use "scaled bitmap" which looks ugly.

I'm trying to remove glyf table from WQY and notice to fontconfig
that WQY is not "scalable", but not success yet.

Regards,
mpsuzuki


More information about the Fontconfig mailing list