fcname.c revision 898dab68
1/* 2 * fontconfig/src/fcname.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 <ctype.h> 27#include <stdlib.h> 28#include <string.h> 29#include <stdio.h> 30 31/* 32 * Please do not change this list, it is used to initialize the object 33 * list in this order to match the FC_foo_OBJECT constants. Those 34 * constants are written into cache files. 35 */ 36 37static const FcObjectType _FcBaseObjectTypes[] = { 38 { FC_FAMILY, FcTypeString, }, /* 1 */ 39 { FC_FAMILYLANG, FcTypeString, }, 40 { FC_STYLE, FcTypeString, }, 41 { FC_STYLELANG, FcTypeString, }, 42 { FC_FULLNAME, FcTypeString, }, 43 { FC_FULLNAMELANG, FcTypeString, }, 44 { FC_SLANT, FcTypeInteger, }, 45 { FC_WEIGHT, FcTypeInteger, }, 46 { FC_WIDTH, FcTypeInteger, }, 47 { FC_SIZE, FcTypeDouble, }, 48 { FC_ASPECT, FcTypeDouble, }, 49 { FC_PIXEL_SIZE, FcTypeDouble, }, 50 { FC_SPACING, FcTypeInteger, }, 51 { FC_FOUNDRY, FcTypeString, }, 52 { FC_ANTIALIAS, FcTypeBool, }, 53 { FC_HINT_STYLE, FcTypeInteger, }, 54 { FC_HINTING, FcTypeBool, }, 55 { FC_VERTICAL_LAYOUT, FcTypeBool, }, 56 { FC_AUTOHINT, FcTypeBool, }, 57 { FC_GLOBAL_ADVANCE, FcTypeBool, }, /* deprecated */ 58 { FC_FILE, FcTypeString, }, 59 { FC_INDEX, FcTypeInteger, }, 60 { FC_RASTERIZER, FcTypeString, }, 61 { FC_OUTLINE, FcTypeBool, }, 62 { FC_SCALABLE, FcTypeBool, }, 63 { FC_DPI, FcTypeDouble }, 64 { FC_RGBA, FcTypeInteger, }, 65 { FC_SCALE, FcTypeDouble, }, 66 { FC_MINSPACE, FcTypeBool, }, 67 { FC_CHAR_WIDTH, FcTypeInteger }, 68 { FC_CHAR_HEIGHT, FcTypeInteger }, 69 { FC_MATRIX, FcTypeMatrix }, 70 { FC_CHARSET, FcTypeCharSet }, 71 { FC_LANG, FcTypeLangSet }, 72 { FC_FONTVERSION, FcTypeInteger }, 73 { FC_CAPABILITY, FcTypeString }, 74 { FC_FONTFORMAT, FcTypeString }, 75 { FC_EMBOLDEN, FcTypeBool }, 76 { FC_EMBEDDED_BITMAP, FcTypeBool }, 77 { FC_DECORATIVE, FcTypeBool }, 78 { FC_LCD_FILTER, FcTypeInteger }, /* 41 */ 79 { FC_NAMELANG, FcTypeString }, /* 42 */ 80}; 81 82#define NUM_OBJECT_TYPES (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0]) 83 84typedef struct _FcObjectTypeList FcObjectTypeList; 85 86struct _FcObjectTypeList { 87 const FcObjectTypeList *next; 88 const FcObjectType *types; 89 int ntypes; 90}; 91 92static const FcObjectTypeList _FcBaseObjectTypesList = { 93 0, 94 _FcBaseObjectTypes, 95 NUM_OBJECT_TYPES, 96}; 97 98static const FcObjectTypeList *_FcObjectTypes = &_FcBaseObjectTypesList; 99 100#define OBJECT_HASH_SIZE 31 101 102typedef struct _FcObjectBucket { 103 struct _FcObjectBucket *next; 104 FcChar32 hash; 105 FcObject id; 106} FcObjectBucket; 107 108static FcObjectBucket *FcObjectBuckets[OBJECT_HASH_SIZE]; 109 110static FcObjectType *FcObjects = (FcObjectType *) _FcBaseObjectTypes; 111static int FcObjectsNumber = NUM_OBJECT_TYPES; 112static int FcObjectsSize = 0; 113static FcBool FcObjectsInited; 114 115static FcObjectType * 116FcObjectInsert (const char *name, FcType type) 117{ 118 FcObjectType *o; 119 if (FcObjectsNumber >= FcObjectsSize) 120 { 121 int newsize = FcObjectsNumber * 2; 122 FcObjectType *newobjects; 123 124 if (FcObjectsSize) 125 newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType)); 126 else 127 { 128 newobjects = malloc (newsize * sizeof (FcObjectType)); 129 if (newobjects) 130 memcpy (newobjects, FcObjects, 131 FcObjectsNumber * sizeof (FcObjectType)); 132 } 133 if (!newobjects) 134 return NULL; 135 FcObjects = newobjects; 136 FcObjectsSize = newsize; 137 } 138 o = &FcObjects[FcObjectsNumber]; 139 o->object = name; 140 o->type = type; 141 ++FcObjectsNumber; 142 return o; 143} 144 145static FcObject 146FcObjectId (FcObjectType *o) 147{ 148 return o - FcObjects + 1; 149} 150 151static FcObjectType * 152FcObjectFindByName (const char *object, FcBool insert) 153{ 154 FcChar32 hash = FcStringHash ((const FcChar8 *) object); 155 FcObjectBucket **p; 156 FcObjectBucket *b; 157 FcObjectType *o; 158 159 if (!FcObjectsInited) 160 FcObjectInit (); 161 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) 162 { 163 o = FcObjects + b->id - 1; 164 if (b->hash == hash && !strcmp (object, (o->object))) 165 return o; 166 } 167 if (!insert) 168 return NULL; 169 /* 170 * Hook it into the hash chain 171 */ 172 b = malloc (sizeof(FcObjectBucket)); 173 if (!b) 174 return NULL; 175 object = (const char *) FcStrCopy ((FcChar8 *) object); 176 if (!object) { 177 free (b); 178 return NULL; 179 } 180 o = FcObjectInsert (object, -1); 181 b->next = NULL; 182 b->hash = hash; 183 b->id = FcObjectId (o); 184 *p = b; 185 return o; 186} 187 188static FcObjectType * 189FcObjectFindById (FcObject object) 190{ 191 if (1 <= object && object <= FcObjectsNumber) 192 return FcObjects + object - 1; 193 return NULL; 194} 195 196static FcBool 197FcObjectHashInsert (const FcObjectType *object, FcBool copy) 198{ 199 FcChar32 hash = FcStringHash ((const FcChar8 *) object->object); 200 FcObjectBucket **p; 201 FcObjectBucket *b; 202 FcObjectType *o; 203 204 if (!FcObjectsInited) 205 FcObjectInit (); 206 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) 207 { 208 o = FcObjects + b->id - 1; 209 if (b->hash == hash && !strcmp (object->object, o->object)) 210 return FcFalse; 211 } 212 /* 213 * Hook it into the hash chain 214 */ 215 b = malloc (sizeof(FcObjectBucket)); 216 if (!b) 217 return FcFalse; 218 if (copy) 219 { 220 o = FcObjectInsert (object->object, object->type); 221 if (!o) 222 { 223 free (b); 224 return FcFalse; 225 } 226 } 227 else 228 o = (FcObjectType *) object; 229 b->next = NULL; 230 b->hash = hash; 231 b->id = FcObjectId (o); 232 *p = b; 233 return FcTrue; 234} 235 236static void 237FcObjectHashRemove (const FcObjectType *object, FcBool cleanobj) 238{ 239 FcChar32 hash = FcStringHash ((const FcChar8 *) object->object); 240 FcObjectBucket **p; 241 FcObjectBucket *b; 242 FcObjectType *o; 243 244 if (!FcObjectsInited) 245 FcObjectInit (); 246 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next)) 247 { 248 o = FcObjects + b->id - 1; 249 if (b->hash == hash && !strcmp (object->object, o->object)) 250 { 251 *p = b->next; 252 free (b); 253 if (cleanobj) 254 { 255 /* Clean up object array */ 256 o->object = NULL; 257 o->type = -1; 258 while (FcObjects[FcObjectsNumber-1].object == NULL) 259 --FcObjectsNumber; 260 } 261 break; 262 } 263 } 264} 265 266FcBool 267FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes) 268{ 269 int i; 270 271 for (i = 0; i < ntypes; i++) 272 if (!FcObjectHashInsert (&types[i], FcTrue)) 273 return FcFalse; 274 return FcTrue; 275} 276 277FcBool 278FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes) 279{ 280 int i; 281 282 for (i = 0; i < ntypes; i++) 283 FcObjectHashRemove (&types[i], FcTrue); 284 return FcTrue; 285} 286 287const FcObjectType * 288FcNameGetObjectType (const char *object) 289{ 290 return FcObjectFindByName (object, FcFalse); 291} 292 293FcBool 294FcObjectValidType (FcObject object, FcType type) 295{ 296 FcObjectType *t = FcObjectFindById (object); 297 298 if (t) { 299 switch (t->type) { 300 case FcTypeDouble: 301 case FcTypeInteger: 302 if (type == FcTypeDouble || type == FcTypeInteger) 303 return FcTrue; 304 break; 305 case FcTypeLangSet: 306 if (type == FcTypeLangSet || type == FcTypeString) 307 return FcTrue; 308 break; 309 default: 310 if (t->type == -1 || type == t->type) 311 return FcTrue; 312 break; 313 } 314 return FcFalse; 315 } 316 return FcTrue; 317} 318 319FcObject 320FcObjectFromName (const char * name) 321{ 322 FcObjectType *o = FcObjectFindByName (name, FcTrue); 323 324 if (o) 325 return FcObjectId (o); 326 return 0; 327} 328 329FcObjectSet * 330FcObjectGetSet (void) 331{ 332 int i; 333 FcObjectSet *os = NULL; 334 335 336 os = FcObjectSetCreate (); 337 for (i = 0; i < FcObjectsNumber; i++) 338 FcObjectSetAdd (os, FcObjects[i].object); 339 340 return os; 341} 342 343FcBool 344FcObjectInit (void) 345{ 346 int i; 347 348 if (FcObjectsInited) 349 return FcTrue; 350 351 FcObjectsInited = FcTrue; 352 for (i = 0; i < NUM_OBJECT_TYPES; i++) 353 if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse)) 354 return FcFalse; 355 return FcTrue; 356} 357 358void 359FcObjectFini (void) 360{ 361 int i; 362 FcObjectBucket *b, *next; 363 364 for (i = 0; i < OBJECT_HASH_SIZE; i++) 365 { 366 for (b = FcObjectBuckets[i]; b; b = next) 367 { 368 next = b->next; 369 free (b); 370 } 371 FcObjectBuckets[i] = 0; 372 } 373 for (i = 0; i < FcObjectsNumber; i++) 374 if (FcObjects[i].type == (FcType)-1) 375 free ((void*) FcObjects[i].object); 376 if (FcObjects != _FcBaseObjectTypes) 377 free (FcObjects); 378 FcObjects = (FcObjectType *) _FcBaseObjectTypes; 379 FcObjectsNumber = NUM_OBJECT_TYPES; 380 FcObjectsSize = 0; 381 FcObjectsInited = FcFalse; 382} 383 384const char * 385FcObjectName (FcObject object) 386{ 387 FcObjectType *o = FcObjectFindById (object); 388 389 if (o) 390 return o->object; 391 return NULL; 392} 393 394static const FcConstant _FcBaseConstants[] = { 395 { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, }, 396 { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, }, 397 { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, }, 398 { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, }, 399 { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, }, 400 { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, }, 401 { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, }, 402 { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, }, 403 { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, }, 404 { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, }, 405 { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, }, 406 { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, }, 407 { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, }, 408 { (FcChar8 *) "heavy", "weight", FC_WEIGHT_HEAVY, }, 409 410 { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, }, 411 { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, }, 412 { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, }, 413 414 { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED }, 415 { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED }, 416 { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED }, 417 { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED }, 418 { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL }, 419 { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED }, 420 { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED }, 421 { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED }, 422 { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED }, 423 424 { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, }, 425 { (FcChar8 *) "dual", "spacing", FC_DUAL, }, 426 { (FcChar8 *) "mono", "spacing", FC_MONO, }, 427 { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, }, 428 429 { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN }, 430 { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, }, 431 { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, }, 432 { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB }, 433 { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR }, 434 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE }, 435 436 { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE }, 437 { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT }, 438 { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM }, 439 { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL }, 440 441 { (FcChar8 *) "antialias", "antialias", FcTrue }, 442 { (FcChar8 *) "hinting", "hinting", FcTrue }, 443 { (FcChar8 *) "verticallayout", "verticallayout", FcTrue }, 444 { (FcChar8 *) "autohint", "autohint", FcTrue }, 445 { (FcChar8 *) "globaladvance", "globaladvance", FcTrue }, /* deprecated */ 446 { (FcChar8 *) "outline", "outline", FcTrue }, 447 { (FcChar8 *) "scalable", "scalable", FcTrue }, 448 { (FcChar8 *) "minspace", "minspace", FcTrue }, 449 { (FcChar8 *) "embolden", "embolden", FcTrue }, 450 { (FcChar8 *) "embeddedbitmap", "embeddedbitmap", FcTrue }, 451 { (FcChar8 *) "decorative", "decorative", FcTrue }, 452 { (FcChar8 *) "lcdnone", "lcdfilter", FC_LCD_NONE }, 453 { (FcChar8 *) "lcddefault", "lcdfilter", FC_LCD_DEFAULT }, 454 { (FcChar8 *) "lcdlight", "lcdfilter", FC_LCD_LIGHT }, 455 { (FcChar8 *) "lcdlegacy", "lcdfilter", FC_LCD_LEGACY }, 456}; 457 458#define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0]) 459 460typedef struct _FcConstantList FcConstantList; 461 462struct _FcConstantList { 463 const FcConstantList *next; 464 const FcConstant *consts; 465 int nconsts; 466}; 467 468static const FcConstantList _FcBaseConstantList = { 469 0, 470 _FcBaseConstants, 471 NUM_FC_CONSTANTS 472}; 473 474static const FcConstantList *_FcConstants = &_FcBaseConstantList; 475 476FcBool 477FcNameRegisterConstants (const FcConstant *consts, int nconsts) 478{ 479 FcConstantList *l; 480 481 l = (FcConstantList *) malloc (sizeof (FcConstantList)); 482 if (!l) 483 return FcFalse; 484 FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList)); 485 l->consts = consts; 486 l->nconsts = nconsts; 487 l->next = _FcConstants; 488 _FcConstants = l; 489 return FcTrue; 490} 491 492FcBool 493FcNameUnregisterConstants (const FcConstant *consts, int nconsts) 494{ 495 const FcConstantList *l, **prev; 496 497 for (prev = &_FcConstants; 498 (l = *prev); 499 prev = (const FcConstantList **) &(l->next)) 500 { 501 if (l->consts == consts && l->nconsts == nconsts) 502 { 503 *prev = l->next; 504 FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList)); 505 free ((void *) l); 506 return FcTrue; 507 } 508 } 509 return FcFalse; 510} 511 512const FcConstant * 513FcNameGetConstant (const FcChar8 *string) 514{ 515 const FcConstantList *l; 516 int i; 517 518 for (l = _FcConstants; l; l = l->next) 519 { 520 for (i = 0; i < l->nconsts; i++) 521 if (!FcStrCmpIgnoreCase (string, l->consts[i].name)) 522 return &l->consts[i]; 523 } 524 return 0; 525} 526 527FcBool 528FcNameConstant (const FcChar8 *string, int *result) 529{ 530 const FcConstant *c; 531 532 if ((c = FcNameGetConstant(string))) 533 { 534 *result = c->value; 535 return FcTrue; 536 } 537 return FcFalse; 538} 539 540FcBool 541FcNameBool (const FcChar8 *v, FcBool *result) 542{ 543 char c0, c1; 544 545 c0 = *v; 546 c0 = FcToLower (c0); 547 if (c0 == 't' || c0 == 'y' || c0 == '1') 548 { 549 *result = FcTrue; 550 return FcTrue; 551 } 552 if (c0 == 'f' || c0 == 'n' || c0 == '0') 553 { 554 *result = FcFalse; 555 return FcTrue; 556 } 557 if (c0 == 'o') 558 { 559 c1 = v[1]; 560 c1 = FcToLower (c1); 561 if (c1 == 'n') 562 { 563 *result = FcTrue; 564 return FcTrue; 565 } 566 if (c1 == 'f') 567 { 568 *result = FcFalse; 569 return FcTrue; 570 } 571 } 572 return FcFalse; 573} 574 575static FcValue 576FcNameConvert (FcType type, FcChar8 *string) 577{ 578 FcValue v; 579 FcMatrix m; 580 581 v.type = type; 582 switch (v.type) { 583 case FcTypeInteger: 584 if (!FcNameConstant (string, &v.u.i)) 585 v.u.i = atoi ((char *) string); 586 break; 587 case FcTypeString: 588 v.u.s = FcSharedStr (string); 589 if (!v.u.s) 590 v.type = FcTypeVoid; 591 break; 592 case FcTypeBool: 593 if (!FcNameBool (string, &v.u.b)) 594 v.u.b = FcFalse; 595 break; 596 case FcTypeDouble: 597 v.u.d = strtod ((char *) string, 0); 598 break; 599 case FcTypeMatrix: 600 sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy); 601 v.u.m = FcMatrixCopy (&m); 602 break; 603 case FcTypeCharSet: 604 v.u.c = FcNameParseCharSet (string); 605 if (!v.u.c) 606 v.type = FcTypeVoid; 607 break; 608 case FcTypeLangSet: 609 v.u.l = FcNameParseLangSet (string); 610 if (!v.u.l) 611 v.type = FcTypeVoid; 612 break; 613 default: 614 break; 615 } 616 return v; 617} 618 619static const FcChar8 * 620FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last) 621{ 622 FcChar8 c; 623 624 while ((c = *cur)) 625 { 626 if (c == '\\') 627 { 628 ++cur; 629 if (!(c = *cur)) 630 break; 631 } 632 else if (strchr (delim, c)) 633 break; 634 ++cur; 635 *save++ = c; 636 } 637 *save = 0; 638 *last = *cur; 639 if (*cur) 640 cur++; 641 return cur; 642} 643 644FcPattern * 645FcNameParse (const FcChar8 *name) 646{ 647 FcChar8 *save; 648 FcPattern *pat; 649 double d; 650 FcChar8 *e; 651 FcChar8 delim; 652 FcValue v; 653 const FcObjectType *t; 654 const FcConstant *c; 655 656 /* freed below */ 657 save = malloc (strlen ((char *) name) + 1); 658 if (!save) 659 goto bail0; 660 pat = FcPatternCreate (); 661 if (!pat) 662 goto bail1; 663 664 for (;;) 665 { 666 name = FcNameFindNext (name, "-,:", save, &delim); 667 if (save[0]) 668 { 669 if (!FcPatternAddString (pat, FC_FAMILY, save)) 670 goto bail2; 671 } 672 if (delim != ',') 673 break; 674 } 675 if (delim == '-') 676 { 677 for (;;) 678 { 679 name = FcNameFindNext (name, "-,:", save, &delim); 680 d = strtod ((char *) save, (char **) &e); 681 if (e != save) 682 { 683 if (!FcPatternAddDouble (pat, FC_SIZE, d)) 684 goto bail2; 685 } 686 if (delim != ',') 687 break; 688 } 689 } 690 while (delim == ':') 691 { 692 name = FcNameFindNext (name, "=_:", save, &delim); 693 if (save[0]) 694 { 695 if (delim == '=' || delim == '_') 696 { 697 t = FcNameGetObjectType ((char *) save); 698 for (;;) 699 { 700 name = FcNameFindNext (name, ":,", save, &delim); 701 if (t) 702 { 703 v = FcNameConvert (t->type, save); 704 if (!FcPatternAdd (pat, t->object, v, FcTrue)) 705 { 706 FcValueDestroy (v); 707 goto bail2; 708 } 709 FcValueDestroy (v); 710 } 711 if (delim != ',') 712 break; 713 } 714 } 715 else 716 { 717 if ((c = FcNameGetConstant (save))) 718 { 719 t = FcNameGetObjectType ((char *) c->object); 720 switch (t->type) { 721 case FcTypeInteger: 722 case FcTypeDouble: 723 if (!FcPatternAddInteger (pat, c->object, c->value)) 724 goto bail2; 725 break; 726 case FcTypeBool: 727 if (!FcPatternAddBool (pat, c->object, c->value)) 728 goto bail2; 729 break; 730 default: 731 break; 732 } 733 } 734 } 735 } 736 } 737 738 free (save); 739 return pat; 740 741bail2: 742 FcPatternDestroy (pat); 743bail1: 744 free (save); 745bail0: 746 return 0; 747} 748static FcBool 749FcNameUnparseString (FcStrBuf *buf, 750 const FcChar8 *string, 751 const FcChar8 *escape) 752{ 753 FcChar8 c; 754 while ((c = *string++)) 755 { 756 if (escape && strchr ((char *) escape, (char) c)) 757 { 758 if (!FcStrBufChar (buf, escape[0])) 759 return FcFalse; 760 } 761 if (!FcStrBufChar (buf, c)) 762 return FcFalse; 763 } 764 return FcTrue; 765} 766 767FcBool 768FcNameUnparseValue (FcStrBuf *buf, 769 FcValue *v0, 770 FcChar8 *escape) 771{ 772 FcChar8 temp[1024]; 773 FcValue v = FcValueCanonicalize(v0); 774 775 switch (v.type) { 776 case FcTypeVoid: 777 return FcTrue; 778 case FcTypeInteger: 779 sprintf ((char *) temp, "%d", v.u.i); 780 return FcNameUnparseString (buf, temp, 0); 781 case FcTypeDouble: 782 sprintf ((char *) temp, "%g", v.u.d); 783 return FcNameUnparseString (buf, temp, 0); 784 case FcTypeString: 785 return FcNameUnparseString (buf, v.u.s, escape); 786 case FcTypeBool: 787 return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); 788 case FcTypeMatrix: 789 sprintf ((char *) temp, "%g %g %g %g", 790 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); 791 return FcNameUnparseString (buf, temp, 0); 792 case FcTypeCharSet: 793 return FcNameUnparseCharSet (buf, v.u.c); 794 case FcTypeLangSet: 795 return FcNameUnparseLangSet (buf, v.u.l); 796 case FcTypeFTFace: 797 return FcTrue; 798 } 799 return FcFalse; 800} 801 802FcBool 803FcNameUnparseValueList (FcStrBuf *buf, 804 FcValueListPtr v, 805 FcChar8 *escape) 806{ 807 while (v) 808 { 809 if (!FcNameUnparseValue (buf, &v->value, escape)) 810 return FcFalse; 811 if ((v = FcValueListNext(v)) != NULL) 812 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0)) 813 return FcFalse; 814 } 815 return FcTrue; 816} 817 818#define FC_ESCAPE_FIXED "\\-:," 819#define FC_ESCAPE_VARIABLE "\\=_:," 820 821FcChar8 * 822FcNameUnparse (FcPattern *pat) 823{ 824 return FcNameUnparseEscaped (pat, FcTrue); 825} 826 827FcChar8 * 828FcNameUnparseEscaped (FcPattern *pat, FcBool escape) 829{ 830 FcStrBuf buf; 831 FcChar8 buf_static[8192]; 832 int i; 833 FcPatternElt *e; 834 const FcObjectTypeList *l; 835 const FcObjectType *o; 836 837 FcStrBufInit (&buf, buf_static, sizeof (buf_static)); 838 e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT); 839 if (e) 840 { 841 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) 842 goto bail0; 843 } 844 e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT); 845 if (e) 846 { 847 if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0)) 848 goto bail0; 849 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) 850 goto bail0; 851 } 852 for (l = _FcObjectTypes; l; l = l->next) 853 { 854 for (i = 0; i < l->ntypes; i++) 855 { 856 o = &l->types[i]; 857 if (!strcmp (o->object, FC_FAMILY) || 858 !strcmp (o->object, FC_SIZE)) 859 continue; 860 861 e = FcPatternObjectFindElt (pat, FcObjectFromName (o->object)); 862 if (e) 863 { 864 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0)) 865 goto bail0; 866 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) 867 goto bail0; 868 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0)) 869 goto bail0; 870 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? 871 (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) 872 goto bail0; 873 } 874 } 875 } 876 return FcStrBufDone (&buf); 877bail0: 878 FcStrBufDestroy (&buf); 879 return 0; 880} 881#define __fcname__ 882#include "fcaliastail.h" 883#undef __fcname__ 884