freetype-devel
[Top][All Lists]
Advanced

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

Re: [ft-devel] FT_Get_Advance() docs


From: Werner LEMBERG
Subject: Re: [ft-devel] FT_Get_Advance() docs
Date: Sun, 11 Dec 2011 15:02:29 +0100 (CET)

> [...] I also found this bug, and used about the same fix as you
> committed.  The only difference is a minor nit, in the case
> FT_LOAD_NO_SCALE is used and the quick way failed with ErrNotImplem,
> <<10 scaling might not be done.

Patch, please (or please commit by yourself).

>> The next two are more subtle and not directly related to
>> `FT_Get_Advance' (I get wrong metrics from some fonts), and I need
>> more investigation to fix them.
> 
> Details please.  I did found something myself, most likely a double
> rounding issue (more below), but I cannot figure where is the
> problem exactly because I do not know the internals enough :-(.

Attached is my quick'n'dirty test program.

. In the font UnicodeAll.otf, a demo font written by Ken Lunde which
  is a CFF with 256 CID-keyed subfonts covering all Unicode
  characters[1], all glyphs have the same width, but `FT_Load_Glyph'
  returns changing width values with light hinting.

. In a Type42 font, `ft_get_advance' returns funny values for empty
  glyphs.

. In arial.ttf (version 2.76), I get different linearHoriAdvance
  values(!) for glyph 556 (`afii10023') if I use normal or light
  hinting.

I can send you my tests fonts privately if you want to play with them.

>>> Another thing we need to document is that the ->glyph instance
>>> inside the face object might be erased after a call through
>>> FT_Get_Advance().
>> 
>> Yes.  Can you provide a patch?
> 
> Will do.

Thanks!

>> After some thinking I now believe that it is a bug that
>> `FT_Get_Advance' returns unrounded advance widths for the light
>> hinting mode.
> 
> Okay, but then we have to mimic exactly the rounding process used by
> the Load_Glyph logic*s*...

Yes, this is what the advince width function hooks into the font
modules are good for.

>>>>> when the requested ppem has an associated hdmx/VDMX table within
>>>>> the font.
>>>>
>>>> Do you volunteer to implement support for those two tables?
>>>
>>> Yes, I will do that (but not today.)
> 
> I looked at it, but it does not appear to be very easy to do,
> particularly because the current (*...clazz->get_advances)()
> functions returns _unscaled_ values (which are to be scaled within
> FT_Get_Advance while "hdmx" values are pixels, hence are already
> scaled.

Mhmm, I suggest that you don't use the `clazz' route.  Instead, simply
add parsing code for those two tables to `ft_get_advance'.

>>> I wonder also about a new demo program to check whether
>>> FT_Get_Advance() gives, or not, the same results as
>>> FT_Load_Glyph().
>> 
>> This might be useful, yes.
> 
> Attached.

Very nice, thanks!  Please add it to the freetype2-demos repository
(but not adding it to the `EXES' variable in the Makefile).

> The problem I detected then was the behaviour of invocations like
> [...]

I'll have a detailed look in the next days.


    Werner


[1] Converting this 70kByte font with ttx gives a whopping 140MByte
    XML file; if you omit the cmap, it's only 317kByte :-)
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_ADVANCES_H


int
main(int argc,
     char** argv)
{
  FT_Library library;
  FT_Face face;
  FT_UShort i;


  FT_Init_FreeType(&library);
  FT_New_Face(library, argv[1], 0, &face);
  FT_Set_Char_Size(face, 50 * 64, 0, 100, 0);

  printf("glyph index:\n"
         "  advance.x (normal hinting/light hinting)\n"
         "  linearHoriAdvance\n"
         "  ft_get_advance (normal hinting/light hinting)\n");
  for (i = 0; i < face->num_glyphs; i++)
  {
    FT_Fixed advance;
    double normal_advance, light_advance;
    double normal_get_advance, light_get_advance;
    double normal_linearHoriAdvance, light_linearHoriAdvance;


    FT_Load_Glyph(face, i, FT_LOAD_DEFAULT);
    normal_advance = face->glyph->advance.x / 64.0;
    normal_linearHoriAdvance = face->glyph->linearHoriAdvance / 65536.0;

    FT_Load_Glyph(face, i, FT_LOAD_TARGET_LIGHT);
    light_advance = face->glyph->advance.x / 64.0;
    light_linearHoriAdvance = face->glyph->linearHoriAdvance / 65536.0;

    FT_Get_Advance(face, i, FT_LOAD_DEFAULT, &advance);
    normal_get_advance = advance / 65536.0;

    FT_Get_Advance(face, i, FT_LOAD_TARGET_LIGHT, &advance);
    light_get_advance = advance / 65536.0;

    printf("%d:\n", i);
    printf("  %f %f\n", normal_advance, light_advance);
    printf("  %f\n", normal_linearHoriAdvance);
    if (normal_linearHoriAdvance != light_linearHoriAdvance)
      printf("  Urgh: %f\n", light_linearHoriAdvance);
    printf("  %f %f\n", normal_get_advance, light_get_advance);
  }

  FT_Done_Face(face);
  FT_Done_FreeType(library);

  return 0;
}

reply via email to

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