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