From cf663b87397be0327b7eef6062e01f5d6542cefc Mon Sep 17 00:00:00 2001 From: Agnelo Vaz Date: Wed, 16 Aug 2017 19:37:00 +0100 Subject: [PATCH] Atlas manager using old block size for new atlas creation Change-Id: I0a192908037db68e226fc3a5c18b2891c7df3a0e --- .../src/dali-toolkit/utc-Dali-TextField.cpp | 26 +++++ .../rendering/atlas/atlas-glyph-manager-impl.cpp | 2 + .../text/rendering/atlas/atlas-manager-impl.cpp | 57 ++++++---- .../text/rendering/atlas/atlas-manager-impl.h | 2 +- .../text/rendering/atlas/text-atlas-renderer.cpp | 116 +++++++++++---------- 5 files changed, 124 insertions(+), 79 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index b764740..266b8e5 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -2502,3 +2502,29 @@ int utcDaliTextFieldSizeUpdate(void) END_TEST; } + +int utcDaliTextFieldExtremlyLargePointSize(void) +{ + ToolkitTestApplication application; + tet_infoline(" utcDaliTextFieldExtremlyLargePointSize"); + + TextField field = TextField::New(); + + field.SetProperty( TextField::Property::TEXT, "Text" ); + field.SetSize( 300.f, 50.f ); + field.SetParentOrigin( ParentOrigin::TOP_LEFT ); + field.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + Stage::GetCurrent().Add( field ); + + try + { + field.SetProperty( TextField::Property::POINT_SIZE, 160.0f ); + application.SendNotification(); + DALI_TEST_CHECK( field ); + } + catch (...) + { + tet_result(TET_FAIL); + } + END_TEST; +} diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp index 7e672bd..0d72be9 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp @@ -49,6 +49,8 @@ void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, { DALI_LOG_INFO( gLogFilter, Debug::General, "Added glyph, font: %d index: %d\n", glyph.fontId, glyph.index ); + // If glyph added to an existing or new atlas then a new glyph record is required. + // Check if an existing atlas will fit the image, create a new one if required. if ( mAtlasManager.Add( bitmap, slot ) ) { // A new atlas was created so set the texture set details for the atlas diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp index 958749e..ba07cef 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp @@ -42,6 +42,11 @@ namespace const uint32_t SINGLE_PIXEL_PADDING( 1u ); const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 ); Toolkit::AtlasManager::AtlasSize EMPTY_SIZE; + + bool IsBlockSizeSufficient( uint32_t width, uint32_t height, uint32_t requiredBlockWidth, uint32_t requiredBlockHeight ) + { + return ( width + DOUBLE_PIXEL_PADDING <= requiredBlockWidth ) && ( height + DOUBLE_PIXEL_PADDING <= requiredBlockHeight ); + } } AtlasManager::AtlasManager() @@ -139,39 +144,46 @@ bool AtlasManager::Add( const PixelData& image, } // Search current atlases to see if there is a good match - while( !foundAtlas && index < mAtlasList.size() ) + while( ( 0u == foundAtlas ) && ( index < mAtlasList.size() ) ) { foundAtlas = CheckAtlas( index, width, height, pixelFormat ); ++index; } // If we can't find a suitable atlas then check the policy to determine action - if ( !foundAtlas-- ) + if ( 0u == foundAtlas ) { if ( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES == mAddFailPolicy ) { - foundAtlas = CreateAtlas( mNewAtlasSize, pixelFormat ); - if ( !foundAtlas-- ) + if ( IsBlockSizeSufficient( width, height, mNewAtlasSize.mBlockWidth, mNewAtlasSize.mBlockHeight ) ) // Checks if image fits within the atlas blocks { - DALI_LOG_ERROR("Failed to create an atlas of %i x %i blocksize: %i x %i.\n", - mNewAtlasSize.mWidth, - mNewAtlasSize.mHeight, - mNewAtlasSize.mBlockWidth, - mNewAtlasSize.mBlockHeight ); - return created; + foundAtlas = CreateAtlas( mNewAtlasSize, pixelFormat ); // Creating atlas with mNewAtlasSize, may not be the needed size! + if ( 0u == foundAtlas ) + { + DALI_LOG_ERROR("Failed to create an atlas of %i x %i blocksize: %i x %i.\n", + mNewAtlasSize.mWidth, + mNewAtlasSize.mHeight, + mNewAtlasSize.mBlockWidth, + mNewAtlasSize.mBlockHeight ); + return false; + } + else + { + created = true; + } } - created = true; - foundAtlas = CheckAtlas( foundAtlas, width, height, pixelFormat ); } - if ( !foundAtlas-- || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy ) + if ( ( 0u == foundAtlas ) || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy ) { - // Haven't found an atlas for this image!!!!!! + // Haven't found an atlas for this image ( may have failed to add image to atlas ) DALI_LOG_ERROR("Failed to create an atlas under current policy.\n"); - return created; + return false; } } + foundAtlas--; // Atlas created successfully, decrement by 1 to get index (starts at 0 not 1) + // Work out which the block we're going to use // Is there currently a next free block available ? if ( mAtlasList[ foundAtlas ].mAvailableBlocks ) @@ -188,7 +200,7 @@ bool AtlasManager::Add( const PixelData& image, desc.mImageWidth = width; desc.mImageHeight = height; - desc.mAtlasId = foundAtlas + 1u; + desc.mAtlasId = foundAtlas + 1u; // Ids start from 1 not the 0 index desc.mCount = 1u; // See if there's a previously freed image ID that we can assign to this new image @@ -211,7 +223,7 @@ bool AtlasManager::Add( const PixelData& image, mImageList[ imageId - 1u ] = desc; slot.mImageId = imageId; } - slot.mAtlasId = foundAtlas + 1u; + slot.mAtlasId = foundAtlas + 1u; // Ids start from 1 not the 0 index // Upload the buffer image into the atlas UploadImage( image, desc ); @@ -226,12 +238,13 @@ AtlasManager::SizeType AtlasManager::CheckAtlas( SizeType atlas, AtlasManager::SizeType result = 0u; if ( pixelFormat == mAtlasList[ atlas ].mPixelFormat ) { - // Check to see if the image will fit in these blocks, if not we'll need to create a new atlas - if ( ( mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size() ) - && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockWidth - && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockHeight ) + // Check to see if the image will fit in these blocks + + const SizeType availableBlocks = mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size(); + + if ( availableBlocks && IsBlockSizeSufficient( width, height,mAtlasList[ atlas ].mSize.mBlockWidth, mAtlasList[ atlas ].mSize.mBlockHeight ) ) { - result = atlas + 1u; + result = atlas + 1u; // Atlas ids start from 1 not 0 } } return result; diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h b/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h index 863bba9..dc48498 100644 --- a/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h @@ -178,7 +178,7 @@ private: std::vector< AtlasDescriptor > mAtlasList; // List of atlases created Vector< AtlasSlotDescriptor > mImageList; // List of bitmaps stored in atlases Toolkit::AtlasManager::AtlasSize mNewAtlasSize; // Atlas size to use in next creation - Toolkit::AtlasManager::AddFailPolicy mAddFailPolicy; // Policy for faling to add an Image + Toolkit::AtlasManager::AddFailPolicy mAddFailPolicy; // Policy for failing to add an Image SizeType CheckAtlas( SizeType atlas, SizeType width, diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp index e9b876d..13eeae6 100644 --- a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -315,25 +315,28 @@ struct AtlasRenderer::Impl lastUnderlinedFontId = glyph.fontId; } // underline - if( !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ) ) + bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ); // Check FontGlyphRecord vector for entry with glyph index and fontId + + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "AddGlyphs fontID[%u] glyphIndex[%u] [%s]\n", glyph.fontId, glyph.index, (glyphNotCached)?"not cached":"cached" ); + + if( glyphNotCached ) { - // Select correct size for new atlas if needed....? - if( lastFontId != glyph.fontId ) + MaxBlockSize& blockSize = mBlockSizes[currentBlockSize]; + + if ( lastFontId != glyph.fontId ) { 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::const_iterator it = mBlockSizes.begin(), endIt = mBlockSizes.end(); it != endIt; ++it, ++index ) { - const MaxBlockSize& blockSize = *it; - if( blockSize.mFontId == glyph.fontId ) + const MaxBlockSize& blockSizeEntry = *it; + if( blockSizeEntry.mFontId == glyph.fontId ) { - currentBlockSize = index; - mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, - DEFAULT_ATLAS_HEIGHT, - blockSize.mNeededBlockWidth, - blockSize.mNeededBlockHeight ); + blockSize = mBlockSizes[index]; } } } @@ -363,31 +366,27 @@ struct AtlasRenderer::Impl if( bitmap ) { - MaxBlockSize& blockSize = mBlockSizes[currentBlockSize]; - // Ensure that the next image will fit into the current block size - bool setSize = false; if( bitmap.GetWidth() > blockSize.mNeededBlockWidth ) { - setSize = true; blockSize.mNeededBlockWidth = bitmap.GetWidth(); } + if( bitmap.GetHeight() > blockSize.mNeededBlockHeight ) { - setSize = true; blockSize.mNeededBlockHeight = bitmap.GetHeight(); } - if( setSize ) - { - mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, - DEFAULT_ATLAS_HEIGHT, - blockSize.mNeededBlockWidth, - blockSize.mNeededBlockHeight ); - } + // 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. + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + blockSize.mNeededBlockWidth, + blockSize.mNeededBlockHeight ); // Locate a new slot for our glyph - mGlyphManager.Add( glyph, bitmap, slot ); + mGlyphManager.Add( glyph, bitmap, slot ); // slot will be 0 is glyph not added } } else @@ -399,40 +398,44 @@ struct AtlasRenderer::Impl // Move the origin (0,0) of the mesh to the center of the actor const Vector2 position = *( positionsBuffer + i ) - halfTextSize - lineOffsetPosition; - // Generate mesh data for this quad, plugging in our supplied position - AtlasManager::Mesh2D newMesh; - mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); - textCacheEntry.mFontId = glyph.fontId; - textCacheEntry.mImageId = slot.mImageId; - textCacheEntry.mIndex = glyph.index; - newTextCache.PushBack( textCacheEntry ); - - AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin(); - - // Get the color of the character. - const ColorIndex colorIndex = useDefaultColor ? 0u : *( colorIndicesBuffer + i ); - const Vector4& color = ( useDefaultColor || ( 0u == colorIndex ) ) ? defaultColor : *( colorsBuffer + colorIndex - 1u ); - - for( unsigned int index = 0u, size = newMesh.mVertices.Count(); - index < size; - ++index ) + if ( 0u != slot.mImageId ) // invalid slot id, glyph has failed to be added to atlas { - AtlasManager::Vertex2D& vertex = *( verticesBuffer + index ); + // Generate mesh data for this quad, plugging in our supplied position + AtlasManager::Mesh2D newMesh; + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh ); + textCacheEntry.mFontId = glyph.fontId; + textCacheEntry.mImageId = slot.mImageId; + textCacheEntry.mIndex = glyph.index; + newTextCache.PushBack( textCacheEntry ); + + AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin(); + + // Get the color of the character. + const ColorIndex colorIndex = useDefaultColor ? 0u : *( colorIndicesBuffer + i ); + const Vector4& color = ( useDefaultColor || ( 0u == colorIndex ) ) ? defaultColor : *( colorsBuffer + colorIndex - 1u ); + + for( unsigned int index = 0u, size = newMesh.mVertices.Count(); + index < size; + ++index ) + { + AtlasManager::Vertex2D& vertex = *( verticesBuffer + index ); - // Set the color of the vertex. - vertex.mColor = color; - } + // Set the color of the vertex. + vertex.mColor = color; + } - // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) - StitchTextMesh( meshContainer, - newMesh, - extents, - position.y + glyph.yBearing, - underlineGlyph, - currentUnderlinePosition, - currentUnderlineThickness, - slot ); - lastFontId = glyph.fontId; + // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) + StitchTextMesh( meshContainer, + newMesh, + extents, + position.y + glyph.yBearing, + underlineGlyph, + currentUnderlinePosition, + currentUnderlineThickness, + slot ); + + lastFontId = glyph.fontId; // Prevents searching for existing blocksizes when string of the same fontId. + } } } // glyphs @@ -737,8 +740,9 @@ struct AtlasRenderer::Impl blockIt != blockEndIt; ++blockIt ) { - if( (*blockIt).mFontId == fontId ) + if( (*blockIt).mFontId == fontId ) // Different size fonts will have a different fontId { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::AtlasRenderer::CalculateBlocksSize match found fontID(%u) glyphIndex(%u)\n", fontId, (*glyphIt).index ); foundFont = true; break; } @@ -753,7 +757,7 @@ struct AtlasRenderer::Impl maxBlockSize.mNeededBlockWidth = static_cast< uint32_t >( fontMetrics.height ); maxBlockSize.mNeededBlockHeight = maxBlockSize.mNeededBlockWidth; maxBlockSize.mFontId = fontId; - + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::AtlasRenderer::CalculateBlocksSize New font with no matched blocksize, setting blocksize[%u]\n", maxBlockSize.mNeededBlockWidth ); mBlockSizes.push_back( maxBlockSize ); } } -- 2.7.4