1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     font_CharWriter.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision: 19298 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_FONT_CHARWRITER_H_
17 #define NW_FONT_CHARWRITER_H_
18 
19 #if defined(_MSC_VER) && _MSC_VER >= 1500
20 #pragma once
21 #endif
22 
23 // 左上原点
24 #define COORDINATE_LT 1
25 
26 #include <cstddef>
27 #include <cstdio>
28 #include <GLES2/gl2.h>
29 #include <nn/types.h>
30 #include <nw/math.h>
31 #include <nw/ut/ut_Color.h>
32 #include <nw/font/font_Font.h>
33 #include <nw/font/font_TextWriterResource.h>
34 #include <nw/font/font_Stopwatch.h>
35 #include <nw/math/math_Types.h>
36 
37 // 文字描画用シェーダバイナリファイル名
38 #define NW_FONT_SHADERBINARY    L"nwfont_TextWriterShader.shbin"
39 
40 #define NW_FONT_RECTDRAWER_SHADERBINARY L"nwfont_RectDrawerShader.shbin"
41 
42 namespace nw {
43 
44 namespace font {
45 
46 struct DispStringBuffer;
47 
48 //---------------------------------------------------------------------------
49 //! @brief        Fontクラスを用いて文字の描画を行うためのクラスです。
50 //---------------------------------------------------------------------------
51 class CharWriter
52 {
53 public:
54     /* ------------------------------------------------------------------------
55 56        ------------------------------------------------------------------------ */
57 
58     //! グラデーションの種類を表す enum です。
59     enum GradationMode
60     {
61         GRADMODE_NONE,                          //!< グラデーションなし
62         GRADMODE_H,                             //!< 水平方向グラデーション
63         GRADMODE_V,                             //!< 垂直方向グラデーション
64 
65         NUM_OF_GRADMODE
66     };
67 
68 
69 
70     /* ------------------------------------------------------------------------
71             定数
72        ------------------------------------------------------------------------ */
73     static const u32 DEFAULT_COLOR_MAPPING_MIN = 0x00000000UL;
74     static const u32 DEFAULT_COLOR_MAPPING_MAX = 0xFFFFFFFFUL;
75 
76 
77     /* ------------------------------------------------------------------------
78             関数
79        ------------------------------------------------------------------------ */
80 
81     //! @name コンストラクタ/デストラクタ
82     //@{
83 
84     //! コンストラクタです。
85                         CharWriter();
86 
87     //! デストラクタです。
88                         ~CharWriter();
89 
90     //@}
91 
92     //! @name フォント
93     //@{
94 
95     //! @brief      フォントを設定します。
96     //!
97     //! @param[in]  pFont  新しく設定するフォントへのポインタ。
98     //!
SetFont(const Font * pFont)99     void                SetFont(const Font* pFont)  { m_pFont = pFont; }
100 
101     //! @brief      フォントを取得します。
102     //!
103     //! @return     フォントが設定されている場合にはフォントへのポインタを返します。
104     //!             設定されていない場合には NULL を返します。
105     //!
GetFont()106     const Font*         GetFont() const             { return m_pFont; }
107 
108     //@}
109 
110     //! @name 文字描画準備
111     //@{
112 
113     //! 文字描画のための準備を行います。
114     void                SetupGX();
115 
116     //! 描画設定の後処理を行います。
FinalizeGX()117     static void         FinalizeGX()
118     {
119         TextWriterResource::FinalizeGX();
120     }
121 
122     //@}
123 
124     //! @name グリフ色の線形変換
125     //@{
126 
127     //! @brief      文字描画時のグリフカラーの線形変換を設定します。
128     //!
129     //! @param[in]  min  各成分についての 0 の変換後の値。
130     //! @param[in]  max  各成分についての 255 の変換後の値。
131     //!
SetColorMapping(ut::Color8 min,ut::Color8 max)132     void                SetColorMapping(
133                             ut::Color8  min,
134                             ut::Color8  max
135     )
136     {
137         m_ColorMapping.min = min;
138         m_ColorMapping.max = max;
139     }
140 
141     //! @brief      グリフカラーの線形変換における各成分の 0 の変換後の値を取得します。
142     //!
143     //! @return     グリフカラーの線形変換における各成分の 0 の変換後の値を返します。
144     //!
GetColorMappingMin()145     const ut::Color8    GetColorMappingMin() const { return m_ColorMapping.min; }
146 
147     //! @brief      グリフカラーの線形変換における各成分の 255 の変換後の値を取得します。
148     //!
149     //! @return     グリフカラーの線形変換における各成分の 255 の変換後の値を返します。
150     //!
GetColorMappingMax()151     const ut::Color8    GetColorMappingMax() const { return m_ColorMapping.max; }
152 
153     //! 文字描画時のグリフカラーの線形変換を行わないように設定します。
ResetColorMapping()154     void                ResetColorMapping()
155     {
156         SetColorMapping(DEFAULT_COLOR_MAPPING_MIN, DEFAULT_COLOR_MAPPING_MAX);
157     }
158 
159     //@}
160 
161     //! @name 文字色/グラデーション
162     //@{
163 
164     //! @brief      文字描画時の追加のアルファ値を設定します。
165     //!
166     //! @param[in]  alpha  新しく設定する追加のアルファ値。
167     //!
SetAlpha(u8 alpha)168     void                SetAlpha(u8 alpha)
169     {
170         m_Alpha = alpha;
171     }
172 
173     //文字描画時の追加のアルファ値を取得します。
174 
175     //! @brief      文字描画時の追加のアルファ値を取得します。
176     //!
177     //! @return     追加のアルファ値を返します。
178     //!
GetAlpha()179     u8                  GetAlpha() const    { return m_Alpha; }
180 
181     //! @brief      グラデーションモードを設定します。
182     //!
183     //! @param[in]  mode    新しく設定するグラデーションモード。
184     //!
SetGradationMode(GradationMode mode)185     void                SetGradationMode(GradationMode mode)
186     {
187         NW_FONT_MINMAX_ASSERT(mode, GRADMODE_NONE, NUM_OF_GRADMODE - 1);
188         m_GradationMode = mode;
189         UpdateVertexColor();
190     }
191 
192     //! @brief      グラデーションモードを取得します。
193     //!
194     //! @return     グラデーションモードを返します。
195     //!
GetGradationMode()196     GradationMode       GetGradationMode() const    { return m_GradationMode; }
197 
198     //! @brief      文字色またはグラデーション色を設定します。
199     //!
200     //! @param[in]  color  文字色。
201     //!
SetTextColor(ut::Color8 color)202     void                SetTextColor(ut::Color8 color)
203     {
204         m_TextColors[internal::TEXTCOLOR_START] = color;
205         UpdateVertexColor();
206     }
207 
208     //! @brief      文字色またはグラデーション色を設定します。
209     //!
210     //! @param[in]  start  グラデーション開始色。
211     //! @param[in]  end    グラデーション終了色。
212     //!
SetTextColor(ut::Color8 start,ut::Color8 end)213     void                SetTextColor(
214                             ut::Color8  start,
215                             ut::Color8  end
216     )
217     {
218         m_TextColors[internal::TEXTCOLOR_START] = start;
219         m_TextColors[internal::TEXTCOLOR_END  ] = end;
220         UpdateVertexColor();
221     }
222 
223     //! @brief      文字色を取得します。
224     //!
225     //! @return     文字色を返します。
226     //!
GetTextColor()227     const ut::Color8     GetTextColor() const           { return m_TextColors[internal::TEXTCOLOR_START]; }
228 
229     //! @brief      グラデーション開始色を取得します。
230     //!
231     //! @return     グラデーション開始色を返します。
232     //!
GetGradationStartColor()233     const ut::Color8     GetGradationStartColor() const { return m_TextColors[internal::TEXTCOLOR_START]; }
234 
235     //! @brief      グラデーション終了色を取得します。
236     //!
237     //! @return     グラデーション終了色を返します。
238     //!
GetGradationEndColor()239     const ut::Color8     GetGradationEndColor() const   { return m_TextColors[internal::TEXTCOLOR_END]; }
240 
241     //@}
242 
243     //! @name 文字の拡大縮小
244     //@{
245 
246     //! @brief      文字の拡大率を指定します。
247     //!
248     //! @param[in]  hScale  横方向拡大率。
249     //! @param[in]  vScale  縦方向拡大率。
250     //!
SetScale(f32 hScale,f32 vScale)251     void                SetScale(
252                             f32 hScale,
253                             f32 vScale
254     )
255     {
256         m_Scale.x = hScale;
257         m_Scale.y = vScale;
258     }
259 
260     //! @brief      文字の拡大率を指定します。
261     //!
262     //! @param[in]  hvScale 拡大率。
263     //!
SetScale(f32 hvScale)264     void                SetScale(f32 hvScale)
265     {
266         m_Scale.x = hvScale;
267         m_Scale.y = hvScale;
268     }
269 
270     //! @brief  文字の横方向の拡大率を取得します。
271     //!
272     //! @return 文字の横方向の拡大率を返します。
273     //!
GetScaleH()274     f32                 GetScaleH() const   { return m_Scale.x; }
275 
276     //! @brief  文字の縦方向の拡大率を取得します。
277     //!
278     //! @return 文字の縦方向の拡大率を返します。
279     //!
GetScaleV()280     f32                 GetScaleV() const   { return m_Scale.y; }
281 
282     //! @brief      文字のサイズを指定します。
283     //!
284     //! @param[in]  width   拡大後のセルの幅。
285     //! @param[in]  height  拡大後のセルの高さ。
286     //!
287     void                SetFontSize(
288                             f32 width,
289                             f32 height);
290 
291     //! @brief      文字のサイズを指定します。
292     //!
293     //! @param[in]  height  拡大後のセルの高さ。
294     //!
295     void                SetFontSize(f32 height);
296 
297     //! @brief      拡大適用後のセル幅を取得します。
298     //!
299     //! @return     フォントが設定されている場合は拡大適用後のセル幅をピクセル単位で取得します。
300     //!             フォントが設定されていない場合の返り値は未定義です。
301     //!
302     f32                 GetFontWidth() const;
303 
304     //! @brief      拡大適用後のセル高さを取得します。
305     //!
306     //! @return     フォントが設定されている場合は拡大適用後のセル高さをピクセル単位で取得します。
307     //!             フォントが設定されていない場合の返り値は未定義です。
308     //!
309     f32                 GetFontHeight() const;
310 
311     //! @brief      拡大適用後のアセントを取得します。
312     //!
313     //! @return     拡大適用後のアセントを返します。
314     //!
315     f32                 GetFontAscent() const;
316 
317     //! @brief      拡大適用後のディセントを取得します。
318     //!
319     //! @return     拡大適用後のディセントを返します。
320     //!
321     f32                 GetFontDescent() const;
322 
323     //@}
324 
325     //! @name 等幅描画
326     //@{
327 
328     //! @brief      強制等幅描画を行うように設定します。
329     //!
330     //! @param[in]  isFixed 強制等幅描画を行うのであれば true を指定します。
331     //!
EnableFixedWidth(bool isFixed)332     void                EnableFixedWidth(bool isFixed)  { m_IsWidthFixed = isFixed; }
333 
334     //! @brief  強制等幅描画を行うかどうかを取得します。
335     //!
336     //! @return 強制等幅描画を行う場合は true を、行わない場合は false を返します。
337     //!
IsWidthFixed()338     bool                IsWidthFixed() const            { return m_IsWidthFixed; }
339 
340     //! @brief      強制等幅描画の文字幅を指定します。
341     //!
342     //! @param[in]  width   新しい等幅描画幅。
343     //!
SetFixedWidth(f32 width)344     void                SetFixedWidth(f32 width)        { m_FixedWidth = width; }
345 
346     //! @brief      強制等幅描画の文字幅を取得します。
347     //!
348     //! @return     強制等幅描画の文字幅を返します。
349     //!
GetFixedWidth()350     f32                 GetFixedWidth() const           { return m_FixedWidth; }
351 
352     //@}
353 
354     //! @name 文字描画
355     //@{
356 
357     //! @brief      文字を描画します。
358     //!
359     //! @param[in]  code    描画する文字の文字コード。
360     //!
361     //! @return     描画した文字の文字幅を返します。
362     //!
363     f32                 Print(CharCode code);
364 
365     //! @brief      グリフを描画します。
366     //!
367     //! @param[in]  glyph   描画する文字のグリフデータ。
368     //!
369     void                DrawGlyph(const Glyph& glyph);
370 
371     //@}
372 
373     //! @name カーソル
374     //@{
375 
376     //! @brief      カーソル位置を指定した新しい座標に設定します。
377     //!
378     //! @param[in]  x   カーソルの新しい X 座標。
379     //! @param[in]  y   カーソルの新しい Y 座標。
380     //!
SetCursor(f32 x,f32 y)381     void                SetCursor(
382                             f32 x,
383                             f32 y
384     )
385     {
386         m_CursorPos.x = x;
387         m_CursorPos.y = y;
388     }
389 
390     //! @brief      カーソル位置を指定した新しい座標に設定します。
391     //!
392     //! @param[in]  x   カーソルの新しい X 座標。
393     //! @param[in]  y   カーソルの新しい Y 座標。
394     //! @param[in]  z   カーソルの新しい Z 座標。
395     //!
SetCursor(f32 x,f32 y,f32 z)396     void                SetCursor(
397                             f32 x,
398                             f32 y,
399                             f32 z
400     )
401     {
402         m_CursorPos.x = x;
403         m_CursorPos.y = y;
404         m_CursorPos.z = z;
405     }
406 
407     //! @brief      カーソルを現在位置から指定された差分だけ移動します。
408     //!
409     //! @param[in]  dx  X 軸方向のカーソル移動量。
410     //! @param[in]  dy  Y 軸方向のカーソル移動量。
411     //!
MoveCursor(f32 dx,f32 dy)412     void                MoveCursor(
413                             f32 dx,
414                             f32 dy
415     )
416     {
417         m_CursorPos.x += dx;
418         m_CursorPos.y += dy;
419     }
420 
421     //! @brief      カーソルを現在位置から指定された差分だけ移動します。
422     //!
423     //! @param[in]  dx  X 軸方向のカーソル移動量。
424     //! @param[in]  dy  Y 軸方向のカーソル移動量。
425     //! @param[in]  dz  Z 軸方向のカーソル移動量。
426     //!
MoveCursor(f32 dx,f32 dy,f32 dz)427     void                MoveCursor(
428                             f32 dx,
429                             f32 dy,
430                             f32 dz
431     )
432     {
433         m_CursorPos.x += dx;
434         m_CursorPos.y += dy;
435         m_CursorPos.z += dz;
436     }
437 
438     //! @brief      カーソルの X 座標を設定します。
439     //!
440     //! @param[in]  x   カーソルの新しい X 座標。
441     //!
SetCursorX(f32 x)442     void                SetCursorX(f32 x)           { m_CursorPos.x = x; }
443 
444     //! @brief      カーソルの Y 座標を設定します。
445     //!
446     //! @param[in]  y   カーソルの新しい Y 座標。
447     //!
SetCursorY(f32 y)448     void                SetCursorY(f32 y)           { m_CursorPos.y = y; }
449 
450     //! @brief      カーソルの Z 座標を設定します。
451     //!
452     //! @param[in]  z   カーソルの新しい Z 座標。
453     //!
SetCursorZ(f32 z)454     void                SetCursorZ(f32 z)           { m_CursorPos.z = z; }
455 
456     //! @brief      カーソルを現在位置から指定された差分だけ移動します。
457     //!
458     //! @param[in]  dx  X 軸方向のカーソル移動量。
459     //!
MoveCursorX(f32 dx)460     void                MoveCursorX(f32 dx)         { m_CursorPos.x += dx; }
461 
462     //! @brief      カーソルを現在位置から指定された差分だけ移動します。
463     //!
464     //! @param[in]  dy  Y 軸方向のカーソル移動量。
465     //!
MoveCursorY(f32 dy)466     void                MoveCursorY(f32 dy)         { m_CursorPos.y += dy; }
467 
468     //! @brief      カーソルを現在位置から指定された差分だけ移動します。
469     //!
470     //! @param[in]  dz  Z 軸方向のカーソル移動量。
471     //!
MoveCursorZ(f32 dz)472     void                MoveCursorZ(f32 dz)         { m_CursorPos.z += dz; }
473 
474     //! @brief      カーソルのX座標を取得します。
475     //!
476     //! @return     カーソルのX座標を返します。
477     //!
GetCursorX()478     f32                 GetCursorX() const          { return m_CursorPos.x; }
479 
480     //! @brief      カーソルのY座標を取得します。
481     //!
482     //! @return     カーソルのY座標を返します。
483     //!
GetCursorY()484     f32                 GetCursorY() const          { return m_CursorPos.y; }
485 
486     //! @brief      カーソルのZ座標を取得します。
487     //!
488     //! @return     カーソルのZ座標を返します。
489     //!
GetCursorZ()490     f32                 GetCursorZ() const          { return m_CursorPos.z; }
491 
492     //@}
493 
494     //! @name シェーダー関連の設定/取得
495     //@{
496 
497     //! @brief      TextWriterResourceインスタンスを取得します。
498     //!
499     //! @return     TextWriterResourceインスタンスへのポインタを返します。
500     //!
GetTextWriterResource()501     TextWriterResource* GetTextWriterResource() const
502     {
503         return m_pTextWriterResource;
504     }
505 
506     //! @brief      TextWriterResourceインスタンスをセットします。
507     //!
508     //! @param[in]  pTextWriterResource  TextWriterResourceインスタンスへのポインタ。
509     //!
SetTextWriterResource(TextWriterResource * pTextWriterResource)510     void                SetTextWriterResource(TextWriterResource* pTextWriterResource)
511     {
512         m_pTextWriterResource = pTextWriterResource;
513     }
514 
515     //@}
516 
517     //! @name 文字列表示用バッファ
518     //@{
519 
520     //! @brief      文字列表示用バッファのサイズを計算します。
521     //!
522     //! @param[in]  charNum         最大描画文字数
523     //!
524     //! @return     文字列表示用バッファのサイズを返します。
525     //!
526     static u32          GetDispStringBufferSize(u32 charNum);
527 
528     //! @brief      文字列表示用バッファを初期化します。
529     //!
530     //! @param[in]  drawBuffer      描画用バッファ。
531     //! @param[in]  charNum         最大描画文字数。
532     //!
533     //! @return     初期化した文字列表示用バッファを返します。
534     //!
535     static DispStringBuffer*
536                         InitDispStringBuffer(
537                             void*   drawBuffer,
538                             u32     charNum);
539 
540     //! @brief      文字列表示用バッファを取得します。
541     //!
542     //! @return     文字列表示用バッファを返します。
543     //!
GetDispStringBuffer()544     DispStringBuffer*   GetDispStringBuffer() const
545     {
546         return m_pDispStringBuffer;
547     }
548 
549     //! @brief      文字列表示用バッファをセットします。
550     //!             NULLを設定した場合は文字列表示用バッファを使用しなくなります。
551     //!
552     //! @param[in]  buffer 文字列表示用バッファ。
553     //!
SetDispStringBuffer(DispStringBuffer * buffer)554     void                SetDispStringBuffer(DispStringBuffer* buffer)
555     {
556         m_pDispStringBuffer = buffer;
557     }
558 
559     //! @brief      文字列の描画を開始します。
560     //!             文字列表示用バッファが設定されている場合に使用します。
561     //!
562     void                StartPrint();
563 
564     //! @brief      文字列の描画を終了します。
565     //!             文字列表示用バッファが設定されている場合に使用します。
566     //!
567     void                EndPrint();
568 
569     //! @brief      文字列表示用のコマンドバッファをカレントのコマンドリストに追加します。
570     //!
571     void                UseCommandBuffer();
572 
573     //@}
574 
575     #if defined(NW_FONT_PROFILE)
576         void                PrintProfile();
577     #endif
578 
579 protected:
580     #if defined(NW_FONT_PROFILE)
581         void                CopyProfileData(const CharWriter& other) const;
582     #endif
583 
584 private:
585 
586     /* ------------------------------------------------------------------------
587 588        ------------------------------------------------------------------------ */
589     typedef math::VEC2      CharScale;
590     typedef math::VEC3      CursorPos;
591 
592     struct ColorMapping
593     {
594         ut::Color8          min;
595         ut::Color8          max;
596     };
597 
598     /* ------------------------------------------------------------------------
599             関数
600        ------------------------------------------------------------------------ */
601     //---- 描画準備
602 
603     //! @brief      グラフィックスエンジンを文字描画用のデフォルト設定にします。
604     //!
605     //! @param[in]  bAlphaTex テクスチャがアルファのみのテクスチャの場合は真。
606     //!
607     void                SetupGXDefault(bool bAlphaTex = false);
608 
609     //! @brief      グラフィックスエンジンをテクスチャカラーの線形変換ありの
610     //!             文字描画用に設定します。
611     //!
612     //! @param[in]  bAlphaTex テクスチャがアルファのみのテクスチャの場合は真。
613     //!
614     void                SetupGXWithColorMapping(bool bAlphaTex = false);
615 
616     //! 頂点フォーマットを文字描画用に設定します。
617     void                SetupVertexFormat();
618 
619     //! グラフィックスエンジンに対して共通の設定を行います。
620     void                SetupGXCommon();
621 
622     //! @brief      グリフを指定位置に描画します。
623     //!             カーソル移動は行いません。
624     //!
625     //! @param[in]  x      描画位置のX座標。
626     //! @param[in]  glyph  描画するグリフデータ。
627     //!
628     void                PrintGlyph(
629                             f32             x,
630                             const Glyph&    glyph);
631 
632     //! テクスチャを張る四角形ポリゴンの頂点カラーを更新します。
633     void                UpdateVertexColor();
634 
635     //! @brief      グリフデータの持つテクスチャをロードします。
636     //!
637     //! @param[in]  glyph  ロードすべきテクスチャ情報を持つグリフデータ。
638     //!
639     void                LoadTexture(const Glyph& glyph);
640 
641     /* ------------------------------------------------------------------------
642             変数
643        ------------------------------------------------------------------------ */
644     static const GLushort       s_VertexIndexs[];
645 
646     ColorMapping                m_ColorMapping;         //!< カラーマッピング
647     ut::Color8                  m_VertexColors[internal::TRIFAN_VTX_MAX];
648                                                         //!< 頂点カラー
649     ut::Color8                  m_TextColors[internal::TEXTCOLOR_MAX];  //!< 文字色
650     GradationMode               m_GradationMode;
651     CharScale                   m_Scale;                //!< 文字拡大率
652     CursorPos                   m_CursorPos;            //!< カーソル位置
653     f32                         m_FixedWidth;           //!< 等幅時の幅
654     const Font*                 m_pFont;                //!< フォント
655 
656     //! TextWriterResourceインスタンスへのポインタ
657     TextWriterResource*         m_pTextWriterResource;
658 
659     //! 頂点バッファオブジェクト用構造体へのポインタ
660     DispStringBuffer*           m_pDispStringBuffer;
661 
662     bool                        m_IsWidthFixed;         //!< 等幅描画するかどうか
663     u8                          m_Alpha;                //!< 不透明度
664 
665     #if defined(NW_FONT_PROFILE)
666         mutable Stopwatch           m_LoadTextureSw;
667         mutable Stopwatch           m_PrintCharSw;
668         mutable u32                 m_LoadTextureCount;
669         mutable u32                 m_PrintCharCount;
670         mutable Stopwatch           m_DispCharSw;
671         mutable u32                 m_DispCharCount;
672     #endif
673 };
674 
675 }   // namespace font
676 }   // namespace nw
677 #endif //  NW_FONT_CHARWRITER_H_
678