2013-07-25 01:22:46 +08:00
/****************************************************************************
Copyright ( c ) 2013 Zynga Inc .
2018-01-29 16:25:32 +08:00
Copyright ( c ) 2013 - 2016 Chukong Technologies Inc .
Copyright ( c ) 2017 - 2018 Xiamen Yaji Software Co . , Ltd .
2013-07-25 01:22:46 +08:00
http : //www.cocos2d-x.org
Permission is hereby granted , free of charge , to any person obtaining a copy
of this software and associated documentation files ( the " Software " ) , to deal
in the Software without restriction , including without limitation the rights
to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
copies of the Software , and to permit persons to whom the Software is
furnished to do so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-07-14 17:53:55 +08:00
# include "2d/CCFontAtlasCache.h"
2013-07-25 01:22:46 +08:00
2015-07-30 11:33:18 +08:00
# include "base/CCDirector.h"
2014-05-01 10:09:13 +08:00
# include "2d/CCFontFNT.h"
# include "2d/CCFontFreeType.h"
2014-08-27 13:39:50 +08:00
# include "2d/CCFontAtlas.h"
# include "2d/CCFontCharMap.h"
2015-07-30 11:33:18 +08:00
# include "2d/CCLabel.h"
2016-11-18 09:23:44 +08:00
# include "platform/CCFileUtils.h"
2013-07-25 01:22:46 +08:00
NS_CC_BEGIN
2013-11-07 09:05:13 +08:00
std : : unordered_map < std : : string , FontAtlas * > FontAtlasCache : : _atlasMap ;
2019-04-11 09:31:50 +08:00
# define ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE 255
2013-07-25 01:22:46 +08:00
2014-03-14 14:59:26 +08:00
void FontAtlasCache : : purgeCachedData ( )
{
2015-08-05 14:12:02 +08:00
auto atlasMapCopy = _atlasMap ;
for ( auto & & atlas : atlasMapCopy )
2014-03-14 14:59:26 +08:00
{
2017-07-31 09:05:55 +08:00
auto refCount = atlas . second - > getReferenceCount ( ) ;
atlas . second - > release ( ) ;
if ( refCount ! = 1 )
atlas . second - > purgeTexturesAtlas ( ) ;
2014-03-14 14:59:26 +08:00
}
2016-03-24 23:05:22 +08:00
_atlasMap . clear ( ) ;
2014-03-14 14:59:26 +08:00
}
2015-07-30 11:33:18 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasTTF ( const _ttfConfig * config )
2016-11-18 09:23:44 +08:00
{
auto realFontFilename = FileUtils : : getInstance ( ) - > getNewFilename ( config - > fontFilePath ) ; // resolves real file path, to prevent storing multiple atlases for the same file.
2015-07-30 11:33:18 +08:00
bool useDistanceField = config - > distanceFieldEnabled ;
if ( config - > outlineSize > 0 )
2014-03-05 15:54:40 +08:00
{
useDistanceField = false ;
}
2014-03-25 09:58:16 +08:00
2019-04-11 09:31:50 +08:00
std : : string key ;
char keyPrefix [ ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE ] ;
snprintf ( keyPrefix , ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE , useDistanceField ? " df %.2f %d " : " %.2f %d " , config - > fontSize , config - > outlineSize ) ;
std : : string atlasName ( keyPrefix ) ;
atlasName + = realFontFilename ;
2014-03-05 15:54:40 +08:00
2014-03-28 16:52:48 +08:00
auto it = _atlasMap . find ( atlasName ) ;
2014-03-05 15:54:40 +08:00
2014-03-28 16:52:48 +08:00
if ( it = = _atlasMap . end ( ) )
2013-07-25 01:22:46 +08:00
{
2016-11-18 09:23:44 +08:00
auto font = FontFreeType : : create ( realFontFilename , config - > fontSize , config - > glyphs ,
2019-10-09 17:50:32 +08:00
config - > customGlyphs , useDistanceField , ( float ) config - > outlineSize ) ;
2014-01-20 10:32:12 +08:00
if ( font )
{
2014-03-28 16:52:48 +08:00
auto tempAtlas = font - > createFontAtlas ( ) ;
2014-01-20 10:32:12 +08:00
if ( tempAtlas )
2014-03-28 16:52:48 +08:00
{
2014-01-20 10:32:12 +08:00
_atlasMap [ atlasName ] = tempAtlas ;
2014-03-28 16:52:48 +08:00
return _atlasMap [ atlasName ] ;
}
2014-01-20 10:32:12 +08:00
}
2013-07-25 01:22:46 +08:00
}
2013-07-31 07:41:26 +08:00
else
2018-05-30 20:33:53 +08:00
return it - > second ;
2014-01-20 10:32:12 +08:00
2014-03-28 16:52:48 +08:00
return nullptr ;
2013-07-25 01:22:46 +08:00
}
2020-01-06 09:35:52 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasFNT ( const std : : string & fontFileName )
2013-07-25 01:22:46 +08:00
{
2020-01-06 09:35:52 +08:00
return getFontAtlasFNT ( fontFileName , Rect : : ZERO , false ) ;
}
FontAtlas * FontAtlasCache : : getFontAtlasFNT ( const std : : string & fontFileName , const std : : string & subTextureKey )
{
const auto realFontFilename = FileUtils : : getInstance ( ) - > getNewFilename ( fontFileName ) ; // resolves real file path, to prevent storing multiple atlases for the same file.
std : : string atlasName = subTextureKey + " " + realFontFilename ;
const auto it = _atlasMap . find ( atlasName ) ;
if ( it = = _atlasMap . end ( ) )
{
const auto font = FontFNT : : create ( realFontFilename , subTextureKey ) ;
if ( font )
{
const auto tempAtlas = font - > createFontAtlas ( ) ;
if ( tempAtlas )
{
_atlasMap [ atlasName ] = tempAtlas ;
return _atlasMap [ atlasName ] ;
}
}
}
else
return it - > second ;
return nullptr ;
}
FontAtlas * FontAtlasCache : : getFontAtlasFNT ( const std : : string & fontFileName , const Rect & imageRect , bool imageRotated )
{
const auto realFontFilename = FileUtils : : getInstance ( ) - > getNewFilename ( fontFileName ) ; // resolves real file path, to prevent storing multiple atlases for the same file.
2019-04-11 09:31:50 +08:00
char keyPrefix [ ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE ] ;
2020-01-06 09:35:52 +08:00
snprintf ( keyPrefix , ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE , " %.2f %.2f " , imageRect . origin . x , imageRect . origin . y ) ;
2019-04-11 09:31:50 +08:00
std : : string atlasName ( keyPrefix ) ;
atlasName + = realFontFilename ;
2016-03-24 23:05:22 +08:00
2020-01-06 09:35:52 +08:00
const auto it = _atlasMap . find ( atlasName ) ;
2014-03-28 16:52:48 +08:00
if ( it = = _atlasMap . end ( ) )
2013-07-25 01:22:46 +08:00
{
2020-01-06 09:35:52 +08:00
const auto font = FontFNT : : create ( realFontFilename , imageRect , imageRotated ) ;
2014-01-20 10:32:12 +08:00
if ( font )
{
2020-01-06 09:35:52 +08:00
const auto tempAtlas = font - > createFontAtlas ( ) ;
2014-01-20 10:32:12 +08:00
if ( tempAtlas )
2014-03-28 16:52:48 +08:00
{
2014-01-20 10:32:12 +08:00
_atlasMap [ atlasName ] = tempAtlas ;
2014-03-28 16:52:48 +08:00
return _atlasMap [ atlasName ] ;
}
2014-01-20 10:32:12 +08:00
}
2013-07-25 01:22:46 +08:00
}
2013-07-31 07:41:26 +08:00
else
2018-05-30 20:33:53 +08:00
return it - > second ;
2013-07-25 01:22:46 +08:00
2014-03-28 16:52:48 +08:00
return nullptr ;
2013-07-25 01:22:46 +08:00
}
2020-01-06 09:35:52 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasFNT ( const std : : string & fontFileName , const Vec2 & imageOffset )
{
return getFontAtlasFNT ( fontFileName , Rect ( imageOffset . x , imageOffset . y , 0 , 0 ) , false ) ;
}
2015-07-30 11:33:18 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasCharMap ( const std : : string & plistFile )
2014-01-16 16:37:29 +08:00
{
2020-01-06 09:35:52 +08:00
const std : : string & atlasName = plistFile ;
2016-03-24 23:05:22 +08:00
2014-03-28 16:52:48 +08:00
auto it = _atlasMap . find ( atlasName ) ;
if ( it = = _atlasMap . end ( ) )
2014-01-16 16:37:29 +08:00
{
2014-03-28 16:52:48 +08:00
auto font = FontCharMap : : create ( plistFile ) ;
2014-01-20 10:32:12 +08:00
if ( font )
{
2014-03-28 16:52:48 +08:00
auto tempAtlas = font - > createFontAtlas ( ) ;
2014-01-20 10:32:12 +08:00
if ( tempAtlas )
2014-03-28 16:52:48 +08:00
{
2014-01-20 10:32:12 +08:00
_atlasMap [ atlasName ] = tempAtlas ;
2014-03-28 16:52:48 +08:00
return _atlasMap [ atlasName ] ;
}
2014-01-20 10:32:12 +08:00
}
2014-01-16 16:37:29 +08:00
}
else
2018-05-30 20:33:53 +08:00
return it - > second ;
2014-01-16 16:37:29 +08:00
2014-03-28 16:52:48 +08:00
return nullptr ;
2014-01-16 16:37:29 +08:00
}
2015-07-30 11:33:18 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasCharMap ( Texture2D * texture , int itemWidth , int itemHeight , int startCharMap )
2014-01-16 16:37:29 +08:00
{
2019-04-11 09:31:50 +08:00
char key [ ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE ] ;
2019-05-22 09:49:11 +08:00
sprintf ( key , " name:%p_%d_%d_%d " , texture - > getBackendTexture ( ) , itemWidth , itemHeight , startCharMap ) ;
2019-04-11 09:31:50 +08:00
std : : string atlasName = key ;
2014-01-16 16:37:29 +08:00
2014-03-28 16:52:48 +08:00
auto it = _atlasMap . find ( atlasName ) ;
if ( it = = _atlasMap . end ( ) )
2014-01-16 16:37:29 +08:00
{
2014-03-28 16:52:48 +08:00
auto font = FontCharMap : : create ( texture , itemWidth , itemHeight , startCharMap ) ;
2014-01-20 10:32:12 +08:00
if ( font )
{
2014-03-28 16:52:48 +08:00
auto tempAtlas = font - > createFontAtlas ( ) ;
2014-01-20 10:32:12 +08:00
if ( tempAtlas )
2014-03-28 16:52:48 +08:00
{
2014-01-20 10:32:12 +08:00
_atlasMap [ atlasName ] = tempAtlas ;
2014-03-28 16:52:48 +08:00
return _atlasMap [ atlasName ] ;
}
2014-01-20 10:32:12 +08:00
}
2014-01-16 16:37:29 +08:00
}
else
2018-05-30 20:33:53 +08:00
return it - > second ;
2014-01-16 16:37:29 +08:00
2014-03-28 16:52:48 +08:00
return nullptr ;
2014-01-16 16:37:29 +08:00
}
2015-07-30 11:33:18 +08:00
FontAtlas * FontAtlasCache : : getFontAtlasCharMap ( const std : : string & charMapFile , int itemWidth , int itemHeight , int startCharMap )
2014-01-16 16:37:29 +08:00
{
2019-04-11 09:31:50 +08:00
char keyPrefix [ ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE ] ;
snprintf ( keyPrefix , ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE , " %d %d %d " , itemWidth , itemHeight , startCharMap ) ;
std : : string atlasName ( keyPrefix ) ;
atlasName + = charMapFile ;
2014-01-16 16:37:29 +08:00
2014-03-28 16:52:48 +08:00
auto it = _atlasMap . find ( atlasName ) ;
if ( it = = _atlasMap . end ( ) )
2014-01-16 16:37:29 +08:00
{
2014-03-28 16:52:48 +08:00
auto font = FontCharMap : : create ( charMapFile , itemWidth , itemHeight , startCharMap ) ;
2014-01-20 10:32:12 +08:00
if ( font )
{
2014-03-28 16:52:48 +08:00
auto tempAtlas = font - > createFontAtlas ( ) ;
2014-01-20 10:32:12 +08:00
if ( tempAtlas )
2014-03-28 16:52:48 +08:00
{
2014-01-20 10:32:12 +08:00
_atlasMap [ atlasName ] = tempAtlas ;
2014-03-28 16:52:48 +08:00
return _atlasMap [ atlasName ] ;
}
2014-01-20 10:32:12 +08:00
}
2014-01-16 16:37:29 +08:00
}
else
2018-05-30 20:33:53 +08:00
return it - > second ;
2014-01-16 16:37:29 +08:00
2014-03-28 16:52:48 +08:00
return nullptr ;
2014-01-16 16:37:29 +08:00
}
2013-07-25 01:22:46 +08:00
bool FontAtlasCache : : releaseFontAtlas ( FontAtlas * atlas )
{
2014-01-04 18:22:50 +08:00
if ( nullptr ! = atlas )
2013-07-25 01:22:46 +08:00
{
2021-10-28 21:07:46 +08:00
if ( atlas - > getReferenceCount ( ) = = 1 )
2013-07-25 01:22:46 +08:00
{
2021-10-28 21:09:03 +08:00
for ( auto & item : _atlasMap )
2013-07-25 01:22:46 +08:00
{
2021-10-28 21:09:03 +08:00
if ( item . second = = atlas )
2014-01-04 18:22:50 +08:00
{
2021-10-28 21:07:46 +08:00
_atlasMap . erase ( item . first ) ;
break ;
2014-01-04 18:22:50 +08:00
}
2013-07-25 01:22:46 +08:00
}
2021-10-28 21:07:46 +08:00
}
atlas - > release ( ) ;
return true ;
2013-07-25 01:22:46 +08:00
}
return false ;
}
2020-01-06 09:35:52 +08:00
void FontAtlasCache : : reloadFontAtlasFNT ( const std : : string & fontFileName , const Rect & imageRect , bool imageRotated )
2015-11-12 09:49:49 +08:00
{
2019-04-11 09:31:50 +08:00
char keyPrefix [ ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE ] ;
2020-01-06 09:35:52 +08:00
snprintf ( keyPrefix , ATLAS_MAP_KEY_PREFIX_BUFFER_SIZE , " %.2f %.2f " , imageRect . origin . x , imageRect . origin . y ) ;
2019-04-11 09:31:50 +08:00
std : : string atlasName ( keyPrefix ) ;
atlasName + = fontFileName ;
2016-03-24 23:05:22 +08:00
2015-11-12 09:49:49 +08:00
auto it = _atlasMap . find ( atlasName ) ;
if ( it ! = _atlasMap . end ( ) )
{
CC_SAFE_RELEASE_NULL ( it - > second ) ;
_atlasMap . erase ( it ) ;
}
FontFNT : : reloadBMFontResource ( fontFileName ) ;
2020-01-06 09:35:52 +08:00
auto font = FontFNT : : create ( fontFileName , imageRect , imageRotated ) ;
2015-11-12 09:49:49 +08:00
if ( font )
{
auto tempAtlas = font - > createFontAtlas ( ) ;
if ( tempAtlas )
{
_atlasMap [ atlasName ] = tempAtlas ;
}
}
2020-01-06 09:35:52 +08:00
}
2015-11-12 09:49:49 +08:00
2020-01-06 09:35:52 +08:00
void FontAtlasCache : : reloadFontAtlasFNT ( const std : : string & fontFileName , const Vec2 & imageOffset )
{
reloadFontAtlasFNT ( fontFileName , Rect ( imageOffset . x , imageOffset . y , 0 , 0 ) , false ) ;
2015-11-12 09:49:49 +08:00
}
void FontAtlasCache : : unloadFontAtlasTTF ( const std : : string & fontFileName )
{
auto item = _atlasMap . begin ( ) ;
while ( item ! = _atlasMap . end ( ) )
{
2016-01-20 22:59:45 +08:00
if ( item - > first . find ( fontFileName ) ! = std : : string : : npos )
2015-11-12 09:49:49 +08:00
{
CC_SAFE_RELEASE_NULL ( item - > second ) ;
item = _atlasMap . erase ( item ) ;
}
else
item + + ;
}
}
2014-01-04 18:22:50 +08:00
NS_CC_END