Cocos2d-xでpurgeCachedDataをやったら文字が抜ける

## 概要
- Cocos2d-xのCCDirector.cppの ```void Director::purgeCachedData(void)``` を行うとLabelで描画した文字が抜けることがある

## バージョン情報
- Cocos2d-x v3.2.0
- 現在の最新バージョンv3.14.1でも未修正だったのでおそらくこの現象は起こる

## 原因概要
```Director::purgeCachedData()``` 内の処理に問題あり。

```CCDirector.cpp
void Director::purgeCachedData(void)
{
    FontFNT::purgeCachedData();
    FontAtlasCache::purgeCachedData();

    if (s_SharedDirector->getOpenGLView())
    {
        SpriteFrameCache::getInstance()->removeUnusedSpriteFrames();
        _textureCache->removeUnusedTextures();

        // Note: some tests such as ActionsTest are leaking refcounted textures
        // There should be no test textures left in the cache
        CCLOG("%s\n", _textureCache->getCachedTextureInfo().c_str());
    }
    FileUtils::getInstance()->purgeCachedEntries();
}
```

## 原因詳細
```Director::purgeCachedData(void)``` で ```FontAtlasCache::purgeCachedData()``` が呼ばれる。
```FontAtlasCache::purgeCachedData()``` でFontAtlasの ```purgeTexturesAtlas()``` が呼ばれる。

```CCFontAtlas.cpp
void FontAtlas::purgeTexturesAtlas()
{
    FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font);
    if (fontTTf && _atlasTextures.size() > 1)
    {
        auto eventDispatcher = Director::getInstance()->getEventDispatcher();
        eventDispatcher->dispatchCustomEvent(CMD_PURGE_FONTATLAS,this);
        eventDispatcher->dispatchCustomEvent(CMD_RESET_FONTATLAS,this);
    }
}
```

ここでCMD_PURGE_FONTATLASとCMD_RESET_FONTATLASのイベントが同時に発行される。
この2つはどこでもセットで呼ばれている。
このイベントを受け取っているのはCCLabelクラス。

CMD_PURGE_FONTATLASのイベントで、SpriteBatchNodeをclearしている。
_fontAtlasも解放している。

その後、CMD_RESET_FONTATLASで_fontAtlasがnullptrになった状態で
```setTTFCongig(_fontConfig)```を行う処理があるが、
この時点で_fontAtlasがnullptrになる場合があり、結果その処理に行かず、リセットされない。
結果、_fontAtlasと_atlasMapに不整合が生じ、文字が再描画されない(特定の文字が解放されっぱなしになっている)。

```CCLabel.cpp
 _purgeTextureListener = EventListenerCustom::create(FontAtlas::CMD_PURGE_FONTATLAS, [this](EventCustom* event){
        if (_fontAtlas && _currentLabelType == LabelType::TTF && event->getUserData() == _fontAtlas)
        {
            for (auto&& it : _letters)
            {
                it.second->setTexture(nullptr);
            }
            _batchNodes.clear();
            
            // _fontAtlasが解放される
            if (_fontAtlas)
            {
                FontAtlasCache::releaseFontAtlas(_fontAtlas);
            }
        }
    });
    _eventDispatcher->addEventListenerWithFixedPriority(_purgeTextureListener, 1);
    
    _resetTextureListener = EventListenerCustom::create(FontAtlas::CMD_RESET_FONTATLAS, [this](EventCustom* event){
        // この時点で_fontAtlasがnullptrになっている場合はifに入らない
        if (_fontAtlas && _currentLabelType == LabelType::TTF && event->getUserData() == _fontAtlas)
        {
            _fontAtlas = nullptr;
            this->setTTFConfig(_fontConfig);
            for (auto&& it : _letters)
            {
                getLetter(it.first);
            }
        }
    });
```

## 修正
- CMD_RESET_FONTATLASイベントで_fontAtlasを解放するようにした

```CCLabel.cpp
_purgeTextureListener = EventListenerCustom::create(FontAtlas::CMD_PURGE_FONTATLAS, [this](EventCustom* event){
        if (_fontAtlas && _currentLabelType == LabelType::TTF && event->getUserData() == _fontAtlas)
        {
            for (auto&& it : _letters)
            {
                it.second->setTexture(nullptr);
            }
            _batchNodes.clear();
        }
    });
    _eventDispatcher->addEventListenerWithFixedPriority(_purgeTextureListener, 1);
    
    _resetTextureListener = EventListenerCustom::create(FontAtlas::CMD_RESET_FONTATLAS, [this](EventCustom* event){
        if (_fontAtlas && _currentLabelType == LabelType::TTF && event->getUserData() == _fontAtlas)
        {
            // ここで明確にreleaseしてnullptrする
            CC_SAFE_RELEASE_NULL(_fontAtlas);
                        
            this->setTTFConfig(_fontConfig);
            for (auto&& it : _letters)
            {
                getLetter(it.first);
            }
        }
    });
    _eventDispatcher->addEventListenerWithFixedPriority(_resetTextureListener, 2);
```