Atlas manager using old block size for new atlas creation 31/144431/8
authorAgnelo Vaz <agnelo.vaz@samsung.com>
Wed, 16 Aug 2017 18:37:00 +0000 (19:37 +0100)
committerAgnelo Vaz <agnelo.vaz@samsung.com>
Thu, 31 Aug 2017 10:37:27 +0000 (11:37 +0100)
Change-Id: I0a192908037db68e226fc3a5c18b2891c7df3a0e

automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp

index b764740..266b8e5 100644 (file)
@@ -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;
+}
index 7e672bd..0d72be9 100644 (file)
@@ -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
index 958749e..ba07cef 100644 (file)
@@ -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 <vector> 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;
index 863bba9..dc48498 100644 (file)
@@ -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,
index e9b876d..13eeae6 100644 (file)
@@ -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<MaxBlockSize>::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 );
       }
     }