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