fcpat.c revision 6fc018e4
1/* 2 * Copyright © 2000 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of the author(s) not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. The authors make no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#include "fcint.h" 24#include "fcftint.h" 25 26/* Objects MT-safe for readonly access. */ 27 28FcPattern * 29FcPatternCreate (void) 30{ 31 FcPattern *p; 32 33 p = (FcPattern *) malloc (sizeof (FcPattern)); 34 if (!p) 35 return 0; 36 p->num = 0; 37 p->size = 0; 38 p->elts_offset = FcPtrToOffset (p, NULL); 39 FcRefInit (&p->ref, 1); 40 return p; 41} 42 43void 44FcValueDestroy (FcValue v) 45{ 46 switch ((int) v.type) { 47 case FcTypeString: 48 FcFree (v.u.s); 49 break; 50 case FcTypeMatrix: 51 FcMatrixFree ((FcMatrix *) v.u.m); 52 break; 53 case FcTypeCharSet: 54 FcCharSetDestroy ((FcCharSet *) v.u.c); 55 break; 56 case FcTypeLangSet: 57 FcLangSetDestroy ((FcLangSet *) v.u.l); 58 break; 59 default: 60 break; 61 } 62} 63 64FcValue 65FcValueCanonicalize (const FcValue *v) 66{ 67 FcValue new; 68 69 switch ((int) v->type) 70 { 71 case FcTypeString: 72 new.u.s = FcValueString(v); 73 new.type = FcTypeString; 74 break; 75 case FcTypeCharSet: 76 new.u.c = FcValueCharSet(v); 77 new.type = FcTypeCharSet; 78 break; 79 case FcTypeLangSet: 80 new.u.l = FcValueLangSet(v); 81 new.type = FcTypeLangSet; 82 break; 83 default: 84 new = *v; 85 break; 86 } 87 return new; 88} 89 90FcValue 91FcValueSave (FcValue v) 92{ 93 switch ((int) v.type) { 94 case FcTypeString: 95 v.u.s = FcStrdup (v.u.s); 96 if (!v.u.s) 97 v.type = FcTypeVoid; 98 break; 99 case FcTypeMatrix: 100 v.u.m = FcMatrixCopy (v.u.m); 101 if (!v.u.m) 102 v.type = FcTypeVoid; 103 break; 104 case FcTypeCharSet: 105 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c); 106 if (!v.u.c) 107 v.type = FcTypeVoid; 108 break; 109 case FcTypeLangSet: 110 v.u.l = FcLangSetCopy (v.u.l); 111 if (!v.u.l) 112 v.type = FcTypeVoid; 113 break; 114 default: 115 break; 116 } 117 return v; 118} 119 120FcValueListPtr 121FcValueListCreate (void) 122{ 123 return calloc (1, sizeof (FcValueList)); 124} 125 126void 127FcValueListDestroy (FcValueListPtr l) 128{ 129 FcValueListPtr next; 130 for (; l; l = next) 131 { 132 switch ((int) l->value.type) { 133 case FcTypeString: 134 FcFree (l->value.u.s); 135 break; 136 case FcTypeMatrix: 137 FcMatrixFree ((FcMatrix *)l->value.u.m); 138 break; 139 case FcTypeCharSet: 140 FcCharSetDestroy 141 ((FcCharSet *) (l->value.u.c)); 142 break; 143 case FcTypeLangSet: 144 FcLangSetDestroy 145 ((FcLangSet *) (l->value.u.l)); 146 break; 147 default: 148 break; 149 } 150 next = FcValueListNext(l); 151 free(l); 152 } 153} 154 155FcValueListPtr 156FcValueListPrepend (FcValueListPtr vallist, 157 FcValue value, 158 FcValueBinding binding) 159{ 160 FcValueListPtr new; 161 162 if (value.type == FcTypeVoid) 163 return vallist; 164 new = FcValueListCreate (); 165 if (!new) 166 return vallist; 167 168 new->value = FcValueSave (value); 169 new->binding = binding; 170 new->next = vallist; 171 172 return new; 173} 174 175FcValueListPtr 176FcValueListAppend (FcValueListPtr vallist, 177 FcValue value, 178 FcValueBinding binding) 179{ 180 FcValueListPtr new, last; 181 182 if (value.type == FcTypeVoid) 183 return vallist; 184 new = FcValueListCreate (); 185 if (!new) 186 return vallist; 187 188 new->value = FcValueSave (value); 189 new->binding = binding; 190 new->next = NULL; 191 192 if (vallist) 193 { 194 for (last = vallist; FcValueListNext (last); last = FcValueListNext (last)); 195 196 last->next = new; 197 } 198 else 199 vallist = new; 200 201 return vallist; 202} 203 204FcValueListPtr 205FcValueListDuplicate(FcValueListPtr orig) 206{ 207 FcValueListPtr new = NULL, l, t = NULL; 208 FcValue v; 209 210 for (l = orig; l != NULL; l = FcValueListNext (l)) 211 { 212 if (!new) 213 { 214 t = new = FcValueListCreate(); 215 } 216 else 217 { 218 t->next = FcValueListCreate(); 219 t = FcValueListNext (t); 220 } 221 v = FcValueCanonicalize (&l->value); 222 t->value = FcValueSave (v); 223 t->binding = l->binding; 224 t->next = NULL; 225 } 226 227 return new; 228} 229 230FcBool 231FcValueEqual (FcValue va, FcValue vb) 232{ 233 if (va.type != vb.type) 234 { 235 if (va.type == FcTypeInteger) 236 { 237 va.type = FcTypeDouble; 238 va.u.d = va.u.i; 239 } 240 if (vb.type == FcTypeInteger) 241 { 242 vb.type = FcTypeDouble; 243 vb.u.d = vb.u.i; 244 } 245 if (va.type != vb.type) 246 return FcFalse; 247 } 248 switch (va.type) { 249 case FcTypeUnknown: 250 return FcFalse; /* don't know how to compare this object */ 251 case FcTypeVoid: 252 return FcTrue; 253 case FcTypeInteger: 254 return va.u.i == vb.u.i; 255 case FcTypeDouble: 256 return va.u.d == vb.u.d; 257 case FcTypeString: 258 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0; 259 case FcTypeBool: 260 return va.u.b == vb.u.b; 261 case FcTypeMatrix: 262 return FcMatrixEqual (va.u.m, vb.u.m); 263 case FcTypeCharSet: 264 return FcCharSetEqual (va.u.c, vb.u.c); 265 case FcTypeFTFace: 266 return va.u.f == vb.u.f; 267 case FcTypeLangSet: 268 return FcLangSetEqual (va.u.l, vb.u.l); 269 } 270 return FcFalse; 271} 272 273static FcChar32 274FcDoubleHash (double d) 275{ 276 if (d < 0) 277 d = -d; 278 if (d > 0xffffffff) 279 d = 0xffffffff; 280 return (FcChar32) d; 281} 282 283FcChar32 284FcStringHash (const FcChar8 *s) 285{ 286 FcChar8 c; 287 FcChar32 h = 0; 288 289 if (s) 290 while ((c = *s++)) 291 h = ((h << 1) | (h >> 31)) ^ c; 292 return h; 293} 294 295static FcChar32 296FcValueHash (const FcValue *v) 297{ 298 switch (v->type) { 299 case FcTypeUnknown: 300 case FcTypeVoid: 301 return 0; 302 case FcTypeInteger: 303 return (FcChar32) v->u.i; 304 case FcTypeDouble: 305 return FcDoubleHash (v->u.d); 306 case FcTypeString: 307 return FcStringHash (FcValueString(v)); 308 case FcTypeBool: 309 return (FcChar32) v->u.b; 310 case FcTypeMatrix: 311 return (FcDoubleHash (v->u.m->xx) ^ 312 FcDoubleHash (v->u.m->xy) ^ 313 FcDoubleHash (v->u.m->yx) ^ 314 FcDoubleHash (v->u.m->yy)); 315 case FcTypeCharSet: 316 return (FcChar32) FcValueCharSet(v)->num; 317 case FcTypeFTFace: 318 return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^ 319 FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name); 320 case FcTypeLangSet: 321 return FcLangSetHash (FcValueLangSet(v)); 322 } 323 return 0; 324} 325 326static FcBool 327FcValueListEqual (FcValueListPtr la, FcValueListPtr lb) 328{ 329 if (la == lb) 330 return FcTrue; 331 332 while (la && lb) 333 { 334 if (!FcValueEqual (la->value, lb->value)) 335 return FcFalse; 336 la = FcValueListNext(la); 337 lb = FcValueListNext(lb); 338 } 339 if (la || lb) 340 return FcFalse; 341 return FcTrue; 342} 343 344static FcChar32 345FcValueListHash (FcValueListPtr l) 346{ 347 FcChar32 hash = 0; 348 349 for (; l; l = FcValueListNext(l)) 350 { 351 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value); 352 } 353 return hash; 354} 355 356void 357FcPatternDestroy (FcPattern *p) 358{ 359 int i; 360 FcPatternElt *elts; 361 362 if (!p) 363 return; 364 365 if (FcRefIsConst (&p->ref)) 366 { 367 FcCacheObjectDereference (p); 368 return; 369 } 370 371 if (FcRefDec (&p->ref) != 1) 372 return; 373 374 elts = FcPatternElts (p); 375 for (i = 0; i < p->num; i++) 376 FcValueListDestroy (FcPatternEltValues(&elts[i])); 377 378 free (elts); 379 free (p); 380} 381 382static int 383FcPatternObjectPosition (const FcPattern *p, FcObject object) 384{ 385 int low, high, mid, c; 386 FcPatternElt *elts = FcPatternElts(p); 387 388 low = 0; 389 high = p->num - 1; 390 c = 1; 391 mid = 0; 392 while (low <= high) 393 { 394 mid = (low + high) >> 1; 395 c = elts[mid].object - object; 396 if (c == 0) 397 return mid; 398 if (c < 0) 399 low = mid + 1; 400 else 401 high = mid - 1; 402 } 403 if (c < 0) 404 mid++; 405 return -(mid + 1); 406} 407 408FcPatternElt * 409FcPatternObjectFindElt (const FcPattern *p, FcObject object) 410{ 411 int i = FcPatternObjectPosition (p, object); 412 if (i < 0) 413 return 0; 414 return &FcPatternElts(p)[i]; 415} 416 417FcPatternElt * 418FcPatternObjectInsertElt (FcPattern *p, FcObject object) 419{ 420 int i; 421 FcPatternElt *e; 422 423 i = FcPatternObjectPosition (p, object); 424 if (i < 0) 425 { 426 i = -i - 1; 427 428 /* reallocate array */ 429 if (p->num + 1 >= p->size) 430 { 431 int s = p->size + 16; 432 if (p->size) 433 { 434 FcPatternElt *e0 = FcPatternElts(p); 435 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt)); 436 if (!e) /* maybe it was mmapped */ 437 { 438 e = malloc(s * sizeof (FcPatternElt)); 439 if (e) 440 memcpy(e, e0, p->num * sizeof (FcPatternElt)); 441 } 442 } 443 else 444 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt)); 445 if (!e) 446 return FcFalse; 447 p->elts_offset = FcPtrToOffset (p, e); 448 while (p->size < s) 449 { 450 e[p->size].object = 0; 451 e[p->size].values = NULL; 452 p->size++; 453 } 454 } 455 456 e = FcPatternElts(p); 457 /* move elts up */ 458 memmove (e + i + 1, 459 e + i, 460 sizeof (FcPatternElt) * 461 (p->num - i)); 462 463 /* bump count */ 464 p->num++; 465 466 e[i].object = object; 467 e[i].values = NULL; 468 } 469 470 return FcPatternElts(p) + i; 471} 472 473FcBool 474FcPatternEqual (const FcPattern *pa, const FcPattern *pb) 475{ 476 int i; 477 FcPatternElt *pae, *pbe; 478 479 if (pa == pb) 480 return FcTrue; 481 482 if (pa->num != pb->num) 483 return FcFalse; 484 pae = FcPatternElts(pa); 485 pbe = FcPatternElts(pb); 486 for (i = 0; i < pa->num; i++) 487 { 488 if (pae[i].object != pbe[i].object) 489 return FcFalse; 490 if (!FcValueListEqual (FcPatternEltValues(&pae[i]), 491 FcPatternEltValues(&pbe[i]))) 492 return FcFalse; 493 } 494 return FcTrue; 495} 496 497FcChar32 498FcPatternHash (const FcPattern *p) 499{ 500 int i; 501 FcChar32 h = 0; 502 FcPatternElt *pe = FcPatternElts(p); 503 504 for (i = 0; i < p->num; i++) 505 { 506 h = (((h << 1) | (h >> 31)) ^ 507 pe[i].object ^ 508 FcValueListHash (FcPatternEltValues(&pe[i]))); 509 } 510 return h; 511} 512 513FcBool 514FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os) 515{ 516 FcPatternElt *ea, *eb; 517 int i; 518 519 for (i = 0; i < os->nobject; i++) 520 { 521 FcObject object = FcObjectFromName (os->objects[i]); 522 ea = FcPatternObjectFindElt (pai, object); 523 eb = FcPatternObjectFindElt (pbi, object); 524 if (ea) 525 { 526 if (!eb) 527 return FcFalse; 528 if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb))) 529 return FcFalse; 530 } 531 else 532 { 533 if (eb) 534 return FcFalse; 535 } 536 } 537 return FcTrue; 538} 539 540FcBool 541FcPatternObjectListAdd (FcPattern *p, 542 FcObject object, 543 FcValueListPtr list, 544 FcBool append) 545{ 546 FcPatternElt *e; 547 FcValueListPtr l, *prev; 548 549 if (FcRefIsConst (&p->ref)) 550 goto bail0; 551 552 /* 553 * Make sure the stored type is valid for built-in objects 554 */ 555 for (l = list; l != NULL; l = FcValueListNext (l)) 556 { 557 if (!FcObjectValidType (object, l->value.type)) 558 { 559 fprintf (stderr, 560 "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object)); 561 FcValuePrintFile (stderr, l->value); 562 fprintf (stderr, "\n"); 563 goto bail0; 564 } 565 } 566 567 e = FcPatternObjectInsertElt (p, object); 568 if (!e) 569 goto bail0; 570 571 if (append) 572 { 573 for (prev = &e->values; *prev; prev = &(*prev)->next) 574 ; 575 *prev = list; 576 } 577 else 578 { 579 for (prev = &list; *prev; prev = &(*prev)->next) 580 ; 581 *prev = e->values; 582 e->values = list; 583 } 584 585 return FcTrue; 586 587bail0: 588 return FcFalse; 589} 590 591FcBool 592FcPatternObjectAddWithBinding (FcPattern *p, 593 FcObject object, 594 FcValue value, 595 FcValueBinding binding, 596 FcBool append) 597{ 598 FcPatternElt *e; 599 FcValueListPtr new, *prev; 600 601 if (FcRefIsConst (&p->ref)) 602 goto bail0; 603 604 new = FcValueListCreate (); 605 if (!new) 606 goto bail0; 607 608 value = FcValueSave (value); 609 if (value.type == FcTypeVoid) 610 goto bail1; 611 612 /* 613 * Make sure the stored type is valid for built-in objects 614 */ 615 if (!FcObjectValidType (object, value.type)) 616 { 617 fprintf (stderr, 618 "Fontconfig warning: FcPattern object %s does not accept value", 619 FcObjectName (object)); 620 FcValuePrintFile (stderr, value); 621 fprintf (stderr, "\n"); 622 goto bail1; 623 } 624 625 new->value = value; 626 new->binding = binding; 627 new->next = NULL; 628 629 e = FcPatternObjectInsertElt (p, object); 630 if (!e) 631 goto bail2; 632 633 if (append) 634 { 635 for (prev = &e->values; *prev; prev = &(*prev)->next) 636 ; 637 *prev = new; 638 } 639 else 640 { 641 new->next = e->values; 642 e->values = new; 643 } 644 645 return FcTrue; 646 647bail2: 648 FcValueDestroy (value); 649bail1: 650 free (new); 651bail0: 652 return FcFalse; 653} 654 655FcBool 656FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append) 657{ 658 return FcPatternObjectAddWithBinding (p, object, 659 value, FcValueBindingStrong, append); 660} 661 662FcBool 663FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append) 664{ 665 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object), 666 value, FcValueBindingStrong, append); 667} 668 669FcBool 670FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append) 671{ 672 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object), 673 value, FcValueBindingWeak, append); 674} 675 676FcBool 677FcPatternObjectDel (FcPattern *p, FcObject object) 678{ 679 FcPatternElt *e; 680 681 e = FcPatternObjectFindElt (p, object); 682 if (!e) 683 return FcFalse; 684 685 /* destroy value */ 686 FcValueListDestroy (e->values); 687 688 /* shuffle existing ones down */ 689 memmove (e, e+1, 690 (FcPatternElts(p) + p->num - (e + 1)) * 691 sizeof (FcPatternElt)); 692 p->num--; 693 e = FcPatternElts(p) + p->num; 694 e->object = 0; 695 e->values = NULL; 696 return FcTrue; 697} 698 699FcBool 700FcPatternDel (FcPattern *p, const char *object) 701{ 702 return FcPatternObjectDel (p, FcObjectFromName (object)); 703} 704 705FcBool 706FcPatternRemove (FcPattern *p, const char *object, int id) 707{ 708 FcPatternElt *e; 709 FcValueListPtr *prev, l; 710 711 e = FcPatternObjectFindElt (p, FcObjectFromName (object)); 712 if (!e) 713 return FcFalse; 714 for (prev = &e->values; (l = *prev); prev = &l->next) 715 { 716 if (!id) 717 { 718 *prev = l->next; 719 l->next = NULL; 720 FcValueListDestroy (l); 721 if (!e->values) 722 FcPatternDel (p, object); 723 return FcTrue; 724 } 725 id--; 726 } 727 return FcFalse; 728} 729 730FcBool 731FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i) 732{ 733 FcValue v; 734 735 v.type = FcTypeInteger; 736 v.u.i = i; 737 return FcPatternObjectAdd (p, object, v, FcTrue); 738} 739 740FcBool 741FcPatternAddInteger (FcPattern *p, const char *object, int i) 742{ 743 return FcPatternObjectAddInteger (p, FcObjectFromName (object), i); 744} 745 746FcBool 747FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d) 748{ 749 FcValue v; 750 751 v.type = FcTypeDouble; 752 v.u.d = d; 753 return FcPatternObjectAdd (p, object, v, FcTrue); 754} 755 756 757FcBool 758FcPatternAddDouble (FcPattern *p, const char *object, double d) 759{ 760 return FcPatternObjectAddDouble (p, FcObjectFromName (object), d); 761} 762 763FcBool 764FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s) 765{ 766 FcValue v; 767 768 if (!s) 769 { 770 v.type = FcTypeVoid; 771 v.u.s = 0; 772 return FcPatternObjectAdd (p, object, v, FcTrue); 773 } 774 775 v.type = FcTypeString; 776 v.u.s = s; 777 return FcPatternObjectAdd (p, object, v, FcTrue); 778} 779 780FcBool 781FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s) 782{ 783 return FcPatternObjectAddString (p, FcObjectFromName (object), s); 784} 785 786FcBool 787FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s) 788{ 789 FcValue v; 790 791 v.type = FcTypeMatrix; 792 v.u.m = s; 793 return FcPatternAdd (p, object, v, FcTrue); 794} 795 796 797FcBool 798FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b) 799{ 800 FcValue v; 801 802 v.type = FcTypeBool; 803 v.u.b = b; 804 return FcPatternObjectAdd (p, object, v, FcTrue); 805} 806 807FcBool 808FcPatternAddBool (FcPattern *p, const char *object, FcBool b) 809{ 810 return FcPatternObjectAddBool (p, FcObjectFromName (object), b); 811} 812 813FcBool 814FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c) 815{ 816 FcValue v; 817 818 v.type = FcTypeCharSet; 819 v.u.c = (FcCharSet *)c; 820 return FcPatternAdd (p, object, v, FcTrue); 821} 822 823FcBool 824FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f) 825{ 826 FcValue v; 827 828 v.type = FcTypeFTFace; 829 v.u.f = (void *) f; 830 return FcPatternAdd (p, object, v, FcTrue); 831} 832 833FcBool 834FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls) 835{ 836 FcValue v; 837 838 v.type = FcTypeLangSet; 839 v.u.l = (FcLangSet *)ls; 840 return FcPatternAdd (p, object, v, FcTrue); 841} 842 843FcResult 844FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v) 845{ 846 FcPatternElt *e; 847 FcValueListPtr l; 848 849 if (!p) 850 return FcResultNoMatch; 851 e = FcPatternObjectFindElt (p, object); 852 if (!e) 853 return FcResultNoMatch; 854 for (l = FcPatternEltValues(e); l; l = FcValueListNext(l)) 855 { 856 if (!id) 857 { 858 *v = FcValueCanonicalize(&l->value); 859 return FcResultMatch; 860 } 861 id--; 862 } 863 return FcResultNoId; 864} 865 866FcResult 867FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v) 868{ 869 return FcPatternObjectGet (p, FcObjectFromName (object), id, v); 870} 871 872FcResult 873FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i) 874{ 875 FcValue v; 876 FcResult r; 877 878 r = FcPatternObjectGet (p, object, id, &v); 879 if (r != FcResultMatch) 880 return r; 881 switch ((int) v.type) { 882 case FcTypeDouble: 883 *i = (int) v.u.d; 884 break; 885 case FcTypeInteger: 886 *i = v.u.i; 887 break; 888 default: 889 return FcResultTypeMismatch; 890 } 891 return FcResultMatch; 892} 893 894FcResult 895FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i) 896{ 897 return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i); 898} 899 900 901FcResult 902FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d) 903{ 904 FcValue v; 905 FcResult r; 906 907 r = FcPatternObjectGet (p, object, id, &v); 908 if (r != FcResultMatch) 909 return r; 910 switch ((int) v.type) { 911 case FcTypeDouble: 912 *d = v.u.d; 913 break; 914 case FcTypeInteger: 915 *d = (double) v.u.i; 916 break; 917 default: 918 return FcResultTypeMismatch; 919 } 920 return FcResultMatch; 921} 922 923FcResult 924FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d) 925{ 926 return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d); 927} 928 929FcResult 930FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s) 931{ 932 FcValue v; 933 FcResult r; 934 935 r = FcPatternObjectGet (p, object, id, &v); 936 if (r != FcResultMatch) 937 return r; 938 if (v.type != FcTypeString) 939 return FcResultTypeMismatch; 940 941 *s = (FcChar8 *) v.u.s; 942 return FcResultMatch; 943} 944 945FcResult 946FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s) 947{ 948 return FcPatternObjectGetString (p, FcObjectFromName (object), id, s); 949} 950 951FcResult 952FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m) 953{ 954 FcValue v; 955 FcResult r; 956 957 r = FcPatternGet (p, object, id, &v); 958 if (r != FcResultMatch) 959 return r; 960 if (v.type != FcTypeMatrix) 961 return FcResultTypeMismatch; 962 *m = (FcMatrix *)v.u.m; 963 return FcResultMatch; 964} 965 966 967FcResult 968FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b) 969{ 970 FcValue v; 971 FcResult r; 972 973 r = FcPatternGet (p, object, id, &v); 974 if (r != FcResultMatch) 975 return r; 976 if (v.type != FcTypeBool) 977 return FcResultTypeMismatch; 978 *b = v.u.b; 979 return FcResultMatch; 980} 981 982FcResult 983FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c) 984{ 985 FcValue v; 986 FcResult r; 987 988 r = FcPatternGet (p, object, id, &v); 989 if (r != FcResultMatch) 990 return r; 991 if (v.type != FcTypeCharSet) 992 return FcResultTypeMismatch; 993 *c = (FcCharSet *)v.u.c; 994 return FcResultMatch; 995} 996 997FcResult 998FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f) 999{ 1000 FcValue v; 1001 FcResult r; 1002 1003 r = FcPatternGet (p, object, id, &v); 1004 if (r != FcResultMatch) 1005 return r; 1006 if (v.type != FcTypeFTFace) 1007 return FcResultTypeMismatch; 1008 *f = (FT_Face) v.u.f; 1009 return FcResultMatch; 1010} 1011 1012FcResult 1013FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls) 1014{ 1015 FcValue v; 1016 FcResult r; 1017 1018 r = FcPatternGet (p, object, id, &v); 1019 if (r != FcResultMatch) 1020 return r; 1021 if (v.type != FcTypeLangSet) 1022 return FcResultTypeMismatch; 1023 *ls = (FcLangSet *)v.u.l; 1024 return FcResultMatch; 1025} 1026 1027FcPattern * 1028FcPatternDuplicate (const FcPattern *orig) 1029{ 1030 FcPattern *new; 1031 FcPatternElt *e; 1032 int i; 1033 FcValueListPtr l; 1034 1035 new = FcPatternCreate (); 1036 if (!new) 1037 goto bail0; 1038 1039 e = FcPatternElts(orig); 1040 1041 for (i = 0; i < orig->num; i++) 1042 { 1043 for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l)) 1044 { 1045 if (!FcPatternObjectAddWithBinding (new, e[i].object, 1046 FcValueCanonicalize(&l->value), 1047 l->binding, 1048 FcTrue)) 1049 goto bail1; 1050 1051 } 1052 } 1053 1054 return new; 1055 1056bail1: 1057 FcPatternDestroy (new); 1058bail0: 1059 return 0; 1060} 1061 1062void 1063FcPatternReference (FcPattern *p) 1064{ 1065 if (!FcRefIsConst (&p->ref)) 1066 FcRefInc (&p->ref); 1067 else 1068 FcCacheObjectReference (p); 1069} 1070 1071FcPattern * 1072FcPatternVaBuild (FcPattern *p, va_list va) 1073{ 1074 FcPattern *ret; 1075 1076 FcPatternVapBuild (ret, p, va); 1077 return ret; 1078} 1079 1080FcPattern * 1081FcPatternBuild (FcPattern *p, ...) 1082{ 1083 va_list va; 1084 1085 va_start (va, p); 1086 FcPatternVapBuild (p, p, va); 1087 va_end (va); 1088 return p; 1089} 1090 1091/* 1092 * Add all of the elements in 's' to 'p' 1093 */ 1094FcBool 1095FcPatternAppend (FcPattern *p, FcPattern *s) 1096{ 1097 int i; 1098 FcPatternElt *e; 1099 FcValueListPtr v; 1100 1101 for (i = 0; i < s->num; i++) 1102 { 1103 e = FcPatternElts(s)+i; 1104 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v)) 1105 { 1106 if (!FcPatternObjectAddWithBinding (p, e->object, 1107 FcValueCanonicalize(&v->value), 1108 v->binding, FcTrue)) 1109 return FcFalse; 1110 } 1111 } 1112 return FcTrue; 1113} 1114 1115FcPattern * 1116FcPatternFilter (FcPattern *p, const FcObjectSet *os) 1117{ 1118 int i; 1119 FcPattern *ret; 1120 FcPatternElt *e; 1121 FcValueListPtr v; 1122 1123 if (!os) 1124 return FcPatternDuplicate (p); 1125 1126 ret = FcPatternCreate (); 1127 if (!ret) 1128 return NULL; 1129 1130 for (i = 0; i < os->nobject; i++) 1131 { 1132 FcObject object = FcObjectFromName (os->objects[i]); 1133 e = FcPatternObjectFindElt (p, object); 1134 if (e) 1135 { 1136 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v)) 1137 { 1138 if (!FcPatternObjectAddWithBinding (ret, e->object, 1139 FcValueCanonicalize(&v->value), 1140 v->binding, FcTrue)) 1141 goto bail0; 1142 } 1143 } 1144 } 1145 return ret; 1146 1147bail0: 1148 FcPatternDestroy (ret); 1149 return NULL; 1150} 1151 1152 1153FcBool 1154FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat) 1155{ 1156 int i; 1157 FcPatternElt *elts = FcPatternElts(pat); 1158 1159 if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern))) 1160 return FcFalse; 1161 if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt))) 1162 return FcFalse; 1163 for (i = 0; i < pat->num; i++) 1164 if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i))) 1165 return FcFalse; 1166 return FcTrue; 1167} 1168 1169FcPattern * 1170FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat) 1171{ 1172 FcPattern *pat_serialized; 1173 FcPatternElt *elts = FcPatternElts (pat); 1174 FcPatternElt *elts_serialized; 1175 FcValueList *values_serialized; 1176 int i; 1177 1178 pat_serialized = FcSerializePtr (serialize, pat); 1179 if (!pat_serialized) 1180 return NULL; 1181 *pat_serialized = *pat; 1182 pat_serialized->size = pat->num; 1183 FcRefSetConst (&pat_serialized->ref); 1184 1185 elts_serialized = FcSerializePtr (serialize, elts); 1186 if (!elts_serialized) 1187 return NULL; 1188 1189 pat_serialized->elts_offset = FcPtrToOffset (pat_serialized, 1190 elts_serialized); 1191 1192 for (i = 0; i < pat->num; i++) 1193 { 1194 values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i)); 1195 if (!values_serialized) 1196 return NULL; 1197 elts_serialized[i].object = elts[i].object; 1198 elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i], 1199 values_serialized, 1200 FcValueList); 1201 } 1202 if (FcDebug() & FC_DBG_CACHEV) { 1203 printf ("Raw pattern:\n"); 1204 FcPatternPrint (pat); 1205 printf ("Serialized pattern:\n"); 1206 FcPatternPrint (pat_serialized); 1207 printf ("\n"); 1208 } 1209 return pat_serialized; 1210} 1211 1212FcBool 1213FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl) 1214{ 1215 while (vl) 1216 { 1217 if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList))) 1218 return FcFalse; 1219 switch ((int) vl->value.type) { 1220 case FcTypeString: 1221 if (!FcStrSerializeAlloc (serialize, vl->value.u.s)) 1222 return FcFalse; 1223 break; 1224 case FcTypeCharSet: 1225 if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c)) 1226 return FcFalse; 1227 break; 1228 case FcTypeLangSet: 1229 if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l)) 1230 return FcFalse; 1231 break; 1232 default: 1233 break; 1234 } 1235 vl = vl->next; 1236 } 1237 return FcTrue; 1238} 1239 1240FcValueList * 1241FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl) 1242{ 1243 FcValueList *vl_serialized; 1244 FcChar8 *s_serialized; 1245 FcCharSet *c_serialized; 1246 FcLangSet *l_serialized; 1247 FcValueList *head_serialized = NULL; 1248 FcValueList *prev_serialized = NULL; 1249 1250 while (vl) 1251 { 1252 vl_serialized = FcSerializePtr (serialize, vl); 1253 if (!vl_serialized) 1254 return NULL; 1255 1256 if (prev_serialized) 1257 prev_serialized->next = FcPtrToEncodedOffset (prev_serialized, 1258 vl_serialized, 1259 FcValueList); 1260 else 1261 head_serialized = vl_serialized; 1262 1263 vl_serialized->next = NULL; 1264 vl_serialized->value.type = vl->value.type; 1265 switch ((int) vl->value.type) { 1266 case FcTypeInteger: 1267 vl_serialized->value.u.i = vl->value.u.i; 1268 break; 1269 case FcTypeDouble: 1270 vl_serialized->value.u.d = vl->value.u.d; 1271 break; 1272 case FcTypeString: 1273 s_serialized = FcStrSerialize (serialize, vl->value.u.s); 1274 if (!s_serialized) 1275 return NULL; 1276 vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value, 1277 s_serialized, 1278 FcChar8); 1279 break; 1280 case FcTypeBool: 1281 vl_serialized->value.u.b = vl->value.u.b; 1282 break; 1283 case FcTypeMatrix: 1284 /* can't happen */ 1285 break; 1286 case FcTypeCharSet: 1287 c_serialized = FcCharSetSerialize (serialize, vl->value.u.c); 1288 if (!c_serialized) 1289 return NULL; 1290 vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value, 1291 c_serialized, 1292 FcCharSet); 1293 break; 1294 case FcTypeFTFace: 1295 /* can't happen */ 1296 break; 1297 case FcTypeLangSet: 1298 l_serialized = FcLangSetSerialize (serialize, vl->value.u.l); 1299 if (!l_serialized) 1300 return NULL; 1301 vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value, 1302 l_serialized, 1303 FcLangSet); 1304 break; 1305 default: 1306 break; 1307 } 1308 prev_serialized = vl_serialized; 1309 vl = vl->next; 1310 } 1311 return head_serialized; 1312} 1313#define __fcpat__ 1314#include "fcaliastail.h" 1315#include "fcftaliastail.h" 1316#undef __fcpat__ 1317