/*---------------------------------------------------------------------------* Project: NintendoWare File: font_TextWriterBase.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_FONT_TEXTWRITERBASE_H_ #define NW_FONT_TEXTWRITERBASE_H_ #if defined(_MSC_VER) && _MSC_VER >= 1500 #pragma once #endif #include #include #include #include #include #include #include #include #include #include namespace nw { namespace font { //--------------------------------------------------------------------------- //! @brief nw::font::Font クラスを用いて文字列の描画を行うためのクラスです。 //! //! @tparam CharType 文字の型。 //--------------------------------------------------------------------------- template class TextWriterBase: public CharWriter { public: /* ------------------------------------------------------------------------ 型 ------------------------------------------------------------------------ */ //! SetDrawFlag() 関数で使用する文字列の配置を行う文字列描画フラグです。 enum PositionFlag { //水平方向の寄せ HORIZONTAL_ALIGN_LEFT = 0x0, //!< 複数行文字列を左寄せする。 HORIZONTAL_ALIGN_CENTER = 0x1, //!< 複数行文字列を中央寄せする。 HORIZONTAL_ALIGN_RIGHT = 0x2, //!< 複数行文字列を右寄せする。 HORIZONTAL_ALIGN_MASK = 0x3, // 原点の水平方向位置 HORIZONTAL_ORIGIN_LEFT = 0x00, //!< 原点を文字列の左端に置く。 HORIZONTAL_ORIGIN_CENTER = 0x10, //!< 原点を文字列の水平方向中央に置く。 HORIZONTAL_ORIGIN_RIGHT = 0x20, //!< 原点を文字列の右端に置く。 HORIZONTAL_ORIGIN_MASK = 0x30, // 原点の垂直方向位置 VERTICAL_ORIGIN_TOP = 0x000, //!< 原点を文字列の上端に置く。 VERTICAL_ORIGIN_MIDDLE = 0x100, //!< 原点を文字列の垂直方向中央に置く。 VERTICAL_ORIGIN_BOTTOM = 0x200, //!< 原点を文字列の 1 行目ベースラインに置く。 VERTICAL_ORIGIN_BASELINE = 0x300, //!< 原点を文字列の下端に置く。 VERTICAL_ORIGIN_MASK = 0x300 }; enum ContextFlag { //! 前の文字との間に文字間が開けられていないことを示します CONTEXT_NO_CHAR_SPACE = 0x1 }; /* ------------------------------------------------------------------------ 変数 ------------------------------------------------------------------------ */ //! コンストラクタで設定されるデフォルトの描画フラグです。 static const u32 DEFAULT_DRAWFLAG = HORIZONTAL_ALIGN_LEFT | HORIZONTAL_ORIGIN_LEFT | VERTICAL_ORIGIN_TOP; /* ------------------------------------------------------------------------ 関数 ------------------------------------------------------------------------ */ //! @name コンストラクタ / デストラクタ //@{ //! コンストラクタです。 TextWriterBase(); //! デストラクタです。 ~TextWriterBase(); //@} //! @name 文字間 / 行間 / タブ幅 //@{ //! @brief 行間を設定します。 //! //! @param[in] space 新しい行間。 //! void SetLineSpace(f32 space) { m_LineSpace = space; } //! @brief 行間を取得します。 //! //! @return 行間を返します。 //! f32 GetLineSpace() const { return m_LineSpace; } //! @brief 1 行の高さを設定します。 //! //! @param[in] height 新しい行の高さ。 //! void SetLineHeight(f32 height); //! @brief 1 行の高さを取得します。 //! //! @return 1 行の高さを返します。 //! f32 GetLineHeight() const; //! @brief 文字間を設定します。 //! //! @param[in] space 新しい文字間。 //! void SetCharSpace(f32 space) { m_CharSpace = space; } //! @brief 文字間を取得します。 //! //! @return 文字間を返します。 //! f32 GetCharSpace() const { return m_CharSpace; } //! @brief タブ幅を指定します。 //! //! @param[in] tabWidth 文字数換算のタブ幅。 //! void SetTabWidth(int tabWidth) { m_TabWidth = tabWidth; } //! @brief タブ幅を取得します。 //! //! @return 文字数換算のタブ幅を返します。 //! int GetTabWidth() const { return m_TabWidth; } //@} //! @name 文字列の自動折り返し //@{ //! @brief 自動的に折り返す幅を指定します。 //! //! @param[in] limit 自動的に折り返す幅。 //! void SetWidthLimit(f32 limit) { m_WidthLimit = limit; } //! @brief 設定されている折り返し幅を取得します。 //! //! @return 設定されている折り返し幅を返します。@n //! 折り返し幅が無効に設定されているときは正の無限大を返します。 //! f32 GetWidthLimit() const { return m_WidthLimit; } //! 自動折り返し機能を無効に設定します。 void ResetWidthLimit() { SetWidthLimit(FLT_MAX); } //@} //! @name 文字列描画フラグ設定 / 取得 //@{ //! @brief 文字列描画フラグを設定します。 //! //! @param[in] flags 新しい文字列描画フラグ //! void SetDrawFlag(u32 flags) { m_DrawFlag = flags; } //! @brief 文字列描画フラグを取得します。 //! //! @return 文字列描画フラグを返します。 //! u32 GetDrawFlag() const { return m_DrawFlag; } //@} //! @name タグプロセッサ設定 / 取得 //@{ //! @brief タグプロセッサを設定します。 //! //! @param[in] tagProcessor 新しいタグプロセッサへのポインタ。 //! void SetTagProcessor(TagProcessorBase* tagProcessor) { NN_POINTER_ASSERT(tagProcessor); m_TagProcessor = tagProcessor; } //! @brief タグプロセッサを取得します。 //! //! @return タグプロセッサのリファレンスを返します。 //! TagProcessorBase& GetTagProcessor() const { return *m_TagProcessor; } //! タグプロセッサをデフォルトに戻します。 void ResetTagProcessor() { m_TagProcessor = &s_DefaultTagProcessor; } //@} //! @name 文字列の描画サイズ計算 //@{ //! @brief 文字列の幅を計算します。 //! //! @param[in] format 書式文字列。 //! @param[in] ... 文字列パラメータ。 //! //! @return 文字列の幅を返します。 //! f32 CalcFormatStringWidth( const CharType* format, ... ) const; //! @brief 文字列の幅を計算します。 //! //! @param[in] str 文字列。 //! //! @return 文字列の幅を返します。 //! f32 CalcStringWidth( const CharType* str ) const { NN_POINTER_ASSERT(str); return CalcStringWidth(str, StrLen(str)); } //! @brief 文字列の幅を計算します。 //! //! @param[in] str 文字列。 //! @param[in] length 文字列長。 //! //! @return 文字列の幅を返します。 //! f32 CalcStringWidth( const CharType* str, int length ) const; //! @brief 文字列の高さを計算します。 //! //! @param[in] format 書式文字列。 //! @param[in] ... 文字列パラメータ。 //! @param[in] str 文字列。 //! @param[in] length 文字列長。 //! //! @return 文字列の高さを返します。 //! f32 CalcFormatStringHeight( const CharType* format, ... ) const; //! @brief 文字列の高さを計算します。 //! //! @param[in] str 文字列。 //! //! @return 文字列の高さを返します。 //! f32 CalcStringHeight( const CharType* str ) const { NN_POINTER_ASSERT(str); return CalcStringHeight(str, StrLen(str)); } //! @brief 文字列の高さを計算します。 //! //! @param[in] str 文字列。 //! @param[in] length 文字列長。 //! //! @return 文字列の高さを返します。 //! f32 CalcStringHeight( const CharType* str, int length ) const; //! @brief 文字列の描画矩形を計算します。 //! //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 //! @param[in] format 書式文字列。 //! @param[in] ... 文字列パラメータ。 //! void CalcFormatStringRect( ut::Rect* pRect, const CharType* format, ... ) const; //! @brief 文字列の描画矩形を計算します。 //! //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 //! @param[in] format 書式文字列。 //! @param[in] args 文字列パラメータ。 //! void CalcVStringRect( ut::Rect* pRect, const CharType* format, std::va_list args ) const; //! @brief 文字列の描画矩形を計算します。 //! //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 //! @param[in] str 文字列。 //! void CalcStringRect( ut::Rect* pRect, const CharType* str ) const { NN_POINTER_ASSERT(pRect); NN_POINTER_ASSERT(str); CalcStringRect(pRect, str, StrLen(str)); } //! @brief 文字列の描画矩形を計算します。 //! //! @param[out] pRect 文字列描画矩形を受け取るバッファへのポインタ。 //! @param[in] str 文字列。 //! @param[in] length 文字列長。 //! void CalcStringRect( ut::Rect* pRect, const CharType* str, int length ) const; //@} //! @name 文字列描画 //@{ //! @brief 文字列を描画します。 //! //! @param[in] format 書式文字列。 //! @param[in] ... 文字列パラメータ //! //! @return 文字列の幅を返します。 //! f32 Printf( const CharType* format, ... ); //! @brief 文字列を描画します。 //! //! @param[in] format 書式文字列。 //! @param[in] args 文字列パラメータ。 //! //! @return 文字列の幅を返します。 //! f32 VPrintf( const CharType* format, std::va_list args); //! @brief 文字列を描画します。 //! //! @param[in] str 文字列。 //! //! @return 文字列の幅を返します。 //! f32 Print( const CharType* str ) { NN_POINTER_ASSERT(str); return Print(str, StrLen(str)); } //! @brief 文字列を描画します。 //! //! @param[in] str 文字列。 //! @param[in] length 文字列長。 //! //! @return 文字列の幅を返します。 //! f32 Print( const CharType* str, int length); //@} //! @name 書式展開バッファ //@{ //! @brief 書式文字列展開用のバッファを割り当てます。 //! //! @param[in] size バッファサイズ。 //! //! @return 以前に TextWriter に割り当てられたバッファが存在する場合には //! そのバッファへのポインタを返します。 //! 割り当てられたバッファが存在しない場合には NULL を返します。 //! static void* SetBuffer( std::size_t size ) { NW_FONT_MIN_ASSERT(size, 1); void* oldBuffer = s_FormatBuffer; s_FormatBuffer = NULL; s_FormatBufferSize = size; return oldBuffer; } //! @brief 書式文字列展開用のバッファを割り当てます。 //! //! @param[in] buffer TextWriter に割り当てるバッファへのポインタ。 //! @param[in] size バッファサイズ。 //! //! @return 以前に TextWriter に割り当てられたバッファが存在する場合には //! そのバッファへのポインタを返します。 //! 割り当てられたバッファが存在しない場合には NULL を返します。 //! static void* SetBuffer( CharType* buffer, std::size_t size ) { NN_POINTER_ASSERT(buffer); NW_FONT_MIN_ASSERT(size, 1); void* oldBuffer = s_FormatBuffer; s_FormatBuffer = buffer; s_FormatBufferSize = size; return oldBuffer; } //! @brief 書式文字列展開用のバッファへのポインタを取得します。 //! //! @return 書式文字列展開用のバッファへのポインタを返します。 //! static const void* GetBuffer() { return s_FormatBuffer; } //! @brief 書式文字列展開用のバッファサイズを取得します。 //! //! @return 書式文字列展開用のバッファのサイズを返します。 //! static std::size_t GetBufferSize() { return s_FormatBufferSize; } //@} //---- vsnprintf の 分岐 static int VSNPrintf( char* buffer, std::size_t count, const char* format, std::va_list arg ) { #if ! defined(_MSC_VER) using namespace std; #endif return vsnprintf(buffer, count, format, arg); } static int VSNPrintf( wchar_t* buffer, std::size_t count, const wchar_t* format, std::va_list arg ) { #if ! defined(_MSC_VER) using namespace std; #endif return vswprintf(buffer, count, format, arg); } static int StrLen(const char* str) { return static_cast(std::strlen(str)); } static int StrLen(const wchar_t* str) { return static_cast(std::wcslen(str)); } using CharWriter::Print; #if defined(NW_FONT_PROFILE) void PrintProfile(); #endif protected: #if defined(NW_FONT_PROFILE) void CopyProfileData(const TextWriterBase& other) const; #endif private: /* ------------------------------------------------------------------------ 型 ------------------------------------------------------------------------ */ typedef TagProcessorBase TagProcessor; typedef const CharType* StreamType; /* ------------------------------------------------------------------------ 定数 ------------------------------------------------------------------------ */ static const int DEFAULT_FORMAT_BUFFER_SIZE = 256; /* ------------------------------------------------------------------------ 関数 ------------------------------------------------------------------------ */ //! @brief 1行の長さを計算します。 //! //! @param[in] str 文字列 //! @param[in] length 文字列長(sizeof(CharType)単位) //! f32 CalcLineWidth( StreamType str, int length); //! @brief 1行分の描画矩形を計算します。 //! //! @param[out] pRect 描画矩形を格納するバッファへのポインタ。 //! @param[in,out] pStr 文字列へのポインタを格納するバッファへのポインタ。 //! @param[in] length 文字列長(sizeof(CharType)単位) //! //! @return WidthLimit を超えたら true を、超えなければ false を返します。 //! bool CalcLineRectImpl( ut::Rect* pRect, StreamType* pStr, int length); //! @brief 文字列の描画矩形を計算します。 //! //! @param[out] pRect 描画矩形を格納するバッファへのポインタ。 //! @param[in] str 文字列 //! @param[in] length 文字列長(sizeof(CharType)単位) //! void CalcStringRectImpl( ut::Rect* pRect, StreamType str, int length); //! @brief 文字列を描画します。 //! //! @param[in] str 文字列 //! @param[in] length 文字列長(sizeof(CharType)単位) //! f32 PrintImpl( StreamType str, int length); //! @brief 文字列を描画フラグに従って描画するときの1文字目の //! 描画開始位置にカーソルを移動します。 //! //! @param[in,out] pXOrigin 描画基準座標を格納したバッファへのポインタ。 //! 補正後の描画基準座標が格納されて返る。 //! @param[in,out] pYOrigin 描画基準座標を格納したバッファへのポインタ。 //! 補正後の描画基準座標が格納されて返る。 //! @param[in] str 文字列 //! @param[in] length 文字列長(sizeof(CharType)単位) //! //! @return 文字列の幅を返します。 //! f32 AdjustCursor( f32* pXOrigin, f32* pYOrigin, StreamType str, int length); //! @brief 描画フラグが設定されているか判定します。 //! //! @param[in] mask 描画フラグのマスク値。 //! @param[in] flag 判定する描画フラグ。 //! //! @return 指定された描画フラグが設定されている場合は真を返します。 //! bool IsDrawFlagSet( u32 mask, u32 flag ) const { return (m_DrawFlag & mask) == flag; } /* ------------------------------------------------------------------------ 変数 ------------------------------------------------------------------------ */ static CharType* s_FormatBuffer; //!< sprintfバッファへのポインタ static std::size_t s_FormatBufferSize; //!< sprintfバッファのサイズ //! デフォルトタグプロセッサ static TagProcessor s_DefaultTagProcessor; f32 m_WidthLimit; //!< 描画幅制限 f32 m_CharSpace; //!< 文字間 f32 m_LineSpace; //!< 行間 int m_TabWidth; //!< タブ幅 u32 m_DrawFlag; //!< 描画フラグ TagProcessor* m_TagProcessor; //!< タグ処理機 #if defined(NW_FONT_PROFILE) mutable Stopwatch m_PrintTextSw; mutable u32 m_PrintTextCount; #endif }; } // namespace font } // namespace nw #endif // NW_FONT_TEXTWRITERBASE_H_