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