Add missing license headers
[platform/upstream/fontconfig.git] / src / fcname.c
1 /*
2  * fontconfig/src/fcname.c
3  *
4  * Copyright © 2000 Keith Packard
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 the author(s) not be used in
11  * advertising or publicity pertaining to distribution of the software without
12  * specific, written prior permission.  The authors make 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  * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE AUTHOR(S) 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 #include <ctype.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 static const FcObjectType FcObjects[] = {
32 #define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME, Type },
33 #include "fcobjs.h"
34 #undef FC_OBJECT
35 };
36
37 #define NUM_OBJECT_TYPES ((int) (sizeof FcObjects / sizeof FcObjects[0]))
38
39 static const FcObjectType *
40 FcObjectFindById (FcObject object)
41 {
42     if (1 <= object && object <= NUM_OBJECT_TYPES)
43         return &FcObjects[object - 1];
44     return FcObjectLookupOtherTypeById (object);
45 }
46
47 FcBool
48 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
49 {
50     /* Deprecated. */
51     return FcFalse;
52 }
53
54 FcBool
55 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
56 {
57     /* Deprecated. */
58     return FcFalse;
59 }
60
61 const FcObjectType *
62 FcNameGetObjectType (const char *object)
63 {
64     int id = FcObjectLookupBuiltinIdByName (object);
65
66     if (!id)
67         return FcObjectLookupOtherTypeByName (object);
68
69     return &FcObjects[id - 1];
70 }
71
72 FcBool
73 FcObjectValidType (FcObject object, FcType type)
74 {
75     const FcObjectType    *t = FcObjectFindById (object);
76
77     if (t) {
78         switch ((int) t->type) {
79         case FcTypeUnknown:
80             return FcTrue;
81         case FcTypeDouble:
82         case FcTypeInteger:
83             if (type == FcTypeDouble || type == FcTypeInteger)
84                 return FcTrue;
85             break;
86         case FcTypeLangSet:
87             if (type == FcTypeLangSet || type == FcTypeString)
88                 return FcTrue;
89             break;
90         default:
91             if (type == t->type)
92                 return FcTrue;
93             break;
94         }
95         return FcFalse;
96     }
97     return FcTrue;
98 }
99
100 FcObject
101 FcObjectFromName (const char * name)
102 {
103     return FcObjectLookupIdByName (name);
104 }
105
106 FcObjectSet *
107 FcObjectGetSet (void)
108 {
109     int         i;
110     FcObjectSet *os = NULL;
111
112
113     os = FcObjectSetCreate ();
114     for (i = 0; i < NUM_OBJECT_TYPES; i++)
115         FcObjectSetAdd (os, FcObjects[i].object);
116
117     return os;
118 }
119
120 const char *
121 FcObjectName (FcObject object)
122 {
123     const FcObjectType   *o = FcObjectFindById (object);
124
125     if (o)
126         return o->object;
127
128     return FcObjectLookupOtherNameById (object);
129 }
130
131 static const FcConstant _FcBaseConstants[] = {
132     { (FcChar8 *) "thin",           "weight",   FC_WEIGHT_THIN, },
133     { (FcChar8 *) "extralight",     "weight",   FC_WEIGHT_EXTRALIGHT, },
134     { (FcChar8 *) "ultralight",     "weight",   FC_WEIGHT_EXTRALIGHT, },
135     { (FcChar8 *) "light",          "weight",   FC_WEIGHT_LIGHT, },
136     { (FcChar8 *) "book",           "weight",   FC_WEIGHT_BOOK, },
137     { (FcChar8 *) "regular",        "weight",   FC_WEIGHT_REGULAR, },
138     { (FcChar8 *) "medium",         "weight",   FC_WEIGHT_MEDIUM, },
139     { (FcChar8 *) "demibold",       "weight",   FC_WEIGHT_DEMIBOLD, },
140     { (FcChar8 *) "semibold",       "weight",   FC_WEIGHT_DEMIBOLD, },
141     { (FcChar8 *) "bold",           "weight",   FC_WEIGHT_BOLD, },
142     { (FcChar8 *) "extrabold",      "weight",   FC_WEIGHT_EXTRABOLD, },
143     { (FcChar8 *) "ultrabold",      "weight",   FC_WEIGHT_EXTRABOLD, },
144     { (FcChar8 *) "black",          "weight",   FC_WEIGHT_BLACK, },
145     { (FcChar8 *) "heavy",          "weight",   FC_WEIGHT_HEAVY, },
146
147     { (FcChar8 *) "roman",          "slant",    FC_SLANT_ROMAN, },
148     { (FcChar8 *) "italic",         "slant",    FC_SLANT_ITALIC, },
149     { (FcChar8 *) "oblique",        "slant",    FC_SLANT_OBLIQUE, },
150
151     { (FcChar8 *) "ultracondensed", "width",    FC_WIDTH_ULTRACONDENSED },
152     { (FcChar8 *) "extracondensed", "width",    FC_WIDTH_EXTRACONDENSED },
153     { (FcChar8 *) "condensed",      "width",    FC_WIDTH_CONDENSED },
154     { (FcChar8 *) "semicondensed",  "width",    FC_WIDTH_SEMICONDENSED },
155     { (FcChar8 *) "normal",         "width",    FC_WIDTH_NORMAL },
156     { (FcChar8 *) "semiexpanded",   "width",    FC_WIDTH_SEMIEXPANDED },
157     { (FcChar8 *) "expanded",       "width",    FC_WIDTH_EXPANDED },
158     { (FcChar8 *) "extraexpanded",  "width",    FC_WIDTH_EXTRAEXPANDED },
159     { (FcChar8 *) "ultraexpanded",  "width",    FC_WIDTH_ULTRAEXPANDED },
160
161     { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
162     { (FcChar8 *) "dual",           "spacing",  FC_DUAL, },
163     { (FcChar8 *) "mono",           "spacing",  FC_MONO, },
164     { (FcChar8 *) "charcell",       "spacing",  FC_CHARCELL, },
165
166     { (FcChar8 *) "unknown",        "rgba",         FC_RGBA_UNKNOWN },
167     { (FcChar8 *) "rgb",            "rgba",         FC_RGBA_RGB, },
168     { (FcChar8 *) "bgr",            "rgba",         FC_RGBA_BGR, },
169     { (FcChar8 *) "vrgb",           "rgba",         FC_RGBA_VRGB },
170     { (FcChar8 *) "vbgr",           "rgba",         FC_RGBA_VBGR },
171     { (FcChar8 *) "none",           "rgba",         FC_RGBA_NONE },
172
173     { (FcChar8 *) "hintnone",       "hintstyle",   FC_HINT_NONE },
174     { (FcChar8 *) "hintslight",     "hintstyle",   FC_HINT_SLIGHT },
175     { (FcChar8 *) "hintmedium",     "hintstyle",   FC_HINT_MEDIUM },
176     { (FcChar8 *) "hintfull",       "hintstyle",   FC_HINT_FULL },
177
178     { (FcChar8 *) "antialias",      "antialias",    FcTrue },
179     { (FcChar8 *) "hinting",        "hinting",      FcTrue },
180     { (FcChar8 *) "verticallayout", "verticallayout",   FcTrue },
181     { (FcChar8 *) "autohint",       "autohint",     FcTrue },
182     { (FcChar8 *) "globaladvance",  "globaladvance",    FcTrue }, /* deprecated */
183     { (FcChar8 *) "outline",        "outline",      FcTrue },
184     { (FcChar8 *) "scalable",       "scalable",     FcTrue },
185     { (FcChar8 *) "minspace",       "minspace",     FcTrue },
186     { (FcChar8 *) "embolden",       "embolden",     FcTrue },
187     { (FcChar8 *) "embeddedbitmap", "embeddedbitmap",   FcTrue },
188     { (FcChar8 *) "decorative",     "decorative",   FcTrue },
189     { (FcChar8 *) "lcdnone",        "lcdfilter",    FC_LCD_NONE },
190     { (FcChar8 *) "lcddefault",     "lcdfilter",    FC_LCD_DEFAULT },
191     { (FcChar8 *) "lcdlight",       "lcdfilter",    FC_LCD_LIGHT },
192     { (FcChar8 *) "lcdlegacy",      "lcdfilter",    FC_LCD_LEGACY },
193 };
194
195 #define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
196
197 FcBool
198 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
199 {
200     /* Deprecated. */
201     return FcFalse;
202 }
203
204 FcBool
205 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
206 {
207     /* Deprecated. */
208     return FcFalse;
209 }
210
211 const FcConstant *
212 FcNameGetConstant (const FcChar8 *string)
213 {
214     unsigned int            i;
215
216     for (i = 0; i < NUM_FC_CONSTANTS; i++)
217         if (!FcStrCmpIgnoreCase (string, _FcBaseConstants[i].name))
218             return &_FcBaseConstants[i];
219
220     return 0;
221 }
222
223 FcBool
224 FcNameConstant (const FcChar8 *string, int *result)
225 {
226     const FcConstant    *c;
227
228     if ((c = FcNameGetConstant(string)))
229     {
230         *result = c->value;
231         return FcTrue;
232     }
233     return FcFalse;
234 }
235
236 FcBool
237 FcNameBool (const FcChar8 *v, FcBool *result)
238 {
239     char    c0, c1;
240
241     c0 = *v;
242     c0 = FcToLower (c0);
243     if (c0 == 't' || c0 == 'y' || c0 == '1')
244     {
245         *result = FcTrue;
246         return FcTrue;
247     }
248     if (c0 == 'f' || c0 == 'n' || c0 == '0')
249     {
250         *result = FcFalse;
251         return FcTrue;
252     }
253     if (c0 == 'o')
254     {
255         c1 = v[1];
256         c1 = FcToLower (c1);
257         if (c1 == 'n')
258         {
259             *result = FcTrue;
260             return FcTrue;
261         }
262         if (c1 == 'f')
263         {
264             *result = FcFalse;
265             return FcTrue;
266         }
267     }
268     return FcFalse;
269 }
270
271 static FcValue
272 FcNameConvert (FcType type, FcChar8 *string)
273 {
274     FcValue     v;
275     FcMatrix    m;
276
277     v.type = type;
278     switch ((int) v.type) {
279     case FcTypeInteger:
280         if (!FcNameConstant (string, &v.u.i))
281             v.u.i = atoi ((char *) string);
282         break;
283     case FcTypeString:
284         v.u.s = FcStrdup (string);
285         if (!v.u.s)
286             v.type = FcTypeVoid;
287         break;
288     case FcTypeBool:
289         if (!FcNameBool (string, &v.u.b))
290             v.u.b = FcFalse;
291         break;
292     case FcTypeDouble:
293         v.u.d = strtod ((char *) string, 0);
294         break;
295     case FcTypeMatrix:
296         FcMatrixInit (&m);
297         sscanf ((char *) string, "%lg %lg %lg %lg", &m.xx, &m.xy, &m.yx, &m.yy);
298         v.u.m = FcMatrixCopy (&m);
299         break;
300     case FcTypeCharSet:
301         v.u.c = FcNameParseCharSet (string);
302         if (!v.u.c)
303             v.type = FcTypeVoid;
304         break;
305     case FcTypeLangSet:
306         v.u.l = FcNameParseLangSet (string);
307         if (!v.u.l)
308             v.type = FcTypeVoid;
309         break;
310     default:
311         break;
312     }
313     return v;
314 }
315
316 static const FcChar8 *
317 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
318 {
319     FcChar8    c;
320
321     while ((c = *cur))
322     {
323         if (!isspace (c))
324             break;
325         ++cur;
326     }
327     while ((c = *cur))
328     {
329         if (c == '\\')
330         {
331             ++cur;
332             if (!(c = *cur))
333                 break;
334         }
335         else if (strchr (delim, c))
336             break;
337         ++cur;
338         *save++ = c;
339     }
340     *save = 0;
341     *last = *cur;
342     if (*cur)
343         cur++;
344     return cur;
345 }
346
347 FcPattern *
348 FcNameParse (const FcChar8 *name)
349 {
350     FcChar8             *save;
351     FcPattern           *pat;
352     double              d;
353     FcChar8             *e;
354     FcChar8             delim;
355     FcValue             v;
356     const FcObjectType  *t;
357     const FcConstant    *c;
358
359     /* freed below */
360     save = malloc (strlen ((char *) name) + 1);
361     if (!save)
362         goto bail0;
363     pat = FcPatternCreate ();
364     if (!pat)
365         goto bail1;
366
367     for (;;)
368     {
369         name = FcNameFindNext (name, "-,:", save, &delim);
370         if (save[0])
371         {
372             if (!FcPatternAddString (pat, FC_FAMILY, save))
373                 goto bail2;
374         }
375         if (delim != ',')
376             break;
377     }
378     if (delim == '-')
379     {
380         for (;;)
381         {
382             name = FcNameFindNext (name, "-,:", save, &delim);
383             d = strtod ((char *) save, (char **) &e);
384             if (e != save)
385             {
386                 if (!FcPatternAddDouble (pat, FC_SIZE, d))
387                     goto bail2;
388             }
389             if (delim != ',')
390                 break;
391         }
392     }
393     while (delim == ':')
394     {
395         name = FcNameFindNext (name, "=_:", save, &delim);
396         if (save[0])
397         {
398             if (delim == '=' || delim == '_')
399             {
400                 t = FcNameGetObjectType ((char *) save);
401                 for (;;)
402                 {
403                     name = FcNameFindNext (name, ":,", save, &delim);
404                     if (t)
405                     {
406                         v = FcNameConvert (t->type, save);
407                         if (!FcPatternAdd (pat, t->object, v, FcTrue))
408                         {
409                             FcValueDestroy (v);
410                             goto bail2;
411                         }
412                         FcValueDestroy (v);
413                     }
414                     if (delim != ',')
415                         break;
416                 }
417             }
418             else
419             {
420                 if ((c = FcNameGetConstant (save)))
421                 {
422                     t = FcNameGetObjectType ((char *) c->object);
423                     if (t == NULL)
424                         goto bail2;
425                     switch ((int) t->type) {
426                     case FcTypeInteger:
427                     case FcTypeDouble:
428                         if (!FcPatternAddInteger (pat, c->object, c->value))
429                             goto bail2;
430                         break;
431                     case FcTypeBool:
432                         if (!FcPatternAddBool (pat, c->object, c->value))
433                             goto bail2;
434                         break;
435                     default:
436                         break;
437                     }
438                 }
439             }
440         }
441     }
442
443     free (save);
444     return pat;
445
446 bail2:
447     FcPatternDestroy (pat);
448 bail1:
449     free (save);
450 bail0:
451     return 0;
452 }
453 static FcBool
454 FcNameUnparseString (FcStrBuf       *buf,
455                      const FcChar8  *string,
456                      const FcChar8  *escape)
457 {
458     FcChar8 c;
459     while ((c = *string++))
460     {
461         if (escape && strchr ((char *) escape, (char) c))
462         {
463             if (!FcStrBufChar (buf, escape[0]))
464                 return FcFalse;
465         }
466         if (!FcStrBufChar (buf, c))
467             return FcFalse;
468     }
469     return FcTrue;
470 }
471
472 FcBool
473 FcNameUnparseValue (FcStrBuf    *buf,
474                     FcValue     *v0,
475                     FcChar8     *escape)
476 {
477     FcChar8     temp[1024];
478     FcValue v = FcValueCanonicalize(v0);
479
480     switch (v.type) {
481     case FcTypeUnknown:
482     case FcTypeVoid:
483         return FcTrue;
484     case FcTypeInteger:
485         sprintf ((char *) temp, "%d", v.u.i);
486         return FcNameUnparseString (buf, temp, 0);
487     case FcTypeDouble:
488         sprintf ((char *) temp, "%g", v.u.d);
489         return FcNameUnparseString (buf, temp, 0);
490     case FcTypeString:
491         return FcNameUnparseString (buf, v.u.s, escape);
492     case FcTypeBool:
493         return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
494     case FcTypeMatrix:
495         sprintf ((char *) temp, "%g %g %g %g",
496                  v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
497         return FcNameUnparseString (buf, temp, 0);
498     case FcTypeCharSet:
499         return FcNameUnparseCharSet (buf, v.u.c);
500     case FcTypeLangSet:
501         return FcNameUnparseLangSet (buf, v.u.l);
502     case FcTypeFTFace:
503         return FcTrue;
504     }
505     return FcFalse;
506 }
507
508 FcBool
509 FcNameUnparseValueList (FcStrBuf        *buf,
510                         FcValueListPtr  v,
511                         FcChar8         *escape)
512 {
513     while (v)
514     {
515         if (!FcNameUnparseValue (buf, &v->value, escape))
516             return FcFalse;
517         if ((v = FcValueListNext(v)) != NULL)
518             if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
519                 return FcFalse;
520     }
521     return FcTrue;
522 }
523
524 #define FC_ESCAPE_FIXED    "\\-:,"
525 #define FC_ESCAPE_VARIABLE "\\=_:,"
526
527 FcChar8 *
528 FcNameUnparse (FcPattern *pat)
529 {
530     return FcNameUnparseEscaped (pat, FcTrue);
531 }
532
533 FcChar8 *
534 FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
535 {
536     FcStrBuf                buf;
537     FcChar8                 buf_static[8192];
538     int                     i;
539     FcPatternElt            *e;
540
541     FcStrBufInit (&buf, buf_static, sizeof (buf_static));
542     e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
543     if (e)
544     {
545         if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
546             goto bail0;
547     }
548     e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
549     if (e)
550     {
551         if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
552             goto bail0;
553         if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
554             goto bail0;
555     }
556     for (i = 0; i < NUM_OBJECT_TYPES; i++)
557     {
558         FcObject id = i + 1;
559         const FcObjectType          *o;
560         o = &FcObjects[i];
561         if (!strcmp (o->object, FC_FAMILY) ||
562             !strcmp (o->object, FC_SIZE))
563             continue;
564     
565         e = FcPatternObjectFindElt (pat, id);
566         if (e)
567         {
568             if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
569                 goto bail0;
570             if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
571                 goto bail0;
572             if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
573                 goto bail0;
574             if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
575                                          (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
576                 goto bail0;
577         }
578     }
579     return FcStrBufDone (&buf);
580 bail0:
581     FcStrBufDestroy (&buf);
582     return 0;
583 }
584 #define __fcname__
585 #include "fcaliastail.h"
586 #undef __fcname__