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