Subject: bug#52888: 29.0.50; font_{delete_unmatched,score} do not handle nil FONT_WEIGHT_INDEX

From: Eli Zaretskii <[email-masked]>
Date: Wed, 05 Jan 2022 14:37:56 +0200

> From: Sean Whitton <[email-masked]>
> Date: Tue, 04 Jan 2022 19:10:46 -0700
> 
> I received a helpful reply from Akira TAGOH on the fontconfig list.  The
> problematic entries are not in fact additional font weights available to
> Emacs, but meta or virtual entries from which applications can extract
> information about the range of weights provided by the variable weight
> .ttf file.
> 
> As we do not need to know the range of weights explicitly, the virtual
> entries are no use to us.  We can just skip over them and process the
> non-virtual FcPattern entries we get for each weight.  I'm attaching a
> patch which detects these virtual entries and skips over them.

Thanks, very good news!

> Maybe we could revert and replace the temporary fix with my patch?

According to what I see in the documentation, FcPatternGetRange exists
only since version 2.11.91 of Fontconfig, whereas we support 2.2.0 and
up.  So we cannot unconditionally use that API, and some part of the
temporary solution will have to be left in the source.  I'd need to
see the final patch with that in mind, before I can decide whether it
is simple/safe enough for the release branch.

> --- a/src/ftfont.c
> +++ b/src/ftfont.c
> @@ -184,11 +184,22 @@ ftfont_pattern_entity (FcPattern *p, Lisp_Object extra)
>    int numeric;
>    double dbl;
>    FcBool b;
> +  FcRange *range;
>  
>    if (FcPatternGetString (p, FC_FILE, 0, &str) != FcResultMatch)
>      return Qnil;
>    if (FcPatternGetInteger (p, FC_INDEX, 0, &idx) != FcResultMatch)
>      return Qnil;
> +  if (FcPatternGetRange (p, FC_WEIGHT, 0, &range) == FcResultMatch
> +      && FcPatternGetBool (p, FC_VARIABLE, 0, &b) == FcResultMatch
> +      && b == FcTrue)
> +    /* This is a virtual/meta FcPattern for a variable weight font,
> +       from which it is possible to extract an FcRange value
> +       specifying the minimum and maximum weights available in this
> +       file.  We don't need to know that information explicitly, so
> +       skip it.  We will be called with an FcPattern for each actually
> +       available, non-virtual weight.  */
> +    return Qnil;

I'm far from being an expert on Fontconfig programming, but the above
use of 'range' looks strange: it's a pointer that starts pointing to
some random (potentially invalid) address, and you pass its address to
FcPatternGetRange, which presumably assigns to it a valid point.  But
doesn't that valid pointer need to be released somehow after we use
it?  Or does it point to static area(s)?  I cannot find anything in
the Fontconfig documentation about the memory-management protocols for
FcValue objects, but maybe we should call FcValueDestroy on it after
we are done with it?  Or maybe this is not needed, as this passage
from the docs says near the end:

  void FcValueDestroy (FcValue v)
      Frees any memory referenced by `v'. Values of type FcTypeString,
      FcTypeMatrix and FcTypeCharSet reference memory, the other types
      do not.

Thanks.