1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     TextWriter.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  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   $Rev: 47859 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "TextWriter.h"
17 
18 //////////////////////////////////////////////////////////////////////////////////////////
19 // Constant definitions
20 //////////////////////////////////////////////////////////////////////////////////////////
21 
22 // Number of displays
23 #define DISPLAY_NUM 2
24 
25 // Display number
26 #define DISPLAY_0 0
27 #define DISPLAY_1 1
28 
29 extern bit8 NNFONT_RECTDRAWERSHADER_BEGIN[];
30 extern bit8 NNFONT_RECTDRAWERSHADER_END[];
31 
32 namespace
33 {
34     // Initialization flag
35     bool s_isInitialized = false;
36     // unit matrix
37     nn::math::MTX34 s_mtxIdentify;
38     // Projection matrix
39     nn::math::MTX44 s_mtxProjection[DISPLAY_NUM];
40 
41     // Color buffer information
42     const nn::font::ColorBufferInfo s_colBufferInfos[DISPLAY_NUM] =
43     {
44         {NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT, PICA_DATA_DEPTH24_STENCIL8_EXT},
45         {NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT, PICA_DATA_DEPTH24_STENCIL8_EXT}
46     };
47 
48     // Render setting command
49     const u32 s_screenSettingCommands0[] =
50     {
51         // Viewport settings
52         NN_FONT_CMD_SET_VIEWPORT(0, 0, s_colBufferInfos[DISPLAY_0].width, s_colBufferInfos[DISPLAY_0].height),
53         // Disable scissoring
54         NN_FONT_CMD_SET_DISABLE_SCISSOR(s_colBufferInfos[DISPLAY_0]),
55         // Disable w Buffer / Set depth range / Disable polygon offset
56         NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(0, 0, 1, 0, s_colBufferInfos[DISPLAY_0])
57     };
58 
59     // Render setting command
60     const u32 s_screenSettingCommands1[] =
61     {
62         // Viewport settings
63         NN_FONT_CMD_SET_VIEWPORT(0, 0, s_colBufferInfos[DISPLAY_1].width, s_colBufferInfos[DISPLAY_1].height),
64         // Disable scissoring
65         NN_FONT_CMD_SET_DISABLE_SCISSOR(s_colBufferInfos[DISPLAY_1]),
66         // Disable w Buffer / Set depth range / Disable polygon offset
67         NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(0, 0, 1, 0, s_colBufferInfos[DISPLAY_1])
68     };
69 
70     // Initialization command
71     const u32 s_initCommands[] =
72     {
73         // Disable culling
74         NN_FONT_CMD_SET_CULL_FACE(NN_FONT_CMD_CULL_FACE_DISABLE),
75         // Disable stencil test
76         NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
77         // Disable depth test / Make all elements of the color buffer writable
78         NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(false, 0, true, true, true, true, true),
79         // Disable early depth test
80         NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false),
81         // Framebuffer access control
82         NN_FONT_CMD_SET_FBACCESS(true, true, false, false, false, false)
83     };
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////////////////
87 namespace scene
88 {
89 
90 // Constructor.
TextWriter()91 TextWriter::TextWriter()
92 {
93     m_pExpHeap      = NULL;
94     m_pStringBuffer = NULL;
95     m_textColor     = nn::util::Color8(255, 255, 255, 255);
96     m_pShaderBuffer = NULL;
97     m_targetDisplay = DISPLAY_0;
98 }
99 
100 // Destructor.
~TextWriter()101 TextWriter::~TextWriter()
102 {
103     Finalize();
104 }
105 
106 // Performs initialization.
Initialize(nn::fnd::ExpHeap * pExpHeap)107 void TextWriter::Initialize(nn::fnd::ExpHeap* pExpHeap)
108 {
109     // Perform shared font initialization
110     if (nn::pl::InitializeSharedFont().IsSuccess())
111     {
112         // Standby until shared font has completed loading
113         while (nn::pl::GetSharedFontLoadState() != nn::pl::SHARED_FONT_LOAD_STATE_LOADED)
114         {
115             nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1));
116         }
117 
118         // Confirm that shared font loading has not failed
119         if (nn::pl::GetSharedFontLoadState() == nn::pl::SHARED_FONT_LOAD_STATE_FAILED)
120         {
121             NN_PANIC("nn::pl::InitializeSharedFont() failed!\n");
122         }
123     }
124 
125     m_pExpHeap = pExpHeap;
126 
127     // Perform font initialization
128     if (!InitializeFont())
129     {
130         NN_PANIC("InitializeFont() failed!\n");
131     }
132 
133     // Perform shader initialization
134     if (!InitializeShader())
135     {
136         NN_PANIC("InitializeShader() failed!\n");
137     }
138 
139     // Allocate the string buffer
140     m_pStringBuffer = AllocateStringBuffer(512);
141 
142     if (!m_pStringBuffer)
143     {
144         NN_PANIC("Allocate string buffer failed!\n");
145     }
146 
147     // Initialization process that is fine to perform once during startup
148     if (!s_isInitialized)
149     {
150         // Create projection matrix
151         nn::math::MTX44OrthoPivot(&s_mtxProjection[DISPLAY_0], 0, NN_GX_DISPLAY0_HEIGHT, NN_GX_DISPLAY0_WIDTH, 0, 0, -1, nn::math::PIVOT_UPSIDE_TO_TOP);
152         nn::math::MTX44OrthoPivot(&s_mtxProjection[DISPLAY_1], 0, NN_GX_DISPLAY1_HEIGHT, NN_GX_DISPLAY1_WIDTH, 0, 0, -1, nn::math::PIVOT_UPSIDE_TO_TOP);
153 
154         // Create the unit matrix
155         nn::math::MTX34Identity(&s_mtxIdentify);
156 
157         s_isInitialized = true;
158     }
159 
160     // Set font object
161     m_writer.SetFont(&m_font);
162     // Since the initial font size is too big, make it smaller
163     m_writer.SetScale(0.6f);
164 }
165 
166 // Performs shutdown.
Finalize()167 void TextWriter::Finalize()
168 {
169     if (m_pExpHeap)
170     {
171         // Disable buffer for rendering
172         void* pDrawBuffer = m_font.SetDrawBuffer(NULL);
173 
174         if (pDrawBuffer)
175         {
176             m_pExpHeap->Free(pDrawBuffer);
177         }
178 
179         if (m_pShaderBuffer)
180         {
181             m_pExpHeap->Free(m_pShaderBuffer);
182         }
183         if (m_pStringBuffer)
184         {
185             m_pExpHeap->Free(m_pStringBuffer);
186         }
187 
188         // Initialize variables
189         m_pExpHeap      = NULL;
190         m_pStringBuffer = NULL;
191         m_pShaderBuffer = NULL;
192     }
193 }
194 
195 // Start rendering.
BeginRender(GLenum targetDisplay)196 void TextWriter::BeginRender(GLenum targetDisplay)
197 {
198     if (targetDisplay == NN_GX_DISPLAY0)
199     {
200         nngxAdd3DCommand(s_screenSettingCommands0, sizeof (s_screenSettingCommands0), true);
201         m_targetDisplay = DISPLAY_0;
202     }
203     else
204     {
205         nngxAdd3DCommand(s_screenSettingCommands1, sizeof (s_screenSettingCommands1), true);
206         m_targetDisplay = DISPLAY_1;
207     }
208 
209     nngxAdd3DCommand(s_initCommands, sizeof (s_initCommands), true);
210 
211     m_writer.SetDispStringBuffer(m_pStringBuffer);
212     m_writer.StartPrint();
213 }
214 
215 // End rendering.
EndRender()216 void TextWriter::EndRender()
217 {
218     m_writer.EndPrint();
219 
220     m_drawer.BuildTextCommand(&m_writer);
221     m_drawer.DrawBegin();
222     {
223         // Set projection matrix
224         m_drawer.SetProjectionMtx(s_mtxProjection[m_targetDisplay]);
225         // Initialize view matrix
226         m_drawer.SetViewMtxForText(s_mtxIdentify);
227 
228         m_writer.UseCommandBuffer();
229     }
230     m_drawer.DrawEnd();
231     nngxUpdateState(NN_GX_STATE_ALL);
232 }
233 
234 // Renders a character string.
Printf(f32 x,f32 y,const wchar_t * pFormat,...)235 void TextWriter::Printf(f32 x, f32 y, const wchar_t* pFormat, ...)
236 {
237     va_list pArgs;
238 
239     va_start(pArgs, pFormat);
240     {
241         m_writer.SetCursor(x, y);
242         m_writer.SetTextColor(m_textColor);
243         m_writer.VPrintf(pFormat, pArgs);
244     }
245     va_end(pArgs);
246 }
247 
248 // Renders a character string.
PutString(f32 x,f32 y,const wchar_t * pString)249 void TextWriter::PutString(f32 x, f32 y, const wchar_t* pString)
250 {
251     m_writer.SetCursor(x, y);
252     m_writer.SetTextColor(m_textColor);
253     m_writer.Print(pString);
254 }
255 
256 // Set the font color.
SetTextColor(u8 red,u8 green,u8 blue,u8 alpha)257 void TextWriter::SetTextColor(u8 red, u8 green, u8 blue, u8 alpha)
258 {
259     // Font color
260     m_textColor = nn::util::Color8(red, green, blue, alpha);
261 }
262 
263 // Get the font size.
GetFontSize()264 f32 TextWriter::GetFontSize()
265 {
266     return m_writer.GetFontHeight();
267 }
268 
269 // Sets the font size.
SetFontSize(f32 size)270 void TextWriter::SetFontSize(f32 size)
271 {
272     m_writer.SetFontSize(size);
273 }
274 
275 // Get the font scale.
276 
GetFontScale()277 f32 TextWriter::GetFontScale()
278 {
279     return m_writer.GetScaleH();
280 }
281 
282 // Set the font scale.
SetFontScale(f32 scale)283 void TextWriter::SetFontScale(f32 scale)
284 {
285     m_writer.SetScale(scale);
286 }
287 
288 // Get the character spacing.
GetCharSpace()289 f32 TextWriter::GetCharSpace()
290 {
291     return m_writer.GetCharSpace();
292 }
293 
294 // Set the character spacing.
SetCharSpace(f32 charSpace)295 void TextWriter::SetCharSpace(f32 charSpace)
296 {
297     m_writer.SetCharSpace(charSpace);
298 }
299 
300 // Calculates the width of a character string.
CalculateStringWidth(const wchar_t * pString)301 f32 TextWriter::CalculateStringWidth(const wchar_t* pString)
302 {
303     return m_writer.CalcStringWidth(pString);
304 }
305 
306 // Calculates the height of a character string.
CalculateStringHeight(const wchar_t * pString)307 f32 TextWriter::CalculateStringHeight(const wchar_t* pString)
308 {
309     return m_writer.CalcStringHeight(pString);
310 }
311 
312 // Perform font initialization.
InitializeFont()313 bool TextWriter::InitializeFont()
314 {
315     // Font buffer
316     void* pBuffer = nn::pl::GetSharedFontAddress();
317     // Set font resource
318     bool isSuccess = m_font.SetResource(pBuffer);
319 
320     // Size of the buffer for rendering
321     u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(pBuffer);
322     // Buffer for rendering
323     void* pDrawBuffer = m_pExpHeap->Allocate(drawBufferSize, 4);
324 
325     NN_NULL_ASSERT(pDrawBuffer);
326 
327     // Set the render buffer
328     m_font.SetDrawBuffer(pDrawBuffer);
329 
330     return isSuccess;
331 }
332 
333 // Perform shader initialization.
InitializeShader()334 bool TextWriter::InitializeShader()
335 {
336     const size_t SHADER_SIZE = NNFONT_RECTDRAWERSHADER_END - NNFONT_RECTDRAWERSHADER_BEGIN;
337     void* pShaderBinary = m_pExpHeap->Allocate(SHADER_SIZE);
338 
339     NN_NULL_ASSERT(pShaderBinary);
340 
341     // Size of the buffer for vertices and command buffer
342     u32 vtxBufferCmdBufferSize = nn::font::RectDrawer::GetVertexBufferCommandBufferSize(NNFONT_RECTDRAWERSHADER_BEGIN, SHADER_SIZE);
343     // Buffer for vertices and command buffer
344     m_pShaderBuffer = m_pExpHeap->Allocate(vtxBufferCmdBufferSize);
345 
346     NN_NULL_ASSERT(m_pShaderBuffer);
347 
348     // Perform render object initialization
349     m_drawer.Initialize(m_pShaderBuffer, NNFONT_RECTDRAWERSHADER_BEGIN, SHADER_SIZE);
350 
351     m_pExpHeap->Free(pShaderBinary);
352 
353     return true;
354 }
355 
356 // Allocate the string buffer.
AllocateStringBuffer(s32 charMax)357 nn::font::DispStringBuffer* TextWriter::AllocateStringBuffer(s32 charMax)
358 {
359     // Buffer size
360     const u32 bufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax);
361     // Buffer
362     void* pBuffer = m_pExpHeap->Allocate(bufferSize);
363 
364     NN_NULL_ASSERT(pBuffer);
365 
366     return nn::font::CharWriter::InitDispStringBuffer(pBuffer, charMax);
367 }
368 
369 } // namespace scene
370