1 /*---------------------------------------------------------------------------*
2 Project: font demo program
3 File: fntdemo1.c
4
5 Copyright 2006 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: fntdemo1.c,v $
14 Revision 1.1 2006/10/18 02:52:17 nishida_yasunari
15 Initial check in.
16
17 $NoKeywords: $
18 *---------------------------------------------------------------------------*/
19
20 #include <demo.h>
21 #include <revolution/sc.h>
22 #include <revolution/fnt.h>
23
24 /*-----------------------------------------------------------------------------
25 Constants
26 -----------------------------------------------------------------------------*/
27 static const char* FONT_FILE_PATH_1 = "/fonts/wbf1.brfna";
28 static const char* FONT_FILE_PATH_2 = "/fonts/wbf2.brfna";
29
30 static const int TEXTURE_COODINATE_FRACTION_BITS = 15;
31 static const u32 TEXTURE_COODINATE_ONE = (1 << TEXTURE_COODINATE_FRACTION_BITS);
32
33 /*-----------------------------------------------------------------------------
34 Name: SetupTextCamera
35
36 Description: Sets up text camera.
37
38 Arguments: None.
39
40 Returns: None.
41 -----------------------------------------------------------------------------*/
SetupTextCamera(void)42 static void SetupTextCamera( void )
43 {
44 {
45 Mtx44 p;
46 f32 znear = 0.0F;
47 f32 zfar = 1.0F;
48 f32 t = 0;
49 f32 b = 480;
50 f32 l = 0;
51 f32 r = 640;
52
53 MTXOrtho(p, t, b, l, r, znear, zfar);
54 GXSetProjection(p, GX_ORTHOGRAPHIC);
55 }
56
57 {
58 Mtx mv;
59 MTXIdentity(mv);
60 GXLoadPosMtxImm(mv, GX_PNMTX0);
61 GXSetCurrentMtx(GX_PNMTX0);
62 }
63 }
64
65 /*-----------------------------------------------------------------------------
66 Name: SetupTextGX
67
68 Description: Sets up text GX.
69
70 Arguments: None.
71
72 Returns: None.
73 -----------------------------------------------------------------------------*/
SetupTextGX(void)74 static void SetupTextGX( void )
75 {
76 GXSetNumChans(1);
77 GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
78 GXSetChanCtrl(GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
79 GXSetNumTexGens(1);
80 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
81 GXSetNumTevStages(1);
82 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
83 GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
84 GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO);
85 GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
86 GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
87 GXSetNumIndStages(0);
88 GXSetTevDirect(GX_TEVSTAGE0);
89 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
90
91 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS , GX_POS_XYZ, GX_F32, 0);
92 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST , GX_U16, TEXTURE_COODINATE_FRACTION_BITS);
93 GXClearVtxDesc();
94 GXSetVtxDesc(GX_VA_POS , GX_DIRECT);
95 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
96
97 GXSetChanMatColor(GX_COLOR0A0, (GXColor){255, 255, 255, 255 });
98 }
99
100 /*-----------------------------------------------------------------------------
101 Name: DrawChar
102
103 Description: Draws one character.
104
105 Arguments: x, y, z Coordinates
106 tex Pointer to a font texture
107 scaleX Horizontal scale
108 scaleY Vertical scale
109 lastImage Pointer to a pointer to the texture image that was last loaded
110
111 Returns: None.
112 -----------------------------------------------------------------------------*/
DrawChar(f32 x,f32 y,f32 z,const FNTTexture * tex,f32 scaleX,f32 scaleY,void ** lastImage)113 static void DrawChar(
114 f32 x, f32 y, f32 z,
115 const FNTTexture* tex,
116 f32 scaleX, f32 scaleY,
117 void** lastImage )
118 {
119 f32 posLeft = x + tex->left * scaleX;
120 f32 posTop = y;
121 f32 posRight = posLeft + tex->glyphWidth * scaleX;
122 f32 posBottom = posTop + tex->charHeight * scaleY;
123
124 u16 texLeft = (u16)(tex->cellX
125 * TEXTURE_COODINATE_ONE / tex->texWidth);
126 u16 texTop = (u16)(tex->cellY
127 * TEXTURE_COODINATE_ONE / tex->texHeight);
128 u16 texRight = (u16)((tex->cellX + tex->glyphWidth)
129 * TEXTURE_COODINATE_ONE / tex->texWidth);
130 u16 texBottom = (u16)((tex->cellY + tex->charHeight)
131 * TEXTURE_COODINATE_ONE / tex->texHeight);
132
133 if (tex->image != *lastImage)
134 {
135 GXTexObj tobj;
136 GXTexFilter filter = GX_LINEAR;
137 GXInitTexObj(&tobj, tex->image, tex->texWidth, tex->texHeight,
138 tex->texFormat, GX_CLAMP, GX_CLAMP, GX_FALSE);
139 GXInitTexObjLOD(&tobj, filter, filter, 0, 0, 0,
140 GX_DISABLE, GX_DISABLE, GX_ANISO_1);
141 GXLoadTexObj(&tobj, GX_TEXMAP0);
142 *lastImage = tex->image;
143 }
144
145 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
146 {
147 GXPosition3f32(posLeft, posTop, z);
148 GXTexCoord2u16(texLeft, texTop);
149
150 GXPosition3f32(posRight, posTop, z);
151 GXTexCoord2u16(texRight, texTop);
152
153 GXPosition3f32(posRight, posBottom, z);
154 GXTexCoord2u16(texRight, texBottom);
155
156 GXPosition3f32(posLeft, posBottom, z);
157 GXTexCoord2u16(texLeft, texBottom);
158 }
159 GXEnd();
160 }
161
162 /*-----------------------------------------------------------------------------
163 Name: DrawString
164
165 Description: Draws a string.
166
167 Arguments: font Pointer to font header
168 x, y, z Coordinates
169 string String
170 scaleX Horizontal scale
171 scaleY Vertical scale
172 fixedWidth fixed width (proportional if 0 is specified)
173 lastImage Pointer to a pointer to the texture image that was last loaded
174
175 Returns: Total string width in pixels.
176 -----------------------------------------------------------------------------*/
DrawString(const FNTHeader * font,f32 x,f32 y,f32 z,const char * string,f32 scaleX,f32 scaleY,f32 fixedWidth,void ** lastImage)177 static f32 DrawString(
178 const FNTHeader* font,
179 f32 x, f32 y, f32 z,
180 const char* string,
181 f32 scaleX, f32 scaleY,
182 f32 fixedWidth,
183 void** lastImage )
184 {
185 f32 startX = x;
186 BOOL utf16 = (FNTGetEncoding(font) == FNT_ENCODING_UTF16);
187
188 while (*string || (utf16 && *(string + 1)))
189 {
190 FNTTexture tex;
191 f32 scaleWd, margin;
192 string = FNTGetTexture(font, string, &tex);
193 scaleWd = tex.charWidth * scaleX;
194 margin = (fixedWidth > 0.0F) ? (fixedWidth - scaleWd) / 2.0F : 0.0F;
195 DrawChar(x + margin, y, z, &tex, scaleX, scaleY, lastImage);
196 x += (fixedWidth > 0.0F) ? fixedWidth : scaleWd;
197 }
198
199 return (x - startX);
200 }
201
202 /*-----------------------------------------------------------------------------
203 Name: GetStringWidth
204
205 Description: Gets string width.
206
207 Arguments: font Pointer to font header
208 string String
209 scaleX Horizontal scale
210
211 Returns: Total string width in pixels.
212 -----------------------------------------------------------------------------*/
GetStringWidth(const FNTHeader * font,const char * string,f32 scaleX)213 static f32 GetStringWidth(
214 const FNTHeader* font,
215 const char* string,
216 f32 scaleX )
217 {
218 f32 totalWidth;
219 BOOL utf16 = (FNTGetEncoding(font) == FNT_ENCODING_UTF16);
220
221 totalWidth = 0.0F;
222 while (*string || (utf16 && *(string + 1)))
223 {
224 s32 width;
225 string = FNTGetWidth(font, string, &width);
226 totalWidth += width * scaleX;
227 }
228
229 return totalWidth;
230 }
231
232 /*-----------------------------------------------------------------------------
233 Name: DrawSample
234
235 Description: Draws a sample.
236
237 Arguments: font Pointer to font header
238 x, y, z Coordinates
239
240 Returns: Y coordinate of next line.
241 -----------------------------------------------------------------------------*/
DrawSample(const FNTHeader * font,f32 x,f32 y,f32 z)242 static f32 DrawSample(
243 const FNTHeader* font,
244 f32 x, f32 y, f32 z )
245 {
246 f32 scaleX = 1.F;
247 f32 scaleY = 1.F;
248 FNTMetrics metrics;
249 void* lastImage = NULL;
250 f32 drawW, getW;
251 const char* str0 = " !\"#$%&'()*+,-./0123456789:;<=>?";
252 const char* str1 = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
253 const char* str2 = "`abcdefghijklmnopqrstuvwxyz{|}~";
254 const char* str3 = "Wii";
255 const char* str4 = "\xca\xdd\xb6\xb8\x20\x82\xa9\x82\xc8\x20\x8a\xbf\x8e\x9a"; // Half-width Kana Kanji
256 f32 startX = x;
257
258 // Get metrics
259 FNTGetMetrics(font, &metrics);
260
261 // Draw proportional string
262 drawW = DrawString(font, x, y, z, str0, scaleX, scaleY, 0.F, &lastImage);
263 y += metrics.leading * scaleY;
264 drawW = DrawString(font, x, y, z, str1, scaleX, scaleY, 0.F, &lastImage);
265 y += metrics.leading * scaleY;
266 drawW = DrawString(font, x, y, z, str2, scaleX, scaleY, 0.F, &lastImage);
267 y += metrics.leading * scaleY;
268
269 scaleX = scaleY = 1.5F; // Change scale
270 drawW = DrawString(font, x, y, z, str3, scaleX, scaleY, 0.F, &lastImage);
271 x += drawW + metrics.width * scaleX;
272
273 // Get width test
274 getW = GetStringWidth(font, str3, scaleX);
275 OSReport("Width Test: %f %f\n", drawW, getW);
276
277 // Draw fixed-width string
278 drawW = DrawString(font, x, y, z, str3, scaleX, scaleY,
279 metrics.width * scaleX, &lastImage);
280 x = startX;
281 y += metrics.leading * scaleY;
282 scaleX = scaleY = 1.F; // Restore scale
283
284 // Draw SJIS string
285 if (FNTGetEncoding(font) == FNT_ENCODING_SJIS)
286 {
287 drawW = DrawString(font, x, y, z, str4, scaleX, scaleY, 0.F, &lastImage);
288 y += metrics.leading * scaleY;
289 }
290
291 return y;
292 }
293
294 /*---------------------------------------------------------------------------*
295 Name: ReadFileAll
296
297 Description: Reads an entire file.
298
299 Arguments: ppBuffer Pointer to a pointer to the read buffer
300 filePath File path
301
302 Returns: TRUE if successful, FALSE otherwise.
303 *---------------------------------------------------------------------------*/
ReadFileAll(void ** ppBuffer,const char * filePath)304 static BOOL ReadFileAll( void** ppBuffer, const char* filePath )
305 {
306 DVDFileInfo fi;
307 u32 fileSize;
308 u32 readBufferSize;
309 s32 readSize;
310
311 if (!DVDOpen(filePath, &fi))
312 {
313 return FALSE;
314 }
315
316 fileSize = DVDGetLength(&fi);
317 if (fileSize == 0)
318 {
319 return FALSE;
320 }
321
322 readBufferSize = OSRoundUp32B(fileSize);
323 *ppBuffer = OSAlloc(readBufferSize);
324
325 readSize = DVDRead(&fi, *ppBuffer, (s32)readBufferSize, 0);
326 DVDClose(&fi);
327 if (readSize != readBufferSize)
328 {
329 return FALSE;
330 }
331
332 return TRUE;
333 }
334
335 /*-----------------------------------------------------------------------------
336 Name: InitFont
337
338 Description: Reads a font file entirely to memory and constructs the font data.
339
340 Arguments: ppFont Pointer to a pointer to the font header
341 filePath Font file path
342
343 Returns: TRUE if successful, FALSE otherwise.
344 -----------------------------------------------------------------------------*/
InitFont(FNTHeader ** ppFont,const char * filePath)345 static BOOL InitFont( FNTHeader** ppFont, const char* filePath )
346 {
347 void* readBuffer;
348 u32 dataSize;
349
350 // Init memory
351 readBuffer = NULL;
352 *ppFont = NULL;
353
354 // Read the entire font file
355 if (!ReadFileAll(&readBuffer, filePath))
356 {
357 OSReport("Failed to read file: %s\n", filePath);
358 goto ErrorHandle;
359 }
360
361 // Get font data size & alloc font data buffer
362 dataSize = FNTGetDataSize(readBuffer);
363 if (dataSize == 0)
364 {
365 OSReport("Failed to get font data size: %s\n", filePath);
366 goto ErrorHandle;
367 }
368 *ppFont = (FNTHeader*)OSAlloc(dataSize);
369
370 // construct
371 OSReport("Constructing: %s: %7d\n", filePath, dataSize);
372 if (!FNTConstruct(*ppFont, readBuffer))
373 {
374 OSReport("Failed to construct font: %s\n", filePath);
375 goto ErrorHandle;
376 }
377
378 // Free memory
379 OSFree(readBuffer);
380
381 return TRUE;
382
383 ErrorHandle:
384 if (readBuffer != NULL)
385 {
386 OSFree(readBuffer);
387 readBuffer = NULL;
388 }
389 if (*ppFont != NULL)
390 {
391 OSFree(*ppFont);
392 *ppFont = NULL;
393 }
394 return FALSE;
395 }
396
397 /*-----------------------------------------------------------------------------
398 Name: InitFontStreaming
399
400 Description: Construct the font while reading a font file sequentially.
401
402 Arguments: ppFont Pointer to a pointer to the font header
403 filePath Font file path
404
405 Returns: TRUE if successful, FALSE otherwise.
406 -----------------------------------------------------------------------------*/
InitFontStreaming(FNTHeader ** ppFont,const char * filePath)407 static BOOL InitFontStreaming( FNTHeader** ppFont, const char* filePath )
408 {
409 DVDFileInfo fi;
410 BOOL fileOpenFlag = FALSE;
411 u32 fileSize;
412 u32 readBufferSize;
413 void* readBuffer;
414 s32 readOfs;
415 s32 readSizeIn;
416 s32 readSize;
417 u32 dataSize;
418 FNTConstructResult ret;
419
420 // Init memory
421 readBuffer = NULL;
422 *ppFont = NULL;
423
424 // Open file
425 if (!DVDOpen(filePath, &fi))
426 {
427 OSReport("Failed to open file: %s\n", filePath);
428 goto ErrorHandle;
429 }
430 fileOpenFlag = TRUE;
431
432 // Get file length
433 fileSize = DVDGetLength(&fi);
434 if (fileSize == 0)
435 {
436 OSReport("Failed to get file length: %s\n", filePath);
437 goto ErrorHandle;
438 }
439
440 // Allocate the read buffer
441 readBufferSize = FNT_RESOURCE_HEADER_SIZE;
442 readBuffer = OSAlloc(readBufferSize);
443
444 // Read file header to get font data size
445 readSizeIn = (readBufferSize <= fileSize) ?
446 (s32)readBufferSize : (s32)OSRoundUp32B(fileSize);
447 readOfs = 0;
448 readSize = DVDRead(&fi, readBuffer, readSizeIn, readOfs);
449 readOfs += readSize;
450 if (readSize != readSizeIn)
451 {
452 OSReport("Failed to read file: %s\n", filePath);
453 goto ErrorHandle;
454 }
455
456 // Get font data size & alloc font data buffer
457 dataSize = FNTGetDataSize(readBuffer);
458 if (dataSize == 0)
459 {
460 OSReport("Failed to get font data size: %s\n", filePath);
461 goto ErrorHandle;
462 }
463 *ppFont = (FNTHeader*)OSAlloc(dataSize);
464
465 // init streaming construct
466 OSReport("Streaming constructing: %s: %7d\n", filePath, dataSize);
467 FNTInitStreamingConstruct(*ppFont, dataSize);
468
469 // Read a font file sequentially & construct
470 while (readSize > 0)
471 {
472 ret = FNTStreamingConstruct(*ppFont, readBuffer, (u32)readSize);
473 if (ret == FNT_CONSTRUCT_ERROR)
474 {
475 OSReport("Failed to construct font: %s\n", filePath);
476 goto ErrorHandle;
477 }
478 if (readOfs >= fileSize)
479 {
480 break;
481 }
482 readSizeIn = (readOfs + readBufferSize <= fileSize) ?
483 (s32)readBufferSize : (s32)OSRoundUp32B(fileSize - readOfs);
484 readSize = DVDRead(&fi, readBuffer, readSizeIn, readOfs);
485 readOfs += readSize;
486 if (readSize != readSizeIn)
487 {
488 OSReport("Failed to read file: %s\n", filePath);
489 goto ErrorHandle;
490 }
491 }
492 ASSERT(ret == FNT_CONSTRUCT_FINISH);
493
494 // Close file
495 DVDClose(&fi);
496
497 // Free memory
498 OSFree(readBuffer);
499
500 return TRUE;
501
502 ErrorHandle:
503 if (fileOpenFlag)
504 {
505 DVDClose(&fi);
506 }
507 if (readBuffer != NULL)
508 {
509 OSFree(readBuffer);
510 readBuffer = NULL;
511 }
512 if (*ppFont != NULL)
513 {
514 OSFree(*ppFont);
515 *ppFont = NULL;
516 }
517 return FALSE;
518 }
519
520 /*-----------------------------------------------------------------------------
521 Name: main
522
523 Description: Main function.
524
525 Arguments: None.
526
527 Returns: None.
528 -----------------------------------------------------------------------------*/
main(void)529 void main( void )
530 {
531 FNTHeader* font0;
532 FNTHeader* font1;
533 FNTEncoding encoding;
534 OSTime timeStart;
535
536 // init
537 DEMOInit(NULL);
538
539 // Init font
540 timeStart = OSGetTime();
541 if (!InitFont(&font0, FONT_FILE_PATH_1))
542 {
543 OSHalt("Stopped");
544 }
545 if (!InitFontStreaming(&font1, FONT_FILE_PATH_2))
546 {
547 OSHalt("Stopped");
548 }
549 OSReport("Initialization Time: %.3f [sec]\n", (OSGetTime() - timeStart) / (f32)OS_TIMER_CLOCK);
550
551 encoding = (SCGetLanguage() == SC_LANG_JAPANESE) ?
552 FNT_ENCODING_SJIS : FNT_ENCODING_CP1252;
553 FNTSetEncoding(font0, encoding);
554 FNTSetEncoding(font1, encoding);
555
556 // Draw
557 DEMOBeforeRender();
558 {
559 f32 curX = 16.F;
560 f32 curY = 20.F;
561 f32 curZ = 0.F;
562
563 SetupTextCamera();
564 SetupTextGX();
565
566 curY = DrawSample(font0, curX, curY, curZ);
567 curY += 16.F;
568 curY = DrawSample(font1, curX, curY, curZ);
569 }
570 DEMODoneRender();
571
572 // end
573 OSFree(font0);
574 OSFree(font1);
575 }
576