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