fcname.c revision 725ddd73
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 31static const FcObjectType FcObjects[] = { 32#define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type }, 33#include "fcobjs.h" 34#undef FC_OBJECT 35}; 36 37#define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0])) 38 39static const FcObjectType * 40FcObjectFindById (FcObject object) 41{ 42 if (1 <= object && object <= NUM_OBJECT_TYPES) 43 return &FcObjects[object - 1]; 44 return FcObjectLookupOtherTypeById (object); 45} 46 47FcBool 48FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes) 49{ 50 /* Deprecated. */ 51 return FcFalse; 52} 53 54FcBool 55FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes) 56{ 57 /* Deprecated. */ 58 return FcFalse; 59} 60 61const FcObjectType * 62FcNameGetObjectType (const char *object) 63{ 64 int id = FcObjectLookupBuiltinIdByName (object); 65 66 if (!id) 67 return FcObjectLookupOtherTypeByName (object); 68 69 return &FcObjects[id - 1]; 70} 71 72FcBool 73FcObjectValidType (FcObject object, FcType type) 74{ 75 const FcObjectType *t = FcObjectFindById (object); 76 77 if (t) { 78 switch ((int) t->type) { 79 case FcTypeDouble: 80 case FcTypeInteger: 81 if (type == FcTypeDouble || type == FcTypeInteger) 82 return FcTrue; 83 break; 84 case FcTypeLangSet: 85 if (type == FcTypeLangSet || type == FcTypeString) 86 return FcTrue; 87 break; 88 default: 89 if ((unsigned int) t->type == (unsigned int) -1 || type == t->type) 90 return FcTrue; 91 break; 92 } 93 return FcFalse; 94 } 95 return FcTrue; 96} 97 98FcObject 99FcObjectFromName (const char * name) 100{ 101 return FcObjectLookupIdByName (name); 102} 103 104FcObjectSet * 105FcObjectGetSet (void) 106{ 107 int i; 108 FcObjectSet *os = NULL; 109 110 111 os = FcObjectSetCreate (); 112 for (i = 0; i < NUM_OBJECT_TYPES; i++) 113 FcObjectSetAdd (os, FcObjects[i].object); 114 115 return os; 116} 117 118const char * 119FcObjectName (FcObject object) 120{ 121 const FcObjectType *o = FcObjectFindById (object); 122 123 if (o) 124 return o->object; 125 126 return FcObjectLookupOtherNameById (object); 127} 128 129static const FcConstant _FcBaseConstants[] = { 130 { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, }, 131 { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, }, 132 { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, }, 133 { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, }, 134 { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, }, 135 { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, }, 136 { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, }, 137 { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, }, 138 { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, }, 139 { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, }, 140 { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, }, 141 { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, }, 142 { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, }, 143 { (FcChar8 *) "heavy", "weight", FC_WEIGHT_HEAVY, }, 144 145 { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, }, 146 { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, }, 147 { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, }, 148 149 { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED }, 150 { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED }, 151 { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED }, 152 { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED }, 153 { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL }, 154 { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED }, 155 { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED }, 156 { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED }, 157 { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED }, 158 159 { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, }, 160 { (FcChar8 *) "dual", "spacing", FC_DUAL, }, 161 { (FcChar8 *) "mono", "spacing", FC_MONO, }, 162 { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, }, 163 164 { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN }, 165 { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, }, 166 { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, }, 167 { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB }, 168 { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR }, 169 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE }, 170 171 { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE }, 172 { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT }, 173 { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM }, 174 { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL }, 175 176 { (FcChar8 *) "antialias", "antialias", FcTrue }, 177 { (FcChar8 *) "hinting", "hinting", FcTrue }, 178 { (FcChar8 *) "verticallayout", "verticallayout", FcTrue }, 179 { (FcChar8 *) "autohint", "autohint", FcTrue }, 180 { (FcChar8 *) "globaladvance", "globaladvance", FcTrue }, /* deprecated */ 181 { (FcChar8 *) "outline", "outline", FcTrue }, 182 { (FcChar8 *) "scalable", "scalable", FcTrue }, 183 { (FcChar8 *) "minspace", "minspace", FcTrue }, 184 { (FcChar8 *) "embolden", "embolden", FcTrue }, 185 { (FcChar8 *) "embeddedbitmap", "embeddedbitmap", FcTrue }, 186 { (FcChar8 *) "decorative", "decorative", FcTrue }, 187 { (FcChar8 *) "lcdnone", "lcdfilter", FC_LCD_NONE }, 188 { (FcChar8 *) "lcddefault", "lcdfilter", FC_LCD_DEFAULT }, 189 { (FcChar8 *) "lcdlight", "lcdfilter", FC_LCD_LIGHT }, 190 { (FcChar8 *) "lcdlegacy", "lcdfilter", FC_LCD_LEGACY }, 191}; 192 193#define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0]) 194 195FcBool 196FcNameRegisterConstants (const FcConstant *consts, int nconsts) 197{ 198 /* Deprecated. */ 199 return FcFalse; 200} 201 202FcBool 203FcNameUnregisterConstants (const FcConstant *consts, int nconsts) 204{ 205 /* Deprecated. */ 206 return FcFalse; 207} 208 209const FcConstant * 210FcNameGetConstant (const FcChar8 *string) 211{ 212 unsigned int i; 213 214 for (i = 0; i < NUM_FC_CONSTANTS; i++) 215 if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name)) 216 return &_FcBaseConstants[i]; 217 218 return 0; 219} 220 221FcBool 222FcNameConstant (const FcChar8 *string, int *result) 223{ 224 const FcConstant *c; 225 226 if ((c = FcNameGetConstant(string))) 227 { 228 *result = c->value; 229 return FcTrue; 230 } 231 return FcFalse; 232} 233 234FcBool 235FcNameBool (const FcChar8 *v, FcBool *result) 236{ 237 char c0, c1; 238 239 c0 = *v; 240 c0 = FcToLower (c0); 241 if (c0 == 't' || c0 == 'y' || c0 == '1') 242 { 243 *result = FcTrue; 244 return FcTrue; 245 } 246 if (c0 == 'f' || c0 == 'n' || c0 == '0') 247 { 248 *result = FcFalse; 249 return FcTrue; 250 } 251 if (c0 == 'o') 252 { 253 c1 = v[1]; 254 c1 = FcToLower (c1); 255 if (c1 == 'n') 256 { 257 *result = FcTrue; 258 return FcTrue; 259 } 260 if (c1 == 'f') 261 { 262 *result = FcFalse; 263 return FcTrue; 264 } 265 } 266 return FcFalse; 267} 268 269static FcValue 270FcNameConvert (FcType type, FcChar8 *string) 271{ 272 FcValue v; 273 FcMatrix m; 274 275 v.type = type; 276 switch ((int) v.type) { 277 case FcTypeInteger: 278 if (!FcNameConstant (string, &v.u.i)) 279 v.u.i = atoi ((char *) string); 280 break; 281 case FcTypeString: 282 v.u.s = FcStrdup (string); 283 if (!v.u.s) 284 v.type = FcTypeVoid; 285 break; 286 case FcTypeBool: 287 if (!FcNameBool (string, &v.u.b)) 288 v.u.b = FcFalse; 289 break; 290 case FcTypeDouble: 291 v.u.d = strtod ((char *) string, 0); 292 break; 293 case FcTypeMatrix: 294 FcMatrixInit (&m); 295 sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy); 296 v.u.m = FcMatrixCopy (&m); 297 break; 298 case FcTypeCharSet: 299 v.u.c = FcNameParseCharSet (string); 300 if (!v.u.c) 301 v.type = FcTypeVoid; 302 break; 303 case FcTypeLangSet: 304 v.u.l = FcNameParseLangSet (string); 305 if (!v.u.l) 306 v.type = FcTypeVoid; 307 break; 308 default: 309 break; 310 } 311 return v; 312} 313 314static const FcChar8 * 315FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last) 316{ 317 FcChar8 c; 318 319 while ((c = *cur)) 320 { 321 if (c == '\\') 322 { 323 ++cur; 324 if (!(c = *cur)) 325 break; 326 } 327 else if (strchr (delim, c)) 328 break; 329 ++cur; 330 *save++ = c; 331 } 332 *save = 0; 333 *last = *cur; 334 if (*cur) 335 cur++; 336 return cur; 337} 338 339FcPattern * 340FcNameParse (const FcChar8 *name) 341{ 342 FcChar8 *save; 343 FcPattern *pat; 344 double d; 345 FcChar8 *e; 346 FcChar8 delim; 347 FcValue v; 348 const FcObjectType *t; 349 const FcConstant *c; 350 351 /* freed below */ 352 save = malloc (strlen ((char *) name) + 1); 353 if (!save) 354 goto bail0; 355 pat = FcPatternCreate (); 356 if (!pat) 357 goto bail1; 358 359 for (;;) 360 { 361 name = FcNameFindNext (name, "-,:", save, &delim); 362 if (save[0]) 363 { 364 if (!FcPatternAddString (pat, FC_FAMILY, save)) 365 goto bail2; 366 } 367 if (delim != ',') 368 break; 369 } 370 if (delim == '-') 371 { 372 for (;;) 373 { 374 name = FcNameFindNext (name, "-,:", save, &delim); 375 d = strtod ((char *) save, (char **) &e); 376 if (e != save) 377 { 378 if (!FcPatternAddDouble (pat, FC_SIZE, d)) 379 goto bail2; 380 } 381 if (delim != ',') 382 break; 383 } 384 } 385 while (delim == ':') 386 { 387 name = FcNameFindNext (name, "=_:", save, &delim); 388 if (save[0]) 389 { 390 if (delim == '=' || delim == '_') 391 { 392 t = FcNameGetObjectType ((char *) save); 393 for (;;) 394 { 395 name = FcNameFindNext (name, ":,", save, &delim); 396 if (t) 397 { 398 v = FcNameConvert (t->type, save); 399 if (!FcPatternAdd (pat, t->object, v, FcTrue)) 400 { 401 FcValueDestroy (v); 402 goto bail2; 403 } 404 FcValueDestroy (v); 405 } 406 if (delim != ',') 407 break; 408 } 409 } 410 else 411 { 412 if ((c = FcNameGetConstant (save))) 413 { 414 t = FcNameGetObjectType ((char *) c->object); 415 switch ((int) t->type) { 416 case FcTypeInteger: 417 case FcTypeDouble: 418 if (!FcPatternAddInteger (pat, c->object, c->value)) 419 goto bail2; 420 break; 421 case FcTypeBool: 422 if (!FcPatternAddBool (pat, c->object, c->value)) 423 goto bail2; 424 break; 425 default: 426 break; 427 } 428 } 429 } 430 } 431 } 432 433 free (save); 434 return pat; 435 436bail2: 437 FcPatternDestroy (pat); 438bail1: 439 free (save); 440bail0: 441 return 0; 442} 443static FcBool 444FcNameUnparseString (FcStrBuf *buf, 445 const FcChar8 *string, 446 const FcChar8 *escape) 447{ 448 FcChar8 c; 449 while ((c = *string++)) 450 { 451 if (escape && strchr ((char *) escape, (char) c)) 452 { 453 if (!FcStrBufChar (buf, escape[0])) 454 return FcFalse; 455 } 456 if (!FcStrBufChar (buf, c)) 457 return FcFalse; 458 } 459 return FcTrue; 460} 461 462FcBool 463FcNameUnparseValue (FcStrBuf *buf, 464 FcValue *v0, 465 FcChar8 *escape) 466{ 467 FcChar8 temp[1024]; 468 FcValue v = FcValueCanonicalize(v0); 469 470 switch (v.type) { 471 case FcTypeVoid: 472 return FcTrue; 473 case FcTypeInteger: 474 sprintf ((char *) temp, "%d", v.u.i); 475 return FcNameUnparseString (buf, temp, 0); 476 case FcTypeDouble: 477 sprintf ((char *) temp, "%g", v.u.d); 478 return FcNameUnparseString (buf, temp, 0); 479 case FcTypeString: 480 return FcNameUnparseString (buf, v.u.s, escape); 481 case FcTypeBool: 482 return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); 483 case FcTypeMatrix: 484 sprintf ((char *) temp, "%g %g %g %g", 485 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); 486 return FcNameUnparseString (buf, temp, 0); 487 case FcTypeCharSet: 488 return FcNameUnparseCharSet (buf, v.u.c); 489 case FcTypeLangSet: 490 return FcNameUnparseLangSet (buf, v.u.l); 491 case FcTypeFTFace: 492 return FcTrue; 493 } 494 return FcFalse; 495} 496 497FcBool 498FcNameUnparseValueList (FcStrBuf *buf, 499 FcValueListPtr v, 500 FcChar8 *escape) 501{ 502 while (v) 503 { 504 if (!FcNameUnparseValue (buf, &v->value, escape)) 505 return FcFalse; 506 if ((v = FcValueListNext(v)) != NULL) 507 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0)) 508 return FcFalse; 509 } 510 return FcTrue; 511} 512 513#define FC_ESCAPE_FIXED "\\-:," 514#define FC_ESCAPE_VARIABLE "\\=_:," 515 516FcChar8 * 517FcNameUnparse (FcPattern *pat) 518{ 519 return FcNameUnparseEscaped (pat, FcTrue); 520} 521 522FcChar8 * 523FcNameUnparseEscaped (FcPattern *pat, FcBool escape) 524{ 525 FcStrBuf buf; 526 FcChar8 buf_static[8192]; 527 int i; 528 FcPatternElt *e; 529 530 FcStrBufInit (&buf, buf_static, sizeof (buf_static)); 531 e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT); 532 if (e) 533 { 534 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) 535 goto bail0; 536 } 537 e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT); 538 if (e) 539 { 540 if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0)) 541 goto bail0; 542 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) 543 goto bail0; 544 } 545 for (i = 0; i < NUM_OBJECT_TYPES; i++) 546 { 547 FcObject id = i + 1; 548 const FcObjectType *o; 549 o = &FcObjects[i]; 550 if (!strcmp (o->object, FC_FAMILY) || 551 !strcmp (o->object, FC_SIZE)) 552 continue; 553 554 e = FcPatternObjectFindElt (pat, id); 555 if (e) 556 { 557 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0)) 558 goto bail0; 559 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) 560 goto bail0; 561 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0)) 562 goto bail0; 563 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? 564 (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) 565 goto bail0; 566 } 567 } 568 return FcStrBufDone (&buf); 569bail0: 570 FcStrBufDestroy (&buf); 571 return 0; 572} 573#define __fcname__ 574#include "fcaliastail.h" 575#undef __fcname__ 576