[918] | 1 | /*
|
---|
[1170] | 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 | * Contributors:
|
---|
[918] | 23 | * Doodle <doodle@netlabs.org>
|
---|
| 24 | * Peter Weilbacher <mozilla@weilbacher.org>
|
---|
| 25 | * KO Myung-Hun <komh78@gmail.com>
|
---|
| 26 | * Alex Taylor <alex@altsan.org>
|
---|
| 27 | * Rich Walsh <rich@e-vertise.com>
|
---|
| 28 | * Silvan Scherrer <silvan.scherrer@aroa.ch>
|
---|
| 29 | *
|
---|
| 30 | */
|
---|
| 31 |
|
---|
| 32 | #include "fcint.h"
|
---|
| 33 |
|
---|
[1170] | 34 | FcPattern *
|
---|
| 35 | FcPatternCreate (void)
|
---|
[918] | 36 | {
|
---|
[1170] | 37 | FcPattern *p;
|
---|
| 38 |
|
---|
| 39 | p = (FcPattern *) malloc (sizeof (FcPattern));
|
---|
| 40 | if (!p)
|
---|
| 41 | return 0;
|
---|
| 42 | memset (p, 0, sizeof (FcPattern));
|
---|
| 43 | p->num = 0;
|
---|
| 44 | p->size = 0;
|
---|
| 45 | p->elts_offset = FcPtrToOffset (p, NULL);
|
---|
| 46 | FcRefInit (&p->ref, 1);
|
---|
| 47 | return p;
|
---|
[918] | 48 | }
|
---|
| 49 |
|
---|
[1170] | 50 | void
|
---|
| 51 | FcValueDestroy (FcValue v)
|
---|
[918] | 52 | {
|
---|
[1170] | 53 | switch ((int) v.type) {
|
---|
| 54 | case FcTypeString:
|
---|
| 55 | FcFree (v.u.s);
|
---|
| 56 | break;
|
---|
| 57 | case FcTypeMatrix:
|
---|
| 58 | FcMatrixFree ((FcMatrix *) v.u.m);
|
---|
| 59 | break;
|
---|
| 60 | case FcTypeCharSet:
|
---|
| 61 | FcCharSetDestroy ((FcCharSet *) v.u.c);
|
---|
| 62 | break;
|
---|
| 63 | case FcTypeLangSet:
|
---|
| 64 | FcLangSetDestroy ((FcLangSet *) v.u.l);
|
---|
| 65 | break;
|
---|
| 66 | case FcTypeRange:
|
---|
| 67 | FcRangeDestroy ((FcRange *) v.u.r);
|
---|
| 68 | break;
|
---|
| 69 | default:
|
---|
| 70 | break;
|
---|
| 71 | }
|
---|
| 72 | }
|
---|
[918] | 73 |
|
---|
[1170] | 74 | FcValue
|
---|
| 75 | FcValueCanonicalize (const FcValue *v)
|
---|
| 76 | {
|
---|
| 77 | FcValue new;
|
---|
| 78 |
|
---|
| 79 | switch ((int) v->type)
|
---|
| 80 | {
|
---|
| 81 | case FcTypeString:
|
---|
| 82 | new.u.s = FcValueString(v);
|
---|
| 83 | new.type = FcTypeString;
|
---|
| 84 | break;
|
---|
| 85 | case FcTypeCharSet:
|
---|
| 86 | new.u.c = FcValueCharSet(v);
|
---|
| 87 | new.type = FcTypeCharSet;
|
---|
| 88 | break;
|
---|
| 89 | case FcTypeLangSet:
|
---|
| 90 | new.u.l = FcValueLangSet(v);
|
---|
| 91 | new.type = FcTypeLangSet;
|
---|
| 92 | break;
|
---|
| 93 | case FcTypeRange:
|
---|
| 94 | new.u.r = FcValueRange(v);
|
---|
| 95 | new.type = FcTypeRange;
|
---|
| 96 | break;
|
---|
| 97 | default:
|
---|
| 98 | new = *v;
|
---|
| 99 | break;
|
---|
| 100 | }
|
---|
| 101 | return new;
|
---|
[918] | 102 | }
|
---|
| 103 |
|
---|
[1170] | 104 | FcValue
|
---|
| 105 | FcValueSave (FcValue v)
|
---|
[918] | 106 | {
|
---|
[1170] | 107 | switch ((int) v.type) {
|
---|
| 108 | case FcTypeString:
|
---|
| 109 | v.u.s = FcStrdup (v.u.s);
|
---|
| 110 | if (!v.u.s)
|
---|
| 111 | v.type = FcTypeVoid;
|
---|
| 112 | break;
|
---|
| 113 | case FcTypeMatrix:
|
---|
| 114 | v.u.m = FcMatrixCopy (v.u.m);
|
---|
| 115 | if (!v.u.m)
|
---|
| 116 | v.type = FcTypeVoid;
|
---|
| 117 | break;
|
---|
| 118 | case FcTypeCharSet:
|
---|
| 119 | v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
|
---|
| 120 | if (!v.u.c)
|
---|
| 121 | v.type = FcTypeVoid;
|
---|
| 122 | break;
|
---|
| 123 | case FcTypeLangSet:
|
---|
| 124 | v.u.l = FcLangSetCopy (v.u.l);
|
---|
| 125 | if (!v.u.l)
|
---|
| 126 | v.type = FcTypeVoid;
|
---|
| 127 | break;
|
---|
| 128 | case FcTypeRange:
|
---|
| 129 | v.u.r = FcRangeCopy (v.u.r);
|
---|
| 130 | if (!v.u.r)
|
---|
| 131 | v.type = FcTypeVoid;
|
---|
| 132 | break;
|
---|
| 133 | default:
|
---|
| 134 | break;
|
---|
| 135 | }
|
---|
| 136 | return v;
|
---|
| 137 | }
|
---|
[918] | 138 |
|
---|
[1170] | 139 | FcValueListPtr
|
---|
| 140 | FcValueListCreate (void)
|
---|
| 141 | {
|
---|
| 142 | return calloc (1, sizeof (FcValueList));
|
---|
| 143 | }
|
---|
[918] | 144 |
|
---|
[1170] | 145 | void
|
---|
| 146 | FcValueListDestroy (FcValueListPtr l)
|
---|
| 147 | {
|
---|
| 148 | FcValueListPtr next;
|
---|
| 149 | for (; l; l = next)
|
---|
| 150 | {
|
---|
| 151 | switch ((int) l->value.type) {
|
---|
| 152 | case FcTypeString:
|
---|
| 153 | FcFree (l->value.u.s);
|
---|
| 154 | break;
|
---|
| 155 | case FcTypeMatrix:
|
---|
| 156 | FcMatrixFree ((FcMatrix *)l->value.u.m);
|
---|
| 157 | break;
|
---|
| 158 | case FcTypeCharSet:
|
---|
| 159 | FcCharSetDestroy
|
---|
| 160 | ((FcCharSet *) (l->value.u.c));
|
---|
| 161 | break;
|
---|
| 162 | case FcTypeLangSet:
|
---|
| 163 | FcLangSetDestroy
|
---|
| 164 | ((FcLangSet *) (l->value.u.l));
|
---|
| 165 | break;
|
---|
| 166 | case FcTypeRange:
|
---|
| 167 | FcRangeDestroy ((FcRange *) (l->value.u.r));
|
---|
| 168 | break;
|
---|
| 169 | default:
|
---|
| 170 | break;
|
---|
| 171 | }
|
---|
| 172 | next = FcValueListNext(l);
|
---|
| 173 | free(l);
|
---|
| 174 | }
|
---|
[918] | 175 | }
|
---|
| 176 |
|
---|
[1170] | 177 | FcValueListPtr
|
---|
| 178 | FcValueListPrepend (FcValueListPtr vallist,
|
---|
| 179 | FcValue value,
|
---|
| 180 | FcValueBinding binding)
|
---|
[918] | 181 | {
|
---|
[1170] | 182 | FcValueListPtr new;
|
---|
[918] | 183 |
|
---|
[1170] | 184 | if (value.type == FcTypeVoid)
|
---|
| 185 | return vallist;
|
---|
| 186 | new = FcValueListCreate ();
|
---|
| 187 | if (!new)
|
---|
| 188 | return vallist;
|
---|
[918] | 189 |
|
---|
[1170] | 190 | new->value = FcValueSave (value);
|
---|
| 191 | new->binding = binding;
|
---|
| 192 | new->next = vallist;
|
---|
[918] | 193 |
|
---|
[1170] | 194 | return new;
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | FcValueListPtr
|
---|
| 198 | FcValueListAppend (FcValueListPtr vallist,
|
---|
| 199 | FcValue value,
|
---|
| 200 | FcValueBinding binding)
|
---|
| 201 | {
|
---|
| 202 | FcValueListPtr new, last;
|
---|
| 203 |
|
---|
| 204 | if (value.type == FcTypeVoid)
|
---|
| 205 | return vallist;
|
---|
| 206 | new = FcValueListCreate ();
|
---|
| 207 | if (!new)
|
---|
| 208 | return vallist;
|
---|
| 209 |
|
---|
| 210 | new->value = FcValueSave (value);
|
---|
| 211 | new->binding = binding;
|
---|
| 212 | new->next = NULL;
|
---|
| 213 |
|
---|
| 214 | if (vallist)
|
---|
[918] | 215 | {
|
---|
[1170] | 216 | for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
|
---|
| 217 |
|
---|
| 218 | last->next = new;
|
---|
| 219 | }
|
---|
| 220 | else
|
---|
| 221 | vallist = new;
|
---|
| 222 |
|
---|
| 223 | return vallist;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | FcValueListPtr
|
---|
| 227 | FcValueListDuplicate(FcValueListPtr orig)
|
---|
| 228 | {
|
---|
| 229 | FcValueListPtr new = NULL, l, t = NULL;
|
---|
| 230 | FcValue v;
|
---|
| 231 |
|
---|
| 232 | for (l = orig; l != NULL; l = FcValueListNext (l))
|
---|
[918] | 233 | {
|
---|
[1170] | 234 | if (!new)
|
---|
| 235 | {
|
---|
| 236 | t = new = FcValueListCreate();
|
---|
| 237 | }
|
---|
| 238 | else
|
---|
| 239 | {
|
---|
| 240 | t->next = FcValueListCreate();
|
---|
| 241 | t = FcValueListNext (t);
|
---|
| 242 | }
|
---|
| 243 | v = FcValueCanonicalize (&l->value);
|
---|
| 244 | t->value = FcValueSave (v);
|
---|
| 245 | t->binding = l->binding;
|
---|
| 246 | t->next = NULL;
|
---|
[918] | 247 | }
|
---|
| 248 |
|
---|
[1170] | 249 | return new;
|
---|
| 250 | }
|
---|
| 251 |
|
---|
| 252 | FcBool
|
---|
| 253 | FcValueEqual (FcValue va, FcValue vb)
|
---|
| 254 | {
|
---|
| 255 | if (va.type != vb.type)
|
---|
[918] | 256 | {
|
---|
[1170] | 257 | if (va.type == FcTypeInteger)
|
---|
| 258 | {
|
---|
| 259 | va.type = FcTypeDouble;
|
---|
| 260 | va.u.d = va.u.i;
|
---|
| 261 | }
|
---|
| 262 | if (vb.type == FcTypeInteger)
|
---|
| 263 | {
|
---|
| 264 | vb.type = FcTypeDouble;
|
---|
| 265 | vb.u.d = vb.u.i;
|
---|
| 266 | }
|
---|
| 267 | if (va.type != vb.type)
|
---|
| 268 | return FcFalse;
|
---|
[918] | 269 | }
|
---|
[1170] | 270 | switch (va.type) {
|
---|
| 271 | case FcTypeUnknown:
|
---|
| 272 | return FcFalse; /* don't know how to compare this object */
|
---|
| 273 | case FcTypeVoid:
|
---|
| 274 | return FcTrue;
|
---|
| 275 | case FcTypeInteger:
|
---|
| 276 | return va.u.i == vb.u.i;
|
---|
| 277 | case FcTypeDouble:
|
---|
| 278 | return va.u.d == vb.u.d;
|
---|
| 279 | case FcTypeString:
|
---|
| 280 | return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
|
---|
| 281 | case FcTypeBool:
|
---|
| 282 | return va.u.b == vb.u.b;
|
---|
| 283 | case FcTypeMatrix:
|
---|
| 284 | return FcMatrixEqual (va.u.m, vb.u.m);
|
---|
| 285 | case FcTypeCharSet:
|
---|
| 286 | return FcCharSetEqual (va.u.c, vb.u.c);
|
---|
| 287 | case FcTypeFTFace:
|
---|
| 288 | return va.u.f == vb.u.f;
|
---|
| 289 | case FcTypeLangSet:
|
---|
| 290 | return FcLangSetEqual (va.u.l, vb.u.l);
|
---|
| 291 | case FcTypeRange:
|
---|
| 292 | return FcRangeIsInRange (va.u.r, vb.u.r);
|
---|
| 293 | }
|
---|
| 294 | return FcFalse;
|
---|
| 295 | }
|
---|
[918] | 296 |
|
---|
[1170] | 297 | static FcChar32
|
---|
| 298 | FcDoubleHash (double d)
|
---|
| 299 | {
|
---|
| 300 | if (d < 0)
|
---|
| 301 | d = -d;
|
---|
| 302 | if (d > 0xffffffff)
|
---|
| 303 | d = 0xffffffff;
|
---|
| 304 | return (FcChar32) d;
|
---|
[918] | 305 | }
|
---|
| 306 |
|
---|
[1170] | 307 | FcChar32
|
---|
| 308 | FcStringHash (const FcChar8 *s)
|
---|
[918] | 309 | {
|
---|
[1170] | 310 | FcChar8 c;
|
---|
| 311 | FcChar32 h = 0;
|
---|
[918] | 312 |
|
---|
[1170] | 313 | if (s)
|
---|
| 314 | while ((c = *s++))
|
---|
| 315 | h = ((h << 1) | (h >> 31)) ^ c;
|
---|
| 316 | return h;
|
---|
| 317 | }
|
---|
[918] | 318 |
|
---|
[1170] | 319 | static FcChar32
|
---|
| 320 | FcValueHash (const FcValue *v)
|
---|
| 321 | {
|
---|
| 322 | switch (v->type) {
|
---|
| 323 | case FcTypeUnknown:
|
---|
| 324 | case FcTypeVoid:
|
---|
| 325 | return 0;
|
---|
| 326 | case FcTypeInteger:
|
---|
| 327 | return (FcChar32) v->u.i;
|
---|
| 328 | case FcTypeDouble:
|
---|
| 329 | return FcDoubleHash (v->u.d);
|
---|
| 330 | case FcTypeString:
|
---|
| 331 | return FcStringHash (FcValueString(v));
|
---|
| 332 | case FcTypeBool:
|
---|
| 333 | return (FcChar32) v->u.b;
|
---|
| 334 | case FcTypeMatrix:
|
---|
| 335 | return (FcDoubleHash (v->u.m->xx) ^
|
---|
| 336 | FcDoubleHash (v->u.m->xy) ^
|
---|
| 337 | FcDoubleHash (v->u.m->yx) ^
|
---|
| 338 | FcDoubleHash (v->u.m->yy));
|
---|
| 339 | case FcTypeCharSet:
|
---|
| 340 | return (FcChar32) FcValueCharSet(v)->num;
|
---|
| 341 | case FcTypeFTFace:
|
---|
| 342 | return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
|
---|
| 343 | FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
|
---|
| 344 | case FcTypeLangSet:
|
---|
| 345 | return FcLangSetHash (FcValueLangSet(v));
|
---|
| 346 | case FcTypeRange:
|
---|
| 347 | return FcRangeHash (v->u.r);
|
---|
| 348 | }
|
---|
| 349 | return 0;
|
---|
[918] | 350 | }
|
---|
| 351 |
|
---|
[1170] | 352 | static FcBool
|
---|
| 353 | FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
|
---|
[918] | 354 | {
|
---|
[1170] | 355 | if (la == lb)
|
---|
| 356 | return FcTrue;
|
---|
[918] | 357 |
|
---|
[1170] | 358 | while (la && lb)
|
---|
| 359 | {
|
---|
| 360 | if (!FcValueEqual (la->value, lb->value))
|
---|
| 361 | return FcFalse;
|
---|
| 362 | la = FcValueListNext(la);
|
---|
| 363 | lb = FcValueListNext(lb);
|
---|
| 364 | }
|
---|
| 365 | if (la || lb)
|
---|
| 366 | return FcFalse;
|
---|
| 367 | return FcTrue;
|
---|
| 368 | }
|
---|
[918] | 369 |
|
---|
[1170] | 370 | static FcChar32
|
---|
| 371 | FcValueListHash (FcValueListPtr l)
|
---|
| 372 | {
|
---|
| 373 | FcChar32 hash = 0;
|
---|
| 374 |
|
---|
| 375 | for (; l; l = FcValueListNext(l))
|
---|
| 376 | {
|
---|
| 377 | hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
|
---|
| 378 | }
|
---|
| 379 | return hash;
|
---|
[918] | 380 | }
|
---|
| 381 |
|
---|
[1170] | 382 | void
|
---|
| 383 | FcPatternDestroy (FcPattern *p)
|
---|
[918] | 384 | {
|
---|
[1170] | 385 | int i;
|
---|
| 386 | FcPatternElt *elts;
|
---|
[918] | 387 |
|
---|
[1170] | 388 | if (!p)
|
---|
| 389 | return;
|
---|
[918] | 390 |
|
---|
[1170] | 391 | if (FcRefIsConst (&p->ref))
|
---|
| 392 | {
|
---|
[1172] | 393 | // FcCacheObjectDereference (p);
|
---|
| 394 | FcRefDec (&p->ref);
|
---|
[1170] | 395 | return;
|
---|
| 396 | }
|
---|
| 397 |
|
---|
| 398 | if (FcRefDec (&p->ref) != 1)
|
---|
| 399 | return;
|
---|
| 400 |
|
---|
| 401 | elts = FcPatternElts (p);
|
---|
| 402 | for (i = 0; i < p->num; i++)
|
---|
| 403 | FcValueListDestroy (FcPatternEltValues(&elts[i]));
|
---|
| 404 |
|
---|
| 405 | free (elts);
|
---|
| 406 | free (p);
|
---|
[918] | 407 | }
|
---|
| 408 |
|
---|
[1170] | 409 | static int
|
---|
| 410 | FcPatternObjectPosition (const FcPattern *p, FcObject object)
|
---|
[918] | 411 | {
|
---|
[1170] | 412 | int low, high, mid, c;
|
---|
| 413 | FcPatternElt *elts = FcPatternElts(p);
|
---|
[918] | 414 |
|
---|
[1170] | 415 | low = 0;
|
---|
| 416 | high = p->num - 1;
|
---|
| 417 | c = 1;
|
---|
| 418 | mid = 0;
|
---|
| 419 | while (low <= high)
|
---|
| 420 | {
|
---|
| 421 | mid = (low + high) >> 1;
|
---|
| 422 | c = elts[mid].object - object;
|
---|
| 423 | if (c == 0)
|
---|
| 424 | return mid;
|
---|
| 425 | if (c < 0)
|
---|
| 426 | low = mid + 1;
|
---|
| 427 | else
|
---|
| 428 | high = mid - 1;
|
---|
| 429 | }
|
---|
| 430 | if (c < 0)
|
---|
| 431 | mid++;
|
---|
| 432 | return -(mid + 1);
|
---|
| 433 | }
|
---|
[918] | 434 |
|
---|
[1170] | 435 | FcPatternElt *
|
---|
| 436 | FcPatternObjectFindElt (const FcPattern *p, FcObject object)
|
---|
| 437 | {
|
---|
| 438 | int i = FcPatternObjectPosition (p, object);
|
---|
| 439 | if (i < 0)
|
---|
| 440 | return 0;
|
---|
| 441 | return &FcPatternElts(p)[i];
|
---|
[918] | 442 | }
|
---|
| 443 |
|
---|
[1170] | 444 | FcPatternElt *
|
---|
| 445 | FcPatternObjectInsertElt (FcPattern *p, FcObject object)
|
---|
[918] | 446 | {
|
---|
[1170] | 447 | int i;
|
---|
| 448 | FcPatternElt *e;
|
---|
[918] | 449 |
|
---|
[1170] | 450 | i = FcPatternObjectPosition (p, object);
|
---|
| 451 | if (i < 0)
|
---|
| 452 | {
|
---|
| 453 | i = -i - 1;
|
---|
[918] | 454 |
|
---|
[1170] | 455 | /* reallocate array */
|
---|
| 456 | if (p->num + 1 >= p->size)
|
---|
| 457 | {
|
---|
| 458 | int s = p->size + 16;
|
---|
| 459 | if (p->size)
|
---|
| 460 | {
|
---|
| 461 | FcPatternElt *e0 = FcPatternElts(p);
|
---|
| 462 | e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
|
---|
| 463 | if (!e) /* maybe it was mmapped */
|
---|
| 464 | {
|
---|
| 465 | e = malloc(s * sizeof (FcPatternElt));
|
---|
| 466 | if (e)
|
---|
| 467 | memcpy(e, e0, p->num * sizeof (FcPatternElt));
|
---|
| 468 | }
|
---|
| 469 | }
|
---|
| 470 | else
|
---|
| 471 | e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
|
---|
| 472 | if (!e)
|
---|
| 473 | return FcFalse;
|
---|
| 474 | p->elts_offset = FcPtrToOffset (p, e);
|
---|
| 475 | while (p->size < s)
|
---|
| 476 | {
|
---|
| 477 | e[p->size].object = 0;
|
---|
| 478 | e[p->size].values = NULL;
|
---|
| 479 | p->size++;
|
---|
| 480 | }
|
---|
| 481 | }
|
---|
| 482 |
|
---|
| 483 | e = FcPatternElts(p);
|
---|
| 484 | /* move elts up */
|
---|
| 485 | memmove (e + i + 1,
|
---|
| 486 | e + i,
|
---|
| 487 | sizeof (FcPatternElt) *
|
---|
| 488 | (p->num - i));
|
---|
| 489 |
|
---|
| 490 | /* bump count */
|
---|
| 491 | p->num++;
|
---|
| 492 |
|
---|
| 493 | e[i].object = object;
|
---|
| 494 | e[i].values = NULL;
|
---|
| 495 | }
|
---|
| 496 |
|
---|
| 497 | return FcPatternElts(p) + i;
|
---|
[918] | 498 | }
|
---|
| 499 |
|
---|
[1170] | 500 | FcBool
|
---|
| 501 | FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
|
---|
[918] | 502 | {
|
---|
[1170] | 503 | int i;
|
---|
| 504 | FcPatternElt *pae, *pbe;
|
---|
[918] | 505 |
|
---|
[1170] | 506 | if (pa == pb)
|
---|
| 507 | return FcTrue;
|
---|
[918] | 508 |
|
---|
[1170] | 509 | if (pa->num != pb->num)
|
---|
| 510 | return FcFalse;
|
---|
| 511 | pae = FcPatternElts(pa);
|
---|
| 512 | pbe = FcPatternElts(pb);
|
---|
| 513 | for (i = 0; i < pa->num; i++)
|
---|
| 514 | {
|
---|
| 515 | if (pae[i].object != pbe[i].object)
|
---|
| 516 | return FcFalse;
|
---|
| 517 | if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
|
---|
| 518 | FcPatternEltValues(&pbe[i])))
|
---|
| 519 | return FcFalse;
|
---|
| 520 | }
|
---|
| 521 | return FcTrue;
|
---|
| 522 | }
|
---|
[918] | 523 |
|
---|
[1170] | 524 | FcChar32
|
---|
| 525 | FcPatternHash (const FcPattern *p)
|
---|
| 526 | {
|
---|
| 527 | int i;
|
---|
| 528 | FcChar32 h = 0;
|
---|
| 529 | FcPatternElt *pe = FcPatternElts(p);
|
---|
| 530 |
|
---|
| 531 | for (i = 0; i < p->num; i++)
|
---|
| 532 | {
|
---|
| 533 | h = (((h << 1) | (h >> 31)) ^
|
---|
| 534 | pe[i].object ^
|
---|
| 535 | FcValueListHash (FcPatternEltValues(&pe[i])));
|
---|
| 536 | }
|
---|
| 537 | return h;
|
---|
[918] | 538 | }
|
---|
| 539 |
|
---|
[1170] | 540 | FcBool
|
---|
| 541 | FcPatternObjectListAdd (FcPattern *p,
|
---|
| 542 | FcObject object,
|
---|
| 543 | FcValueListPtr list,
|
---|
| 544 | FcBool append)
|
---|
[918] | 545 | {
|
---|
[1170] | 546 | FcPatternElt *e;
|
---|
| 547 | FcValueListPtr l, *prev;
|
---|
[918] | 548 |
|
---|
[1170] | 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))
|
---|
[918] | 556 | {
|
---|
[1170] | 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 | }
|
---|
[918] | 565 | }
|
---|
| 566 |
|
---|
[1170] | 567 | e = FcPatternObjectInsertElt (p, object);
|
---|
| 568 | if (!e)
|
---|
| 569 | goto bail0;
|
---|
| 570 |
|
---|
| 571 | if (append)
|
---|
[918] | 572 | {
|
---|
[1170] | 573 | for (prev = &e->values; *prev; prev = &(*prev)->next)
|
---|
| 574 | ;
|
---|
| 575 | *prev = list;
|
---|
[918] | 576 | }
|
---|
[1170] | 577 | else
|
---|
| 578 | {
|
---|
| 579 | for (prev = &list; *prev; prev = &(*prev)->next)
|
---|
| 580 | ;
|
---|
| 581 | *prev = e->values;
|
---|
| 582 | e->values = list;
|
---|
| 583 | }
|
---|
| 584 |
|
---|
[918] | 585 | return FcTrue;
|
---|
| 586 |
|
---|
[1170] | 587 | bail0:
|
---|
| 588 | return FcFalse;
|
---|
| 589 | }
|
---|
| 590 |
|
---|
| 591 | FcBool
|
---|
| 592 | FcPatternObjectAddWithBinding (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))
|
---|
[918] | 616 | {
|
---|
[1170] | 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;
|
---|
[918] | 623 | }
|
---|
| 624 |
|
---|
[1170] | 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)
|
---|
[918] | 634 | {
|
---|
[1170] | 635 | for (prev = &e->values; *prev; prev = &(*prev)->next)
|
---|
| 636 | ;
|
---|
| 637 | *prev = new;
|
---|
[918] | 638 | }
|
---|
[1170] | 639 | else
|
---|
[918] | 640 | {
|
---|
[1170] | 641 | new->next = e->values;
|
---|
| 642 | e->values = new;
|
---|
| 643 | }
|
---|
[918] | 644 |
|
---|
| 645 | return FcTrue;
|
---|
| 646 |
|
---|
[1170] | 647 | bail2:
|
---|
| 648 | FcValueDestroy (value);
|
---|
| 649 | bail1:
|
---|
| 650 | free (new);
|
---|
| 651 | bail0:
|
---|
| 652 | return FcFalse;
|
---|
[918] | 653 | }
|
---|
| 654 |
|
---|
[1170] | 655 | FcBool
|
---|
| 656 | FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
|
---|
[918] | 657 | {
|
---|
[1170] | 658 | return FcPatternObjectAddWithBinding (p, object,
|
---|
| 659 | value, FcValueBindingStrong, append);
|
---|
| 660 | }
|
---|
[918] | 661 |
|
---|
[1170] | 662 | FcBool
|
---|
| 663 | FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
|
---|
| 664 | {
|
---|
| 665 | return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
|
---|
| 666 | value, FcValueBindingStrong, append);
|
---|
| 667 | }
|
---|
[918] | 668 |
|
---|
[1170] | 669 | FcBool
|
---|
| 670 | FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
|
---|
| 671 | {
|
---|
| 672 | return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
|
---|
| 673 | value, FcValueBindingWeak, append);
|
---|
[918] | 674 | }
|
---|
| 675 |
|
---|
[1170] | 676 | FcBool
|
---|
| 677 | FcPatternObjectDel (FcPattern *p, FcObject object)
|
---|
[918] | 678 | {
|
---|
[1170] | 679 | FcPatternElt *e;
|
---|
[918] | 680 |
|
---|
[1170] | 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;
|
---|
[918] | 696 | return FcTrue;
|
---|
[1170] | 697 | }
|
---|
[918] | 698 |
|
---|
[1170] | 699 | FcBool
|
---|
| 700 | FcPatternDel (FcPattern *p, const char *object)
|
---|
| 701 | {
|
---|
| 702 | return FcPatternObjectDel (p, FcObjectFromName (object));
|
---|
[918] | 703 | }
|
---|
| 704 |
|
---|
[1170] | 705 | FcBool
|
---|
| 706 | FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
|
---|
[918] | 707 | {
|
---|
[1170] | 708 | FcValue v;
|
---|
[918] | 709 |
|
---|
[1170] | 710 | v.type = FcTypeInteger;
|
---|
| 711 | v.u.i = i;
|
---|
| 712 | return FcPatternObjectAdd (p, object, v, FcTrue);
|
---|
| 713 | }
|
---|
[918] | 714 |
|
---|
[1170] | 715 | FcBool
|
---|
| 716 | FcPatternAddInteger (FcPattern *p, const char *object, int i)
|
---|
| 717 | {
|
---|
| 718 | return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
|
---|
| 719 | }
|
---|
[918] | 720 |
|
---|
[1170] | 721 | FcBool
|
---|
| 722 | FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
|
---|
| 723 | {
|
---|
| 724 | FcValue v;
|
---|
| 725 |
|
---|
| 726 | v.type = FcTypeDouble;
|
---|
| 727 | v.u.d = d;
|
---|
| 728 | return FcPatternObjectAdd (p, object, v, FcTrue);
|
---|
[918] | 729 | }
|
---|
| 730 |
|
---|
[1170] | 731 |
|
---|
| 732 | FcBool
|
---|
| 733 | FcPatternAddDouble (FcPattern *p, const char *object, double d)
|
---|
[918] | 734 | {
|
---|
[1170] | 735 | return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
|
---|
[918] | 736 | }
|
---|
| 737 |
|
---|
[1170] | 738 | FcBool
|
---|
| 739 | FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
|
---|
[918] | 740 | {
|
---|
[1170] | 741 | FcValue v;
|
---|
[918] | 742 |
|
---|
[1170] | 743 | if (!s)
|
---|
| 744 | {
|
---|
| 745 | v.type = FcTypeVoid;
|
---|
| 746 | v.u.s = 0;
|
---|
| 747 | return FcPatternObjectAdd (p, object, v, FcTrue);
|
---|
| 748 | }
|
---|
[918] | 749 |
|
---|
[1170] | 750 | v.type = FcTypeString;
|
---|
| 751 | v.u.s = s;
|
---|
| 752 | return FcPatternObjectAdd (p, object, v, FcTrue);
|
---|
| 753 | }
|
---|
[918] | 754 |
|
---|
[1170] | 755 | FcBool
|
---|
| 756 | FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
|
---|
| 757 | {
|
---|
| 758 | return FcPatternObjectAddString (p, FcObjectFromName (object), s);
|
---|
| 759 | }
|
---|
[918] | 760 |
|
---|
[1170] | 761 | FcBool
|
---|
| 762 | FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
|
---|
| 763 | {
|
---|
| 764 | FcValue v;
|
---|
[918] | 765 |
|
---|
[1170] | 766 | v.type = FcTypeMatrix;
|
---|
| 767 | v.u.m = s;
|
---|
| 768 | return FcPatternAdd (p, object, v, FcTrue);
|
---|
| 769 | }
|
---|
[918] | 770 |
|
---|
| 771 |
|
---|
[1170] | 772 | FcBool
|
---|
| 773 | FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
|
---|
| 774 | {
|
---|
| 775 | FcValue v;
|
---|
| 776 |
|
---|
| 777 | v.type = FcTypeBool;
|
---|
| 778 | v.u.b = b;
|
---|
| 779 | return FcPatternObjectAdd (p, object, v, FcTrue);
|
---|
[918] | 780 | }
|
---|
| 781 |
|
---|
[1170] | 782 | FcBool
|
---|
| 783 | FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
|
---|
[918] | 784 | {
|
---|
[1170] | 785 | return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
|
---|
| 786 | }
|
---|
[918] | 787 |
|
---|
[1170] | 788 | FcBool
|
---|
| 789 | FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
|
---|
| 790 | {
|
---|
| 791 | FcValue v;
|
---|
| 792 |
|
---|
| 793 | v.type = FcTypeCharSet;
|
---|
| 794 | v.u.c = (FcCharSet *)c;
|
---|
| 795 | return FcPatternAdd (p, object, v, FcTrue);
|
---|
[918] | 796 | }
|
---|
| 797 |
|
---|
[1170] | 798 | FcBool
|
---|
| 799 | FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
|
---|
[918] | 800 | {
|
---|
[1170] | 801 | FcValue v;
|
---|
[918] | 802 |
|
---|
[1170] | 803 | v.type = FcTypeFTFace;
|
---|
| 804 | v.u.f = (void *) f;
|
---|
| 805 | return FcPatternAdd (p, object, v, FcTrue);
|
---|
| 806 | }
|
---|
[918] | 807 |
|
---|
[1170] | 808 | FcBool
|
---|
| 809 | FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
|
---|
| 810 | {
|
---|
| 811 | FcValue v;
|
---|
| 812 |
|
---|
| 813 | v.type = FcTypeLangSet;
|
---|
| 814 | v.u.l = (FcLangSet *)ls;
|
---|
| 815 | return FcPatternAdd (p, object, v, FcTrue);
|
---|
[918] | 816 | }
|
---|
| 817 |
|
---|
[1170] | 818 | FcResult
|
---|
| 819 | FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
|
---|
[918] | 820 | {
|
---|
[1170] | 821 | FcPatternElt *e;
|
---|
| 822 | FcValueListPtr l;
|
---|
[918] | 823 |
|
---|
[1170] | 824 | if (!p)
|
---|
| 825 | return FcResultNoMatch;
|
---|
| 826 | e = FcPatternObjectFindElt (p, object);
|
---|
| 827 | if (!e)
|
---|
| 828 | return FcResultNoMatch;
|
---|
| 829 | for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
|
---|
| 830 | {
|
---|
| 831 | if (!id)
|
---|
| 832 | {
|
---|
| 833 | *v = FcValueCanonicalize(&l->value);
|
---|
| 834 | return FcResultMatch;
|
---|
| 835 | }
|
---|
| 836 | id--;
|
---|
| 837 | }
|
---|
| 838 | return FcResultNoId;
|
---|
| 839 | }
|
---|
[918] | 840 |
|
---|
[1170] | 841 | FcResult
|
---|
| 842 | FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
|
---|
| 843 | {
|
---|
| 844 | return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
|
---|
[918] | 845 | }
|
---|
| 846 |
|
---|
[1170] | 847 | FcResult
|
---|
| 848 | FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
|
---|
[918] | 849 | {
|
---|
[1170] | 850 | FcValue v;
|
---|
| 851 | FcResult r;
|
---|
[918] | 852 |
|
---|
[1170] | 853 | r = FcPatternObjectGet (p, object, id, &v);
|
---|
| 854 | if (r != FcResultMatch)
|
---|
| 855 | return r;
|
---|
| 856 | switch ((int) v.type) {
|
---|
| 857 | case FcTypeDouble:
|
---|
| 858 | *i = (int) v.u.d;
|
---|
| 859 | break;
|
---|
[918] | 860 | case FcTypeInteger:
|
---|
[1170] | 861 | *i = v.u.i;
|
---|
| 862 | break;
|
---|
[918] | 863 | default:
|
---|
[1170] | 864 | return FcResultTypeMismatch;
|
---|
| 865 | }
|
---|
| 866 | return FcResultMatch;
|
---|
| 867 | }
|
---|
[918] | 868 |
|
---|
[1170] | 869 | FcResult
|
---|
| 870 | FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
|
---|
| 871 | {
|
---|
| 872 | return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
|
---|
[918] | 873 | }
|
---|
| 874 |
|
---|
[1170] | 875 |
|
---|
| 876 | FcResult
|
---|
| 877 | FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
|
---|
[918] | 878 | {
|
---|
[1170] | 879 | FcValue v;
|
---|
| 880 | FcResult r;
|
---|
[918] | 881 |
|
---|
[1170] | 882 | r = FcPatternObjectGet (p, object, id, &v);
|
---|
| 883 | if (r != FcResultMatch)
|
---|
| 884 | return r;
|
---|
| 885 | switch ((int) v.type) {
|
---|
| 886 | case FcTypeDouble:
|
---|
| 887 | *d = v.u.d;
|
---|
| 888 | break;
|
---|
[918] | 889 | case FcTypeInteger:
|
---|
[1170] | 890 | *d = (double) v.u.i;
|
---|
| 891 | break;
|
---|
[918] | 892 | default:
|
---|
[1170] | 893 | return FcResultTypeMismatch;
|
---|
| 894 | }
|
---|
| 895 | return FcResultMatch;
|
---|
| 896 | }
|
---|
[918] | 897 |
|
---|
[1170] | 898 | FcResult
|
---|
| 899 | FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
|
---|
| 900 | {
|
---|
| 901 | return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
|
---|
[918] | 902 | }
|
---|
| 903 |
|
---|
[1170] | 904 | FcResult
|
---|
| 905 | FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
|
---|
[918] | 906 | {
|
---|
[1170] | 907 | FcValue v;
|
---|
| 908 | FcResult r;
|
---|
| 909 |
|
---|
| 910 | r = FcPatternObjectGet (p, object, id, &v);
|
---|
| 911 | if (r != FcResultMatch)
|
---|
| 912 | return r;
|
---|
| 913 | if (v.type != FcTypeString)
|
---|
| 914 | return FcResultTypeMismatch;
|
---|
| 915 |
|
---|
| 916 | *s = (FcChar8 *) v.u.s;
|
---|
| 917 | return FcResultMatch;
|
---|
[918] | 918 | }
|
---|
| 919 |
|
---|
[1170] | 920 | FcResult
|
---|
| 921 | FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
|
---|
| 922 | {
|
---|
| 923 | return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
|
---|
| 924 | }
|
---|
[918] | 925 |
|
---|
[1170] | 926 | FcResult
|
---|
| 927 | FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
|
---|
[918] | 928 | {
|
---|
[1170] | 929 | FcValue v;
|
---|
| 930 | FcResult r;
|
---|
[918] | 931 |
|
---|
[1170] | 932 | r = FcPatternGet (p, object, id, &v);
|
---|
| 933 | if (r != FcResultMatch)
|
---|
| 934 | return r;
|
---|
| 935 | if (v.type != FcTypeMatrix)
|
---|
| 936 | return FcResultTypeMismatch;
|
---|
| 937 | *m = (FcMatrix *)v.u.m;
|
---|
| 938 | return FcResultMatch;
|
---|
[918] | 939 | }
|
---|
[1170] | 940 |
|
---|
| 941 | FcResult
|
---|
| 942 | FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
|
---|
| 943 | {
|
---|
| 944 | FcValue v;
|
---|
| 945 | FcResult r;
|
---|
| 946 |
|
---|
| 947 | r = FcPatternGet (p, object, id, &v);
|
---|
| 948 | if (r != FcResultMatch)
|
---|
| 949 | return r;
|
---|
| 950 | if (v.type != FcTypeBool)
|
---|
| 951 | return FcResultTypeMismatch;
|
---|
| 952 | *b = v.u.b;
|
---|
| 953 | return FcResultMatch;
|
---|
| 954 | }
|
---|
| 955 |
|
---|
| 956 | FcResult
|
---|
| 957 | FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
|
---|
| 958 | {
|
---|
| 959 | FcValue v;
|
---|
| 960 | FcResult r;
|
---|
| 961 |
|
---|
| 962 | r = FcPatternGet (p, object, id, &v);
|
---|
| 963 | if (r != FcResultMatch)
|
---|
| 964 | return r;
|
---|
| 965 | if (v.type != FcTypeCharSet)
|
---|
| 966 | return FcResultTypeMismatch;
|
---|
| 967 | *c = (FcCharSet *)v.u.c;
|
---|
| 968 | return FcResultMatch;
|
---|
| 969 | }
|
---|
| 970 |
|
---|
| 971 | FcResult
|
---|
| 972 | FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
|
---|
| 973 | {
|
---|
| 974 | FcValue v;
|
---|
| 975 | FcResult r;
|
---|
| 976 |
|
---|
| 977 | r = FcPatternGet (p, object, id, &v);
|
---|
| 978 | if (r != FcResultMatch)
|
---|
| 979 | return r;
|
---|
| 980 | if (v.type != FcTypeFTFace)
|
---|
| 981 | return FcResultTypeMismatch;
|
---|
| 982 | *f = (FT_Face) v.u.f;
|
---|
| 983 | return FcResultMatch;
|
---|
| 984 | }
|
---|
| 985 |
|
---|
| 986 | FcResult
|
---|
| 987 | FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
|
---|
| 988 | {
|
---|
| 989 | FcValue v;
|
---|
| 990 | FcResult r;
|
---|
| 991 |
|
---|
| 992 | r = FcPatternGet (p, object, id, &v);
|
---|
| 993 | if (r != FcResultMatch)
|
---|
| 994 | return r;
|
---|
| 995 | if (v.type != FcTypeLangSet)
|
---|
| 996 | return FcResultTypeMismatch;
|
---|
| 997 | *ls = (FcLangSet *)v.u.l;
|
---|
| 998 | return FcResultMatch;
|
---|
| 999 | }
|
---|
| 1000 |
|
---|
| 1001 | FcPattern *
|
---|
| 1002 | FcPatternDuplicate (const FcPattern *orig)
|
---|
| 1003 | {
|
---|
| 1004 | FcPattern *new;
|
---|
| 1005 | FcPatternElt *e;
|
---|
| 1006 | int i;
|
---|
| 1007 | FcValueListPtr l;
|
---|
| 1008 |
|
---|
| 1009 | new = FcPatternCreate ();
|
---|
| 1010 | if (!new)
|
---|
| 1011 | goto bail0;
|
---|
| 1012 |
|
---|
| 1013 | e = FcPatternElts(orig);
|
---|
| 1014 |
|
---|
| 1015 | for (i = 0; i < orig->num; i++)
|
---|
| 1016 | {
|
---|
| 1017 | for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
|
---|
| 1018 | {
|
---|
| 1019 | if (!FcPatternObjectAddWithBinding (new, e[i].object,
|
---|
| 1020 | FcValueCanonicalize(&l->value),
|
---|
| 1021 | l->binding,
|
---|
| 1022 | FcTrue))
|
---|
| 1023 | goto bail1;
|
---|
| 1024 |
|
---|
| 1025 | }
|
---|
| 1026 | }
|
---|
| 1027 |
|
---|
| 1028 | return new;
|
---|
| 1029 |
|
---|
| 1030 | bail1:
|
---|
| 1031 | FcPatternDestroy (new);
|
---|
| 1032 | bail0:
|
---|
| 1033 | return 0;
|
---|
| 1034 | }
|
---|
| 1035 |
|
---|
| 1036 | void
|
---|
| 1037 | FcPatternReference (FcPattern *p)
|
---|
| 1038 | {
|
---|
| 1039 | if (!p)
|
---|
| 1040 | return;
|
---|
| 1041 |
|
---|
| 1042 | if (!FcRefIsConst (&p->ref))
|
---|
| 1043 | FcRefInc (&p->ref);
|
---|
| 1044 | else
|
---|
[1172] | 1045 | FcRefInc (&p->ref);
|
---|
| 1046 | // FcCacheObjectReference (p);
|
---|
[1170] | 1047 | }
|
---|
| 1048 |
|
---|
| 1049 | FcPattern *
|
---|
| 1050 | FcPatternBuild (FcPattern *p, ...)
|
---|
| 1051 | {
|
---|
| 1052 | va_list va;
|
---|
| 1053 |
|
---|
| 1054 | // according to fontconfig FcInit() it's not needed in a app, so make sure its called
|
---|
| 1055 | if (!pConfig)
|
---|
| 1056 | FcInit();
|
---|
| 1057 |
|
---|
| 1058 | va_start (va, p);
|
---|
| 1059 | FcPatternVapBuild (p, p, va);
|
---|
| 1060 | va_end (va);
|
---|
| 1061 | return p;
|
---|
| 1062 | }
|
---|