FontAtlas::FontAtlas(Font &theFont) : _font(&theFont) , _currentPageData(nullptr) , _fontAscender(0) , _toForegroundListener(nullptr) , _toBackgroundListener(nullptr) , _antialiasEnabled(true) { _font->retain(); FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font); if (fontTTf) { _commonLineHeight = _font->getFontMaxHeight(); _fontAscender = fontTTf->getFontAscender(); auto texture = new Texture2D; _currentPage = 0; _currentPageOrigX = 0; _currentPageOrigY = 0; _letterPadding = 0; if(fontTTf->isDistanceFieldEnabled()) { _letterPadding += 2 * FontFreeType::DistanceMapSpread; } _currentPageDataSize = CacheTextureWidth * CacheTextureHeight; if(fontTTf->getOutlineSize() > 0) { _currentPageDataSize *= 2; } _currentPageData = new unsigned char[_currentPageDataSize]; memset(_currentPageData, 0, _currentPageDataSize); auto pixelFormat = fontTTf->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8; texture->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) ); addTexture(texture,0); texture->release(); #if CC_ENABLE_CACHE_TEXTURE_DATA auto eventDispatcher = Director::getInstance()->getEventDispatcher(); _toBackgroundListener = EventListenerCustom::create(EVENT_COME_TO_BACKGROUND, CC_CALLBACK_1(FontAtlas::listenToBackground, this)); eventDispatcher->addEventListenerWithFixedPriority(_toBackgroundListener, 1); _toForegroundListener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(FontAtlas::listenToForeground, this)); eventDispatcher->addEventListenerWithFixedPriority(_toForegroundListener, 1); #endif } }
void FontAtlas::listenToForeground(EventCustom *event) { #if CC_ENABLE_CACHE_TEXTURE_DATA FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font); if (fontTTf) { if (_currentPageOrigX == 0 && _currentPageOrigY == 0) { auto eventDispatcher = Director::getInstance()->getEventDispatcher(); eventDispatcher->dispatchCustomEvent(EVENT_PURGE_TEXTURES,this); } else { auto contentSize = Size(CacheTextureWidth,CacheTextureHeight); auto pixelFormat = fontTTf->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8; _atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize ); } } #endif }
bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String) { FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font); if(fontTTf == nullptr) return false; int length = cc_wcslen(utf16String); float offsetAdjust = _letterPadding / 2; int bitmapWidth; int bitmapHeight; Rect tempRect; FontLetterDefinition tempDef; auto contentSize = Size(CacheTextureWidth,CacheTextureHeight); auto scaleFactor = CC_CONTENT_SCALE_FACTOR(); auto pixelFormat = fontTTf->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8; bool existNewLetter = false; for (int i = 0; i < length; ++i) { auto outIterator = _fontLetterDefinitions.find(utf16String[i]); if (outIterator == _fontLetterDefinitions.end()) { existNewLetter = true; auto bitmap = fontTTf->getGlyphBitmap(utf16String[i],bitmapWidth,bitmapHeight,tempRect,tempDef.xAdvance); if (bitmap) { tempDef.validDefinition = true; tempDef.letteCharUTF16 = utf16String[i]; tempDef.width = tempRect.size.width + _letterPadding; tempDef.height = tempRect.size.height + _letterPadding; tempDef.offsetX = tempRect.origin.x + offsetAdjust; tempDef.offsetY = _fontAscender + tempRect.origin.y - offsetAdjust; if (_currentPageOrigX + tempDef.width > CacheTextureWidth) { _currentPageOrigY += _commonLineHeight; _currentPageOrigX = 0; if(_currentPageOrigY + _commonLineHeight >= CacheTextureHeight) { _atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize ); _currentPageOrigY = 0; memset(_currentPageData, 0, _currentPageDataSize); _currentPage++; auto tex = new Texture2D; addTexture(tex,_currentPage); tex->release(); } } fontTTf->renderCharAt(_currentPageData,_currentPageOrigX,_currentPageOrigY,bitmap,bitmapWidth,bitmapHeight); tempDef.U = _currentPageOrigX; tempDef.V = _currentPageOrigY; tempDef.textureID = _currentPage; _currentPageOrigX += tempDef.width + 1; // take from pixels to points tempDef.width = tempDef.width / scaleFactor; tempDef.height = tempDef.height / scaleFactor; tempDef.U = tempDef.U / scaleFactor; tempDef.V = tempDef.V / scaleFactor; } else{ if(tempDef.xAdvance) tempDef.validDefinition = true; else tempDef.validDefinition = false; tempDef.letteCharUTF16 = utf16String[i]; tempDef.width = 0; tempDef.height = 0; tempDef.U = 0; tempDef.V = 0; tempDef.offsetX = 0; tempDef.offsetY = 0; tempDef.textureID = 0; _currentPageOrigX += 1; } _fontLetterDefinitions[tempDef.letteCharUTF16] = tempDef; } } if(existNewLetter) { _atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, contentSize ); } return true; }
bool FontAtlas::prepareLetterDefinitions(const std::u16string& utf16String) { FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_font); if(fontTTf == nullptr) return false; size_t length = utf16String.length(); float offsetAdjust = _letterPadding / 2; long bitmapWidth; long bitmapHeight; Rect tempRect; FontLetterDefinition tempDef; auto scaleFactor = CC_CONTENT_SCALE_FACTOR(); auto pixelFormat = fontTTf->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8; bool existNewLetter = false; int bottomHeight = _commonLineHeight - _fontAscender; float startY = _currentPageOrigY; for (size_t i = 0; i < length; ++i) { auto outIterator = _fontLetterDefinitions.find(utf16String[i]); if (outIterator == _fontLetterDefinitions.end()) { existNewLetter = true; auto bitmap = fontTTf->getGlyphBitmap(utf16String[i],bitmapWidth,bitmapHeight,tempRect,tempDef.xAdvance); if (bitmap) { tempDef.validDefinition = true; tempDef.letteCharUTF16 = utf16String[i]; tempDef.width = tempRect.size.width + _letterPadding; tempDef.height = tempRect.size.height + _letterPadding; tempDef.offsetX = tempRect.origin.x + offsetAdjust; tempDef.offsetY = _fontAscender + tempRect.origin.y - offsetAdjust; tempDef.clipBottom = bottomHeight - (tempDef.height + tempRect.origin.y + offsetAdjust); if (_currentPageOrigX + tempDef.width > CacheTextureWidth) { _currentPageOrigY += _commonLineHeight; _currentPageOrigX = 0; if(_currentPageOrigY + _commonLineHeight >= CacheTextureHeight) { unsigned char *data = nullptr; if(pixelFormat == Texture2D::PixelFormat::AI88) { data = _currentPageData + CacheTextureWidth * (int)startY * 2; } else { data = _currentPageData + CacheTextureWidth * (int)startY; } _atlasTextures[_currentPage]->updateWithData(data, 0, startY, CacheTextureWidth, CacheTextureHeight - startY); startY = 0.0f; _currentPageOrigY = 0; memset(_currentPageData, 0, _currentPageDataSize); _currentPage++; auto tex = new (std::nothrow) Texture2D; if (_antialiasEnabled) { tex->setAntiAliasTexParameters(); } else { tex->setAliasTexParameters(); } tex->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) ); addTexture(tex,_currentPage); tex->release(); } } fontTTf->renderCharAt(_currentPageData,_currentPageOrigX,_currentPageOrigY,bitmap,bitmapWidth,bitmapHeight); tempDef.U = _currentPageOrigX; tempDef.V = _currentPageOrigY; tempDef.textureID = _currentPage; _currentPageOrigX += tempDef.width + 1; // take from pixels to points tempDef.width = tempDef.width / scaleFactor; tempDef.height = tempDef.height / scaleFactor; tempDef.U = tempDef.U / scaleFactor; tempDef.V = tempDef.V / scaleFactor; } else{ if(tempDef.xAdvance) tempDef.validDefinition = true; else tempDef.validDefinition = false; tempDef.letteCharUTF16 = utf16String[i]; tempDef.width = 0; tempDef.height = 0; tempDef.U = 0; tempDef.V = 0; tempDef.offsetX = 0; tempDef.offsetY = 0; tempDef.textureID = 0; tempDef.clipBottom = 0; _currentPageOrigX += 1; } _fontLetterDefinitions[tempDef.letteCharUTF16] = tempDef; } } if(existNewLetter) { if (_rendererRecreate) { _atlasTextures[_currentPage]->initWithData(_currentPageData, _currentPageDataSize, pixelFormat, CacheTextureWidth, CacheTextureHeight, Size(CacheTextureWidth,CacheTextureHeight) ); } else { unsigned char *data = nullptr; if(pixelFormat == Texture2D::PixelFormat::AI88) { data = _currentPageData + CacheTextureWidth * (int)startY * 2; } else { data = _currentPageData + CacheTextureWidth * (int)startY; } _atlasTextures[_currentPage]->updateWithData(data, 0, startY, CacheTextureWidth, _currentPageOrigY - startY + _commonLineHeight); } } return true; }