]> git.saurik.com Git - apple/icu.git/blob - icuSources/samples/layout/FontMap.cpp
ICU-6.2.4.tar.gz
[apple/icu.git] / icuSources / samples / layout / FontMap.cpp
1 /*
2 ******************************************************************************
3 * Copyright (C) 1998-2003, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 ******************************************************************************
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <ctype.h>
11
12 #include "unicode/utypes.h"
13 #include "unicode/uscript.h"
14
15 #include "layout/LETypes.h"
16 #include "layout/LEScripts.h"
17 #include "layout/LEFontInstance.h"
18
19 #include "GUISupport.h"
20 #include "FontMap.h"
21
22 FontMap::FontMap(const char *fileName, le_int16 pointSize, GUISupport *guiSupport, LEErrorCode &status)
23 : fPointSize(pointSize), fFontCount(0), fAscent(0), fDescent(0), fLeading(0), fGUISupport(guiSupport)
24 {
25 le_int32 defaultFont = -1, i, script;
26
27 for (i = 0; i < scriptCodeCount; i += 1) {
28 fFontIndices[i] = -1;
29 fFontNames[i] = NULL;
30 fFontInstances[i] = NULL;
31 }
32
33 if (LE_FAILURE(status)) {
34 return;
35 }
36
37 char *c, *scriptName, *fontName, *line, buffer[BUFFER_SIZE];
38 FILE *file;
39
40 file = fopen(fileName, "r");
41
42 if (file == NULL) {
43 sprintf(errorMessage, "Could not open the font map file: %s.", fileName);
44 fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
45 status = LE_FONT_FILE_NOT_FOUND_ERROR;
46 return;
47 }
48
49 while (fgets(buffer, BUFFER_SIZE, file) != NULL) {
50 UScriptCode scriptCode;
51 UErrorCode scriptStatus = U_ZERO_ERROR;
52
53 line = strip(buffer);
54 if (line[0] == '#' || line[0] == 0) {
55 continue;
56 }
57
58 c = strchr(line, ':');
59 c[0] = 0;
60
61 fontName = strip(&c[1]);
62 scriptName = strip(line);
63
64 if (strcmp(scriptName, "DEFAULT") == 0) {
65 defaultFont = getFontIndex(fontName);
66 continue;
67 }
68
69 uscript_getCode(scriptName, &scriptCode, 1, &scriptStatus);
70
71 if (U_FAILURE(scriptStatus) || scriptStatus == U_USING_FALLBACK_WARNING ||
72 scriptStatus == U_USING_DEFAULT_WARNING) {
73 sprintf(errorMessage, "The script name %s is invalid.", line);
74 fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
75 status = LE_ILLEGAL_ARGUMENT_ERROR;
76 fclose(file);
77 return;
78 }
79
80 script = (le_int32) scriptCode;
81
82 if (fFontIndices[script] >= 0) {
83 // FIXME: complain that this is a duplicate entry and bail (?)
84 fFontIndices[script] = -1;
85 }
86
87 fFontIndices[script] = getFontIndex(fontName);
88 }
89
90 if (defaultFont >= 0) {
91 for (script = 0; script < scriptCodeCount; script += 1) {
92 if (fFontIndices[script] < 0) {
93 fFontIndices[script] = defaultFont;
94 }
95 }
96 }
97
98 fclose(file);
99 }
100
101 FontMap::~FontMap()
102 {
103 le_int32 font;
104
105 for (font = 0; font < fFontCount; font += 1) {
106 if (fFontNames[font] != NULL) {
107 delete[] (char *) fFontNames[font];
108 }
109 }
110
111 for (font = 0; font < fFontCount; font += 1) {
112 if (fFontInstances[font] != NULL) {
113 delete fFontInstances[font];
114 }
115 }
116 }
117
118 le_int32 FontMap::getFontIndex(const char *fontName)
119 {
120 le_int32 index;
121
122 for (index = 0; index < fFontCount; index += 1) {
123 if (strcmp(fontName, fFontNames[index]) == 0) {
124 return index;
125 }
126 }
127
128 if (fFontCount < (le_int32) scriptCodeCount) {
129 index = fFontCount++;
130 } else {
131 // The font name table is full. Since there can
132 // only be scriptCodeCount fonts in use at once,
133 // there should be at least one that's not being
134 // referenced; find it and resue it's index.
135
136 for (index = 0; index < fFontCount; index += 1) {
137 le_int32 script;
138
139 for (script = 0; script < scriptCodeCount; script += 1) {
140 if (fFontIndices[script] == index) {
141 break;
142 }
143 }
144
145 if (script >= scriptCodeCount) {
146 break;
147 }
148 }
149 }
150
151 if (index >= scriptCodeCount) {
152 return -1;
153 }
154
155 le_int32 len = strlen(fontName);
156 char *s = new char[len + 1];
157
158 fFontNames[index] = strcpy(s, fontName);
159 return index;
160 }
161
162 char *FontMap::strip(char *s)
163 {
164 le_int32 start, end, len;
165
166 start = 0;
167 len = strlen(s);
168
169 while (start < len && isspace(s[start])) {
170 start += 1;
171 }
172
173 end = len - 1;
174
175 while (end > start && isspace(s[end])) {
176 end -= 1;
177 }
178
179 if (end < len) {
180 s[end + 1] = '\0';
181 }
182
183 return &s[start];
184 }
185
186 const LEFontInstance *FontMap::getScriptFont(le_int32 scriptCode, LEErrorCode &status)
187 {
188 if (LE_FAILURE(status)) {
189 return NULL;
190 }
191
192 if (scriptCode <= -1 || scriptCode >= scriptCodeCount) {
193 status = LE_ILLEGAL_ARGUMENT_ERROR;
194 return NULL;
195 }
196
197
198 le_int32 fontIndex = fFontIndices[scriptCode];
199
200 if (fontIndex < 0) {
201 sprintf(errorMessage, "No font was set for script %s", uscript_getName((UScriptCode) scriptCode));
202 fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
203 status = LE_FONT_FILE_NOT_FOUND_ERROR;
204 return NULL;
205 }
206
207 if (fFontInstances[fontIndex] == NULL) {
208 fFontInstances[fontIndex] = openFont(fFontNames[fontIndex], fPointSize, status);
209
210 if (LE_FAILURE(status)) {
211 sprintf(errorMessage, "Could not open font file %s", fFontNames[fontIndex]);
212 fGUISupport->postErrorMessage(errorMessage, "Font Map Error");
213 return NULL;
214 }
215 }
216
217 return fFontInstances[fontIndex];
218 }
219
220 le_int32 FontMap::getAscent() const
221 {
222 if (fAscent <= 0) {
223 ((FontMap *) this)->getMaxMetrics();
224 }
225
226 return fAscent;
227 }
228
229 le_int32 FontMap::getDescent() const
230 {
231 if (fDescent <= 0) {
232 ((FontMap *) this)->getMaxMetrics();
233 }
234
235 return fDescent;
236 }
237
238 le_int32 FontMap::getLeading() const
239 {
240 if (fLeading <= 0) {
241 ((FontMap *) this)->getMaxMetrics();
242 }
243
244 return fLeading;
245 }
246
247 void FontMap::getMaxMetrics()
248 {
249 for (le_int32 i = 0; i < fFontCount; i += 1) {
250 LEErrorCode status = LE_NO_ERROR;
251 le_int32 ascent, descent, leading;
252
253 if (fFontInstances[i] == NULL) {
254 fFontInstances[i] = openFont(fFontNames[i], fPointSize, status);
255
256 if (LE_FAILURE(status)) {
257 continue;
258 }
259 }
260
261 ascent = fFontInstances[i]->getAscent();
262 descent = fFontInstances[i]->getDescent();
263 leading = fFontInstances[i]->getLeading();
264
265 if (ascent > fAscent) {
266 fAscent = ascent;
267 }
268
269 if (descent > fDescent) {
270 fDescent = descent;
271 }
272
273 if (leading > fLeading) {
274 fLeading = leading;
275 }
276 }
277 }
278