fc-match.c revision 6fc018e4
1/* 2 * fontconfig/fc-match/fc-match.c 3 * 4 * Copyright © 2003 Keith Packard 5 * 6 * Permission to use, copy, modify, distribute, and sell this software and its 7 * documentation for any purpose is hereby granted without fee, provided that 8 * the above copyright notice appear in all copies and that both that 9 * copyright notice and this permission notice appear in supporting 10 * documentation, and that the name of the author(s) not be used in 11 * advertising or publicity pertaining to distribution of the software without 12 * specific, written prior permission. The authors make no 13 * representations about the suitability of this software for any purpose. It 14 * is provided "as is" without express or implied warranty. 15 * 16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 * PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include <config.h> 27#else 28#ifdef linux 29#define HAVE_GETOPT_LONG 1 30#endif 31#define HAVE_GETOPT 1 32#endif 33 34#include <fontconfig/fontconfig.h> 35#include <stdio.h> 36#include <unistd.h> 37#include <stdlib.h> 38#include <string.h> 39 40#ifndef HAVE_GETOPT 41#define HAVE_GETOPT 0 42#endif 43#ifndef HAVE_GETOPT_LONG 44#define HAVE_GETOPT_LONG 0 45#endif 46 47#if HAVE_GETOPT_LONG 48#undef _GNU_SOURCE 49#define _GNU_SOURCE 50#include <getopt.h> 51static const struct option longopts[] = { 52 {"sort", 0, 0, 's'}, 53 {"all", 0, 0, 'a'}, 54 {"verbose", 0, 0, 'v'}, 55 {"format", 1, 0, 'f'}, 56 {"version", 0, 0, 'V'}, 57 {"help", 0, 0, 'h'}, 58 {NULL,0,0,0}, 59}; 60#else 61#if HAVE_GETOPT 62extern char *optarg; 63extern int optind, opterr, optopt; 64#endif 65#endif 66 67static void 68usage (char *program, int error) 69{ 70 FILE *file = error ? stderr : stdout; 71#if HAVE_GETOPT_LONG 72 fprintf (file, "usage: %s [-savVh] [-f FORMAT] [--sort] [--all] [--verbose] [--format=FORMAT] [--version] [--help] [pattern] {element...}\n", 73 program); 74#else 75 fprintf (file, "usage: %s [-savVh] [-f FORMAT] [pattern] {element...}\n", 76 program); 77#endif 78 fprintf (file, "List best font matching [pattern]\n"); 79 fprintf (file, "\n"); 80#if HAVE_GETOPT_LONG 81 fprintf (file, " -s, --sort display sorted list of matches\n"); 82 fprintf (file, " -a, --all display unpruned sorted list of matches\n"); 83 fprintf (file, " -v, --verbose display entire font pattern verbosely\n"); 84 fprintf (file, " -f, --format=FORMAT use the given output format\n"); 85 fprintf (file, " -V, --version display font config version and exit\n"); 86 fprintf (file, " -h, --help display this help and exit\n"); 87#else 88 fprintf (file, " -s, (sort) display sorted list of matches\n"); 89 fprintf (file, " -a (all) display unpruned sorted list of matches\n"); 90 fprintf (file, " -v (verbose) display entire font pattern verbosely\n"); 91 fprintf (file, " -f FORMAT (format) use the given output format\n"); 92 fprintf (file, " -V (version) display font config version and exit\n"); 93 fprintf (file, " -h (help) display this help and exit\n"); 94#endif 95 exit (error); 96} 97 98int 99main (int argc, char **argv) 100{ 101 int verbose = 0; 102 int sort = 0, all = 0; 103 const FcChar8 *format = NULL; 104 int i; 105 FcObjectSet *os = 0; 106 FcFontSet *fs; 107 FcPattern *pat; 108 FcResult result; 109#if HAVE_GETOPT_LONG || HAVE_GETOPT 110 int c; 111 112#if HAVE_GETOPT_LONG 113 while ((c = getopt_long (argc, argv, "asvf:Vh", longopts, NULL)) != -1) 114#else 115 while ((c = getopt (argc, argv, "asvf:Vh")) != -1) 116#endif 117 { 118 switch (c) { 119 case 'a': 120 all = 1; 121 break; 122 case 's': 123 sort = 1; 124 break; 125 case 'v': 126 verbose = 1; 127 break; 128 case 'f': 129 format = (FcChar8 *) strdup (optarg); 130 break; 131 case 'V': 132 fprintf (stderr, "fontconfig version %d.%d.%d\n", 133 FC_MAJOR, FC_MINOR, FC_REVISION); 134 exit (0); 135 case 'h': 136 usage (argv[0], 0); 137 default: 138 usage (argv[0], 1); 139 } 140 } 141 i = optind; 142#else 143 i = 1; 144#endif 145 146 if (argv[i]) 147 { 148 pat = FcNameParse ((FcChar8 *) argv[i]); 149 if (!pat) 150 { 151 fputs ("Unable to parse the pattern\n", stderr); 152 return 1; 153 } 154 while (argv[++i]) 155 { 156 if (!os) 157 os = FcObjectSetCreate (); 158 FcObjectSetAdd (os, argv[i]); 159 } 160 } 161 else 162 pat = FcPatternCreate (); 163 164 if (!pat) 165 return 1; 166 167 FcConfigSubstitute (0, pat, FcMatchPattern); 168 FcDefaultSubstitute (pat); 169 170 fs = FcFontSetCreate (); 171 172 if (sort || all) 173 { 174 FcFontSet *font_patterns; 175 int j; 176 font_patterns = FcFontSort (0, pat, all ? FcFalse : FcTrue, 0, &result); 177 178 if (!font_patterns || font_patterns->nfont == 0) 179 { 180 fputs("No fonts installed on the system\n", stderr); 181 return 1; 182 } 183 for (j = 0; j < font_patterns->nfont; j++) 184 { 185 FcPattern *font_pattern; 186 187 font_pattern = FcFontRenderPrepare (NULL, pat, font_patterns->fonts[j]); 188 if (font_pattern) 189 FcFontSetAdd (fs, font_pattern); 190 } 191 192 FcFontSetSortDestroy (font_patterns); 193 } 194 else 195 { 196 FcPattern *match; 197 match = FcFontMatch (0, pat, &result); 198 if (match) 199 FcFontSetAdd (fs, match); 200 } 201 FcPatternDestroy (pat); 202 203 if (!format) 204 { 205 if (os) 206 format = (const FcChar8 *) "%{=unparse}\n"; 207 else 208 format = (const FcChar8 *) "%{=fcmatch}\n"; 209 } 210 211 if (fs) 212 { 213 int j; 214 215 for (j = 0; j < fs->nfont; j++) 216 { 217 FcPattern *font; 218 219 font = FcPatternFilter (fs->fonts[j], os); 220 221 if (verbose) 222 { 223 FcPatternPrint (font); 224 } 225 else 226 { 227 FcChar8 *s; 228 229 s = FcPatternFormat (font, format); 230 if (s) 231 { 232 printf ("%s", s); 233 FcStrFree (s); 234 } 235 } 236 237 FcPatternDestroy (font); 238 } 239 FcFontSetDestroy (fs); 240 } 241 242 if (os) 243 FcObjectSetDestroy (os); 244 245 FcFini (); 246 247 return 0; 248} 249