Move existing fonts.conf to fonts.conf.bak
[platform/upstream/fontconfig.git] / src / fcname.c
1 /*
2  * $RCSId: xc/lib/fontconfig/src/fcname.c,v 1.15 2002/09/26 00:17:28 keithp Exp $
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 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 <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include "fcint.h"
30
31 static const FcObjectType _FcBaseObjectTypes[] = {
32     { FC_FAMILY,        FcTypeString, },
33     { FC_FAMILYLANG,    FcTypeString, },
34     { FC_STYLE,         FcTypeString, },
35     { FC_STYLELANG,     FcTypeString, },
36     { FC_FULLNAME,      FcTypeString, },
37     { FC_FULLNAMELANG,  FcTypeString, },
38     { FC_SLANT,         FcTypeInteger, },
39     { FC_WEIGHT,        FcTypeInteger, },
40     { FC_WIDTH,         FcTypeInteger, },
41     { FC_SIZE,          FcTypeDouble, },
42     { FC_ASPECT,        FcTypeDouble, },
43     { FC_PIXEL_SIZE,    FcTypeDouble, },
44     { FC_SPACING,       FcTypeInteger, },
45     { FC_FOUNDRY,       FcTypeString, },
46 /*    { FC_CORE,                FcTypeBool, }, */
47     { FC_ANTIALIAS,     FcTypeBool, },
48     { FC_HINT_STYLE,    FcTypeInteger, },
49     { FC_HINTING,       FcTypeBool, },
50     { FC_VERTICAL_LAYOUT,   FcTypeBool, },
51     { FC_AUTOHINT,      FcTypeBool, },
52     { FC_GLOBAL_ADVANCE,    FcTypeBool, },
53 /*    { FC_XLFD,                FcTypeString, }, */
54     { FC_FILE,          FcTypeString, },
55     { FC_INDEX,         FcTypeInteger, },
56     { FC_RASTERIZER,    FcTypeString, },
57     { FC_OUTLINE,       FcTypeBool, },
58     { FC_SCALABLE,      FcTypeBool, },
59     { FC_DPI,           FcTypeDouble },
60     { FC_RGBA,          FcTypeInteger, },
61     { FC_SCALE,         FcTypeDouble, },
62 /*    { FC_RENDER,      FcTypeBool, },*/
63     { FC_MINSPACE,      FcTypeBool, },
64     { FC_CHAR_WIDTH,    FcTypeInteger },
65     { FC_CHAR_HEIGHT,   FcTypeInteger },
66     { FC_MATRIX,        FcTypeMatrix },
67     { FC_CHARSET,       FcTypeCharSet },
68     { FC_LANG,          FcTypeLangSet },
69     { FC_FONTVERSION,   FcTypeInteger },
70 };
71
72 #define NUM_OBJECT_TYPES    (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
73
74 typedef struct _FcObjectTypeList    FcObjectTypeList;
75
76 struct _FcObjectTypeList {
77     const FcObjectTypeList  *next;
78     const FcObjectType      *types;
79     int                     ntypes;
80 };
81
82 static const FcObjectTypeList _FcBaseObjectTypesList = {
83     0,
84     _FcBaseObjectTypes,
85     NUM_OBJECT_TYPES
86 };
87
88 static const FcObjectTypeList   *_FcObjectTypes = &_FcBaseObjectTypesList;
89
90 FcBool
91 FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
92 {
93     FcObjectTypeList    *l;
94
95     l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
96     if (!l)
97         return FcFalse;
98     FcMemAlloc (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
99     l->types = types;
100     l->ntypes = ntypes;
101     l->next = _FcObjectTypes;
102     _FcObjectTypes = l;
103     return FcTrue;
104 }
105
106 FcBool
107 FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
108 {
109     const FcObjectTypeList      *l, **prev;
110
111     for (prev = &_FcObjectTypes; 
112          (l = *prev); 
113          prev = (const FcObjectTypeList **) &(l->next))
114     {
115         if (l->types == types && l->ntypes == ntypes)
116         {
117             *prev = l->next;
118             FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
119             free ((void *) l);
120             return FcTrue;
121         }
122     }
123     return FcFalse;
124 }
125
126 const FcObjectType *
127 FcNameGetObjectType (const char *object)
128 {
129     int                     i;
130     const FcObjectTypeList  *l;
131     const FcObjectType      *t;
132     
133     for (l = _FcObjectTypes; l; l = l->next)
134     {
135         for (i = 0; i < l->ntypes; i++)
136         {
137             t = &l->types[i];
138             if (!strcmp (object, t->object))
139                 return t;
140         }
141     }
142     return 0;
143 }
144
145 static const FcConstant _FcBaseConstants[] = {
146     { (FcChar8 *) "thin",           "weight",   FC_WEIGHT_THIN, },
147     { (FcChar8 *) "extralight",     "weight",   FC_WEIGHT_EXTRALIGHT, },
148     { (FcChar8 *) "ultralight",     "weight",   FC_WEIGHT_EXTRALIGHT, },
149     { (FcChar8 *) "light",          "weight",   FC_WEIGHT_LIGHT, },
150     { (FcChar8 *) "book",           "weight",   FC_WEIGHT_BOOK, },
151     { (FcChar8 *) "regular",        "weight",   FC_WEIGHT_REGULAR, },
152     { (FcChar8 *) "medium",         "weight",   FC_WEIGHT_MEDIUM, },
153     { (FcChar8 *) "demibold",       "weight",   FC_WEIGHT_DEMIBOLD, },
154     { (FcChar8 *) "semibold",       "weight",   FC_WEIGHT_DEMIBOLD, },
155     { (FcChar8 *) "bold",           "weight",   FC_WEIGHT_BOLD, },
156     { (FcChar8 *) "extrabold",      "weight",   FC_WEIGHT_EXTRABOLD, },
157     { (FcChar8 *) "ultrabold",      "weight",   FC_WEIGHT_EXTRABOLD, },
158     { (FcChar8 *) "black",          "weight",   FC_WEIGHT_BLACK, },
159
160     { (FcChar8 *) "roman",          "slant",    FC_SLANT_ROMAN, },
161     { (FcChar8 *) "italic",         "slant",    FC_SLANT_ITALIC, },
162     { (FcChar8 *) "oblique",        "slant",    FC_SLANT_OBLIQUE, },
163
164     { (FcChar8 *) "ultracondensed", "width",    FC_WIDTH_ULTRACONDENSED },
165     { (FcChar8 *) "extracondensed", "width",    FC_WIDTH_EXTRACONDENSED },
166     { (FcChar8 *) "condensed",      "width",    FC_WIDTH_CONDENSED },
167     { (FcChar8 *) "semicondensed", "width",     FC_WIDTH_SEMICONDENSED },
168     { (FcChar8 *) "normal",         "width",    FC_WIDTH_NORMAL },
169     { (FcChar8 *) "semiexpanded",   "width",    FC_WIDTH_SEMIEXPANDED },
170     { (FcChar8 *) "expanded",       "width",    FC_WIDTH_EXPANDED },
171     { (FcChar8 *) "extraexpanded",  "width",    FC_WIDTH_EXTRAEXPANDED },
172     { (FcChar8 *) "ultraexpanded",  "width",    FC_WIDTH_ULTRAEXPANDED },
173     
174     { (FcChar8 *) "proportional",   "spacing",  FC_PROPORTIONAL, },
175     { (FcChar8 *) "dual",           "spacing",  FC_DUAL, },
176     { (FcChar8 *) "mono",           "spacing",  FC_MONO, },
177     { (FcChar8 *) "charcell",       "spacing",  FC_CHARCELL, },
178
179     { (FcChar8 *) "unknown",        "rgba",         FC_RGBA_UNKNOWN },
180     { (FcChar8 *) "rgb",            "rgba",         FC_RGBA_RGB, },
181     { (FcChar8 *) "bgr",            "rgba",         FC_RGBA_BGR, },
182     { (FcChar8 *) "vrgb",           "rgba",         FC_RGBA_VRGB },
183     { (FcChar8 *) "vbgr",           "rgba",         FC_RGBA_VBGR },
184     { (FcChar8 *) "none",           "rgba",         FC_RGBA_NONE },
185
186     { (FcChar8 *) "hintnone",       "hintstyle",   FC_HINT_NONE },
187     { (FcChar8 *) "hintslight",     "hintstyle",   FC_HINT_SLIGHT },
188     { (FcChar8 *) "hintmedium",     "hintstyle",   FC_HINT_MEDIUM },
189     { (FcChar8 *) "hintfull",       "hintstyle",   FC_HINT_FULL },
190 };
191
192 #define NUM_FC_CONSTANTS   (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
193
194 typedef struct _FcConstantList FcConstantList;
195
196 struct _FcConstantList {
197     const FcConstantList    *next;
198     const FcConstant        *consts;
199     int                     nconsts;
200 };
201
202 static const FcConstantList _FcBaseConstantList = {
203     0,
204     _FcBaseConstants,
205     NUM_FC_CONSTANTS
206 };
207
208 static const FcConstantList     *_FcConstants = &_FcBaseConstantList;
209
210 FcBool
211 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
212 {
213     FcConstantList      *l;
214
215     l = (FcConstantList *) malloc (sizeof (FcConstantList));
216     if (!l)
217         return FcFalse;
218     FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList));
219     l->consts = consts;
220     l->nconsts = nconsts;
221     l->next = _FcConstants;
222     _FcConstants = l;
223     return FcTrue;
224 }
225
226 FcBool
227 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
228 {
229     const FcConstantList        *l, **prev;
230
231     for (prev = &_FcConstants; 
232          (l = *prev); 
233          prev = (const FcConstantList **) &(l->next))
234     {
235         if (l->consts == consts && l->nconsts == nconsts)
236         {
237             *prev = l->next;
238             FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList));
239             free ((void *) l);
240             return FcTrue;
241         }
242     }
243     return FcFalse;
244 }
245
246 const FcConstant *
247 FcNameGetConstant (FcChar8 *string)
248 {
249     const FcConstantList    *l;
250     int                     i;
251
252     for (l = _FcConstants; l; l = l->next)
253     {
254         for (i = 0; i < l->nconsts; i++)
255             if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
256                 return &l->consts[i];
257     }
258     return 0;
259 }
260
261 FcBool
262 FcNameConstant (FcChar8 *string, int *result)
263 {
264     const FcConstant    *c;
265
266     if ((c = FcNameGetConstant(string)))
267     {
268         *result = c->value;
269         return FcTrue;
270     }
271     return FcFalse;
272 }
273
274 FcBool
275 FcNameBool (FcChar8 *v, FcBool *result)
276 {
277     char    c0, c1;
278
279     c0 = *v;
280     c0 = FcToLower (c0);
281     if (c0 == 't' || c0 == 'y' || c0 == '1')
282     {
283         *result = FcTrue;
284         return FcTrue;
285     }
286     if (c0 == 'f' || c0 == 'n' || c0 == '0')
287     {
288         *result = FcFalse;
289         return FcTrue;
290     }
291     if (c0 == 'o')
292     {
293         c1 = v[1];
294         c1 = FcToLower (c1);
295         if (c1 == 'n')
296         {
297             *result = FcTrue;
298             return FcTrue;
299         }
300         if (c1 == 'f')
301         {
302             *result = FcFalse;
303             return FcTrue;
304         }
305     }
306     return FcFalse;
307 }
308
309 static FcValue
310 FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
311 {
312     FcValue     v;
313
314     v.type = type;
315     switch (v.type) {
316     case FcTypeInteger:
317         if (!FcNameConstant (string, &v.u.i))
318             v.u.i = atoi ((char *) string);
319         break;
320     case FcTypeString:
321         v.u.s = string;
322         break;
323     case FcTypeBool:
324         if (!FcNameBool (string, &v.u.b))
325             v.u.b = FcFalse;
326         break;
327     case FcTypeDouble:
328         v.u.d = strtod ((char *) string, 0);
329         break;
330     case FcTypeMatrix:
331         v.u.m = m;
332         sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
333         break;
334     case FcTypeCharSet:
335         v.u.c = FcNameParseCharSet (string);
336         break;
337     case FcTypeLangSet:
338         v.u.l = FcNameParseLangSet (string);
339         break;
340     default:
341         break;
342     }
343     return v;
344 }
345
346 static const FcChar8 *
347 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
348 {
349     FcChar8    c;
350     
351     while ((c = *cur))
352     {
353         if (c == '\\')
354         {
355             ++cur;
356             if (!(c = *cur))
357                 break;
358         }
359         else if (strchr (delim, c))
360             break;
361         ++cur;
362         *save++ = c;
363     }
364     *save = 0;
365     *last = *cur;
366     if (*cur)
367         cur++;
368     return cur;
369 }
370
371 FcPattern *
372 FcNameParse (const FcChar8 *name)
373 {
374     FcChar8             *save;
375     FcPattern           *pat;
376     double              d;
377     FcChar8             *e;
378     FcChar8             delim;
379     FcValue             v;
380     FcMatrix            m;
381     const FcObjectType  *t;
382     const FcConstant    *c;
383
384     /* freed below */
385     save = malloc (strlen ((char *) name) + 1);
386     if (!save)
387         goto bail0;
388     pat = FcPatternCreate ();
389     if (!pat)
390         goto bail1;
391
392     for (;;)
393     {
394         name = FcNameFindNext (name, "-,:", save, &delim);
395         if (save[0])
396         {
397             if (!FcPatternAddString (pat, FC_FAMILY, save))
398                 goto bail2;
399         }
400         if (delim != ',')
401             break;
402     }
403     if (delim == '-')
404     {
405         for (;;)
406         {
407             name = FcNameFindNext (name, "-,:", save, &delim);
408             d = strtod ((char *) save, (char **) &e);
409             if (e != save)
410             {
411                 if (!FcPatternAddDouble (pat, FC_SIZE, d))
412                     goto bail2;
413             }
414             if (delim != ',')
415                 break;
416         }
417     }
418     while (delim == ':')
419     {
420         name = FcNameFindNext (name, "=_:", save, &delim);
421         if (save[0])
422         {
423             if (delim == '=' || delim == '_')
424             {
425                 t = FcNameGetObjectType ((char *) save);
426                 for (;;)
427                 {
428                     name = FcNameFindNext (name, ":,", save, &delim);
429                     if (t)
430                     {
431                         v = FcNameConvert (t->type, save, &m);
432                         if (!FcPatternAdd (pat, t->object, v, FcTrue))
433                         {
434                             switch (v.type) {
435                             case FcTypeCharSet:
436                                 FcCharSetDestroy ((FcCharSet *) v.u.c);
437                                 break;
438                             case FcTypeLangSet:
439                                 FcLangSetDestroy ((FcLangSet *) v.u.l);
440                                 break;
441                             default:
442                                 break;
443                             }
444                             goto bail2;
445                         }
446                         switch (v.type) {
447                         case FcTypeCharSet:
448                             FcCharSetDestroy ((FcCharSet *) v.u.c);
449                             break;
450                         case FcTypeLangSet:
451                             FcLangSetDestroy ((FcLangSet *) v.u.l);
452                             break;
453                         default:
454                             break;
455                         }
456                     }
457                     if (delim != ',')
458                         break;
459                 }
460             }
461             else
462             {
463                 if ((c = FcNameGetConstant (save)))
464                 {
465                     if (!FcPatternAddInteger (pat, c->object, c->value))
466                         goto bail2;
467                 }
468             }
469         }
470     }
471
472     free (save);
473     return pat;
474
475 bail2:
476     FcPatternDestroy (pat);
477 bail1:
478     free (save);
479 bail0:
480     return 0;
481 }
482 static FcBool
483 FcNameUnparseString (FcStrBuf       *buf, 
484                      const FcChar8  *string,
485                      const FcChar8  *escape)
486 {
487     FcChar8 c;
488     while ((c = *string++))
489     {
490         if (escape && strchr ((char *) escape, (char) c))
491         {
492             if (!FcStrBufChar (buf, escape[0]))
493                 return FcFalse;
494         }
495         if (!FcStrBufChar (buf, c))
496             return FcFalse;
497     }
498     return FcTrue;
499 }
500
501 static FcBool
502 FcNameUnparseValue (FcStrBuf    *buf,
503                     FcValue     v,
504                     FcChar8     *escape)
505 {
506     FcChar8     temp[1024];
507     
508     switch (v.type) {
509     case FcTypeVoid:
510         return FcTrue;
511     case FcTypeInteger:
512         sprintf ((char *) temp, "%d", v.u.i);
513         return FcNameUnparseString (buf, temp, 0);
514     case FcTypeDouble:
515         sprintf ((char *) temp, "%g", v.u.d);
516         return FcNameUnparseString (buf, temp, 0);
517     case FcTypeString:
518         return FcNameUnparseString (buf, v.u.s, escape);
519     case FcTypeBool:
520         return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
521     case FcTypeMatrix:
522         sprintf ((char *) temp, "%g %g %g %g", 
523                  v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
524         return FcNameUnparseString (buf, temp, 0);
525     case FcTypeCharSet:
526         return FcNameUnparseCharSet (buf, v.u.c);
527     case FcTypeLangSet:
528         return FcNameUnparseLangSet (buf, v.u.l);
529     case FcTypeFTFace:
530         return FcTrue;
531     }
532     return FcFalse;
533 }
534
535 static FcBool
536 FcNameUnparseValueList (FcStrBuf        *buf,
537                         FcValueList     *v,
538                         FcChar8         *escape)
539 {
540     while (v)
541     {
542         if (!FcNameUnparseValue (buf, v->value, escape))
543             return FcFalse;
544         if ((v = v->next))
545             if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
546                 return FcFalse;
547     }
548     return FcTrue;
549 }
550
551 #define FC_ESCAPE_FIXED    "\\-:,"
552 #define FC_ESCAPE_VARIABLE "\\=_:,"
553
554 FcChar8 *
555 FcNameUnparse (FcPattern *pat)
556 {
557     FcStrBuf                buf;
558     FcChar8                 buf_static[8192];
559     int                     i;
560     FcPatternElt            *e;
561     const FcObjectTypeList  *l;
562     const FcObjectType      *o;
563
564     FcStrBufInit (&buf, buf_static, sizeof (buf_static));
565     e = FcPatternFindElt (pat, FC_FAMILY);
566     if (e)
567     {
568         if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
569             goto bail0;
570     }
571     e = FcPatternFindElt (pat, FC_SIZE);
572     if (e)
573     {
574         if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
575             goto bail0;
576         if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
577             goto bail0;
578     }
579     for (l = _FcObjectTypes; l; l = l->next)
580     {
581         for (i = 0; i < l->ntypes; i++)
582         {
583             o = &l->types[i];
584             if (!strcmp (o->object, FC_FAMILY) || 
585                 !strcmp (o->object, FC_SIZE) ||
586                 !strcmp (o->object, FC_FILE))
587                 continue;
588             
589             e = FcPatternFindElt (pat, o->object);
590             if (e)
591             {
592                 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
593                     goto bail0;
594                 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, (FcChar8 *) FC_ESCAPE_VARIABLE))
595                     goto bail0;
596                 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
597                     goto bail0;
598                 if (!FcNameUnparseValueList (&buf, e->values, 
599                                              (FcChar8 *) FC_ESCAPE_VARIABLE))
600                     goto bail0;
601             }
602         }
603     }
604     return FcStrBufDone (&buf);
605 bail0:
606     FcStrBufDestroy (&buf);
607     return 0;
608 }