[PATCH v2 1/3] gdi32: Fix the truetype interpreter version problem.

Nikolay Sivov nsivov at codeweavers.com
Mon Nov 5 01:21:24 CST 2018


On 11/05/2018 08:08 AM, Byeongsik Jeon wrote:

> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41639
> Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
> ---
> v2:
> Fix the wine-tests build error at the debian9(Freetype v2.6.3).
> Because the build-time check is meaningless, v2 has modified it to check
> the supported interpreter version at the runtime.
>
> v1:
> This is also a problem in Linux. It just seemed to stand out in
> MacOS(Tahoma builtined) XQuartz2.7.11 Freetype2.7(subpixel turned off).
>
> The truetype bytecode interpreter of the Freetype appears to have the
> following problems depending on the version.
> - v35: MS cleartype font(ex. Consolas) rendering is ugly.
> - v40: MS legacy font (ex. Tahoma) rendering is ugly. Some fonts return
> the wrong values even for the glyph metrics.
>
> Is this a Freetype bug? Basically NOT.

I think this went away from original reported issue, and the patch is 
basically the same workaround suggested there.

The question is what changed in freetype 2.7 that caused broken 
rendering in wine's Tahoma, as an example that's easy to test.

Not that wine fonts don't use freetype instructions, so it's not obvious 
why interpreter mode could make a difference if we're still going to use 
embedded bitmaps for small sizes and original outline for the rest.

>
> https://docs.microsoft.com/en-us/typography/opentype/spec/tt_instructions#get-information
>
> The bytecode interptreter is a stack-based virtual maching the interprets
> the truetype bytecode instructions. Ths bytecode program receives the
> interpreter version information through the GETINFO instruction. GETINFO
> also provided the information of the fontsmoothing, cleartype, etc.
> The bytecode program actually changes the location of the glyph points
> based on this information.
>
> So, what looks like a bug above is that the wrong version information was
> delivered to the bytecode program. To determine this version value, this
> patch use the gasp table version. This idea is inspired by the following
> documentation.
>
> https://www.freetype.org/freetype2/docs/reference/ft2-properties.html#TT_INTERPRETER_VERSION_XXX
> --
> Note that ‘Gray ClearType’ is essentially the same as v1.6's
> grayscale rendering. However, the GETINFO instruction handles it
> differently: v1.6 returns bit 12 (hinting for grayscale), while v2.1
> returns bits 13 (hinting for ClearType), 18 (symmetrical smoothing), and
> 19 (Gray ClearType). Also, this mode respects bits 2 and 3 for the
> version 1 gasp table exclusively (like Color ClearType), while v1.6 only
> respects the values of version 0 (bits 0 and 1).
> --
> I think the maximum value that can be applied to the gasp version 0 font
> is the interpreter version 37.
>
> The Freetype interpreter version 38 includes tweaks based on the font
> names. I was able to use the v38 by modifying the build option of the
> Freetype.
> #define TT_CONFIG_OPTION_SUBPIXEL_HINTING     ( 1 | 2 )
>
> This allows the gasp version 0 fonts to be rendered more similar to the
> Windows old cleartype in the subpixel rendering mode. However, this is
> not applied because the build option must be modified and the Freetype
> document is marked as a feature to be deleted.
>
> To quickly check changes with the Freetype version up, I have added the
> WINE_GDI_PROPERTIES code.
> WINE_GDI_PROPERTIES="truetype:interpreter-version=35" winecfg
>
>   dlls/gdi32/freetype.c | 104 ++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 99 insertions(+), 5 deletions(-)
>
> diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
> index 07de6f2f6c..dd94d22db5 100644
> --- a/dlls/gdi32/freetype.c
> +++ b/dlls/gdi32/freetype.c
> @@ -130,6 +130,10 @@ typedef struct
>   } FT_Version_t;
>   static FT_Version_t FT_Version;
>   static DWORD FT_SimpleVersion;
> +static FT_UInt forced_interpreter_version = 0;
> +static BOOL interpreter_v35_supported = FALSE;
> +static BOOL interpreter_v38_supported = FALSE;
> +static BOOL interpreter_v40_supported = FALSE;
>   
>   static void *ft_handle = NULL;
>   
> @@ -158,6 +162,8 @@ MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
>   MAKE_FUNCPTR(FT_Outline_Get_CBox);
>   MAKE_FUNCPTR(FT_Outline_Transform);
>   MAKE_FUNCPTR(FT_Outline_Translate);
> +MAKE_FUNCPTR(FT_Property_Get);
> +MAKE_FUNCPTR(FT_Property_Set);
>   MAKE_FUNCPTR(FT_Render_Glyph);
>   MAKE_FUNCPTR(FT_Set_Charmap);
>   MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
> @@ -399,6 +405,7 @@ struct tagGdiFont {
>       DWORD total_kern_pairs;
>       KERNINGPAIR *kern_pairs;
>       struct list child_fonts;
> +    FT_UInt interpreter_version;
>   
>       /* the following members can be accessed without locking, they are never modified after creation */
>       FT_Face ft_face;
> @@ -4101,6 +4108,49 @@ static void update_font_info(void)
>       }
>   }
>   
> +static void set_forced_interpreter_version(void)
> +{
> +    static const char property_name[] = "truetype:interpreter-version=";
> +    const char *env;
> +
> +    env = getenv( "WINE_GDI_PROPERTIES" );
> +    if ( env && (env = strstr( env, property_name )) )
> +    {
> +        forced_interpreter_version = atoi( env + sizeof(property_name) - 1 );
> +
> +        TRACE( "forced_interpreter_version = %d\n" , forced_interpreter_version );
> +    }
> +}

I don't think we want that.

> +
> +static void diagnose_freetype(void)
> +{
> +    if (pFT_Property_Set && pFT_Property_Get)
> +    {
> +        FT_UInt set_version, get_version;
> +
> +        set_version = 35;
> +        get_version = 0;
> +        pFT_Property_Set( library, "truetype", "interpreter-version", &set_version );
> +        pFT_Property_Get( library, "truetype", "interpreter-version", &get_version );
> +        if (get_version == set_version)
> +            interpreter_v35_supported = TRUE;
> +
> +        set_version = 38;
> +        get_version = 0;
> +        pFT_Property_Set( library, "truetype", "interpreter-version", &set_version );
> +        pFT_Property_Get( library, "truetype", "interpreter-version", &get_version );
> +        if (get_version == set_version)
> +            interpreter_v38_supported = TRUE;
> +
> +        set_version = 40;
> +        get_version = 0;
> +        pFT_Property_Set( library, "truetype", "interpreter-version", &set_version );
> +        pFT_Property_Get( library, "truetype", "interpreter-version", &get_version );
> +        if (get_version == set_version)
> +            interpreter_v40_supported = TRUE;
> +    }
> +}
> +

Have you actually tested older freetype versions? E.g. does ftview with 
wine's Tahoma show same corruption or not.





More information about the wine-devel mailing list