2 * $XFree86: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
4 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
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.
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.
32 #include "../fc-lang/fclang.h"
35 FcChar32 map[NUM_LANG_SET_MAP];
39 #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
40 #define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
43 FcFreeTypeLangSet (const FcCharSet *charset,
44 const FcChar8 *exclusiveLang)
48 const FcCharSet *exclusiveCharset = 0;
53 exclusiveCharset = FcCharSetForLang (exclusiveLang);
54 ls = FcLangSetCreate ();
57 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
60 * Check for Han charsets to make fonts
61 * which advertise support for a single language
62 * not support other Han languages
64 if (exclusiveCharset &&
65 FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang) &&
66 fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves)
70 missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
71 if (FcDebug() & FC_DBG_SCANV)
73 if (missing && missing < 10)
75 FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
78 FcChar32 map[FC_CHARSET_MAP_SIZE];
81 printf ("\n%s(%d) ", fcLangCharSets[i].lang, missing);
83 for (ucs4 = FcCharSetFirstPage (missed, map, &next);
84 ucs4 != FC_CHARSET_DONE;
85 ucs4 = FcCharSetNextPage (missed, map, &next))
88 for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
91 for (j = 0; j < 32; j++)
92 if (map[i] & (1 << j))
93 printf (" %04x", ucs4 + i * 32 + j);
97 FcCharSetDestroy (missed);
100 printf ("%s(%d) ", fcLangCharSets[i].lang, missing);
103 FcLangSetBitSet (ls, i);
106 if (FcDebug() & FC_DBG_SCANV)
113 #define FcLangEnd(c) ((c) == '-' || (c) == '\0')
116 FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
119 FcLangResult result = FcLangDifferentLang;
130 if (FcLangEnd (c1) && FcLangEnd (c2))
131 result = FcLangDifferentCountry;
137 result = FcLangDifferentCountry;
142 FcCharSetForLang (const FcChar8 *lang)
146 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
148 switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
150 return &fcLangCharSets[i].charset;
151 case FcLangDifferentCountry:
160 return &fcLangCharSets[i].charset;
164 FcLangSetCreate (void)
168 ls = malloc (sizeof (FcLangSet));
171 FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
172 memset (ls->map, '\0', sizeof (ls->map));
178 FcLangSetDestroy (FcLangSet *ls)
181 FcStrSetDestroy (ls->extra);
182 FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
187 FcLangSetCopy (const FcLangSet *ls)
191 new = FcLangSetCreate ();
194 memcpy (new->map, ls->map, sizeof (new->map));
200 new->extra = FcStrSetCreate ();
204 list = FcStrListCreate (ls->extra);
208 while ((extra = FcStrListNext (list)))
209 if (!FcStrSetAdd (new->extra, extra))
211 FcStrListDone (list);
214 FcStrListDone (list);
218 FcLangSetDestroy (new);
224 FcLangSetIndex (const FcChar8 *lang)
230 high = NUM_LANG_CHAR_SET - 1;
233 mid = (high + low) >> 1;
234 cmp = FcStrCmpIgnoreCase (fcLangCharSets[mid].lang, lang);
248 FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
252 id = FcLangSetIndex (lang);
255 FcLangSetBitSet (ls, id);
260 ls->extra = FcStrSetCreate ();
264 return FcStrSetAdd (ls->extra, lang);
268 FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
271 FcLangResult best, r;
274 id = FcLangSetIndex (lang);
277 else if (FcLangSetBitGet (ls, id))
279 best = FcLangDifferentLang;
280 for (i = id - 1; i >= 0; i--)
282 r = FcLangCompare (lang, fcLangCharSets[i].lang);
283 if (r == FcLangDifferentLang)
285 if (FcLangSetBitGet (ls, i) && r < best)
288 for (i = id; i < NUM_LANG_CHAR_SET; i++)
290 r = FcLangCompare (lang, fcLangCharSets[i].lang);
291 if (r == FcLangDifferentLang)
293 if (FcLangSetBitGet (ls, i) && r < best)
298 FcStrList *list = FcStrListCreate (ls->extra);
304 while (best > FcLangEqual && (extra = FcStrListNext (list)))
306 r = FcLangCompare (lang, extra);
310 FcStrListDone (list);
317 FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
319 FcStrList *list = FcStrListCreate (set);
320 FcLangResult r, best = FcLangDifferentLang;
325 while (best > FcLangEqual && (extra = FcStrListNext (list)))
327 r = FcLangSetHasLang (ls, extra);
331 FcStrListDone (list);
337 FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
340 FcLangResult best, r;
342 for (i = 0; i < NUM_LANG_SET_MAP; i++)
343 if (lsa->map[i] & lsb->map[i])
345 best = FcLangDifferentLang;
346 for (j = 0; j < NUM_COUNTRY_SET; j++)
347 for (i = 0; i < NUM_LANG_SET_MAP; i++)
348 if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
349 (lsb->map[i] & fcLangCountrySets[j][i]))
351 best = FcLangDifferentCountry;
356 r = FcLangSetCompareStrSet (lsb, lsa->extra);
360 if (best > FcLangEqual && lsb->extra)
362 r = FcLangSetCompareStrSet (lsa, lsb->extra);
370 * Used in computing values -- mustn't allocate any storage
373 FcLangSetPromote (const FcChar8 *lang)
376 static FcStrSet strs;
380 memset (ls.map, '\0', sizeof (ls.map));
382 id = FcLangSetIndex (lang);
385 FcLangSetBitSet (&ls, id);
394 str = (FcChar8 *) lang;
400 FcLangSetHash (const FcLangSet *ls)
405 for (i = 0; i < NUM_LANG_SET_MAP; i++)
413 FcNameParseLangSet (const FcChar8 *string)
416 const FcChar8 *end, *next;
419 ls = FcLangSetCreate ();
423 while (string && *string)
425 end = (FcChar8 *) strchr ((char *) string, '|');
428 end = string + strlen ((char *) string);
433 if (end - string < sizeof (lang) - 1)
435 strncpy ((char *) lang, (char *) string, end - string);
436 lang[end-string] = '\0';
437 if (!FcLangSetAdd (ls, lang))
444 FcLangSetDestroy (ls);
450 FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
454 FcBool first = FcTrue;
456 for (i = 0; i < NUM_LANG_SET_MAP; i++)
458 if ((bits = ls->map[i]))
460 for (bit = 0; bit <= 31; bit++)
461 if (bits & (1 << bit))
463 int id = (i << 5) | bit;
465 if (!FcStrBufChar (buf, '|'))
467 if (!FcStrBufString (buf, fcLangCharSets[id].lang))
475 FcStrList *list = FcStrListCreate (ls->extra);
480 while ((extra = FcStrListNext (list)))
483 if (!FcStrBufChar (buf, '|'))
485 if (!FcStrBufString (buf, extra));
494 FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
498 for (i = 0; i < NUM_LANG_SET_MAP; i++)
500 if (lsa->map[i] != lsb->map[i])
503 if (!lsa->extra && !lsb->extra)
505 if (lsa->extra && lsb->extra)
506 return FcStrSetEqual (lsa->extra, lsb->extra);