ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
fsfont.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <malloc.h>
4 #include <string.h>
5 
6 #include <draw.h>
7 #include <draw3d.h>
8 
9 #include <font.h>
10 
11 static prim_t charprim =
12 {
16 };
17 
18 #define TAB '\t'
19 #define NEWLINE '\n'
20 #define SPACE ' '
21 
22 fsfont_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 
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 
53 char *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 
91 int 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
329 int 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] > 0xDF) && (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] > 0xEF) && (in[i] < 0xF5))
368  {
369  // Supports only up to U+FFFF
370  i+=3;
371  }
372  }
373  }
374 
375  return j;
376 
377 }
378 
379 unsigned 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 
400 void 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 
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 
456 qword_t *fontstudio_print_string(qword_t *q, int context, const unsigned char *str, int alignment, 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 
641 
642  return q;
643 }
644 
#define v0
Definition: as_reg_compat.h:35
qword_t * draw_prim_start(qword_t *q, int context, prim_t *prim, color_t *color)
Definition: draw3d.c:11
#define DRAW_UV_REGLIST
Definition: draw3d.h:24
qword_t * draw_prim_end(qword_t *q, int nreg, u64 reglist)
Definition: draw3d.c:33
u8 context
Definition: main.c:71
#define DRAW_ENABLE
Definition: draw.h:25
#define DRAW_DISABLE
Definition: draw.h:24
#define PRIM_UNFIXED
#define PRIM_MAP_UV
#define PRIM_SPRITE
#define PRIM_SHADE_FLAT
#define ftoi4(F)
Definition: draw_types.h:15
#define RIGHT_ALIGN
Definition: font.h:62
#define LEFT_ALIGN
Definition: font.h:60
#define CENTER_ALIGN
Definition: font.h:61
qword_t * fontstudio_print_string(qword_t *q, int context, const unsigned char *str, int alignment, vertex_t *v0, color_t *c0, fsfont_t *font)
Definition: fsfont.c:456
int decode_unicode(const unsigned char *in, unsigned short *out)
Definition: fsfont.c:329
int fontstudio_parse_ini(fsfont_t *font, char *ini, float tex_width, float tex_height)
Definition: fsfont.c:91
fsfont_t * fontstudio_init(int char_height)
Definition: fsfont.c:22
void fontstudio_free(fsfont_t *font)
Definition: fsfont.c:36
void convert_to_index(unsigned short *in, int num, fsfont_t *font)
Definition: fsfont.c:400
unsigned short get_char(unsigned short c, fsfont_t *font)
Definition: fsfont.c:379
#define SPACE
Definition: fsfont.c:20
void fontstudio_unload_ini(fsfont_t *font)
Definition: fsfont.c:313
#define NEWLINE
Definition: fsfont.c:19
qword_t * draw_fontstudio_char(qword_t *q, unsigned int c, vertex_t *v0, fsfont_t *font)
Definition: fsfont.c:436
static prim_t charprim
Definition: fsfont.c:11
#define TAB
Definition: fsfont.c:18
char * fontstudio_load_ini(const char *path)
Definition: fsfont.c:53
#define GIF_SET_XYZ(X, Y, Z)
Definition: gif_tags.h:103
#define GIF_SET_UV(U, V)
Definition: gif_tags.h:100
s32 x
Definition: libmouse.c:34
s32 y
Definition: libmouse.c:34
Definition: font.h:50
inidata_t * chardata
Definition: font.h:56
float scale
Definition: font.h:51
int totalchars
Definition: font.h:54
char height
Definition: font.h:52
unsigned short * charmap
Definition: font.h:53
int spacewidth
Definition: font.h:55
Definition: font.h:36
unsigned short v2
Definition: font.h:47
char width
Definition: font.h:42
char C
Definition: font.h:39
unsigned short u1
Definition: font.h:44
char A
Definition: font.h:37
char height
Definition: font.h:43
unsigned short u2
Definition: font.h:46
char oy
Definition: font.h:41
unsigned short v1
Definition: font.h:45
char B
Definition: font.h:38
char ox
Definition: font.h:40
float y
Definition: draw_types.h:53
float x
Definition: draw_types.h:52
#define NULL
Definition: tamtypes.h:91
u64 dw[2]
Definition: tamtypes.h:85