PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
fsfont.c
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include <draw.h>
7#include <draw3d.h>
8
9#include <font.h>
10
11static prim_t charprim =
12{
13 PRIM_SPRITE, PRIM_SHADE_FLAT, DRAW_ENABLE,
14 DRAW_DISABLE, DRAW_ENABLE, DRAW_DISABLE,
15 PRIM_MAP_UV, PRIM_UNFIXED
16};
17
18#define TAB '\t'
19#define NEWLINE '\n'
20#define SPACE ' '
21
22fsfont_t *fontstudio_init( int char_height)
23{
24
25 fsfont_t *font;
26
27 font = (fsfont_t*)malloc(sizeof(fsfont_t));
28
29 font->height = char_height;
30 font->scale = 1.0f;
31
32 return font;
33
34}
35
36void fontstudio_free(fsfont_t *font)
37{
38
39 if (font->charmap != NULL)
40 {
41 free(font->charmap);
42 }
43
44 if (font->chardata != NULL)
45 {
46 free(font->chardata);
47 }
48
49 free(font);
50
51}
52
53char *fontstudio_load_ini(const char *path)
54{
55
56 FILE *file;
57
58 char *ini;
59 int size;
60
61 file = fopen(path, "r");
62
63 if (file == NULL)
64 {
65
66 printf("Error opening %s.\n", path);
67 return NULL;
68
69 }
70
71 fseek(file, 0, SEEK_END);
72 size = ftell(file);
73 fseek(file, 0, SEEK_SET);
74
75 ini = (char *)malloc(size);
76
77 if (ini == NULL)
78 {
79 printf("Error allocated %d bytes of memory.\n", size);
80 fclose(file);
81 return NULL;
82 }
83
84 fread(ini, size, 1, file);
85 fclose(file);
86
87 return ini;
88
89}
90
91int fontstudio_parse_ini(fsfont_t *font, char *ini, float tex_width, float tex_height)
92{
93
94 int i;
95
96 char *temp0;
97 char *temp1;
98
99 temp0 = ini;
100
101 temp1 = strtok(temp0,"=");
102 if (temp1 == NULL)
103 {
104 printf("Error parsing number of chars.\n");
105 return -1;
106 }
107 temp0 += strlen(temp1)+1;
108
109 font->totalchars = (int)strtol(temp0,NULL,10);
110
111 temp1 = strtok(temp0,"=");
112 if (temp1 == NULL)
113 {
114 printf("Error parsing space width.\n");
115 return -1;
116 }
117 temp0 += strlen(temp1)+1;
118
119 font->spacewidth = (int)strtol(temp0,NULL,10);
120
121 font->charmap = (unsigned short*)malloc(sizeof(short)*font->totalchars);
122
123 if (font->charmap == NULL)
124 {
125
126 //131 kilobytes of memory
127 printf("Error allocated %d bytes of memory.\n", sizeof(short)*font->totalchars);
128 return -1;
129
130 }
131
132 // Clear memory
133 memset(font->charmap,0,sizeof(short)*font->totalchars);
134
135 font->chardata = (inidata_t*)malloc(sizeof(inidata_t)*font->totalchars);
136
137 if (font->chardata == NULL)
138 {
139
140 printf("Error allocating %d bytes of memory.\n", sizeof(inidata_t)*font->totalchars);
141 free(font->charmap);
142 return -1;
143
144 }
145
146 // Clear memory
147 memset(font->chardata,0,sizeof(inidata_t)*font->totalchars);
148
149 for (i = 0; i < font->totalchars; i++)
150 {
151
152 temp1 = strtok(temp0,"=");
153 if (temp1 == NULL)
154 {
155
156 printf("Error parsing Char for char %d.\n", i);
157 free(font->charmap);
158 free(font->chardata);
159 return -1;
160
161 }
162 temp0 += strlen(temp1)+1;
163 font->charmap[i] = (int)strtol(temp0,NULL,10);
164
165 temp1 = strtok(temp0,"=");
166 if (temp1 == NULL)
167 {
168
169 printf("Error parsing A for char %d.\n", i);
170 free(font->charmap);
171 free(font->chardata);
172 return -1;
173
174 }
175 temp0 += strlen(temp1)+1;
176 font->chardata[i].A = (int)strtol(temp0,NULL,10);
177
178 temp1 = strtok(temp0,"=");
179 if (temp1 == NULL)
180 {
181
182 printf("Error parsing B for char %d.\n", i);
183 free(font->charmap);
184 free(font->chardata);
185 return -1;
186
187 }
188 temp0 += strlen(temp1)+1;
189 font->chardata[i].B = (int)strtol(temp0,NULL,10);
190
191 temp1 = strtok(temp0,"=");
192 if (temp1 == NULL)
193 {
194
195 printf("Error parsing C for char %d.\n", i);
196 free(font->charmap);
197 free(font->chardata);
198 return -1;
199
200 }
201 temp0 += strlen(temp1)+1;
202 font->chardata[i].C = (int)strtol(temp0,NULL,10);
203
204 temp1 = strtok(temp0,"=");
205 if (temp1 == NULL)
206 {
207
208 printf("Error parsing ox for char %d.\n", i);
209 free(font->charmap);
210 free(font->chardata);
211 return -1;
212
213 }
214 temp0 += strlen(temp1)+1;
215 font->chardata[i].ox = (int)strtol(temp0,NULL,10);
216
217 temp1 = strtok(temp0,"=");
218 if (temp1 == NULL)
219 {
220
221 printf("Error parsing oy for char %d.\n", i);
222 free(font->charmap);
223 free(font->chardata);
224 return -1;
225
226 }
227 temp0 += strlen(temp1)+1;
228 font->chardata[i].oy = (int)strtol(temp0,NULL,10);
229
230 temp1 = strtok(temp0,"=");
231 if (temp1 == NULL)
232 {
233
234 printf("Error parsing Wid for char %d.\n", i);
235 free(font->charmap);
236 free(font->chardata);
237 return -1;
238
239 }
240 temp0 += strlen(temp1)+1;
241 font->chardata[i].width = (int)strtol(temp0,NULL,10);
242
243 temp1 = strtok(temp0,"=");
244 if (temp1 == NULL)
245 {
246
247 printf("Error parsing Hgt for char %d.\n", i);
248 free(font->charmap);
249 free(font->chardata);
250 return -1;
251
252 }
253 temp0 += strlen(temp1)+1;
254 font->chardata[i].height = (int)strtol(temp0,NULL,10);
255
256 temp1 = strtok(temp0,"=");
257 if (temp1 == NULL)
258 {
259
260 printf("Error parsing X1 for char %d.\n", i);
261 free(font->charmap);
262 free(font->chardata);
263 return -1;
264
265 }
266 temp0 += strlen(temp1)+1;
267 font->chardata[i].u1 = ftoi4(((float)(strtod(temp0,NULL) * tex_width)));
268
269 temp1 = strtok(temp0,"=");
270 if (temp1 == NULL)
271 {
272
273 printf("Error parsing Y1 for char %d.\n", i);
274 free(font->charmap);
275 free(font->chardata);
276 return -1;
277
278 }
279 temp0 += strlen(temp1)+1;
280 font->chardata[i].v1 = ftoi4(((float)(strtod(temp0,NULL) * tex_height)));
281
282 temp1 = strtok(temp0,"=");
283 if (temp1 == NULL)
284 {
285
286 printf("Error parsing X2 for char %d.\n", i);
287 free(font->charmap);
288 free(font->chardata);
289 return -1;
290
291 }
292 temp0 += strlen(temp1)+1;
293 font->chardata[i].u2 = ftoi4(((float)(strtod(temp0,NULL) * tex_width)));
294
295 temp1 = strtok(temp0,"=");
296 if (temp1 == NULL)
297 {
298
299 printf("Error parsing Y2 for char %d.\n", i);
300 free(font->charmap);
301 free(font->chardata);
302 return -1;
303
304 }
305 temp0 += strlen(temp1)+1;
306 font->chardata[i].v2 = ftoi4(((float)(strtod(temp0,NULL) * tex_height)));
307 }
308
309 return 0;
310
311}
312
314{
315 if(font->charmap != NULL)
316 {
317 free(font->charmap);
318 font->charmap = NULL;
319 }
320 if(font->chardata != NULL)
321 {
322 free(font->chardata);
323 font->chardata = NULL;
324 }
325}
326
327// Decode unicode byte sequences into unicode a single numerical character U+XXXX
328// Returns the number of actual unicode characters
329int decode_unicode(const unsigned char *in, unsigned short *out)
330{
331
332 // 0x00 - 0x7f - single byte ascii
333 // 0x80 - 0xbf - continuation bytes
334 // 0xC2 - 0xDF - start of 2 byte sequence (1 byte after)
335 // first_byte & 0x1F << 6 + second_byte & 0x3f = index
336 // 0xE0 - 0xEF - start of 3 byte sequence (2 bytes after)
337 // first_byte & 0xF << 12 + second_byte & 0x3f << 6 + third_byte & 0x3f
338 // 0xF0 - 0xF4 - start of 4 byte sequence (3 bytes after)
339 // first_byte & 0x7 << 18 + second_byte & 0x3f << 12 + third_byte & 0x3f << 6 + fourth_byte & 0x3f
340
341 int i;
342
343 int j = 0;
344
345 int length = strlen((const char *)in);
346
347 for (i = 0; i < length; i++)
348 {
349 if (in[i] < 0x80)
350 {
351 out[j++] = in[i];
352 }
353
354 if (in[i] > 0xC1)
355 {
356 if (in[i] < 0xE0)
357 {
358 out[j] = (in[i++] & 0x1f)<<6;
359 out[j++] += (in[i] & 0x3f);
360 }
361 else if (in[i] < 0xF0)
362 {
363 out[j] = (in[i++] & 0xF)<<12;
364 out[j] += (in[i++] & 0x3f)<<6;
365 out[j++] += (in[i] & 0x3f);
366 }
367 else if (in[i] < 0xF5)
368 {
369 // Supports only up to U+FFFF
370 i+=3;
371 }
372 }
373 }
374
375 return j;
376
377}
378
379unsigned short get_char(unsigned short c, fsfont_t *font)
380{
381
382 unsigned short i;
383
384 for (i = 0; i < font->totalchars; i++)
385 {
386
387 if (c == font->charmap[i])
388 {
389 return i;
390
391 }
392
393 }
394
395 // Use unknown <?> character if character isn't in character map
396 return 0xFFFD;
397
398}
399
400void convert_to_index(unsigned short *in, int num, fsfont_t *font)
401{
402
403 int i;
404
405 for (i = 0; i < num; i++)
406 {
407 // These characters aren't included in the FontStudio index, I think
408 while (in[i] == '\n' || in[i] == '\t' || in[i] == ' ')
409 {
410 /*
411 if (in[i] == '\n')
412 {
413 in[i] = NEWLINE;
414 }
415 if (in[i] == '\t')
416 {
417 in[i] = TAB;
418 }
419 if (in[i] == ' ')
420 {
421 in[i] = SPACE;
422 }
423 */
424 i++;
425 }
426
427 in[i] = get_char(in[i],font);
428 }
429
430}
431
432#define DRAW_ST_REGLIST \
433 ((u64)GIF_REG_ST) << 0 | \
434 ((u64)GIF_REG_XYZ2) << 4
435
436qword_t *draw_fontstudio_char(qword_t *q, unsigned int c, vertex_t *v0, fsfont_t *font)
437{
438
439 int x,y;
440
441 x = ftoi4(v0->x);
442 y = ftoi4(v0->y);
443
444 q->dw[0] = GIF_SET_UV(font->chardata[c].u1,font->chardata[c].v1);
445 q->dw[1] = GIF_SET_XYZ(x + 32759,y + 32759,v0->z);
446 q++;
447
448 q->dw[0] = GIF_SET_UV(font->chardata[c].u2, font->chardata[c].v2);
449 q->dw[1] = GIF_SET_XYZ(x + (int)((font->chardata[c].width*font->scale)*16.0f) + 32777,y + (int)((font->chardata[c].height*font->scale)*16.0f) + 32777,v0->z);
450 q++;
451
452 return q;
453
454}
455
456qword_t *fontstudio_print_string(qword_t *q, int context, const unsigned char *str, int alignment, const vertex_t *v0, color_t *c0, fsfont_t *font)
457{
458
459 int i = 0,j;
460
461 unsigned short curchar = 0;
462
463 int length;
464
465 vertex_t v_pos = *v0;
466
467 unsigned short utf8[2048];
468
469 memset(utf8,0,sizeof(short)*2048);
470
471 // Decodes the encoded string into unicode numbers U+xxxx
472 // length is the number of characters in the string
473 length = decode_unicode(str, utf8);
474
475 //for (i = 0; i < length; i++)
476 //{
477 // printf("utf8[%d] = %d\n", i, utf8[i]);
478 //}
479
480 // Converts the unicode numbers into the index numbers
481 // used by the FontStudio ini
482 convert_to_index(utf8,length,font);
483
484 //for (i = 0; i < length; i++)
485 //{
486 // printf("utf8[%d] = %d\n", i, utf8[i]);
487 //}
488
489 float line_num[100];
490 int line = 0;
491
492 float x_orig[100];
493 x_orig[0] = 0;
494
495 // line_num is used to keep track of number of characters per line
496 line_num[0] = 0;
497
498 switch (alignment)
499 {
500 default:
501 case LEFT_ALIGN:
502 {
503 for (i = 0; i < length; i++)
504 {
505
506 while (utf8[i] == TAB || utf8[i] == NEWLINE)
507 {
508 if (utf8[i] == NEWLINE)
509 {
510 x_orig[line] = v_pos.x;
511 line++;
512 line_num[line] = 0;
513 }
514 i++;
515 }
516
517 if (i == length-1)
518 {
519 x_orig[line] = v_pos.x;
520 line++;
521 }
522
523 }
524 break;
525
526 }
527 case RIGHT_ALIGN:
528 {
529 for (i = 0; i < length; i++)
530 {
531
532 while (utf8[i] == TAB || utf8[i] == NEWLINE || utf8[i] == SPACE)
533 {
534 if (utf8[i] == NEWLINE)
535 {
536 x_orig[line] = v_pos.x - line_num[line]*font->scale;
537 line++;
538 line_num[line] = 0;
539 }
540 if (utf8[i] == TAB)
541 {
542 line_num[line] += font->spacewidth * 4;
543 }
544 if (utf8[i] == SPACE)
545 {
546 line_num[line] += font->spacewidth;
547 }
548 i++;
549 }
550
551 curchar = utf8[i];
552 line_num[line] += font->chardata[curchar].A + font->chardata[curchar].B + font->chardata[curchar].C;
553
554 if (i == length-1)
555 {
556 x_orig[line] = v_pos.x - line_num[line]*font->scale;
557 line++;
558 }
559
560 }
561 break;
562
563 }
564 case CENTER_ALIGN:
565 {
566 for (i = 0; i < length; i++)
567 {
568
569 while (utf8[i] == TAB || utf8[i] == NEWLINE || utf8[i] == SPACE)
570 {
571 if (utf8[i] == NEWLINE)
572 {
573 x_orig[line] = v_pos.x - (line_num[line]*font->scale)/2.0f;
574 line++;
575 line_num[line] = 0;
576 }
577 if (utf8[i] == TAB)
578 {
579 line_num[line] += font->spacewidth * 4;
580 }
581 if (utf8[i] == SPACE)
582 {
583 line_num[line] += font->spacewidth;
584 }
585 i++;
586 }
587
588 curchar = utf8[i];
589 line_num[line] += font->chardata[curchar].A + font->chardata[curchar].B + font->chardata[curchar].C;
590
591 if (i == length-1)
592 {
593 x_orig[line] = v_pos.x - (line_num[line]*font->scale)/2.0f;
594 line++;
595 }
596
597 }
598 break;
599
600 }
601
602 };
603
604 line = 0;
605 v_pos.x = x_orig[0];
606
607 q = draw_prim_start(q,context,&charprim,c0);
608
609 for (j = 0; j < length; j++)
610 {
611
612 while(utf8[j] == NEWLINE || utf8[j] == TAB || utf8[j] == SPACE)
613 {
614 if (utf8[j] == NEWLINE)
615 {
616 line++;
617 v_pos.y += font->height*font->scale;
618 v_pos.x = x_orig[line];
619 }
620 if (utf8[j] == TAB)
621 {
622 v_pos.x += font->spacewidth*font->scale * 4.0f;
623 }
624 if (utf8[j] == SPACE)
625 {
626 v_pos.x += font->spacewidth*font->scale;
627 }
628 j++;
629 }
630
631 v_pos.x += (font->chardata[utf8[j]].A*font->scale);
632
633 q = draw_fontstudio_char(q,utf8[j],&v_pos,font);
634
635 v_pos.x += (font->chardata[utf8[j]].B*font->scale) + (font->chardata[utf8[j]].C*font->scale);
636
637
638 }
639
640 q = draw_prim_end(q,2,DRAW_UV_REGLIST);
641
642 return q;
643}
644
qword_t * draw_prim_end(qword_t *q, int nreg, u64 reglist)
Definition draw3d.c:33
qword_t * draw_prim_start(qword_t *q, int context, prim_t *prim, color_t *color)
Definition draw3d.c:11
#define PRIM_UNFIXED
#define PRIM_SHADE_FLAT
int fontstudio_parse_ini(fsfont_t *font, char *ini, float tex_width, float tex_height)
Definition fsfont.c:91
qword_t * fontstudio_print_string(qword_t *q, int context, const unsigned char *string, int alignment, const vertex_t *v0, color_t *c0, fsfont_t *font)
Definition fsfont.c:456
fsfont_t * fontstudio_init(int height)
Definition fsfont.c:22
void fontstudio_unload_ini(fsfont_t *font)
Definition fsfont.c:313
#define LEFT_ALIGN
Definition font.h:60
char * fontstudio_load_ini(const char *path)
Definition fsfont.c:53