// borrowed from Wine static inline USHORT get_fixed_windescent(USHORT windescent) { return abs((SHORT)windescent); } static LONG calc_ppem_for_height(FT_Face ft_face, LONG height) { TT_OS2 *pOS2; TT_HoriHeader *pHori; LONG ppem; const LONG MAX_PPEM = (1 << 16) - 1; pOS2 = FT_Get_Sfnt_Table(ft_face, FT_SFNT_OS2); pHori = FT_Get_Sfnt_Table(ft_face, FT_SFNT_HHEA); ASSERT(pOS2); ASSERT(pHori); if (height == 0) height = 16; /* For lfHeight > 0: * ppem = units_per_em * lfheight / (winAscent + winDescent). * * For lfHeight < 0: * ppem = |lfHeight| = (winAscent + winDescent - IL) * ppem / units_per_em * ; with IL = winAscent + winDescent - units_per_em. */ if (height > 0) { USHORT windescent = get_fixed_windescent(pOS2->usWinDescent); if (pOS2->usWinAscent + windescent == 0) { ppem = MulDiv(ft_face->units_per_EM, height, pHori->Ascender - pHori->Descender); } else { ppem = MulDiv(ft_face->units_per_EM, height, pOS2->usWinAscent + windescent); } if (ppem > MAX_PPEM) { ppem = 1; } } else if (height >= -MAX_PPEM) { ppem = -height; } else { DPRINT("Ignoring too large height %d\n", height); ppem = 1; } return ppem; }