1 |
/* ufont.c */ |
2 |
|
3 |
#include "ufont.h" |
4 |
|
5 |
#include "oslib/osfile.h" |
6 |
|
7 |
|
8 |
#define MALLOC_CHUNK 256 |
9 |
|
10 |
|
11 |
struct ufont_font |
12 |
{ |
13 |
font_f handle[65536]; |
14 |
char character[65536]; |
15 |
unsigned int handles_used; |
16 |
font_f handles[256]; |
17 |
}; |
18 |
|
19 |
|
20 |
os_error error_exists = { error_FONT_NOT_FOUND, "Fonts file not found" }; |
21 |
os_error error_memory = { error_FONT_NO_ROOM, "Insufficient memory for font" }; |
22 |
os_error error_size = { error_FONT_BAD_FONT_FILE, "Wrong size of font file" }; |
23 |
|
24 |
|
25 |
/* |
26 |
* UFont_FindFont |
27 |
* |
28 |
* => as Font_FindFont, but |
29 |
* font_name does not support '\' qualifiers |
30 |
* |
31 |
* <= as Font_FindFont, but |
32 |
* handle is 32-bit |
33 |
*/ |
34 |
|
35 |
os_error * |
36 |
xufont_find_font(char const *font_name, |
37 |
int xsize, |
38 |
int ysize, |
39 |
int xres, |
40 |
int yres, |
41 |
struct ufont_font **font, |
42 |
int *xres_out, |
43 |
int *yres_out) |
44 |
{ |
45 |
char *old_font; |
46 |
char *fonts_file; |
47 |
char file_name[256]; |
48 |
fileswitch_object_type obj_type; |
49 |
int code; |
50 |
int handle; |
51 |
unsigned int size; |
52 |
os_error *error; |
53 |
|
54 |
/* find size of Fonts file */ |
55 |
strcpy(file_name, font_name); |
56 |
strcat(file_name, ".Fonts"); |
57 |
error = xosfile_read_stamped_path(file_name, "UFont:", &obj_type, NULL, NULL, &size, NULL, NULL); |
58 |
if (error != NULL) return error; |
59 |
if (obj_type != fileswitch_IS_FILE) return &error_exists; |
60 |
|
61 |
/* allocate memory */ |
62 |
fonts_file = malloc(size); |
63 |
if (fonts_file == NULL) return &error_memory; |
64 |
|
65 |
*font = malloc(sizeof(struct ufont_font)); |
66 |
if (*font == NULL) return &error_memory; |
67 |
|
68 |
/* load Fonts */ |
69 |
error = xosfile_load_stamped_path(file_name, fonts_file, "UFont:", NULL, NULL, NULL, NULL, NULL); |
70 |
if (error != NULL) return error; |
71 |
|
72 |
/* open all fonts listed in Fonts */ |
73 |
for (old_font = fonts_file, handle = 0; old_font - fonts_file < size; |
74 |
old_font += strlen(old_font) + 1, handle++) |
75 |
{ |
76 |
/* #ifdef DEBUG */ |
77 |
/* printf("%i %s: ", handle, old_font); */ |
78 |
/* #endif */ |
79 |
|
80 |
error = xfont_find_font(old_font, xsize, ysize, xres, yres, |
81 |
&(*font)->handles[handle], xres_out, yres_out); |
82 |
if (error != NULL) return error; |
83 |
|
84 |
/* #ifdef DEBUG */ |
85 |
/* printf("%i\n", (*font)->handles[handle]); */ |
86 |
/* #endif */ |
87 |
} |
88 |
(*font)->handles_used = handle; |
89 |
|
90 |
/* free Fonts */ |
91 |
free(fonts_file); |
92 |
|
93 |
/* load Data */ |
94 |
strcpy(file_name, font_name); |
95 |
strcat(file_name, ".Data"); |
96 |
error = xosfile_load_stamped_path(file_name, (byte *) (*font), "UFont:", |
97 |
NULL, NULL, NULL, &size, NULL); |
98 |
if (error != NULL) return error; |
99 |
if (size != 2*65536) return &error_size; |
100 |
|
101 |
/* change font indexes to font handles */ |
102 |
for (code = 0; code < 65536; code++) |
103 |
(*font)->handle[code] = (*font)->handles[(*font)->handle[code]]; |
104 |
|
105 |
return NULL; |
106 |
} |
107 |
|
108 |
|
109 |
/* |
110 |
* UFont_LoseFont |
111 |
* |
112 |
* => font handle as returned by UFont_FindFont |
113 |
*/ |
114 |
|
115 |
os_error * |
116 |
xufont_lose_font(struct ufont_font *font) |
117 |
{ |
118 |
unsigned int handle; |
119 |
os_error *error; |
120 |
|
121 |
/* close all fonts used */ |
122 |
for (handle = 0; handle < font->handles_used; handle++) |
123 |
{ |
124 |
error = xfont_lose_font(font->handles[handle]); |
125 |
if (error != NULL) return error; |
126 |
} |
127 |
|
128 |
/* free font structure */ |
129 |
free(font); |
130 |
|
131 |
return NULL; |
132 |
} |
133 |
|
134 |
|
135 |
/* |
136 |
* UFont_Paint |
137 |
* |
138 |
* => font handle as returned by UFont_FindFont |
139 |
* string is unicode (2 byte characters), see UFont_Convert |
140 |
* other parameters as Font_Paint |
141 |
*/ |
142 |
|
143 |
os_error * |
144 |
xufont_paint(struct ufont_font *font, |
145 |
wchar_t const *string, |
146 |
font_string_flags flags, |
147 |
int xpos, |
148 |
int ypos, |
149 |
font_paint_block const *block, |
150 |
os_trfm const *trfm, |
151 |
unsigned int length) |
152 |
{ |
153 |
char *result; |
154 |
os_error *error; |
155 |
|
156 |
if ((flags & font_GIVEN_LENGTH) == 0) length = 0x7fffffff; |
157 |
|
158 |
error = xufont_convert(font, string, length, &result, NULL); |
159 |
if (error != NULL) return error; |
160 |
|
161 |
error = xfont_paint(result[1], result, |
162 |
(flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT, |
163 |
xpos, ypos, block, trfm, 0); |
164 |
if (error != NULL) { free(result); return error; } |
165 |
|
166 |
free(result); |
167 |
|
168 |
return NULL; |
169 |
} |
170 |
|
171 |
|
172 |
/* |
173 |
* UFont_Convert |
174 |
* |
175 |
* => initial font |
176 |
* unicode string to convert |
177 |
* length to convert (characters) |
178 |
* |
179 |
* control sequences in string (all 2 byte): |
180 |
* |
181 |
* 9, dx_low, dx_middle, dx_high (each 2 byte, but maximum 255) |
182 |
* 11, dy_low, dy_middle, dy_high " |
183 |
* 19, r, g, b, R, G, B, max " |
184 |
* 25, underline_position, underline_thickness " |
185 |
* 26, font_handle (4 bytes, ie. 2 wide characters) |
186 |
* 27, m1, m2, m3, m4 (each matrix entry 4 bytes, |
187 |
* 28, m1, m2, m3, m4, m5, m6 ie. 2 wide characters) |
188 |
* |
189 |
* <= string converted to Font_Paint format |
190 |
* table of offsets in unicode string |
191 |
*/ |
192 |
|
193 |
os_error * |
194 |
xufont_convert(struct ufont_font *font, |
195 |
wchar_t const *string, |
196 |
unsigned int length, |
197 |
char **presult, |
198 |
unsigned int **ptable) |
199 |
{ |
200 |
char *result; |
201 |
unsigned int string_index = 0; |
202 |
unsigned int result_index = 0; |
203 |
unsigned int i; |
204 |
unsigned int current_size = MALLOC_CHUNK; |
205 |
unsigned int *table; |
206 |
font_f current_font = 0; |
207 |
|
208 |
result = malloc(MALLOC_CHUNK); |
209 |
if (result == NULL) return &error_memory; |
210 |
|
211 |
if (ptable != NULL) |
212 |
{ |
213 |
table = malloc(MALLOC_CHUNK * sizeof(unsigned int)); |
214 |
if (table == NULL) return &error_memory; |
215 |
} |
216 |
|
217 |
while ((string[string_index] != 0) && (string_index < length)) |
218 |
{ |
219 |
/* #ifdef DEBUG */ |
220 |
/* printf("0x%x ", string[string_index]); */ |
221 |
/* #endif */ |
222 |
|
223 |
if (result_index + 32 > current_size) |
224 |
{ |
225 |
current_size += MALLOC_CHUNK; |
226 |
|
227 |
result = realloc(result, current_size); |
228 |
if (result == NULL) return &error_memory; |
229 |
|
230 |
if (ptable != NULL) |
231 |
{ |
232 |
table = realloc(result, current_size * sizeof(unsigned int)); |
233 |
if (table == NULL) return &error_memory; |
234 |
} |
235 |
} |
236 |
|
237 |
if (ptable != NULL) table[result_index] = string_index; |
238 |
|
239 |
switch (string[string_index]) |
240 |
{ |
241 |
case 9: |
242 |
case 11: |
243 |
{ |
244 |
if (ptable != NULL) |
245 |
table[result_index + 1] = table[result_index + 2] = table[result_index + 3] = string_index; |
246 |
|
247 |
result[result_index++] = string[string_index++]; |
248 |
result[result_index++] = string[string_index++]; |
249 |
result[result_index++] = string[string_index++]; |
250 |
result[result_index++] = string[string_index++]; |
251 |
break; |
252 |
} |
253 |
case 19: |
254 |
{ |
255 |
if (ptable != NULL) |
256 |
table[result_index + 1] = table[result_index + 2] = table[result_index + 3] = |
257 |
table[result_index + 4] = table[result_index + 5] = table[result_index + 6] = |
258 |
table[result_index + 7] = string_index; |
259 |
|
260 |
result[result_index++] = string[string_index++]; |
261 |
result[result_index++] = string[string_index++]; |
262 |
result[result_index++] = string[string_index++]; |
263 |
result[result_index++] = string[string_index++]; |
264 |
result[result_index++] = string[string_index++]; |
265 |
result[result_index++] = string[string_index++]; |
266 |
result[result_index++] = string[string_index++]; |
267 |
result[result_index++] = string[string_index++]; |
268 |
break; |
269 |
} |
270 |
case 25: |
271 |
{ |
272 |
if (ptable != NULL) |
273 |
table[result_index + 1] = table[result_index + 2] = string_index; |
274 |
|
275 |
result[result_index++] = string[string_index++]; |
276 |
result[result_index++] = string[string_index++]; |
277 |
result[result_index++] = string[string_index++]; |
278 |
break; |
279 |
} |
280 |
case 26: |
281 |
{ |
282 |
string_index++; |
283 |
font = (struct ufont_font *) ((string[string_index + 1] << 16) | string[string_index]); |
284 |
break; |
285 |
} |
286 |
case 27: |
287 |
{ |
288 |
if (ptable != NULL) |
289 |
for (i = result_index + 1; i < ((result_index + 1 + 16 + 3) & (unsigned int) (~3)); i++) |
290 |
table[i] = string_index; |
291 |
|
292 |
result[result_index++] = string[string_index++]; |
293 |
result_index = (result_index + 3) & (unsigned int) (~3); |
294 |
for (i = 0; i < 8; i++) |
295 |
{ |
296 |
result[result_index++] = string[string_index] & 0xff; |
297 |
result[result_index++] = string[string_index++] >> 8; |
298 |
} |
299 |
break; |
300 |
} |
301 |
case 28: |
302 |
{ |
303 |
if (ptable != NULL) |
304 |
for (i = result_index + 1; i < ((result_index + 1 + 24 + 3) & (unsigned int) (~3)); i++) |
305 |
table[i] = string_index; |
306 |
|
307 |
result[result_index++] = string[string_index++]; |
308 |
result_index = (result_index + 3) & (unsigned int) (~3); |
309 |
for (i = 0; i < 12; i++) |
310 |
{ |
311 |
result[result_index++] = string[string_index] & 0xff; |
312 |
result[result_index++] = string[string_index++] >> 8; |
313 |
} |
314 |
break; |
315 |
} |
316 |
default: |
317 |
{ |
318 |
if (font->handle[(unsigned int) string[string_index]] != current_font) |
319 |
{ |
320 |
if (ptable != NULL) |
321 |
table[result_index + 1] = table[result_index + 2] = string_index; |
322 |
|
323 |
result[result_index++] = 26; |
324 |
result[result_index++] = current_font = font->handle[(unsigned int) string[string_index]]; |
325 |
|
326 |
/* #ifdef DEBUG */ |
327 |
/* printf("{%i} ", current_font); */ |
328 |
/* #endif */ |
329 |
} |
330 |
result[result_index++] = font->character[(unsigned int) string[string_index++]]; |
331 |
|
332 |
/* #ifdef DEBUG */ |
333 |
/* printf("[0x%x] ", result[result_index - 1]); */ |
334 |
/* #endif */ |
335 |
|
336 |
break; |
337 |
} |
338 |
} |
339 |
} |
340 |
result[result_index] = 0; |
341 |
|
342 |
*presult = result; |
343 |
if (ptable != NULL) |
344 |
{ |
345 |
table[result_index] = string_index; |
346 |
*ptable = table; |
347 |
} |
348 |
|
349 |
/* #ifdef DEBUG */ |
350 |
/* printf("\n"); */ |
351 |
|
352 |
/* for (result_index = 0; result[result_index] != 0; result_index++) */ |
353 |
/* printf("0x%x ", result[result_index]); */ |
354 |
/* printf("\n"); */ |
355 |
/* #endif */ |
356 |
|
357 |
return NULL; |
358 |
} |
359 |
|
360 |
|
361 |
/* |
362 |
* UFont_ScanString |
363 |
* |
364 |
* => font handle as returned by UFont_FindFont |
365 |
* string is unicode (2 byte characters), see UFont_Convert |
366 |
* split length is index in string, not pointer |
367 |
* other parameters as Font_ScanString |
368 |
* |
369 |
* <= as Font_ScanString |
370 |
*/ |
371 |
|
372 |
extern os_error * |
373 |
xufont_scan_string(ufont_f font, |
374 |
wchar_t const *string, |
375 |
font_string_flags flags, |
376 |
int x, |
377 |
int y, |
378 |
font_scan_block const *block, |
379 |
os_trfm const *trfm, |
380 |
unsigned int length, |
381 |
int *split_length, |
382 |
int *x_out, |
383 |
int *y_out, |
384 |
int *length_out) |
385 |
{ |
386 |
char *result; |
387 |
char *split_point; |
388 |
unsigned int *table; |
389 |
os_error *error; |
390 |
|
391 |
if ((flags & font_GIVEN_LENGTH) == 0) length = 0x7fffffff; |
392 |
|
393 |
error = xufont_convert(font, string, length, &result, &table); |
394 |
if (error != NULL) return error; |
395 |
|
396 |
/* #ifdef DEBUG */ |
397 |
/* { */ |
398 |
/* unsigned int i; */ |
399 |
/* for (i = 0; i < 200; i++) */ |
400 |
/* printf("%i ", table[i]); */ |
401 |
/* printf("\n"); */ |
402 |
/* } */ |
403 |
/* #endif */ |
404 |
|
405 |
error = xfont_scan_string((font_f) result[1], result, |
406 |
(flags & (~font_GIVEN_LENGTH)) | font_GIVEN_FONT, |
407 |
x, y, block, trfm, 0, |
408 |
&split_point, x_out, y_out, length_out); |
409 |
if (error != NULL) { free(result); return error; } |
410 |
|
411 |
if (split_length != NULL) |
412 |
*split_length = table[split_point - result]; |
413 |
|
414 |
free(result); |
415 |
free(table); |
416 |
|
417 |
return NULL; |
418 |
} |