1c9710b42Smrg/* 2c9710b42Smrg * fontconfig/fc-validate/fc-validate.c 3c9710b42Smrg * 4c9710b42Smrg * Copyright © 2003 Keith Packard 5c9710b42Smrg * Copyright © 2012 Red Hat, Inc. 6c9710b42Smrg * Red Hat Author(s): Akira TAGOH 7c9710b42Smrg * 8c9710b42Smrg * Permission to use, copy, modify, distribute, and sell this software and its 9c9710b42Smrg * documentation for any purpose is hereby granted without fee, provided that 10c9710b42Smrg * the above copyright notice appear in all copies and that both that 11c9710b42Smrg * copyright notice and this permission notice appear in supporting 12c9710b42Smrg * documentation, and that the name of the author(s) not be used in 13c9710b42Smrg * advertising or publicity pertaining to distribution of the software without 14c9710b42Smrg * specific, written prior permission. The authors make no 15c9710b42Smrg * representations about the suitability of this software for any purpose. It 16c9710b42Smrg * is provided "as is" without express or implied warranty. 17c9710b42Smrg * 18c9710b42Smrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19c9710b42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 20c9710b42Smrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 21c9710b42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 22c9710b42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 23c9710b42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 24c9710b42Smrg * PERFORMANCE OF THIS SOFTWARE. 25c9710b42Smrg */ 26c9710b42Smrg 27c9710b42Smrg#ifdef HAVE_CONFIG_H 28c9710b42Smrg#include <config.h> 29c9710b42Smrg#else 30c9710b42Smrg#ifdef linux 31c9710b42Smrg#define HAVE_GETOPT_LONG 1 32c9710b42Smrg#endif 33c9710b42Smrg#define HAVE_GETOPT 1 34c9710b42Smrg#endif 35c9710b42Smrg 36c9710b42Smrg#include <fontconfig/fontconfig.h> 37c9710b42Smrg#include <fontconfig/fcfreetype.h> 38c9710b42Smrg#include <stdio.h> 39c9710b42Smrg#include <stdlib.h> 40c9710b42Smrg#include <string.h> 41c9710b42Smrg#include <locale.h> 42c9710b42Smrg 43a4e54154Smrg#ifdef HAVE_UNISTD_H 44a4e54154Smrg#include <unistd.h> 45a4e54154Smrg#endif 46a4e54154Smrg 47a32e9e42Smrg#ifdef ENABLE_NLS 48a32e9e42Smrg#include <libintl.h> 49a32e9e42Smrg#define _(x) (dgettext(GETTEXT_PACKAGE, x)) 50a32e9e42Smrg#else 51a32e9e42Smrg#define dgettext(d, s) (s) 52a32e9e42Smrg#define _(x) (x) 53a32e9e42Smrg#endif 54a32e9e42Smrg 55c9710b42Smrg#ifndef HAVE_GETOPT 56c9710b42Smrg#define HAVE_GETOPT 0 57c9710b42Smrg#endif 58c9710b42Smrg#ifndef HAVE_GETOPT_LONG 59c9710b42Smrg#define HAVE_GETOPT_LONG 0 60c9710b42Smrg#endif 61c9710b42Smrg 62c9710b42Smrg#if HAVE_GETOPT_LONG 63c9710b42Smrg#undef _GNU_SOURCE 64c9710b42Smrg#define _GNU_SOURCE 65c9710b42Smrg#include <getopt.h> 66c9710b42Smrgstatic const struct option longopts[] = { 67c9710b42Smrg {"index", 1, 0, 'i'}, 68c9710b42Smrg {"lang", 1, 0, 'l'}, 69c9710b42Smrg {"verbose", 0, 0, 'v'}, 70c9710b42Smrg {"version", 0, 0, 'V'}, 71c9710b42Smrg {"help", 0, 0, 'h'}, 72c9710b42Smrg {NULL,0,0,0}, 73c9710b42Smrg}; 74c9710b42Smrg#else 75c9710b42Smrg#if HAVE_GETOPT 76c9710b42Smrgextern char *optarg; 77c9710b42Smrgextern int optind, opterr, optopt; 78c9710b42Smrg#endif 79c9710b42Smrg#endif 80c9710b42Smrg 81c9710b42Smrgstatic void 82c9710b42Smrgusage (char *program, int error) 83c9710b42Smrg{ 84c9710b42Smrg FILE *file = error ? stderr : stdout; 85c9710b42Smrg#if HAVE_GETOPT_LONG 86a32e9e42Smrg fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] [--index index] [--lang LANG] [--verbose] [--version] [--help] font-file...\n"), 87c9710b42Smrg program); 88c9710b42Smrg#else 89a32e9e42Smrg fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] font-file...\n"), 90c9710b42Smrg program); 91c9710b42Smrg#endif 92a32e9e42Smrg fprintf (file, _("Validate font files and print result\n")); 93c9710b42Smrg fprintf (file, "\n"); 94c9710b42Smrg#if HAVE_GETOPT_LONG 95a32e9e42Smrg fprintf (file, _(" -i, --index INDEX display the INDEX face of each font file only\n")); 96a32e9e42Smrg fprintf (file, _(" -l, --lang=LANG set LANG instead of current locale\n")); 97a32e9e42Smrg fprintf (file, _(" -v, --verbose show more detailed information\n")); 98a32e9e42Smrg fprintf (file, _(" -V, --version display font config version and exit\n")); 99a32e9e42Smrg fprintf (file, _(" -h, --help display this help and exit\n")); 100c9710b42Smrg#else 101a32e9e42Smrg fprintf (file, _(" -i INDEX (index) display the INDEX face of each font file only\n")); 102a32e9e42Smrg fprintf (file, _(" -l LANG (lang) set LANG instead of current locale\n")); 103a32e9e42Smrg fprintf (file, _(" -v (verbose) show more detailed information\n")); 104a32e9e42Smrg fprintf (file, _(" -V (version) display font config version and exit\n")); 105a32e9e42Smrg fprintf (file, _(" -h (help) display this help and exit\n")); 106c9710b42Smrg#endif 107c9710b42Smrg exit (error); 108c9710b42Smrg} 109c9710b42Smrg 110c9710b42Smrgint 111c9710b42Smrgmain (int argc, char **argv) 112c9710b42Smrg{ 113c9710b42Smrg int index_set = 0; 114c9710b42Smrg int set_index = 0; 115c9710b42Smrg FcChar8 *lang = NULL; 116c9710b42Smrg const FcCharSet *fcs_lang = NULL; 117c9710b42Smrg int err = 0; 118c9710b42Smrg int i; 119c9710b42Smrg FT_Library ftlib; 120c9710b42Smrg FcBool verbose = FcFalse; 121c9710b42Smrg#if HAVE_GETOPT_LONG || HAVE_GETOPT 122c9710b42Smrg int c; 123c9710b42Smrg 124c9710b42Smrg setlocale (LC_ALL, ""); 125c9710b42Smrg 126c9710b42Smrg#if HAVE_GETOPT_LONG 127c9710b42Smrg while ((c = getopt_long (argc, argv, "i:l:mVhv", longopts, NULL)) != -1) 128c9710b42Smrg#else 129c9710b42Smrg while ((c = getopt (argc, argv, "i:l:mVhv")) != -1) 130c9710b42Smrg#endif 131c9710b42Smrg { 132c9710b42Smrg switch (c) { 133c9710b42Smrg case 'i': 134c9710b42Smrg index_set = 1; 135c9710b42Smrg set_index = atoi (optarg); 136c9710b42Smrg break; 137c9710b42Smrg case 'l': 138c9710b42Smrg lang = (FcChar8 *) FcLangNormalize ((const FcChar8 *) optarg); 139c9710b42Smrg break; 140c9710b42Smrg case 'v': 141c9710b42Smrg verbose = FcTrue; 142c9710b42Smrg break; 143c9710b42Smrg case 'V': 144c9710b42Smrg fprintf (stderr, "fontconfig version %d.%d.%d\n", 145c9710b42Smrg FC_MAJOR, FC_MINOR, FC_REVISION); 146c9710b42Smrg exit (0); 147c9710b42Smrg case 'h': 148c9710b42Smrg usage (argv[0], 0); 149c9710b42Smrg default: 150c9710b42Smrg usage (argv[0], 1); 151c9710b42Smrg } 152c9710b42Smrg } 153c9710b42Smrg i = optind; 154c9710b42Smrg#else 155c9710b42Smrg i = 1; 156c9710b42Smrg verbose = FcTrue; 157c9710b42Smrg#endif 158c9710b42Smrg 159c9710b42Smrg if (i == argc) 160c9710b42Smrg usage (argv[0], 1); 161c9710b42Smrg 162c9710b42Smrg if (!lang) 163c9710b42Smrg lang = FcLangNormalize ((const FcChar8 *) setlocale (LC_CTYPE, NULL)); 164c9710b42Smrg 165c9710b42Smrg if (lang) 166c9710b42Smrg fcs_lang = FcLangGetCharSet (lang); 167c9710b42Smrg 168c9710b42Smrg if (FT_Init_FreeType (&ftlib)) 169c9710b42Smrg { 170a4e54154Smrg fprintf (stderr, _("Can't initialize FreeType library\n")); 171c9710b42Smrg return 1; 172c9710b42Smrg } 173c9710b42Smrg 174c9710b42Smrg for (; i < argc; i++) 175c9710b42Smrg { 176c9710b42Smrg int index; 177c9710b42Smrg 178c9710b42Smrg index = set_index; 179c9710b42Smrg 180c9710b42Smrg do { 181c9710b42Smrg FT_Face face; 182c9710b42Smrg FcCharSet *fcs, *fcs_sub; 183c9710b42Smrg 184c9710b42Smrg if (FT_New_Face (ftlib, argv[i], index, &face)) 185c9710b42Smrg { 186c9710b42Smrg if (!index_set && index > 0) 187c9710b42Smrg break; 188a32e9e42Smrg fprintf (stderr, _("Unable to open %s\n"), argv[i]); 189c9710b42Smrg err = 1; 190c9710b42Smrg } 191c9710b42Smrg else 192c9710b42Smrg { 193c9710b42Smrg FcChar32 count; 194c9710b42Smrg 195c9710b42Smrg fcs = FcFreeTypeCharSet (face, NULL); 196c9710b42Smrg fcs_sub = FcCharSetSubtract (fcs_lang, fcs); 197c9710b42Smrg 198c9710b42Smrg count = FcCharSetCount (fcs_sub); 199c9710b42Smrg if (count > 0) 200c9710b42Smrg { 201c9710b42Smrg FcChar32 ucs4, pos, map[FC_CHARSET_MAP_SIZE]; 202c9710b42Smrg 203a4e54154Smrg err = 1; 204a32e9e42Smrg printf (_("%s:%d Missing %d glyph(s) to satisfy the coverage for %s language\n"), 205c9710b42Smrg argv[i], index, count, lang); 206c9710b42Smrg 207c9710b42Smrg if (verbose) 208c9710b42Smrg { 209c9710b42Smrg for (ucs4 = FcCharSetFirstPage (fcs_sub, map, &pos); 210c9710b42Smrg ucs4 != FC_CHARSET_DONE; 211c9710b42Smrg ucs4 = FcCharSetNextPage (fcs_sub, map, &pos)) 212c9710b42Smrg { 213c9710b42Smrg int j; 214c9710b42Smrg 215c9710b42Smrg for (j = 0; j < FC_CHARSET_MAP_SIZE; j++) 216c9710b42Smrg { 217c9710b42Smrg FcChar32 bits = map[j]; 218c9710b42Smrg FcChar32 base = ucs4 + j * 32; 219c9710b42Smrg int b = 0; 220c9710b42Smrg 221c9710b42Smrg while (bits) 222c9710b42Smrg { 223c9710b42Smrg if (bits & 1) 224c9710b42Smrg printf (" 0x%04x\n", base + b); 225c9710b42Smrg bits >>= 1; 226c9710b42Smrg b++; 227c9710b42Smrg } 228c9710b42Smrg } 229c9710b42Smrg } 230c9710b42Smrg } 231c9710b42Smrg } 232c9710b42Smrg else 233c9710b42Smrg { 234a32e9e42Smrg printf (_("%s:%d Satisfy the coverage for %s language\n"), argv[i], index, lang); 235c9710b42Smrg } 236c9710b42Smrg 237c9710b42Smrg FcCharSetDestroy (fcs); 238c9710b42Smrg FcCharSetDestroy (fcs_sub); 239c9710b42Smrg 240c9710b42Smrg FT_Done_Face (face); 241c9710b42Smrg } 242c9710b42Smrg 243c9710b42Smrg index++; 244c9710b42Smrg } while (index_set == 0); 245c9710b42Smrg } 246c9710b42Smrg 247c9710b42Smrg FT_Done_FreeType (ftlib); 248c9710b42Smrg 249c9710b42Smrg if (lang) 250c9710b42Smrg FcStrFree (lang); 251c9710b42Smrg 252c9710b42Smrg FcFini (); 253c9710b42Smrg return err; 254c9710b42Smrg} 255