+ uint32_t index = 0u;
+ // Looks through all stored block sizes until finds the one which mataches required glyph font it. Ensures new atlas block size will match existing for same font id.
+ // CalculateBlocksSize() above ensures a block size entry exists.
+ for(std::vector<MaxBlockSize>::const_iterator it = mBlockSizes.begin(),
+ endIt = mBlockSizes.end();
+ it != endIt;
+ ++it, ++index)
+ {
+ const MaxBlockSize& blockSizeEntry = *it;
+ if(blockSizeEntry.mFontId == glyph.fontId)
+ {
+ blockSize = mBlockSizes[index];
+ }
+ }
+ }
+
+ // Create a new image for the glyph
+ PixelData bitmap;
+
+ // Whether the glyph is an outline.
+ const bool isOutline = 0u != style.outline;
+
+ // Whether the current glyph is a color one.
+ const bool isColorGlyph = mFontClient.IsColorGlyph(glyph.fontId, glyph.index);
+
+ if(!isOutline || (isOutline && !isColorGlyph))
+ {
+ // Retrieve the emoji's bitmap.
+ TextAbstraction::FontClient::GlyphBufferData glyphBufferData;
+ glyphBufferData.width = isColorGlyph ? glyph.width : 0; // Desired width and height.
+ glyphBufferData.height = isColorGlyph ? glyph.height : 0;
+
+ mFontClient.CreateBitmap(glyph.fontId,
+ glyph.index,
+ glyph.isItalicRequired,
+ glyph.isBoldRequired,
+ glyphBufferData,
+ style.outline);
+
+ uint32_t glyphBufferSize = glyphBufferData.width * glyphBufferData.height * Pixel::GetBytesPerPixel(glyphBufferData.format);
+ // If glyph buffer data don't have ownership, Or if we need to decompress, create new memory and replace ownership.
+ if(!glyphBufferData.isBufferOwned || glyphBufferData.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION)
+ {
+ uint8_t* newBuffer = (uint8_t*)malloc(glyphBufferSize);
+ if(DALI_LIKELY(newBuffer != nullptr))
+ {
+ TextAbstraction::FontClient::GlyphBufferData::Decompress(glyphBufferData, newBuffer);
+ if(glyphBufferData.isBufferOwned)
+ {
+ // Release previous buffer
+ free(glyphBufferData.buffer);
+ }
+ glyphBufferData.isBufferOwned = true;
+ glyphBufferData.buffer = newBuffer;
+ glyphBufferData.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+ }
+ }
+
+ // Create the pixel data.
+ bitmap = PixelData::New(glyphBufferData.buffer,
+ glyphBufferSize,
+ glyphBufferData.width,
+ glyphBufferData.height,
+ glyphBufferData.format,
+ PixelData::FREE);
+
+ // Change buffer ownership.
+ glyphBufferData.isBufferOwned = false;
+
+ if(bitmap)
+ {
+ // Ensure that the next image will fit into the current block size
+ if(bitmap.GetWidth() > blockSize.mNeededBlockWidth)
+ {
+ blockSize.mNeededBlockWidth = bitmap.GetWidth();
+ }
+
+ if(bitmap.GetHeight() > blockSize.mNeededBlockHeight)
+ {
+ blockSize.mNeededBlockHeight = bitmap.GetHeight();
+ }
+
+ // If CheckAtlas in AtlasManager::Add can't fit the bitmap in the current atlas it will create a new atlas
+
+ // Setting the block size and size of new atlas does not mean a new one will be created. An existing atlas may still surffice.
+ uint32_t default_width = defaultTextAtlasSize.width;
+ uint32_t default_height = defaultTextAtlasSize.height;
+
+ while(
+ (blockSize.mNeededBlockWidth >= (default_width - (DOUBLE_PIXEL_PADDING + 1u)) ||
+ blockSize.mNeededBlockHeight >= (default_height - (DOUBLE_PIXEL_PADDING + 1u))) &&
+ (default_width < maximumTextAtlasSize.width &&
+ default_height < maximumTextAtlasSize.height))
+ {
+ default_width <<= 1u;
+ default_height <<= 1u;
+ }
+ mGlyphManager.SetNewAtlasSize(default_width,
+ default_height,
+ blockSize.mNeededBlockWidth,
+ blockSize.mNeededBlockHeight);
+
+ // Locate a new slot for our glyph
+ mGlyphManager.Add(glyph, style, bitmap, slot); // slot will be 0 is glyph not added
+ }