freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ft] TrueType table trickery to match Windows MM_TEXT render size (= mat


From: David LAMPARTER
Subject: [ft] TrueType table trickery to match Windows MM_TEXT render size (= match pixel baseline distance
Date: Thu, 18 Jan 2007 13:08:26 +0100
User-agent: Mutt/1.5.11

Hi,

while diving into an issue with a project of mine which needs to
reproduce Windows behaviour as exact as possible, I hit some very
strange size discrepancies. I was able to resolve them with a quite
strange hack by accessing information from the hori and os2 TT headers.
Since this keeps bugging me, I'm curious whether someone can tell me if
this is correct (I wasn't able to test with too many fonts, but unlike
for every other attempt I made, I didn't hit a mismatch yet.)

The core problem is that the Windows app (VSFilter, by the way) does:

  SetMapMode(g_hDC, MM_TEXT);
  LOGFONT lf;
  CreateFontIndirect(&lf);

According to the Platform SDK docs, MM_TEXT means "Each logical unit is
mapped to one device pixel. Positive x is to the right; positive y is
down." Testing shows that the baseline distance is equal to the
specified font size.

I then tried to create a similar rendering with FreeType. My starting
point was:

  FT_Size_RequestRec req;
  req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
  req.width = 0;
  req.height = (FT_F26Dot6)(size * 64);
  req.horiResolution = req.vertResolution = 0;
  FT_Request_Size(face, &req);

This worked fine for some fonts (e.g. Arial) but gave incorrect size for
some other fonts (e.g. Vogue). I tried all possibilities for req.type
with different resolution values (0, 72, 96) but either Arial did not
match anymore or the mis-sized fonts were still mis-sized.

After poking one of the mis-sized fonts with an font editor, and
comparing values to the scaling factors I had deduced, the resulting
hack is the following:

  float scale = 1.0f;
  os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
  hori = (TT_HoriHeader *)FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
  if (os2 && hori) {
    int horisum = hori->Ascender - hori->Descender;
    unsigned winsum = os2->usWinAscent + os2->usWinDescent;
    float mscale = (float)horisum / (float)winsum;
  }

  req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
  req.height = (FT_F26Dot6)(size * 64 * scale);

(Note how hori->Line_Gap is not included...)

Any explanation (either why this is wrong or why this is correct or
whatever) would be appreciated.

Greetings,


LAMPARTER, David






reply via email to

[Prev in Thread] Current Thread [Next in Thread]