1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | #ifdef HAVE_CONFIG_H1 |
42 | #include <config.h> |
43 | #endif |
44 | #include <X11/fonts/fontmisc.h> |
45 | #include <string.h> |
46 | #include <ctype.h> |
47 | #include <math.h> |
48 | |
49 | #ifndef True(-1) |
50 | #define True(-1) (-1) |
51 | #endif /* True */ |
52 | #ifndef False(0) |
53 | #define False(0) (0) |
54 | #endif /* False */ |
55 | |
56 | #include "xttcap.h" |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | typedef struct TagSPropRecValListNodeP |
66 | { |
67 | SPropRecValContainerEntityP containerE; |
68 | struct TagSPropRecValListNodeP *nextNode; |
69 | } SPropRecValListNodeP; |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | static SPropertyRecord const validRecords[] = |
78 | { |
79 | { "FontFile", eRecTypeString }, |
80 | { "FaceNumber", eRecTypeString }, |
81 | { "AutoItalic", eRecTypeDouble }, |
82 | { "DoubleStrike", eRecTypeString }, |
83 | { "FontProperties", eRecTypeBool }, |
84 | { "ForceSpacing", eRecTypeString }, |
85 | { "ScaleBBoxWidth", eRecTypeString }, |
86 | { "ScaleWidth", eRecTypeDouble }, |
87 | { "EncodingOptions", eRecTypeString }, |
88 | { "Hinting", eRecTypeBool }, |
89 | { "VeryLazyMetrics", eRecTypeBool }, |
90 | { "CodeRange", eRecTypeString }, |
91 | { "EmbeddedBitmap", eRecTypeString }, |
92 | { "VeryLazyBitmapWidthScale", eRecTypeDouble }, |
93 | { "ForceConstantSpacingCodeRange", eRecTypeString }, |
94 | { "ForceConstantSpacingMetrics", eRecTypeString }, |
95 | { "Dummy", eRecTypeVoid } |
96 | }; |
97 | static int const |
98 | numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]); |
99 | |
100 | |
101 | static struct { |
102 | char const * capVariable; |
103 | char const * recordName; |
104 | } const correspondRelations[] = { |
105 | { "fn", "FaceNumber" }, |
106 | { "ai", "AutoItalic" }, |
107 | { "ds", "DoubleStrike" }, |
108 | { "fp", "FontProperties" }, |
109 | { "fs", "ForceSpacing" }, |
110 | { "bw", "ScaleBBoxWidth" }, |
111 | { "sw", "ScaleWidth" }, |
112 | { "eo", "EncodingOptions" }, |
113 | { "vl", "VeryLazyMetrics" }, |
114 | { "bs", "VeryLazyBitmapWidthScale" }, |
115 | { "cr", "CodeRange" }, |
116 | { "eb", "EmbeddedBitmap" }, |
117 | { "hi", "Hinting" }, |
118 | { "fc", "ForceConstantSpacingCodeRange" }, |
119 | { "fm", "ForceConstantSpacingMetrics" } |
120 | }; |
121 | static int const |
122 | numOfCorrespondRelations |
123 | = sizeof(correspondRelations)/sizeof(correspondRelations[0]); |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | static Bool |
131 | get_record_type_by_name(SPropertyRecord const ** const refRefRecord, |
132 | char const *strName) |
133 | { |
134 | Bool result = False(0); |
135 | int i; |
136 | |
137 | *refRefRecord = NULL((void *)0); |
138 | for (i=0; i<numOfValidRecords; i++) { |
139 | if (!strcasecmp(validRecords[i].strRecordName, strName)) { |
140 | result = True(-1); |
141 | *refRefRecord = &validRecords[i]; |
142 | break; |
143 | } |
144 | } |
145 | |
146 | return result; |
147 | } |
148 | |
149 | |
150 | static Bool |
151 | SPropRecValList_add_record(SDynPropRecValList *pThisList, |
152 | char const * const recordName, |
153 | char const * const strValue) |
154 | { |
155 | Bool result = False(0); |
156 | SPropRecValContainerEntityP tmpContainerE; |
157 | |
158 | if (get_record_type_by_name(&tmpContainerE.refRecordType, recordName)) { |
| |
159 | switch (tmpContainerE.refRecordType->recordType) { |
| 17 | | Control jumps to 'case eRecTypeString:' at line 233 | |
|
160 | case eRecTypeInteger: |
161 | { |
162 | int val; |
163 | char *endPtr; |
164 | |
165 | val = strtol(strValue, &endPtr, 0); |
166 | if ('\0' != *endPtr) { |
167 | fprintf(stderr__stderrp, |
168 | "truetype font property : " |
169 | "%s record needs integer value.\n", |
170 | recordName); |
171 | result = True(-1); |
172 | goto quit; |
173 | } |
174 | SPropContainer_value_int(&tmpContainerE)((&tmpContainerE)->uValue.integerValue) = val; |
175 | } |
176 | break; |
177 | case eRecTypeDouble: |
178 | { |
179 | double val; |
180 | char *endPtr; |
181 | |
182 | val = strtod(strValue, &endPtr); |
183 | if ('\0' != *endPtr) { |
184 | fprintf(stderr__stderrp, |
185 | "truetype font property : " |
186 | "%s record needs floating point value.\n", |
187 | recordName); |
188 | result = True(-1); |
189 | goto quit; |
190 | } |
191 | SPropContainer_value_dbl(&tmpContainerE)((&tmpContainerE)->uValue.doubleValue) = val; |
192 | } |
193 | break; |
194 | case eRecTypeBool: |
195 | { |
196 | Bool val; |
197 | |
198 | if (!strcasecmp(strValue, "yes")) |
199 | val = True(-1); |
200 | else if (!strcasecmp(strValue, "y")) |
201 | val = True(-1); |
202 | else if (!strcasecmp(strValue, "on")) |
203 | val = True(-1); |
204 | else if (!strcasecmp(strValue, "true")) |
205 | val = True(-1); |
206 | else if (!strcasecmp(strValue, "t")) |
207 | val = True(-1); |
208 | else if (!strcasecmp(strValue, "ok")) |
209 | val = True(-1); |
210 | else if (!strcasecmp(strValue, "no")) |
211 | val = False(0); |
212 | else if (!strcasecmp(strValue, "n")) |
213 | val = False(0); |
214 | else if (!strcasecmp(strValue, "off")) |
215 | val = False(0); |
216 | else if (!strcasecmp(strValue, "false")) |
217 | val = False(0); |
218 | else if (!strcasecmp(strValue, "f")) |
219 | val = False(0); |
220 | else if (!strcasecmp(strValue, "bad")) |
221 | val = False(0); |
222 | else { |
223 | fprintf(stderr__stderrp, |
224 | "truetype font property : " |
225 | "%s record needs boolean value.\n", |
226 | recordName); |
227 | result = True(-1); |
228 | goto quit; |
229 | } |
230 | SPropContainer_value_bool(&tmpContainerE)((&tmpContainerE)->uValue.boolValue) = val; |
231 | } |
232 | break; |
233 | case eRecTypeString: |
234 | { |
235 | char *p; |
236 | |
237 | if (NULL((void *)0) == (p = strdup(strValue))) { |
| |
| |
238 | fprintf(stderr__stderrp, |
239 | "truetype font property : " |
240 | "cannot allocate memory.\n"); |
241 | result = True(-1); |
242 | goto quit; |
243 | } |
244 | SPropContainer_value_str(&tmpContainerE)((&tmpContainerE)->uValue.dynStringValue) = p; |
245 | } |
246 | break; |
| 20 | | Execution continues on line 258 | |
|
247 | case eRecTypeVoid: |
248 | if ('\0' != *strValue) { |
249 | fprintf(stderr__stderrp, |
250 | "truetype font property : " |
251 | "%s record needs void.\n", recordName); |
252 | result = True(-1); |
253 | } |
254 | break; |
255 | } |
256 | { |
257 | |
258 | SPropRecValListNodeP *newNode; |
259 | |
260 | if (NULL((void *)0) == (newNode = malloc(sizeof(*newNode)))) { |
| |
261 | fprintf(stderr__stderrp, |
| 22 | | Potential leak of memory pointed to by 'tmpContainerE.uValue.dynStringValue' |
|
262 | "truetype font property : " |
263 | "cannot allocate memory.\n"); |
264 | result = True(-1); |
265 | goto quit; |
266 | } |
267 | newNode->nextNode = pThisList->headNode; |
268 | newNode->containerE = tmpContainerE; |
269 | tmpContainerE.refRecordType = NULL((void *)0); |
270 | |
271 | pThisList->headNode = newNode; |
272 | } |
273 | } else { |
274 | |
275 | fprintf(stderr__stderrp, |
276 | "truetype font : " |
277 | "invalid record name \"%s.\"\n", recordName); |
278 | result = True(-1); |
279 | } |
280 | |
281 | quit: |
282 | return result; |
283 | } |
284 | |
285 | #ifdef USE_TTP_FILE |
286 | |
287 | #ifndef LEN_LINEBUF |
288 | #define LEN_LINEBUF 2048 |
289 | #endif /* !def LEN_LINEBUF */ |
290 | |
291 | |
292 | static Bool |
293 | get_one_line(FILE *is, char *buf) |
294 | { |
295 | Bool result = False(0); |
296 | int count = 0; |
297 | Bool flHead = True(-1); |
298 | Bool flSpace = False(0); |
299 | Bool flInSingleQuote = False(0); |
300 | Bool flInDoubleQuote = False(0); |
301 | Bool flBackSlash = False(0); |
302 | Bool flFirstElement = True(-1); |
303 | |
304 | *buf = '\0'; |
305 | for (;;) { |
306 | int c = fgetc(is); |
307 | |
308 | if (ferror(is)) { |
309 | fprintf(stderr__stderrp, "truetype font property file : read error.\n"); |
310 | result = True(-1); |
311 | break; |
312 | } |
313 | |
314 | if (EOF(-1) == c) { |
315 | if (flInSingleQuote || flInDoubleQuote) { |
316 | fprintf(stderr__stderrp, |
317 | "truetype font property file : unmatched quote.\n"); |
318 | result = True(-1); |
319 | } |
320 | break; |
321 | } |
322 | if (flInSingleQuote) { |
323 | if ('\'' == c) { |
324 | |
325 | flInSingleQuote = False(0); |
326 | c = -1; |
327 | } else |
328 | |
329 | ; |
330 | goto trans; |
331 | } |
332 | if (flBackSlash) { |
333 | |
334 | |
335 | flBackSlash = False(0); |
336 | if ('n' == c) |
337 | |
338 | c = '\n'; |
339 | if ('\n' == c) |
340 | |
341 | c = -1; |
342 | else |
343 | |
344 | ; |
345 | goto trans; |
346 | } |
347 | if ('\\' == c) { |
348 | |
349 | flBackSlash = True(-1); |
350 | c = -1; |
351 | goto trans; |
352 | } |
353 | if (flInDoubleQuote) { |
354 | if ('"' == c) { |
355 | |
356 | flInDoubleQuote = False(0); |
357 | c = -1; |
358 | } else |
359 | |
360 | ; |
361 | goto trans; |
362 | } |
363 | if ('#' == c) { |
364 | |
365 | while ('\n' != c) { |
366 | c = fgetc(is); |
367 | if (ferror(is)) { |
368 | fprintf(stderr__stderrp, |
369 | "truetype font property file : read error.\n"); |
370 | result = True(-1); |
371 | break; |
372 | } |
373 | if (EOF(-1) == c) { |
374 | break; |
375 | } |
376 | } |
377 | break; |
378 | } |
379 | if ('\'' == c) { |
380 | |
381 | flInSingleQuote = True(-1); |
382 | c = -1; |
383 | goto trans; |
384 | } |
385 | if ('"' == c) { |
386 | |
387 | flInDoubleQuote = True(-1); |
388 | c = -1; |
389 | goto trans; |
390 | } |
391 | if ('\n' == c) |
392 | |
393 | break; |
394 | if (isspace(c)) { |
395 | |
396 | if (!flHead) |
397 | |
398 | flSpace = True(-1); |
399 | continue; |
400 | } |
401 | trans: |
402 | |
403 | |
404 | flHead = False(0); |
405 | do { |
406 | if (count>=LEN_LINEBUF-1) { |
407 | |
408 | fprintf(stderr__stderrp, |
409 | "truetype font property file : too long line.\n"); |
410 | result = True(-1); |
411 | goto quit; |
412 | } |
413 | if (flSpace) { |
414 | |
415 | |
416 | if (flFirstElement) { |
417 | |
418 | flFirstElement = False(0); |
419 | |
420 | *buf = (char)0xff; |
421 | } else |
422 | *buf = ' '; |
423 | flSpace = False(0); |
424 | } else |
425 | if (-1 != c) { |
426 | *buf = c; |
427 | c = -1; |
428 | } else |
429 | |
430 | buf--; |
431 | buf++; |
432 | } while (-1 != c); |
433 | |
434 | } |
435 | *buf = '\0'; |
436 | |
437 | quit: |
438 | return result; |
439 | } |
440 | |
441 | |
442 | static Bool |
443 | parse_one_line(SDynPropRecValList *pThisList, FILE *is) |
444 | { |
445 | Bool result = False(0); |
446 | char *buf = NULL((void *)0); |
447 | char *recordHead, *valueHead = NULL((void *)0); |
448 | |
449 | if (NULL((void *)0) == (buf = malloc(LEN_LINEBUF))) { |
450 | fprintf(stderr__stderrp, |
451 | "truetype font property file : cannot allocate memory.\n"); |
452 | result = True(-1); |
453 | goto abort; |
454 | } |
455 | { |
456 | recordHead = buf; |
457 | |
458 | do { |
459 | if (get_one_line(is, buf)) { |
460 | result = True(-1); |
461 | goto quit; |
462 | } |
463 | if (feof(is)) { |
464 | if ('\0' == *buf) |
465 | goto quit; |
466 | break; |
467 | } |
468 | } while ('\0' == *buf); |
469 | |
470 | if (NULL((void *)0) != (valueHead = strchr(buf, 0xff))) { |
471 | *valueHead = '\0'; |
472 | valueHead++; |
473 | } else |
474 | valueHead = buf+strlen(buf); |
475 | #if 0 |
476 | fprintf(stderr__stderrp, |
477 | "truetype font property file : \n" |
478 | "recName:\"%s\"\nvalue:\"%s\"\n", |
479 | recordHead, valueHead); |
480 | #endif |
481 | result = SPropRecValList_add_record(pThisList, recordHead, valueHead); |
482 | } |
483 | quit: |
484 | free(buf); |
485 | abort: |
486 | return result; |
487 | } |
488 | |
489 | |
490 | Bool |
491 | SPropRecValList_read_prop_file(SDynPropRecValList *pThisList, |
492 | char const * const strFileName) |
493 | { |
494 | Bool result = False(0); |
495 | FILE *is; |
496 | |
497 | #if 1 |
498 | if (!strcmp(strFileName, "-")) |
499 | is = stdin__stdinp; |
500 | else |
501 | #endif |
502 | is = fopen(strFileName, "r"); |
503 | if (NULL((void *)0) == is) { |
504 | fprintf(stderr__stderrp, "truetype font property : cannot open file %s.\n", |
505 | strFileName); |
506 | result = True(-1); |
507 | goto abort; |
508 | } |
509 | { |
510 | for (;;) { |
511 | if (False(0) != (result = parse_one_line(pThisList, is))) |
512 | goto quit; |
513 | if (feof(is)) |
514 | break; |
515 | } |
516 | } |
517 | quit: |
518 | #if 1 |
519 | if (strcmp(strFileName, "-")) |
520 | #endif |
521 | fclose(is); |
522 | abort: |
523 | return result; |
524 | } |
525 | #endif /* USE_TTP_FILE */ |
526 | |
527 | |
528 | Bool |
529 | SPropRecValList_new(SDynPropRecValList *pThisList) |
530 | { |
531 | Bool result = False(0); |
532 | |
533 | pThisList->headNode = NULL((void *)0); |
534 | |
535 | return result; |
536 | } |
537 | |
538 | #ifdef DUMP |
539 | void |
540 | SPropRecValList_dump(SRefPropRecValList *pThisList) |
541 | { |
542 | SPropRecValListNodeP *p; |
543 | for (p=pThisList->headNode; NULL((void *)0)!=p; p=p->nextNode) { |
544 | switch (p->containerE.refRecordType->recordType) { |
545 | case eRecTypeInteger: |
546 | fprintf(stderr__stderrp, "%s = %d\n", |
547 | p->containerE.refRecordType->strRecordName, |
548 | p->containerE.uValue.integerValue); |
549 | break; |
550 | case eRecTypeDouble: |
551 | fprintf(stderr__stderrp, "%s = %f\n", |
552 | p->containerE.refRecordType->strRecordName, |
553 | p->containerE.uValue.doubleValue); |
554 | break; |
555 | case eRecTypeBool: |
556 | fprintf(stderr__stderrp, "%s = %s\n", |
557 | p->containerE.refRecordType->strRecordName, |
558 | p->containerE.uValue.boolValue |
559 | ? "True":"False"); |
560 | break; |
561 | case eRecTypeString: |
562 | fprintf(stderr__stderrp, "%s = \"%s\"\n", |
563 | p->containerE.refRecordType->strRecordName, |
564 | p->containerE.uValue.dynStringValue); |
565 | break; |
566 | case eRecTypeVoid: |
567 | fprintf(stderr__stderrp, "%s = void\n", |
568 | p->containerE.refRecordType->strRecordName); |
569 | break; |
570 | } |
571 | } |
572 | } |
573 | #endif |
574 | |
575 | |
576 | |
577 | Bool |
578 | SPropRecValList_search_record(SRefPropRecValList *pThisList, |
579 | SPropRecValContainer *refRecValue, |
580 | char const * const recordName) |
581 | { |
582 | Bool result = False(0); |
583 | SPropRecValListNodeP *p; |
584 | |
585 | *refRecValue = NULL((void *)0); |
586 | for (p=pThisList->headNode; NULL((void *)0)!=p; p=p->nextNode) { |
587 | if (!strcasecmp(p->containerE.refRecordType->strRecordName, |
588 | recordName)) { |
589 | *refRecValue = &p->containerE; |
590 | result = True(-1); |
591 | break; |
592 | } |
593 | } |
594 | |
595 | return result; |
596 | } |
597 | |
598 | |
599 | |
600 | Bool |
601 | SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList, |
602 | char const *strCapHead) |
603 | { |
604 | Bool result = False(0); |
605 | |
606 | char const *term; |
607 | |
608 | if (NULL((void *)0) == (term = strrchr(strCapHead, ':'))) |
| |
609 | goto abort; |
610 | |
611 | { |
612 | |
613 | char const *p; |
614 | for (p=term-1; p>=strCapHead; p--) { |
| 2 | | Loop condition is false. Execution continues on line 640 | |
|
615 | if ( ':'==*p ) { |
616 | |
617 | |
618 | |
619 | |
620 | if ( p!=term ) { |
621 | int len = term-p-1; |
622 | char *value; |
623 | |
624 | value=malloc(len+1); |
625 | memcpy(value, p+1, len)__builtin___memcpy_chk (value, p+1, len, __builtin_object_size (value, 0)); |
626 | value[len]='\0'; |
627 | SPropRecValList_add_record(pThisList, |
628 | "FaceNumber", |
629 | value); |
630 | free(value); |
631 | term=p; |
632 | } |
633 | break; |
634 | } |
635 | if ( !isdigit(*p) ) |
636 | break; |
637 | } |
638 | } |
639 | |
640 | while (strCapHead<term) { |
| 3 | | Assuming 'strCapHead' is < 'term' | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 6 | | Loop condition is true. Entering loop body | |
|
| 8 | | Loop condition is true. Entering loop body | |
|
641 | int i; |
642 | char const *nextColon = strchr(strCapHead, ':'); |
643 | if (0<nextColon-strCapHead) { |
| |
| |
| |
644 | char *duplicated = malloc((nextColon-strCapHead)+1); |
645 | { |
646 | char *value; |
647 | |
648 | memcpy(duplicated, strCapHead, nextColon-strCapHead)__builtin___memcpy_chk (duplicated, strCapHead, nextColon-strCapHead , __builtin_object_size (duplicated, 0)); |
649 | duplicated[nextColon-strCapHead] = '\0'; |
650 | if (NULL((void *)0) != (value=strchr(duplicated, '='))) { |
| |
651 | *value = '\0'; |
652 | value++; |
653 | } else |
654 | value = &duplicated[nextColon-strCapHead]; |
655 | |
656 | for (i=0; i<numOfCorrespondRelations; i++) { |
| 11 | | Loop condition is true. Entering loop body | |
|
| 13 | | Loop condition is true. Entering loop body | |
|
657 | if (!strcasecmp(correspondRelations[i].capVariable, |
| |
| |
658 | duplicated)) { |
659 | if (SPropRecValList_add_record(pThisList, |
| 15 | | Calling 'SPropRecValList_add_record' | |
|
660 | correspondRelations[i] |
661 | .recordName, |
662 | value)) |
663 | break; |
664 | goto next; |
665 | } |
666 | } |
667 | fprintf(stderr__stderrp, "truetype font : Illegal Font Cap.\n"); |
668 | result = True(-1); |
669 | break; |
670 | next: |
671 | ; |
672 | } |
673 | free(duplicated); |
674 | } |
675 | strCapHead = nextColon+1; |
676 | } |
677 | |
678 | |
679 | abort: |
680 | return result; |
681 | } |
682 | |
683 | |