fcdir.c revision ca08ab68
1/* 2 * fontconfig/src/fcdir.c 3 * 4 * Copyright © 2000 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#include "fcint.h" 26#include <dirent.h> 27 28FcBool 29FcFileIsDir (const FcChar8 *file) 30{ 31 struct stat statb; 32 33 if (FcStat (file, &statb) != 0) 34 return FcFalse; 35 return S_ISDIR(statb.st_mode); 36} 37 38static FcBool 39FcFileScanFontConfig (FcFontSet *set, 40 FcBlanks *blanks, 41 const FcChar8 *file, 42 FcConfig *config) 43{ 44 FcPattern *font; 45 FcBool ret = FcTrue; 46 int id; 47 int count = 0; 48 49 id = 0; 50 do 51 { 52 font = 0; 53 /* 54 * Nothing in the cache, scan the file 55 */ 56 if (FcDebug () & FC_DBG_SCAN) 57 { 58 printf ("\tScanning file %s...", file); 59 fflush (stdout); 60 } 61 font = FcFreeTypeQuery (file, id, blanks, &count); 62 if (FcDebug () & FC_DBG_SCAN) 63 printf ("done\n"); 64 65 /* 66 * Edit pattern with user-defined rules 67 */ 68 if (font && config && !FcConfigSubstitute (config, font, FcMatchScan)) 69 { 70 FcPatternDestroy (font); 71 font = NULL; 72 ret = FcFalse; 73 } 74 75 /* 76 * Add the font 77 */ 78 if (font) 79 { 80 if (FcDebug() & FC_DBG_SCANV) 81 { 82 printf ("Final font pattern:\n"); 83 FcPatternPrint (font); 84 } 85 if (!FcFontSetAdd (set, font)) 86 { 87 FcPatternDestroy (font); 88 font = NULL; 89 ret = FcFalse; 90 } 91 } 92 else if (font) 93 FcPatternDestroy (font); 94 id++; 95 } while (font && ret && id < count); 96 return ret; 97} 98 99FcBool 100FcFileScanConfig (FcFontSet *set, 101 FcStrSet *dirs, 102 FcBlanks *blanks, 103 const FcChar8 *file, 104 FcConfig *config) 105{ 106 if (FcFileIsDir (file)) 107 return FcStrSetAdd (dirs, file); 108 else 109 return FcFileScanFontConfig (set, blanks, file, config); 110} 111 112FcBool 113FcFileScan (FcFontSet *set, 114 FcStrSet *dirs, 115 FcFileCache *cache, /* XXX unused */ 116 FcBlanks *blanks, 117 const FcChar8 *file, 118 FcBool force) 119{ 120 return FcFileScanConfig (set, dirs, blanks, file, FcConfigGetCurrent ()); 121} 122 123/* 124 * Strcmp helper that takes pointers to pointers, copied from qsort(3) manpage 125 */ 126static int 127cmpstringp(const void *p1, const void *p2) 128{ 129 return strcmp(* (char **) p1, * (char **) p2); 130} 131 132FcBool 133FcDirScanConfig (FcFontSet *set, 134 FcStrSet *dirs, 135 FcBlanks *blanks, 136 const FcChar8 *dir, 137 FcBool force, /* XXX unused */ 138 FcConfig *config) 139{ 140 DIR *d; 141 struct dirent *e; 142 FcStrSet *files; 143 FcChar8 *file; 144 FcChar8 *base; 145 FcBool ret = FcTrue; 146 int i; 147 148 if (!force) 149 return FcFalse; 150 151 if (!set && !dirs) 152 return FcTrue; 153 154 if (!blanks) 155 blanks = FcConfigGetBlanks (config); 156 157 /* freed below */ 158 file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1); 159 if (!file) { 160 ret = FcFalse; 161 goto bail; 162 } 163 164 strcpy ((char *) file, (char *) dir); 165 strcat ((char *) file, "/"); 166 base = file + strlen ((char *) file); 167 168 if (FcDebug () & FC_DBG_SCAN) 169 printf ("\tScanning dir %s\n", dir); 170 171 d = opendir ((char *) dir); 172 if (!d) 173 { 174 /* Don't complain about missing directories */ 175 if (errno != ENOENT) 176 ret = FcFalse; 177 goto bail; 178 } 179 180 files = FcStrSetCreate (); 181 if (!files) 182 { 183 ret = FcFalse; 184 goto bail1; 185 } 186 while ((e = readdir (d))) 187 { 188 if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN) 189 { 190 strcpy ((char *) base, (char *) e->d_name); 191 if (!FcStrSetAdd (files, file)) { 192 ret = FcFalse; 193 goto bail2; 194 } 195 } 196 } 197 198 /* 199 * Sort files to make things prettier 200 */ 201 qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp); 202 203 /* 204 * Scan file files to build font patterns 205 */ 206 for (i = 0; i < files->num; i++) 207 FcFileScanConfig (set, dirs, blanks, files->strs[i], config); 208 209bail2: 210 FcStrSetDestroy (files); 211bail1: 212 closedir (d); 213bail: 214 if (file) 215 free (file); 216 217 return ret; 218} 219 220FcBool 221FcDirScan (FcFontSet *set, 222 FcStrSet *dirs, 223 FcFileCache *cache, /* XXX unused */ 224 FcBlanks *blanks, 225 const FcChar8 *dir, 226 FcBool force /* XXX unused */) 227{ 228 if (cache || !force) 229 return FcFalse; 230 231 return FcDirScanConfig (set, dirs, blanks, dir, force, FcConfigGetCurrent ()); 232} 233 234/* 235 * Scan the specified directory and construct a cache of its contents 236 */ 237FcCache * 238FcDirCacheScan (const FcChar8 *dir, FcConfig *config) 239{ 240 FcStrSet *dirs; 241 FcFontSet *set; 242 FcCache *cache = NULL; 243 struct stat dir_stat; 244 245 if (FcDebug () & FC_DBG_FONTSET) 246 printf ("cache scan dir %s\n", dir); 247 248 if (FcStatChecksum (dir, &dir_stat) < 0) 249 goto bail; 250 251 set = FcFontSetCreate(); 252 if (!set) 253 goto bail; 254 255 dirs = FcStrSetCreate (); 256 if (!dirs) 257 goto bail1; 258 259 /* 260 * Scan the dir 261 */ 262 if (!FcDirScanConfig (set, dirs, NULL, dir, FcTrue, config)) 263 goto bail2; 264 265 /* 266 * Build the cache object 267 */ 268 cache = FcDirCacheBuild (set, dir, &dir_stat, dirs); 269 if (!cache) 270 goto bail2; 271 272 /* 273 * Write out the cache file, ignoring any troubles 274 */ 275 FcDirCacheWrite (cache, config); 276 277 bail2: 278 FcStrSetDestroy (dirs); 279 bail1: 280 FcFontSetDestroy (set); 281 bail: 282 return cache; 283} 284 285/* 286 * Read (or construct) the cache for a directory 287 */ 288FcCache * 289FcDirCacheRead (const FcChar8 *dir, FcBool force, FcConfig *config) 290{ 291 FcCache *cache = NULL; 292 293 /* Try to use existing cache file */ 294 if (!force) 295 cache = FcDirCacheLoad (dir, config, NULL); 296 297 /* Not using existing cache file, construct new cache */ 298 if (!cache) 299 cache = FcDirCacheScan (dir, config); 300 301 return cache; 302} 303 304FcBool 305FcDirSave (FcFontSet *set, FcStrSet * dirs, const FcChar8 *dir) 306{ 307 return FcFalse; /* XXX deprecated */ 308} 309#define __fcdir__ 310#include "fcaliastail.h" 311#undef __fcdir__ 312