1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: font_TextWriterBase.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: 25674 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_FONT_CTR_FONT_TEXT_WRITER_BASE_H_ 17 #define NN_FONT_CTR_FONT_TEXT_WRITER_BASE_H_ 18 19 #include <cstddef> 20 #include <cwchar> 21 #include <cstdio> 22 #include <cstring> 23 #include <cfloat> 24 #include <nn/types.h> 25 #include <nn/font/font_Font.h> 26 #include <nn/font/CTR/font_TagProcessorBase.h> 27 #include <nn/font/CTR/font_CharWriter.h> 28 #include <nn/util/util_Rect.h> 29 30 31 namespace nn { 32 namespace font { 33 namespace CTR { 34 35 36 //--------------------------------------------------------------------------- 37 //! @brief nw::font::Font クラスを用いて文字列の描画を行うためのクラスです。 38 //! 39 //! @tparam CharType 文字の型。 40 //--------------------------------------------------------------------------- 41 template <typename CharType> 42 class TextWriterBase: public CharWriter 43 { 44 public: 45 /* ------------------------------------------------------------------------ 46 型 47 ------------------------------------------------------------------------ */ 48 49 //! SetDrawFlag() 関数で使用する文字列の配置を行う文字列描画フラグです。 50 enum PositionFlag 51 { 52 //水平方向の寄せ 53 HORIZONTAL_ALIGN_LEFT = 0x0, //!< 複数行文字列を左寄せする。 54 HORIZONTAL_ALIGN_CENTER = 0x1, //!< 複数行文字列を中央寄せする。 55 HORIZONTAL_ALIGN_RIGHT = 0x2, //!< 複数行文字列を右寄せする。 56 HORIZONTAL_ALIGN_MASK = 0x3, 57 58 // 原点の水平方向位置 59 HORIZONTAL_ORIGIN_LEFT = 0x00, //!< 原点を文字列の左端に置く。 60 HORIZONTAL_ORIGIN_CENTER = 0x10, //!< 原点を文字列の水平方向中央に置く。 61 HORIZONTAL_ORIGIN_RIGHT = 0x20, //!< 原点を文字列の右端に置く。 62 HORIZONTAL_ORIGIN_MASK = 0x30, 63 64 // 原点の垂直方向位置 65 VERTICAL_ORIGIN_TOP = 0x000, //!< 原点を文字列の上端に置く。 66 VERTICAL_ORIGIN_MIDDLE = 0x100, //!< 原点を文字列の垂直方向中央に置く。 67 VERTICAL_ORIGIN_BOTTOM = 0x200, //!< 原点を文字列の 1 行目ベースラインに置く。 68 VERTICAL_ORIGIN_BASELINE = 0x300, //!< 原点を文字列の下端に置く。 69 VERTICAL_ORIGIN_MASK = 0x300 70 }; 71 72 enum ContextFlag 73 { 74 //! 前の文字との間に文字間が開けられていないことを示します 75 CONTEXT_NO_CHAR_SPACE = 0x1 76 }; 77 78 /* ------------------------------------------------------------------------ 79 変数 80 ------------------------------------------------------------------------ */ 81 //! コンストラクタで設定されるデフォルトの描画フラグです。 82 static const u32 DEFAULT_DRAWFLAG = 83 HORIZONTAL_ALIGN_LEFT | HORIZONTAL_ORIGIN_LEFT | VERTICAL_ORIGIN_TOP; 84 85 86 /* ------------------------------------------------------------------------ 87 関数 88 ------------------------------------------------------------------------ */ 89 90 //! @name コンストラクタ / デストラクタ 91 //@{ 92 93 //! コンストラクタです。 94 TextWriterBase(); 95 96 //! デストラクタです。 97 ~TextWriterBase(); 98 99 //@} 100 101 //! @name 文字間 / 行間 / タブ幅 102 //@{ 103 104 //! @brief 行間を設定します。 105 //! 106 //! @param[in] space 新しい行間。 107 //! SetLineSpace(f32 space)108 void SetLineSpace(f32 space) { m_LineSpace = space; } 109 110 //! @brief 行間を取得します。 111 //! 112 //! @return 行間を返します。 113 //! GetLineSpace()114 f32 GetLineSpace() const { return m_LineSpace; } 115 116 //! @brief 1 行の高さを設定します。 117 //! 118 //! @param[in] height 新しい行の高さ。 119 //! 120 void SetLineHeight(f32 height); 121 122 //! @brief 1 行の高さを取得します。 123 //! 124 //! @return 1 行の高さを返します。 125 //! 126 f32 GetLineHeight() const; 127 128 //! @brief 文字間を設定します。 129 //! 130 //! @param[in] space 新しい文字間。 131 //! SetCharSpace(f32 space)132 void SetCharSpace(f32 space) { m_CharSpace = space; } 133 134 //! @brief 文字間を取得します。 135 //! 136 //! @return 文字間を返します。 137 //! GetCharSpace()138 f32 GetCharSpace() const { return m_CharSpace; } 139 140 //! @brief タブ幅を指定します。 141 //! 142 //! @param[in] tabWidth 文字数換算のタブ幅。 143 //! SetTabWidth(int tabWidth)144 void SetTabWidth(int tabWidth) { m_TabWidth = tabWidth; } 145 146 //! @brief タブ幅を取得します。 147 //! 148 //! @return 文字数換算のタブ幅を返します。 149 //! GetTabWidth()150 int GetTabWidth() const { return m_TabWidth; } 151 152 //@} 153 154 //! @name 文字列の自動折り返し 155 //@{ 156 157 //! @brief 自動的に折り返す幅を指定します。 158 //! 159 //! @param[in] limit 自動的に折り返す幅。 160 //! SetWidthLimit(f32 limit)161 void SetWidthLimit(f32 limit) { m_WidthLimit = limit; } 162 163 //! @brief 設定されている折り返し幅を取得します。 164 //! 165 //! @return 設定されている折り返し幅を返します。@n 166 //! 折り返し幅が無効に設定されているときは正の無限大を返します。 167 //! GetWidthLimit()168 f32 GetWidthLimit() const { return m_WidthLimit; } 169 170 //! 自動折り返し機能を無効に設定します。 ResetWidthLimit()171 void ResetWidthLimit() { SetWidthLimit(FLT_MAX); } 172 173 //@} 174 175 176 //! @name 文字列描画フラグ設定 / 取得 177 //@{ 178 179 //! @brief 文字列描画フラグを設定します。 180 //! 181 //! @param[in] flags 新しい文字列描画フラグ 182 //! SetDrawFlag(u32 flags)183 void SetDrawFlag(u32 flags) { m_DrawFlag = flags; } 184 185 //! @brief 文字列描画フラグを取得します。 186 //! 187 //! @return 文字列描画フラグを返します。 188 //! GetDrawFlag()189 u32 GetDrawFlag() const { return m_DrawFlag; } 190 191 //@} 192 193 194 //! @name タグプロセッサ設定 / 取得 195 //@{ 196 197 //! @brief タグプロセッサを設定します。 198 //! 199 //! @param[in] tagProcessor 新しいタグプロセッサへのポインタ。 200 //! SetTagProcessor(TagProcessorBase<CharType> * tagProcessor)201 void SetTagProcessor(TagProcessorBase<CharType>* tagProcessor) 202 { 203 NN_POINTER_ASSERT(tagProcessor); 204 205 m_TagProcessor = tagProcessor; 206 } 207 208 //! @brief タグプロセッサを取得します。 209 //! 210 //! @return タグプロセッサのリファレンスを返します。 211 //! 212 TagProcessorBase<CharType>& GetTagProcessor()213 GetTagProcessor() const { return *m_TagProcessor; } 214 215 //! タグプロセッサをデフォルトに戻します。 ResetTagProcessor()216 void ResetTagProcessor() { m_TagProcessor = &s_DefaultTagProcessor; } 217 218 //@} 219 220 221 //! @name 文字列の描画サイズ計算 222 //@{ 223 224 //! @brief 文字列の幅を計算します。 225 //! 226 //! @param[in] format 書式文字列。 227 //! @param[in] ... 文字列パラメータ。 228 //! 229 //! @return 文字列の幅を返します。 230 //! 231 f32 CalcFormatStringWidth( 232 const CharType* format, 233 ... 234 ) const; 235 236 //! @brief 文字列の幅を計算します。 237 //! 238 //! @param[in] str 文字列。 239 //! 240 //! @return 文字列の幅を返します。 241 //! CalcStringWidth(const CharType * str)242 f32 CalcStringWidth( 243 const CharType* str 244 ) const 245 { 246 NN_POINTER_ASSERT(str); 247 248 return CalcStringWidth(str, StrLen(str)); 249 } 250 251 //! @brief 文字列の幅を計算します。 252 //! 253 //! @param[in] str 文字列。 254 //! @param[in] length 文字列長。 255 //! 256 //! @return 文字列の幅を返します。 257 //! 258 f32 CalcStringWidth( 259 const CharType* str, 260 int length 261 ) const; 262 263 264 //! @brief 文字列の高さを計算します。 265 //! 266 //! @param[in] format 書式文字列。 267 //! @param[in] ... 文字列パラメータ。 268 //! @param[in] str 文字列。 269 //! @param[in] length 文字列長。 270 //! 271 //! @return 文字列の高さを返します。 272 //! 273 f32 CalcFormatStringHeight( 274 const CharType* format, 275 ... 276 ) const; 277 278 //! @brief 文字列の高さを計算します。 279 //! 280 //! @param[in] str 文字列。 281 //! 282 //! @return 文字列の高さを返します。 283 //! CalcStringHeight(const CharType * str)284 f32 CalcStringHeight( 285 const CharType* str 286 ) const 287 { 288 NN_POINTER_ASSERT(str); 289 290 return CalcStringHeight(str, StrLen(str)); 291 } 292 293 //! @brief 文字列の高さを計算します。 294 //! 295 //! @param[in] str 文字列。 296 //! @param[in] length 文字列長。 297 //! 298 //! @return 文字列の高さを返します。 299 //! 300 f32 CalcStringHeight( 301 const CharType* str, 302 int length 303 ) const; 304 305 //! @brief 文字列の描画矩形を計算します。 306 //! 307 //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 308 //! @param[in] format 書式文字列。 309 //! @param[in] ... 文字列パラメータ。 310 //! 311 void CalcFormatStringRect( 312 util::Rect* pRect, 313 const CharType* format, 314 ... 315 ) const; 316 317 318 //! @brief 文字列の描画矩形を計算します。 319 //! 320 //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 321 //! @param[in] format 書式文字列。 322 //! @param[in] args 文字列パラメータ。 323 //! 324 void CalcVStringRect( 325 util::Rect* pRect, 326 const CharType* format, 327 std::va_list args 328 ) const; 329 330 331 //! @brief 文字列の描画矩形を計算します。 332 //! 333 //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 334 //! @param[in] str 文字列。 335 //! CalcStringRect(util::Rect * pRect,const CharType * str)336 void CalcStringRect( 337 util::Rect* pRect, 338 const CharType* str 339 ) const 340 { 341 NN_POINTER_ASSERT(pRect); 342 NN_POINTER_ASSERT(str); 343 344 CalcStringRect(pRect, str, StrLen(str)); 345 } 346 347 //! @brief 文字列の描画矩形を計算します。 348 //! 349 //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 350 //! @param[in] str 文字列。 351 //! @param[in] length 文字列長。 352 //! 353 void CalcStringRect( 354 util::Rect* pRect, 355 const CharType* str, 356 int length 357 ) const; 358 359 //@} 360 361 362 //! @name 文字列描画 363 //@{ 364 365 //! @brief 文字列を描画します。 366 //! 367 //! @param[in] format 書式文字列。 368 //! @param[in] ... 文字列パラメータ 369 //! 370 //! @return 文字列の幅を返します。 371 //! 372 f32 Printf( 373 const CharType* format, 374 ... ); 375 376 //! @brief 文字列を描画します。 377 //! 378 //! @param[in] format 書式文字列。 379 //! @param[in] args 文字列パラメータ。 380 //! 381 //! @return 文字列の幅を返します。 382 //! 383 f32 VPrintf( 384 const CharType* format, 385 std::va_list args); 386 387 //! @brief 文字列を描画します。 388 //! 389 //! @param[in] str 文字列。 390 //! 391 //! @return 文字列の幅を返します。 392 //! Print(const CharType * str)393 f32 Print( 394 const CharType* str 395 ) 396 { 397 NN_POINTER_ASSERT(str); 398 399 return Print(str, StrLen(str)); 400 } 401 402 //! @brief 文字列を描画します。 403 //! 404 //! @param[in] str 文字列。 405 //! @param[in] length 文字列長。 406 //! 407 //! @return 文字列の幅を返します。 408 //! 409 f32 Print( 410 const CharType* str, 411 int length); 412 413 //@} 414 415 //! @name 書式展開バッファ 416 //@{ 417 418 //! @brief 書式文字列展開用のバッファを割り当てます。 419 //! 420 //! @param[in] size バッファサイズ。 421 //! 422 //! @return 以前に TextWriter に割り当てられたバッファが存在する場合には 423 //! そのバッファへのポインタを返します。 424 //! 割り当てられたバッファが存在しない場合には NULL を返します。 425 //! SetBuffer(std::size_t size)426 static void* SetBuffer( 427 std::size_t size 428 ) 429 { 430 NN_FONT_MIN_ASSERT(size, 1); 431 void* oldBuffer = s_FormatBuffer; 432 433 s_FormatBuffer = NULL; 434 s_FormatBufferSize = size; 435 436 return oldBuffer; 437 } 438 439 //! @brief 書式文字列展開用のバッファを割り当てます。 440 //! 441 //! @param[in] buffer TextWriter に割り当てるバッファへのポインタ。 442 //! @param[in] size バッファサイズ。 443 //! 444 //! @return 以前に TextWriter に割り当てられたバッファが存在する場合には 445 //! そのバッファへのポインタを返します。 446 //! 割り当てられたバッファが存在しない場合には NULL を返します。 447 //! SetBuffer(CharType * buffer,std::size_t size)448 static void* SetBuffer( 449 CharType* buffer, 450 std::size_t size 451 ) 452 { 453 NN_POINTER_ASSERT(buffer); 454 NN_FONT_MIN_ASSERT(size, 1); 455 void* oldBuffer = s_FormatBuffer; 456 457 s_FormatBuffer = buffer; 458 s_FormatBufferSize = size; 459 460 return oldBuffer; 461 } 462 463 //! @brief 書式文字列展開用のバッファへのポインタを取得します。 464 //! 465 //! @return 書式文字列展開用のバッファへのポインタを返します。 466 //! GetBuffer()467 static const void* GetBuffer() 468 { 469 return s_FormatBuffer; 470 } 471 472 //! @brief 書式文字列展開用のバッファサイズを取得します。 473 //! 474 //! @return 書式文字列展開用のバッファのサイズを返します。 475 //! GetBufferSize()476 static std::size_t GetBufferSize() 477 { 478 return s_FormatBufferSize; 479 } 480 481 //@} 482 483 484 //---- vsnprintf の 分岐 VSNPrintf(char * buffer,std::size_t count,const char * format,std::va_list arg)485 static int VSNPrintf( 486 char* buffer, 487 std::size_t count, 488 const char* format, 489 std::va_list arg 490 ) 491 { 492 #if ! defined(_MSC_VER) 493 using namespace std; 494 #endif 495 496 return vsnprintf(buffer, count, format, arg); 497 } 498 VSNPrintf(wchar_t * buffer,std::size_t count,const wchar_t * format,std::va_list arg)499 static int VSNPrintf( 500 wchar_t* buffer, 501 std::size_t count, 502 const wchar_t* format, 503 std::va_list arg 504 ) 505 { 506 #if ! defined(_MSC_VER) 507 using namespace std; 508 #endif 509 510 return vswprintf(buffer, count, format, arg); 511 } 512 StrLen(const char * str)513 static int StrLen(const char* str) 514 { 515 return static_cast<int>(std::strlen(str)); 516 } 517 StrLen(const wchar_t * str)518 static int StrLen(const wchar_t* str) 519 { 520 return static_cast<int>(std::wcslen(str)); 521 } 522 523 524 using CharWriter::Print; 525 526 #if defined(NN_FONT_PROFILE) 527 void PrintProfile(); 528 #endif 529 530 protected: 531 #if defined(NN_FONT_PROFILE) 532 void CopyProfileData(const TextWriterBase<CharType>& other) const; 533 #endif 534 535 536 private: 537 /* ------------------------------------------------------------------------ 538 型 539 ------------------------------------------------------------------------ */ 540 typedef TagProcessorBase<CharType> TagProcessor; 541 typedef const CharType* StreamType; 542 543 /* ------------------------------------------------------------------------ 544 定数 545 ------------------------------------------------------------------------ */ 546 static const int DEFAULT_FORMAT_BUFFER_SIZE = 256; 547 548 /* ------------------------------------------------------------------------ 549 関数 550 ------------------------------------------------------------------------ */ 551 552 //! @brief 1行の長さを計算します。 553 //! 554 //! @param[in] str 文字列 555 //! @param[in] length 文字列長(sizeof(CharType)単位) 556 //! 557 f32 CalcLineWidth( 558 StreamType str, 559 int length); 560 561 //! @brief 1行分の描画矩形を計算します。 562 //! 563 //! @param[out] pRect 描画矩形を格納するバッファへのポインタ。 564 //! @param[in,out] pStr 文字列へのポインタを格納するバッファへのポインタ。 565 //! @param[in] length 文字列長(sizeof(CharType)単位) 566 //! 567 //! @return WidthLimit を超えたら true を、超えなければ false を返します。 568 //! 569 bool CalcLineRectImpl( 570 util::Rect* pRect, 571 StreamType* pStr, 572 int length); 573 574 //! @brief 文字列の描画矩形を計算します。 575 //! 576 //! @param[out] pRect 描画矩形を格納するバッファへのポインタ。 577 //! @param[in] str 文字列 578 //! @param[in] length 文字列長(sizeof(CharType)単位) 579 //! 580 void CalcStringRectImpl( 581 util::Rect* pRect, 582 StreamType str, 583 int length); 584 585 //! @brief 文字列を描画します。 586 //! 587 //! @param[in] str 文字列 588 //! @param[in] length 文字列長(sizeof(CharType)単位) 589 //! 590 f32 PrintImpl( 591 StreamType str, 592 int length); 593 594 595 //! @brief 文字列を描画フラグに従って描画するときの1文字目の 596 //! 描画開始位置にカーソルを移動します。 597 //! 598 //! @param[in,out] pXOrigin 描画基準座標を格納したバッファへのポインタ。 599 //! 補正後の描画基準座標が格納されて返る。 600 //! @param[in,out] pYOrigin 描画基準座標を格納したバッファへのポインタ。 601 //! 補正後の描画基準座標が格納されて返る。 602 //! @param[in] str 文字列 603 //! @param[in] length 文字列長(sizeof(CharType)単位) 604 //! 605 //! @return 文字列の幅を返します。 606 //! 607 f32 AdjustCursor( 608 f32* pXOrigin, 609 f32* pYOrigin, 610 StreamType str, 611 int length); 612 613 //! @brief 描画フラグが設定されているか判定します。 614 //! 615 //! @param[in] mask 描画フラグのマスク値。 616 //! @param[in] flag 判定する描画フラグ。 617 //! 618 //! @return 指定された描画フラグが設定されている場合は真を返します。 619 //! IsDrawFlagSet(u32 mask,u32 flag)620 bool IsDrawFlagSet( 621 u32 mask, 622 u32 flag 623 ) const 624 { 625 return (m_DrawFlag & mask) == flag; 626 } 627 628 /* ------------------------------------------------------------------------ 629 変数 630 ------------------------------------------------------------------------ */ 631 632 static CharType* s_FormatBuffer; //!< sprintfバッファへのポインタ 633 static std::size_t s_FormatBufferSize; //!< sprintfバッファのサイズ 634 635 //! デフォルトタグプロセッサ 636 static TagProcessor s_DefaultTagProcessor; 637 638 f32 m_WidthLimit; //!< 描画幅制限 639 f32 m_CharSpace; //!< 文字間 640 f32 m_LineSpace; //!< 行間 641 int m_TabWidth; //!< タブ幅 642 u32 m_DrawFlag; //!< 描画フラグ 643 TagProcessor* m_TagProcessor; //!< タグ処理機 644 645 #if defined(NN_FONT_PROFILE) 646 mutable Stopwatch m_PrintTextSw; 647 mutable u32 m_PrintTextCount; 648 #endif 649 }; 650 651 } // namespace CTR 652 } // namespace font 653 } // namespace nn 654 655 #endif // NN_FONT_CTR_FONT_TEXT_WRITER_BASE_H_ 656