1 |
james |
16 |
/* 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 |
|
|
} |