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
#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;
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
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},
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)
{
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.
*/
*/
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().
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();
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.
}
}
+/**
+ * @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},
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)
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()
{
}
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)
{
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);
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