Re: FcPattern Gotcha

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

 



On Tue, 29 Nov 2016 16:30:35 +0900, Akira TAGOH wrote:

> Can you attach the example that can reproduce your issue?
> 
> FcNameParse() should generates the same FcPattern with the strings
> generated by FcNameUnparse().

OK, I have narrowed it down. Attached is the simplest C program I could
come up with to demonstrate the issue. Pass it a pattern string on the
command line, e.g.

    fc_pattern_2 sans-serif

and it will print out some information about what it found. Having
found a matching pattern, it calls FcNameUnparse to convert that to a
pattern string, followed by FcNameParse to convert the string back to a
pattern.

If the pattern includes the “charset” property, the FcNameParse call
fails, possibly even segfaults. Removing this property causes the parse
(and the subsequent match) to succeed. I helpfully put the call
“FcPatternDel(found_pat, FC_CHARSET);” inside an “if (true)” block, so
you can try changing it to “if (false)” to observe the effect.

I have libconfig 2.11.0 installed from the repo package on Debian
Unstable.
/*
    Try to investigate oddity with parsing/unparsing of Fontconfig patterns.

    Build command:
        gcc -o fc_pattern_2 -lfontconfig fc_pattern_2.c

    Usage:
        fc_pattern_2 «pat-string»
*/

#include <stdbool.h>
#include <iso646.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fontconfig/fontconfig.h>

static char *
    progname;
static int
    exit_status = 0;

int main
  (
    int argc,
    char ** argv
  )
  {
    FcPattern * find_pat = 0;
    FcPattern * found_pat = 0;
    char * pat_str = 0;
    FcPattern * parsed_pat = 0;
    FcPattern * found_pat_2 = 0;
    FcResult fc_result;
    progname = argv[0];
    do /*once*/
      {
        if (argc != 2)
          {
            fprintf(stderr, "Usage:\n\t%s «pat-string»\n", progname);
            exit_status = 1;
            break;
          } /*if*/
        find_pat = FcNameParse(argv[1]);
        if (find_pat == 0)
          {
            fprintf(stderr, "%s: initial FcNameParse failed\n", progname);
            exit_status = 3;
            break;
          } /*if*/
        if (not FcConfigSubstitute(0, find_pat, FcMatchPattern))
          {
            fprintf(stderr, "%s: FcConfigSubstitute failed\n", progname);
            exit_status = 3;
            break;
          } /*if*/
        FcDefaultSubstitute(find_pat);
        found_pat = FcFontMatch(0, find_pat, &fc_result);
        if (found_pat == 0)
          {
            fprintf(stderr, "%s: first FcFontMatch failed with status %d\n", progname, fc_result);
            exit_status = 3;
            break;
          } /*if*/
          {
            char * namestr;
            FcPatternGetString(found_pat, FC_FAMILY, 0, (FcChar8 **)&namestr);
            fprintf(stderr, "found font with family name â??%sâ??\n", namestr);
          }
        if (true)
          {
          /* if this is disabled, the following FcNameParse call will fail */
            FcPatternDel(found_pat, FC_CHARSET);
          } /*if*/
        pat_str = FcNameUnparse(found_pat);
        if (pat_str == 0)
          {
            fprintf(stderr, "%s: FcNameUnparse failed\n", progname);
            exit_status = 3;
            break;
          } /*if*/
        fprintf(stdout, "Found pat (%d): %s\n", fc_result, pat_str);
        parsed_pat = FcNameParse(pat_str);
        if (parsed_pat == 0)
          {
            fprintf(stderr, "%s: second FcNameParse failed\n", progname);
            exit_status = 3;
            break;
          } /*if*/
        found_pat_2 = FcFontMatch(0, find_pat, &fc_result);
        if (found_pat_2 == 0)
          {
            fprintf(stderr, "%s: second FcFontMatch failed with status %d\n", progname, fc_result);
            exit_status = 3;
            break;
          } /*if*/
          {
            char * namestr;
            FcPatternGetString(found_pat_2, FC_FAMILY, 0, (FcChar8 **)&namestr);
            fprintf(stderr, "found second font with family name â??%sâ??\n", namestr);
          }
      }
    while (false);
    FcPatternDestroy(found_pat_2);
    FcPatternDestroy(parsed_pat);
    free(pat_str);
    FcPatternDestroy(found_pat);
    FcPatternDestroy(find_pat);
    return
        exit_status;
  } /*main*/
_______________________________________________
Fontconfig mailing list
Fontconfig@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/fontconfig

[Index of Archives]     [Fedora Fonts]     [Fedora Users]     [Fedora Cloud]     [Kernel]     [Fedora Packaging]     [Fedora Desktop]     [PAM]     [Gimp Graphics Editor]     [Yosemite News]

  Powered by Linux