freetype
[Top][All Lists]
Advanced

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

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


From: Huw Davies
Subject: Re: [ft] TrueType table trickery to match Windows MM_TEXT render size (= match pixel baseline distance
Date: Thu, 18 Jan 2007 12:27:59 +0000
User-agent: Mutt/1.4.2.1i

On Thu, Jan 18, 2007 at 01:08:26PM +0100, David LAMPARTER wrote:
> 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.

It's more complicated than that.  Windows uses the VDMX table for
instance, so you end up with a non-linear lfHeight -> ppem size
mapping.  For all the details, grab the source of Wine
(http://www.winehq.org) and look in dlls/gdi32/freetype.c

Huw.




reply via email to

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