[Fontconfig] Questionable usage of FcPatternAddInteger()

Fabian Greffrath fabian at greffrath.com
Fri Apr 27 05:25:15 PDT 2012


Dear fontconfig-devs,

I have a question about the proper use of FcPatternAddInteger() and 
friends to add specific information to a fontconfig pattern. Please 
have a look at the attached code, which is based on an excerpt from 
cups-filter's texttopdf filter.

It is supposed to read a fontconfig pattern from the command line, 
find the most appropriate candidates to match that pattern (just like 
"fc-match -s") and print them to stdout prefixed with "C:" for 
"candidate". The first candidate that is both monospaced and in a font 
format that allows for embedding in a PDF file (i.e. either TTF or 
CFF) is printed to stdout prefixed with "S" for "selection".

Now, the line in question is line 17, which calls 
FcPatternAddInteger() to "guide" fontconfig and add the information 
that we are looking for monospaced fonts to "pattern". However, this 
line does not seem to do what is expected. First, there are still a 
lot of fonts returned by FcFontSort() that are non-monospaced (remove 
the "break;" commands to see them all) and second, the list of fonts 
returned by FcFontSort() is slightly puzzled depending on the 
FcPatternAddInteger() call being commented out or not.

This has lead to a bug reported in Debian [1] that occured when 
Liberation-Mono was the only installed monospaced Truetype font and 
the queried pattern was "FreeMono". I believe that removing the 
FcPatternAddInteger() call fixes this issue (it did on my system, but 
the OP hasn't answered yet).

But then I am not sure what else this command is supposed to do. It 
does not restrict the list of candidates returned by FcFontSort() to 
monospaced fonts, even if this requirement should get added to the 
pattern by means of FcPatternAddInteger(). Furthermore, it shuffles 
the list of candidates returned by FcFontSort() in a way that the most 
obvious installed monospaced Truetype fint is not part of that list. 
so what is the purpose of FcPatternAddInteger() again?

Best Regards,
Fabian Greffrath

[1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=670055

--

#include <stdio.h>
#include <fontconfig/fontconfig.h>

int main (int argc, char *argv[])
{
char *font = argv[1];
FcPattern *pattern;
FcFontSet *candidates;
FcChar8   *fontname = NULL;
int i;

if (!font)
	return 1;

FcInit ();
pattern = FcNameParse ((const FcChar8 *)font);
FcPatternAddInteger (pattern, FC_SPACING, FC_MONO);
FcConfigSubstitute (0, pattern, FcMatchPattern);
FcDefaultSubstitute (pattern);

candidates = FcFontSort (0, pattern, FcTrue, 0, 0);
FcPatternDestroy (pattern);

for (i = 0; i < candidates->nfont; i++) {
	FcChar8 *fontformat=NULL;
	int spacing=0;
	FcPatternGetString  (candidates->fonts[i], FC_FONTFORMAT, 0, 
&fontformat);
	FcPatternGetInteger (candidates->fonts[i], FC_SPACING,    0, &spacing);

	printf ("C: %s\n", FcPatternFormat (candidates->fonts[i], (const 
FcChar8 *)"%{file|cescape}"));

	if ( (fontformat)&&(spacing == FC_MONO) ) {
		if (strcmp((const char *)fontformat, "TrueType") == 0) {
		  fontname = FcPatternFormat (candidates->fonts[i], (const FcChar8 
*)"%{file|cescape}/%{index}");
		  break;
		} else if (strcmp((const char *)fontformat, "CFF") == 0) {
		  fontname = FcPatternFormat (candidates->fonts[i], (const FcChar8 
*)"%{file|cescape}");
		  break;
		}
	}
}
FcFontSetDestroy (candidates);

if (fontname)
	printf("S: %s\n", fontname);

return 0;
}



More information about the Fontconfig mailing list