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