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