From: Victor Cebollada Date: Mon, 25 Mar 2019 14:31:03 +0000 (+0000) Subject: Bitmap Font support for TextLabel. X-Git-Tag: dali_1.4.15~2^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=8bd6da23805f5ee7c029a0e00d4c9bef93e539c0 Bitmap Font support for TextLabel. * The TextTypesetter supports glyphs from a bitmap font. Change-Id: Ic8befd32368d9747953545d0c504599fa835c0fd Signed-off-by: Victor Cebollada --- diff --git a/automated-tests/resources/fonts/bitmap/u0030.png b/automated-tests/resources/fonts/bitmap/u0030.png new file mode 100644 index 0000000..1b0cc3c Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0030.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0031.png b/automated-tests/resources/fonts/bitmap/u0031.png new file mode 100644 index 0000000..2c70e9c Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0031.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0032.png b/automated-tests/resources/fonts/bitmap/u0032.png new file mode 100644 index 0000000..2ed2d75 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0032.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0033.png b/automated-tests/resources/fonts/bitmap/u0033.png new file mode 100644 index 0000000..2cb1673 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0033.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0034.png b/automated-tests/resources/fonts/bitmap/u0034.png new file mode 100644 index 0000000..99d72e1 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0034.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0035.png b/automated-tests/resources/fonts/bitmap/u0035.png new file mode 100644 index 0000000..2780eae Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0035.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0036.png b/automated-tests/resources/fonts/bitmap/u0036.png new file mode 100644 index 0000000..62e240f Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0036.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0037.png b/automated-tests/resources/fonts/bitmap/u0037.png new file mode 100644 index 0000000..ae3790a Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0037.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0038.png b/automated-tests/resources/fonts/bitmap/u0038.png new file mode 100644 index 0000000..e2b0d13 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0038.png differ diff --git a/automated-tests/resources/fonts/bitmap/u0039.png b/automated-tests/resources/fonts/bitmap/u0039.png new file mode 100644 index 0000000..2a3f481 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u0039.png differ diff --git a/automated-tests/resources/fonts/bitmap/u003a.png b/automated-tests/resources/fonts/bitmap/u003a.png new file mode 100644 index 0000000..a6ca724 Binary files /dev/null and b/automated-tests/resources/fonts/bitmap/u003a.png differ diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp index 4c94126..9a6d206 100755 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp @@ -185,7 +185,10 @@ int UtcDaliTextCircularBitmapFont(void) Dali::Toolkit::DevelText::BitmapFontDescription description; Dali::Toolkit::DevelText::Glyph glyph; glyph.url = "BitmapFontUrl"; - glyph.utf8 = "BitmapFontUrl"; + glyph.utf8[0u] = 0u; + glyph.utf8[1u] = 0u; + glyph.utf8[2u] = 0u; + glyph.utf8[3u] = 0u; glyph.ascender = 1.f; glyph.descender = 1.f; description.glyphs.push_back( glyph ); diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp index 44136a7..8ec03d6 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include using namespace Dali; using namespace Toolkit; @@ -196,3 +198,53 @@ int UtcDaliTextTypesetterVerticalLineAlignment(void) tet_result(TET_PASS); END_TEST; } + +int UtcDaliTextTypesetterBitmapFont(void) +{ + tet_infoline("UtcDaliTextTypesetterBitmapFont "); + ToolkitTestApplication application; + + DevelText::BitmapFontDescription fontDescription; + fontDescription.name = "Digits"; + fontDescription.underlinePosition = 0.f; + fontDescription.underlineThickness = 0.f; + fontDescription.isColorFont = true; + + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0031.png", "0", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0032.png", "1", 34.f, 0.f } ); + + TextAbstraction::BitmapFont bitmapFont; + DevelText::CreateBitmapFont( fontDescription, bitmapFont ); + + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.GetFontId( bitmapFont ); + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + // Configures the text controller similarly to the text-label. + ConfigureTextLabel( controller ); + + // Sets the text. + controller->SetMarkupProcessorEnabled( true ); + controller->SetText( "0" ); + + // Creates the text's model and relais-out the text. + const Size relayoutSize( 31.f, 34.f ); + controller->Relayout( relayoutSize ); + + // Tests the rendering controller has been created. + TypesetterPtr renderingController = Typesetter::New( controller->GetTextModel() ); + DALI_TEST_CHECK( renderingController ); + + controller->Relayout( relayoutSize ); + + // Renders the text and creates the final bitmap. + auto bitmap = renderingController->Render( relayoutSize, Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ); + + DALI_TEST_EQUALS( 31u, bitmap.GetWidth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 34u, bitmap.GetHeight(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 493655d..96fcb63 100755 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include using namespace Dali; using namespace Toolkit; @@ -1419,3 +1421,50 @@ int UtcDaliToolkitTextlabelVerticalLineAlignment(void) END_TEST; } + +int UtcDaliToolkitTextLabelBitmapFont(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextLabelBitmapFont"); + + DevelText::BitmapFontDescription fontDescription; + fontDescription.name = "Digits"; + fontDescription.underlinePosition = 0.f; + fontDescription.underlineThickness = 0.f; + + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0030.png", ":", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0031.png", "0", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0032.png", "1", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0033.png", "2", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0034.png", "3", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0035.png", "4", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0036.png", "5", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0037.png", "6", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0038.png", "7", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u0039.png", "8", 34.f, 0.f } ); + fontDescription.glyphs.push_back( { TEST_RESOURCE_DIR "/fonts/bitmap/u003a.png", "9", 34.f, 0.f } ); + + TextAbstraction::BitmapFont bitmapFont; + DevelText::CreateBitmapFont( fontDescription, bitmapFont ); + + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.GetFontId( bitmapFont ); + + TextLabel label = TextLabel::New(); + + label.SetProperty( TextLabel::Property::TEXT, "0123456789:" ); + label.SetProperty( TextLabel::Property::FONT_FAMILY, "Digits" ); + + // The text has been laid out with the bitmap font if the natural size is the sum of all the width (322) and 34 height. + DALI_TEST_EQUALS( label.GetNaturalSize(), Vector3(322.f, 34.f, 0.f), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + Stage::GetCurrent().Add( label ); + + application.SendNotification(); + application.Render(); + + // The text has been rendered if the height of the text-label is the height of the line. + DALI_TEST_EQUALS( label.GetCurrentSize().height, 34.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/text/bitmap-font.cpp b/dali-toolkit/devel-api/text/bitmap-font.cpp index 1e0e9c6..6c22e44 100755 --- a/dali-toolkit/devel-api/text/bitmap-font.cpp +++ b/dali-toolkit/devel-api/text/bitmap-font.cpp @@ -19,30 +19,39 @@ #include // EXTERNAL INCLUDE -#include #include +#include // INTERNAL INCLUDE #include -#include - namespace Dali { namespace Toolkit { -using namespace Text; + namespace DevelText { Glyph::Glyph() : url{}, - utf8{ 0u }, + utf8{}, ascender{ 0.f }, descender{ 0.f } {} +Glyph::Glyph( const std::string& url, const std::string utf8Character, float ascender, float descender ) +: url{ url }, + utf8{}, + ascender{ ascender }, + descender{ descender } +{ + DALI_ASSERT_DEBUG( utf8Character.size() <= 4u ); + + std::copy( utf8Character.begin(), utf8Character.end(), utf8 ); +} + Glyph::~Glyph() {} @@ -62,20 +71,14 @@ void CreateBitmapFont( const BitmapFontDescription& description, TextAbstraction bitmapFont.name = description.name; bitmapFont.underlinePosition = description.underlinePosition; bitmapFont.underlineThickness = description.underlineThickness; + bitmapFont.isColorFont = description.isColorFont; for( const auto& glyph : description.glyphs ) { - // 1) Convert to utf32 - Vector utf32; - utf32.Resize( glyph.utf8.size() ); - - const uint32_t numberOfCharacters = ( glyph.utf8.size() == 0 ) ? 0 : - Text::Utf8ToUtf32( reinterpret_cast( glyph.utf8.c_str() ), - glyph.utf8.size(), - &utf32[0u] ); - utf32.Resize( numberOfCharacters ); + uint32_t c = 0u; + Text::Utf8ToUtf32( glyph.utf8, Text::GetUtf8Length( glyph.utf8[0u] ), &c ); - TextAbstraction::BitmapGlyph bitmapGlyph( glyph.url, utf32[0u], glyph.ascender, glyph.descender ); + TextAbstraction::BitmapGlyph bitmapGlyph( glyph.url, c, glyph.ascender, glyph.descender ); bitmapFont.glyphs.push_back( std::move( bitmapGlyph ) ); } diff --git a/dali-toolkit/devel-api/text/bitmap-font.h b/dali-toolkit/devel-api/text/bitmap-font.h index ca068b4..0d463df 100755 --- a/dali-toolkit/devel-api/text/bitmap-font.h +++ b/dali-toolkit/devel-api/text/bitmap-font.h @@ -52,14 +52,26 @@ struct DALI_TOOLKIT_API Glyph Glyph(); /** + * @brief Constructor. + * + * Initialize the members with the given values. + * + * @param[in] url The url of the bitmap for that glyph. + * @param[in] utf8 The utf8 codification of the glyph. + * @param[in] ascender The ascender of the glyph. + * @param[in] descender The descender of the glyph. + */ + Glyph( const std::string& url, const std::string utf8, float ascender, float descender ); + + /** * @brief Default destructor. */ ~Glyph(); - std::string url; ///< The url of the glyph. - std::string utf8; ///< the glyph encoded in utf8 - float ascender; ///< The ascender. The distance from the base line to the top of the glyph. - float descender; ///< The descender. The distance from the base line to the bottom of the glyph. + std::string url; ///< The url of the glyph. + uint8_t utf8[4]; ///< the glyph encoded in utf8 + float ascender; ///< The ascender. The distance from the base line to the top of the glyph. + float descender; ///< The descender. The distance from the base line to the bottom of the glyph. }; /** @@ -83,6 +95,7 @@ struct DALI_TOOLKIT_API BitmapFontDescription std::string name; ///< Name of the font. float underlinePosition; ///< The position of the underline from the base line. float underlineThickness; ///< The thickness of the underline. + bool isColorFont:1; ///< Whether the glyphs of this font have their own colors. }; /** diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index de6b712..20ea5f7 100755 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -80,7 +80,10 @@ void TypesetGlyph( GlyphData& data, if ( Pixel::RGBA8888 == pixelFormat ) { // Whether the given glyph is a color one. - const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; + const bool isColorGlyph = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap; + const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel( data.glyphBitmap.format ); + const uint32_t alphaIndex = glyphPixelSize - 1u; + const bool swapChannelsBR = Pixel::BGRA8888 == data.glyphBitmap.format; // Pointer to the color glyph if there is one. const uint32_t* const colorGlyphBuffer = isColorGlyph ? reinterpret_cast( data.glyphBitmap.buffer ) : NULL; @@ -88,6 +91,8 @@ void TypesetGlyph( GlyphData& data, // Initial vertical offset. const int yOffset = data.verticalOffset + position->y; + uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); + // Traverse the pixels of the glyph line per line. for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) { @@ -110,11 +115,9 @@ void TypesetGlyph( GlyphData& data, continue; } - uint32_t* bitmapBuffer = reinterpret_cast< uint32_t* >( data.bitmapBuffer.GetBuffer() ); - if( isColorGlyph ) { - // Retrieves the color from the color glyph. The format is BGRA8888. + // Retrieves the color from the color glyph. uint32_t packedColorGlyph = *( colorGlyphBuffer + glyphBufferOffset + index ); uint8_t* packedColorGlyphBuffer = reinterpret_cast( &packedColorGlyph ); @@ -129,7 +132,7 @@ void TypesetGlyph( GlyphData& data, } else { - uint8_t colorAlpha = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); + const uint8_t colorAlpha = static_cast( color->a * static_cast( *( packedColorGlyphBuffer + 3u ) ) ); *( packedColorGlyphBuffer + 3u ) = colorAlpha; if( Typesetter::STYLE_SHADOW == style ) @@ -141,11 +144,21 @@ void TypesetGlyph( GlyphData& data, } else { - std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. + if( swapChannelsBR ) + { + std::swap( *packedColorGlyphBuffer, *( packedColorGlyphBuffer + 2u ) ); // Swap B and R. + } *( packedColorGlyphBuffer + 2u ) = ( *( packedColorGlyphBuffer + 2u ) * colorAlpha / 255 ); *( packedColorGlyphBuffer + 1u ) = ( *( packedColorGlyphBuffer + 1u ) * colorAlpha / 255 ); *packedColorGlyphBuffer = ( *( packedColorGlyphBuffer ) * colorAlpha / 255 ); + + if( data.glyphBitmap.isColorBitmap ) + { + *( packedColorGlyphBuffer + 2u ) = static_cast( *( packedColorGlyphBuffer + 2u ) * color->b ); + *( packedColorGlyphBuffer + 1u ) = static_cast( *( packedColorGlyphBuffer + 1u ) * color->g ); + *packedColorGlyphBuffer = static_cast( *packedColorGlyphBuffer * color->r ); + } } } @@ -160,7 +173,7 @@ void TypesetGlyph( GlyphData& data, uint8_t* packedColorBuffer = reinterpret_cast( &packedColor ); // Update the alpha channel. - const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); + const uint8_t alpha = *( data.glyphBitmap.buffer + glyphPixelSize * ( glyphBufferOffset + index ) + alphaIndex ); // Copy non-transparent pixels only if ( alpha > 0u ) @@ -192,11 +205,15 @@ void TypesetGlyph( GlyphData& data, else { // Whether the given glyph is a color one. - const bool isColorGlyph = Pixel::BGRA8888 == data.glyphBitmap.format; + const bool isColorGlyph = data.glyphBitmap.isColorEmoji || data.glyphBitmap.isColorBitmap; + const uint32_t glyphPixelSize = Pixel::GetBytesPerPixel( data.glyphBitmap.format ); + const uint32_t alphaIndex = glyphPixelSize - 1u; // Initial vertical offset. const int yOffset = data.verticalOffset + position->y; + uint8_t* bitmapBuffer = reinterpret_cast< uint8_t* >( data.bitmapBuffer.GetBuffer() ); + // Traverse the pixels of the glyph line per line. for( int lineIndex = 0, glyphHeight = static_cast( data.glyphBitmap.height ); lineIndex < glyphHeight; ++lineIndex ) { @@ -219,12 +236,10 @@ void TypesetGlyph( GlyphData& data, continue; } - uint8_t* bitmapBuffer = reinterpret_cast< uint8_t* >( data.bitmapBuffer.GetBuffer() ); - if ( !isColorGlyph ) { // Update the alpha channel. - const uint8_t alpha = *( data.glyphBitmap.buffer + glyphBufferOffset + index ); + const uint8_t alpha = *( data.glyphBitmap.buffer + glyphPixelSize * ( glyphBufferOffset + index ) + alphaIndex ); // Copy non-transparent pixels only if ( alpha > 0u ) @@ -236,7 +251,7 @@ void TypesetGlyph( GlyphData& data, // overwrite a previous bigger alpha with a smaller alpha (in order to avoid // semi-transparent gaps between joint glyphs with overlapped pixels, which could // happen, for example, in the RTL text when we copy glyphs from right to left). - *( bitmapBuffer + verticalOffset + xOffsetIndex ) = std::max( currentAlpha, alpha ); + currentAlpha = std::max( currentAlpha, alpha ); } } }