/*---------------------------------------------------------------------------* Project: Horizon File: font_PackedFont.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. 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. $Revision: 25674 $ *---------------------------------------------------------------------------*/ #ifndef NN_FONT_FONT_PACKED_FONT_H_ #define NN_FONT_FONT_PACKED_FONT_H_ #include #include namespace nn { namespace font { //--------------------------------------------------------------------------- //! @brief 圧縮されているフォントリソースをそのままメモリ上に持ち、 //! グリフを要求された場合に、必要に応じて展開して使用するクラスです。 //--------------------------------------------------------------------------- class PackedFont : public ArchiveFontBase { public: /* ------------------------------------------------------------------------ 関数 ------------------------------------------------------------------------ */ //! @name コンストラクタ / デストラクタ //@{ //! コンストラクタです。 PackedFont(); //! デストラクタです。 virtual ~PackedFont(); //@} //! @name リソースの関連付け / 解除 //@{ //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 //! //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への //! ポインタ。 //! @param[in] numSheetCache 展開したシートをキャッシュする最大枚数。 //! //! @return Construct() 関数または InitStreamingConstruct() 関数で //! フォントを構築する場合に必要なバッファのサイズを返します。@n //! リソース @a bfnt が不正である等の理由でバッファサイズが //! 計算できなかった場合は 0 を返します。 //! static u32 GetRequireBufferSize( const void* bfnt, int numSheetCache ) { return GetRequireBufferSize(bfnt, LOAD_GLYPH_ALL, numSheetCache); } //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 //! //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への //! ポインタ。 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 //! @param[in] numSheetCache 展開したシートをキャッシュする最大枚数。 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 //! シートの枚数に対する割合。 //! //! @return Construct() 関数または InitStreamingConstruct() 関数で //! フォントを構築する場合に必要なバッファのサイズを返します。@n //! リソース @a bfnt が不正である等の理由でバッファサイズが //! 計算できなかった場合は 0 を返します。 //! static u32 GetRequireBufferSize( const void* bfnt, const char* glyphGroups, int numSheetCache); //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 //! //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への //! ポインタ。 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 //! シートの枚数に対する割合。 //! //! @return Construct() 関数または InitStreamingConstruct() 関数で //! フォントを構築する場合に必要なバッファのサイズを返します。@n //! リソース @a bfnt が不正である等の理由でバッファサイズが //! 計算できなかった場合は 0 を返します。 //! static u32 GetRequireBufferSize( const void* bfnt, f32 rateSheetCache ) { return GetRequireBufferSize(bfnt, LOAD_GLYPH_ALL, rateSheetCache); } //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 //! //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への //! ポインタ。 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 //! シートの枚数に対する割合。 //! //! @return Construct() 関数または InitStreamingConstruct() 関数で //! フォントを構築する場合に必要なバッファのサイズを返します。@n //! リソース @a bfnt が不正である等の理由でバッファサイズが //! 計算できなかった場合は 0 を返します。 //! static u32 GetRequireBufferSize( const void* bfnt, const char* glyphGroups, f32 rateSheetCache ); //! @brief アーカイブフォントからグリフグループを抽出しフォントを構築します。 //! //! @param[out] pBuffer このインスタンスに関連付けるバッファへのポインタ。 //! 128byte アライメントされている必要があります。 //! @param[in] bufferSize @a pBuffer が指すバッファのサイズ。 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt) へのポインタ。 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 //! //! @return フォントの構築が成功したなら true を、そうでなければ false を返します。@n //! アーカイブフォント @a bfnt が不正であったり //! バッファサイズが小さすぎると失敗します。 //! bool Construct( void* pBuffer, u32 bufferSize, const void* bfnt, const char* glyphGroups = LOAD_GLYPH_ALL ); //! @brief アーカイブフォントから順次読み込みでグリフグループを抽出し、 //! フォントを構築するための初期化を行います。 //! //! @param[out] pContext 初期化するストリーミング構築コンテキストへのポインタ。 //! @param[out] pBuffer このインスタンスに関連付けるバッファへのポインタ。 //! 128byte アライメントされている必要があります。 //! @param[in] bufferSize @a pBuffer が指すバッファのサイズ。 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 //! void InitStreamingConstruct( ConstructContext* pContext, void* pBuffer, u32 bufferSize, const char* glyphGroups = LOAD_GLYPH_ALL ); //! @brief アーカイブフォントから順次読み込みでフォントを構築します。 //! //! @param[out] pContext InitStreamingConstruct() 関数で初期化した //! ストリーミング構築コンテキストへのポインタ。 //! @param[in] stream アーカイブフォントの一部を格納したバッファへのポインタ。 //! @param[in] streamSize @a stream が指すバッファに格納されているデータのバイト数。 //! //! @return 構築処理の経過状態を返します。 //! ConstructResult StreamingConstruct( ConstructContext* pContext, const void* stream, u32 streamSize); //! @brief フォントを破棄します。 //! //! @return Construct() 関数または InitStreamingConstruct() 関数で、 //! このインスタンスに割り当てたメモリ領域へのポインタを返します。 //! void* Destroy(); //@} //! @name キャッシュ管理 //@{ //! @brief キャッシュの数を取得します。 //! //! @return キャッシュの数を返します。 //! int GetNumCache() const { return m_NumSheetCache; } //! @brief シートをあらかじめキャッシュに読み込みます。 //! //! @param[in] c ロードするシートに含まれるグリフを指す文字コード。 //! //! @return シートを新たにキャッシュした場合は true を、 //! 既にキャッシュ済みだった場合は false を返します。 //! bool PreloadSheet(CharCode c); //! @brief キャッシュ上のシートを破棄されないようにします。 //! //! @param[in] c ロックするシートに含まれるグリフを指す文字コード。 //! //! @return ロックを行った場合は true を、 //! ロックを行えなかった場合は false を返します。@n //! ロックできるシートの最大数を超える場合にはロックは行えません。 //! bool LockSheet(CharCode c); //! @brief シートのロックを解除します。 //! //! @param[in] c ロックを解除するシートに含まれるグリフを指す文字コード。 //! @param[in] bUnload ロック解除後、さらにキャッシュを破棄するならば、true を指定します。 //! //! @return 対象のシートがキャッシュ上に存在しなかった場合には false を返します。 //! bool UnlockSheet( CharCode c, bool bUnload = true ); //! @brief 全てのシートのロックを解除します。 //! void UnlockSheetAll(); //@} //! @name 文字情報の取得 //@{ //! @brief グリフデータを取得します。 //! //! @param[out] glyph グリフデータを受け取るバッファへのポインタ。 //! @param[in] c グリフデータを取得する文字の文字コード。 //! virtual void GetGlyph( Glyph* glyph, CharCode c ) const; //@} protected: //! @name シート情報の取得 //@{ virtual int GetActiveSheetNum() const; //@} private: /* ------------------------------------------------------------------------ 型 ------------------------------------------------------------------------ */ // Leaset Recently Used 管理のためのクラス class LRUManager { public: struct OrderNode { u16 prevIndex; u16 nextIndex; }; static u32 GetRequireBufferSize(int numNode) { return sizeof(OrderNode) * (numNode + 1); } //! @brief 初期化します。 //! //! @param[in] buffer: LRUManager に割り当てるバッファを指定します。 //! @param[in] numOrderNode LRU管理するオブジェクトの数を指定します。 //! void Init( void* buffer, int numOrderNode); //! @brief Use されたことを記録します。 //! //! @param[in] index Use されたオブジェクトの番号。 //! void Use(int index); //! @brief 最も最後に使用されたことにします。 //! //! @param[in] index LRU にするブジェクトの番号。 //! void Unuse(int index); //! @brief LRU 管理対象から除外します。 //! //! @param[in] index ロックするオブジェクトの番号。 //! void Lock(int index); //! @brief LRU 管理対象に戻します。 //! //! @param[in] index ロック解除するオブジェクトの番号。 //! void Unlock(int index); int GetLastIndex() const { return GetRootNode().prevIndex; } bool IsLocked(int index) const { const OrderNode& node = GetNode(index); return IsLockedNode(node); } int GetNumLocked() const { return mNumLockedNode; } private: bool IsLockedNode(const OrderNode& node) const { NN_ASSERT( ! (node.prevIndex == LOCKED_INDEX) ^ (node.nextIndex == LOCKED_INDEX) ); return (node.prevIndex == LOCKED_INDEX); } void MarkLocked(OrderNode& node) const { node.prevIndex = LOCKED_INDEX; node.nextIndex = LOCKED_INDEX; } void Unlink(OrderNode& node) { OrderNode& prev = GetNode(node.prevIndex); OrderNode& next = GetNode(node.nextIndex); prev.nextIndex = node.nextIndex; next.prevIndex = node.prevIndex; } OrderNode& GetRootNode() { return GetNode(mNumOrderNode); } const OrderNode& GetRootNode() const { return GetNode(mNumOrderNode); } OrderNode& GetNode(int index) { return mpOrderNodeArray[index]; } const OrderNode& GetNode(int index) const { return mpOrderNodeArray[index]; } private: static const u16 LOCKED_INDEX = 0xFFFF; OrderNode* mpOrderNodeArray; u16 mNumOrderNode; u16 mNumLockedNode; }; /* ------------------------------------------------------------------------ 定数 ------------------------------------------------------------------------ */ static const u16 SHEET_INDEX_NOT_LOADED = 0xFFFF; /* ------------------------------------------------------------------------ 関数 ------------------------------------------------------------------------ */ //---- グリフの取得 //! @brief Glyph 構造体にグリフの情報を格納します。 //! //! @param[out] glyph: 情報の格納先となる構造体へのポインタ。 //! @param[in] gindex: 情報を格納するグリフを指すグリフインデックス。 //! @param[in] cacheIndex: gindex が指すグリフのグリフイメージが含まれた //! シートが展開されているキャッシュ領域番号。 //! void MakeGlyph( Glyph* glyph, GlyphIndex gindex, int cacheIndex ) const; //---- シートの解凍 //! @brief 圧縮シートを展開してキャッシュします。 //! //! @param[in] compIndex 圧縮シート番号 //! //! @return 展開したシートがキャッシュされたキャッシュ領域番号 //! int LoadSheet(int compIndex) const; //! @brief キャッシュされているシートを破棄します。 //! //! @param[in] compIndex 圧縮シート番号。 //! void UnloadSheet(int compIndex) const; //---- シート状態の管理 //! @brief 文字コードからその文字コードが表すグリフを含むシートの //! 番号を取得します。 //! //! @param[in] c 文字コード。 //! //! @return c で指定される文字コードが表すグリフが含まれるシートの番号。 //! int GetSheetIndex(CharCode c) const; //! @brief 調整済みグリフインデックスからそのグリフが含まれる //! シート番号を計算します。 //! //! @param[in] index グリフインデックス。 //! //! @return index で指定されるグリフが含まれるシートの番号。 //! int CalcSheetIndex(GlyphIndex index) const; //! @brief 圧縮シートを展開したデータがキャッシュされている //! キャッシュ領域番号を取得します。 //! //! @param[in] compIndex 問い合わせる圧縮シート番号。 //! //! @return compIndex で指定される圧縮シートを展開したデータが //! キャッシュされているキャッシュ領域番号を返します。 //! キャッシュが存在しない場合は SHEET_INDEX_NOT_LOADED を返します。 //! int GetCacheIndex(int compIndex) const; //! @brief あるキャッシュに格納されているデータがどの圧縮シートを //! 展開した物かを取得します。 //! //! @param[in] cacheIndex 問い合わせるキャッシュ番号。 //! //! @return cacheIndex に格納されているデータの展開元圧縮シート番号を //! 返します。 //! 格納されているデータが意味を持たない場合は //! SHEET_INDEX_NOT_LOADED を返します。 //! int GetCacheUser(int cacheIndex) const; //! @brief 圧縮シートを展開したデータが格納されている //! キャッシュ番号を記録します。 //! //! @param[in] compIndex 圧縮シート番号。 //! @param[in] cacheIndex compIndex で指定される圧縮シートを展開したデータが //! 格納されているキャッシュ番号 //! void SetCacheUser( int compIndex, int cacheIndex ) const; //! @brief 圧縮シートとキャッシュの関係を消去します。 //! //! @param[in] compIndex 圧縮シート番号。 //! @param[in] cacheIndex compIndex で指定される圧縮シートを展開したデータが //! 格納されていたキャッシュ番号。 //! void ResetCacheUser( int compIndex, int cacheIndex ) const; //---- シートの取得 //! @brief 展開済みシートキャッシュ先頭へのポインタを取得します。 //! //! @param[in] cacheIndex キャッシュ番号。 //! //! @return cacheIndex で指定されるキャッシュの先頭へのポインタを返します。 //! u8* GetLoadedSheet(int cacheIndex) const; //! @brief 圧縮シートの先頭へのポインタを取得します。 //! //! @param[in] compIndex 圧縮シート番号。 //! //! @return compIndex で指定される圧縮シートの先頭へのポインタを返します。 //! const u8* GetCompSheet(int compIndex) const; //---- メモリ割り当て //! @brief バッファを分配し各メンバに割り当てます。 //! //! @param buffer: 割り当てるメモリ領域へのポインタ。 //! @param bufferSize: buffer のサイズ。 //! @param numResSheet: リソースに含まれるシートの総数。 //! @param numLoadSheet: メモリ上にロードするシートの枚数。 //! @param sheetSize: 展開したシートサイズ。 //! //! @return buffer 上に割り当てたグリフインデックス調整テーブルへの //! ポインタを返します。 //! buffer が小さすぎる場合は NULL を返します。 //! u16* AssignMemory( u8* buffer, u32 bufferSize, u32 numResSheet, u32 numLoadSheet, u32 sheetSize); //---- 必要メモリサイズ計算 //! @brief フォントリソース格納領域に必要なバッファサイズを計算します。 //! //! @param[in] gg GLGR ブロックアクセサ。 //! @param[in] glyphGroups ロードするグリフグループ。 //! @param[in] pNumLoadSheet ロードするシートの枚数を格納するバッファへの //! ポインタ。 //! //! @return フォントリソース格納領域に必要なバッファサイズを返します。 //! static u32 CalcCopySize( const FontGlyphGroupsAcs& gg, const char* glyphGroups, int* pNumLoadSheet); //! @brief キャッシュ領域に必要なバッファサイズを計算します。 //! //! @param[in] gg GLGR ブロックアクセサ。 //! @param[in] numSheetCache 確保するシートキャッシュの数。 //! //! @return キャッシュ領域に必要なバッファサイズを返します。 //! static u32 CalcCacheSize( const FontGlyphGroupsAcs& gg, int numSheetCache); //---- ストリーミング処理 //! @brief GLGR ブロックを処理します。 //! //! @param pContext ストリーム構築コンテキスト。 //! @param pStream 入力ストリーム。 //! //! @return 処理状態を返します。 //! ConstructResult ConstructOpAnalyzeGLGRPacked( ConstructContext* pContext, CachedStreamReader* pStream); //! @brief シートのコピー処理をセットアップします。 //! //! @param pContext ストリーム構築コンテキスト。 //! @param pStream 入力ストリーム。 //! //! @return 処理状態を返します。 //! static ConstructResult ConstructOpPrepairCopyPackedSheet( ConstructContext* pContext, CachedStreamReader* pStream); /* ------------------------------------------------------------------------ 変数 ------------------------------------------------------------------------ */ //! 解凍済みシートのキャッシュ状態を管理するオブジェクト mutable LRUManager m_LRUMan; u16 m_NumCompSheet; //!< ロードしたシートの数 u16 m_NumSheetCache; //!< シートキャッシュの数 //! シート番号から使用しているキャッシュ領域番号を引くためのテーブル u16* m_pCacheIndexArray; // mNumLoadedSheet //! キャッシュ領域番号からキャッシュされているシート番号を引くためのテーブル u16* m_pCacheUserArray; // m_NumSheetCache //! 圧縮済みシートへのポインタの配列 const u8** m_pCompSheetArray; // mNumLoadedSheet //! シートキャッシュ領域へのポインタ u8* m_pSheetCache; // sheetSize * m_NumSheetCache }; } // namespace font } // namespace nn #endif // NN_FONT_FONT_PACKED_FONT_H_