fc-match.c revision a6844aab
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 Keith Packard not be used in 11 * advertising or publicity pertaining to distribution of the software without 12 * specific, written prior permission. Keith Packard makes 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 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 (!FcInit ()) 147 { 148 fprintf (stderr, "Can't init font config library\n"); 149 return 1; 150 } 151 if (argv[i]) 152 { 153 pat = FcNameParse ((FcChar8 *) argv[i]); 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 for (j = 0; j < font_patterns->nfont; j++) 179 { 180 FcPattern *font_pattern; 181 182 font_pattern = FcFontRenderPrepare (NULL, pat, font_patterns->fonts[j]); 183 if (font_pattern) 184 FcFontSetAdd (fs, font_pattern); 185 } 186 187 FcFontSetSortDestroy (font_patterns); 188 } 189 else 190 { 191 FcPattern *match; 192 match = FcFontMatch (0, pat, &result); 193 if (match) 194 FcFontSetAdd (fs, match); 195 } 196 FcPatternDestroy (pat); 197 198 if (fs) 199 { 200 int j; 201 202 for (j = 0; j < fs->nfont; j++) 203 { 204 FcPattern *font; 205 206 font = FcPatternFilter (fs->fonts[j], os); 207 208 if (verbose) 209 { 210 FcPatternPrint (font); 211 } 212 else if (format) 213 { 214 FcChar8 *s; 215 216 s = FcPatternFormat (font, format); 217 if (s) 218 { 219 printf ("%s", s); 220 free (s); 221 } 222 } 223 else if (os) 224 { 225 FcChar8 *str; 226 str = FcNameUnparse (font); 227 printf ("%s\n", str); 228 free (str); 229 } 230 else 231 { 232 FcChar8 *family; 233 FcChar8 *style; 234 FcChar8 *file; 235 236 if (FcPatternGetString (font, FC_FILE, 0, &file) != FcResultMatch) 237 file = (FcChar8 *) "<unknown filename>"; 238 else 239 { 240 FcChar8 *slash = (FcChar8 *) strrchr ((char *) file, '/'); 241 if (slash) 242 file = slash+1; 243 } 244 if (FcPatternGetString (font, FC_FAMILY, 0, &family) != FcResultMatch) 245 family = (FcChar8 *) "<unknown family>"; 246 if (FcPatternGetString (font, FC_STYLE, 0, &style) != FcResultMatch) 247 style = (FcChar8 *) "<unknown style>"; 248 249 printf ("%s: \"%s\" \"%s\"\n", file, family, style); 250 } 251 252 FcPatternDestroy (font); 253 } 254 FcFontSetDestroy (fs); 255 } 256 257 if (os) 258 FcObjectSetDestroy (os); 259 260 FcFini (); 261 262 return 0; 263} 264