2 * $XFree86: xc/lib/fontconfig/src/fclang.c,v 1.4 2002/07/12 21:06:03 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"
34 #define NUM_LANG_CHAR_SET (sizeof (fcLangCharSets) / sizeof (fcLangCharSets[0]))
35 #define NUM_LANG_SET_MAP ((NUM_LANG_CHAR_SET + 31) / 32)
38 FcChar32 map[NUM_LANG_SET_MAP];
42 #define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
43 #define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
46 FcFreeTypeLangSet (const FcCharSet *charset,
47 const FcChar8 *exclusiveLang)
51 const FcCharSet *exclusiveCharset = 0;
56 exclusiveCharset = FcCharSetForLang (exclusiveLang);
57 ls = FcLangSetCreate ();
60 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
63 * Check for Han charsets to make fonts
64 * which advertise support for a single language
65 * not support other Han languages
67 if (exclusiveCharset &&
68 FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang) &&
69 fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves)
73 missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
74 if (FcDebug() & FC_DBG_SCANV)
76 if (missing && missing < 10)
78 FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
81 FcChar32 map[FC_CHARSET_MAP_SIZE];
84 printf ("\n%s(%d) ", fcLangCharSets[i].lang, missing);
86 for (ucs4 = FcCharSetFirstPage (missed, map, &next);
87 ucs4 != FC_CHARSET_DONE;
88 ucs4 = FcCharSetNextPage (missed, map, &next))
91 for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
94 for (j = 0; j < 32; j++)
95 if (map[i] & (1 << j))
96 printf (" %04x", ucs4 + i * 32 + j);
100 FcCharSetDestroy (missed);
103 printf ("%s(%d) ", fcLangCharSets[i].lang, missing);
106 FcLangSetBitSet (ls, i);
109 if (FcDebug() & FC_DBG_SCANV)
116 #define FcLangEnd(c) ((c) == '-' || (c) == '\0')
119 FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
122 FcLangResult result = FcLangDifferentLang;
133 if (FcLangEnd (c1) && FcLangEnd (c2))
134 result = FcLangDifferentCountry;
140 result = FcLangDifferentCountry;
145 FcCharSetForLang (const FcChar8 *lang)
149 for (i = 0; i < NUM_LANG_CHAR_SET; i++)
151 switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
153 return &fcLangCharSets[i].charset;
154 case FcLangDifferentCountry:
163 return &fcLangCharSets[i].charset;
167 FcLangSetCreate (void)
171 ls = malloc (sizeof (FcLangSet));
174 FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
175 memset (ls->map, '\0', sizeof (ls->map));
181 FcLangSetDestroy (FcLangSet *ls)
184 FcStrSetDestroy (ls->extra);
185 FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
190 FcLangSetCopy (const FcLangSet *ls)
194 new = FcLangSetCreate ();
197 memcpy (new->map, ls->map, sizeof (new->map));
203 new->extra = FcStrSetCreate ();
207 list = FcStrListCreate (ls->extra);
211 while ((extra = FcStrListNext (list)))
212 if (!FcStrSetAdd (new->extra, extra))
214 FcStrListDone (list);
217 FcStrListDone (list);
221 FcLangSetDestroy (new);
227 FcLangSetIndex (const FcChar8 *lang)
233 high = NUM_LANG_CHAR_SET - 1;
236 mid = (high + low) >> 1;
237 cmp = FcStrCmpIgnoreCase (fcLangCharSets[mid].lang, lang);
251 FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
255 id = FcLangSetIndex (lang);
258 FcLangSetBitSet (ls, id);
263 ls->extra = FcStrSetCreate ();
267 return FcStrSetAdd (ls->extra, lang);
271 FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
274 FcLangResult best, r;
277 id = FcLangSetIndex (lang);
281 best = FcLangDifferentLang;
282 for (i = id - 1; i >= 0; i--)
284 r = FcLangCompare (lang, fcLangCharSets[i].lang);
285 if (r == FcLangDifferentLang)
287 if (FcLangSetBitGet (ls, i) && r < best)
290 for (i = id; i < NUM_LANG_CHAR_SET; i++)
292 r = FcLangCompare (lang, fcLangCharSets[i].lang);
293 if (r == FcLangDifferentLang)
295 if (FcLangSetBitGet (ls, i) && r < best)
300 FcStrList *list = FcStrListCreate (ls->extra);
306 while (best > FcLangEqual && (extra = FcStrListNext (list)))
308 r = FcLangCompare (lang, extra);
312 FcStrListDone (list);
319 FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
321 FcStrList *list = FcStrListCreate (set);
322 FcLangResult r, best = FcLangDifferentLang;
327 while (best > FcLangEqual && (extra = FcStrListNext (list)))
329 r = FcLangSetHasLang (ls, extra);
333 FcStrListDone (list);
339 FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
342 FcLangResult best, r;
344 for (i = 0; i < NUM_LANG_SET_MAP; i++)
345 if (lsa->map[i] & lsb->map[i])
347 best = FcLangDifferentLang;
350 r = FcLangSetCompareStrSet (lsb, lsa->extra);
354 if (best > FcLangEqual && lsb->extra)
356 r = FcLangSetCompareStrSet (lsa, lsb->extra);
364 * Used in computing values -- mustn't allocate any storage
367 FcLangSetPromote (const FcChar8 *lang)
370 static FcStrSet strs;
374 memset (ls.map, '\0', sizeof (ls.map));
376 id = FcLangSetIndex (lang);
379 FcLangSetBitSet (&ls, id);
387 str = (FcChar8 *) lang;
393 FcLangSetHash (const FcLangSet *ls)
398 for (i = 0; i < NUM_LANG_SET_MAP; i++)
406 FcNameParseLangSet (const FcChar8 *string)
409 const FcChar8 *end, *next;
412 ls = FcLangSetCreate ();
416 while (string && *string)
418 end = (FcChar8 *) strchr ((char *) string, '|');
421 end = string + strlen ((char *) string);
426 if (end - string < sizeof (lang) - 1)
428 strncpy ((char *) lang, (char *) string, end - string);
429 lang[end-string] = '\0';
430 if (!FcLangSetAdd (ls, lang))
437 FcLangSetDestroy (ls);
443 FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
447 FcBool first = FcTrue;
449 for (i = 0; i < NUM_LANG_SET_MAP; i++)
451 if ((bits = ls->map[i]))
453 for (bit = 0; bit <= 31; bit++)
454 if (bits & (1 << bit))
456 int id = (i << 5) | bit;
458 if (!FcStrBufChar (buf, '|'))
460 if (!FcStrBufString (buf, fcLangCharSets[id].lang))
468 FcStrList *list = FcStrListCreate (ls->extra);
473 while ((extra = FcStrListNext (list)))
476 if (!FcStrBufChar (buf, '|'))
478 if (!FcStrBufString (buf, extra));
487 FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
491 for (i = 0; i < NUM_LANG_SET_MAP; i++)
493 if (lsa->map[i] != lsb->map[i])
496 if (!lsa->extra && !lsb->extra)
498 if (lsa->extra && lsb->extra)
499 return FcStrSetEqual (lsa->extra, lsb->extra);