1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     font_TagProcessorBase.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31628 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_FONT_TAGPROCESSORBASE_H_
19 #define NW_FONT_TAGPROCESSORBASE_H_
20 
21 #include <nn/types.h>
22 #include <nw/ut/ut_Rect.h>
23 
24 namespace nw {
25 namespace font {
26 
27 
28 
29 template <typename CharType>
30 class TextWriterBase;
31 
32 
33 template <typename CharType>
34 struct PrintContext
35 {
36     TextWriterBase<CharType>*   writer;     //!< 文字列描画に使用しているTextWriterへのポインタ。
37     const CharType*             str;        //!< 描画中の文字列へのポインタ。
38     const f32                   xOrigin;    //!< 描画開始X座標。
39     const f32                   yOrigin;    //!< 描画開始Y座標。
40     u32                         flags;      //!< TextWriter::ContextFlag のOR。
41 
PrintContextPrintContext42     PrintContext(
43         TextWriterBase<CharType>*   aWriter,
44         const CharType*             aStr,
45         const f32                   aXOrigin,
46         const f32                   aYOrigin,
47         u32                         aFlags
48     )
49     :   writer(aWriter),
50         str(aStr),
51         xOrigin(aXOrigin),
52         yOrigin(aYOrigin),
53         flags(aFlags)
54     {}
55 };
56 
57 //---------------------------------------------------------------------------
58 //! @brief        グリフグループが定義されているフォントリソースを扱うクラスです。
59 //!
60 //! @tparam       CharType 文字の型。
61 //---------------------------------------------------------------------------
62 template <typename CharType>
63 class TagProcessorBase
64 {
65 public:
66     /* ------------------------------------------------------------------------
67 68        ------------------------------------------------------------------------ */
69 
70     //! 呼び出し元 (TextWriter) が行うべき処理の列挙子です。
71     enum Operation
72     {
73         //! @brief      行頭では次の文字との間に文字間を開けません。
74         //!             行頭以外の位置では次の文字との間に文字間を開けます。
75         //!
76         OPERATION_DEFAULT,
77 
78         //! @brief      行頭以外の位置でタグ処理が行われた場合、
79         //!             デフォルトでは次の文字との間に文字間を空けますが、
80         //!             これを空けないようにします。
81         //!
82         OPERATION_NO_CHAR_SPACE,
83 
84         //! @brief      行頭でタグ処理が行われた場合、
85         //!             デフォルトでは次の文字との間に文字間を空けませんが、
86         //!             これを空けるようにします。
87         //!
88         OPERATION_CHAR_SPACE,
89 
90         //! @brief      改行時に必要な処理のうち X 座標の調整のみを行います。
91         //!             Y 座標の調整は行いません。
92         //!             また、次の文字との間に文字間を開けません。
93         //!
94         OPERATION_NEXT_LINE,
95 
96         //! @brief      文字列の途中で文字列描画を終了する場合に使用します。
97         //!
98         OPERATION_END_DRAW,
99 
100         //! @details :private
101         NUM_OF_OPERATION
102     };
103 
104     /* ------------------------------------------------------------------------
105             関数
106        ------------------------------------------------------------------------ */
107 
108     //! @name コンストラクタ / デストラクタ
109     //@{
110 
111     //! コンストラクタです。
TagProcessorBase()112                         TagProcessorBase() {}
113 
114 
115     //! デストラクタです。
~TagProcessorBase()116     virtual             ~TagProcessorBase() {}
117 
118 
119     //@}
120 
121 
122     //! @name タグ処理
123     //@{
124 
125     //! @brief      タグに従って処理を行います。
126     //!
127     //! @param[in]      code      タグ処理の起点となった制御文字コード。(0x0000 ~ 0x001F)
128     //! @param[in,out]  pContext  文字列の描画状態情報へのポインタ。
129     //!
130     //! @return     呼び出し元 (TextWriter) が行うべき処理を返します。
131     //!
Process(u16 code,PrintContext<CharType> * pContext)132     virtual Operation   Process(
133                             u16                     code,
134                             PrintContext<CharType>* pContext
135                         )
136     {
137         NN_ASSERT(code < ' ');
138         NN_POINTER_ASSERT(pContext);
139 
140         switch (code)
141         {
142         case '\n':
143             ProcessLinefeed(pContext);
144             return OPERATION_NEXT_LINE;
145 
146         case '\t':
147             ProcessTab(pContext);
148             return OPERATION_NO_CHAR_SPACE;
149 
150         default:
151             // nothing to do;
152             break;
153         }
154 
155         return OPERATION_DEFAULT;
156     }
157 
158     //! @brief      タグの影響範囲を計算します。
159     //!
160     //! @param[out]     pRect     タグの影響範囲を格納する矩形構造体へのポインタ。
161     //! @param[in]      code      タグ処理の起点となった制御文字コード。(0x0000 ~ 0x001F)
162     //! @param[in,out]  pContext  文字列の描画状態情報へのポインタ。
163     //!
164     //! @return     呼び出し元 (TextWriter) が行うべき処理を返します。
165     //!             同じタグに対して Process() 関数が返す値と同じ値を返すべきです。
166     //!
CalcRect(ut::Rect * pRect,u16 code,PrintContext<CharType> * pContext)167     virtual Operation   CalcRect(
168                             ut::Rect*               pRect,
169                             u16                     code,
170                             PrintContext<CharType>* pContext
171                         )
172     {
173         NN_POINTER_ASSERT(pRect);
174         NN_ASSERT(code < ' ');
175         NN_POINTER_ASSERT(pContext);
176 
177         switch (code)
178         {
179         case '\n':
180             {
181                 TextWriterBase<CharType>& writer = *pContext->writer;
182 
183                 pRect->right    = writer.GetCursorX();
184                 pRect->top      = writer.GetCursorY();
185 
186                 ProcessLinefeed(pContext);
187 
188                 pRect->left     = writer.GetCursorX();
189 
190                 // ProcessLinefeed はカーソルを移動するだけで次の行の高さは含まれていないので
191                 // 次の行の高さとして FontHeight を足す。
192                 pRect->bottom   = writer.GetCursorY() + pContext->writer->GetFontHeight();
193 
194                 pRect->Normalize();
195             }
196             return OPERATION_NEXT_LINE;
197 
198         case '\t':
199             {
200                 TextWriterBase<CharType>& writer = *pContext->writer;
201 
202                 pRect->left     = writer.GetCursorX();
203 
204                 ProcessTab(pContext);
205 
206                 pRect->right    = writer.GetCursorX();
207                 pRect->top      = writer.GetCursorY();
208                 pRect->bottom   = pRect->top + writer.GetFontHeight();
209 
210                 pRect->Normalize();
211             }
212             return OPERATION_NO_CHAR_SPACE;
213 
214         default:
215             // nothing to do;
216             break;
217         }
218 
219         return OPERATION_DEFAULT;
220     }
221 
222     //@}
223 
224 private:
225     /* ------------------------------------------------------------------------
226 227        ------------------------------------------------------------------------ */
228     typedef PrintContext<CharType>  ContextType;
229 
230     void                ProcessLinefeed(ContextType* pContext);
231     void                ProcessTab(ContextType* pContext);
232 };
233 
234 /* ------------------------------------------------------------------------
235         private タグ処理
236    ------------------------------------------------------------------------ */
237 template <typename CharType>
238 void
ProcessLinefeed(ContextType * pContext)239 TagProcessorBase<CharType>::ProcessLinefeed(ContextType* pContext)
240 {
241     NN_POINTER_ASSERT(pContext);
242 
243     TextWriterBase<CharType>& writer = *pContext->writer;
244 
245     const f32 x   = pContext->xOrigin;
246     const f32 y   = writer.GetCursorY() + writer.GetLineHeight();
247 
248     writer.SetCursor(x, y);
249 }
250 
251 template <typename CharType>
252 void
ProcessTab(ContextType * pContext)253 TagProcessorBase<CharType>::ProcessTab(ContextType* pContext)
254 {
255     NN_POINTER_ASSERT(pContext);
256 
257     TextWriterBase<CharType>& writer = *pContext->writer;
258     const int tabWidth = writer.GetTabWidth();
259 
260     if (tabWidth > 0)
261     {
262         const f32 aCharWidth  = writer.IsWidthFixed() ? writer.GetFixedWidth(): writer.GetFontWidth();
263         const f32 dx          = writer.GetCursorX() - pContext->xOrigin;
264         const f32 tabPixel    = tabWidth * aCharWidth;
265         const int numTab      = static_cast<int>(dx / tabPixel) + 1;
266         const f32 x           = pContext->xOrigin + tabPixel * numTab;
267 
268         writer.SetCursorX(x);
269     }
270 }
271 
272 }   // namespace font
273 }   // namespace nw
274 
275 #endif //  NW_FONT_TAGPROCESSORBASE_H_
276