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