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