fontdir.c revision 60da515c
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> 37c7b4381aSmrg#include "src/util/replace.h" 38a96d7823Smrg 39a96d7823Smrg#if HAVE_STDINT_H 40a96d7823Smrg#include <stdint.h> 41a96d7823Smrg#elif !defined(INT32_MAX) 42a96d7823Smrg#define INT32_MAX 0x7fffffff 43a96d7823Smrg#endif 44a96d7823Smrg 45a96d7823SmrgBool 46a96d7823SmrgFontFileInitTable (FontTablePtr table, int size) 47a96d7823Smrg{ 48a96d7823Smrg if (size < 0 || (size > INT32_MAX/sizeof(FontEntryRec))) 49a96d7823Smrg return FALSE; 50a96d7823Smrg if (size) 51a96d7823Smrg { 52c7b4381aSmrg table->entries = mallocarray(size, sizeof(FontEntryRec)); 53a96d7823Smrg if (!table->entries) 54a96d7823Smrg return FALSE; 55a96d7823Smrg } 56a96d7823Smrg else 57a96d7823Smrg table->entries = 0; 58a96d7823Smrg table->used = 0; 59a96d7823Smrg table->size = size; 60a96d7823Smrg table->sorted = FALSE; 61a96d7823Smrg return TRUE; 62a96d7823Smrg} 63a96d7823Smrg 64a96d7823Smrgvoid 65a96d7823SmrgFontFileFreeEntry (FontEntryPtr entry) 66a96d7823Smrg{ 67a96d7823Smrg FontScalableExtraPtr extra; 68a96d7823Smrg int i; 69a96d7823Smrg 70a96d7823Smrg if (entry->name.name) 71a96d7823Smrg free(entry->name.name); 72a96d7823Smrg entry->name.name = NULL; 73a96d7823Smrg 74a96d7823Smrg switch (entry->type) 75a96d7823Smrg { 76a96d7823Smrg case FONT_ENTRY_SCALABLE: 77a96d7823Smrg free (entry->u.scalable.fileName); 78a96d7823Smrg extra = entry->u.scalable.extra; 79a96d7823Smrg for (i = 0; i < extra->numScaled; i++) 80a96d7823Smrg if (extra->scaled[i].vals.ranges) 81a96d7823Smrg free (extra->scaled[i].vals.ranges); 82a96d7823Smrg free (extra->scaled); 83a96d7823Smrg free (extra); 84a96d7823Smrg break; 85a96d7823Smrg case FONT_ENTRY_BITMAP: 86a96d7823Smrg free (entry->u.bitmap.fileName); 87a96d7823Smrg entry->u.bitmap.fileName = NULL; 88a96d7823Smrg break; 89a96d7823Smrg case FONT_ENTRY_ALIAS: 90a96d7823Smrg free (entry->u.alias.resolved); 91a96d7823Smrg entry->u.alias.resolved = NULL; 92a96d7823Smrg break; 93a96d7823Smrg } 94a96d7823Smrg} 95a96d7823Smrg 96a96d7823Smrgvoid 97a96d7823SmrgFontFileFreeTable (FontTablePtr table) 98a96d7823Smrg{ 99a96d7823Smrg int i; 100a96d7823Smrg 101a96d7823Smrg for (i = 0; i < table->used; i++) 102a96d7823Smrg FontFileFreeEntry (&table->entries[i]); 103a96d7823Smrg free (table->entries); 104a96d7823Smrg} 105a96d7823Smrg 106a96d7823SmrgFontDirectoryPtr 107a96d7823SmrgFontFileMakeDir(const char *dirName, int size) 108a96d7823Smrg{ 109a96d7823Smrg FontDirectoryPtr dir; 110a96d7823Smrg int dirlen; 111a96d7823Smrg int needslash = 0; 112a96d7823Smrg const char *attrib; 113a96d7823Smrg int attriblen; 114a96d7823Smrg 115a96d7823Smrg#if !defined(WIN32) 116a96d7823Smrg attrib = strchr(dirName, ':'); 117a96d7823Smrg#else 118a96d7823Smrg /* OS/2 uses the colon in the drive letter descriptor, skip this */ 119a96d7823Smrg attrib = strchr(dirName+2, ':'); 120a96d7823Smrg#endif 121a96d7823Smrg if (attrib) { 122a96d7823Smrg dirlen = attrib - dirName; 123a96d7823Smrg attriblen = strlen(attrib); 124a96d7823Smrg } else { 125a96d7823Smrg dirlen = strlen(dirName); 126a96d7823Smrg attriblen = 0; 127a96d7823Smrg } 12860da515cSmrg if (dirlen && dirName[dirlen - 1] != '/') 129a96d7823Smrg needslash = 1; 130a96d7823Smrg dir = malloc(sizeof *dir + dirlen + needslash + 1 + 131a96d7823Smrg (attriblen ? attriblen + 1 : 0)); 132a96d7823Smrg if (!dir) 133a96d7823Smrg return (FontDirectoryPtr)0; 134a96d7823Smrg if (!FontFileInitTable (&dir->scalable, 0)) 135a96d7823Smrg { 136a96d7823Smrg free (dir); 137a96d7823Smrg return (FontDirectoryPtr)0; 138a96d7823Smrg } 139a96d7823Smrg if (!FontFileInitTable (&dir->nonScalable, size)) 140a96d7823Smrg { 141a96d7823Smrg FontFileFreeTable (&dir->scalable); 142a96d7823Smrg free (dir); 143a96d7823Smrg return (FontDirectoryPtr)0; 144a96d7823Smrg } 145a96d7823Smrg dir->directory = (char *) (dir + 1); 146a96d7823Smrg dir->dir_mtime = 0; 147a96d7823Smrg dir->alias_mtime = 0; 148a96d7823Smrg if (attriblen) 149a96d7823Smrg dir->attributes = dir->directory + dirlen + needslash + 1; 150a96d7823Smrg else 151a96d7823Smrg dir->attributes = NULL; 152a96d7823Smrg strncpy(dir->directory, dirName, dirlen); 153a96d7823Smrg if (needslash) 154c7b4381aSmrg dir->directory[dirlen] = '/'; 155c7b4381aSmrg dir->directory[dirlen + needslash] = '\0'; 156c7b4381aSmrg if (dir->attributes) 157c7b4381aSmrg strlcpy(dir->attributes, attrib, attriblen + 1); 158a96d7823Smrg return dir; 159a96d7823Smrg} 160a96d7823Smrg 161a96d7823Smrgvoid 162a96d7823SmrgFontFileFreeDir (FontDirectoryPtr dir) 163a96d7823Smrg{ 164a96d7823Smrg FontFileFreeTable (&dir->scalable); 165a96d7823Smrg FontFileFreeTable (&dir->nonScalable); 166a96d7823Smrg free(dir); 167a96d7823Smrg} 168a96d7823Smrg 169a96d7823SmrgFontEntryPtr 170a96d7823SmrgFontFileAddEntry(FontTablePtr table, FontEntryPtr prototype) 171a96d7823Smrg{ 172a96d7823Smrg FontEntryPtr entry; 173a96d7823Smrg int newsize; 174a96d7823Smrg 175a96d7823Smrg /* can't add entries to a sorted table, pointers get broken! */ 176a96d7823Smrg if (table->sorted) 177a96d7823Smrg return (FontEntryPtr) 0; /* "cannot" happen */ 178a96d7823Smrg if (table->used == table->size) { 179a96d7823Smrg if (table->size >= ((INT32_MAX / sizeof(FontEntryRec)) - 100)) 180a96d7823Smrg /* If we've read so many entries we're going to ask for 2gb 181a96d7823Smrg or more of memory, something is so wrong with this font 182a96d7823Smrg directory that we should just give up before we overflow. */ 183a96d7823Smrg return NULL; 184a96d7823Smrg newsize = table->size + 100; 185c7b4381aSmrg entry = reallocarray(table->entries, newsize, sizeof(FontEntryRec)); 186a96d7823Smrg if (!entry) 187a96d7823Smrg return (FontEntryPtr)0; 188a96d7823Smrg table->size = newsize; 189a96d7823Smrg table->entries = entry; 190a96d7823Smrg } 191a96d7823Smrg entry = &table->entries[table->used]; 192a96d7823Smrg *entry = *prototype; 193a96d7823Smrg entry->name.name = malloc(prototype->name.length + 1); 194a96d7823Smrg if (!entry->name.name) 195a96d7823Smrg return (FontEntryPtr)0; 196a96d7823Smrg memcpy (entry->name.name, prototype->name.name, prototype->name.length); 197a96d7823Smrg entry->name.name[entry->name.length] = '\0'; 198a96d7823Smrg table->used++; 199a96d7823Smrg return entry; 200a96d7823Smrg} 201a96d7823Smrg 202a96d7823Smrg/* 203a96d7823Smrg * Compare two strings just like strcmp, but preserve decimal integer 204a96d7823Smrg * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" < 205a96d7823Smrg * "iso10646-1". Strings are sorted as if sequences of digits were 206a96d7823Smrg * prefixed by a length indicator (i.e., does not ignore leading zeroes). 207a96d7823Smrg * 208a96d7823Smrg * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> 209a96d7823Smrg */ 210a96d7823Smrg#define Xisdigit(c) ('\060' <= (c) && (c) <= '\071') 211a96d7823Smrg 212a96d7823Smrgstatic int strcmpn(const char *s1, const char *s2) 213a96d7823Smrg{ 214a96d7823Smrg int digits, predigits = 0; 215a96d7823Smrg const char *ss1, *ss2; 216a96d7823Smrg 217a96d7823Smrg while (1) { 218a96d7823Smrg if (*s1 == 0 && *s2 == 0) 219a96d7823Smrg return 0; 220a96d7823Smrg digits = Xisdigit(*s1) && Xisdigit(*s2); 221a96d7823Smrg if (digits && !predigits) { 222a96d7823Smrg ss1 = s1; 223a96d7823Smrg ss2 = s2; 224a96d7823Smrg while (Xisdigit(*ss1) && Xisdigit(*ss2)) 225a96d7823Smrg ss1++, ss2++; 226a96d7823Smrg if (!Xisdigit(*ss1) && Xisdigit(*ss2)) 227a96d7823Smrg return -1; 228a96d7823Smrg if (Xisdigit(*ss1) && !Xisdigit(*ss2)) 229a96d7823Smrg return 1; 230a96d7823Smrg } 231a96d7823Smrg if ((unsigned char)*s1 < (unsigned char)*s2) 232a96d7823Smrg return -1; 233a96d7823Smrg if ((unsigned char)*s1 > (unsigned char)*s2) 234a96d7823Smrg return 1; 235a96d7823Smrg predigits = digits; 236a96d7823Smrg s1++, s2++; 237a96d7823Smrg } 238a96d7823Smrg} 239a96d7823Smrg 240a96d7823Smrg 241a96d7823Smrgstatic int 242a96d7823SmrgFontFileNameCompare(const void* a, const void* b) 243a96d7823Smrg{ 244a96d7823Smrg FontEntryPtr a_name = (FontEntryPtr) a, 245a96d7823Smrg b_name = (FontEntryPtr) b; 246a96d7823Smrg 247a96d7823Smrg return strcmpn(a_name->name.name, b_name->name.name); 248a96d7823Smrg} 249a96d7823Smrg 250a96d7823Smrgvoid 251a96d7823SmrgFontFileSortTable (FontTablePtr table) 252a96d7823Smrg{ 253a96d7823Smrg if (!table->sorted) { 254a96d7823Smrg qsort((char *) table->entries, table->used, sizeof(FontEntryRec), 255a96d7823Smrg FontFileNameCompare); 256a96d7823Smrg table->sorted = TRUE; 257a96d7823Smrg } 258a96d7823Smrg} 259a96d7823Smrg 260a96d7823Smrgvoid 261a96d7823SmrgFontFileSortDir(FontDirectoryPtr dir) 262a96d7823Smrg{ 263a96d7823Smrg FontFileSortTable (&dir->scalable); 264a96d7823Smrg FontFileSortTable (&dir->nonScalable); 265a96d7823Smrg /* now that the table is fixed in size, swizzle the pointers */ 266a96d7823Smrg FontFileSwitchStringsToBitmapPointers (dir); 267a96d7823Smrg} 268a96d7823Smrg 269a96d7823Smrg/* 270a96d7823Smrg Given a Font Table, SetupWildMatch() sets up various pointers and state 271a96d7823Smrg information so the table can be searched for name(s) that match a given 272a96d7823Smrg fontname pattern -- which may contain wildcards. Under certain 273a96d7823Smrg circumstances, SetupWildMatch() will find the one table entry that 274a96d7823Smrg matches the pattern. If those circumstances do not pertain, 275a96d7823Smrg SetupWildMatch() returns a range within the the table that should be 276a96d7823Smrg searched for matching name(s). With the information established by 277a96d7823Smrg SetupWildMatch(), including state information in "private", the 278a96d7823Smrg PatternMatch() procedure is then used to test names in the range for a 279a96d7823Smrg match. 280a96d7823Smrg*/ 281a96d7823Smrg 282a96d7823Smrg#define isWild(c) ((c) == XK_asterisk || (c) == XK_question) 283a96d7823Smrg#define isDigit(c) (XK_0 <= (c) && (c) <= XK_9) 284a96d7823Smrg 285a96d7823Smrgstatic int 286a96d7823SmrgSetupWildMatch(FontTablePtr table, FontNamePtr pat, 287a96d7823Smrg int *leftp, int *rightp, int *privatep) 288a96d7823Smrg{ 289a96d7823Smrg int nDashes; 290a96d7823Smrg char c; 291a96d7823Smrg char *t; 292a96d7823Smrg char *firstWild; 293a96d7823Smrg char *firstDigit; 294a96d7823Smrg int first; 295a96d7823Smrg int center, 296a96d7823Smrg left, 297a96d7823Smrg right; 298a96d7823Smrg int result; 299a96d7823Smrg char *name; 300a96d7823Smrg 301a96d7823Smrg name = pat->name; 302a96d7823Smrg nDashes = pat->ndashes; 303a96d7823Smrg firstWild = 0; 304a96d7823Smrg firstDigit = 0; 305a96d7823Smrg t = name; 306a96d7823Smrg while ((c = *t++)) { 307a96d7823Smrg if (isWild(c)) { 308a96d7823Smrg if (!firstWild) 309a96d7823Smrg firstWild = t - 1; 310a96d7823Smrg } 311a96d7823Smrg if (isDigit(c)) { 312a96d7823Smrg if (!firstDigit) 313a96d7823Smrg firstDigit = t - 1; 314a96d7823Smrg } 315a96d7823Smrg } 316a96d7823Smrg left = 0; 317a96d7823Smrg right = table->used; 318a96d7823Smrg if (firstWild) 319a96d7823Smrg *privatep = nDashes; 320a96d7823Smrg else 321a96d7823Smrg *privatep = -1; 322a96d7823Smrg if (!table->sorted) { 323a96d7823Smrg *leftp = left; 324a96d7823Smrg *rightp = right; 325a96d7823Smrg return -1; 326a96d7823Smrg } else if (firstWild) { 327a96d7823Smrg if (firstDigit && firstDigit < firstWild) 328a96d7823Smrg first = firstDigit - name; 329a96d7823Smrg else 330a96d7823Smrg first = firstWild - name; 331a96d7823Smrg while (left < right) { 332a96d7823Smrg center = (left + right) / 2; 333a96d7823Smrg result = strncmp(name, table->entries[center].name.name, first); 334a96d7823Smrg if (result == 0) 335a96d7823Smrg break; 336a96d7823Smrg if (result < 0) 337a96d7823Smrg right = center; 338a96d7823Smrg else 339a96d7823Smrg left = center + 1; 340a96d7823Smrg } 341a96d7823Smrg *leftp = left; 342a96d7823Smrg *rightp = right; 343a96d7823Smrg return -1; 344a96d7823Smrg } else { 345a96d7823Smrg while (left < right) { 346a96d7823Smrg center = (left + right) / 2; 347a96d7823Smrg result = strcmpn(name, table->entries[center].name.name); 348a96d7823Smrg if (result == 0) 349a96d7823Smrg return center; 350a96d7823Smrg if (result < 0) 351a96d7823Smrg right = center; 352a96d7823Smrg else 353a96d7823Smrg left = center + 1; 354a96d7823Smrg } 355a96d7823Smrg *leftp = 1; 356a96d7823Smrg *rightp = 0; 357a96d7823Smrg return -1; 358a96d7823Smrg } 359a96d7823Smrg} 360a96d7823Smrg 361a96d7823Smrgstatic int 362a96d7823SmrgPatternMatch(char *pat, int patdashes, char *string, int stringdashes) 363a96d7823Smrg{ 364a96d7823Smrg char c, 365a96d7823Smrg t; 366a96d7823Smrg 367a96d7823Smrg if (stringdashes < patdashes) 368a96d7823Smrg return 0; 369a96d7823Smrg for (;;) { 370a96d7823Smrg switch (c = *pat++) { 371a96d7823Smrg case '*': 372a96d7823Smrg if (!(c = *pat++)) 373a96d7823Smrg return 1; 374a96d7823Smrg if (c == XK_minus) { 375a96d7823Smrg patdashes--; 376a96d7823Smrg for (;;) { 377a96d7823Smrg while ((t = *string++) != XK_minus) 378a96d7823Smrg if (!t) 379a96d7823Smrg return 0; 380a96d7823Smrg stringdashes--; 381a96d7823Smrg if (PatternMatch(pat, patdashes, string, stringdashes)) 382a96d7823Smrg return 1; 383a96d7823Smrg if (stringdashes == patdashes) 384a96d7823Smrg return 0; 385a96d7823Smrg } 386a96d7823Smrg } else { 387a96d7823Smrg for (;;) { 388a96d7823Smrg while ((t = *string++) != c) { 389a96d7823Smrg if (!t) 390a96d7823Smrg return 0; 391a96d7823Smrg if (t == XK_minus) { 392a96d7823Smrg if (stringdashes-- < patdashes) 393a96d7823Smrg return 0; 394a96d7823Smrg } 395a96d7823Smrg } 396a96d7823Smrg if (PatternMatch(pat, patdashes, string, stringdashes)) 397a96d7823Smrg return 1; 398a96d7823Smrg } 399a96d7823Smrg } 400a96d7823Smrg case '?': 401fd60135fSmrg if ((t = *string++) == XK_minus) 402a96d7823Smrg stringdashes--; 403fd60135fSmrg if (!t) 404fd60135fSmrg return 0; 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