]> git.wh0rd.org - fontconfig.git/blame - src/fcname.c
FcObjectValidType: tweak -1 checking
[fontconfig.git] / src / fcname.c
CommitLineData
24330d27 1/*
317b8492 2 * fontconfig/src/fcname.c
24330d27 3 *
46b51147 4 * Copyright © 2000 Keith Packard
24330d27
KP
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
5aaf466d 10 * documentation, and that the name of the author(s) not be used in
24330d27 11 * advertising or publicity pertaining to distribution of the software without
5aaf466d 12 * specific, written prior permission. The authors make no
24330d27
KP
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
3074a73b 16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24330d27 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
3074a73b 18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24330d27
KP
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
f045376c 25#include "fcint.h"
24330d27
KP
26#include <ctype.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
24330d27 30
594dcef0 31/*
09f9f6f6 32 * Please do not change this list, it is used to initialize the object
594dcef0 33 * list in this order to match the FC_foo_OBJECT constants. Those
09f9f6f6
KP
34 * constants are written into cache files.
35 */
36
24330d27 37static const FcObjectType _FcBaseObjectTypes[] = {
09f9f6f6 38 { FC_FAMILY, FcTypeString, }, /* 1 */
4f27c1c0 39 { FC_FAMILYLANG, FcTypeString, },
24330d27 40 { FC_STYLE, FcTypeString, },
4f27c1c0
KP
41 { FC_STYLELANG, FcTypeString, },
42 { FC_FULLNAME, FcTypeString, },
43 { FC_FULLNAMELANG, FcTypeString, },
24330d27
KP
44 { FC_SLANT, FcTypeInteger, },
45 { FC_WEIGHT, FcTypeInteger, },
81fa16c3 46 { FC_WIDTH, FcTypeInteger, },
24330d27 47 { FC_SIZE, FcTypeDouble, },
2a41214a 48 { FC_ASPECT, FcTypeDouble, },
24330d27
KP
49 { FC_PIXEL_SIZE, FcTypeDouble, },
50 { FC_SPACING, FcTypeInteger, },
51 { FC_FOUNDRY, FcTypeString, },
24330d27 52 { FC_ANTIALIAS, FcTypeBool, },
f077d662 53 { FC_HINT_STYLE, FcTypeInteger, },
4c003605
KP
54 { FC_HINTING, FcTypeBool, },
55 { FC_VERTICAL_LAYOUT, FcTypeBool, },
56 { FC_AUTOHINT, FcTypeBool, },
57 { FC_GLOBAL_ADVANCE, FcTypeBool, },
24330d27
KP
58 { FC_FILE, FcTypeString, },
59 { FC_INDEX, FcTypeInteger, },
60 { FC_RASTERIZER, FcTypeString, },
61 { FC_OUTLINE, FcTypeBool, },
62 { FC_SCALABLE, FcTypeBool, },
4c003605 63 { FC_DPI, FcTypeDouble },
24330d27
KP
64 { FC_RGBA, FcTypeInteger, },
65 { FC_SCALE, FcTypeDouble, },
24330d27
KP
66 { FC_MINSPACE, FcTypeBool, },
67 { FC_CHAR_WIDTH, FcTypeInteger },
68 { FC_CHAR_HEIGHT, FcTypeInteger },
69 { FC_MATRIX, FcTypeMatrix },
70 { FC_CHARSET, FcTypeCharSet },
d8d73958 71 { FC_LANG, FcTypeLangSet },
a342e87d 72 { FC_FONTVERSION, FcTypeInteger },
dbf68dd5 73 { FC_CAPABILITY, FcTypeString },
537e3d23 74 { FC_FONTFORMAT, FcTypeString },
414f7202 75 { FC_EMBOLDEN, FcTypeBool },
c2c6976d 76 { FC_EMBEDDED_BITMAP, FcTypeBool },
53aec111
SP
77 { FC_DECORATIVE, FcTypeBool },
78 { FC_LCD_FILTER, FcTypeInteger }, /* 41 */
24330d27
KP
79};
80
81#define NUM_OBJECT_TYPES (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
82
83typedef struct _FcObjectTypeList FcObjectTypeList;
84
85struct _FcObjectTypeList {
86 const FcObjectTypeList *next;
87 const FcObjectType *types;
88 int ntypes;
89};
90
91static const FcObjectTypeList _FcBaseObjectTypesList = {
92 0,
93 _FcBaseObjectTypes,
9ab79bdf 94 NUM_OBJECT_TYPES,
24330d27
KP
95};
96
97static const FcObjectTypeList *_FcObjectTypes = &_FcBaseObjectTypesList;
98
09f9f6f6 99#define OBJECT_HASH_SIZE 31
24330d27 100
09f9f6f6
KP
101typedef struct _FcObjectBucket {
102 struct _FcObjectBucket *next;
103 FcChar32 hash;
104 FcObject id;
105} FcObjectBucket;
24330d27 106
09f9f6f6 107static FcObjectBucket *FcObjectBuckets[OBJECT_HASH_SIZE];
24330d27 108
09f9f6f6
KP
109static FcObjectType *FcObjects = (FcObjectType *) _FcBaseObjectTypes;
110static int FcObjectsNumber = NUM_OBJECT_TYPES;
111static int FcObjectsSize = 0;
112static FcBool FcObjectsInited;
113
114static FcObjectType *
115FcObjectInsert (const char *name, FcType type)
116{
117 FcObjectType *o;
118 if (FcObjectsNumber >= FcObjectsSize)
24330d27 119 {
09f9f6f6
KP
120 int newsize = FcObjectsNumber * 2;
121 FcObjectType *newobjects;
122
123 if (FcObjectsSize)
124 newobjects = realloc (FcObjects, newsize * sizeof (FcObjectType));
125 else
24330d27 126 {
09f9f6f6
KP
127 newobjects = malloc (newsize * sizeof (FcObjectType));
128 if (newobjects)
129 memcpy (newobjects, FcObjects,
130 FcObjectsNumber * sizeof (FcObjectType));
24330d27 131 }
09f9f6f6
KP
132 if (!newobjects)
133 return NULL;
134 FcObjects = newobjects;
135 FcObjectsSize = newsize;
24330d27 136 }
09f9f6f6
KP
137 o = &FcObjects[FcObjectsNumber];
138 o->object = name;
139 o->type = type;
140 ++FcObjectsNumber;
141 return o;
24330d27
KP
142}
143
09f9f6f6
KP
144static FcObject
145FcObjectId (FcObjectType *o)
7f37423d 146{
09f9f6f6 147 return o - FcObjects + 1;
7f37423d
PL
148}
149
09f9f6f6
KP
150static FcObjectType *
151FcObjectFindByName (const char *object, FcBool insert)
24330d27 152{
09f9f6f6
KP
153 FcChar32 hash = FcStringHash ((const FcChar8 *) object);
154 FcObjectBucket **p;
155 FcObjectBucket *b;
156 FcObjectType *o;
157
158 if (!FcObjectsInited)
159 FcObjectInit ();
160 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
24330d27 161 {
09f9f6f6
KP
162 o = FcObjects + b->id - 1;
163 if (b->hash == hash && !strcmp (object, (o->object)))
164 return o;
165 }
166 if (!insert)
167 return NULL;
168 /*
169 * Hook it into the hash chain
170 */
171 b = malloc (sizeof(FcObjectBucket));
594dcef0 172 if (!b)
09f9f6f6
KP
173 return NULL;
174 object = (const char *) FcStrCopy ((FcChar8 *) object);
175 if (!object) {
176 free (b);
177 return NULL;
178 }
179 o = FcObjectInsert (object, -1);
180 b->next = NULL;
181 b->hash = hash;
182 b->id = FcObjectId (o);
183 *p = b;
184 return o;
185}
186
187static FcObjectType *
188FcObjectFindById (FcObject object)
189{
190 if (1 <= object && object <= FcObjectsNumber)
191 return FcObjects + object - 1;
192 return NULL;
193}
c6103dfb 194
09f9f6f6
KP
195static FcBool
196FcObjectHashInsert (const FcObjectType *object, FcBool copy)
197{
198 FcChar32 hash = FcStringHash ((const FcChar8 *) object->object);
199 FcObjectBucket **p;
200 FcObjectBucket *b;
201 FcObjectType *o;
202
203 if (!FcObjectsInited)
204 FcObjectInit ();
205 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
206 {
207 o = FcObjects + b->id - 1;
208 if (b->hash == hash && !strcmp (object->object, o->object))
209 return FcFalse;
210 }
211 /*
212 * Hook it into the hash chain
213 */
214 b = malloc (sizeof(FcObjectBucket));
594dcef0 215 if (!b)
09f9f6f6
KP
216 return FcFalse;
217 if (copy)
218 {
219 o = FcObjectInsert (object->object, object->type);
220 if (!o)
24330d27 221 {
09f9f6f6
KP
222 free (b);
223 return FcFalse;
24330d27
KP
224 }
225 }
09f9f6f6
KP
226 else
227 o = (FcObjectType *) object;
228 b->next = NULL;
229 b->hash = hash;
230 b->id = FcObjectId (o);
231 *p = b;
232 return FcTrue;
24330d27
KP
233}
234
09f9f6f6
KP
235static void
236FcObjectHashRemove (const FcObjectType *object, FcBool cleanobj)
4262e0b3 237{
09f9f6f6
KP
238 FcChar32 hash = FcStringHash ((const FcChar8 *) object->object);
239 FcObjectBucket **p;
240 FcObjectBucket *b;
241 FcObjectType *o;
242
243 if (!FcObjectsInited)
244 FcObjectInit ();
245 for (p = &FcObjectBuckets[hash%OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
4262e0b3 246 {
09f9f6f6
KP
247 o = FcObjects + b->id - 1;
248 if (b->hash == hash && !strcmp (object->object, o->object))
4262e0b3 249 {
09f9f6f6
KP
250 *p = b->next;
251 free (b);
252 if (cleanobj)
13cdf607 253 {
09f9f6f6
KP
254 /* Clean up object array */
255 o->object = NULL;
256 o->type = -1;
257 while (FcObjects[FcObjectsNumber-1].object == NULL)
258 --FcObjectsNumber;
13cdf607 259 }
09f9f6f6 260 break;
4262e0b3
PL
261 }
262 }
09f9f6f6 263}
4262e0b3 264
09f9f6f6
KP
265FcBool
266FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
267{
268 int i;
13cdf607 269
09f9f6f6
KP
270 for (i = 0; i < ntypes; i++)
271 if (!FcObjectHashInsert (&types[i], FcTrue))
272 return FcFalse;
273 return FcTrue;
274}
13cdf607 275
09f9f6f6
KP
276FcBool
277FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
278{
279 int i;
13cdf607 280
09f9f6f6
KP
281 for (i = 0; i < ntypes; i++)
282 FcObjectHashRemove (&types[i], FcTrue);
283 return FcTrue;
284}
13cdf607 285
09f9f6f6
KP
286const FcObjectType *
287FcNameGetObjectType (const char *object)
288{
289 return FcObjectFindByName (object, FcFalse);
13cdf607 290}
7f37423d 291
7ce19673
KP
292FcBool
293FcObjectValidType (FcObject object, FcType type)
294{
09f9f6f6
KP
295 FcObjectType *t = FcObjectFindById (object);
296
297 if (t) {
298 switch (t->type) {
09f9f6f6
KP
299 case FcTypeDouble:
300 case FcTypeInteger:
301 if (type == FcTypeDouble || type == FcTypeInteger)
302 return FcTrue;
303 break;
551b6b2c
KP
304 case FcTypeLangSet:
305 if (type == FcTypeLangSet || type == FcTypeString)
306 return FcTrue;
307 break;
09f9f6f6 308 default:
789702de 309 if (t->type == -1 || type == t->type)
09f9f6f6
KP
310 return FcTrue;
311 break;
312 }
7ce19673 313 return FcFalse;
09f9f6f6 314 }
7ce19673
KP
315 return FcTrue;
316}
317
318FcObject
319FcObjectFromName (const char * name)
7f37423d 320{
09f9f6f6
KP
321 FcObjectType *o = FcObjectFindByName (name, FcTrue);
322
323 if (o)
324 return FcObjectId (o);
325 return 0;
326}
327
29874098
BE
328FcObjectSet *
329FcObjectGetSet (void)
330{
331 int i;
332 FcObjectSet *os = NULL;
333
334
335 os = FcObjectSetCreate ();
336 for (i = 0; i < FcObjectsNumber; i++)
337 FcObjectSetAdd (os, FcObjects[i].object);
338
339 return os;
340}
341
09f9f6f6
KP
342FcBool
343FcObjectInit (void)
344{
345 int i;
346
347 if (FcObjectsInited)
348 return FcTrue;
349
350 FcObjectsInited = FcTrue;
351 for (i = 0; i < NUM_OBJECT_TYPES; i++)
352 if (!FcObjectHashInsert (&_FcBaseObjectTypes[i], FcFalse))
353 return FcFalse;
354 return FcTrue;
7f37423d
PL
355}
356
357void
09f9f6f6 358FcObjectFini (void)
7f37423d 359{
09f9f6f6
KP
360 int i;
361 FcObjectBucket *b, *next;
7f37423d
PL
362
363 for (i = 0; i < OBJECT_HASH_SIZE; i++)
364 {
365 for (b = FcObjectBuckets[i]; b; b = next)
366 {
367 next = b->next;
7f37423d
PL
368 free (b);
369 }
370 FcObjectBuckets[i] = 0;
371 }
09f9f6f6
KP
372 for (i = 0; i < FcObjectsNumber; i++)
373 if (FcObjects[i].type == -1)
374 free ((void*) FcObjects[i].object);
375 if (FcObjects != _FcBaseObjectTypes)
376 free (FcObjects);
377 FcObjects = (FcObjectType *) _FcBaseObjectTypes;
378 FcObjectsNumber = NUM_OBJECT_TYPES;
379 FcObjectsSize = 0;
380 FcObjectsInited = FcFalse;
7f37423d
PL
381}
382
4262e0b3 383const char *
7ce19673 384FcObjectName (FcObject object)
4262e0b3 385{
09f9f6f6 386 FcObjectType *o = FcObjectFindById (object);
14143250 387
09f9f6f6
KP
388 if (o)
389 return o->object;
390 return NULL;
4262e0b3
PL
391}
392
24330d27 393static const FcConstant _FcBaseConstants[] = {
81fa16c3
KP
394 { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, },
395 { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, },
396 { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, },
ccb3e93b 397 { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, },
1f71c4d8 398 { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, },
81fa16c3 399 { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, },
ccb3e93b
KP
400 { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, },
401 { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, },
81fa16c3 402 { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, },
ccb3e93b 403 { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, },
81fa16c3
KP
404 { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, },
405 { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, },
ccb3e93b 406 { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, },
c2c6976d 407 { (FcChar8 *) "heavy", "weight", FC_WEIGHT_HEAVY, },
ccb3e93b
KP
408
409 { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, },
410 { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, },
411 { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, },
412
81fa16c3
KP
413 { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED },
414 { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED },
415 { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED },
416 { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED },
417 { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL },
418 { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED },
419 { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED },
420 { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED },
421 { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED },
594dcef0 422
ccb3e93b 423 { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, },
a05d257f 424 { (FcChar8 *) "dual", "spacing", FC_DUAL, },
ccb3e93b
KP
425 { (FcChar8 *) "mono", "spacing", FC_MONO, },
426 { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, },
427
1852d490 428 { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN },
ccb3e93b
KP
429 { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, },
430 { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, },
431 { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB },
432 { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR },
1852d490 433 { (FcChar8 *) "none", "rgba", FC_RGBA_NONE },
f077d662
OT
434
435 { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE },
436 { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT },
437 { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM },
438 { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL },
c2c6976d
KP
439
440 { (FcChar8 *) "antialias", "antialias", FcTrue },
441 { (FcChar8 *) "hinting", "hinting", FcTrue },
442 { (FcChar8 *) "verticallayout", "verticallayout", FcTrue },
443 { (FcChar8 *) "autohint", "autohint", FcTrue },
444 { (FcChar8 *) "globaladvance", "globaladvance", FcTrue },
445 { (FcChar8 *) "outline", "outline", FcTrue },
446 { (FcChar8 *) "scalable", "scalable", FcTrue },
447 { (FcChar8 *) "minspace", "minspace", FcTrue },
448 { (FcChar8 *) "embolden", "embolden", FcTrue },
449 { (FcChar8 *) "embeddedbitmap", "embeddedbitmap", FcTrue },
450 { (FcChar8 *) "decorative", "decorative", FcTrue },
53aec111
SP
451 { (FcChar8 *) "lcdnone", "lcdfilter", FC_LCD_NONE },
452 { (FcChar8 *) "lcddefault", "lcdfilter", FC_LCD_DEFAULT },
453 { (FcChar8 *) "lcdlight", "lcdfilter", FC_LCD_LIGHT },
454 { (FcChar8 *) "lcdlegacy", "lcdfilter", FC_LCD_LEGACY },
24330d27
KP
455};
456
457#define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
458
459typedef struct _FcConstantList FcConstantList;
460
461struct _FcConstantList {
462 const FcConstantList *next;
463 const FcConstant *consts;
464 int nconsts;
465};
466
467static const FcConstantList _FcBaseConstantList = {
468 0,
469 _FcBaseConstants,
470 NUM_FC_CONSTANTS
471};
472
473static const FcConstantList *_FcConstants = &_FcBaseConstantList;
474
475FcBool
476FcNameRegisterConstants (const FcConstant *consts, int nconsts)
477{
478 FcConstantList *l;
479
480 l = (FcConstantList *) malloc (sizeof (FcConstantList));
481 if (!l)
482 return FcFalse;
9dac3c59 483 FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList));
24330d27
KP
484 l->consts = consts;
485 l->nconsts = nconsts;
486 l->next = _FcConstants;
487 _FcConstants = l;
488 return FcTrue;
489}
490
491FcBool
492FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
493{
494 const FcConstantList *l, **prev;
495
594dcef0
BE
496 for (prev = &_FcConstants;
497 (l = *prev);
24330d27
KP
498 prev = (const FcConstantList **) &(l->next))
499 {
500 if (l->consts == consts && l->nconsts == nconsts)
501 {
502 *prev = l->next;
9dac3c59 503 FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList));
24330d27
KP
504 free ((void *) l);
505 return FcTrue;
506 }
507 }
508 return FcFalse;
509}
510
511const FcConstant *
4d93d3a0 512FcNameGetConstant (const FcChar8 *string)
24330d27
KP
513{
514 const FcConstantList *l;
515 int i;
94421e40 516
24330d27
KP
517 for (l = _FcConstants; l; l = l->next)
518 {
519 for (i = 0; i < l->nconsts; i++)
520 if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
521 return &l->consts[i];
522 }
523 return 0;
524}
525
526FcBool
4d93d3a0 527FcNameConstant (const FcChar8 *string, int *result)
24330d27
KP
528{
529 const FcConstant *c;
530
531 if ((c = FcNameGetConstant(string)))
532 {
533 *result = c->value;
534 return FcTrue;
535 }
536 return FcFalse;
537}
538
539FcBool
ca60d2b5 540FcNameBool (const FcChar8 *v, FcBool *result)
24330d27
KP
541{
542 char c0, c1;
543
544 c0 = *v;
94421e40 545 c0 = FcToLower (c0);
24330d27
KP
546 if (c0 == 't' || c0 == 'y' || c0 == '1')
547 {
548 *result = FcTrue;
549 return FcTrue;
550 }
551 if (c0 == 'f' || c0 == 'n' || c0 == '0')
552 {
553 *result = FcFalse;
554 return FcTrue;
555 }
556 if (c0 == 'o')
557 {
558 c1 = v[1];
94421e40 559 c1 = FcToLower (c1);
24330d27
KP
560 if (c1 == 'n')
561 {
562 *result = FcTrue;
563 return FcTrue;
564 }
565 if (c1 == 'f')
566 {
567 *result = FcFalse;
568 return FcTrue;
569 }
570 }
571 return FcFalse;
572}
573
574static FcValue
ccb3e93b 575FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
24330d27
KP
576{
577 FcValue v;
578
579 v.type = type;
580 switch (v.type) {
581 case FcTypeInteger:
582 if (!FcNameConstant (string, &v.u.i))
ccb3e93b 583 v.u.i = atoi ((char *) string);
24330d27
KP
584 break;
585 case FcTypeString:
7f37423d 586 v.u.s = FcStrStaticName(string);
04cedae0
KP
587 if (!v.u.s)
588 v.type = FcTypeVoid;
24330d27
KP
589 break;
590 case FcTypeBool:
591 if (!FcNameBool (string, &v.u.b))
592 v.u.b = FcFalse;
593 break;
594 case FcTypeDouble:
ccb3e93b 595 v.u.d = strtod ((char *) string, 0);
24330d27
KP
596 break;
597 case FcTypeMatrix:
4262e0b3 598 v.u.m = m;
ccb3e93b 599 sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
24330d27
KP
600 break;
601 case FcTypeCharSet:
4262e0b3 602 v.u.c = FcNameParseCharSet (string);
04cedae0
KP
603 if (!v.u.c)
604 v.type = FcTypeVoid;
24330d27 605 break;
d8d73958 606 case FcTypeLangSet:
4262e0b3 607 v.u.l = FcNameParseLangSet (string);
04cedae0
KP
608 if (!v.u.l)
609 v.type = FcTypeVoid;
d8d73958 610 break;
24330d27
KP
611 default:
612 break;
613 }
614 return v;
615}
616
ccb3e93b
KP
617static const FcChar8 *
618FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
24330d27 619{
ccb3e93b 620 FcChar8 c;
594dcef0 621
24330d27
KP
622 while ((c = *cur))
623 {
624 if (c == '\\')
625 {
626 ++cur;
627 if (!(c = *cur))
628 break;
629 }
630 else if (strchr (delim, c))
631 break;
632 ++cur;
633 *save++ = c;
634 }
635 *save = 0;
636 *last = *cur;
637 if (*cur)
638 cur++;
639 return cur;
640}
641
642FcPattern *
ccb3e93b 643FcNameParse (const FcChar8 *name)
24330d27 644{
ccb3e93b 645 FcChar8 *save;
24330d27
KP
646 FcPattern *pat;
647 double d;
ccb3e93b
KP
648 FcChar8 *e;
649 FcChar8 delim;
24330d27
KP
650 FcValue v;
651 FcMatrix m;
652 const FcObjectType *t;
653 const FcConstant *c;
654
9dac3c59 655 /* freed below */
ccb3e93b 656 save = malloc (strlen ((char *) name) + 1);
24330d27
KP
657 if (!save)
658 goto bail0;
659 pat = FcPatternCreate ();
660 if (!pat)
661 goto bail1;
662
663 for (;;)
664 {
665 name = FcNameFindNext (name, "-,:", save, &delim);
666 if (save[0])
667 {
668 if (!FcPatternAddString (pat, FC_FAMILY, save))
669 goto bail2;
670 }
671 if (delim != ',')
672 break;
673 }
674 if (delim == '-')
675 {
676 for (;;)
677 {
678 name = FcNameFindNext (name, "-,:", save, &delim);
ccb3e93b 679 d = strtod ((char *) save, (char **) &e);
24330d27
KP
680 if (e != save)
681 {
682 if (!FcPatternAddDouble (pat, FC_SIZE, d))
683 goto bail2;
684 }
685 if (delim != ',')
686 break;
687 }
688 }
689 while (delim == ':')
690 {
691 name = FcNameFindNext (name, "=_:", save, &delim);
692 if (save[0])
693 {
694 if (delim == '=' || delim == '_')
695 {
ccb3e93b 696 t = FcNameGetObjectType ((char *) save);
24330d27
KP
697 for (;;)
698 {
699 name = FcNameFindNext (name, ":,", save, &delim);
c2c6976d 700 if (t)
24330d27
KP
701 {
702 v = FcNameConvert (t->type, save, &m);
703 if (!FcPatternAdd (pat, t->object, v, FcTrue))
704 {
d8d73958
KP
705 switch (v.type) {
706 case FcTypeCharSet:
4262e0b3 707 FcCharSetDestroy ((FcCharSet *) v.u.c);
d8d73958
KP
708 break;
709 case FcTypeLangSet:
4262e0b3 710 FcLangSetDestroy ((FcLangSet *) v.u.l);
d8d73958
KP
711 break;
712 default:
713 break;
714 }
24330d27
KP
715 goto bail2;
716 }
d8d73958
KP
717 switch (v.type) {
718 case FcTypeCharSet:
4262e0b3 719 FcCharSetDestroy ((FcCharSet *) v.u.c);
d8d73958
KP
720 break;
721 case FcTypeLangSet:
4262e0b3 722 FcLangSetDestroy ((FcLangSet *) v.u.l);
d8d73958
KP
723 break;
724 default:
725 break;
726 }
24330d27
KP
727 }
728 if (delim != ',')
729 break;
730 }
731 }
732 else
733 {
734 if ((c = FcNameGetConstant (save)))
735 {
c2c6976d
KP
736 t = FcNameGetObjectType ((char *) c->object);
737 switch (t->type) {
738 case FcTypeInteger:
739 case FcTypeDouble:
740 if (!FcPatternAddInteger (pat, c->object, c->value))
741 goto bail2;
742 break;
743 case FcTypeBool:
744 if (!FcPatternAddBool (pat, c->object, c->value))
745 goto bail2;
746 break;
747 default:
748 break;
749 }
24330d27
KP
750 }
751 }
752 }
753 }
754
755 free (save);
756 return pat;
757
758bail2:
759 FcPatternDestroy (pat);
760bail1:
761 free (save);
762bail0:
763 return 0;
764}
24330d27 765static FcBool
594dcef0 766FcNameUnparseString (FcStrBuf *buf,
24330d27
KP
767 const FcChar8 *string,
768 const FcChar8 *escape)
769{
770 FcChar8 c;
771 while ((c = *string++))
772 {
773 if (escape && strchr ((char *) escape, (char) c))
774 {
c2e7c611 775 if (!FcStrBufChar (buf, escape[0]))
24330d27
KP
776 return FcFalse;
777 }
c2e7c611 778 if (!FcStrBufChar (buf, c))
24330d27
KP
779 return FcFalse;
780 }
781 return FcTrue;
782}
783
9c83a837 784FcBool
c2e7c611 785FcNameUnparseValue (FcStrBuf *buf,
4262e0b3 786 FcValue *v0,
24330d27
KP
787 FcChar8 *escape)
788{
789 FcChar8 temp[1024];
4262e0b3 790 FcValue v = FcValueCanonicalize(v0);
594dcef0 791
24330d27
KP
792 switch (v.type) {
793 case FcTypeVoid:
794 return FcTrue;
795 case FcTypeInteger:
796 sprintf ((char *) temp, "%d", v.u.i);
797 return FcNameUnparseString (buf, temp, 0);
798 case FcTypeDouble:
799 sprintf ((char *) temp, "%g", v.u.d);
800 return FcNameUnparseString (buf, temp, 0);
801 case FcTypeString:
4262e0b3 802 return FcNameUnparseString (buf, v.u.s, escape);
24330d27 803 case FcTypeBool:
ccb3e93b 804 return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
24330d27 805 case FcTypeMatrix:
594dcef0 806 sprintf ((char *) temp, "%g %g %g %g",
4262e0b3 807 v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
24330d27
KP
808 return FcNameUnparseString (buf, temp, 0);
809 case FcTypeCharSet:
4262e0b3 810 return FcNameUnparseCharSet (buf, v.u.c);
d8d73958 811 case FcTypeLangSet:
4262e0b3 812 return FcNameUnparseLangSet (buf, v.u.l);
88c747e2
KP
813 case FcTypeFTFace:
814 return FcTrue;
24330d27
KP
815 }
816 return FcFalse;
817}
818
0c93b91d 819FcBool
c2e7c611 820FcNameUnparseValueList (FcStrBuf *buf,
cd2ec1a9 821 FcValueListPtr v,
ccb3e93b 822 FcChar8 *escape)
24330d27 823{
7ce19673 824 while (v)
24330d27 825 {
7ce19673 826 if (!FcNameUnparseValue (buf, &v->value, escape))
24330d27 827 return FcFalse;
7ce19673 828 if ((v = FcValueListNext(v)) != NULL)
ccb3e93b 829 if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
24330d27
KP
830 return FcFalse;
831 }
832 return FcTrue;
833}
834
835#define FC_ESCAPE_FIXED "\\-:,"
836#define FC_ESCAPE_VARIABLE "\\=_:,"
837
838FcChar8 *
839FcNameUnparse (FcPattern *pat)
2fa3f27e
PL
840{
841 return FcNameUnparseEscaped (pat, FcTrue);
842}
843
844FcChar8 *
845FcNameUnparseEscaped (FcPattern *pat, FcBool escape)
24330d27 846{
c2e7c611 847 FcStrBuf buf;
24330d27
KP
848 FcChar8 buf_static[8192];
849 int i;
850 FcPatternElt *e;
851 const FcObjectTypeList *l;
852 const FcObjectType *o;
853
c2e7c611 854 FcStrBufInit (&buf, buf_static, sizeof (buf_static));
7ce19673 855 e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT);
24330d27
KP
856 if (e)
857 {
7ce19673 858 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
24330d27
KP
859 goto bail0;
860 }
7ce19673 861 e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT);
24330d27
KP
862 if (e)
863 {
ccb3e93b 864 if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
24330d27 865 goto bail0;
7ce19673 866 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0))
24330d27
KP
867 goto bail0;
868 }
869 for (l = _FcObjectTypes; l; l = l->next)
870 {
871 for (i = 0; i < l->ntypes; i++)
872 {
873 o = &l->types[i];
594dcef0 874 if (!strcmp (o->object, FC_FAMILY) ||
e0be405a 875 !strcmp (o->object, FC_SIZE))
24330d27 876 continue;
594dcef0 877
7ce19673 878 e = FcPatternObjectFindElt (pat, FcObjectFromName (o->object));
24330d27
KP
879 if (e)
880 {
ccb3e93b 881 if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
24330d27 882 goto bail0;
2fa3f27e 883 if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
24330d27 884 goto bail0;
ccb3e93b 885 if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
24330d27 886 goto bail0;
594dcef0 887 if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ?
2fa3f27e 888 (FcChar8 *) FC_ESCAPE_VARIABLE : 0))
24330d27
KP
889 goto bail0;
890 }
891 }
892 }
c2e7c611 893 return FcStrBufDone (&buf);
24330d27 894bail0:
c2e7c611 895 FcStrBufDestroy (&buf);
24330d27
KP
896 return 0;
897}
23816bf9
KP
898#define __fcname__
899#include "fcaliastail.h"
900#undef __fcname__