fontdir.c revision a96d7823
1a96d7823Smrg/* 2a96d7823Smrg 3a96d7823SmrgCopyright 1991, 1998 The Open Group 4a96d7823Smrg 5a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its 6a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that 7a96d7823Smrgthe above copyright notice appear in all copies and that both that 8a96d7823Smrgcopyright notice and this permission notice appear in supporting 9a96d7823Smrgdocumentation. 10a96d7823Smrg 11a96d7823SmrgThe above copyright notice and this permission notice shall be included in 12a96d7823Smrgall copies or substantial portions of the Software. 13a96d7823Smrg 14a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15a96d7823SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16a96d7823SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17a96d7823SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18a96d7823SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19a96d7823SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20a96d7823Smrg 21a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall not be 22a96d7823Smrgused in advertising or otherwise to promote the sale, use or other dealings 23a96d7823Smrgin this Software without prior written authorization from The Open Group. 24a96d7823Smrg 25a96d7823Smrg*/ 26a96d7823Smrg 27a96d7823Smrg/* 28a96d7823Smrg * Author: Keith Packard, MIT X Consortium 29a96d7823Smrg */ 30a96d7823Smrg 31a96d7823Smrg#ifdef HAVE_CONFIG_H 32a96d7823Smrg#include <config.h> 33a96d7823Smrg#endif 34a96d7823Smrg#include "libxfontint.h" 35a96d7823Smrg#include <X11/fonts/fntfilst.h> 36a96d7823Smrg#include <X11/keysym.h> 37a96d7823Smrg 38a96d7823Smrg#if HAVE_STDINT_H 39a96d7823Smrg#include <stdint.h> 40a96d7823Smrg#elif !defined(INT32_MAX) 41a96d7823Smrg#define INT32_MAX 0x7fffffff 42a96d7823Smrg#endif 43a96d7823Smrg 44a96d7823SmrgBool 45a96d7823SmrgFontFileInitTable (FontTablePtr table, int size) 46a96d7823Smrg{ 47a96d7823Smrg if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec))) 48a96d7823Smrg return FALSE; 49a96d7823Smrg if (size) 50a96d7823Smrg { 51a96d7823Smrg table->entries = malloc(sizeof(FontEntryRec) * size); 52a96d7823Smrg if (!table->entries) 53a96d7823Smrg return FALSE; 54a96d7823Smrg } 55a96d7823Smrg else 56a96d7823Smrg table->entries = 0; 57a96d7823Smrg table->used = 0; 58a96d7823Smrg table->size = size; 59a96d7823Smrg table->sorted = FALSE; 60a96d7823Smrg return TRUE; 61a96d7823Smrg} 62a96d7823Smrg 63a96d7823Smrgvoid 64a96d7823SmrgFontFileFreeEntry (FontEntryPtr entry) 65a96d7823Smrg{ 66a96d7823Smrg FontScalableExtraPtr extra; 67a96d7823Smrg int i; 68a96d7823Smrg 69a96d7823Smrg if (entry->name.name) 70a96d7823Smrg free(entry->name.name); 71a96d7823Smrg entry->name.name = NULL; 72a96d7823Smrg 73a96d7823Smrg switch (entry->type) 74a96d7823Smrg { 75a96d7823Smrg case FONT_ENTRY_SCALABLE: 76a96d7823Smrg free (entry->u.scalable.fileName); 77a96d7823Smrg extra = entry->u.scalable.extra; 78a96d7823Smrg for (i = 0; i < extra->numScaled; i++) 79a96d7823Smrg if (extra->scaled[i].vals.ranges) 80a96d7823Smrg free (extra->scaled[i].vals.ranges); 81a96d7823Smrg free (extra->scaled); 82a96d7823Smrg free (extra); 83a96d7823Smrg break; 84a96d7823Smrg case FONT_ENTRY_BITMAP: 85a96d7823Smrg free (entry->u.bitmap.fileName); 86a96d7823Smrg entry->u.bitmap.fileName = NULL; 87a96d7823Smrg break; 88a96d7823Smrg case FONT_ENTRY_ALIAS: 89a96d7823Smrg free (entry->u.alias.resolved); 90a96d7823Smrg entry->u.alias.resolved = NULL; 91a96d7823Smrg break; 92a96d7823Smrg } 93a96d7823Smrg} 94a96d7823Smrg 95a96d7823Smrgvoid 96a96d7823SmrgFontFileFreeTable (FontTablePtr table) 97a96d7823Smrg{ 98a96d7823Smrg int i; 99a96d7823Smrg 100a96d7823Smrg for (i = 0; i < table->used; i++) 101a96d7823Smrg FontFileFreeEntry (&table->entries[i]); 102a96d7823Smrg free (table->entries); 103a96d7823Smrg} 104a96d7823Smrg 105a96d7823SmrgFontDirectoryPtr 106a96d7823SmrgFontFileMakeDir(const char *dirName, int size) 107a96d7823Smrg{ 108a96d7823Smrg FontDirectoryPtr dir; 109a96d7823Smrg int dirlen; 110a96d7823Smrg int needslash = 0; 111a96d7823Smrg const char *attrib; 112a96d7823Smrg int attriblen; 113a96d7823Smrg 114a96d7823Smrg#if !defined(WIN32) 115a96d7823Smrg attrib = strchr(dirName, ':'); 116a96d7823Smrg#else 117a96d7823Smrg /* OS/2 uses the colon in the drive letter descriptor, skip this */ 118a96d7823Smrg attrib = strchr(dirName+2, ':'); 119a96d7823Smrg#endif 120a96d7823Smrg if (attrib) { 121a96d7823Smrg dirlen = attrib - dirName; 122a96d7823Smrg attriblen = strlen(attrib); 123a96d7823Smrg } else { 124a96d7823Smrg dirlen = strlen(dirName); 125a96d7823Smrg attriblen = 0; 126a96d7823Smrg } 127a96d7823Smrg if (dirName[dirlen - 1] != '/') 128a96d7823Smrg#ifdef NCD 129a96d7823Smrg if (dirlen) /* leave out slash for builtins */ 130a96d7823Smrg#endif 131a96d7823Smrg needslash = 1; 132a96d7823Smrg dir = malloc(sizeof *dir + dirlen + needslash + 1 + 133a96d7823Smrg (attriblen ? attriblen + 1 : 0)); 134a96d7823Smrg if (!dir) 135a96d7823Smrg return (FontDirectoryPtr)0; 136a96d7823Smrg if (!FontFileInitTable (&dir->scalable, 0)) 137a96d7823Smrg { 138a96d7823Smrg free (dir); 139a96d7823Smrg return (FontDirectoryPtr)0; 140a96d7823Smrg } 141a96d7823Smrg if (!FontFileInitTable (&dir->nonScalable, size)) 142a96d7823Smrg { 143a96d7823Smrg FontFileFreeTable (&dir->scalable); 144a96d7823Smrg free (dir); 145a96d7823Smrg return (FontDirectoryPtr)0; 146a96d7823Smrg } 147a96d7823Smrg dir->directory = (char *) (dir + 1); 148a96d7823Smrg dir->dir_mtime = 0; 149a96d7823Smrg dir->alias_mtime = 0; 150a96d7823Smrg if (attriblen) 151a96d7823Smrg dir->attributes = dir->directory + dirlen + needslash + 1; 152a96d7823Smrg else 153a96d7823Smrg dir->attributes = NULL; 154a96d7823Smrg strncpy(dir->directory, dirName, dirlen); 155a96d7823Smrg dir->directory[dirlen] = '\0'; 156a96d7823Smrg if (dir->attributes) 157a96d7823Smrg strcpy(dir->attributes, attrib); 158a96d7823Smrg if (needslash) 159a96d7823Smrg strcat(dir->directory, "/"); 160a96d7823Smrg return dir; 161a96d7823Smrg} 162a96d7823Smrg 163a96d7823Smrgvoid 164a96d7823SmrgFontFileFreeDir (FontDirectoryPtr dir) 165a96d7823Smrg{ 166a96d7823Smrg FontFileFreeTable (&dir->scalable); 167a96d7823Smrg FontFileFreeTable (&dir->nonScalable); 168a96d7823Smrg free(dir); 169a96d7823Smrg} 170a96d7823Smrg 171a96d7823SmrgFontEntryPtr 172a96d7823SmrgFontFileAddEntry(FontTablePtr table, FontEntryPtr prototype) 173a96d7823Smrg{ 174a96d7823Smrg FontEntryPtr entry; 175a96d7823Smrg int newsize; 176a96d7823Smrg 177a96d7823Smrg /* can't add entries to a sorted table, pointers get broken! */ 178a96d7823Smrg if (table->sorted) 179a96d7823Smrg return (FontEntryPtr) 0; /* "cannot" happen */ 180a96d7823Smrg if (table->used == table->size) { 181a96d7823Smrg if (table->size >= ((INT32_MAX / sizeof(FontEntryRec)) - 100)) 182a96d7823Smrg /* If we've read so many entries we're going to ask for 2gb 183a96d7823Smrg or more of memory, something is so wrong with this font 184a96d7823Smrg directory that we should just give up before we overflow. */ 185a96d7823Smrg return NULL; 186a96d7823Smrg newsize = table->size + 100; 187a96d7823Smrg entry = realloc(table->entries, newsize * sizeof(FontEntryRec)); 188a96d7823Smrg if (!entry) 189a96d7823Smrg return (FontEntryPtr)0; 190a96d7823Smrg table->size = newsize; 191a96d7823Smrg table->entries = entry; 192a96d7823Smrg } 193a96d7823Smrg entry = &table->entries[table->used]; 194a96d7823Smrg *entry = *prototype; 195a96d7823Smrg entry->name.name = malloc(prototype->name.length + 1); 196a96d7823Smrg if (!entry->name.name) 197a96d7823Smrg return (FontEntryPtr)0; 198a96d7823Smrg memcpy (entry->name.name, prototype->name.name, prototype->name.length); 199a96d7823Smrg entry->name.name[entry->name.length] = '\0'; 200a96d7823Smrg table->used++; 201a96d7823Smrg return entry; 202a96d7823Smrg} 203a96d7823Smrg 204a96d7823Smrg/* 205a96d7823Smrg * Compare two strings just like strcmp, but preserve decimal integer 206a96d7823Smrg * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" < 207a96d7823Smrg * "iso10646-1". Strings are sorted as if sequences of digits were 208a96d7823Smrg * prefixed by a length indicator (i.e., does not ignore leading zeroes). 209a96d7823Smrg * 210a96d7823Smrg * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> 211a96d7823Smrg */ 212a96d7823Smrg#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071') 213a96d7823Smrg 214a96d7823Smrgstatic int strcmpn(const char *s1, const char *s2) 215a96d7823Smrg{ 216a96d7823Smrg int digits, predigits = 0; 217a96d7823Smrg const char *ss1, *ss2; 218a96d7823Smrg 219a96d7823Smrg while (1) { 220a96d7823Smrg if (*s1 == 0 && *s2 == 0) 221a96d7823Smrg return 0; 222a96d7823Smrg digits = Xisdigit(*s1) && Xisdigit(*s2); 223a96d7823Smrg if (digits && !predigits) { 224a96d7823Smrg ss1 = s1; 225a96d7823Smrg ss2 = s2; 226a96d7823Smrg while (Xisdigit(*ss1) && Xisdigit(*ss2)) 227a96d7823Smrg ss1++, ss2++; 228a96d7823Smrg if (!Xisdigit(*ss1) && Xisdigit(*ss2)) 229a96d7823Smrg return -1; 230a96d7823Smrg if (Xisdigit(*ss1) && !Xisdigit(*ss2)) 231a96d7823Smrg return 1; 232a96d7823Smrg } 233a96d7823Smrg if ((unsigned char)*s1 < (unsigned char)*s2) 234a96d7823Smrg return -1; 235a96d7823Smrg if ((unsigned char)*s1 > (unsigned char)*s2) 236a96d7823Smrg return 1; 237a96d7823Smrg predigits = digits; 238a96d7823Smrg s1++, s2++; 239a96d7823Smrg } 240a96d7823Smrg} 241a96d7823Smrg 242a96d7823Smrg 243a96d7823Smrgstatic int 244a96d7823SmrgFontFileNameCompare(const void* a, const void* b) 245a96d7823Smrg{ 246a96d7823Smrg FontEntryPtr a_name = (FontEntryPtr) a, 247a96d7823Smrg b_name = (FontEntryPtr) b; 248a96d7823Smrg 249a96d7823Smrg return strcmpn(a_name->name.name, b_name->name.name); 250a96d7823Smrg} 251a96d7823Smrg 252a96d7823Smrgvoid 253a96d7823SmrgFontFileSortTable (FontTablePtr table) 254a96d7823Smrg{ 255a96d7823Smrg if (!table->sorted) { 256a96d7823Smrg qsort((char *) table->entries, table->used, sizeof(FontEntryRec), 257a96d7823Smrg FontFileNameCompare); 258a96d7823Smrg table->sorted = TRUE; 259a96d7823Smrg } 260a96d7823Smrg} 261a96d7823Smrg 262a96d7823Smrgvoid 263a96d7823SmrgFontFileSortDir(FontDirectoryPtr dir) 264a96d7823Smrg{ 265a96d7823Smrg FontFileSortTable (&dir->scalable); 266a96d7823Smrg FontFileSortTable (&dir->nonScalable); 267a96d7823Smrg /* now that the table is fixed in size, swizzle the pointers */ 268a96d7823Smrg FontFileSwitchStringsToBitmapPointers (dir); 269a96d7823Smrg} 270a96d7823Smrg 271a96d7823Smrg/* 272a96d7823Smrg Given a Font Table, SetupWildMatch() sets up various pointers and state 273a96d7823Smrg information so the table can be searched for name(s) that match a given 274a96d7823Smrg fontname pattern -- which may contain wildcards. Under certain 275a96d7823Smrg circumstances, SetupWildMatch() will find the one table entry that 276a96d7823Smrg matches the pattern. If those circumstances do not pertain, 277a96d7823Smrg SetupWildMatch() returns a range within the the table that should be 278a96d7823Smrg searched for matching name(s). With the information established by 279a96d7823Smrg SetupWildMatch(), including state information in "private", the 280a96d7823Smrg PatternMatch() procedure is then used to test names in the range for a 281a96d7823Smrg match. 282a96d7823Smrg*/ 283a96d7823Smrg 284a96d7823Smrg#define isWild(c) ((c) == XK_asterisk || (c) == XK_question) 285a96d7823Smrg#define isDigit(c) (XK_0 <= (c) && (c) <= XK_9) 286a96d7823Smrg 287a96d7823Smrgstatic int 288a96d7823SmrgSetupWildMatch(FontTablePtr table, FontNamePtr pat, 289a96d7823Smrg int *leftp, int *rightp, int *privatep) 290a96d7823Smrg{ 291a96d7823Smrg int nDashes; 292a96d7823Smrg char c; 293a96d7823Smrg char *t; 294a96d7823Smrg char *firstWild; 295a96d7823Smrg char *firstDigit; 296a96d7823Smrg int first; 297a96d7823Smrg int center, 298a96d7823Smrg left, 299a96d7823Smrg right; 300a96d7823Smrg int result; 301a96d7823Smrg char *name; 302a96d7823Smrg 303a96d7823Smrg name = pat->name; 304a96d7823Smrg nDashes = pat->ndashes; 305a96d7823Smrg firstWild = 0; 306a96d7823Smrg firstDigit = 0; 307a96d7823Smrg t = name; 308a96d7823Smrg while ((c = *t++)) { 309a96d7823Smrg if (isWild(c)) { 310a96d7823Smrg if (!firstWild) 311a96d7823Smrg firstWild = t - 1; 312a96d7823Smrg } 313a96d7823Smrg if (isDigit(c)) { 314a96d7823Smrg if (!firstDigit) 315a96d7823Smrg firstDigit = t - 1; 316a96d7823Smrg } 317a96d7823Smrg } 318a96d7823Smrg left = 0; 319a96d7823Smrg right = table->used; 320a96d7823Smrg if (firstWild) 321a96d7823Smrg *privatep = nDashes; 322a96d7823Smrg else 323a96d7823Smrg *privatep = -1; 324a96d7823Smrg if (!table->sorted) { 325a96d7823Smrg *leftp = left; 326a96d7823Smrg *rightp = right; 327a96d7823Smrg return -1; 328a96d7823Smrg } else if (firstWild) { 329a96d7823Smrg if (firstDigit && firstDigit < firstWild) 330a96d7823Smrg first = firstDigit - name; 331a96d7823Smrg else 332a96d7823Smrg first = firstWild - name; 333a96d7823Smrg while (left < right) { 334a96d7823Smrg center = (left + right) / 2; 335a96d7823Smrg result = strncmp(name, table->entries[center].name.name, first); 336a96d7823Smrg if (result == 0) 337a96d7823Smrg break; 338a96d7823Smrg if (result < 0) 339a96d7823Smrg right = center; 340a96d7823Smrg else 341a96d7823Smrg left = center + 1; 342a96d7823Smrg } 343a96d7823Smrg *leftp = left; 344a96d7823Smrg *rightp = right; 345a96d7823Smrg return -1; 346a96d7823Smrg } else { 347a96d7823Smrg while (left < right) { 348a96d7823Smrg center = (left + right) / 2; 349a96d7823Smrg result = strcmpn(name, table->entries[center].name.name); 350a96d7823Smrg if (result == 0) 351a96d7823Smrg return center; 352a96d7823Smrg if (result < 0) 353a96d7823Smrg right = center; 354a96d7823Smrg else 355a96d7823Smrg left = center + 1; 356a96d7823Smrg } 357a96d7823Smrg *leftp = 1; 358a96d7823Smrg *rightp = 0; 359a96d7823Smrg return -1; 360a96d7823Smrg } 361a96d7823Smrg} 362a96d7823Smrg 363a96d7823Smrgstatic int 364a96d7823SmrgPatternMatch(char *pat, int patdashes, char *string, int stringdashes) 365a96d7823Smrg{ 366a96d7823Smrg char c, 367a96d7823Smrg t; 368a96d7823Smrg 369a96d7823Smrg if (stringdashes < patdashes) 370a96d7823Smrg return 0; 371a96d7823Smrg for (;;) { 372a96d7823Smrg switch (c = *pat++) { 373a96d7823Smrg case '*': 374a96d7823Smrg if (!(c = *pat++)) 375a96d7823Smrg return 1; 376a96d7823Smrg if (c == XK_minus) { 377a96d7823Smrg patdashes--; 378a96d7823Smrg for (;;) { 379a96d7823Smrg while ((t = *string++) != XK_minus) 380a96d7823Smrg if (!t) 381a96d7823Smrg return 0; 382a96d7823Smrg stringdashes--; 383a96d7823Smrg if (PatternMatch(pat, patdashes, string, stringdashes)) 384a96d7823Smrg return 1; 385a96d7823Smrg if (stringdashes == patdashes) 386a96d7823Smrg return 0; 387a96d7823Smrg } 388a96d7823Smrg } else { 389a96d7823Smrg for (;;) { 390a96d7823Smrg while ((t = *string++) != c) { 391a96d7823Smrg if (!t) 392a96d7823Smrg return 0; 393a96d7823Smrg if (t == XK_minus) { 394a96d7823Smrg if (stringdashes-- < patdashes) 395a96d7823Smrg return 0; 396a96d7823Smrg } 397a96d7823Smrg } 398a96d7823Smrg if (PatternMatch(pat, patdashes, string, stringdashes)) 399a96d7823Smrg return 1; 400a96d7823Smrg } 401a96d7823Smrg } 402a96d7823Smrg case '?': 403a96d7823Smrg if (*string++ == XK_minus) 404a96d7823Smrg stringdashes--; 405a96d7823Smrg break; 406a96d7823Smrg case '\0': 407a96d7823Smrg return (*string == '\0'); 408a96d7823Smrg case XK_minus: 409a96d7823Smrg if (*string++ == XK_minus) { 410a96d7823Smrg patdashes--; 411a96d7823Smrg stringdashes--; 412a96d7823Smrg break; 413a96d7823Smrg } 414a96d7823Smrg return 0; 415a96d7823Smrg default: 416a96d7823Smrg if (c == *string++) 417a96d7823Smrg break; 418a96d7823Smrg return 0; 419a96d7823Smrg } 420a96d7823Smrg } 421a96d7823Smrg} 422a96d7823Smrg 423a96d7823Smrgint 424a96d7823SmrgFontFileCountDashes (char *name, int namelen) 425a96d7823Smrg{ 426a96d7823Smrg int ndashes = 0; 427a96d7823Smrg 428a96d7823Smrg while (namelen--) 429a96d7823Smrg if (*name++ == '\055') /* avoid non ascii systems */ 430a96d7823Smrg ++ndashes; 431a96d7823Smrg return ndashes; 432a96d7823Smrg} 433a96d7823Smrg 434a96d7823Smrg/* exported in public API in <X11/fonts/fntfil.h> */ 435a96d7823Smrgchar * 436a96d7823SmrgFontFileSaveString (char *s) 437a96d7823Smrg{ 438a96d7823Smrg return strdup(s); 439a96d7823Smrg} 440a96d7823Smrg#define FontFileSaveString(s) strdup(s) 441a96d7823Smrg 442a96d7823SmrgFontEntryPtr 443a96d7823SmrgFontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat, 444a96d7823Smrg FontScalablePtr vals) 445a96d7823Smrg{ 446a96d7823Smrg int i, 447a96d7823Smrg start, 448a96d7823Smrg stop, 449a96d7823Smrg res, 450a96d7823Smrg private; 451a96d7823Smrg FontNamePtr name; 452a96d7823Smrg 453a96d7823Smrg if (!table->entries) 454a96d7823Smrg return NULL; 455a96d7823Smrg if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) 456a96d7823Smrg return &table->entries[i]; 457a96d7823Smrg for (i = start; i < stop; i++) { 458a96d7823Smrg name = &table->entries[i].name; 459a96d7823Smrg res = PatternMatch(pat->name, private, name->name, name->ndashes); 460a96d7823Smrg if (res > 0) 461a96d7823Smrg { 462a96d7823Smrg /* Check to see if enhancements requested are available */ 463a96d7823Smrg if (vals) 464a96d7823Smrg { 465a96d7823Smrg int vs = vals->values_supplied; 466a96d7823Smrg int cap; 467a96d7823Smrg 468a96d7823Smrg if (table->entries[i].type == FONT_ENTRY_SCALABLE) 469a96d7823Smrg cap = table->entries[i].u.scalable.renderer->capabilities; 470a96d7823Smrg else if (table->entries[i].type == FONT_ENTRY_ALIAS) 471a96d7823Smrg cap = ~0; /* Calling code will have to see if true */ 472a96d7823Smrg else 473a96d7823Smrg cap = 0; 474a96d7823Smrg if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || 475a96d7823Smrg (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && 476a96d7823Smrg !(cap & CAP_MATRIX)) || 477a96d7823Smrg ((vs & CHARSUBSET_SPECIFIED) && 478a96d7823Smrg !(cap & CAP_CHARSUBSETTING))) 479a96d7823Smrg continue; 480a96d7823Smrg } 481a96d7823Smrg return &table->entries[i]; 482a96d7823Smrg } 483a96d7823Smrg if (res < 0) 484a96d7823Smrg break; 485a96d7823Smrg } 486a96d7823Smrg return (FontEntryPtr)0; 487a96d7823Smrg} 488a96d7823Smrg 489a96d7823SmrgFontEntryPtr 490a96d7823SmrgFontFileFindNameInDir(FontTablePtr table, FontNamePtr pat) 491a96d7823Smrg{ 492a96d7823Smrg return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0); 493a96d7823Smrg} 494a96d7823Smrg 495a96d7823Smrgint 496a96d7823SmrgFontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max, 497a96d7823Smrg FontNamesPtr names, FontScalablePtr vals, 498a96d7823Smrg int alias_behavior, int *newmax) 499a96d7823Smrg{ 500a96d7823Smrg int i, 501a96d7823Smrg start, 502a96d7823Smrg stop, 503a96d7823Smrg res, 504a96d7823Smrg private; 505a96d7823Smrg int ret = Successful; 506a96d7823Smrg FontEntryPtr fname; 507a96d7823Smrg FontNamePtr name; 508a96d7823Smrg 509a96d7823Smrg if (max <= 0) 510a96d7823Smrg return Successful; 511a96d7823Smrg if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) { 512a96d7823Smrg if (alias_behavior == NORMAL_ALIAS_BEHAVIOR || 513a96d7823Smrg table->entries[i].type != FONT_ENTRY_ALIAS) 514a96d7823Smrg { 515a96d7823Smrg name = &table->entries[i].name; 516a96d7823Smrg if (newmax) *newmax = max - 1; 517a96d7823Smrg return xfont2_add_font_names_name(names, name->name, name->length); 518a96d7823Smrg } 519a96d7823Smrg start = i; 520a96d7823Smrg stop = i + 1; 521a96d7823Smrg } 522a96d7823Smrg for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) { 523a96d7823Smrg res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes); 524a96d7823Smrg if (res > 0) { 525a96d7823Smrg if (vals) 526a96d7823Smrg { 527a96d7823Smrg int vs = vals->values_supplied; 528a96d7823Smrg int cap; 529a96d7823Smrg 530a96d7823Smrg if (fname->type == FONT_ENTRY_SCALABLE) 531a96d7823Smrg cap = fname->u.scalable.renderer->capabilities; 532a96d7823Smrg else if (fname->type == FONT_ENTRY_ALIAS) 533a96d7823Smrg cap = ~0; /* Calling code will have to see if true */ 534a96d7823Smrg else 535a96d7823Smrg cap = 0; 536a96d7823Smrg if ((((vs & PIXELSIZE_MASK) == PIXELSIZE_ARRAY || 537a96d7823Smrg (vs & POINTSIZE_MASK) == POINTSIZE_ARRAY) && 538a96d7823Smrg !(cap & CAP_MATRIX)) || 539a96d7823Smrg ((vs & CHARSUBSET_SPECIFIED) && 540a96d7823Smrg !(cap & CAP_CHARSUBSETTING))) 541a96d7823Smrg continue; 542a96d7823Smrg } 543a96d7823Smrg 544a96d7823Smrg if ((alias_behavior & IGNORE_SCALABLE_ALIASES) && 545a96d7823Smrg fname->type == FONT_ENTRY_ALIAS) 546a96d7823Smrg { 547a96d7823Smrg FontScalableRec tmpvals; 548a96d7823Smrg if (FontParseXLFDName (fname->name.name, &tmpvals, 549a96d7823Smrg FONT_XLFD_REPLACE_NONE) && 550a96d7823Smrg !(tmpvals.values_supplied & SIZE_SPECIFY_MASK)) 551a96d7823Smrg continue; 552a96d7823Smrg } 553a96d7823Smrg 554a96d7823Smrg ret = xfont2_add_font_names_name(names, fname->name.name, fname->name.length); 555a96d7823Smrg if (ret != Successful) 556a96d7823Smrg goto bail; 557a96d7823Smrg 558a96d7823Smrg /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark 559a96d7823Smrg this entry as an alias by negating its length and follow 560a96d7823Smrg it by the resolved name */ 561a96d7823Smrg if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES) && 562a96d7823Smrg fname->type == FONT_ENTRY_ALIAS) 563a96d7823Smrg { 564a96d7823Smrg names->length[names->nnames - 1] = 565a96d7823Smrg -names->length[names->nnames - 1]; 566a96d7823Smrg ret = xfont2_add_font_names_name(names, fname->u.alias.resolved, 567a96d7823Smrg strlen(fname->u.alias.resolved)); 568a96d7823Smrg if (ret != Successful) 569a96d7823Smrg goto bail; 570a96d7823Smrg } 571a96d7823Smrg 572a96d7823Smrg if (--max <= 0) 573a96d7823Smrg break; 574a96d7823Smrg } else if (res < 0) 575a96d7823Smrg break; 576a96d7823Smrg } 577a96d7823Smrg bail: ; 578a96d7823Smrg if (newmax) *newmax = max; 579a96d7823Smrg return ret; 580a96d7823Smrg} 581a96d7823Smrg 582a96d7823Smrgint 583a96d7823SmrgFontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat, 584a96d7823Smrg int max, FontNamesPtr names) 585a96d7823Smrg{ 586a96d7823Smrg return FontFileFindNamesInScalableDir(table, pat, max, names, 587a96d7823Smrg (FontScalablePtr)0, 588a96d7823Smrg NORMAL_ALIAS_BEHAVIOR, (int *)0); 589a96d7823Smrg} 590a96d7823Smrg 591a96d7823SmrgBool 592a96d7823SmrgFontFileMatchName(char *name, int length, FontNamePtr pat) 593a96d7823Smrg{ 594a96d7823Smrg /* Perform a fontfile-type name match on a single name */ 595a96d7823Smrg FontTableRec table; 596a96d7823Smrg FontEntryRec entries[1]; 597a96d7823Smrg 598a96d7823Smrg /* Dummy up a table */ 599a96d7823Smrg table.used = 1; 600a96d7823Smrg table.size = 1; 601a96d7823Smrg table.sorted = TRUE; 602a96d7823Smrg table.entries = entries; 603a96d7823Smrg entries[0].name.name = name; 604a96d7823Smrg entries[0].name.length = length; 605a96d7823Smrg entries[0].name.ndashes = FontFileCountDashes(name, length); 606a96d7823Smrg 607a96d7823Smrg return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0; 608a96d7823Smrg} 609a96d7823Smrg 610a96d7823Smrg/* 611a96d7823Smrg * Add a font file to a directory. This handles bitmap and 612a96d7823Smrg * scalable names both 613a96d7823Smrg */ 614a96d7823Smrg 615a96d7823SmrgBool 616a96d7823SmrgFontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName) 617a96d7823Smrg{ 618a96d7823Smrg FontEntryRec entry; 619a96d7823Smrg FontScalableRec vals, zeroVals; 620a96d7823Smrg FontRendererPtr renderer; 621a96d7823Smrg FontEntryPtr existing; 622a96d7823Smrg FontScalableExtraPtr extra; 623a96d7823Smrg FontEntryPtr bitmap = 0, scalable; 624a96d7823Smrg Bool isscale; 625a96d7823Smrg Bool scalable_xlfd; 626a96d7823Smrg 627a96d7823Smrg renderer = FontFileMatchRenderer (fileName); 628a96d7823Smrg if (!renderer) 629a96d7823Smrg return FALSE; 630a96d7823Smrg entry.name.length = strlen (fontName); 631a96d7823Smrg if (entry.name.length > MAXFONTNAMELEN) 632a96d7823Smrg entry.name.length = MAXFONTNAMELEN; 633a96d7823Smrg entry.name.name = fontName; 634a96d7823Smrg CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length); 635a96d7823Smrg entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); 636a96d7823Smrg entry.name.name[entry.name.length] = '\0'; 637a96d7823Smrg /* 638a96d7823Smrg * Add a bitmap name if the incoming name isn't an XLFD name, or 639a96d7823Smrg * if it isn't a scalable name (i.e. non-zero scalable fields) 640a96d7823Smrg * 641a96d7823Smrg * If name of bitmapped font contains XLFD enhancements, do not add 642a96d7823Smrg * a scalable version of the name... this can lead to confusion and 643a96d7823Smrg * ambiguity between the font name and the field enhancements. 644a96d7823Smrg */ 645a96d7823Smrg isscale = entry.name.ndashes == 14 && 646a96d7823Smrg FontParseXLFDName(entry.name.name, 647a96d7823Smrg &vals, FONT_XLFD_REPLACE_NONE) && 648a96d7823Smrg (vals.values_supplied & PIXELSIZE_MASK) != PIXELSIZE_ARRAY && 649a96d7823Smrg (vals.values_supplied & POINTSIZE_MASK) != POINTSIZE_ARRAY && 650a96d7823Smrg !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK); 651a96d7823Smrg#define UNSCALED_ATTRIB "unscaled" 652a96d7823Smrg scalable_xlfd = (isscale && 653a96d7823Smrg (((vals.values_supplied & PIXELSIZE_MASK) == 0) || 654a96d7823Smrg ((vals.values_supplied & POINTSIZE_MASK) == 0))); 655a96d7823Smrg /* 656a96d7823Smrg * For scalable fonts without a scalable XFLD, check if the "unscaled" 657a96d7823Smrg * attribute is present. 658a96d7823Smrg */ 659a96d7823Smrg if (isscale && !scalable_xlfd && 660a96d7823Smrg dir->attributes && dir->attributes[0] == ':') { 661a96d7823Smrg char *ptr1 = dir->attributes + 1; 662a96d7823Smrg char *ptr2; 663a96d7823Smrg int length; 664a96d7823Smrg int uslength = strlen(UNSCALED_ATTRIB); 665a96d7823Smrg 666a96d7823Smrg do { 667a96d7823Smrg ptr2 = strchr(ptr1, ':'); 668a96d7823Smrg if (ptr2) 669a96d7823Smrg length = ptr2 - ptr1; 670a96d7823Smrg else 671a96d7823Smrg length = dir->attributes + strlen(dir->attributes) - ptr1; 672a96d7823Smrg if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB, uslength)) 673a96d7823Smrg isscale = FALSE; 674a96d7823Smrg if (ptr2) 675a96d7823Smrg ptr1 = ptr2 + 1; 676a96d7823Smrg } while (ptr2); 677a96d7823Smrg } 678a96d7823Smrg if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK)) 679a96d7823Smrg { 680a96d7823Smrg /* 681a96d7823Smrg * If the renderer doesn't support OpenBitmap, FontFileOpenFont 682a96d7823Smrg * will still do the right thing. 683a96d7823Smrg */ 684a96d7823Smrg entry.type = FONT_ENTRY_BITMAP; 685a96d7823Smrg entry.u.bitmap.renderer = renderer; 686a96d7823Smrg entry.u.bitmap.pFont = NullFont; 687a96d7823Smrg if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName))) 688a96d7823Smrg return FALSE; 689a96d7823Smrg if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry))) 690a96d7823Smrg { 691a96d7823Smrg free (entry.u.bitmap.fileName); 692a96d7823Smrg return FALSE; 693a96d7823Smrg } 694a96d7823Smrg } 695a96d7823Smrg /* 696a96d7823Smrg * Parse out scalable fields from XLFD names - a scalable name 697a96d7823Smrg * just gets inserted, a scaled name has more things to do. 698a96d7823Smrg */ 699a96d7823Smrg if (isscale) 700a96d7823Smrg { 701a96d7823Smrg if (vals.values_supplied & SIZE_SPECIFY_MASK) 702a96d7823Smrg { 703a96d7823Smrg bzero((char *)&zeroVals, sizeof(zeroVals)); 704a96d7823Smrg zeroVals.x = vals.x; 705a96d7823Smrg zeroVals.y = vals.y; 706a96d7823Smrg zeroVals.values_supplied = PIXELSIZE_SCALAR | POINTSIZE_SCALAR; 707a96d7823Smrg FontParseXLFDName (entry.name.name, &zeroVals, 708a96d7823Smrg FONT_XLFD_REPLACE_VALUE); 709a96d7823Smrg entry.name.length = strlen (entry.name.name); 710a96d7823Smrg existing = FontFileFindNameInDir (&dir->scalable, &entry.name); 711a96d7823Smrg if (existing) 712a96d7823Smrg { 713a96d7823Smrg if ((vals.values_supplied & POINTSIZE_MASK) == 714a96d7823Smrg POINTSIZE_SCALAR && 715a96d7823Smrg (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) 716a96d7823Smrg { 717a96d7823Smrg existing->u.scalable.extra->defaults = vals; 718a96d7823Smrg 719a96d7823Smrg free (existing->u.scalable.fileName); 720a96d7823Smrg if (!(existing->u.scalable.fileName = FontFileSaveString (fileName))) 721a96d7823Smrg return FALSE; 722a96d7823Smrg } 723a96d7823Smrg if(bitmap) 724a96d7823Smrg { 725a96d7823Smrg FontFileCompleteXLFD(&vals, &vals); 726a96d7823Smrg FontFileAddScaledInstance (existing, &vals, NullFont, 727a96d7823Smrg bitmap->name.name); 728a96d7823Smrg return TRUE; 729a96d7823Smrg } 730a96d7823Smrg } 731a96d7823Smrg } 732a96d7823Smrg if (!(entry.u.scalable.fileName = FontFileSaveString (fileName))) 733a96d7823Smrg return FALSE; 734a96d7823Smrg extra = malloc (sizeof (FontScalableExtraRec)); 735a96d7823Smrg if (!extra) 736a96d7823Smrg { 737a96d7823Smrg free (entry.u.scalable.fileName); 738a96d7823Smrg return FALSE; 739a96d7823Smrg } 740a96d7823Smrg bzero((char *)&extra->defaults, sizeof(extra->defaults)); 741a96d7823Smrg if ((vals.values_supplied & POINTSIZE_MASK) == POINTSIZE_SCALAR && 742a96d7823Smrg (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize()) 743a96d7823Smrg extra->defaults = vals; 744a96d7823Smrg else 745a96d7823Smrg { 746a96d7823Smrg FontResolutionPtr resolution; 747a96d7823Smrg int num; 748a96d7823Smrg int default_point_size = GetDefaultPointSize(); 749a96d7823Smrg 750a96d7823Smrg extra->defaults.point_matrix[0] = 751a96d7823Smrg extra->defaults.point_matrix[3] = 752a96d7823Smrg (double)default_point_size / 10.0; 753a96d7823Smrg extra->defaults.point_matrix[1] = 754a96d7823Smrg extra->defaults.point_matrix[2] = 0.0; 755a96d7823Smrg extra->defaults.values_supplied = 756a96d7823Smrg POINTSIZE_SCALAR | PIXELSIZE_UNDEFINED; 757a96d7823Smrg extra->defaults.width = -1; 758a96d7823Smrg if (vals.x <= 0 || vals.y <= 0) 759a96d7823Smrg { 760a96d7823Smrg resolution = GetClientResolutions (&num); 761a96d7823Smrg if (resolution && num > 0) 762a96d7823Smrg { 763a96d7823Smrg extra->defaults.x = resolution->x_resolution; 764a96d7823Smrg extra->defaults.y = resolution->y_resolution; 765a96d7823Smrg } 766a96d7823Smrg else 767a96d7823Smrg { 768a96d7823Smrg extra->defaults.x = 75; 769a96d7823Smrg extra->defaults.y = 75; 770a96d7823Smrg } 771a96d7823Smrg } 772a96d7823Smrg else 773a96d7823Smrg { 774a96d7823Smrg extra->defaults.x = vals.x; 775a96d7823Smrg extra->defaults.y = vals.y; 776a96d7823Smrg } 777a96d7823Smrg FontFileCompleteXLFD (&extra->defaults, &extra->defaults); 778a96d7823Smrg } 779a96d7823Smrg extra->numScaled = 0; 780a96d7823Smrg extra->sizeScaled = 0; 781a96d7823Smrg extra->scaled = 0; 782a96d7823Smrg extra->private = 0; 783a96d7823Smrg entry.type = FONT_ENTRY_SCALABLE; 784a96d7823Smrg entry.u.scalable.renderer = renderer; 785a96d7823Smrg entry.u.scalable.extra = extra; 786a96d7823Smrg if (!(scalable = FontFileAddEntry (&dir->scalable, &entry))) 787a96d7823Smrg { 788a96d7823Smrg free (extra); 789a96d7823Smrg free (entry.u.scalable.fileName); 790a96d7823Smrg return FALSE; 791a96d7823Smrg } 792a96d7823Smrg if (vals.values_supplied & SIZE_SPECIFY_MASK) 793a96d7823Smrg { 794a96d7823Smrg if(bitmap) 795a96d7823Smrg { 796a96d7823Smrg FontFileCompleteXLFD(&vals, &vals); 797a96d7823Smrg FontFileAddScaledInstance (scalable, &vals, NullFont, 798a96d7823Smrg bitmap->name.name); 799a96d7823Smrg } 800a96d7823Smrg } 801a96d7823Smrg } 802a96d7823Smrg return TRUE; 803a96d7823Smrg} 804a96d7823Smrg 805a96d7823SmrgBool 806a96d7823SmrgFontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName) 807a96d7823Smrg{ 808a96d7823Smrg FontEntryRec entry; 809a96d7823Smrg 810a96d7823Smrg if (strcmp(aliasName,fontName) == 0) { 811a96d7823Smrg /* Don't allow an alias to point to itself and create a loop */ 812a96d7823Smrg return FALSE; 813a96d7823Smrg } 814a96d7823Smrg entry.name.length = strlen (aliasName); 815a96d7823Smrg CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length); 816a96d7823Smrg entry.name.name = aliasName; 817a96d7823Smrg entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); 818a96d7823Smrg entry.type = FONT_ENTRY_ALIAS; 819a96d7823Smrg if (!(entry.u.alias.resolved = FontFileSaveString (fontName))) 820a96d7823Smrg return FALSE; 821a96d7823Smrg if (!FontFileAddEntry (&dir->nonScalable, &entry)) 822a96d7823Smrg { 823a96d7823Smrg free (entry.u.alias.resolved); 824a96d7823Smrg return FALSE; 825a96d7823Smrg } 826a96d7823Smrg return TRUE; 827a96d7823Smrg} 828