[Tizen] Fixing issue: On Text, reducing font-point-size when the Glyph-block-size... 65/258865/1
authorShrouq Sabah <s.sabah@samsung.com>
Wed, 10 Mar 2021 12:57:22 +0000 (14:57 +0200)
committerBowon Ryu <bowon.ryu@samsung.com>
Wed, 26 May 2021 07:18:23 +0000 (16:18 +0900)
Issue: On TextEditor or TextField when use font size (Point-Size) which creating Glyphs its size larger than Atlas-block size then logging error says that can’t create block and nothing appear in Text-Controller.

Solution: At Adaptor level, checking block size according to point-size if the block will be larger than Atlas size then keep decreasing point-size until achieve block that fit into Atlas size.
Toolkit calls API named “EnableAtlasLimitation” on Font-Client object to activate this validation on Adaptor level. Since the Atlas size information added as constants in Font-Client class.
Log warning that the point-size is reduced.
Automated test-cases added to Adaptor and Toolkit

Added APIs into font-client/Adaptor for Point-size & Atlas information instead of constants/literal values in toolkit.

Reproduce by:
Creating TextEditor or TextFiled then set properties:
mEditor.SetProperty( TextEditor::Property::POINT_SIZE, 330) ;
mEditor.SetProperty( TextEditor::Property::FONT_FAMILY, " DejaVu Sans ") ;

Logged error appears:
Logged ERROR: “ERROR: DALI: CreateAtlas Atlas 512 x 512 too small. Dimensions need to be at least 517x517”
Logged ERROR: “ERROR: DALI: Add Failed to create an atlas of 512 x 512 blocksize: 514 x 514.”

Change-Id: Ia47462aa74b9807ed916fd63c4ba8b47437582e6

automated-tests/resources/fonts/dejavu/DejaVuSans.ttf [new file with mode: 0644]
automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp
dali/devel-api/text-abstraction/font-client.cpp
dali/devel-api/text-abstraction/font-client.h
dali/internal/text/text-abstraction/font-client-impl.cpp
dali/internal/text/text-abstraction/font-client-impl.h
dali/internal/text/text-abstraction/font-client-plugin-impl.cpp
dali/internal/text/text-abstraction/font-client-plugin-impl.h

diff --git a/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf
new file mode 100644 (file)
index 0000000..5267218
Binary files /dev/null and b/automated-tests/resources/fonts/dejavu/DejaVuSans.ttf differ
index 1774a04..ebf8994 100644 (file)
 #include <dali-test-suite-utils.h>
 #include <dali/dali.h>
 #include <dali/internal/text/text-abstraction/font-client-helper.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 using namespace Dali;
 
@@ -85,3 +87,269 @@ int UtcDaliFontClient(void)
 
   END_TEST;
 }
+
+int UtcDaliFontClientAtlasLimitation(void)
+{
+  TestApplication application;
+  bool             result = 0;
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+
+  tet_infoline("UtcDaliFontClientAtlasLimitation Default");
+  result = fontClient.IsAtlasLimitationEnabled();
+  DALI_TEST_EQUALS(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED, result, TEST_LOCATION);
+
+  tet_infoline("UtcDaliFontClientAtlasLimitation Enabled");
+  fontClient.EnableAtlasLimitation(true);
+  result = fontClient.IsAtlasLimitationEnabled();
+  DALI_TEST_EQUALS(true, result, TEST_LOCATION);
+
+  tet_infoline("UtcDaliFontClientAtlasLimitation Disabled");
+  fontClient.EnableAtlasLimitation(false);
+  result = fontClient.IsAtlasLimitationEnabled();
+  DALI_TEST_EQUALS(false, result, TEST_LOCATION);
+ END_TEST;
+ }
+
+const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+const uint32_t    MAX_WIDTH_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+const uint32_t    MAX_HEIGHT_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+
+int UtcDaliFontClientAtlasLimitationEnabled(void)
+{
+
+  TestApplication application;
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.EnableAtlasLimitation(true);
+
+  // The font file "DejaVuSans.ttf" is copied from Toolkit to Adaptor to make test-case of specific font-family.
+  // Note the block size depends on font-family.
+  // This is to create FontDescription and pass it to GetFontId with point-size (various cases).
+  TextAbstraction::FontDescription fontDescription;
+  fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+  fontDescription.family = "DejaVuSans";
+  fontDescription.width = TextAbstraction::FontWidth::NONE;
+  fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
+  fontDescription.slant = TextAbstraction::FontSlant::NONE;
+
+
+  // Block's width or height are less than 512
+  tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=200");
+  uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
+  glyphBufferData200.width  = 0;
+  glyphBufferData200.height = 0;
+  fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
+
+  DALI_TEST_GREATER( MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION );
+  DALI_TEST_GREATER( MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION );
+
+  // Block's width or height are  greater than 512 and less than 1024
+  uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=1000");
+  TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
+  glyphBufferData1000.width  = 0;
+  glyphBufferData1000.height = 0;
+  fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
+
+  DALI_TEST_GREATER(  MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION );
+  DALI_TEST_GREATER(  MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION );
+
+  // Block's width or height are greater than 1024 and less than 2048
+  uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=2000");
+  TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
+  glyphBufferData2000.width  = 0;
+  glyphBufferData2000.height = 0;
+  fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
+
+  DALI_TEST_GREATER(  MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION );
+  DALI_TEST_GREATER(  MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION );
+
+ END_TEST;
+}
+
+
+int UtcDaliFontClientAtlasLimitationDisabled(void)
+{
+
+  TestApplication application;
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.EnableAtlasLimitation(false);
+
+  TextAbstraction::FontDescription fontDescription;
+  fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+  fontDescription.family = "DejaVuSans";
+  fontDescription.width = TextAbstraction::FontWidth::NONE;
+  fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
+  fontDescription.slant = TextAbstraction::FontSlant::NONE;
+
+  // Block's width or height are less than 512
+  tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=200");
+  uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
+  glyphBufferData200.width  = 0;
+  glyphBufferData200.height = 0;
+  fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
+
+  DALI_TEST_GREATER(512u, glyphBufferData200.width,  TEST_LOCATION ); //93u
+  DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION ); //115u
+
+  // Block's width or height are  greater than 512 and less than 1024
+  tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=1000");
+  uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
+  glyphBufferData1000.width  = 0;
+  glyphBufferData1000.height = 0;
+  fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
+
+  DALI_TEST_GREATER( 512u, glyphBufferData1000.width, TEST_LOCATION ); //462u
+  DALI_TEST_GREATER( glyphBufferData1000.height, 512u, TEST_LOCATION ); //574u
+
+  // Block's width or height are greater than 1024 and less than 2048
+  tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=2000");
+  uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+  TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
+  glyphBufferData2000.width  = 0;
+  glyphBufferData2000.height = 0;
+  fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
+
+  DALI_TEST_GREATER( 1024u, glyphBufferData2000.width, TEST_LOCATION ); //924u
+  DALI_TEST_GREATER( glyphBufferData2000.height, 1024u, TEST_LOCATION ); //1148u
+
+ END_TEST;
+}
+
+int UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas ");
+
+  bool isChanged ;
+  TextAbstraction::FontClient fontClient;
+  fontClient = TextAbstraction::FontClient::Get();
+
+  Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
+  Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
+  Size currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+
+  tet_infoline("CurrentMaximumBlockSizeFitInAtlas start with default ");
+  DALI_TEST_EQUALS( currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION );
+
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
+  DALI_TEST_CHECK (isChanged);
+
+  Size decreaseOnlyWidth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with width < current ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyWidth);
+  DALI_TEST_CHECK (isChanged);
+
+  Size decreaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with height < current ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyHeigth);
+  DALI_TEST_CHECK (isChanged);
+
+  Size decreaseBoth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with size < current ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseBoth);
+  DALI_TEST_CHECK (isChanged);
+
+  Size increaseOnlyWidth (maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with width > max ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyWidth);
+  DALI_TEST_CHECK (!isChanged);
+
+  Size increaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with height > max ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyHeigth);
+  DALI_TEST_CHECK (!isChanged);
+
+  Size increaseBoth (maximumTextAtlasSize.width  + 1u, maximumTextAtlasSize.height + 1u);
+  tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size > max ");
+  isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseBoth);
+  DALI_TEST_CHECK (!isChanged);
+
+  currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+  if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
+  {
+    tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current < size < max ");
+    Size increaseWidth = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
+    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
+    DALI_TEST_CHECK (isChanged);
+    currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+
+    Size increaseHeigth = Size(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height + 1u);
+    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
+    DALI_TEST_CHECK (isChanged);
+    currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+
+    Size sizeLessThanMax = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height + 1u);
+    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
+
+    if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
+    {
+      DALI_TEST_CHECK (isChanged);
+    }
+    else
+    {
+      DALI_TEST_CHECK (!isChanged);
+    }
+
+    currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+
+    DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS (currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION );
+
+    tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size == max ");
+    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(maximumTextAtlasSize);
+    DALI_TEST_CHECK (!isChanged);
+  }
+
+  currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
+  DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize,  0.0f, TEST_LOCATION );
+
+
+  END_TEST;
+}
+
+int UtcDaliFontClientTextAtlasConstants(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliFontClientTextAtlasConstants ");
+
+  TextAbstraction::FontClient fontClient;
+  fontClient = TextAbstraction::FontClient::Get();
+
+  Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
+  Size defaultTextAtlasWidthHeight(TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_HEIGHT);
+  DALI_TEST_EQUALS (defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION );
+  DALI_TEST_EQUALS (defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION );
+
+
+  Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
+  Size maxTextAtlasWidthHeight(TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT);
+  DALI_TEST_EQUALS (maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION );
+  DALI_TEST_EQUALS (maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION );
+
+
+  uint32_t numberOfPointsPerOneUnitOfPointSize = fontClient.GetNumberOfPointsPerOneUnitOfPointSize();
+  DALI_TEST_EQUALS (numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION );
+
+  END_TEST;
+}
\ No newline at end of file
index 5f0f5c4..7531f55 100644 (file)
@@ -28,6 +28,26 @@ namespace TextAbstraction
 const PointSize26Dot6 FontClient::DEFAULT_POINT_SIZE   = 768u;                           // 12*64
 const float           FontClient::DEFAULT_ITALIC_ANGLE = 12.f * Dali::Math::PI_OVER_180; // FreeType documentation states the software italic is done by doing a horizontal shear of 12 degrees (file ftsynth.h).
 
+//Default atlas block
+const bool     FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED  = true;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_WIDTH          = 512u;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_HEIGHT         = 512u;
+const Size     FontClient::DEFAULT_TEXT_ATLAS_SIZE(DEFAULT_TEXT_ATLAS_WIDTH, DEFAULT_TEXT_ATLAS_HEIGHT);
+
+//Maximum atlas block
+const uint32_t FontClient::MAX_TEXT_ATLAS_WIDTH  = 1024u;
+const uint32_t FontClient::MAX_TEXT_ATLAS_HEIGHT = 1024u;
+const Size     FontClient::MAX_TEXT_ATLAS_SIZE(MAX_TEXT_ATLAS_WIDTH, MAX_TEXT_ATLAS_HEIGHT);
+
+//MAX_WIDTH_FIT_IN_ATLAS: blockWidth + 2 * DOUBLE_PIXEL_PADDING + 1u <= atlasWidth
+//MAX_HEIGHT_FIT_IN_ATLAS: blockHeight + 2 * DOUBLE_PIXEL_PADDING + 1u <= atlasHeight
+const uint16_t FontClient::PADDING_TEXT_ATLAS_BLOCK = 5u; // 2 * DOUBLE_PIXEL_PADDING + 1u
+
+//Maximum block size to fit into atlas block
+const Size  FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT_ATLAS_BLOCK, MAX_TEXT_ATLAS_HEIGHT - PADDING_TEXT_ATLAS_BLOCK );
+
+const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u;//Found this value from toolkit
+
 FontClient::GlyphBufferData::GlyphBufferData()
 : buffer{nullptr},
   width{0u},
@@ -235,6 +255,41 @@ GlyphIndex FontClient::CreateEmbeddedItem(const EmbeddedItemDescription& descrip
   return GetImplementation(*this).CreateEmbeddedItem(description, pixelFormat);
 }
 
+void FontClient::EnableAtlasLimitation(bool enabled)
+{
+  return GetImplementation(*this).EnableAtlasLimitation(enabled);
+}
+
+bool FontClient::IsAtlasLimitationEnabled() const
+{
+  return GetImplementation(*this).IsAtlasLimitationEnabled( );
+}
+
+Size FontClient::GetMaximumTextAtlasSize() const
+{
+  return GetImplementation(*this).GetMaximumTextAtlasSize( );
+}
+
+Size FontClient::GetDefaultTextAtlasSize() const
+{
+  return GetImplementation(*this).GetDefaultTextAtlasSize( );
+}
+
+Size FontClient::GetCurrentMaximumBlockSizeFitInAtlas() const
+{
+  return GetImplementation(*this).GetCurrentMaximumBlockSizeFitInAtlas( );
+}
+
+bool FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+{
+  return GetImplementation(*this).SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
+}
+
+uint32_t FontClient::GetNumberOfPointsPerOneUnitOfPointSize() const
+{
+  return GetImplementation(*this).GetNumberOfPointsPerOneUnitOfPointSize();
+}
+
 FontClient::FontClient(Internal::FontClient* internal)
 : BaseHandle(internal)
 {
index 92c8390..e77b53f 100644 (file)
@@ -64,6 +64,22 @@ public:
   static const PointSize26Dot6 DEFAULT_POINT_SIZE;   ///< The default point size.
   static const float           DEFAULT_ITALIC_ANGLE; ///< The default software italic angle in radians.
 
+  static const bool            DEFAULT_ATLAS_LIMITATION_ENABLED;  ///< The default behavior of whether atlas limitation is enabled in dali.
+  static const uint32_t        DEFAULT_TEXT_ATLAS_WIDTH;          ///< The default width of text-atlas-block.
+  static const uint32_t        DEFAULT_TEXT_ATLAS_HEIGHT;         ///< The default height of text-atlas-block.
+  static const Size            DEFAULT_TEXT_ATLAS_SIZE;           ///< The default size(width, height) of text-atlas-block.
+
+  static const uint32_t        MAX_TEXT_ATLAS_WIDTH;             ///< The maximum width of text-atlas-block.
+  static const uint32_t        MAX_TEXT_ATLAS_HEIGHT;            ///< The maximum height of text-atlas-block.
+  static const Size            MAX_TEXT_ATLAS_SIZE;              ///< The maximum height of text-atlas-block.
+
+  static const uint16_t        PADDING_TEXT_ATLAS_BLOCK ;        ///< Padding per edge. How much the block size (width, height) less than the text-atlas-block size (width, height).
+  static const Size            MAX_SIZE_FIT_IN_ATLAS;            ///< The maximum block's size fit into text-atlas-block.
+
+  static const uint32_t        NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
+
+
+
   /**
    * @brief Struct used to retrieve the glyph's bitmap.
    */
@@ -468,6 +484,63 @@ public:
    */
   GlyphIndex CreateEmbeddedItem(const EmbeddedItemDescription& description, Pixel::Format& pixelFormat);
 
+  /**
+   * @brief true to enable Atlas-Limitation.
+   *
+   * @note Used default configuration.
+   * @param[in] enabled The on/off value to enable/disable Atlas-Limitation.
+   */
+  void EnableAtlasLimitation(bool enabled);
+
+  /**
+   * @brief Check Atlas-Limitation is enabled or disabled.
+   *
+   * @note Used default configuration.
+   * return true if Atlas-Limitation is enabled, otherwise false.
+   */
+  bool IsAtlasLimitationEnabled() const;
+
+   /**
+   * @brief retrieve the maximum allowed width and height for text-atlas-block.
+   *
+   * @note Used default configuration.
+   * return the maximum width and height of text-atlas-block.
+   */
+  Size GetMaximumTextAtlasSize() const;
+
+   /**
+   * @brief retrieve the default width and height for text-atlas-block.
+   *
+   * @note Used default configuration.
+   * return the default width and height of text-atlas-block.
+   */
+  Size GetDefaultTextAtlasSize() const;
+
+  /**
+   * @brief retrieve the current maximum width and height for text-atlas-block.
+   *
+   * @note Used default configuration.
+   * return the current maximum width and height of text-atlas-block.
+   */
+  Size GetCurrentMaximumBlockSizeFitInAtlas() const;
+
+   /**
+   * @brief set the achieved size (width and height) for text-atlas-block.
+   * If @p currentMaximumBlockSizeFitInAtlas larger than the current maximum text atlas then store, otherwise ignore.
+   *
+   * @note Used default configuration.
+   * return true if the current maximum text atlas size is changed, otherwise false.
+   */
+  bool SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas);
+
+  /**
+   * @brief retrieve the number of points to scale-up one unit of point-size.
+   *
+   * @note Used default configuration.
+   * return the number of points per one unit of point-size
+   */
+  uint32_t GetNumberOfPointsPerOneUnitOfPointSize() const;
+
 public: // Not intended for application developers
   /**
    * @brief This constructor is used by FontClient::Get().
index 3f3bedb..d708d85 100644 (file)
@@ -333,6 +333,63 @@ GlyphIndex FontClient::CreateEmbeddedItem(const TextAbstraction::FontClient::Emb
   return mPlugin->CreateEmbeddedItem(description, pixelFormat);
 }
 
+void FontClient::EnableAtlasLimitation(bool enabled)
+{
+  CreatePlugin();
+  return mPlugin->EnableAtlasLimitation(enabled);
+}
+
+bool FontClient::IsAtlasLimitationEnabled() const
+{
+  if(mPlugin)
+  {
+    return mPlugin->IsAtlasLimitationEnabled();
+  }
+  return TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED;
+}
+
+Size FontClient::GetMaximumTextAtlasSize() const
+{
+  if(mPlugin)
+  {
+    return mPlugin->GetMaximumTextAtlasSize();
+  }
+  return TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::GetDefaultTextAtlasSize() const
+{
+  if(mPlugin)
+  {
+    return mPlugin->GetDefaultTextAtlasSize();
+  }
+  return TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::GetCurrentMaximumBlockSizeFitInAtlas() const
+{
+  if(mPlugin)
+  {
+    return mPlugin->GetCurrentMaximumBlockSizeFitInAtlas();
+  }
+  return TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE;
+}
+
+bool FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+{
+  CreatePlugin();
+  return mPlugin->SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
+}
+
+uint32_t FontClient::GetNumberOfPointsPerOneUnitOfPointSize() const
+{
+  if(mPlugin)
+  {
+    return mPlugin->GetNumberOfPointsPerOneUnitOfPointSize();
+  }
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+}
+
 FT_FaceRec_* FontClient::GetFreetypeFace(FontId fontId)
 {
   CreatePlugin();
index de6b99f..07eea78 100644 (file)
@@ -219,6 +219,41 @@ public:
   GlyphIndex CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat);
 
   /**
+   * @copydoc Dali::TextAbstraction::FontClient::EnableAtlasLimitation(bool enabled)
+   */
+  void EnableAtlasLimitation(bool enabled);
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::IsAtlasLimitationEnabled()
+   */
+  bool IsAtlasLimitationEnabled() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetMaximumTextAtlasSize()
+   */
+  Size GetMaximumTextAtlasSize() const;
+
+   /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
+   */
+  Size GetDefaultTextAtlasSize() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetCurrentMaximumBlockSizeFitInAtlas()
+   */
+  Size GetCurrentMaximumBlockSizeFitInAtlas() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+   */
+  bool SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas);
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetNumberOfPointsPerOneUnitOfPointSize()
+   */
+  uint32_t GetNumberOfPointsPerOneUnitOfPointSize() const;
+
+  /**
    * @brief Retrieves the pointer to the FreeType Font Face for the given @p fontId.
    *
    * @param[in] fontId The font id.
index 5bf652c..60deca8 100644 (file)
@@ -154,6 +154,126 @@ void DestroyCharacterSets(CharacterSetList& characterSets)
   }
 }
 
+/**
+ * @brief Check if @p ftFace and @p requestedPointSize produces block that fit into atlas block
+ *
+ * @param[in/out] ftFace Face type object.
+ * @param[in] horizontalDpi The horizontal dpi.
+ * @param[in] verticalDpi The vertical dpi.
+ * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
+ * @param[in] requestedPointSize The requested point-size.
+ * @return whether the  ftFace's block can fit into atlas
+ */
+bool IsFitIntoAtlas(FT_Face& ftFace, int& error, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, const uint32_t& requestedPointSize)
+{
+  bool isFit = false;
+
+  error = FT_Set_Char_Size(ftFace,
+                      0,
+                      requestedPointSize,
+                      horizontalDpi,
+                      verticalDpi);
+
+  if( error == FT_Err_Ok)
+  {
+    //Check width and height of block for requestedPointSize
+    //If the width or height is greater than the maximum-size then decrement by one unit of point-size.
+    if( static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height
+      && (static_cast<float>(ftFace->size->metrics.ascender)-static_cast<float>(ftFace->size->metrics.descender))* FROM_266 <= maxSizeFitInAtlas.width)
+    {
+      isFit = true;
+    }
+  }
+
+  return isFit;
+}
+
+/**
+ * @brief Search on proper @p requestedPointSize that produces block that fit into atlas block considering on @p ftFace, @p horizontalDpi, and @p verticalDpi
+ *
+ * @param[in/out] ftFace Face type object.
+ * @param[in] horizontalDpi The horizontal dpi.
+ * @param[in] verticalDpi The vertical dpi.
+ * @param[in] maxSizeFitInAtlas The maximum size of block to fit into atlas
+ * @param[in/out] requestedPointSize The requested point-size.
+ * @return FreeType error code. 0 means success when requesting the nominal size (in points).
+ */
+int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi, const unsigned int& verticalDpi, const Size& maxSizeFitInAtlas, uint32_t& requestedPointSize)
+{
+  //To improve performance of sequential search. This code is applying Exponential search then followed by Binary search.
+  const uint32_t& pointSizePerOneUnit = TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  bool canFitInAtlas;
+  int error; // FreeType error code.
+
+  canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+  if(FT_Err_Ok != error)
+  {
+    return error;
+  }
+
+  if(!canFitInAtlas)
+  {
+    //Exponential search
+    uint32_t exponentialDecrement = 1;
+
+    while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit*exponentialDecrement)
+    {
+      requestedPointSize-=(pointSizePerOneUnit*exponentialDecrement);
+      canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+      if(FT_Err_Ok != error)
+      {
+        return error;
+      }
+
+      exponentialDecrement*=2;
+    }
+
+    //Binary search
+    uint32_t minPointSize;
+    uint32_t maxPointSize;
+
+    if(canFitInAtlas)
+    {
+      exponentialDecrement/=2;
+      minPointSize = requestedPointSize;
+      maxPointSize = requestedPointSize + (pointSizePerOneUnit*exponentialDecrement);
+    }
+    else
+    {
+      minPointSize = 0;
+      maxPointSize = requestedPointSize;
+    }
+
+    while(minPointSize < maxPointSize)
+    {
+      requestedPointSize = ((maxPointSize/pointSizePerOneUnit - minPointSize/pointSizePerOneUnit)/2) * pointSizePerOneUnit + minPointSize;
+      canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+      if(FT_Err_Ok != error)
+      {
+        return error;
+      }
+
+      if(canFitInAtlas)
+      {
+        if(minPointSize == requestedPointSize)
+        {
+          //Found targeted point-size
+          return error;
+        }
+
+        minPointSize = requestedPointSize;
+      }
+      else
+      {
+        maxPointSize = requestedPointSize;
+      }
+    }
+  }
+
+  return error;
+}
+
+
 FontClient::Plugin::FallbackCacheItem::FallbackCacheItem(FontDescription&& font, FontList* fallbackFonts, CharacterSetList* characterSets)
 : fontDescription{std::move(font)},
   fallbackFonts{fallbackFonts},
@@ -247,7 +367,10 @@ FontClient::Plugin::Plugin(unsigned int horizontalDpi,
   mVectorFontCache(nullptr),
   mEllipsisCache(),
   mEmbeddedItemCache(),
-  mDefaultFontDescriptionCached(false)
+  mDefaultFontDescriptionCached(false),
+  mIsAtlasLimitationEnabled(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED),
+  mCurrentMaximumBlockSizeFitInAtlas(TextAbstraction::FontClient::MAX_SIZE_FIT_IN_ATLAS)
+
 {
   int error = FT_Init_FreeType(&mFreeTypeLibrary);
   if(FT_Err_Ok != error)
@@ -1882,6 +2005,54 @@ GlyphIndex FontClient::Plugin::CreateEmbeddedItem(const TextAbstraction::FontCli
 
   return mEmbeddedItemCache.Count();
 }
+//SHS
+
+void FontClient::Plugin::EnableAtlasLimitation(bool enabled)
+{
+  mIsAtlasLimitationEnabled = enabled;
+}
+
+bool FontClient::Plugin::IsAtlasLimitationEnabled() const
+{
+  return mIsAtlasLimitationEnabled;
+}
+
+Size FontClient::Plugin::GetMaximumTextAtlasSize() const
+{
+  return TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::Plugin::GetDefaultTextAtlasSize() const
+{
+  return TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE;
+}
+
+Size FontClient::Plugin::GetCurrentMaximumBlockSizeFitInAtlas() const
+{
+  return mCurrentMaximumBlockSizeFitInAtlas;
+}
+
+bool FontClient::Plugin::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+{
+  bool            isChanged        = false;
+  const Size&     maxTextAtlasSize = TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
+  const uint16_t& padding          = TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+
+  if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding
+      && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
+  {
+    mCurrentMaximumBlockSizeFitInAtlas = currentMaximumBlockSizeFitInAtlas;
+    isChanged = true;
+  }
+
+  return isChanged;
+}
+
+uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
+{
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+}
+
 
 void FontClient::Plugin::InitSystemFonts()
 {
@@ -2198,11 +2369,29 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
     }
     else
     {
-      error = FT_Set_Char_Size(ftFace,
+      if(mIsAtlasLimitationEnabled)
+      {
+        //There is limitation on block size to fit in predefined atlas size.
+        //If the block size cannot fit into atlas size, then the system cannot draw block.
+        //This is workaround to avoid issue in advance
+        //Decrementing point-size until arriving to maximum allowed block size.
+        auto requestedPointSizeBackup= requestedPointSize;
+        const Size& maxSizeFitInAtlas = GetCurrentMaximumBlockSizeFitInAtlas();
+        error = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
+
+        if(requestedPointSize != requestedPointSizeBackup)
+        {
+          DALI_LOG_WARNING(" The requested-point-size : %d, is reduced to point-size : %d\n", requestedPointSizeBackup, requestedPointSize);
+        }
+      }
+      else
+      {
+         error = FT_Set_Char_Size(ftFace,
                                0,
                                requestedPointSize,
                                mDpiHorizontal,
                                mDpiVertical);
+      }
 
       if(FT_Err_Ok == error)
       {
index 1449e49..fb3569a 100644 (file)
@@ -391,6 +391,41 @@ struct FontClient::Plugin
   GlyphIndex CreateEmbeddedItem(const TextAbstraction::FontClient::EmbeddedItemDescription& description, Pixel::Format& pixelFormat);
 
   /**
+   * @copydoc Dali::TextAbstraction::FontClient::EnableAtlasLimitation(bool enabled)
+   */
+  void EnableAtlasLimitation(bool enabled);
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::IsAtlasLimitationEnabled()
+   */
+  bool IsAtlasLimitationEnabled() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetMaximumTextAtlasSize()
+   */
+  Size GetMaximumTextAtlasSize() const;
+
+   /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
+   */
+  Size GetDefaultTextAtlasSize() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetCurrentMaximumBlockSizeFitInAtlas()
+   */
+  Size GetCurrentMaximumBlockSizeFitInAtlas() const;
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
+   */
+  bool SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas);
+
+  /**
+   * @copydoc Dali::TextAbstraction::FontClient::GetNumberOfPointsPerOneUnitOfPointSize()
+   */
+  uint32_t GetNumberOfPointsPerOneUnitOfPointSize() const;
+
+  /**
    * @copydoc Dali::TextAbstraction::Internal::FontClient::GetFreetypeFace()
    */
   FT_FaceRec_* GetFreetypeFace(FontId fontId);
@@ -649,6 +684,9 @@ private:
   std::vector<BitmapFontCacheItem>  mBitmapFontCache;   ///< Stores bitmap fonts.
 
   bool mDefaultFontDescriptionCached : 1; ///< Whether the default font is cached or not
+
+  bool mIsAtlasLimitationEnabled : 1; ///< Whether the validation on maximum atlas block size, then reduce block size to fit into it is enabled or not.
+  Vector2 mCurrentMaximumBlockSizeFitInAtlas; ///< The current maximum size (width, height) of text-atlas-block.
 };
 
 } // namespace Internal