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