]> git.wh0rd.org - fontconfig.git/blob - src/fcname.c
Move existing fonts.conf to fonts.conf.bak
[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 }