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