]> git.wh0rd.org - fontconfig.git/blame - src/fclang.c
Rework cache files to use offsets for all data structures.
[fontconfig.git] / src / fclang.c
CommitLineData
3de8881e 1/*
793e946c 2 * $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
3de8881e 3 *
46b51147 4 * Copyright © 2002 Keith Packard
3de8881e
KP
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25#include "fcint.h"
26
27typedef struct {
21696e5b
PL
28 const FcChar8 *lang;
29 const FcCharSet charset;
3de8881e
KP
30} FcLangCharSet;
31
793e946c
KP
32typedef struct {
33 int begin;
34 int end;
35} FcLangCharSetRange;
36
e50b9ae7 37#include "../fc-lang/fclang.h"
3de8881e 38
d8d73958
KP
39struct _FcLangSet {
40 FcChar32 map[NUM_LANG_SET_MAP];
4262e0b3 41 FcStrSet *extra;
d8d73958
KP
42};
43
44#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
45#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
46
47FcLangSet *
48FcFreeTypeLangSet (const FcCharSet *charset,
e50b9ae7 49 const FcChar8 *exclusiveLang)
3de8881e 50{
cd2ec1a9 51 int i, j;
e50b9ae7 52 FcChar32 missing;
e50b9ae7 53 const FcCharSet *exclusiveCharset = 0;
d8d73958 54 FcLangSet *ls;
82f35f8b 55
e50b9ae7
KP
56 if (exclusiveLang)
57 exclusiveCharset = FcCharSetForLang (exclusiveLang);
d8d73958
KP
58 ls = FcLangSetCreate ();
59 if (!ls)
60 return 0;
7ce19673
KP
61 if (FcDebug() & FC_DBG_LANGSET)
62 {
63 printf ("font charset\n");
64 FcCharSetPrint (charset);
65 printf ("\n");
66 }
3de8881e
KP
67 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
68 {
7ce19673
KP
69 if (FcDebug() & FC_DBG_LANGSET)
70 {
71 printf ("%s charset\n", fcLangCharSets[i].lang);
72 FcCharSetPrint (&fcLangCharSets[i].charset);
73 printf ("\n");
74 }
75
e50b9ae7
KP
76 /*
77 * Check for Han charsets to make fonts
78 * which advertise support for a single language
79 * not support other Han languages
80 */
81 if (exclusiveCharset &&
cd2ec1a9 82 FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
e50b9ae7 83 {
cd2ec1a9
PL
84 if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
85 continue;
86
87 for (j = 0; j < fcLangCharSets[i].charset.num; j++)
7ce19673
KP
88 if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) !=
89 FcCharSetLeaf(exclusiveCharset, j))
cd2ec1a9 90 continue;
e50b9ae7 91 }
3de8881e
KP
92 missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
93 if (FcDebug() & FC_DBG_SCANV)
c80d2ac4
KP
94 {
95 if (missing && missing < 10)
96 {
97 FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
98 charset);
99 FcChar32 ucs4;
100 FcChar32 map[FC_CHARSET_MAP_SIZE];
101 FcChar32 next;
102
0d745819 103 printf ("\n%s(%u) ", fcLangCharSets[i].lang, missing);
c80d2ac4
KP
104 printf ("{");
105 for (ucs4 = FcCharSetFirstPage (missed, map, &next);
106 ucs4 != FC_CHARSET_DONE;
107 ucs4 = FcCharSetNextPage (missed, map, &next))
108 {
109 int i, j;
110 for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
111 if (map[i])
112 {
113 for (j = 0; j < 32; j++)
114 if (map[i] & (1 << j))
115 printf (" %04x", ucs4 + i * 32 + j);
116 }
117 }
118 printf (" }\n\t");
119 FcCharSetDestroy (missed);
120 }
121 else
0d745819 122 printf ("%s(%u) ", fcLangCharSets[i].lang, missing);
c80d2ac4 123 }
e50b9ae7 124 if (!missing)
d8d73958 125 FcLangSetBitSet (ls, i);
3de8881e 126 }
e50b9ae7 127
3de8881e
KP
128 if (FcDebug() & FC_DBG_SCANV)
129 printf ("\n");
d8d73958
KP
130
131
132 return ls;
3de8881e
KP
133}
134
d8d73958 135#define FcLangEnd(c) ((c) == '-' || (c) == '\0')
3de8881e
KP
136
137FcLangResult
138FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
139{
3de8881e 140 FcChar8 c1, c2;
d8d73958
KP
141 FcLangResult result = FcLangDifferentLang;
142
3de8881e
KP
143 for (;;)
144 {
145 c1 = *s1++;
146 c2 = *s2++;
d8d73958 147
3de8881e
KP
148 c1 = FcToLower (c1);
149 c2 = FcToLower (c2);
150 if (c1 != c2)
d8d73958
KP
151 {
152 if (FcLangEnd (c1) && FcLangEnd (c2))
153 result = FcLangDifferentCountry;
154 return result;
155 }
156 else if (!c1)
157 return FcLangEqual;
158 else if (c1 == '-')
159 result = FcLangDifferentCountry;
3de8881e 160 }
3de8881e
KP
161}
162
793e946c 163/*
74a623e0 164 * Return FcTrue when super contains sub.
793e946c 165 *
74a623e0
KP
166 * super contains sub if super and sub have the same
167 * language and either the same country or one
168 * is missing the country
793e946c
KP
169 */
170
171static FcBool
74a623e0 172FcLangContains (const FcChar8 *super, const FcChar8 *sub)
793e946c
KP
173{
174 FcChar8 c1, c2;
175
176 for (;;)
177 {
74a623e0
KP
178 c1 = *super++;
179 c2 = *sub++;
793e946c
KP
180
181 c1 = FcToLower (c1);
182 c2 = FcToLower (c2);
183 if (c1 != c2)
184 {
74a623e0 185 /* see if super has a country while sub is mising one */
793e946c
KP
186 if (c1 == '-' && c2 == '\0')
187 return FcTrue;
74a623e0
KP
188 /* see if sub has a country while super is mising one */
189 if (c1 == '\0' && c2 == '-')
190 return FcTrue;
793e946c
KP
191 return FcFalse;
192 }
193 else if (!c1)
194 return FcTrue;
195 }
196}
197
3de8881e
KP
198const FcCharSet *
199FcCharSetForLang (const FcChar8 *lang)
200{
201 int i;
202 int country = -1;
82f35f8b 203
3de8881e
KP
204 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
205 {
206 switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
207 case FcLangEqual:
208 return &fcLangCharSets[i].charset;
209 case FcLangDifferentCountry:
210 if (country == -1)
211 country = i;
212 default:
213 break;
214 }
215 }
216 if (country == -1)
217 return 0;
b36f2a39 218 return &fcLangCharSets[country].charset;
3de8881e 219}
d8d73958
KP
220
221FcLangSet *
222FcLangSetCreate (void)
223{
224 FcLangSet *ls;
225
226 ls = malloc (sizeof (FcLangSet));
227 if (!ls)
228 return 0;
229 FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
230 memset (ls->map, '\0', sizeof (ls->map));
4262e0b3 231 ls->extra = 0;
d8d73958
KP
232 return ls;
233}
234
235void
236FcLangSetDestroy (FcLangSet *ls)
237{
4262e0b3
PL
238 if (ls->extra)
239 FcStrSetDestroy (ls->extra);
d8d73958
KP
240 FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
241 free (ls);
242}
243
244FcLangSet *
245FcLangSetCopy (const FcLangSet *ls)
246{
247 FcLangSet *new;
248
249 new = FcLangSetCreate ();
250 if (!new)
251 goto bail0;
252 memcpy (new->map, ls->map, sizeof (new->map));
4262e0b3 253 if (ls->extra)
d8d73958
KP
254 {
255 FcStrList *list;
256 FcChar8 *extra;
257
4262e0b3
PL
258 new->extra = FcStrSetCreate ();
259 if (!new->extra)
d8d73958
KP
260 goto bail1;
261
4262e0b3 262 list = FcStrListCreate (ls->extra);
d8d73958
KP
263 if (!list)
264 goto bail1;
265
266 while ((extra = FcStrListNext (list)))
4262e0b3 267 if (!FcStrSetAdd (new->extra, extra))
d8d73958
KP
268 {
269 FcStrListDone (list);
270 goto bail1;
271 }
272 FcStrListDone (list);
273 }
274 return new;
275bail1:
276 FcLangSetDestroy (new);
277bail0:
278 return 0;
279}
280
281static int
282FcLangSetIndex (const FcChar8 *lang)
283{
12d49d3c
CW
284 int low, high, mid = 0;
285 int cmp = 0;
793e946c 286 FcChar8 firstChar = FcToLower(lang[0]);
947afeb5 287 FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
793e946c
KP
288
289 if (firstChar < 'a')
290 {
291 low = 0;
292 high = fcLangCharSetRanges[0].begin;
293 }
294 else if(firstChar > 'z')
295 {
296 low = fcLangCharSetRanges[25].begin;
297 high = NUM_LANG_CHAR_SET - 1;
298 }
299 else
300 {
301 low = fcLangCharSetRanges[firstChar - 'a'].begin;
302 high = fcLangCharSetRanges[firstChar - 'a'].end;
303 /* no matches */
304 if (low > high)
305 return -low; /* next entry after where it would be */
306 }
d8d73958 307
d8d73958
KP
308 while (low <= high)
309 {
310 mid = (high + low) >> 1;
793e946c
KP
311 if(fcLangCharSets[mid].lang[0] != firstChar)
312 cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang);
313 else
314 { /* fast path for resolving 2-letter languages (by far the most common) after
315 * finding the first char (probably already true because of the hash table) */
947afeb5
KP
316 cmp = fcLangCharSets[mid].lang[1] - secondChar;
317 if (cmp == 0 &&
318 (fcLangCharSets[mid].lang[2] != '\0' ||
319 lang[2] != '\0'))
793e946c 320 {
947afeb5
KP
321 cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
322 lang+2);
793e946c 323 }
793e946c
KP
324 }
325 if (cmp == 0)
d8d73958
KP
326 return mid;
327 if (cmp < 0)
328 low = mid + 1;
329 else
330 high = mid - 1;
331 }
332 if (cmp < 0)
333 mid++;
334 return -(mid + 1);
335}
336
337FcBool
338FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
339{
340 int id;
341
342 id = FcLangSetIndex (lang);
343 if (id >= 0)
344 {
345 FcLangSetBitSet (ls, id);
346 return FcTrue;
347 }
4262e0b3 348 if (!ls->extra)
d8d73958 349 {
4262e0b3
PL
350 ls->extra = FcStrSetCreate ();
351 if (!ls->extra)
d8d73958
KP
352 return FcFalse;
353 }
4262e0b3 354 return FcStrSetAdd (ls->extra, lang);
d8d73958
KP
355}
356
357FcLangResult
358FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
359{
360 int id;
361 FcLangResult best, r;
362 int i;
363
364 id = FcLangSetIndex (lang);
2458a6d8
KP
365 if (id < 0)
366 id = -id - 1;
367 else if (FcLangSetBitGet (ls, id))
d8d73958 368 return FcLangEqual;
d8d73958
KP
369 best = FcLangDifferentLang;
370 for (i = id - 1; i >= 0; i--)
371 {
372 r = FcLangCompare (lang, fcLangCharSets[i].lang);
373 if (r == FcLangDifferentLang)
374 break;
375 if (FcLangSetBitGet (ls, i) && r < best)
376 best = r;
377 }
378 for (i = id; i < NUM_LANG_CHAR_SET; i++)
379 {
380 r = FcLangCompare (lang, fcLangCharSets[i].lang);
381 if (r == FcLangDifferentLang)
382 break;
383 if (FcLangSetBitGet (ls, i) && r < best)
384 best = r;
385 }
4262e0b3 386 if (ls->extra)
d8d73958 387 {
4262e0b3 388 FcStrList *list = FcStrListCreate (ls->extra);
d8d73958 389 FcChar8 *extra;
d8d73958
KP
390
391 if (list)
392 {
393 while (best > FcLangEqual && (extra = FcStrListNext (list)))
394 {
395 r = FcLangCompare (lang, extra);
396 if (r < best)
397 best = r;
398 }
399 FcStrListDone (list);
400 }
401 }
402 return best;
403}
404
405static FcLangResult
406FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
407{
408 FcStrList *list = FcStrListCreate (set);
409 FcLangResult r, best = FcLangDifferentLang;
410 FcChar8 *extra;
411
412 if (list)
413 {
414 while (best > FcLangEqual && (extra = FcStrListNext (list)))
415 {
416 r = FcLangSetHasLang (ls, extra);
417 if (r < best)
418 best = r;
419 }
420 FcStrListDone (list);
421 }
422 return best;
423}
424
425FcLangResult
426FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
427{
234397b4 428 int i, j;
d8d73958
KP
429 FcLangResult best, r;
430
431 for (i = 0; i < NUM_LANG_SET_MAP; i++)
432 if (lsa->map[i] & lsb->map[i])
433 return FcLangEqual;
434 best = FcLangDifferentLang;
234397b4
DD
435 for (j = 0; j < NUM_COUNTRY_SET; j++)
436 for (i = 0; i < NUM_LANG_SET_MAP; i++)
437 if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
438 (lsb->map[i] & fcLangCountrySets[j][i]))
439 {
440 best = FcLangDifferentCountry;
441 break;
442 }
4262e0b3 443 if (lsa->extra)
d8d73958 444 {
4262e0b3 445 r = FcLangSetCompareStrSet (lsb, lsa->extra);
d8d73958
KP
446 if (r < best)
447 best = r;
448 }
4262e0b3 449 if (best > FcLangEqual && lsb->extra)
d8d73958 450 {
4262e0b3 451 r = FcLangSetCompareStrSet (lsa, lsb->extra);
d8d73958
KP
452 if (r < best)
453 best = r;
454 }
455 return best;
456}
457
458/*
459 * Used in computing values -- mustn't allocate any storage
460 */
461FcLangSet *
462FcLangSetPromote (const FcChar8 *lang)
463{
464 static FcLangSet ls;
465 static FcStrSet strs;
466 static FcChar8 *str;
467 int id;
468
469 memset (ls.map, '\0', sizeof (ls.map));
4262e0b3 470 ls.extra = 0;
d8d73958
KP
471 id = FcLangSetIndex (lang);
472 if (id > 0)
473 {
474 FcLangSetBitSet (&ls, id);
475 }
476 else
477 {
4262e0b3 478 ls.extra = &strs;
d8d73958
KP
479 strs.num = 1;
480 strs.size = 1;
4262e0b3 481 strs.strs = &str;
47d4f950 482 strs.ref = 1;
d8d73958
KP
483 str = (FcChar8 *) lang;
484 }
485 return &ls;
486}
487
488FcChar32
489FcLangSetHash (const FcLangSet *ls)
490{
491 FcChar32 h = 0;
492 int i;
493
494 for (i = 0; i < NUM_LANG_SET_MAP; i++)
495 h ^= ls->map[i];
4262e0b3
PL
496 if (ls->extra)
497 h ^= ls->extra->num;
d8d73958
KP
498 return h;
499}
500
501FcLangSet *
502FcNameParseLangSet (const FcChar8 *string)
503{
793e946c
KP
504 FcChar8 lang[32],c;
505 int i;
d8d73958
KP
506 FcLangSet *ls;
507
508 ls = FcLangSetCreate ();
509 if (!ls)
510 goto bail0;
511
793e946c 512 for(;;)
d8d73958 513 {
793e946c 514 for(i = 0; i < 31;i++)
d8d73958 515 {
793e946c
KP
516 c = *string++;
517 if(c == '\0' || c == '|')
518 break; /* end of this code */
519 lang[i] = c;
d8d73958 520 }
793e946c
KP
521 lang[i] = '\0';
522 if (!FcLangSetAdd (ls, lang))
523 goto bail1;
524 if(c == '\0')
525 break;
d8d73958
KP
526 }
527 return ls;
528bail1:
529 FcLangSetDestroy (ls);
530bail0:
531 return 0;
532}
533
534FcBool
535FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
536{
537 int i, bit;
538 FcChar32 bits;
539 FcBool first = FcTrue;
540
541 for (i = 0; i < NUM_LANG_SET_MAP; i++)
542 {
543 if ((bits = ls->map[i]))
544 {
545 for (bit = 0; bit <= 31; bit++)
546 if (bits & (1 << bit))
547 {
548 int id = (i << 5) | bit;
549 if (!first)
550 if (!FcStrBufChar (buf, '|'))
551 return FcFalse;
552 if (!FcStrBufString (buf, fcLangCharSets[id].lang))
553 return FcFalse;
554 first = FcFalse;
555 }
556 }
557 }
4262e0b3 558 if (ls->extra)
d8d73958 559 {
4262e0b3 560 FcStrList *list = FcStrListCreate (ls->extra);
d8d73958
KP
561 FcChar8 *extra;
562
563 if (!list)
564 return FcFalse;
565 while ((extra = FcStrListNext (list)))
566 {
567 if (!first)
568 if (!FcStrBufChar (buf, '|'))
04f7d3e7
PL
569 {
570 FcStrListDone (list);
d8d73958 571 return FcFalse;
04f7d3e7 572 }
793e946c 573 if (!FcStrBufString (buf, extra))
04f7d3e7
PL
574 {
575 FcStrListDone (list);
576 return FcFalse;
577 }
d8d73958
KP
578 first = FcFalse;
579 }
2de24638 580 FcStrListDone (list);
d8d73958
KP
581 }
582 return FcTrue;
583}
584
585FcBool
586FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
587{
588 int i;
589
590 for (i = 0; i < NUM_LANG_SET_MAP; i++)
591 {
592 if (lsa->map[i] != lsb->map[i])
593 return FcFalse;
594 }
4262e0b3 595 if (!lsa->extra && !lsb->extra)
d8d73958 596 return FcTrue;
4262e0b3
PL
597 if (lsa->extra && lsb->extra)
598 return FcStrSetEqual (lsa->extra, lsb->extra);
d8d73958
KP
599 return FcFalse;
600}
793e946c
KP
601
602static FcBool
603FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
604{
605 int id;
793e946c
KP
606 int i;
607
608 id = FcLangSetIndex (lang);
609 if (id < 0)
610 id = -id - 1;
611 else if (FcLangSetBitGet (ls, id))
612 return FcTrue;
613 /*
614 * search up and down among equal languages for a match
615 */
616 for (i = id - 1; i >= 0; i--)
617 {
618 if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
619 break;
620 if (FcLangSetBitGet (ls, i) &&
621 FcLangContains (fcLangCharSets[i].lang, lang))
622 return FcTrue;
623 }
624 for (i = id; i < NUM_LANG_CHAR_SET; i++)
625 {
626 if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
627 break;
628 if (FcLangSetBitGet (ls, i) &&
629 FcLangContains (fcLangCharSets[i].lang, lang))
630 return FcTrue;
631 }
4262e0b3 632 if (ls->extra)
793e946c 633 {
4262e0b3 634 FcStrList *list = FcStrListCreate (ls->extra);
793e946c 635 FcChar8 *extra;
793e946c
KP
636
637 if (list)
638 {
639 while ((extra = FcStrListNext (list)))
640 {
641 if (FcLangContains (extra, lang))
642 break;
643 }
644 FcStrListDone (list);
645 if (extra)
646 return FcTrue;
647 }
648 }
649 return FcFalse;
650}
651
652/*
653 * return FcTrue if lsa contains every language in lsb
654 */
655FcBool
656FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
657{
658 int i, j;
659 FcChar32 missing;
660
661 if (FcDebug() & FC_DBG_MATCHV)
662 {
663 printf ("FcLangSet "); FcLangSetPrint (lsa);
664 printf (" contains "); FcLangSetPrint (lsb);
665 printf ("\n");
666 }
667 /*
668 * check bitmaps for missing language support
669 */
670 for (i = 0; i < NUM_LANG_SET_MAP; i++)
671 {
672 missing = lsb->map[i] & ~lsa->map[i];
673 if (missing)
674 {
675 for (j = 0; j < 32; j++)
676 if (missing & (1 << j))
677 {
678 if (!FcLangSetContainsLang (lsa,
679 fcLangCharSets[i*32 + j].lang))
680 {
681 if (FcDebug() & FC_DBG_MATCHV)
682 printf ("\tMissing bitmap %s\n", fcLangCharSets[i*32+j].lang);
683 return FcFalse;
684 }
685 }
686 }
687 }
4262e0b3 688 if (lsb->extra)
793e946c 689 {
4262e0b3 690 FcStrList *list = FcStrListCreate (lsb->extra);
793e946c
KP
691 FcChar8 *extra;
692
693 if (list)
694 {
695 while ((extra = FcStrListNext (list)))
696 {
697 if (!FcLangSetContainsLang (lsa, extra))
698 {
699 if (FcDebug() & FC_DBG_MATCHV)
700 printf ("\tMissing string %s\n", extra);
701 break;
702 }
703 }
704 FcStrListDone (list);
705 if (extra)
706 return FcFalse;
707 }
708 }
709 return FcTrue;
710}
cd2ec1a9 711
7ce19673
KP
712FcBool
713FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l)
cd2ec1a9 714{
7ce19673
KP
715 if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet)))
716 return FcFalse;
4262e0b3 717 return FcTrue;
cd2ec1a9 718}
212c9f43 719
4262e0b3 720FcLangSet *
7ce19673 721FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l)
4262e0b3 722{
7ce19673 723 FcLangSet *l_serialize = FcSerializePtr (serialize, l);
4262e0b3 724
7ce19673
KP
725 if (!l_serialize)
726 return NULL;
727 *l_serialize = *l;
728 return l_serialize;
212c9f43 729}