]> git.wh0rd.org - fontconfig.git/blob - src/fcname.c
Add FC_RGBA_UNKNOWN
[fontconfig.git] / src / fcname.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcname.c,v 1.15 2002/09/26 00:17:28 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 *) "unknown", "rgba", FC_RGBA_UNKNOWN },
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 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE },
160 };
161
162 #define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
163
164 typedef struct _FcConstantList FcConstantList;
165
166 struct _FcConstantList {
167 const FcConstantList *next;
168 const FcConstant *consts;
169 int nconsts;
170 };
171
172 static const FcConstantList _FcBaseConstantList = {
173 0,
174 _FcBaseConstants,
175 NUM_FC_CONSTANTS
176 };
177
178 static const FcConstantList *_FcConstants = &_FcBaseConstantList;
179
180 FcBool
181 FcNameRegisterConstants (const FcConstant *consts, int nconsts)
182 {
183 FcConstantList *l;
184
185 l = (FcConstantList *) malloc (sizeof (FcConstantList));
186 if (!l)
187 return FcFalse;
188 FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList));
189 l->consts = consts;
190 l->nconsts = nconsts;
191 l->next = _FcConstants;
192 _FcConstants = l;
193 return FcTrue;
194 }
195
196 FcBool
197 FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
198 {
199 const FcConstantList *l, **prev;
200
201 for (prev = &_FcConstants;
202 (l = *prev);
203 prev = (const FcConstantList **) &(l->next))
204 {
205 if (l->consts == consts && l->nconsts == nconsts)
206 {
207 *prev = l->next;
208 FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList));
209 free ((void *) l);
210 return FcTrue;
211 }
212 }
213 return FcFalse;
214 }
215
216 const FcConstant *
217 FcNameGetConstant (FcChar8 *string)
218 {
219 const FcConstantList *l;
220 int i;
221
222 for (l = _FcConstants; l; l = l->next)
223 {
224 for (i = 0; i < l->nconsts; i++)
225 if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
226 return &l->consts[i];
227 }
228 return 0;
229 }
230
231 FcBool
232 FcNameConstant (FcChar8 *string, int *result)
233 {
234 const FcConstant *c;
235
236 if ((c = FcNameGetConstant(string)))
237 {
238 *result = c->value;
239 return FcTrue;
240 }
241 return FcFalse;
242 }
243
244 FcBool
245 FcNameBool (FcChar8 *v, FcBool *result)
246 {
247 char c0, c1;
248
249 c0 = *v;
250 if (isupper (c0))
251 c0 = tolower (c0);
252 if (c0 == 't' || c0 == 'y' || c0 == '1')
253 {
254 *result = FcTrue;
255 return FcTrue;
256 }
257 if (c0 == 'f' || c0 == 'n' || c0 == '0')
258 {
259 *result = FcFalse;
260 return FcTrue;
261 }
262 if (c0 == 'o')
263 {
264 c1 = v[1];
265 if (isupper (c1))
266 c1 = tolower (c1);
267 if (c1 == 'n')
268 {
269 *result = FcTrue;
270 return FcTrue;
271 }
272 if (c1 == 'f')
273 {
274 *result = FcFalse;
275 return FcTrue;
276 }
277 }
278 return FcFalse;
279 }
280
281 static FcValue
282 FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
283 {
284 FcValue v;
285
286 v.type = type;
287 switch (v.type) {
288 case FcTypeInteger:
289 if (!FcNameConstant (string, &v.u.i))
290 v.u.i = atoi ((char *) string);
291 break;
292 case FcTypeString:
293 v.u.s = string;
294 break;
295 case FcTypeBool:
296 if (!FcNameBool (string, &v.u.b))
297 v.u.b = FcFalse;
298 break;
299 case FcTypeDouble:
300 v.u.d = strtod ((char *) string, 0);
301 break;
302 case FcTypeMatrix:
303 v.u.m = m;
304 sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
305 break;
306 case FcTypeCharSet:
307 v.u.c = FcNameParseCharSet (string);
308 break;
309 case FcTypeLangSet:
310 v.u.l = FcNameParseLangSet (string);
311 break;
312 default:
313 break;
314 }
315 return v;
316 }
317
318 static const FcChar8 *
319 FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
320 {
321 FcChar8 c;
322
323 while ((c = *cur))
324 {
325 if (c == '\\')
326 {
327 ++cur;
328 if (!(c = *cur))
329 break;
330 }
331 else if (strchr (delim, c))
332 break;
333 ++cur;
334 *save++ = c;
335 }
336 *save = 0;
337 *last = *cur;
338 if (*cur)
339 cur++;
340 return cur;
341 }
342
343 FcPattern *
344 FcNameParse (const FcChar8 *name)
345 {
346 FcChar8 *save;
347 FcPattern *pat;
348 double d;
349 FcChar8 *e;
350 FcChar8 delim;
351 FcValue v;
352 FcMatrix m;
353 const FcObjectType *t;
354 const FcConstant *c;
355
356 /* freed below */
357 save = malloc (strlen ((char *) name) + 1);
358 if (!save)
359 goto bail0;
360 pat = FcPatternCreate ();
361 if (!pat)
362 goto bail1;
363
364 for (;;)
365 {
366 name = FcNameFindNext (name, "-,:", save, &delim);
367 if (save[0])
368 {
369 if (!FcPatternAddString (pat, FC_FAMILY, save))
370 goto bail2;
371 }
372 if (delim != ',')
373 break;
374 }
375 if (delim == '-')
376 {
377 for (;;)
378 {
379 name = FcNameFindNext (name, "-,:", save, &delim);
380 d = strtod ((char *) save, (char **) &e);
381 if (e != save)
382 {
383 if (!FcPatternAddDouble (pat, FC_SIZE, d))
384 goto bail2;
385 }
386 if (delim != ',')
387 break;
388 }
389 }
390 while (delim == ':')
391 {
392 name = FcNameFindNext (name, "=_:", save, &delim);
393 if (save[0])
394 {
395 if (delim == '=' || delim == '_')
396 {
397 t = FcNameGetObjectType ((char *) save);
398 for (;;)
399 {
400 name = FcNameFindNext (name, ":,", save, &delim);
401 if (t)
402 {
403 v = FcNameConvert (t->type, save, &m);
404 if (!FcPatternAdd (pat, t->object, v, FcTrue))
405 {
406 switch (v.type) {
407 case FcTypeCharSet:
408 FcCharSetDestroy ((FcCharSet *) v.u.c);
409 break;
410 case FcTypeLangSet:
411 FcLangSetDestroy ((FcLangSet *) v.u.l);
412 break;
413 default:
414 break;
415 }
416 goto bail2;
417 }
418 switch (v.type) {
419 case FcTypeCharSet:
420 FcCharSetDestroy ((FcCharSet *) v.u.c);
421 break;
422 case FcTypeLangSet:
423 FcLangSetDestroy ((FcLangSet *) v.u.l);
424 break;
425 default:
426 break;
427 }
428 }
429 if (delim != ',')
430 break;
431 }
432 }
433 else
434 {
435 if ((c = FcNameGetConstant (save)))
436 {
437 if (!FcPatternAddInteger (pat, c->object, c->value))
438 goto bail2;
439 }
440 }
441 }
442 }
443
444 free (save);
445 return pat;
446
447 bail2:
448 FcPatternDestroy (pat);
449 bail1:
450 free (save);
451 bail0:
452 return 0;
453 }
454 static FcBool
455 FcNameUnparseString (FcStrBuf *buf,
456 const FcChar8 *string,
457 const FcChar8 *escape)
458 {
459 FcChar8 c;
460 while ((c = *string++))
461 {
462 if (escape && strchr ((char *) escape, (char) c))
463 {
464 if (!FcStrBufChar (buf, escape[0]))
465 return FcFalse;
466 }
467 if (!FcStrBufChar (buf, c))
468 return FcFalse;
469 }
470 return FcTrue;
471 }
472
473 static FcBool
474 FcNameUnparseValue (FcStrBuf *buf,
475 FcValue v,
476 FcChar8 *escape)
477 {
478 FcChar8 temp[1024];
479
480 switch (v.type) {
481 case FcTypeVoid:
482 return FcTrue;
483 case FcTypeInteger:
484 sprintf ((char *) temp, "%d", v.u.i);
485 return FcNameUnparseString (buf, temp, 0);
486 case FcTypeDouble:
487 sprintf ((char *) temp, "%g", v.u.d);
488 return FcNameUnparseString (buf, temp, 0);
489 case FcTypeString:
490 return FcNameUnparseString (buf, v.u.s, escape);
491 case FcTypeBool:
492 return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
493 case FcTypeMatrix:
494 sprintf ((char *) temp, "%g %g %g %g",
495 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
496 return FcNameUnparseString (buf, temp, 0);
497 case FcTypeCharSet:
498 return FcNameUnparseCharSet (buf, v.u.c);
499 case FcTypeLangSet:
500 return FcNameUnparseLangSet (buf, v.u.l);
501 case FcTypeFTFace:
502 return FcTrue;
503 }
504 return FcFalse;
505 }
506
507 static FcBool
508 FcNameUnparseValueList (FcStrBuf *buf,
509 FcValueList *v,
510 FcChar8 *escape)
511 {
512 while (v)
513 {
514 if (!FcNameUnparseValue (buf, v->value, escape))
515 return FcFalse;
516 if ((v = v->next))
517 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
518 return FcFalse;
519 }
520 return FcTrue;
521 }
522
523 #define FC_ESCAPE_FIXED "\\-:,"
524 #define FC_ESCAPE_VARIABLE "\\=_:,"
525
526 FcChar8 *
527 FcNameUnparse (FcPattern *pat)
528 {
529 FcStrBuf buf;
530 FcChar8 buf_static[8192];
531 int i;
532 FcPatternElt *e;
533 const FcObjectTypeList *l;
534 const FcObjectType *o;
535
536 FcStrBufInit (&buf, buf_static, sizeof (buf_static));
537 e = FcPatternFindElt (pat, FC_FAMILY);
538 if (e)
539 {
540 if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
541 goto bail0;
542 }
543 e = FcPatternFindElt (pat, FC_SIZE);
544 if (e)
545 {
546 if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
547 goto bail0;
548 if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
549 goto bail0;
550 }
551 for (l = _FcObjectTypes; l; l = l->next)
552 {
553 for (i = 0; i < l->ntypes; i++)
554 {
555 o = &l->types[i];
556 if (!strcmp (o->object, FC_FAMILY) ||
557 !strcmp (o->object, FC_SIZE) ||
558 !strcmp (o->object, FC_FILE))
559 continue;
560
561 e = FcPatternFindElt (pat, o->object);
562 if (e)
563 {
564 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
565 goto bail0;
566 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, (FcChar8 *) FC_ESCAPE_VARIABLE))
567 goto bail0;
568 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
569 goto bail0;
570 if (!FcNameUnparseValueList (&buf, e->values,
571 (FcChar8 *) FC_ESCAPE_VARIABLE))
572 goto bail0;
573 }
574 }
575 }
576 return FcStrBufDone (&buf);
577 bail0:
578 FcStrBufDestroy (&buf);
579 return 0;
580 }