1 /*---------------------------------------------------------------------------* 2 Project: NintendoWare 3 File: font_PackedFont.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_PACKEDFONT_H_ 17 #define NW_FONT_PACKEDFONT_H_ 18 19 #include <nn/types.h> 20 #include <nw/font/font_ArchiveFontBase.h> 21 22 namespace nw { 23 namespace font { 24 25 26 //--------------------------------------------------------------------------- 27 //! @brief 圧縮されているフォントリソースをそのままメモリ上に持ち、 28 //! グリフを要求された場合に、必要に応じて展開して使用するクラスです。 29 //--------------------------------------------------------------------------- 30 class PackedFont : public ArchiveFontBase 31 { 32 public: 33 /* ------------------------------------------------------------------------ 34 関数 35 ------------------------------------------------------------------------ */ 36 //! @name コンストラクタ / デストラクタ 37 //@{ 38 39 //! コンストラクタです。 40 PackedFont(); 41 42 //! デストラクタです。 43 virtual ~PackedFont(); 44 45 //@} 46 47 //! @name リソースの関連付け / 解除 48 //@{ 49 50 //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 51 //! 52 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への 53 //! ポインタ。 54 //! @param[in] numSheetCache 展開したシートをキャッシュする最大枚数。 55 //! 56 //! @return Construct() 関数または InitStreamingConstruct() 関数で 57 //! フォントを構築する場合に必要なバッファのサイズを返します。@n 58 //! リソース @a bfnt が不正である等の理由でバッファサイズが 59 //! 計算できなかった場合は 0 を返します。 60 //! GetRequireBufferSize(const void * bfnt,int numSheetCache)61 static u32 GetRequireBufferSize( 62 const void* bfnt, 63 int numSheetCache 64 ) 65 { 66 return GetRequireBufferSize(bfnt, LOAD_GLYPH_ALL, numSheetCache); 67 } 68 69 //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 70 //! 71 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への 72 //! ポインタ。 73 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 74 //! @param[in] numSheetCache 展開したシートをキャッシュする最大枚数。 75 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 76 //! シートの枚数に対する割合。 77 //! 78 //! @return Construct() 関数または InitStreamingConstruct() 関数で 79 //! フォントを構築する場合に必要なバッファのサイズを返します。@n 80 //! リソース @a bfnt が不正である等の理由でバッファサイズが 81 //! 計算できなかった場合は 0 を返します。 82 //! 83 static u32 GetRequireBufferSize( 84 const void* bfnt, 85 const char* glyphGroups, 86 int numSheetCache); 87 88 //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 89 //! 90 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への 91 //! ポインタ。 92 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 93 //! シートの枚数に対する割合。 94 //! 95 //! @return Construct() 関数または InitStreamingConstruct() 関数で 96 //! フォントを構築する場合に必要なバッファのサイズを返します。@n 97 //! リソース @a bfnt が不正である等の理由でバッファサイズが 98 //! 計算できなかった場合は 0 を返します。 99 //! GetRequireBufferSize(const void * bfnt,f32 rateSheetCache)100 static u32 GetRequireBufferSize( 101 const void* bfnt, 102 f32 rateSheetCache 103 ) 104 { 105 return GetRequireBufferSize(bfnt, LOAD_GLYPH_ALL, rateSheetCache); 106 } 107 108 //! @brief フォントを構築するのに必要なバッファのサイズを計算します。 109 //! 110 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt)先頭部分への 111 //! ポインタ。 112 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 113 //! @param[in] rateSheetCache 展開したシートをキャッシュする最大枚数の、 114 //! シートの枚数に対する割合。 115 //! 116 //! @return Construct() 関数または InitStreamingConstruct() 関数で 117 //! フォントを構築する場合に必要なバッファのサイズを返します。@n 118 //! リソース @a bfnt が不正である等の理由でバッファサイズが 119 //! 計算できなかった場合は 0 を返します。 120 //! 121 static u32 GetRequireBufferSize( 122 const void* bfnt, 123 const char* glyphGroups, 124 f32 rateSheetCache 125 ); 126 127 //! @brief アーカイブフォントからグリフグループを抽出しフォントを構築します。 128 //! 129 //! @param[out] pBuffer このインスタンスに関連付けるバッファへのポインタ。 130 //! 128byte アライメントされている必要があります。 131 //! @param[in] bufferSize @a pBuffer が指すバッファのサイズ。 132 //! @param[in] bfnt メモリ上にロード済みのバイナリリソース(bfnt) へのポインタ。 133 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 134 //! 135 //! @return フォントの構築が成功したなら true を、そうでなければ false を返します。@n 136 //! アーカイブフォント @a bfnt が不正であったり 137 //! バッファサイズが小さすぎると失敗します。 138 //! 139 bool Construct( 140 void* pBuffer, 141 u32 bufferSize, 142 const void* bfnt, 143 const char* glyphGroups = LOAD_GLYPH_ALL 144 ); 145 146 //! @brief アーカイブフォントから順次読み込みでグリフグループを抽出し、 147 //! フォントを構築するための初期化を行います。 148 //! 149 //! @param[out] pContext 初期化するストリーミング構築コンテキストへのポインタ。 150 //! @param[out] pBuffer このインスタンスに関連付けるバッファへのポインタ。 151 //! 128byte アライメントされている必要があります。 152 //! @param[in] bufferSize @a pBuffer が指すバッファのサイズ。 153 //! @param[in] glyphGroups ロードするグリフグループを指定する文字列。 154 //! 155 void InitStreamingConstruct( 156 ConstructContext* pContext, 157 void* pBuffer, 158 u32 bufferSize, 159 const char* glyphGroups = LOAD_GLYPH_ALL 160 ); 161 162 //! @brief アーカイブフォントから順次読み込みでフォントを構築します。 163 //! 164 //! @param[out] pContext InitStreamingConstruct() 関数で初期化した 165 //! ストリーミング構築コンテキストへのポインタ。 166 //! @param[in] stream アーカイブフォントの一部を格納したバッファへのポインタ。 167 //! @param[in] streamSize @a stream が指すバッファに格納されているデータのバイト数。 168 //! 169 //! @return 構築処理の経過状態を返します。 170 //! 171 ConstructResult StreamingConstruct( 172 ConstructContext* pContext, 173 const void* stream, 174 u32 streamSize); 175 176 //! @brief フォントを破棄します。 177 //! 178 //! @return Construct() 関数または InitStreamingConstruct() 関数で、 179 //! このインスタンスに割り当てたメモリ領域へのポインタを返します。 180 //! 181 void* Destroy(); 182 183 //@} 184 185 186 //! @name キャッシュ管理 187 //@{ 188 189 //! @brief キャッシュの数を取得します。 190 //! 191 //! @return キャッシュの数を返します。 192 //! GetNumCache()193 int GetNumCache() const { return m_NumSheetCache; } 194 195 //! @brief シートをあらかじめキャッシュに読み込みます。 196 //! 197 //! @param[in] c ロードするシートに含まれるグリフを指す文字コード。 198 //! 199 //! @return シートを新たにキャッシュした場合は true を、 200 //! 既にキャッシュ済みだった場合は false を返します。 201 //! 202 bool PreloadSheet(CharCode c); 203 204 //! @brief キャッシュ上のシートを破棄されないようにします。 205 //! 206 //! @param[in] c ロックするシートに含まれるグリフを指す文字コード。 207 //! 208 //! @return ロックを行った場合は true を、 209 //! ロックを行えなかった場合は false を返します。@n 210 //! ロックできるシートの最大数を超える場合にはロックは行えません。 211 //! 212 bool LockSheet(CharCode c); 213 214 //! @brief シートのロックを解除します。 215 //! 216 //! @param[in] c ロックを解除するシートに含まれるグリフを指す文字コード。 217 //! @param[in] bUnload ロック解除後、さらにキャッシュを破棄するならば、true を指定します。 218 //! 219 //! @return 対象のシートがキャッシュ上に存在しなかった場合には false を返します。 220 //! 221 bool UnlockSheet( 222 CharCode c, 223 bool bUnload = true 224 ); 225 226 //! @brief 全てのシートのロックを解除します。 227 //! 228 void UnlockSheetAll(); 229 230 //@} 231 232 233 //! @name 文字情報の取得 234 //@{ 235 236 //! @brief グリフデータを取得します。 237 //! 238 //! @param[out] glyph グリフデータを受け取るバッファへのポインタ。 239 //! @param[in] c グリフデータを取得する文字の文字コード。 240 //! 241 virtual void GetGlyph( 242 Glyph* glyph, 243 CharCode c 244 ) const; 245 246 //@} 247 248 249 protected: 250 251 //! @name シート情報の取得 252 //@{ 253 254 virtual int GetActiveSheetNum() const; 255 256 //@} 257 258 259 private: 260 /* ------------------------------------------------------------------------ 261 型 262 ------------------------------------------------------------------------ */ 263 // Leaset Recently Used 管理のためのクラス 264 class LRUManager 265 { 266 public: 267 struct OrderNode 268 { 269 u16 prevIndex; 270 u16 nextIndex; 271 }; 272 GetRequireBufferSize(int numNode)273 static u32 GetRequireBufferSize(int numNode) 274 { 275 return sizeof(OrderNode) * (numNode + 1); 276 } 277 278 //! @brief 初期化します。 279 //! 280 //! @param[in] buffer: LRUManager に割り当てるバッファを指定します。 281 //! @param[in] numOrderNode LRU管理するオブジェクトの数を指定します。 282 //! 283 void Init( 284 void* buffer, 285 int numOrderNode); 286 287 //! @brief Use されたことを記録します。 288 //! 289 //! @param[in] index Use されたオブジェクトの番号。 290 //! 291 void Use(int index); 292 293 //! @brief 最も最後に使用されたことにします。 294 //! 295 //! @param[in] index LRU にするブジェクトの番号。 296 //! 297 void Unuse(int index); 298 299 //! @brief LRU 管理対象から除外します。 300 //! 301 //! @param[in] index ロックするオブジェクトの番号。 302 //! 303 void Lock(int index); 304 305 //! @brief LRU 管理対象に戻します。 306 //! 307 //! @param[in] index ロック解除するオブジェクトの番号。 308 //! 309 void Unlock(int index); 310 GetLastIndex()311 int GetLastIndex() const { return GetRootNode().prevIndex; } 312 IsLocked(int index)313 bool IsLocked(int index) const 314 { 315 const OrderNode& node = GetNode(index); 316 return IsLockedNode(node); 317 } 318 GetNumLocked()319 int GetNumLocked() const { return mNumLockedNode; } 320 321 private: IsLockedNode(const OrderNode & node)322 bool IsLockedNode(const OrderNode& node) const 323 { 324 NN_ASSERT( ! (node.prevIndex == LOCKED_INDEX) ^ (node.nextIndex == LOCKED_INDEX) ); 325 return (node.prevIndex == LOCKED_INDEX); 326 } 327 MarkLocked(OrderNode & node)328 void MarkLocked(OrderNode& node) const 329 { 330 node.prevIndex = LOCKED_INDEX; 331 node.nextIndex = LOCKED_INDEX; 332 } 333 Unlink(OrderNode & node)334 void Unlink(OrderNode& node) 335 { 336 OrderNode& prev = GetNode(node.prevIndex); 337 OrderNode& next = GetNode(node.nextIndex); 338 prev.nextIndex = node.nextIndex; 339 next.prevIndex = node.prevIndex; 340 } 341 GetRootNode()342 OrderNode& GetRootNode() { return GetNode(mNumOrderNode); } 343 GetRootNode()344 const OrderNode& GetRootNode() const { return GetNode(mNumOrderNode); } 345 GetNode(int index)346 OrderNode& GetNode(int index) { return mpOrderNodeArray[index]; } 347 GetNode(int index)348 const OrderNode& GetNode(int index) const { return mpOrderNodeArray[index]; } 349 350 private: 351 static const u16 LOCKED_INDEX = 0xFFFF; 352 353 OrderNode* mpOrderNodeArray; 354 u16 mNumOrderNode; 355 u16 mNumLockedNode; 356 }; 357 358 359 /* ------------------------------------------------------------------------ 360 定数 361 ------------------------------------------------------------------------ */ 362 static const u16 SHEET_INDEX_NOT_LOADED = 0xFFFF; 363 364 365 /* ------------------------------------------------------------------------ 366 関数 367 ------------------------------------------------------------------------ */ 368 //---- グリフの取得 369 370 //! @brief Glyph 構造体にグリフの情報を格納します。 371 //! 372 //! @param[out] glyph: 情報の格納先となる構造体へのポインタ。 373 //! @param[in] gindex: 情報を格納するグリフを指すグリフインデックス。 374 //! @param[in] cacheIndex: gindex が指すグリフのグリフイメージが含まれた 375 //! シートが展開されているキャッシュ領域番号。 376 //! 377 void MakeGlyph( 378 Glyph* glyph, 379 GlyphIndex gindex, 380 int cacheIndex 381 ) const; 382 383 //---- シートの解凍 384 385 //! @brief 圧縮シートを展開してキャッシュします。 386 //! 387 //! @param[in] compIndex 圧縮シート番号 388 //! 389 //! @return 展開したシートがキャッシュされたキャッシュ領域番号 390 //! 391 int LoadSheet(int compIndex) const; 392 393 //! @brief キャッシュされているシートを破棄します。 394 //! 395 //! @param[in] compIndex 圧縮シート番号。 396 //! 397 void UnloadSheet(int compIndex) const; 398 399 //---- シート状態の管理 400 401 //! @brief 文字コードからその文字コードが表すグリフを含むシートの 402 //! 番号を取得します。 403 //! 404 //! @param[in] c 文字コード。 405 //! 406 //! @return c で指定される文字コードが表すグリフが含まれるシートの番号。 407 //! 408 int GetSheetIndex(CharCode c) const; 409 410 //! @brief 調整済みグリフインデックスからそのグリフが含まれる 411 //! シート番号を計算します。 412 //! 413 //! @param[in] index グリフインデックス。 414 //! 415 //! @return index で指定されるグリフが含まれるシートの番号。 416 //! 417 int CalcSheetIndex(GlyphIndex index) const; 418 419 //! @brief 圧縮シートを展開したデータがキャッシュされている 420 //! キャッシュ領域番号を取得します。 421 //! 422 //! @param[in] compIndex 問い合わせる圧縮シート番号。 423 //! 424 //! @return compIndex で指定される圧縮シートを展開したデータが 425 //! キャッシュされているキャッシュ領域番号を返します。 426 //! キャッシュが存在しない場合は SHEET_INDEX_NOT_LOADED を返します。 427 //! 428 int GetCacheIndex(int compIndex) const; 429 430 //! @brief あるキャッシュに格納されているデータがどの圧縮シートを 431 //! 展開した物かを取得します。 432 //! 433 //! @param[in] cacheIndex 問い合わせるキャッシュ番号。 434 //! 435 //! @return cacheIndex に格納されているデータの展開元圧縮シート番号を 436 //! 返します。 437 //! 格納されているデータが意味を持たない場合は 438 //! SHEET_INDEX_NOT_LOADED を返します。 439 //! 440 int GetCacheUser(int cacheIndex) const; 441 442 //! @brief 圧縮シートを展開したデータが格納されている 443 //! キャッシュ番号を記録します。 444 //! 445 //! @param[in] compIndex 圧縮シート番号。 446 //! @param[in] cacheIndex compIndex で指定される圧縮シートを展開したデータが 447 //! 格納されているキャッシュ番号 448 //! 449 void SetCacheUser( 450 int compIndex, 451 int cacheIndex 452 ) const; 453 454 //! @brief 圧縮シートとキャッシュの関係を消去します。 455 //! 456 //! @param[in] compIndex 圧縮シート番号。 457 //! @param[in] cacheIndex compIndex で指定される圧縮シートを展開したデータが 458 //! 格納されていたキャッシュ番号。 459 //! 460 void ResetCacheUser( 461 int compIndex, 462 int cacheIndex 463 ) const; 464 465 //---- シートの取得 466 467 //! @brief 展開済みシートキャッシュ先頭へのポインタを取得します。 468 //! 469 //! @param[in] cacheIndex キャッシュ番号。 470 //! 471 //! @return cacheIndex で指定されるキャッシュの先頭へのポインタを返します。 472 //! 473 u8* GetLoadedSheet(int cacheIndex) const; 474 475 //! @brief 圧縮シートの先頭へのポインタを取得します。 476 //! 477 //! @param[in] compIndex 圧縮シート番号。 478 //! 479 //! @return compIndex で指定される圧縮シートの先頭へのポインタを返します。 480 //! 481 const u8* GetCompSheet(int compIndex) const; 482 483 //---- メモリ割り当て 484 485 //! @brief バッファを分配し各メンバに割り当てます。 486 //! 487 //! @param buffer: 割り当てるメモリ領域へのポインタ。 488 //! @param bufferSize: buffer のサイズ。 489 //! @param numResSheet: リソースに含まれるシートの総数。 490 //! @param numLoadSheet: メモリ上にロードするシートの枚数。 491 //! @param sheetSize: 展開したシートサイズ。 492 //! 493 //! @return buffer 上に割り当てたグリフインデックス調整テーブルへの 494 //! ポインタを返します。 495 //! buffer が小さすぎる場合は NULL を返します。 496 //! 497 u16* AssignMemory( 498 u8* buffer, 499 u32 bufferSize, 500 u32 numResSheet, 501 u32 numLoadSheet, 502 u32 sheetSize); 503 504 505 //---- 必要メモリサイズ計算 506 507 //! @brief フォントリソース格納領域に必要なバッファサイズを計算します。 508 //! 509 //! @param[in] gg GLGR ブロックアクセサ。 510 //! @param[in] glyphGroups ロードするグリフグループ。 511 //! @param[in] pNumLoadSheet ロードするシートの枚数を格納するバッファへの 512 //! ポインタ。 513 //! 514 //! @return フォントリソース格納領域に必要なバッファサイズを返します。 515 //! 516 static u32 CalcCopySize( 517 const FontGlyphGroupsAcs& gg, 518 const char* glyphGroups, 519 int* pNumLoadSheet); 520 521 //! @brief キャッシュ領域に必要なバッファサイズを計算します。 522 //! 523 //! @param[in] gg GLGR ブロックアクセサ。 524 //! @param[in] numSheetCache 確保するシートキャッシュの数。 525 //! 526 //! @return キャッシュ領域に必要なバッファサイズを返します。 527 //! 528 static u32 CalcCacheSize( 529 const FontGlyphGroupsAcs& gg, 530 int numSheetCache); 531 532 //---- ストリーミング処理 533 534 //! @brief GLGR ブロックを処理します。 535 //! 536 //! @param pContext ストリーム構築コンテキスト。 537 //! @param pStream 入力ストリーム。 538 //! 539 //! @return 処理状態を返します。 540 //! 541 ConstructResult ConstructOpAnalyzeGLGRPacked( 542 ConstructContext* pContext, 543 CachedStreamReader* pStream); 544 545 //! @brief シートのコピー処理をセットアップします。 546 //! 547 //! @param pContext ストリーム構築コンテキスト。 548 //! @param pStream 入力ストリーム。 549 //! 550 //! @return 処理状態を返します。 551 //! 552 static ConstructResult 553 ConstructOpPrepairCopyPackedSheet( 554 ConstructContext* pContext, 555 CachedStreamReader* pStream); 556 557 /* ------------------------------------------------------------------------ 558 変数 559 ------------------------------------------------------------------------ */ 560 //! 解凍済みシートのキャッシュ状態を管理するオブジェクト 561 mutable LRUManager m_LRUMan; 562 563 u16 m_NumCompSheet; //!< ロードしたシートの数 564 u16 m_NumSheetCache; //!< シートキャッシュの数 565 566 //! シート番号から使用しているキャッシュ領域番号を引くためのテーブル 567 u16* m_pCacheIndexArray; // mNumLoadedSheet 568 569 //! キャッシュ領域番号からキャッシュされているシート番号を引くためのテーブル 570 u16* m_pCacheUserArray; // m_NumSheetCache 571 572 //! 圧縮済みシートへのポインタの配列 573 const u8** m_pCompSheetArray; // mNumLoadedSheet 574 575 //! シートキャッシュ領域へのポインタ 576 u8* m_pSheetCache; // sheetSize * m_NumSheetCache 577 }; 578 579 } // namespace font 580 } // namespace nw 581 582 #endif // NW_FONT_PACKEDFONT_H_ 583