1 /* ===EmacsMode: -*- Mode: C; tab-width:4; c-basic-offset: 4; -*- === */
3 Copyright (c) 1998 Takuya SHIOZAKI, All Rights reserved.
4 Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
5 Copyright (c) 2003 After X-TT Project, All rights reserved.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 Major Release ID: X-TrueType Server Version 1.4 [Charles's Wain Release 0]
35 #include "xttversion.h"
37 static char const * const releaseID =
44 #include <X11/fonts/fontmisc.h>
59 /**************************************************************************
63 /* Property Record List */
65 typedef struct TagSPropRecValListNodeP
67 SPropRecValContainerEntityP containerE;
68 struct TagSPropRecValListNodeP *nextNode;
69 } SPropRecValListNodeP;
72 /**************************************************************************
76 /* valid record field */
77 static SPropertyRecord const validRecords[] =
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 }
98 numOfValidRecords = sizeof(validRecords)/sizeof(validRecords[0]);
100 /* correspondence between record name and cap variable name */
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" },
118 { "fc", "ForceConstantSpacingCodeRange" },
119 { "fm", "ForceConstantSpacingMetrics" }
122 numOfCorrespondRelations
123 = sizeof(correspondRelations)/sizeof(correspondRelations[0]);
125 /**************************************************************************
129 /* get property record type by record name */
130 static Bool /* True == Found, False == Not Found */
131 get_record_type_by_name(SPropertyRecord const ** const refRefRecord, /*result*/
137 *refRefRecord = NULL;
138 for (i=0; i<numOfValidRecords; i++) {
139 if (!strcasecmp(validRecords[i].strRecordName, strName)) {
141 *refRefRecord = &validRecords[i];
149 /* Add Property Record Value */
150 static Bool /* True == Error, False == Success */
151 SPropRecValList_add_record(SDynPropRecValList *pThisList,
152 char const * const recordName,
153 char const * const strValue)
156 SPropRecValContainerEntityP tmpContainerE;
158 if (get_record_type_by_name(&tmpContainerE.refRecordType, recordName)) {
159 switch (tmpContainerE.refRecordType->recordType) {
160 case eRecTypeInteger:
165 val = strtol(strValue, &endPtr, 0);
166 if ('\0' != *endPtr) {
168 "truetype font property : "
169 "%s record needs integer value.\n",
174 SPropContainer_value_int(&tmpContainerE) = val;
182 val = strtod(strValue, &endPtr);
183 if ('\0' != *endPtr) {
185 "truetype font property : "
186 "%s record needs floating point value.\n",
191 SPropContainer_value_dbl(&tmpContainerE) = val;
198 if (!strcasecmp(strValue, "yes"))
200 else if (!strcasecmp(strValue, "y"))
202 else if (!strcasecmp(strValue, "on"))
204 else if (!strcasecmp(strValue, "true"))
206 else if (!strcasecmp(strValue, "t"))
208 else if (!strcasecmp(strValue, "ok"))
210 else if (!strcasecmp(strValue, "no"))
212 else if (!strcasecmp(strValue, "n"))
214 else if (!strcasecmp(strValue, "off"))
216 else if (!strcasecmp(strValue, "false"))
218 else if (!strcasecmp(strValue, "f"))
220 else if (!strcasecmp(strValue, "bad"))
224 "truetype font property : "
225 "%s record needs boolean value.\n",
230 SPropContainer_value_bool(&tmpContainerE) = val;
237 if (NULL == (p = malloc(strlen(strValue)+1))) {
239 "truetype font property : "
240 "cannot allocate memory.\n");
245 SPropContainer_value_str(&tmpContainerE) = p;
249 if ('\0' != *strValue) {
251 "truetype font property : "
252 "%s record needs void.\n", recordName);
259 SPropRecValListNodeP *newNode;
261 if (NULL == (newNode = malloc(sizeof(*newNode)))) {
263 "truetype font property : "
264 "cannot allocate memory.\n");
268 newNode->nextNode = pThisList->headNode;
269 newNode->containerE = tmpContainerE;
270 tmpContainerE.refRecordType = NULL; /* invalidate --
271 disown value handle. */
272 pThisList->headNode = newNode;
275 /* invalid record name */
278 "invalid record name \"%s.\"\n", recordName);
289 #define LEN_LINEBUF 2048
290 #endif /* !def LEN_LINEBUF */
293 static Bool /* True == Error, False == Success */
294 get_one_line(FILE *is, char *buf)
299 Bool flSpace = False;
300 Bool flInSingleQuote = False;
301 Bool flInDoubleQuote = False;
302 Bool flBackSlash = False;
303 Bool flFirstElement = True;
310 fprintf(stderr, "truetype font property file : read error.\n");
316 if (flInSingleQuote || flInDoubleQuote) {
318 "truetype font property file : unmatched quote.\n");
323 if (flInSingleQuote) {
325 /* end of single quoted string */
326 flInSingleQuote = False;
327 c = -1; /* NOT extract to buffer. */
329 /* others, extract all character to buffer unconditionally. */
334 /* escape --- when just before character is backslash,
335 next character is escaped. */
344 /* others, extract all character to buffer unconditionally. */
349 /* set flag to escape next character. */
351 c = -1; /* NOT extract to buffer. */
354 if (flInDoubleQuote) {
356 /* end of double quoted string */
357 flInDoubleQuote = False;
358 c = -1; /* NOT extract to buffer. */
360 /* others, extract all character to buffer unconditionally. */
365 /* skip comment till end of line. */
370 "truetype font property file : read error.\n");
381 /* into single quoted string */
382 flInSingleQuote = True;
383 c = -1; /* NOT extract to buffer. */
387 /* into double quoted string */
388 flInDoubleQuote = True;
389 c = -1; /* NOT extract to buffer. */
396 /* convine multiple spaces */
398 /* except space at the head of line */
403 /* set flHead to False, since current character is not white space
404 when reaches here. */
407 if (count>=LEN_LINEBUF-1) {
410 "truetype font property file : too long line.\n");
415 /* just before characters is white space, but
416 current character is not WS. */
417 if (flFirstElement) {
418 /* this spaces is the first cell(?) of white spaces. */
419 flFirstElement = False;
420 /* separate record name and record value */
428 c = -1; /* invalidate */
433 } while (-1 != c); /* when 'c' is not -1, it means
434 that 'c' contains an untreated character. */
443 static Bool /* True == Error, False == Success */
444 parse_one_line(SDynPropRecValList *pThisList, FILE *is)
448 char *recordHead, *valueHead = NULL;
450 if (NULL == (buf = malloc(LEN_LINEBUF))) {
452 "truetype font property file : cannot allocate memory.\n");
458 /* refRecordValue->refRecordType = NULL;*/
460 if (get_one_line(is, buf)) {
469 } while ('\0' == *buf);
471 if (NULL != (valueHead = strchr(buf, 0xff))) {
475 valueHead = buf+strlen(buf);
478 "truetype font property file : \n"
479 "recName:\"%s\"\nvalue:\"%s\"\n",
480 recordHead, valueHead);
482 result = SPropRecValList_add_record(pThisList, recordHead, valueHead);
490 /* Read Property File */
491 Bool /* True == Error, False == Success */
492 SPropRecValList_read_prop_file(SDynPropRecValList *pThisList,
493 char const * const strFileName)
499 if (!strcmp(strFileName, "-"))
503 is = fopen(strFileName, "r");
505 fprintf(stderr, "truetype font property : cannot open file %s.\n",
512 if (False != (result = parse_one_line(pThisList, is)))
520 if (strcmp(strFileName, "-"))
526 #endif /* USE_TTP_FILE */
528 /* Constructor for Container Node */
529 Bool /* True == Error, False == Success */
530 SPropRecValList_new(SDynPropRecValList *pThisList)
534 pThisList->headNode = NULL;
541 SPropRecValList_dump(SRefPropRecValList *pThisList)
543 SPropRecValListNodeP *p;
544 for (p=pThisList->headNode; NULL!=p; p=p->nextNode) {
545 switch (p->containerE.refRecordType->recordType) {
546 case eRecTypeInteger:
547 fprintf(stderr, "%s = %d\n",
548 p->containerE.refRecordType->strRecordName,
549 p->containerE.uValue.integerValue);
552 fprintf(stderr, "%s = %f\n",
553 p->containerE.refRecordType->strRecordName,
554 p->containerE.uValue.doubleValue);
557 fprintf(stderr, "%s = %s\n",
558 p->containerE.refRecordType->strRecordName,
559 p->containerE.uValue.boolValue
563 fprintf(stderr, "%s = \"%s\"\n",
564 p->containerE.refRecordType->strRecordName,
565 p->containerE.uValue.dynStringValue);
568 fprintf(stderr, "%s = void\n",
569 p->containerE.refRecordType->strRecordName);
577 /* Search Property Record */
578 Bool /* True == Hit, False == Miss */
579 SPropRecValList_search_record(SRefPropRecValList *pThisList,
580 SPropRecValContainer *refRecValue,
581 char const * const recordName)
584 SPropRecValListNodeP *p;
587 for (p=pThisList->headNode; NULL!=p; p=p->nextNode) {
588 if (!strcasecmp(p->containerE.refRecordType->strRecordName,
590 *refRecValue = &p->containerE;
601 Bool /* True == Error, False == Success */
602 SPropRecValList_add_by_font_cap(SDynPropRecValList *pThisList,
603 char const *strCapHead)
606 /* SPropertyRecord const *refRecordType; */
609 if (NULL == (term = strrchr(strCapHead, ':')))
613 /* for xfsft compatible */
615 for (p=term-1; p>=strCapHead; p--) {
627 memcpy(value, p+1, len);
629 SPropRecValList_add_record(pThisList,
642 while (strCapHead<term) {
644 char const *nextColon = strchr(strCapHead, ':');
645 if (0<nextColon-strCapHead) {
646 char *duplicated = malloc((nextColon-strCapHead)+1);
650 memcpy(duplicated, strCapHead, nextColon-strCapHead);
651 duplicated[nextColon-strCapHead] = '\0';
652 if (NULL != (value=strchr(duplicated, '='))) {
656 value = &duplicated[nextColon-strCapHead];
658 for (i=0; i<numOfCorrespondRelations; i++) {
659 if (!strcasecmp(correspondRelations[i].capVariable,
661 if (SPropRecValList_add_record(pThisList,
662 correspondRelations[i]
669 fprintf(stderr, "truetype font : Illegal Font Cap.\n");
677 strCapHead = nextColon+1;
686 /**************************************************************************
690 /* strdup clone with using the allocator of X server */
692 XttXstrdup(char const *str)
696 result = malloc(strlen(str)+1);