Re: FcPattern Gotcha
Lawrence D'Oliveiro <[email protected]>
| Newsgroups | gmane.comp.fonts.fontconfig |
|---|---|
| Organization | Geek Central |
| Message-ID | <[email protected]> |
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.
_______________________________________________
Fontconfig mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/fontconfig
fc_pattern_2.c
(text/x-c++src, 3.2 KB)
/*
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*/