utc-Dali-PropertyHelper.cpp
utc-Dali-SizeNegotiationMapper.cpp
utc-Dali-Text-CharacterSetConversion.cpp
+ utc-Dali-Text-Circular.cpp
utc-Dali-Text-Controller.cpp
utc-Dali-Text-Cursor.cpp
utc-Dali-Text-Layout.cpp
../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-render-controller.cpp
+ ../dali-toolkit/dali-toolkit-test-utils/test-render-surface.cpp
../dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
../dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
dali-toolkit-test-utils/toolkit-text-utils.cpp
visualModel = VisualModel::New();
MarkupProcessData markupProcessData( logicalModel->mColorRuns,
- logicalModel->mFontDescriptionRuns );
+ logicalModel->mFontDescriptionRuns,
+ logicalModel->mEmbeddedItems );
Length textSize = 0u;
const uint8_t* utf8 = NULL;
Vector2 naturalSize;
textVisual.GetNaturalSize( naturalSize );
- DALI_TEST_EQUALS( naturalSize, Vector2( 80.f, 20.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( naturalSize, Vector2( 78.f, 20.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION );
const float height = textVisual.GetHeightForWidth( 40.f );
DALI_TEST_EQUALS( height, 38.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
unsigned int characterIndex06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
12u, 12u, 12u, 12u, 12u, 12u };
- unsigned int logicalIndex06[] = { 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u, 0u,
- 16u, 15u, 14u, 13u, 12u, 11u };
+ unsigned int logicalIndex06[] = { 11u, 10u, 9u, 8u, 7u, 6u, 5u, 4u, 3u, 2u, 1u,
+ 13u, 16u, 15u, 14u, 13u, 12u };
unsigned int bidirectionalLineIndex06[] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
1u, 1u, 1u, 1u, 1u, 1u };
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-utils.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/bitmap-font.h>
+#include <dali/devel-api/text-abstraction/bitmap-font.h>
+#include <dali-toolkit/devel-api/text/text-utils-devel.h>
+#include <devel-api/adaptor-framework/image-loading.h>
+
+
+
+using namespace std;
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+namespace
+{
+const std::string TEST_IMAGE_FILE_NAME1 = TEST_RESOURCE_DIR "/application-icon-20.png";
+const std::string TEST_IMAGE_FILE_NAME2 = TEST_RESOURCE_DIR "/application-icon-26.png";
+
+const std::vector<std::string> embeddedItems = { TEST_IMAGE_FILE_NAME2, TEST_IMAGE_FILE_NAME2, TEST_IMAGE_FILE_NAME2, TEST_IMAGE_FILE_NAME2, TEST_IMAGE_FILE_NAME2 };
+
+struct CircularTextData
+{
+ std::string description;
+ std::string text;
+ DevelText::RendererParameters& textParameters;
+ const std::vector<std::string>& embeddedItems;
+ bool blend:1;
+};
+
+
+bool CircularRenderTest( const CircularTextData& data )
+{
+ bool ret = true;
+
+ Dali::Vector<Dali::Toolkit::DevelText::EmbeddedItemInfo> embeddedItemLayout;
+
+ Devel::PixelBuffer pixelBuffer = Toolkit::DevelText::Render( data.textParameters, embeddedItemLayout );
+
+ const int dstWidth = static_cast<int>( pixelBuffer.GetWidth() );
+ const int dstHeight = static_cast<int>( pixelBuffer.GetHeight() );
+
+ unsigned int index = 0u;
+ for( const auto& itemLayout : embeddedItemLayout )
+ {
+ int width = static_cast<int>( itemLayout.size.width );
+ int height = static_cast<int>( itemLayout.size.height );
+ int x = static_cast<int>( itemLayout.position.x );
+ int y = static_cast<int>( itemLayout.position.y );
+
+ Dali::Devel::PixelBuffer itemPixelBuffer = Dali::LoadImageFromFile( data.embeddedItems[index++] );
+ itemPixelBuffer.Resize( width, height );
+ itemPixelBuffer.Rotate( itemLayout.angle );
+
+ width = static_cast<int>( itemPixelBuffer.GetWidth() );
+ height = static_cast<int>( itemPixelBuffer.GetHeight() );
+
+ Dali::Pixel::Format itemPixelFormat = itemPixelBuffer.GetPixelFormat();
+
+ // Check if the item is out of the buffer.
+ if( ( x + width < 0 ) ||
+ ( x > dstWidth ) ||
+ ( y < 0 ) ||
+ ( y - height > dstHeight ) )
+ {
+ // The embedded item is completely out of the buffer.
+ continue;
+ }
+
+ // Crop if it exceeds the boundaries of the destination buffer.
+ int layoutX = 0;
+ int layoutY = 0;
+ int cropX = 0;
+ int cropY = 0;
+ int newWidth = width;
+ int newHeight = height;
+
+ bool crop = false;
+
+ if( 0 > x )
+ {
+ newWidth += x;
+ cropX = std::abs( x );
+ crop = true;
+ }
+ else
+ {
+ layoutX = x;
+ }
+
+ if( cropX + newWidth > dstWidth )
+ {
+ crop = true;
+ newWidth -= ( ( cropX + newWidth ) - dstWidth );
+ }
+
+ layoutY = y;
+ if( 0.f > layoutY )
+ {
+ newHeight += layoutY;
+ cropY = std::abs(layoutY);
+ crop = true;
+ }
+
+ if( cropY + newHeight > dstHeight )
+ {
+ crop = true;
+ newHeight -= ( ( cropY + newHeight ) - dstHeight );
+ }
+
+ uint16_t uiCropX = static_cast<uint16_t>(cropX);
+ uint16_t uiCropY = static_cast<uint16_t>(cropY);
+ uint16_t uiNewWidth = static_cast<uint16_t>(newWidth);
+ uint16_t uiNewHeight = static_cast<uint16_t>(newHeight);
+
+ if( crop )
+ {
+ itemPixelBuffer.Crop( uiCropX, uiCropY, uiNewWidth, uiNewHeight );
+ }
+
+ // Blend the item pixel buffer with the text's color according its blending mode.
+ if( Dali::TextAbstraction::ColorBlendingMode::MULTIPLY == itemLayout.colorBlendingMode )
+ {
+ Dali::Devel::PixelBuffer buffer = Dali::Devel::PixelBuffer::New( uiNewWidth,
+ uiNewHeight,
+ itemPixelFormat );
+
+ unsigned char* bufferPtr = buffer.GetBuffer();
+ const unsigned char* itemBufferPtr = itemPixelBuffer.GetBuffer();
+ const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(itemPixelFormat);
+ const unsigned int size = uiNewWidth * uiNewHeight * bytesPerPixel;
+
+ for (unsigned int i = 0u; i < size; i += bytesPerPixel)
+ {
+ *(bufferPtr + 0u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 0u) ) * data.textParameters.textColor.r );
+ *(bufferPtr + 1u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 1u) ) * data.textParameters.textColor.g );
+ *(bufferPtr + 2u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 2u) ) * data.textParameters.textColor.b );
+ *(bufferPtr + 3u) = static_cast<unsigned char>( static_cast<float>( *(itemBufferPtr + 3u) ) * data.textParameters.textColor.a );
+
+ itemBufferPtr += bytesPerPixel;
+ bufferPtr += bytesPerPixel;
+ }
+
+ itemPixelBuffer = buffer;
+ }
+
+ Dali::Toolkit::DevelText::UpdateBuffer(itemPixelBuffer, pixelBuffer, layoutX, layoutY, data.blend);
+ }
+
+ return ret;
+}
+
+} // namespace
+
+int UtcDaliTextCircularBitmapFont(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularBitmapFont");
+
+ Dali::Toolkit::DevelText::BitmapFontDescription description;
+ Dali::Toolkit::DevelText::Glyph glyph;
+ glyph.url = "BitmapFontUrl";
+ glyph.utf8 = "BitmapFontUrl";
+ glyph.ascender = 1.f;
+ glyph.descender = 1.f;
+ description.glyphs.push_back( glyph );
+
+ TextAbstraction::BitmapFont bitmapFont;
+ Dali::Toolkit::DevelText::CreateBitmapFont( description, bitmapFont );
+
+ for( const auto& bitmapGlyph : bitmapFont.glyphs )
+ {
+ if( glyph.url != bitmapGlyph.url )
+ {
+ std::cout << " different output string : " << bitmapGlyph.url << ", expected : " << glyph.url << " " << std::endl;
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularShadowText(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularShadowText");
+
+ Dali::Toolkit::DevelText::ShadowParameters shadowParameters;
+ Devel::PixelBuffer outPixelBuffer;
+ shadowParameters.input = Devel::PixelBuffer::New( 100, 100, Pixel::RGBA8888 );
+ shadowParameters.textColor = Color::BLACK;
+ shadowParameters.color = Color::BLACK;
+ shadowParameters.offset.x = 10u;
+ shadowParameters.offset.y = 10u;
+ shadowParameters.blendShadow = true;
+ outPixelBuffer = Dali::Toolkit::DevelText::CreateShadow( shadowParameters );
+ DALI_TEST_CHECK( outPixelBuffer );
+ DALI_TEST_EQUALS( outPixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ shadowParameters.blendShadow = false;
+ outPixelBuffer = Dali::Toolkit::DevelText::CreateShadow( shadowParameters );
+ DALI_TEST_CHECK( outPixelBuffer );
+ DALI_TEST_EQUALS( outPixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ shadowParameters.input = Devel::PixelBuffer::New( 100, 100, Pixel::A8 );
+ outPixelBuffer = Dali::Toolkit::DevelText::CreateShadow( shadowParameters );
+ DALI_TEST_CHECK( outPixelBuffer );
+ DALI_TEST_EQUALS( outPixelBuffer.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularPixelBufferText(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularPixelBufferText");
+
+ Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::A8 );
+ Vector4 color;
+ Devel::PixelBuffer pixelBufferRgba = Dali::Toolkit::DevelText::ConvertToRgba8888( pixbuf, color, true );
+ pixelBufferRgba = Dali::Toolkit::DevelText::ConvertToRgba8888( pixbuf, color, false );
+ DALI_TEST_CHECK( pixelBufferRgba );
+ DALI_TEST_EQUALS( pixelBufferRgba.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ pixbuf = Devel::PixelBuffer::New( 10, 10, Pixel::RGBA8888 );
+ pixelBufferRgba = Dali::Toolkit::DevelText::ConvertToRgba8888( pixbuf, color, false );
+ DALI_TEST_CHECK( pixelBufferRgba );
+ DALI_TEST_EQUALS( pixelBufferRgba.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularNoText(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularNoText");
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "";
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+
+ CircularTextData data =
+ {
+ "No text",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.text = "<item 'width'=26 'height'=26/>";
+ textParameters.markupEnabled = true;
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularIncrementAngle(void)
+{
+
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularIncrementAngle");
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "Hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 0.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+
+ CircularTextData data =
+ {
+ "IncrementAngle",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+
+
+int UtcDaliTextCircularMarkup(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularMarkup");
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = false;
+
+ CircularTextData data =
+ {
+ "Markup",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularFont(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularFont");
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "Hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "thin";
+ textParameters.fontWidth = "condensed";
+ textParameters.fontSlant = "normal";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "Font",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularAlignment(void)
+{
+
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularAlignment");
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "Hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "Alignment",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.horizontalAlignment = "begin";
+ textParameters.verticalAlignment = "top";
+ textParameters.circularAlignment = "begin";
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.horizontalAlignment = "end";
+ textParameters.verticalAlignment = "bottom";
+ textParameters.circularAlignment = "end";
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularRTL(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularRTL");
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "مرحبا بالعالم" + image1 + " hello world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "RTL",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.circularAlignment = "begin";
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.circularAlignment = "end";
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.text = "שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم";
+ textParameters.layout = "singleLine";
+ textParameters.horizontalAlignment = "end";
+ textParameters.fontSize = 90.f;
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularN(void)
+{
+
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCircularN");
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "singleLine";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "singleLine",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.verticalAlignment = "top";
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.verticalAlignment = "bottom";
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.textWidth = 90u;
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularBlend(void)
+{
+ tet_infoline(" UtcDaliTextCircularN");
+
+ ToolkitTestApplication application;
+ Stage stage = Stage::GetCurrent();
+ stage.SetBackgroundColor( Color::WHITE );
+ stage.SetBackgroundColor( Vector4( 0.04f, 0.345f, 0.392f, 1.0f ) );
+
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "blend",
+ "",
+ textParameters,
+ embeddedItems,
+ false
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularEllipsis(void)
+{
+ tet_infoline(" UtcDaliTextCircularEllipsis");
+
+ ToolkitTestApplication application;
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = false;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "ellipsis",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ textParameters.layout = "singleLine";
+ textParameters.textHeight = 50u;
+ textParameters.ellipsisEnabled = true;
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularEmoji(void)
+{
+ tet_infoline(" UtcDaliTextCircularEmoji");
+
+ ToolkitTestApplication application;
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "<font family='BreezeColorEmoji' size='60'>\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84</font>";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "Emoji",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextUpdateBufferFormatCheck(void)
+{
+ tet_infoline(" UtcDaliTextUpdateBufferFormatCheck");
+ ToolkitTestApplication application;
+
+ Devel::PixelBuffer srcBuffer = Devel::PixelBuffer::New( 10, 10, Pixel::RGBA8888 );
+ Devel::PixelBuffer dstBuffer = Devel::PixelBuffer::New( 10, 10, Pixel::A8 );
+
+ Dali::Toolkit::DevelText::UpdateBuffer(srcBuffer, dstBuffer, 0, 0, true);
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularTextColor(void)
+{
+ tet_infoline(" UtcDaliTextCircularTextColor");
+
+ ToolkitTestApplication application;
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "'/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "hello " + image1 + " <color value='blue'>world</color> " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "textColor",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCircularColorBlend(void)
+{
+ tet_infoline(" UtcDaliTextCircularColorBlend");
+
+ ToolkitTestApplication application;
+
+ const std::string image1 = "<item 'width'=26 'height'=26 'url'='" + TEST_IMAGE_FILE_NAME1 + "' 'color-blending'=multiply/>";
+ const std::string image2 = "<item 'width'=26 'height'=26/>";
+
+ Dali::Toolkit::DevelText::RendererParameters textParameters;
+ textParameters.text = "hello " + image1 + " world " + image2 + " this " + image1 + " is " + image2 + " a " + image1 + " demo " + image2 + " of " + image1 + " circular " + image2 + " text " + image1 + " width " + image2 + " icons.";
+ textParameters.horizontalAlignment = "center";
+ textParameters.verticalAlignment = "center";
+ textParameters.circularAlignment = "center";
+ textParameters.fontFamily = "SamsungUI";
+ textParameters.fontWeight = "";
+ textParameters.fontWidth = "";
+ textParameters.fontSlant = "";
+ textParameters.layout = "circular";
+ textParameters.textColor = Color::BLACK;
+ textParameters.fontSize = 25.f;
+ textParameters.textWidth = 360u;
+ textParameters.textHeight = 360u;
+ textParameters.radius = 180u;
+ textParameters.beginAngle = 15.f;
+ textParameters.incrementAngle = 360.f;
+ textParameters.ellipsisEnabled = true;
+ textParameters.markupEnabled = true;
+
+ CircularTextData data =
+ {
+ "colorBlend",
+ "",
+ textParameters,
+ embeddedItems,
+ true
+ };
+
+ if( !CircularRenderTest( data ) )
+ {
+ tet_result(TET_FAIL);
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
gClipboardText = notifier.GetContent();
}
+// Generate a KeyEvent to send to Core.
+Dali::KeyEvent GenerateKey( const std::string& keyName,
+ const std::string& keyString,
+ int keyCode,
+ int keyModifier,
+ unsigned long timeStamp,
+ const Dali::KeyEvent::State& keyState )
+{
+ return Dali::KeyEvent( keyName,
+ keyString,
+ keyCode,
+ keyModifier,
+ timeStamp,
+ keyState );
+}
+
} // namespace
int UtcDaliTextController(void)
// single line, line spacing = 0px
{
const float EXPECTED_SPACING = 0.0f;
- const Vector2 EXPECTED_LAYOUT_SIZE( 343.0f, 19.0f);
- const Vector3 EXPECTED_NATURAL_SIZE( 344.0f, 20.0f, 0.0f );
+ const Vector2 EXPECTED_LAYOUT_SIZE( 342.0f, 19.0f);
+ const Vector3 EXPECTED_NATURAL_SIZE( 342.0f, 20.0f, 0.0f );
controller->SetText(textSingle);
controller->Relayout(size);
// single line, line spacing = 20px
{
const float EXPECTED_SPACING = 20.0f;
- const Vector2 EXPECTED_LAYOUT_SIZE( 343.0f, 19.0f );
- const Vector3 EXPECTED_NATURAL_SIZE( 344.0f, 40.0f, 0.0f );
+ const Vector2 EXPECTED_LAYOUT_SIZE( 342.0f, 19.0f );
+ const Vector3 EXPECTED_NATURAL_SIZE( 342.0f, 40.0f, 0.0f );
controller->SetText(textSingle);
controller->Relayout(size);
// multi-line, line spacing = 0px
{
const float EXPECTED_SPACING = 0.0f;
- const Vector2 EXPECTED_LAYOUT_SIZE( 333.0f, 39.0f );
- const Vector3 EXPECTED_NATURAL_SIZE( 120.0f, 58.0f, 0.0f );
+ const Vector2 EXPECTED_LAYOUT_SIZE( 332.0f, 39.0f );
+ const Vector3 EXPECTED_NATURAL_SIZE( 118.0f, 58.0f, 0.0f );
controller->SetText(textMulti);
controller->Relayout(size);
// multi-line, line spacing = 20px
{
const float EXPECTED_SPACING = 20.0f;
- const Vector2 EXPECTED_LAYOUT_SIZE( 119.0f, 57.0f );
- const Vector3 EXPECTED_NATURAL_SIZE( 120.0f, 118.0f, 0.0f );
+ const Vector2 EXPECTED_LAYOUT_SIZE( 118.0f, 57.0f );
+ const Vector3 EXPECTED_NATURAL_SIZE( 118.0f, 118.0f, 0.0f );
controller->SetText(textMulti);
controller->Relayout(size);
// multi-line, line spacing = 30px
{
const float EXPECTED_SPACING = 30.0f;
- const Vector2 EXPECTED_LAYOUT_SIZE( 119.0f, 117.0f );
- const Vector3 EXPECTED_NATURAL_SIZE( 120.0f, 148.0f, 0.0f );
+ const Vector2 EXPECTED_LAYOUT_SIZE( 118.0f, 117.0f );
+ const Vector3 EXPECTED_NATURAL_SIZE( 118.0f, 148.0f, 0.0f );
controller->SetText(textMulti);
controller->Relayout(size);
END_TEST;
}
+
+int UtcDaliTextControllerCheckInputColorChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputColorChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text
+ const std::string text("Hello World!");
+ controller->SetText(text);
+
+ const Vector4 inputColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ controller->SetInputColor( inputColor );
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input color
+ const Vector4 newInputColor( 1.0f, 0.0f, 0.0f, 1.0f );
+ controller->SetInputColor( newInputColor );
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::COLOR, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::COLOR ), TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
+
+int UtcDaliTextControllerCheckInputFontFamilyChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputFontFamilyChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text and font family
+ const std::string text("Hello World!");
+ controller->SetText(text);
+ controller->SetInputFontFamily("SamsungOneUI_200");
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input font family
+ controller->SetInputFontFamily("SamsungOneUI_300");
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::VALIDATE_FONTS, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::VALIDATE_FONTS ),
+ TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
+
+int UtcDaliTextControllerCheckInputFontWeightChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputFontWeightChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text
+ const std::string text("Hello World!");
+ controller->SetText(text);
+ controller->SetInputFontWeight( TextAbstraction::FontWeight::NORMAL );
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input font weight
+ controller->SetInputFontWeight( TextAbstraction::FontWeight::BOLD );
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::VALIDATE_FONTS, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::VALIDATE_FONTS ),
+ TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
+
+int UtcDaliTextControllerCheckInputFontWidthChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputFontWidthChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text
+ const std::string text("Hello World!");
+ controller->SetText(text);
+ controller->SetInputFontWidth( TextAbstraction::FontWidth::NORMAL );
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input font width
+ controller->SetInputFontWidth( TextAbstraction::FontWidth::EXPANDED );
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::VALIDATE_FONTS, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::VALIDATE_FONTS ),
+ TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
+
+int UtcDaliTextControllerCheckInputFontSlantChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputFontSlantChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text
+ const std::string text("Hello World!");
+ controller->SetText(text);
+ controller->SetInputFontSlant( TextAbstraction::FontSlant::NORMAL );
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input font slant
+ controller->SetInputFontSlant( TextAbstraction::FontSlant::ROMAN );
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::VALIDATE_FONTS, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::VALIDATE_FONTS ),
+ TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
+
+int UtcDaliTextControllerCheckInputFontPointSizeChanged(void)
+{
+ tet_infoline(" UtcDaliTextControllerCheckInputFontPointSizeChanged");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextLabel(controller);
+
+ // Enable the text input.
+ // Creates a decorator.
+ Text::DecoratorPtr decorator = Text::Decorator::New( *controller,
+ *controller );
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+ // Enables the text input.
+ controller->EnableTextInput( decorator, inputMethodContext );
+
+ // Set the text
+ const std::string text("Hello World!");
+ controller->SetText(text);
+ controller->SetInputFontPointSize( 1.0f );
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation( *controller.Get() );
+
+ // Reset operation
+ mImpl.mOperationsPending = Controller::NO_OPERATION;
+
+ // simulate a key event.
+ controller->KeyEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Dali::KeyEvent::Down ) );
+
+ // change the input font point size
+ controller->SetInputFontPointSize( 1.2f );
+
+ // Check if relayout is requested or not when event state is INACTIVE.
+ DALI_TEST_EQUALS( EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION );
+ DALI_TEST_EQUALS( Controller::VALIDATE_FONTS, static_cast<Controller::OperationsMask>( mImpl.mOperationsPending & Controller::VALIDATE_FONTS ),
+ TEST_LOCATION );
+
+ // Perform a relayout
+ const Size size( Dali::Stage::GetCurrent().GetSize() );
+ controller->Relayout(size);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
float visualX02[] = { -100.f, 1000.f, 60.f, 79.f, 83.f, 148.f, 99.f };
float visualY02[] = { -100.f, 1000.f, 12.f, 12.f, 12.f, 12.f, 12.f };
CharacterHitTest::Mode mode02[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
- CharacterIndex logicalIndex02[] = { 0, 21u, 7u, 10u, 11u, 13u, 20u };
+ CharacterIndex logicalIndex02[] = { 0, 21u, 8u, 11u, 11u, 13u, 20u };
bool isCharacterHit02[] = { false, false, true, true, true, true, true };
float visualX03[] = { 19.f, 104.f, -2.f, 127.f };
CharacterHitTest::Mode mode04[] = { CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
- CharacterIndex logicalIndex04[] = { 0, 5u, 6u, 11u, 11u,
+ CharacterIndex logicalIndex04[] = { 0, 6u, 6u, 11u, 11u,
12u, 16u, 17u, 21u, 21u,
22u, 25u, 31u, 32u, 34u, 40u, 40u,
41u };
bool isCharacterHit04[] = { false, true, true, false, false,
- false, true, true, true, false,
- false, true, true, true, true, true, false };
+ false, true, true, false, false,
+ false, true, true, true, true, false, false };
// 0 10 20 30 40 46
// abcשנבdefג קכghiעיןjk lחלךmnoצמם pqrפרףstuד אוvwxה
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP,
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
- CharacterIndex logicalIndex05[] = { 0, 10u, 20u, 30u, 40u, 45u,
- 46u, 50u, 60u, 70u, 80u, 92u,
- 93u, 100u, 110u, 120u, 130u, 138u,
- 139u, 150u, 160u, 170u, 180u, 185u,
- 186u, 190u, 200u, 210u, 220u, 232u,
- 233u, 240u, 250u, 260u, 265u };
+ CharacterIndex logicalIndex05[] = { 0, 10u, 20u, 30u, 40u, 46u,
+ 47u, 52u, 62u, 71u, 82u, 93u,
+ 95u, 99u, 112u, 122u, 131u, 140u,
+ 141u, 153u, 162u, 171u, 181u, 187u,
+ 188u, 194u, 201u, 213u, 222u, 234u,
+ 236u, 244u, 254u, 263u, 265u };
bool isCharacterHit05[] = { false, true, true, true, true, false,
false, true, true, true, true, false,
false, true, true, true, true, false,
CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP, CharacterHitTest::TAP };
CharacterIndex logicalIndex06[] = { 0, 10u, 20u, 30u, 40u, 45u,
46u, 50u, 60u, 70u, 80u, 92u,
- 93u, 100u, 110u, 120u, 130u, 138u,
+ 93u, 100u, 110u, 121u, 131u, 138u,
139u, 150u, 160u, 170u, 180u, 185u,
186u, 190u, 200u, 210u, 220u, 231u,
232u, 240u, 250u, 260u, 265u };
float visualX08[] = { 7.f };
float visualY08[] = { 12.f };
CharacterHitTest::Mode mode08[] = { CharacterHitTest::TAP };
- CharacterIndex logicalIndex08[] = { 1u };
+ CharacterIndex logicalIndex08[] = { 2u };
bool isCharacterHit08[] = { true };
struct GetClosestCursorIndexData data[] =
{
tet_infoline(" UtcDaliGetCursorPosition");
- float visualX08[] = { 5.f };
+ float visualX08[] = { 4.f };
float visualY08[] = { 0.f };
CharacterIndex logicalIndex08[] = { 1u };
CharacterIndex endIndex03[] = { 11u };
CharacterIndex noHitText03[] = { 0u };
- float visualX04[] = { 132.f };
+ float visualX04[] = { 131.f };
float visualY04[] = { 12.f };
bool found04[] = { true };
CharacterIndex startIndex04[] = { 12u };
CharacterIndex endIndex04[] = { 16u };
CharacterIndex noHitText04[] = { 0u };
- float visualX05[] = { 1.f };
+ float visualX05[] = { 0.f };
float visualY05[] = { 12.f };
bool found05[] = { true };
CharacterIndex startIndex05[] = { 0 };
Layout::Engine engine;
- DALI_TEST_EQUALS( 1, engine.GetCursorWidth(), TEST_LOCATION );
+ DALI_TEST_EQUALS( 0, engine.GetCursorWidth(), TEST_LOCATION );
engine.SetCursorWidth( 2 );
DALI_TEST_EQUALS( 2, engine.GetCursorWidth(), TEST_LOCATION );
Vector<FontDescriptionRun> fontDescriptionRuns;
fontDescriptionRuns.PushBack( fontDescriptionRun );
Size textArea(1.f, 1.f);
- Size layoutSize(80.f, 19.f);
- float positions[] = { 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f };
+ Size layoutSize(78.f, 19.f);
+ float positions[] = { 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f };
struct LineRun line =
{
{ 0u, 11u },
{ 0u, 11u },
- 80.f,
+ 78.f,
15.f,
-4.f,
0.f,
fontDescriptionRuns.PushBack( fontDescriptionRun1 );
fontDescriptionRuns.PushBack( fontDescriptionRun2 );
Size textArea(100.f, 300.f);
- Size layoutSize(95.f, 95.f);
+ Size layoutSize(91.f, 95.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f, 42.f, -12.f,
- 1.f, -12.f, 9.f, -9.f, 17.f, -9.f, 27.f, -9.f, 36.f, -9.f, 45.f, -11.f, 51.f, -0.f,
- 1.f, -12.f, 11.f, -12.f, 15.f, -12.f, 26.f, -9.f, 35.f, -9.f, 41.f, -9.f, 50.f, -9.f, 59.f, -11.f, 65.f, -0.f,
- 1.f, -12.f, 5.f, -12.f, 9.f, -9.f, 19.f, -9.f, 28.f, -9.f, 35.f, -0.f, 41.f, -9.f, 50.f, -12.f, 54.f, -0.f, 59.f, -11.f, 66.f, -9.f, 75.f, -9.f, 83.f, -11.f, 91.f, -2.f
+ 0.f, -12.f, 8.f, -9.f, 16.f, -9.f, 26.f, -9.f, 35.f, -9.f, 44.f, -11.f, 50.f, -0.f,
+ 0.f, -12.f, 10.f, -12.f, 14.f, -12.f, 25.f, -9.f, 34.f, -9.f, 40.f, -9.f, 49.f, -9.f, 58.f, -11.f, 64.f, -0.f,
+ 0.f, -12.f, 4.f, -12.f, 8.f, -9.f, 18.f, -9.f, 27.f, -9.f, 34.f, -0.f, 40.f, -9.f, 49.f, -12.f, 53.f, -0.f, 58.f, -11.f, 65.f, -9.f, 74.f, -9.f, 82.f, -11.f, 90.f, -2.f
};
struct LineRun line0 =
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 12u, 6u },
{ 12u, 6u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
{
{ 18u, 7u },
{ 18u, 7u },
- 52.f,
+ 49.f,
15.f,
-4.f,
5.f,
{
{ 25u, 9u },
{ 25u, 10u },
- 66.f,
+ 63.f,
15.f,
-4.f,
5.f,
{
{ 34u, 14u },
{ 35u, 14u },
- 95.f,
+ 91.f,
15.f,
-4.f,
0.f,
fontDescriptionRuns.PushBack( fontDescriptionRun4 );
fontDescriptionRuns.PushBack( fontDescriptionRun5 );
Size textArea(100.f, 300.f);
- Size layoutSize(80.f, 114.f);
+ Size layoutSize(78.f, 114.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f,
};
struct LineRun line0 =
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 12u, 10u },
{ 12u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 22u, 6u },
{ 22u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
{
{ 28u, 10u },
{ 28u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
{
{ 38u, 12u },
{ 38u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 50u, 5u },
{ 50u, 5u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
Vector<FontDescriptionRun> fontDescriptionRuns;
fontDescriptionRuns.PushBack( fontDescriptionRun );
Size textArea(100.f, 300.f);
- Size layoutSize(96.f, 57.f);
+ Size layoutSize(94.f, 57.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -9.f, 47.f, -9.f, 57.f, -9.f, 63.f, -13.f, 66.f, -13.f, 75.f, -13.f, 84.f, -9.f,
- 1.f, -9.f, 13.f, -9.f, 23.f, -13.f, 31.f, -9.f, 40.f, -13.f, 44.f, -13.f, 47.f, -9.f, 56.f, -9.f, 67.f, -9.f, 77.f, -9.f, 83.f, -13.f, 86.f, -13.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -9.f, 46.f, -9.f, 56.f, -9.f, 62.f, -13.f, 65.f, -13.f, 74.f, -13.f, 83.f, -9.f,
+ 0.f, -9.f, 12.f, -9.f, 22.f, -13.f, 30.f, -9.f, 39.f, -13.f, 43.f, -13.f, 46.f, -9.f, 55.f, -9.f, 66.f, -9.f, 76.f, -9.f, 82.f, -13.f, 85.f, -13.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f,
};
struct LineRun line0 =
{
{ 0u, 12u },
{ 0u, 12u },
- 93.f,
+ 91.f,
15.f,
-4.f,
0.f,
{
{ 12u, 12u },
{ 12u, 12u },
- 96.f,
+ 94.f,
15.f,
-4.f,
0.f,
{
{ 24u, 5u },
{ 24u, 5u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
Vector<FontDescriptionRun> fontDescriptionRuns;
fontDescriptionRuns.PushBack( fontDescriptionRun );
Size textArea(100.f, 300.f);
- Size layoutSize(83.f, 38.f);
+ Size layoutSize(81.f, 38.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -2.f, 82.f, -12.f
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -2.f, 81.f, -12.f
};
struct LineRun line0 =
{
{ 0u, 13u },
{ 0u, 13u },
- 83.f,
+ 81.f,
15.f,
-4.f,
0.f,
fontDescriptionRuns.PushBack( fontDescriptionRun2 );
fontDescriptionRuns.PushBack( fontDescriptionRun3 );
Size textArea(100.f, 300.f);
- Size layoutSize(89.f, 51.f);
+ Size layoutSize(87.f, 51.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -14.f, 60.f, -9.f, 70.f, -9.f, 76.f, -13.f, 79.f, -13.f, 88.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -14.f, 59.f, -9.f, 69.f, -9.f, 75.f, -13.f, 78.f, -13.f, 87.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f
};
struct LineRun line0 =
{
{ 0u, 12u },
{ 0u, 12u },
- 89.f,
+ 87.f,
25.f,
-7.f,
4.f,
{
{ 12u, 5u },
{ 12u, 5u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
Size layoutSize(92.f, 361.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 67.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f, 42.f, -12.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
};
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 12u, 10u },
{ 12u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 22u, 6u },
{ 22u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
4.f,
0.f,
0.f,
- false,
+ true,
false
};
struct LineRun line05 =
{
{ 48u, 11u },
{ 48u, 11u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 59u, 5u },
{ 59u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 64u, 10u },
{ 64u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
0.f,
0.f,
- false,
+ true,
false
};
struct LineRun line08 =
{
{ 74u, 12u },
{ 74u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
- 1.f,
0.f,
- false,
+ 0.f,
+ true,
false
};
struct LineRun line09 =
{
{ 86u, 6u },
{ 86u, 6u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
{
{ 92u, 12u },
{ 92u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 123u, 5u },
{ 123u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 128u, 12u },
{ 128u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 140u, 10u },
{ 140u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 150u, 6u },
{ 150u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
{
{ 156u, 10u },
{ 156u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
0.f,
0.f,
- false,
+ true,
false
};
struct LineRun line17 =
{
{ 166u, 12u },
{ 166u, 12u },
- 79.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 178u, 14u },
{ 178u, 14u },
- 55.f,
+ 56.f,
15.f,
-4.f,
0.f,
Size layoutSize(92.f, 361.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 67.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f, 42.f, -12.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
};
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 12u, 10u },
{ 12u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 22u, 6u },
{ 22u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
4.f,
0.f,
0.f,
- false,
+ true,
false
};
struct LineRun line05 =
{
{ 48u, 11u },
{ 48u, 11u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 59u, 5u },
{ 59u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 64u, 10u },
{ 64u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
{
{ 74u, 12u },
{ 74u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 86u, 6u },
{ 86u, 6u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
{
{ 92u, 12u },
{ 92u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 123u, 5u },
{ 123u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 128u, 12u },
{ 128u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 140u, 10u },
{ 140u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 150u, 6u },
{ 150u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
{
{ 156u, 10u },
{ 156u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
{
{ 166u, 12u },
{ 166u, 12u },
- 79.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 178u, 14u },
{ 178u, 14u },
- 55.f,
+ 56.f,
15.f,
-4.f,
0.f,
Size layoutSize(92.f, 361.f);
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 67.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -2.f, 42.f, -12.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -2.f, 33.f, -12.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
- 1.f, -13.f, 9.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -2.f, 32.f, -12.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f,
+ 0.f, -13.f, 8.f, -9.f, 17.f, -13.f, 21.f, -13.f, 24.f, -9.f, 33.f, -0.f, 37.f, -9.f, 48.f, -9.f, 58.f, -9.f, 64.f, -13.f, 67.f, -13.f, 76.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
};
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 12u, 10u },
{ 12u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 22u, 6u },
{ 22u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
{
{ 48u, 11u },
{ 48u, 11u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 59u, 5u },
{ 59u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 64u, 10u },
{ 64u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
{
{ 74u, 12u },
{ 74u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 86u, 6u },
{ 86u, 6u },
- 43.f,
+ 42.f,
15.f,
-4.f,
0.f,
{
{ 92u, 12u },
{ 92u, 12u },
- 78.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 123u, 5u },
{ 123u, 5u },
- 31.f,
+ 29.f,
15.f,
-4.f,
0.f,
{
{ 128u, 12u },
{ 128u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
{
{ 140u, 10u },
{ 140u, 10u },
- 76.f,
+ 75.f,
15.f,
-4.f,
4.f,
{
{ 150u, 6u },
{ 150u, 6u },
- 34.f,
+ 32.f,
15.f,
-4.f,
0.f,
{
{ 156u, 10u },
{ 156u, 10u },
- 67.f,
+ 65.f,
15.f,
-4.f,
4.f,
{
{ 166u, 12u },
{ 166u, 12u },
- 79.f,
+ 76.f,
15.f,
-4.f,
4.f,
{
{ 178u, 14u },
{ 178u, 14u },
- 55.f,
+ 56.f,
15.f,
-4.f,
0.f,
struct LineRun line01 =
{
- { 0u, 13u },
- { 0u, 13u },
- 93.f,
+ { 0u, 14u },
+ { 0u, 14u },
+ 99.f,
15.f,
-4.f,
0.f,
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f, 83.f, -13.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f, 82.f, -13.f,
};
Size textArea( 100.f, 50.f );
{
{ 0u, 12u },
{ 0u, 12u },
- 80.f,
+ 78.f,
15.f,
-4.f,
4.f,
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f, 78.f, -0.f,
0.f, -13.f, 9.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -13.f, 52.f, -9.f, 61.f, -13.f, 65.f, -13.f, 68.f, -9.f, 77.f, -0.f, 81.f, -9.f,
};
struct LineRun line01 =
{
- { 0u, 16u },
- { 0u, 16u },
- 95.f,
+ { 0u, 17u },
+ { 0u, 17u },
+ 99.f,
15.f,
-4.f,
0.f,
float positions[] =
{
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
};
Size textArea( 100.f, 50.f );
{
{ 0u, 16u },
{ 0u, 16u },
- 96.f,
+ 94.f,
15.f,
-4.f,
3.f,
float positions[] =
{
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 9.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f, 32.f, -10.f, 43.f, -13.f, 50.f, -10.f, 55.f, -10.f, 63.f, -0.f, 68.f, -10.f, 76.f, -10.f, 81.f, -13.f, 89.f, -10.f, 97.f, -0.f,
};
{
{ 0u, 11u },
{ 0u, 11u },
- 80.f,
+ 78.f,
15.f,
-4.f,
0.f,
float positions[] =
{
- 1.f, -12.f
+ 0.f, -12.f
};
Size textArea( 100.f, 19.f );
- Size layoutSize( 80.f, 19.f );
+ Size layoutSize( 78.f, 19.f );
LayoutTextData data =
{
float positions[] =
{
- 1.f, -12.f, 11.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f,
+ 0.f, -12.f, 10.f, -9.f, 19.f, -13.f, 23.f, -13.f, 26.f, -9.f, 35.f, -0.f, 39.f, -9.f, 50.f, -9.f, 60.f, -9.f, 66.f, -13.f, 69.f, -13.f,
};
Size textArea( 100.f, 300.f );
87.f, -10.f, 79.f, -13.f, 74.f, -10.f, 66.f, -10.f, 61.f, -0.f, 53.f, -10.f, 48.f, -10.f, 41.f, -13.f, 32.f, -10.f, 27.f, -0.f, 20.f, -8.f, 15.f, -6.f, 8.f, -8.f, 5.f, -7.f, 4.f, -11.f, 0.f, -0.f,
23.f, -7.f, 22.f, -11.f, 17.f, -11.f, 11.f, -8.f, 10.f, -11.f, 5.f, -11.f, 0.f, -8.f, 0.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 9.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 30.f, -2.f,
};
float positions[] =
{
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 9.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f,
86.f, -8.f, 81.f, -6.f, 74.f, -8.f, 71.f, -7.f, 70.f, -11.f, 66.f, -0.f, 62.f, -7.f, 61.f, -11.f, 56.f, -11.f, 50.f, -8.f, 49.f, -11.f, 44.f, -11.f, 39.f, -8.f, 36.f, -0.f, 26.f, -10.f, 18.f, -13.f, 13.f, -10.f, 5.f, -10.f, 0.f, -0.f,
22.f, -10.f, 17.f, -10.f, 10.f, -13.f, 1.f, -10.f, 0.f, -0.f,
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 9.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 30.f, -2.f,
};
float positions[] =
{
- 1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -8.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+ 0.f, -10.f, 11.f, -13.f, 18.f, -10.f, 23.f, -10.f, 31.f, -0.f, 36.f, -10.f, 44.f, -10.f, 49.f, -13.f, 57.f, -10.f, 65.f, -0.f, 68.f, -8.f, 75.f, -6.f, 80.f, -8.f, 86.f, -7.f, 91.f, -11.f, 93.f, -0.f,
0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 9.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f,
0.f, -8.f, 7.f, -6.f, 12.f, -8.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 36.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
- 1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+ 0.f, -10.f, 8.f, -10.f, 13.f, -13.f, 21.f, -10.f, 29.f, -0.f,
87.f, -10.f, 79.f, -13.f, 74.f, -10.f, 66.f, -10.f, 61.f, -0.f, 53.f, -10.f, 48.f, -10.f, 41.f, -13.f, 32.f, -10.f, 27.f, -0.f, 20.f, -8.f, 15.f, -6.f, 8.f, -8.f, 5.f, -7.f, 4.f, -11.f, 0.f, -0.f,
- 28.f, -7.f, 27.f, -11.f, 22.f, -11.f, 16.f, -8.f, 15.f, -11.f, 10.f, -11.f, 5.f, -8.f, 2.f, -2.f,
+ 26.f, -7.f, 25.f, -11.f, 20.f, -11.f, 14.f, -8.f, 13.f, -11.f, 8.f, -11.f, 3.f, -8.f, 0.f, -2.f,
};
Size textArea( 100.f, 300.f );
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 0.f, 0.f, 2.f, 60.f, 0.f, 0.f };
+ float positions[] = { 0.f, 0.f, 2.f, 61.f, 0.f, 0.f };
Size textArea( 100.f, 300.f );
AlignData data =
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 10.f, 16.f, 0.f, 0.f, 0.f, 0.f };
+ float positions[] = { 11.f, 17.f, 0.f, 0.f, 0.f, 0.f };
Size textArea( 100.f, 300.f );
AlignData data =
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 0.f, 0.f, 0.f, 0.f, 10.f, 20.f };
+ float positions[] = { 0.f, 0.f, 0.f, 0.f, 11.f, 21.f };
Size textArea( 100.f, 300.f );
AlignData data =
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 20.f, 33.f, 0.f, 0.f, 0.f, 0.f };
+ float positions[] = { 22.f, 35.f, 0.f, 0.f, 0.f, 0.f };
Size textArea( 100.f, 300.f );
AlignData data =
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 0.f, 0.f, 0.f, 0.f, 20.f, 40.f };
+ float positions[] = { 0.f, 0.f, 0.f, 0.f, 22.f, 42.f };
Size textArea( 100.f, 300.f );
AlignData data =
fontDescriptionRuns.PushBack( fontDescriptionRun05 );
fontDescriptionRuns.PushBack( fontDescriptionRun06 );
- float positions[] = { 20.f, 33.f, 2.f, 0.f, 0.f, 0.f };
+ float positions[] = { 22.f, 35.f, 2.f, 0.f, 0.f, 0.f };
Size textArea( 100.f, 300.f );
AlignData data =
namespace
{
+
///////////////////////////////////////////////////////////
struct TokenComparisonData
Vector<ColorRun> colorRuns;
Vector<FontDescriptionRun> fontRuns;
- MarkupProcessData markupProcessData( colorRuns, fontRuns );
+ Vector<EmbeddedItem> items;
+ MarkupProcessData markupProcessData( colorRuns, fontRuns, items );
ProcessMarkupString( data.xHTMLEntityString, markupProcessData );
+ for( Vector<EmbeddedItem>::Iterator it = items.Begin(),
+ endIt = items.End();
+ it != endIt;
+ ++it )
+ {
+ EmbeddedItem& item = *it;
+ delete[] item.url;
+ }
+ items.Clear();
+
if( markupProcessData.markupProcessedText != data.expectedString )
{
std::cout << " different output string : " << markupProcessData.markupProcessedText << ", expected : " << data.expectedString << " " << std::endl;
float yBearing; ///< The distance from the baseline to the topmost border of the glyph
float advance; ///< The distance to move the cursor for this glyph
float scaleFactor; ///< The scaling applied (fixed-size fonts only)
- bool softwareItalic; ///< Whether glyph needs software support to draw italic style
- bool softwareBold; ///< Whether glyph needs software support to draw bold style
+ bool isItalicRequired; ///< Whether the italic style is required.
+ bool isBoldRequired; ///< Whether the bold style is required.
};
bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
{
return false;
}
- if( glyphData.softwareItalic != glyph.softwareItalic )
+ if( glyphData.isItalicRequired != glyph.isItalicRequired )
{
return false;
}
- if( glyphData.softwareBold != glyph.softwareBold )
+ if( glyphData.isBoldRequired != glyph.isBoldRequired )
{
return false;
}
struct GlyphInfoData glyphs01[] =
{
- { 2u, 4857u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, false },
- { 2u, 7316u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, false },
- { 2u, 4364u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, false },
+ { 2u, 21154u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, true, true },
+ { 2u, 12298u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, true, true },
+ { 2u, 17828u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, true, true },
};
struct GlyphInfoData glyphs02[] =
{
- { 2u, 4857u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, false, false },
- { 2u, 7316u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, false, false },
- { 2u, 4364u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, false },
+ { 2u, 21154u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, false, false },
+ { 2u, 12298u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, false, true },
+ { 2u, 17828u, 0.f, 0.f, 0.f, 0.f, 16.f, 0.f, true, false },
};
CharacterIndex characterIndices[] = { 0u, 1u, 2u };
const Length LOREM_NUMBER_OF_GLYPHS_ELIDED = 395u;
// The expected layout size for UtcDaliTextViewModelGetLayoutSize
-const Size LAYOUT_SIZE( 197.f, 45.f );
+const Size LAYOUT_SIZE( 194.f, 45.f );
// The expected color indices for UtcDaliTextViewModelGetColors
const ColorIndex COLOR_INDICES[] = { 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 2u, 2u, 2u, 2u, 2u, 1u, 1u, 1u, 1u, 1u, 3u, 1u, 1u, 1u, 0u, 0u, 0u, 0u };
float positions01[] = { 0.f, 8.f, 16.f, 26.f, 33.f, 41.f, 45.f, 54.f, 64.0f };
Size textSize02( 80.f, 100.f );
- float positions02[] = { 72.f, 63.f, 54.f, 50.f, 43.f, 38.f, 30.f, 9.0f };
+ float positions02[] = { 75.f, 66.f, 57.f, 53.f, 46.f, 41.f, 33.f, 26.0f };
Size textSize03( 80.f, 100.f );
- float positions03[] = { 78.f, 73.f, 70.f, 65.f, 57.f, 55.f, 51.f, 50.f, 45.f, 35.f, 32.f, 24.f, 7.f };
+ float positions03[] = { 79.f, 74.f, 71.f, 66.f, 58.f, 56.f, 52.f, 51.f, 46.f, 36.f, 33.f, 25.f, 22.f };
Size textSize04( 80.f, 10.f );
float positions04[] = { 2.f };
../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-render-controller.cpp
+ ../dali-toolkit/dali-toolkit-test-utils/test-render-surface.cpp
../dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
../dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
)
../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp
../dali-toolkit/dali-toolkit-test-utils/test-render-controller.cpp
+ ../dali-toolkit/dali-toolkit-test-utils/test-render-surface.cpp
../dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
../dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
)
dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
dali-toolkit-test-utils/test-platform-abstraction.cpp
dali-toolkit-test-utils/test-render-controller.cpp
+ dali-toolkit-test-utils/test-render-surface.cpp
dali-toolkit-test-utils/test-trace-call-stack.cpp
dali-toolkit-test-utils/test-native-image.cpp
)
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Integration::StencilBufferAvailable::TRUE );
mCore->ContextCreated();
- mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
- mCore->SetDpi( mDpi.x, mDpi.y );
Dali::Integration::Log::LogFunction logFunction(&TestApplication::LogMessage);
Dali::Integration::Log::InstallLogFunction(logFunction);
Dali::Integration::Trace::LogContext( true, "Test" );
+ mRenderSurface = new TestRenderSurface( Dali::PositionSize( 0, 0, mSurfaceWidth, mSurfaceHeight ) );
+ mScene = Dali::Integration::Scene::New( Vector2( static_cast<float>( mSurfaceWidth ), static_cast<float>( mSurfaceHeight ) ) );
+ mScene.SetSurface( *mRenderSurface );
+
+ mScene.SetDpi( Vector2( static_cast<float>( mDpi.x ), static_cast<float>( mDpi.y ) ) );
+
+ mCore->SurfaceResized( mRenderSurface );
+
mCore->SceneCreated();
+ mCore->Initialize();
}
TestApplication::~TestApplication()
{
Dali::Integration::Log::UninstallLogFunction();
+ delete mRenderSurface;
delete mCore;
}
mCore->ProcessEvents();
}
-void TestApplication::SetSurfaceWidth( uint32_t width, uint32_t height )
-{
- mSurfaceWidth = width;
- mSurfaceHeight = height;
-
- mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
-}
-
-void TestApplication::SetTopMargin( uint32_t margin )
-{
- mCore->SetTopMargin( margin );
-}
-
void TestApplication::DoUpdate( uint32_t intervalMilliseconds, const char* location )
{
if( GetUpdateStatus() == 0 &&
#define __DALI_TEST_APPLICATION_H__
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "test-gl-sync-abstraction.h"
#include "test-gl-abstraction.h"
#include "test-render-controller.h"
+#include "test-render-surface.h"
#include <dali/public-api/common/dali-common.h>
#include <dali/integration-api/resource-policies.h>
#include <dali/integration-api/trace.h>
+#include <dali/integration-api/scene.h>
namespace Dali
{
TestGestureManager& GetGestureManager();
void ProcessEvent(const Integration::Event& event);
void SendNotification();
- void SetSurfaceWidth( uint32_t width, unsigned height );
- void SetTopMargin( uint32_t margin );
bool Render( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location=NULL );
uint32_t GetUpdateStatus();
bool UpdateOnly( uint32_t intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
mLoggingEnabled = enabled;
}
+ Integration::Scene GetScene() const
+ {
+ return mScene;
+ }
+
private:
void DoUpdate( uint32_t intervalMilliseconds, const char* location=NULL );
TestGlAbstraction mGlAbstraction;
TestGlSyncAbstraction mGlSyncAbstraction;
TestGestureManager mGestureManager;
+ TestRenderSurface* mRenderSurface;
Integration::UpdateStatus mStatus;
Integration::RenderStatus mRenderStatus;
Integration::Core* mCore;
+ Dali::Integration::Scene mScene;
uint32_t mSurfaceWidth;
uint32_t mSurfaceHeight;
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-render-surface.h"
+
+namespace Dali
+{
+
+TestRenderSurface::TestRenderSurface( Dali::PositionSize positionSize )
+: mPositionSize( positionSize ),
+ mBackgroundColor()
+{
+}
+
+TestRenderSurface::~TestRenderSurface()
+{
+}
+
+Dali::PositionSize TestRenderSurface::GetPositionSize() const
+{
+ return mPositionSize;
+};
+
+void TestRenderSurface::GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical )
+{
+ dpiHorizontal = dpiVertical = 96;
+};
+
+void TestRenderSurface::InitializeGraphics()
+{
+}
+
+void TestRenderSurface::CreateSurface()
+{
+}
+
+void TestRenderSurface::DestroySurface()
+{
+}
+
+bool TestRenderSurface::ReplaceGraphicsSurface()
+{
+ return false;
+}
+
+void TestRenderSurface::MoveResize( Dali::PositionSize positionSize )
+{
+ mPositionSize = positionSize;
+}
+
+void TestRenderSurface::StartRender()
+{
+}
+
+bool TestRenderSurface::PreRender( bool resizingSurface )
+{
+ return true;
+}
+
+void TestRenderSurface::PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface )
+{
+}
+
+void TestRenderSurface::StopRender()
+{
+}
+
+void TestRenderSurface::ReleaseLock()
+{
+}
+
+Dali::Integration::RenderSurface::Type TestRenderSurface::GetSurfaceType()
+{
+ return WINDOW_RENDER_SURFACE;
+}
+
+void TestRenderSurface::MakeContextCurrent()
+{
+}
+
+Integration::DepthBufferAvailable TestRenderSurface::GetDepthBufferRequired()
+{
+ return Integration::DepthBufferAvailable::TRUE;
+}
+
+Integration::StencilBufferAvailable TestRenderSurface::GetStencilBufferRequired()
+{
+ return Integration::StencilBufferAvailable::TRUE;
+}
+
+void TestRenderSurface::SetBackgroundColor( Vector4 color )
+{
+ mBackgroundColor = color;
+}
+
+Vector4 TestRenderSurface::GetBackgroundColor()
+{
+ return mBackgroundColor;
+}
+
+} // Namespace dali
--- /dev/null
+#ifndef TEST_REENDER_SURFACE_H
+#define TEST_REENDER_SURFACE_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/render-surface.h>
+
+namespace Dali
+{
+
+/**
+ * Concrete implementation of the RenderSurface class.
+ */
+class DALI_CORE_API TestRenderSurface : public Dali::Integration::RenderSurface
+{
+public:
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::RenderSurface
+ */
+ TestRenderSurface( Dali::PositionSize positionSize );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::~RenderSurface
+ */
+ virtual ~TestRenderSurface();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetPositionSize
+ */
+ virtual Dali::PositionSize GetPositionSize() const;
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetDpi
+ */
+ virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::InitializeGraphics
+ */
+ virtual void InitializeGraphics();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::CreateSurface
+ */
+ virtual void CreateSurface();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::DestroySurface
+ */
+ virtual void DestroySurface();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::ReplaceGraphicsSurface
+ */
+ virtual bool ReplaceGraphicsSurface();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::MoveResize
+ */
+ virtual void MoveResize( Dali::PositionSize positionSize );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::StartRender
+ */
+ virtual void StartRender();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::PreRender
+ */
+ virtual bool PreRender( bool resizingSurface );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::PostRender
+ */
+ virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::StopRender
+ */
+ virtual void StopRender();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::ReleaseLock
+ */
+ virtual void ReleaseLock();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetSurfaceType
+ */
+ virtual Dali::Integration::RenderSurface::Type GetSurfaceType();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::MakeContextCurrent
+ */
+ virtual void MakeContextCurrent();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetDepthBufferRequired
+ */
+ virtual Integration::DepthBufferAvailable GetDepthBufferRequired();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetStencilBufferRequired
+ */
+ virtual Integration::StencilBufferAvailable GetStencilBufferRequired();
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::SetBackgroundColor
+ */
+ virtual void SetBackgroundColor( Vector4 color );
+
+ /**
+ * @copydoc Dali::Integration::RenderSurface::GetBackgroundColor
+ */
+ virtual Vector4 GetBackgroundColor();
+
+private:
+
+ /**
+ * @brief Undefined copy constructor. RenderSurface cannot be copied
+ */
+ TestRenderSurface( const TestRenderSurface& rhs );
+
+ /**
+ * @brief Undefined assignment operator. RenderSurface cannot be copied
+ */
+ TestRenderSurface& operator=( const TestRenderSurface& rhs );
+
+private:
+
+ Dali::PositionSize mPositionSize;
+ Vector4 mBackgroundColor; ///< The background color of the surface
+};
+
+} // Dali
+
+#endif
bool HandleActionReadFromTopEvent();
bool HandleActionReadFromNextEvent();
bool HandleActionZoomEvent();
- bool HandleActionReadIndicatorInformationEvent();
bool HandleActionReadPauseResumeEvent();
bool HandleActionStartStopEvent();
return false;
}
-bool AccessibilityAdaptor::HandleActionReadIndicatorInformationEvent()
-{
- if( mActionHandler )
- {
- return mActionHandler->AccessibilityActionReadIndicatorInformation();
- }
- return false;
-}
-
bool AccessibilityAdaptor::HandleActionReadPauseResumeEvent()
{
if( mActionHandler )
return Internal::Adaptor::GetImplementation(*this).HandleActionZoomEvent();
}
-bool AccessibilityAdaptor::HandleActionReadIndicatorInformationEvent()
-{
- return Internal::Adaptor::GetImplementation(*this).HandleActionReadIndicatorInformationEvent();
-}
-
bool AccessibilityAdaptor::HandleActionReadPauseResumeEvent()
{
return Internal::Adaptor::GetImplementation(*this).HandleActionReadPauseResumeEvent();
*
*/
-#include <dali/integration-api/adaptors/render-surface.h>
+#include <dali/integration-api/adaptors/render-surface-interface.h>
namespace Dali
{
} // namespace Integration
-class TestRenderSurface : public RenderSurface
-{
-public:
- virtual PositionSize GetPositionSize() const { PositionSize size; return size; }
-
- virtual void GetDpi( unsigned int& dpiHorizontal, unsigned int& dpiVertical ) { dpiHorizontal = dpiVertical = 96; }
-
- virtual void InitializeGraphics( Dali::Internal::Adaptor::GraphicsInterface& graphics, Dali::DisplayConnection& displayConnection ) {};
-
- virtual void CreateSurface() {}
-
- virtual void DestroySurface() {}
-
- virtual bool ReplaceGraphicsSurface() { return false; }
-
- virtual void MoveResize( Dali::PositionSize positionSize ) {}
-
- virtual void SetViewMode( ViewMode viewMode ) {}
-
- virtual void StartRender() {}
-
- virtual bool PreRender( bool resizingSurface ) { return false; }
-
- virtual void PostRender( bool renderToFbo, bool replacingSurface, bool resizingSurface ) {}
-
- virtual void StopRender() {}
-
- virtual void ReleaseLock() {}
-
- virtual void SetThreadSynchronization( ThreadSynchronizationInterface& threadSynchronization ) {}
-
- virtual RenderSurface::Type GetSurfaceType() { return RenderSurface::WINDOW_RENDER_SURFACE; }
-};
-
namespace Internal
{
namespace Adaptor
~Adaptor();
public:
- static Dali::RenderSurface& GetSurface();
+ static Dali::RenderSurfaceInterface& GetSurface();
static Dali::Adaptor::AdaptorSignalType& AdaptorSignal();
static bool mAvailable;
static Vector<CallbackBase*> mCallbacks;
#include <toolkit-adaptor-impl.h>
#include <dali/integration-api/debug.h>
#include <test-application.h>
+#include <test-render-surface.h>
namespace Dali
{
return *adaptor;
}
-Dali::RenderSurface& Adaptor::GetSurface()
+Dali::RenderSurfaceInterface& Adaptor::GetSurface()
{
- Dali::RenderSurface *renderSurface = new Dali::TestRenderSurface;
+ Dali::RenderSurfaceInterface* renderSurface = reinterpret_cast <Dali::RenderSurfaceInterface*>( new Dali::TestRenderSurface( Dali::PositionSize( 0, 0, 480, 800 ) ) );
return *renderSurface;
}
return Internal::Adaptor::Adaptor::Get();
}
-Adaptor& Adaptor::New( Any nativeWindow, const Dali::RenderSurface& surface )
+Adaptor& Adaptor::New( Window window, const Dali::RenderSurfaceInterface& surface )
{
return Internal::Adaptor::Adaptor::Get();
}
-Adaptor& Adaptor::New( Any nativeWindow, const Dali::RenderSurface& surface, Configuration::ContextLoss configuration )
+Adaptor& Adaptor::New( Window window, const Dali::RenderSurfaceInterface& surface, Configuration::ContextLoss configuration )
{
return Internal::Adaptor::Adaptor::Get();
}
}
}
-void Adaptor::ReplaceSurface( Any nativeWindow, Dali::RenderSurface& surface )
+void Adaptor::ReplaceSurface( Window window, Dali::RenderSurfaceInterface& surface )
{
}
return Internal::Adaptor::Adaptor::AdaptorSignal();
}
-RenderSurface& Adaptor::GetSurface()
+Dali::RenderSurfaceInterface& Adaptor::GetSurface()
{
return Internal::Adaptor::Adaptor::GetSurface();
}
{
}
- uint32_t GetTotalFrameNumber()
+ uint32_t GetTotalFrameNumber() const
{
return 5;
}
+ float GetFrameRate() const
+ {
+ return 60.0f;
+ }
+
public:
std::string mUrl;
Internal::Adaptor::GetImplementation( *this ).Render( frameNumber );
}
-uint32_t VectorAnimationRenderer::GetTotalFrameNumber()
+uint32_t VectorAnimationRenderer::GetTotalFrameNumber() const
{
return Internal::Adaptor::GetImplementation( *this ).GetTotalFrameNumber();
}
+float VectorAnimationRenderer::GetFrameRate() const
+{
+ return Internal::Adaptor::GetImplementation( *this ).GetFrameRate();
+}
+
} // namespace Dali;
END_TEST;
}
-
int UtcDaliLayouting_AbsoluteLayout01(void)
{
ToolkitTestApplication application;
END_TEST;
}
+
+int UtcDaliLayouting_AbsoluteLayout_SetPosition(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliLayouting_AbsoluteLayout_GetWorldPosition - Testing WorldPosition");
+
+ Stage stage = Stage::GetCurrent();
+
+ Dali::Toolkit::Control layoutControl = Dali::Toolkit::Control::New();
+ layoutControl.SetName("AsoluteLayout");
+ layoutControl.SetAnchorPoint( Dali::AnchorPoint::CENTER );
+ layoutControl.SetParentOrigin( Dali::ParentOrigin::CENTER );
+
+ Dali::Toolkit::AbsoluteLayout absoluteLayout = Dali::Toolkit::AbsoluteLayout::New();
+ Dali::Toolkit::DevelControl::SetLayout( layoutControl, absoluteLayout );
+
+ stage.GetRootLayer().Add( layoutControl );
+
+ // Ensure layouting happens
+ application.SendNotification();
+ application.Render(0);
+
+ Dali::Toolkit::Control control = Dali::Toolkit::Control::New();
+ control.SetSize( 100.0f, 100.0f );
+ control.SetParentOrigin( ParentOrigin::CENTER );
+ control.SetAnchorPoint( AnchorPoint::CENTER );
+ Vector3 parentPosition( 1.0f, 2.0f, 3.0f );
+ control.SetPosition( parentPosition );
+
+ layoutControl.Add( control );
+
+ // Ensure layouting happens
+ application.SendNotification();
+ application.Render(0);
+
+ // The value of z should not be zero
+ DALI_TEST_EQUALS( control.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+
+ END_TEST;
+}
END_TEST;
}
-int UtcDaliAccessibilityManagerActionReadIndicatorInformationSignalP(void)
-{
- ToolkitTestApplication application;
- tet_infoline( " UtcDaliAccessibilityManagerActionReadIndicatorInformationSignalP" );
-
- AccessibilityManagerSignalHandler callback;
-
- Dali::AccessibilityAdaptor accAdaptor = Dali::AccessibilityAdaptor::Get();
- Test::AccessibilityAdaptor::SetEnabled( accAdaptor, true );
- accAdaptor.HandleActionEnableEvent();
-
- AccessibilityManager manager = AccessibilityManager::Get();
- DALI_TEST_CHECK( manager );
-
- manager.ActionReadIndicatorInformationSignal().Connect( &callback, &AccessibilityManagerSignalHandler::Callback );
-
- Dali::AccessibilityAdaptor accessibilityAdaptor = Dali::AccessibilityAdaptor::Get();
- accessibilityAdaptor.HandleActionReadIndicatorInformationEvent();
-
- DALI_TEST_EQUALS( callback.GetCalls(), 1u, TEST_LOCATION );
-
- END_TEST;
-}
-
int UtcDaliAccessibilityManagerActionReadIndicatorInformationSignalN(void)
{
ToolkitTestApplication application;
#include <iostream>
#include <stdlib.h>
+#include <chrono>
+#include <thread>
#include <dali-toolkit-test-suite-utils.h>
#include <toolkit-timer.h>
#include <toolkit-event-thread-callback.h>
application.SendNotification();
application.Render( 16 );
+ std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); // wait for one animation loop (16fps, 5frames, need 80ms)
+
DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
Property::Map map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
application.SendNotification();
application.Render(16);
+ std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); // wait for next rasterize thread run
+
map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
value = map.Find( DevelImageVisual::Property::PLAY_STATE );
DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PAUSED ) );
ToolkitTestApplication application;
tet_infoline( "UtcDaliAnimatedVectorImageVisualJumpToCurrentProgress" );
- Vector2 playRange( 0.2f, 0.8f );
+ Vector2 playRange( 0.2f, 0.5f );
Property::Map propertyMap;
propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE )
value = map.Find( DevelImageVisual::Property::PLAY_RANGE );
DALI_TEST_EQUALS( value->Get< Vector2 >(), playRange, TEST_LOCATION );
- Vector2 newPlayRange( 0.4f, 1.0f );
+ Vector2 newPlayRange( 0.6f, 1.0f );
Property::Map attributes;
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, newPlayRange );
value = map.Find( DevelImageVisual::Property::PLAY_RANGE );
DALI_TEST_EQUALS( value->Get< Vector2 >(), newPlayRange, TEST_LOCATION );
+ attributes.Clear();
+ attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange );
+
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+
+ application.SendNotification();
+ application.Render();
+
+ map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL );
+ value = map.Find( DevelImageVisual::Property::PLAY_RANGE );
+ DALI_TEST_EQUALS( value->Get< Vector2 >(), playRange, TEST_LOCATION );
+
END_TEST;
}
namespace
{
bool gOnRelayout = false;
+
+static bool gKeyInputFocusCallBackCalled;
+
+static void TestKeyInputFocusCallback( Control control )
+{
+ tet_infoline(" TestKeyInputFocusCallback");
+
+ gKeyInputFocusCallBackCalled = true;
+}
} // namespace
///////////////////////////////////////////////////////////////////////////////////////////////////
END_TEST;
}
+
+int UtcDaliControlWrapperEmitKeyFocusSignal(void)
+{
+ ToolkitTestApplication application;
+
+ Impl::TestCustomControl* controlWrapperImpl = new ::Impl::TestCustomControl( Toolkit::Internal::ControlWrapper::CONTROL_BEHAVIOUR_DEFAULT );
+ ControlWrapper controlWrapper = ControlWrapper::New( customControlTypeName, *controlWrapperImpl );
+
+ gKeyInputFocusCallBackCalled = false;
+ controlWrapper.KeyInputFocusGainedSignal().Connect(&TestKeyInputFocusCallback);
+
+ application.SendNotification();
+ application.Render();
+
+ controlWrapperImpl->EmitKeyInputFocusSignal( true );
+
+ DALI_TEST_CHECK( gKeyInputFocusCallBackCalled );
+
+ END_TEST;
+}
\ No newline at end of file
application.Render();
DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 54.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 52.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
// Test flexbox2 is sized to wrap its content
DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
application.Render();
DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 216.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 214.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
test_return_value = TET_PASS;
}
+int UtcDaliLayouting_GridLayout00(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliLayouting_GridLayout00 1 Column, 0 Items");
+
+ const auto NUMBER_OF_COLUMNS = 1;
+ const auto NUMBER_OF_ITEMS = 0;
+
+ tet_printf( "Testing %d columns with %d items\n", NUMBER_OF_COLUMNS, NUMBER_OF_ITEMS );
+
+ Stage stage = Stage::GetCurrent();
+
+ auto rootControl = Control::New();
+ auto absoluteLayout = AbsoluteLayout::New();
+ DevelControl::SetLayout( rootControl, absoluteLayout );
+ rootControl.SetName( "AbsoluteLayout" );
+ stage.Add( rootControl );
+
+ auto gridContainer = Control::New();
+ auto gridLayout = Grid::New();
+ gridLayout.SetNumberOfColumns( NUMBER_OF_COLUMNS );
+ gridContainer.SetName( "GridLayout");
+ DevelControl::SetLayout( gridContainer, gridLayout );
+ gridContainer.SetProperty( LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+ gridContainer.SetProperty( LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+
+ rootControl.Add( gridContainer );
+
+ // Ensure layouting happens
+ application.SendNotification();
+ application.Render();
+
+ tet_printf( "Confirm number of columns is as set\n");
+ DALI_TEST_EQUALS( gridLayout.GetNumberOfColumns(), NUMBER_OF_COLUMNS, TEST_LOCATION );
+
+ END_TEST;
+}
+
int UtcDaliLayouting_GridLayout01(void)
{
ToolkitTestApplication application;
DALI_TEST_CHECK( gridLayoutCandidate );
END_TEST;
-}
\ No newline at end of file
+}
#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <test-native-image.h>
Property::Value value = renderer.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
bool enable;
DALI_TEST_CHECK( value.Get( enable ) );
- DALI_TEST_CHECK( !enable );
+ DALI_TEST_CHECK( enable );
// pre-multiplied alpha blending
imageView.SetProperty( Toolkit::ImageView::Property::PRE_MULTIPLIED_ALPHA, true );
END_TEST;
}
+int UtcDaliImageViewPreMultipliedAlphaPng(void)
+{
+ ToolkitTestApplication application;
+
+ // Set up trace debug
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable( true );
+
+ Property::Map imageMap;
+ imageMap[ ImageVisual::Property::URL ] = gImage_34_RGBA;
+ imageMap[ ImageVisual::Property::RELEASE_POLICY] = ImageVisual::ReleasePolicy::NEVER; // To keep the texture cache
+
+ ImageView imageView1 = ImageView::New();
+ imageView1.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+ Stage::GetCurrent().Add( imageView1 );
+
+ Property::Value value = imageView1.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ bool enable;
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( enable ); // Default value is true
+
+ // loading started, this waits for the loader thread for max 30 seconds
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView1.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( enable ); // Keep true
+
+ // conventional alpha blending
+ Renderer renderer1 = imageView1.GetRendererAt( 0 );
+ value = renderer1.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( enable );
+
+ int srcFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_RGB );
+ int destFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_RGB );
+ int srcFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_ALPHA );
+ int destFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_ALPHA );
+ DALI_TEST_CHECK( srcFactorRgb == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorRgb == BlendFactor::ONE_MINUS_SRC_ALPHA );
+ DALI_TEST_CHECK( srcFactorAlpha == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorAlpha == BlendFactor::ONE_MINUS_SRC_ALPHA );
+
+ DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); // A new texture should be generated.
+ textureTrace.Reset();
+
+ // Disable pre-multiplied alpha blending
+ imageView1.SetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA, false );
+
+ // Reload the image
+ Property::Map attributes;
+ DevelControl::DoAction( imageView1, ImageView::Property::IMAGE, DevelImageVisual::Action::RELOAD, attributes );
+
+ // loading started, this waits for the loader thread for max 30 seconds
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView1.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable );
+
+ // conventional alpha blending
+ value = renderer1.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable );
+
+ srcFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_RGB );
+ destFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_RGB );
+ srcFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_ALPHA );
+ destFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_ALPHA );
+ DALI_TEST_CHECK( srcFactorRgb == BlendFactor::SRC_ALPHA );
+ DALI_TEST_CHECK( destFactorRgb == BlendFactor::ONE_MINUS_SRC_ALPHA );
+ DALI_TEST_CHECK( srcFactorAlpha == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorAlpha == BlendFactor::ONE_MINUS_SRC_ALPHA );
+
+ DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); // A new texture should be generated.
+ textureTrace.Reset();
+
+ // Make a new ImageView using the same image
+ ImageView imageView2 = ImageView::New();
+ imageView2.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+ Stage::GetCurrent().Add( imageView2 );
+
+ application.SendNotification();
+ application.Render();
+
+ Renderer renderer2 = imageView2.GetRendererAt( 0 );
+ value = renderer2.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( enable );
+
+ srcFactorRgb = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_RGB );
+ destFactorRgb = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_RGB );
+ srcFactorAlpha = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_ALPHA );
+ destFactorAlpha = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_ALPHA );
+ DALI_TEST_CHECK( srcFactorRgb == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorRgb == BlendFactor::ONE_MINUS_SRC_ALPHA );
+ DALI_TEST_CHECK( srcFactorAlpha == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorAlpha == BlendFactor::ONE_MINUS_SRC_ALPHA );
+
+ DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); // The cached texture should be used.
+
+ END_TEST;
+}
+
+int UtcDaliImageViewPreMultipliedAlphaJpg(void)
+{
+ ToolkitTestApplication application;
+
+ // Set up trace debug
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable( true );
+
+ Property::Map imageMap;
+ imageMap[ ImageVisual::Property::URL ] = gImage_600_RGB;
+ imageMap[ ImageVisual::Property::RELEASE_POLICY] = ImageVisual::ReleasePolicy::NEVER; // To keep the texture cache
+
+ ImageView imageView1 = ImageView::New();
+ imageView1.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+ Stage::GetCurrent().Add( imageView1 );
+
+ Property::Value value = imageView1.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ bool enable;
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( enable ); // Default value is true
+
+ // loading started, this waits for the loader thread for max 30 seconds
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView1.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable ); // Should be false after loading
+
+ // conventional alpha blending
+ Renderer renderer1 = imageView1.GetRendererAt( 0 );
+ value = renderer1.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable );
+
+ int srcFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_RGB );
+ int destFactorRgb = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_RGB );
+ int srcFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_ALPHA );
+ int destFactorAlpha = renderer1.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_ALPHA );
+ DALI_TEST_CHECK( srcFactorRgb == BlendFactor::SRC_ALPHA );
+ DALI_TEST_CHECK( destFactorRgb == BlendFactor::ONE_MINUS_SRC_ALPHA );
+ DALI_TEST_CHECK( srcFactorAlpha == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorAlpha == BlendFactor::ONE_MINUS_SRC_ALPHA );
+
+ DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), true, TEST_LOCATION ); // A new texture should be generated.
+ textureTrace.Reset();
+
+ ImageView imageView2 = ImageView::New();
+ imageView2.SetProperty( ImageView::Property::IMAGE, imageMap );
+
+ // Disable pre-multiplied alpha blending
+ imageView2.SetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA, false );
+
+ Stage::GetCurrent().Add( imageView2 );
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView2.GetProperty( ImageView::Property::PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable );
+
+ // conventional alpha blending
+ Renderer renderer2 = imageView2.GetRendererAt( 0 );
+ value = renderer2.GetProperty( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_CHECK( value.Get( enable ) );
+ DALI_TEST_CHECK( !enable );
+
+ srcFactorRgb = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_RGB );
+ destFactorRgb = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_RGB );
+ srcFactorAlpha = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_SRC_ALPHA );
+ destFactorAlpha = renderer2.GetProperty<int>( Renderer::Property::BLEND_FACTOR_DEST_ALPHA );
+ DALI_TEST_CHECK( srcFactorRgb == BlendFactor::SRC_ALPHA );
+ DALI_TEST_CHECK( destFactorRgb == BlendFactor::ONE_MINUS_SRC_ALPHA );
+ DALI_TEST_CHECK( srcFactorAlpha == BlendFactor::ONE );
+ DALI_TEST_CHECK( destFactorAlpha == BlendFactor::ONE_MINUS_SRC_ALPHA );
+
+ DALI_TEST_EQUALS( textureTrace.FindMethod("GenTextures"), false, TEST_LOCATION ); // The cached texture should be used.
+
+ END_TEST;
+}
+
int UtcDaliImageViewPixelArea(void)
{
// Test pixel area property
application.Render();
DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 368.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 54.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 52.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
textLabel.SetProperty( TextLabel::Property::TEXT, "WWWW" );
application.Render();
DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 368.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 216.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 214.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
textLabel.SetProperty( TextLabel::Property::POINT_SIZE, 10.0f );
application.Render();
tet_infoline("Test text is it's natural size");
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 228.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
tet_infoline("Test control is width of it's parent and height of it's child");
DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 600.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
application.Render();
tet_infoline("Test text is it's natural size");
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 228.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
tet_infoline("Test text is centered in the control, the control is the size of the largest child");
DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
application.Render();
tet_infoline("Test text is it's natural size");
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 228.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
tet_infoline("Test control is size of it's child and control it's own padding");
- DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 245.0f, 86.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 243.0f, 86.0f, 0.0f ), 0.0001f, TEST_LOCATION );
END_TEST;
}
application.Render();
tet_infoline("Test text is it's natural size");
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 230.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 228.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
tet_infoline("Test control is width of it's parent and height of it's child");
- DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 255.0f, 91.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( control.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 253.0f, 91.0f, 0.0f ), 0.0001f, TEST_LOCATION );
END_TEST;
}
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 260.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 260.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 254.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 254.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
tet_infoline("Changing to longer text");
textLabel.SetProperty( TextLabel::Property::TEXT, "muchlongerText" );
application.SendNotification();
application.Render();
- DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 432.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
- DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 432.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 426.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 426.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
END_TEST;
-}
\ No newline at end of file
+}
int UtcDaliScrollViewPagePathEffectSetup(void)
{
+ ToolkitTestApplication application;
tet_infoline(" UtcDaliScrollViewPagePathEffectSetup");
ScrollViewPagePathEffect effect;
Property::Map underlineMapSet;
Property::Map underlineMapGet;
- underlineMapSet.Insert( "enable", "true" );
- underlineMapSet.Insert( "color", "red" );
- underlineMapSet.Insert( "height", "1" );
+ underlineMapSet.Insert( "enable", true );
+ underlineMapSet.Insert( "color", Color::RED );
+ underlineMapSet.Insert( "height", 1 );
editor.SetProperty( TextEditor::Property::UNDERLINE, underlineMapSet );
// Check the input underline property
Property::Map underlineMapSet;
Property::Map underlineMapGet;
- underlineMapSet.Insert( "enable", "true" );
- underlineMapSet.Insert( "color", "blue" );
- underlineMapSet.Insert( "height", "2" );
+ underlineMapSet.Insert( "enable", true );
+ underlineMapSet.Insert( "color", Color::BLUE );
+ underlineMapSet.Insert( "height", 2 );
editor.SetProperty( TextEditor::Property::UNDERLINE, underlineMapSet );
underlineMapGet = editor.GetProperty<Property::Map>( TextEditor::Property::UNDERLINE );
Property::Map underlineMapSet;
Property::Map underlineMapGet;
- underlineMapSet.Insert( "enable", "true" );
- underlineMapSet.Insert( "color", "red" );
- underlineMapSet.Insert( "height", "1" );
+ underlineMapSet.Insert( "enable", true );
+ underlineMapSet.Insert( "color", Color::RED );
+ underlineMapSet.Insert( "height", 1 );
// Check the underline property
field.SetProperty( TextField::Property::UNDERLINE, underlineMapSet );
// Move the cursor and check the position changes.
Vector3 position1 = cursor.GetCurrentPosition();
-
- application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
// Render and notify
application.Render();
Vector3 position2 = cursor.GetCurrentPosition();
-
DALI_TEST_CHECK( position2.x < position1.x );
application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
- application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
// Render and notify
application.SendNotification();
application.Render();
Vector3 position3 = cursor.GetCurrentPosition();
-
DALI_TEST_EQUALS( position1, position3, TEST_LOCATION ); // Should be in the same position1.
+
+ // Move the cursor to the first position.
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+ application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position4 = cursor.GetCurrentPosition();
+
// Send some taps and check the cursor positions.
// Try to tap at the beginning.
application.Render();
// Cursor position should be the same than position1.
- Vector3 position4 = cursor.GetCurrentPosition();
+ Vector3 position5 = cursor.GetCurrentPosition();
- DALI_TEST_EQUALS( position2, position4, TEST_LOCATION ); // Should be in the same position2.
+ DALI_TEST_EQUALS( position4, position5, TEST_LOCATION ); // Should be in the same position2.
// Tap away from the start position.
application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 16.f, 25.0f ) ) );
application.SendNotification();
application.Render();
- Vector3 position5 = cursor.GetCurrentPosition();
+ Vector3 position6 = cursor.GetCurrentPosition();
- DALI_TEST_CHECK( position5.x > position4.x );
+ DALI_TEST_CHECK( position6.x > position5.x );
// Remove all the text.
application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::Down, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
application.Render();
// Cursor position should be the same than position2.
- Vector3 position6 = cursor.GetCurrentPosition();
+ Vector3 position7 = cursor.GetCurrentPosition();
- DALI_TEST_EQUALS( position2, position6, TEST_LOCATION );// Should be in the same position2.
+ DALI_TEST_EQUALS( position4, position7, TEST_LOCATION );// Should be in the same position2.
// Should not be a renderer.
DALI_TEST_EQUALS( stencil.GetChildCount(), 0u, TEST_LOCATION );
Property::Map underlineMapSet;
Property::Map underlineMapGet;
- underlineMapSet.Insert( "enable", "false" );
- underlineMapSet.Insert( "color", "blue" );
- underlineMapSet.Insert( "height", "0" );
+ underlineMapSet.Insert( "enable", false );
+ underlineMapSet.Insert( "color", Color::BLUE );
+ underlineMapSet.Insert( "height", 0 );
underlineMapGet = label.GetProperty<Property::Map>( TextLabel::Property::UNDERLINE );
DALI_TEST_EQUALS( underlineMapGet.Count(), underlineMapSet.Count(), TEST_LOCATION );
// Check the underline property
underlineMapSet.Clear();
- underlineMapSet.Insert( "enable", "true" );
- underlineMapSet.Insert( "color", "red" );
- underlineMapSet.Insert( "height", "1" );
+ underlineMapSet.Insert( "enable", true );
+ underlineMapSet.Insert( "color", Color::RED );
+ underlineMapSet.Insert( "height", 1 );
label.SetProperty( TextLabel::Property::UNDERLINE, underlineMapSet );
DALI_TEST_EQUALS( DaliTestCheckMaps( underlineMapGet, underlineMapSet ), true, TEST_LOCATION );
underlineMapSet.Clear();
- underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::ENABLE, "true" );
- underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::COLOR, "green" );
- underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::HEIGHT, "2" );
+ underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::ENABLE, true );
+ underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::COLOR, Color::GREEN );
+ underlineMapSet.Insert( Toolkit::DevelText::Underline::Property::HEIGHT, 2 );
label.SetProperty( TextLabel::Property::UNDERLINE, underlineMapSet );
underlineMapSet.Clear();
Property::Map underlineDisabledMapGet;
- underlineDisabledMapGet.Insert( "enable", "false" );
- underlineDisabledMapGet.Insert( "color", "green" );
- underlineDisabledMapGet.Insert( "height", "2" );
+ underlineDisabledMapGet.Insert( "enable", false );
+ underlineDisabledMapGet.Insert( "color", Color::GREEN );
+ underlineDisabledMapGet.Insert( "height", 2 );
label.SetProperty( TextLabel::Property::UNDERLINE, underlineMapSet );
label.SetProperty( TextLabel::Property::MULTI_LINE, true );
Property::Map underlineMap;
- underlineMap.Insert( "enable", "true" );
- underlineMap.Insert( "color", "red" );
+ underlineMap.Insert( "enable", true );
+ underlineMap.Insert( "color", Color::RED );
label.SetProperty( TextLabel::Property::UNDERLINE, underlineMap );
Property::Map shadowMap;
application.Render();
lineCount = label.GetProperty<int>( TextLabel::Property::LINE_COUNT );
- DALI_TEST_EQUALS( lineCount, 4, TEST_LOCATION );
+ DALI_TEST_EQUALS( lineCount, 2, TEST_LOCATION );
label.SetProperty( TextLabel::Property::LINE_WRAP_MODE, "CHARACTER" );
DALI_TEST_EQUALS( label.GetProperty< int >( TextLabel::Property::LINE_WRAP_MODE ), static_cast< int >( Text::LineWrap::CHARACTER ), TEST_LOCATION );
application.Render();
lineCount = label.GetProperty<int>( TextLabel::Property::LINE_COUNT );
- DALI_TEST_EQUALS( lineCount, 4, TEST_LOCATION );
+ DALI_TEST_EQUALS( lineCount, 2, TEST_LOCATION );
label.SetProperty( TextLabel::Property::LINE_WRAP_MODE, Text::LineWrap::CHARACTER );
DALI_TEST_EQUALS( label.GetProperty< int >( TextLabel::Property::LINE_WRAP_MODE ), static_cast< int >( Text::LineWrap::CHARACTER ), TEST_LOCATION );
application.Render();
lineCount = label.GetProperty<int>( TextLabel::Property::LINE_COUNT );
- DALI_TEST_EQUALS( lineCount, 3, TEST_LOCATION );
+ DALI_TEST_EQUALS( lineCount, 2, TEST_LOCATION );
tet_infoline( "Ensure invalid string does not change wrapping mode" );
label.SetProperty( TextLabel::Property::LINE_WRAP_MODE, "InvalidWrapMode" );
propertyMap.Insert( "shadow", shadowMapSet.Add("color", Color::RED).Add("offset", Vector2(2.0f, 2.0f)).Add("blurRadius", 3.0f) );
Property::Map underlineMapSet;
- propertyMap.Insert( "underline", underlineMapSet.Add("enable", "true").Add("color", "green").Add("height", "1") );
+ propertyMap.Insert( "underline", underlineMapSet.Add("enable", true).Add("color", Color::GREEN).Add("height", 1) );
Property::Map outlineMapSet;
propertyMap.Insert( "outline", outlineMapSet.Add("color", Color::YELLOW).Add("width", 1) );
VisualFactory factory = VisualFactory::Get();
- // image visual, test default value ( false )
+ // image visual, test default value ( true )
{
Visual::Base imageVisual = factory.CreateVisual(
Property::Map()
// test values
DALI_TEST_CHECK( value );
- DALI_TEST_EQUALS( value->Get<bool>(), false, TEST_LOCATION );
+ DALI_TEST_EQUALS( value->Get<bool>(), true, TEST_LOCATION );
}
// image visual, override premultiplied
Property::Map()
.Add( Toolkit::Visual::Property::TYPE, Visual::IMAGE )
.Add( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME )
- .Add( Visual::Property::PREMULTIPLIED_ALPHA, true ) );
+ .Add( Visual::Property::PREMULTIPLIED_ALPHA, false ) );
Dali::Property::Map visualMap;
imageVisual.CreatePropertyMap( visualMap );
// test values
DALI_TEST_CHECK( value );
- DALI_TEST_EQUALS( value->Get<bool>(), true, TEST_LOCATION);
+ DALI_TEST_EQUALS( value->Get<bool>(), false, TEST_LOCATION);
}
// svg visual ( premultiplied alpha by default is true )
return DevelCustomActor::GetTypeInfo(Self());
}
+void ControlWrapper::EmitKeyInputFocusSignal( bool focusGained )
+{
+ Control::EmitKeyInputFocusSignal( focusGained );
+}
+
} // namespace Internal
} // namespace Toolkit
$(devel_api_src_dir)/layouting/layout-transition-data.cpp \
$(devel_api_src_dir)/scripting/script.cpp \
$(devel_api_src_dir)/styling/style-manager-devel.cpp \
+ $(devel_api_src_dir)/text/bitmap-font.cpp \
+ $(devel_api_src_dir)/text/text-utils-devel.cpp \
$(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \
$(devel_api_src_dir)/transition-effects/cube-transition-effect.cpp \
$(devel_api_src_dir)/transition-effects/cube-transition-fold-effect.cpp \
$(devel_api_src_dir)/controls/text-controls/text-style-properties-devel.h
devel_api_text_header_files = \
- $(devel_api_src_dir)/text/text-enumerations-devel.h
+ $(devel_api_src_dir)/text/text-enumerations-devel.h \
+ $(devel_api_src_dir)/text/bitmap-font.h \
+ $(devel_api_src_dir)/text/text-utils-devel.h
devel_api_tool_bar_header_files = \
$(devel_api_src_dir)/controls/tool-bar/tool-bar.h
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/devel-api/text/bitmap-font.h>
+
+// EXTERNAL INCLUDE
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/devel-api/text-abstraction/bitmap-font.h>
+
+// INTERNAL INCLUDE
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+using namespace Text;
+namespace DevelText
+{
+
+Glyph::Glyph()
+: url{},
+ utf8{ 0u },
+ ascender{ 0.f },
+ descender{ 0.f }
+{}
+
+Glyph::~Glyph()
+{}
+
+BitmapFontDescription::BitmapFontDescription()
+: glyphs{},
+ name{},
+ underlinePosition{ 0.f },
+ underlineThickness{ 1.f }
+{}
+
+BitmapFontDescription::~BitmapFontDescription()
+{}
+
+void CreateBitmapFont( const BitmapFontDescription& description, TextAbstraction::BitmapFont& bitmapFont )
+{
+ bitmapFont.glyphs.reserve( description.glyphs.size() );
+ bitmapFont.name = description.name;
+ bitmapFont.underlinePosition = description.underlinePosition;
+ bitmapFont.underlineThickness = description.underlineThickness;
+
+ for( const auto& glyph : description.glyphs )
+ {
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( glyph.utf8.size() );
+
+ const uint32_t numberOfCharacters = ( glyph.utf8.size() == 0 ) ? 0 :
+ Text::Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( glyph.utf8.c_str() ),
+ glyph.utf8.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ TextAbstraction::BitmapGlyph bitmapGlyph( glyph.url, utf32[0u], glyph.ascender, glyph.descender );
+
+ bitmapFont.glyphs.push_back( std::move( bitmapGlyph ) );
+ }
+}
+
+} // namespace DevelText
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_FONT_BITMAP_DEVEL_H
+#define DALI_TOOLKIT_FONT_BITMAP_DEVEL_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <string>
+
+namespace Dali
+{
+
+namespace TextAbstraction
+{
+// Forward declarations
+struct BitmapFont;
+}
+
+namespace Toolkit
+{
+
+namespace DevelText
+{
+
+/**
+ * @brief Struct that stores the needed info to create a bitmap glyph.
+ */
+
+struct DALI_TOOLKIT_API Glyph
+{
+ /**
+ * @brief Default constructor.
+ *
+ * Initialize the members to its defaults.
+ */
+ Glyph();
+
+ /**
+ * @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.
+};
+
+/**
+ * @brief Describes a bitmap font.
+ */
+struct DALI_TOOLKIT_API BitmapFontDescription
+{
+ /**
+ * @brief Default constructor.
+ *
+ * Initialize the members to its defaults.
+ */
+ BitmapFontDescription();
+
+ /**
+ * @brief Default destructor.
+ */
+ ~BitmapFontDescription();
+
+ std::vector<Glyph> glyphs; ///< Vector of glyphs.
+ 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.
+};
+
+/**
+ * @brief Creates a bitmap font with the given description.
+ *
+ * The @p bitmapFont output can be passed to the FontClient::GetFontId()
+ * method to load the font and get an Id.
+ *
+ * @param[in] description The description of the bitmap font.
+ * @param[out] bitmapFont A bitmap font.
+ *
+ * @note If the @e ascender and @e descender of the glyphs are zero, the @e descender value will be left as zero and all the bitmaps will be loaded to find out the @e ascender value.
+ */
+DALI_TOOLKIT_API void CreateBitmapFont( const BitmapFontDescription& description, TextAbstraction::BitmapFont& bitmapFont );
+
+} // namespace DevelText
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_UTILS_DEVEL_H
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/devel-api/text/text-utils-devel.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/text-abstraction/text-renderer.h>
+#include <dali/devel-api/text-abstraction/text-renderer-layout-helper.h>
+#include <dali/integration-api/debug.h>
+#include <dali/devel-api/scripting/enum-helper.h>
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/bidirectional-support.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/color-segmentation.h>
+#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
+#include <dali-toolkit/internal/text/text-font-style.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
+
+namespace Dali
+{
+
+using namespace TextAbstraction;
+
+namespace Toolkit
+{
+using namespace Text;
+
+namespace DevelText
+{
+
+namespace Layout
+{
+
+/**
+ * @brief The text's layout.
+ */
+enum Type
+{
+ SINGLELINE, ///< The text is laid out on a single line.
+ MULTILINE, ///< The text is laid out in multiple lines.
+ CIRCULAR, ///< The text is laid out on a single line following a circular path.
+};
+
+} // namespace Layout
+
+namespace CircularAlignment
+{
+
+/**
+ * @brief The enumerations for the circular alignment.
+ */
+enum Type
+{
+ BEGIN, ///< The text is aligned to the @p begin angle of the arc (or to the @p begin+increment if it's a RTL text).
+ CENTER, ///< The text is centered within the arc.
+ END, ///< The text is aligned to the @p begin+increment angle of the arc (or to the @p begin if it's a RTL text).
+};
+
+} // namespace CircularAlignment
+
+const float TO_POINT_26_DOT_6 = 64.f;
+const float TO_FLOAT = 1.f / 255.f;
+const float TO_UCHAR = 255.f;
+const bool RTL = true;
+const float TWO_PI = 2.f * Dali::Math::PI; ///< 360 degrees in radians
+const float RAD_135 = Math::PI_2 + Math::PI_4; ///< 135 degrees in radians;
+const float RAD_225 = RAD_135 + Math::PI_2; ///< 225 degrees in radians;
+const float RAD_270 = 3.f * Math::PI_2; ///< 270 degrees in radians;
+const float RAD_315 = RAD_225 + Math::PI_2; ///< 315 degrees in radians;
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_TYPE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, SINGLELINE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, MULTILINE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::Layout, CIRCULAR )
+DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_TYPE )
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN( CIRCULAR_ALIGNMENT_TYPE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, BEGIN )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, CENTER )
+DALI_ENUM_TO_STRING_WITH_SCOPE( DevelText::CircularAlignment, END )
+DALI_ENUM_TO_STRING_TABLE_END( CIRCULAR_ALIGNMENT_TYPE )
+
+bool GetLayoutEnumeration(const Property::Value& propertyValue, DevelText::Layout::Type& layout)
+{
+ return Scripting::GetEnumerationProperty(propertyValue, LAYOUT_TYPE_TABLE, LAYOUT_TYPE_TABLE_COUNT, layout);
+}
+
+bool GetCircularAlignmentEnumeration(const Property::Value& propertyValue, DevelText::CircularAlignment::Type& circularAlignment)
+{
+ return Scripting::GetEnumerationProperty(propertyValue, CIRCULAR_ALIGNMENT_TYPE_TABLE, CIRCULAR_ALIGNMENT_TYPE_TABLE_COUNT, circularAlignment);
+}
+
+Devel::PixelBuffer Render( const RendererParameters& textParameters, Vector<EmbeddedItemInfo>& embeddedItemLayout )
+{
+ if( textParameters.text.empty() )
+ {
+ Dali::Devel::PixelBuffer pixelBuffer = Dali::Devel::PixelBuffer::New( textParameters.textWidth,
+ textParameters.textHeight,
+ Dali::Pixel::RGBA8888 );
+
+ const unsigned int bufferSize = textParameters.textWidth * textParameters.textHeight * Dali::Pixel::GetBytesPerPixel(Dali::Pixel::RGBA8888);
+ unsigned char* buffer = pixelBuffer.GetBuffer();
+ memset(buffer, 0, bufferSize);
+
+ return pixelBuffer;
+ }
+
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+ FontClient fontClient = FontClient::Get();
+ MetricsPtr metrics;
+ Text::Layout::Engine layoutEngine; ///< The layout engine.
+ LogicalModelPtr logicalModel = LogicalModel::New(); ///< Pointer to the logical model.
+ VisualModelPtr visualModel = VisualModel::New(); ///< Pointer to the visual model.
+ Vector<ColorBlendingMode> blendingMode; ///< How embedded items and bitmap font glyphs are blended with color text.
+ Vector<bool> isEmoji; ///< Whether the glyph is an emoji.
+
+ // Use this to access FontClient i.e. to get down-scaled Emoji metrics.
+ metrics = Metrics::New( fontClient );
+ layoutEngine.SetMetrics( metrics );
+
+ TextAbstraction::TextRenderer::Parameters rendererParameters( visualModel->mGlyphs,
+ visualModel->mGlyphPositions,
+ visualModel->mColors,
+ visualModel->mColorIndices,
+ blendingMode,
+ isEmoji );
+
+ rendererParameters.width = textParameters.textWidth;
+ rendererParameters.height = textParameters.textHeight;
+ rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888; // @note: At the moment all textures are generated RGBA8888
+
+ Vector<Character>& utf32Characters = logicalModel->mText; // Characters encoded in utf32.
+ Vector<Character> mirroredUtf32Characters; // The utf32Characters Characters but mirrored if there are RTL text.
+ Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo; // The line break info.
+ Vector<ScriptRun>& scripts = logicalModel->mScriptRuns; // Charactes's script.
+ Vector<FontDescriptionRun>& fontDescriptionRuns = logicalModel->mFontDescriptionRuns; // Desired font descriptions.
+ Vector<FontRun>& validFonts = logicalModel->mFontRuns; // Validated fonts.
+ Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = logicalModel->mBidirectionalParagraphInfo; // The bidirectional info per paragraph.
+ Vector<BidirectionalLineInfoRun>& bidirectionalLineInfo = logicalModel->mBidirectionalLineInfo; // The bidirectional info per line.
+ Vector<CharacterDirection>& directions = logicalModel->mCharacterDirections; // Character's directions.
+ Vector<ColorRun>& colorRuns = logicalModel->mColorRuns; // colors of the text.
+
+ Vector<CharacterIndex>& glyphsToCharacters = visualModel->mGlyphsToCharacters; // Glyphs to character map.
+ Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph; // Characters to glyphs map.
+ Vector<Length>& charactersPerGlyph = visualModel->mCharactersPerGlyph; // Number of characters per glyph.
+ Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter; // The number of glyphs that are shaped.
+ Vector<LineRun>& lines = visualModel->mLines; // The laid out lines.
+
+ Vector<GlyphIndex> newParagraphGlyphs; // Glyphs for the new paragraph characters.
+
+ // the default font's description.
+ FontDescription defaultFontDescription;
+ PointSize26Dot6 defaultPointSize = FontClient::DEFAULT_POINT_SIZE;
+
+ Length numberOfCharacters = 0u; // The number of characters (not glyphs!).
+ bool isTextMirrored = false; // Whether the text has been mirrored.
+
+ const uint8_t* utf8 = NULL; // pointer to the first character of the text (encoded in utf8)
+ Length textSize = 0u; // The length of the utf8 string.
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Process the markup string if the mark-up processor is enabled.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ MarkupProcessData markupProcessData( colorRuns,
+ fontDescriptionRuns,
+ logicalModel->mEmbeddedItems );
+
+ if (textParameters.markupEnabled)
+ {
+ ProcessMarkupString(textParameters.text, markupProcessData);
+ textSize = markupProcessData.markupProcessedText.size();
+
+ // This is a bit horrible but std::string returns a (signed) char*
+ utf8 = reinterpret_cast<const uint8_t*>(markupProcessData.markupProcessedText.c_str());
+ }
+ else
+ {
+ textSize = textParameters.text.size();
+
+ // This is a bit horrible but std::string returns a (signed) char*
+ utf8 = reinterpret_cast<const uint8_t*>(textParameters.text.c_str());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Convert from utf8 to utf32
+ ////////////////////////////////////////////////////////////////////////////////
+
+ utf32Characters.Resize(textSize);
+
+ // Transform a text array encoded in utf8 into an array encoded in utf32.
+ // It returns the actual number of characters.
+ numberOfCharacters = Utf8ToUtf32( utf8, textSize, utf32Characters.Begin() );
+ utf32Characters.Resize( numberOfCharacters );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the Line and Word Break Info.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ lineBreakInfo.Resize( numberOfCharacters, LINE_NO_BREAK );
+
+ SetLineBreakInfo( utf32Characters,
+ 0u,
+ numberOfCharacters,
+ lineBreakInfo );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the script runs.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ multilanguageSupport.SetScripts( utf32Characters,
+ 0u,
+ numberOfCharacters,
+ scripts );
+
+ // Check if there are emojis.
+ // If there are an RGBA8888 pixel format is needed.
+ for( const auto& run : scripts )
+ {
+ if( run.script == TextAbstraction::Script::EMOJI )
+ {
+ rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888;
+ break;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the font runs.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // Set the description font run with the given text parameters.
+ FontDescriptionRun fontDescriptionRun;
+ fontDescriptionRun.characterRun.characterIndex = 0u;
+ fontDescriptionRun.characterRun.numberOfCharacters = numberOfCharacters;
+
+ fontDescriptionRun.familyLength = 0u;
+ fontDescriptionRun.familyName = nullptr;
+ fontDescriptionRun.familyDefined = !textParameters.fontFamily.empty();
+ if( fontDescriptionRun.familyDefined )
+ {
+ // The allocated memory will be freed when the logical model is destroyed.
+ fontDescriptionRun.familyLength = textParameters.fontFamily.size();
+ fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
+ memcpy( fontDescriptionRun.familyName, textParameters.fontFamily.c_str(), fontDescriptionRun.familyLength );
+ }
+
+ fontDescriptionRun.weightDefined = !textParameters.fontWeight.empty();
+ if( fontDescriptionRun.weightDefined )
+ {
+ fontDescriptionRun.weight = StringToWeight( textParameters.fontWeight.c_str() );
+ }
+
+ fontDescriptionRun.widthDefined = !textParameters.fontWidth.empty();
+ if( fontDescriptionRun.widthDefined )
+ {
+ fontDescriptionRun.width = StringToWidth( textParameters.fontWidth.c_str() );
+ }
+
+ fontDescriptionRun.slantDefined = !textParameters.fontSlant.empty();
+ if( fontDescriptionRun.slantDefined )
+ {
+ fontDescriptionRun.slant = StringToSlant( textParameters.fontSlant.c_str() );
+ }
+
+ fontDescriptionRun.sizeDefined = !EqualsZero( textParameters.fontSize );
+ if( fontDescriptionRun.sizeDefined )
+ {
+ fontDescriptionRun.size = static_cast<unsigned int>( textParameters.fontSize * TO_POINT_26_DOT_6 );
+ }
+
+ fontDescriptionRuns.PushBack( fontDescriptionRun );
+
+ // Validates the fonts. If there is a character with no assigned font it sets a default one.
+ // After this call, fonts are validated.
+ multilanguageSupport.ValidateFonts( utf32Characters,
+ scripts,
+ fontDescriptionRuns,
+ defaultFontDescription,
+ defaultPointSize,
+ 0u,
+ numberOfCharacters,
+ validFonts );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the Bidirectional info.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ bidirectionalInfo.Reserve( 1u );
+
+ SetBidirectionalInfo( utf32Characters,
+ scripts,
+ lineBreakInfo,
+ 0u,
+ numberOfCharacters,
+ bidirectionalInfo );
+
+ const bool hasBidirectionalText = 0u != bidirectionalInfo.Count();
+ if( hasBidirectionalText )
+ {
+ // Only set the character directions if there is right to left characters.
+ GetCharactersDirection( bidirectionalInfo,
+ numberOfCharacters,
+ 0u,
+ numberOfCharacters,
+ directions );
+
+ // This paragraph has right to left text. Some characters may need to be mirrored.
+ // TODO: consider if the mirrored string can be stored as well.
+
+ isTextMirrored = GetMirroredText( utf32Characters,
+ directions,
+ bidirectionalInfo,
+ 0u,
+ numberOfCharacters,
+ mirroredUtf32Characters );
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the glyphs. Text shaping
+ ////////////////////////////////////////////////////////////////////////////////
+
+ const Vector<Character>& textToShape = isTextMirrored ? mirroredUtf32Characters : utf32Characters;
+
+ newParagraphGlyphs.Reserve( 1u );
+
+ // Shapes the text.
+ ShapeText( textToShape,
+ lineBreakInfo,
+ scripts,
+ validFonts,
+ 0u,
+ 0u,
+ numberOfCharacters,
+ rendererParameters.glyphs,
+ glyphsToCharacters,
+ charactersPerGlyph,
+ newParagraphGlyphs );
+
+ // Create the 'number of glyphs' per character and the glyph to character conversion tables.
+ visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
+ visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
+
+ const Length numberOfGlyphs = rendererParameters.glyphs.Count();
+
+ // Once the text has been shaped and the glyphs created it's possible to replace the font id of those glyphs
+ // that represent an image or an item and create the embedded item layout info.
+ // Note: the position of the embedded item can't be set until the text is laid-out.
+ embeddedItemLayout.Reserve( logicalModel->mEmbeddedItems.Count() );
+ for( const auto& item : logicalModel->mEmbeddedItems )
+ {
+ // Get the glyph that matches with the character index.
+ const GlyphIndex glyphIndex = visualModel->mCharactersToGlyph[item.characterIndex];
+ GlyphInfo& glyph = rendererParameters.glyphs[glyphIndex];
+
+ glyph.fontId = 0u;
+ Pixel::Format pixelFormat = Pixel::A8;
+ TextAbstraction::FontClient::EmbeddedItemDescription description = { std::string( item.url, item.urlLength ), item.width, item.height, item.colorBlendingMode };
+ glyph.index = fontClient.CreateEmbeddedItem( description, pixelFormat ); // Set here an index to an item.
+
+ if( ( Pixel::RGBA8888 == pixelFormat ) || ( Pixel::BGRA8888 == pixelFormat ) )
+ {
+ rendererParameters.pixelFormat = TextAbstraction::TextRenderer::Parameters::RGBA8888;
+ }
+
+ // If the url is empty the item is going to be added after the text is rendered. It's needed to store the layout here.
+ if( description.url.empty() )
+ {
+ EmbeddedItemInfo embeddedInfo =
+ {
+ item.characterIndex,
+ glyphIndex,
+ Vector2::ZERO,
+ Size( static_cast<float>( item.width ), static_cast<float>( item.height ) ),
+ Size( static_cast<float>( item.width ), static_cast<float>( item.height ) ),
+ Degree( 0.f ),
+ item.colorBlendingMode
+ };
+
+ embeddedItemLayout.PushBack( embeddedInfo );
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Retrieve the glyph's metrics.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ metrics->GetGlyphMetrics( rendererParameters.glyphs.Begin(), numberOfGlyphs );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Set the color runs in glyphs.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ SetColorSegmentationInfo( colorRuns,
+ charactersToGlyph,
+ glyphsPerCharacter,
+ 0u,
+ 0u,
+ numberOfCharacters,
+ visualModel->mColors,
+ visualModel->mColorIndices );
+
+ // Insert the default color at the beginning of the vector.
+ visualModel->mColors.Insert( visualModel->mColors.Begin(),textParameters.textColor );
+
+ // Set how the embedded items are blended with text color.
+ blendingMode.Resize( numberOfGlyphs, textParameters.isTextColorSet ? ColorBlendingMode::MULTIPLY : ColorBlendingMode::NONE );
+
+ if( !textParameters.isTextColorSet )
+ {
+ // Traverse the color runs.
+ for( const auto& run : colorRuns )
+ {
+ const GlyphIndex firstGlyph = visualModel->mCharactersToGlyph[run.characterRun.characterIndex];
+ const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u;
+ const GlyphIndex lastGlyphPlusOne = visualModel->mCharactersToGlyph[lastCharacter] + visualModel->mGlyphsPerCharacter[lastCharacter];
+
+ for( GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index )
+ {
+ blendingMode[index] = ColorBlendingMode::MULTIPLY;
+ }
+ }
+ }
+
+ // Traverse the embedded items and update the blending mode vector.
+ for( const auto& item : logicalModel->mEmbeddedItems )
+ {
+ const GlyphIndex glyphIndex = visualModel->mCharactersToGlyph[item.characterIndex];
+ blendingMode[glyphIndex] = item.colorBlendingMode;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Set the isEmoji Vector
+ ////////////////////////////////////////////////////////////////////////////////
+
+ isEmoji.Resize( numberOfGlyphs, false );
+
+ for( const auto& run : scripts )
+ {
+ if( run.script == TextAbstraction::Script::EMOJI )
+ {
+ const GlyphIndex firstGlyph = visualModel->mCharactersToGlyph[run.characterRun.characterIndex];
+ const CharacterIndex lastCharacter = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u;
+ const GlyphIndex lastGlyphPlusOne = visualModel->mCharactersToGlyph[lastCharacter] + visualModel->mGlyphsPerCharacter[lastCharacter];
+
+ for( GlyphIndex index = firstGlyph; index < lastGlyphPlusOne; ++index )
+ {
+ isEmoji[index] = true;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Layout the text.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // Sets the alignment
+ HorizontalAlignment::Type horizontalAlignment = Toolkit::HorizontalAlignment::CENTER;
+ HorizontalAlignment::Type horizontalCircularAlignment = Toolkit::HorizontalAlignment::CENTER;
+ VerticalAlignment::Type verticalAlignment = VerticalAlignment::CENTER;
+ Layout::Type layout = Layout::SINGLELINE;
+ CircularAlignment::Type circularAlignment = CircularAlignment::BEGIN;
+
+ Property::Value horizontalAlignmentStr( textParameters.horizontalAlignment );
+ GetHorizontalAlignmentEnumeration( horizontalAlignmentStr, horizontalAlignment );
+ horizontalCircularAlignment = horizontalAlignment;
+
+ Property::Value verticalAlignmentStr( textParameters.verticalAlignment );
+ GetVerticalAlignmentEnumeration( verticalAlignmentStr, verticalAlignment );
+
+ Property::Value layoutStr( textParameters.layout );
+ GetLayoutEnumeration( layoutStr, layout );
+
+ Property::Value circularAlignmentStr( textParameters.circularAlignment );
+ GetCircularAlignmentEnumeration( circularAlignmentStr, circularAlignment );
+
+ // Whether the layout is multi-line.
+ const Text::Layout::Engine::Type horizontalLayout = ( Layout::MULTILINE == layout ) ? Text::Layout::Engine::MULTI_LINE_BOX : Text::Layout::Engine::SINGLE_LINE_BOX;
+ layoutEngine.SetLayout( horizontalLayout ); // TODO: multi-line.
+
+
+ // Whether the layout is circular.
+ const bool isCircularTextLayout = (Layout::CIRCULAR == layout);
+ const bool isClockwise = isCircularTextLayout && ( 0.f < textParameters.incrementAngle );
+
+ // Calculates the max ascender or the max descender.
+ // Is used to calculate the radius of the base line of the text.
+ float maxAscenderDescender = 0.f;
+ if( isCircularTextLayout )
+ {
+ FontId currentFontId = 0u;
+ for( const auto& glyph : rendererParameters.glyphs )
+ {
+ if( currentFontId != glyph.fontId )
+ {
+ currentFontId = glyph.fontId;
+ FontMetrics metrics;
+ fontClient.GetFontMetrics(currentFontId, metrics);
+ maxAscenderDescender = std::max( maxAscenderDescender, isClockwise ? metrics.ascender : metrics.descender );
+ }
+ }
+ }
+ const unsigned int radius = textParameters.radius - static_cast<unsigned int>( maxAscenderDescender );
+
+ // Convert CircularAlignment to HorizontalAlignment.
+ if( isCircularTextLayout )
+ {
+ switch( circularAlignment )
+ {
+ case CircularAlignment::BEGIN:
+ {
+ horizontalCircularAlignment = Toolkit::HorizontalAlignment::BEGIN;
+ break;
+ }
+ case CircularAlignment::CENTER:
+ {
+ horizontalCircularAlignment = Toolkit::HorizontalAlignment::CENTER;
+ break;
+ }
+ case CircularAlignment::END:
+ {
+ horizontalCircularAlignment = Toolkit::HorizontalAlignment::END;
+ break;
+ }
+ }
+ }
+
+ // Set the layout parameters.
+ Size textLayoutArea( static_cast<float>( textParameters.textWidth ),
+ static_cast<float>( textParameters.textHeight ) );
+
+ if( isCircularTextLayout )
+ {
+ // In a circular layout, the length of the text area depends on the radius.
+ rendererParameters.radius = radius;
+ textLayoutArea.width = fabs( Radian( Degree( textParameters.incrementAngle ) ) * static_cast<float>( rendererParameters.radius ) );
+ }
+
+ Text::Layout::Parameters layoutParameters( textLayoutArea,
+ textToShape.Begin(),
+ lineBreakInfo.Begin(),
+ nullptr,
+ ( 0u != directions.Count() ) ? directions.Begin() : nullptr,
+ rendererParameters.glyphs.Begin(),
+ glyphsToCharacters.Begin(),
+ charactersPerGlyph.Begin(),
+ charactersToGlyph.Begin(),
+ glyphsPerCharacter.Begin(),
+ numberOfGlyphs,
+ isCircularTextLayout ? horizontalCircularAlignment : horizontalAlignment,
+ LineWrap::WORD,
+ 0.f,
+ false,
+ false ); // Outline's width
+
+ // Resize the vector of positions to have the same size than the vector of glyphs.
+ rendererParameters.positions.Resize( numberOfGlyphs );
+
+ // Whether the last character is a new paragraph character.
+ layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( textToShape[numberOfCharacters - 1u] );
+
+ // The initial glyph and the number of glyphs to layout.
+ layoutParameters.startGlyphIndex = 0u;
+ layoutParameters.numberOfGlyphs = numberOfGlyphs;
+ layoutParameters.startLineIndex = 0u;
+ layoutParameters.estimatedNumberOfLines = 1u;
+ layoutParameters.interGlyphExtraAdvance = 0.f;
+
+ // Update the visual model.
+ Size newLayoutSize;
+ bool isAutoScrollEnabled = false;
+ layoutEngine.LayoutText( layoutParameters,
+ rendererParameters.positions,
+ lines,
+ newLayoutSize,
+ textParameters.ellipsisEnabled,
+ isAutoScrollEnabled );
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Reorder BiDirectional lines.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ if( hasBidirectionalText )
+ {
+ // Reorder the line.
+ bidirectionalLineInfo.Reserve( 1u );
+
+ ReorderLines( bidirectionalInfo,
+ 0u,
+ numberOfCharacters,
+ lines,
+ bidirectionalLineInfo );
+
+ // Set the bidirectional info per line into the layout parameters.
+ layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
+ layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
+
+ // Re-layout the text. Reorder those lines with right to left characters.
+ layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
+ 0u,
+ numberOfCharacters,
+ rendererParameters.positions );
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Align the text.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // Retrieve the line of text to know the direction and the width. @todo multi-line
+ const LineRun& line = lines[0u];
+
+ if( isCircularTextLayout )
+ {
+ // Set the circular alignment.
+ rendererParameters.circularLayout = isClockwise ? TextRenderer::Parameters::CLOCKWISE : TextRenderer::Parameters::COUNTER_CLOCKWISE;
+
+ // Update the text's height to be used by the ellipsis code.
+ textLayoutArea.height = newLayoutSize.height;
+
+ // Set the size of the text laid out on a straight horizontal line.
+ rendererParameters.circularWidth = static_cast<unsigned int>( newLayoutSize.width );
+ rendererParameters.circularHeight = static_cast<unsigned int>( newLayoutSize.height );
+
+ // Calculate the center of the circular text according the horizontal and vertical alingments and the radius.
+ switch( horizontalAlignment )
+ {
+ case HorizontalAlignment::BEGIN:
+ {
+ rendererParameters.centerX = static_cast<int>(textParameters.radius);
+ break;
+ }
+ case HorizontalAlignment::CENTER:
+ {
+ rendererParameters.centerX = static_cast<int>( textParameters.textWidth / 2u );
+ break;
+ }
+ case HorizontalAlignment::END:
+ {
+ rendererParameters.centerX = static_cast<int>( textParameters.textWidth ) - static_cast<int>(textParameters.radius);
+ break;
+ }
+ }
+
+ switch( verticalAlignment )
+ {
+ case VerticalAlignment::TOP:
+ {
+ rendererParameters.centerY = static_cast<int>(textParameters.radius);
+ break;
+ }
+ case VerticalAlignment::CENTER:
+ {
+ rendererParameters.centerY = static_cast<int>( textParameters.textHeight / 2u );
+ break;
+ }
+ case VerticalAlignment::BOTTOM:
+ {
+ rendererParameters.centerY = static_cast<int>( textParameters.textHeight ) - static_cast<int>(textParameters.radius);
+ break;
+ }
+ }
+
+ // Calculate the beginning angle according with the given horizontal alignment.
+ const bool isRTL = RTL == line.direction;
+
+ CircularAlignment::Type alignment = circularAlignment;
+ if( isRTL )
+ {
+ // Swap the alignment type if the line is right to left.
+ switch( alignment )
+ {
+ case CircularAlignment::BEGIN:
+ {
+ alignment = CircularAlignment::END;
+ break;
+ }
+ case CircularAlignment::CENTER:
+ {
+ // Nothing to do.
+ break;
+ }
+ case CircularAlignment::END:
+ {
+ alignment = CircularAlignment::BEGIN;
+ break;
+ }
+ }
+ }
+
+ float angleOffset = 0.f;
+
+ switch( alignment )
+ {
+ case CircularAlignment::BEGIN:
+ {
+ angleOffset = 0.f;
+ break;
+ }
+ case CircularAlignment::CENTER:
+ {
+ const bool isNeg = textParameters.incrementAngle < 0.f;
+ const float textWidth = static_cast<float>( rendererParameters.circularWidth );
+ angleOffset = ( isNeg ? -0.5f : 0.5f ) * ( textLayoutArea.width - textWidth ) / static_cast<float>( radius );
+ break;
+ }
+ case CircularAlignment::END:
+ {
+ const bool isNeg = textParameters.incrementAngle < 0.f;
+ const float textWidth = static_cast<float>( rendererParameters.circularWidth );
+ angleOffset = ( isNeg ? -1.f : 1.f ) * ( textLayoutArea.width - textWidth ) / static_cast<float>( radius );
+ break;
+ }
+ }
+
+ // Update the beginning angle with the calculated offset.
+ rendererParameters.beginAngle = Radian( Degree( textParameters.beginAngle ) ) + angleOffset;
+
+ // Set the vertical position of the glyphs.
+ for( auto& position : rendererParameters.positions )
+ {
+ position.y = 0.f;
+ }
+ }
+ else
+ {
+ // Calculate the vertical offset according with the given alignment.
+ float penY = 0.f;
+
+ switch( verticalAlignment )
+ {
+ case VerticalAlignment::TOP:
+ {
+ penY = line.ascender;
+ break;
+ }
+ case VerticalAlignment::CENTER:
+ {
+ penY = line.ascender + 0.5f * ( textLayoutArea.height - ( line.ascender - line.descender ) );
+ break;
+ }
+ case VerticalAlignment::BOTTOM:
+ {
+ penY = textLayoutArea.height;
+ break;
+ }
+ }
+
+ // Calculate the horizontal offset according with the given alignment.
+ float alignmentOffset = 0.f;
+ layoutEngine.Align( textLayoutArea,
+ 0u,
+ numberOfCharacters,
+ horizontalAlignment,
+ lines,
+ alignmentOffset,
+ Dali::LayoutDirection::LEFT_TO_RIGHT,
+ false );
+
+ // Update the position of the glyphs with the calculated offsets.
+ for( auto& position : rendererParameters.positions )
+ {
+ position.x += line.alignmentOffset;
+ position.y = penY;
+ }
+ }
+
+ // Cairo adds the bearing to the position of the glyph
+ // that has already been added by the DALi's layout engine,
+ // so it's needed to be removed here.
+ for( unsigned int index = 0u; index < rendererParameters.glyphs.Count(); ++index )
+ {
+ const GlyphInfo& glyph = rendererParameters.glyphs[index];
+ Vector2& position = rendererParameters.positions[index];
+
+ position.x -= glyph.xBearing;
+ }
+
+ // Set the position of the embedded items (if there is any).
+ EmbeddedItemInfo* embeddedItemLayoutBuffer = embeddedItemLayout.Begin();
+
+ auto transformToArc = isClockwise ? &Dali::TextAbstraction::TransformToArcClockwise : &Dali::TextAbstraction::TransformToArcAntiClockwise;
+
+ for( Length index = 0u, endIndex = embeddedItemLayout.Count(); index < endIndex; ++index )
+ {
+ EmbeddedItemInfo& embeddedItem = *( embeddedItemLayoutBuffer + index );
+
+ embeddedItem.position = rendererParameters.positions[embeddedItem.glyphIndex];
+
+ if( isCircularTextLayout )
+ {
+ // Calculate the new position of the embedded item in the circular path.
+
+ // Center of the bitmap.
+ const float halfWidth = 0.5f * embeddedItem.size.width;
+ const float halfHeight = 0.5f * embeddedItem.size.height;
+ double centerX = static_cast<double>( embeddedItem.position.x + halfWidth );
+ double centerY = static_cast<double>(embeddedItem.position.y - halfHeight);
+
+ Dali::TextAbstraction::CircularTextParameters circularTextParameters;
+
+ circularTextParameters.radius = static_cast<double>( radius );
+ circularTextParameters.invRadius = 1.0 / circularTextParameters.radius;
+ circularTextParameters.beginAngle = static_cast<double>( -rendererParameters.beginAngle + Dali::Math::PI_2 );
+ circularTextParameters.centerX = 0.5f * static_cast<double>( textParameters.textWidth );
+ circularTextParameters.centerY = 0.5f * static_cast<double>( textParameters.textHeight );
+
+ // Calculate the rotation angle.
+ float radians = rendererParameters.beginAngle;
+ if( isClockwise )
+ {
+ radians += static_cast<float>( circularTextParameters.invRadius * centerX );
+ radians = -radians;
+ }
+ else
+ {
+ radians -= static_cast<float>( circularTextParameters.invRadius * centerX );
+ radians = -radians + Dali::Math::PI;
+ }
+ embeddedItem.angle = Degree( Radian( radians ) );
+
+ transformToArc( circularTextParameters, centerX, centerY );
+
+ // Recalculate the size of the embedded item after the rotation to position it correctly.
+ float width = embeddedItem.size.width;
+ float height = embeddedItem.size.height;
+
+ // Transform the input angle into the range [0..2PI]
+ radians = fmod( radians, TWO_PI );
+ radians += ( radians < 0.f ) ? TWO_PI : 0.f;
+
+ // Does the same operations than rotate by shear.
+ if( ( radians > Math::PI_4 ) && ( radians <= RAD_135 ) )
+ {
+ std::swap( width, height );
+ radians -= Math::PI_2;
+ }
+ else if( ( radians > RAD_135 ) && ( radians <= RAD_225 ) )
+ {
+ radians -= Math::PI;
+ }
+ else if( ( radians > RAD_225 ) && ( radians <= RAD_315 ) )
+ {
+ std::swap( width, height );
+ radians -= RAD_270;
+ }
+
+ if( fabs( radians ) > Dali::Math::MACHINE_EPSILON_10 )
+ {
+ const float angleSinus = fabs( sin( radians ) );
+ const float angleCosinus = cos( radians );
+
+ // Calculate the rotated image dimensions.
+ embeddedItem.rotatedSize.height = width * angleSinus + height * angleCosinus;
+ embeddedItem.rotatedSize.width = height * angleSinus + width * angleCosinus + 1.f;
+ }
+
+ embeddedItem.position.x = floor( static_cast<float>( centerX ) - 0.5f * embeddedItem.rotatedSize.width );
+ embeddedItem.position.y = floor( static_cast<float>( centerY ) - 0.5f * embeddedItem.rotatedSize.height );
+ }
+ else
+ {
+ embeddedItem.position.y -= embeddedItem.size.height;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Ellipsis the text.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ if( textParameters.ellipsisEnabled )
+ {
+ const LineRun& line = lines[0u]; // TODO: multi-line
+
+ if( line.ellipsis )
+ {
+ Length finalNumberOfGlyphs = 0u;
+
+ if( ( line.ascender - line.descender ) > textLayoutArea.height )
+ {
+ // The height of the line is bigger than the height of the text area.
+ // Show the ellipsis glyph even if it doesn't fit in the text area.
+ // If no text is rendered then issues are rised and it may be a while
+ // until is find out that the text area is too small.
+
+ // Get the first glyph which is going to be replaced and the ellipsis glyph.
+ GlyphInfo& glyphInfo = rendererParameters.glyphs[0u];
+ const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph( fontClient.GetPointSize( glyphInfo.fontId ) );
+
+ // Change the 'x' and 'y' position of the ellipsis glyph.
+ Vector2& position = rendererParameters.positions[0u];
+ position.x = ellipsisGlyph.xBearing;
+ position.y = textLayoutArea.height - ellipsisGlyph.yBearing;
+
+ // Replace the glyph by the ellipsis glyph.
+ glyphInfo = ellipsisGlyph;
+
+ // Set the final number of glyphs
+ finalNumberOfGlyphs = 1u;
+ }
+ else
+ {
+
+ // firstPenX, penY and firstPenSet are used to position the ellipsis glyph if needed.
+ float firstPenX = 0.f; // Used if rtl text is elided.
+ bool firstPenSet = false;
+
+ // Add the ellipsis glyph.
+ bool inserted = false;
+ float removedGlypsWidth = 0.f;
+ Length numberOfRemovedGlyphs = 0u;
+ if (line.glyphRun.numberOfGlyphs > 0u)
+ {
+ GlyphIndex index = line.glyphRun.numberOfGlyphs - 1u;
+
+ GlyphInfo* glyphs = rendererParameters.glyphs.Begin();
+ Vector2* glyphPositions = rendererParameters.positions.Begin();
+
+ float penY = 0.f;
+
+ // The ellipsis glyph has to fit in the place where the last glyph(s) is(are) removed.
+ while( !inserted )
+ {
+ const GlyphInfo& glyphToRemove = *( glyphs + index );
+
+ if( 0u != glyphToRemove.fontId )
+ {
+ // i.e. The font id of the glyph shaped from the '\n' character is zero.
+
+ // Need to reshape the glyph as the font may be different in size.
+ const GlyphInfo& ellipsisGlyph = fontClient.GetEllipsisGlyph( fontClient.GetPointSize( glyphToRemove.fontId ) );
+
+ if( !firstPenSet )
+ {
+ const Vector2& position = *( glyphPositions + index );
+
+ // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
+ penY = position.y;
+
+ // Calculates the first penX which will be used if rtl text is elided.
+ firstPenX = position.x - glyphToRemove.xBearing;
+ if( firstPenX < -ellipsisGlyph.xBearing )
+ {
+ // Avoids to exceed the bounding box when rtl text is elided.
+ firstPenX = -ellipsisGlyph.xBearing;
+ }
+
+ removedGlypsWidth = -ellipsisGlyph.xBearing;
+
+ firstPenSet = true;
+ }
+
+ removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
+
+ // Calculate the width of the ellipsis glyph and check if it fits.
+ const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
+ if( ellipsisGlyphWidth < removedGlypsWidth )
+ {
+ GlyphInfo& glyphInfo = *( glyphs + index );
+ Vector2& position = *( glyphPositions + index );
+ position.x -= ( 0.f > glyphInfo.xBearing ) ? glyphInfo.xBearing : 0.f;
+
+ // Replace the glyph by the ellipsis glyph.
+ glyphInfo = ellipsisGlyph;
+
+ // Update the isEmoji vector
+ isEmoji[index] = false;
+
+ // Change the 'x' and 'y' position of the ellipsis glyph.
+
+ if( position.x > firstPenX )
+ {
+ position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+ }
+
+ position.x += ellipsisGlyph.xBearing;
+ position.y = penY;
+
+ inserted = true;
+ }
+ }
+
+ if( !inserted )
+ {
+ if( index > 0u )
+ {
+ --index;
+ }
+ else
+ {
+ // No space for the ellipsis.
+ inserted = true;
+ }
+ ++numberOfRemovedGlyphs;
+ }
+
+ // Set the final number of glyphs
+ finalNumberOfGlyphs = line.glyphRun.numberOfGlyphs - numberOfRemovedGlyphs;
+ }
+ }
+
+ // Resize the number of glyphs/positions
+ rendererParameters.glyphs.Resize( finalNumberOfGlyphs );
+ rendererParameters.positions.Resize( finalNumberOfGlyphs );
+
+ // Remove from the embedded items those exceding the last laid out glyph.
+ embeddedItemLayout.Erase( std::remove_if( embeddedItemLayout.Begin(),
+ embeddedItemLayout.End(),
+ [finalNumberOfGlyphs]( const EmbeddedItemInfo& item )
+ {
+ return item.glyphIndex >= finalNumberOfGlyphs;
+ } ),
+ embeddedItemLayout.End() );
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Render the text.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ rendererParameters.width = textParameters.textWidth;
+ rendererParameters.height = textParameters.textHeight;
+
+ TextAbstraction::TextRenderer renderer = TextAbstraction::TextRenderer::Get();
+ return renderer.Render( rendererParameters );
+}
+
+Devel::PixelBuffer CreateShadow( const ShadowParameters& shadowParameters )
+{
+ // The size of the pixel data.
+ const int width = static_cast<int>(shadowParameters.input.GetWidth());
+ const int height = static_cast<int>(shadowParameters.input.GetHeight());
+
+ // The shadow's offset.
+ const int xOffset = static_cast<int>( shadowParameters.offset.x );
+ const int yOffset = static_cast<int>( shadowParameters.offset.y );
+
+ // The size in bytes of the pixel of the input's buffer.
+ const Pixel::Format inputFormat = shadowParameters.input.GetPixelFormat();
+ const unsigned int inputPixelSize = Pixel::GetBytesPerPixel( inputFormat );
+ const bool isA8 = Pixel::A8 == inputFormat;
+
+ // Creates the output pixel buffer.
+ Devel::PixelBuffer outputPixelBuffer = Devel::PixelBuffer::New(width, height, Pixel::RGBA8888);
+
+ // Clear the output buffer
+ unsigned char* outputPixelBufferPtr = outputPixelBuffer.GetBuffer();
+ memset(outputPixelBufferPtr, 0, width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888));
+
+ // Gets the buffer of the input pixel buffer.
+ const unsigned char* const inputPixelBuffer = shadowParameters.input.GetBuffer();
+
+ float textColor[4u];
+ if (isA8)
+ {
+ memcpy(textColor, shadowParameters.textColor.AsFloat(), 4u * sizeof(float));
+ }
+ const float* const shadowColor = shadowParameters.color.AsFloat();
+
+ // Traverse the input pixel buffer and write the text on the foreground and the shadow on the background.
+ for (int rowIndex = 0; rowIndex < height; ++rowIndex)
+ {
+ // Calculates the rowIndex to the input pixel buffer for the shadow and whether it's within the boundaries.
+ const int yOffsetIndex = rowIndex - yOffset;
+ const bool isValidRowIndex = ((yOffsetIndex >= 0) && (yOffsetIndex < height));
+
+ const int rows = rowIndex * width;
+ const int offsetRows = yOffsetIndex * width;
+ for (int columnIndex = 0; columnIndex < width; ++columnIndex)
+ {
+ // Index to the input buffer to retrieve the alpha value of the foreground text.
+ const unsigned int index = inputPixelSize * static_cast<unsigned int>(rows + columnIndex);
+
+ // Build the index to the input buffer to retrieve the alpha value of the background shadow.
+ unsigned int shadowIndex = 0u;
+ bool isValidShadowIndex = false;
+ if (isValidRowIndex)
+ {
+ const int xOffsetIndex = columnIndex - xOffset;
+ isValidShadowIndex = ((xOffsetIndex >= 0) && (xOffsetIndex < width));
+
+ if (isValidShadowIndex)
+ {
+ shadowIndex = inputPixelSize * static_cast<unsigned int>(offsetRows + xOffsetIndex);
+ }
+ }
+
+ // If the input buffer is an alpha mask, retrieve the values for the foreground text and the background shadow.
+ // If not retrieve the color.
+ float inputShadowOffsetAlphaValue = 1.f;
+ float inputAlphaValue = 1.f;
+ if (isA8)
+ {
+ // Retrieve the alpha value for the shadow.
+ inputShadowOffsetAlphaValue = isValidShadowIndex ? (static_cast<float>(*(inputPixelBuffer + shadowIndex)) / 255.f) : 0.f;
+
+ // Retrieve the alpha value for the text.
+ inputAlphaValue = static_cast<float>(*(inputPixelBuffer + index)) / 255.f;
+ }
+ else
+ {
+ // The input buffer is not an alpha mask. Retrieve the color.
+ textColor[0u] = TO_FLOAT * static_cast<float>( *(inputPixelBuffer + index + 0u) );
+ textColor[1u] = TO_FLOAT * static_cast<float>( *(inputPixelBuffer + index + 1u) );
+ textColor[2u] = TO_FLOAT * static_cast<float>( *(inputPixelBuffer + index + 2u) );
+ textColor[3u] = TO_FLOAT * static_cast<float>( *(inputPixelBuffer + index + 3u) );
+ inputAlphaValue = textColor[3u];
+ inputShadowOffsetAlphaValue = isValidShadowIndex ? TO_FLOAT * static_cast<float>( *(inputPixelBuffer + shadowIndex + 3u) ) : 0.f;
+ }
+
+ // Build the output color.
+ float outputColor[4u];
+
+ if( shadowParameters.blendShadow )
+ {
+ // Blend the shadow's color with the text's color on top
+ const float textAlpha = textColor[3u] * inputAlphaValue;
+ const float shadowAlpha = shadowColor[3u] * inputShadowOffsetAlphaValue;
+
+ // Blends the alpha.
+ outputColor[3u] = 1.f - ((1.f - textAlpha) * (1.f - shadowAlpha));
+ const bool isOutputAlphaZero = outputColor[3u] < Dali::Math::MACHINE_EPSILON_1000;
+ if( isOutputAlphaZero )
+ {
+ std::fill( outputColor, outputColor + 4u, 0.f );
+ }
+ else
+ {
+ // Blends the RGB components.
+ float shadowComponent = 0.f;
+ float textComponent = 0.f;
+
+ shadowComponent = shadowColor[0u] * inputShadowOffsetAlphaValue;
+ textComponent = textColor[0u] * inputAlphaValue;
+ outputColor[0u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]);
+
+ shadowComponent = shadowColor[1u] * inputShadowOffsetAlphaValue;
+ textComponent = textColor[1u] * inputAlphaValue;
+ outputColor[1u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]);
+
+ shadowComponent = shadowColor[2u] * inputShadowOffsetAlphaValue;
+ textComponent = textColor[2u] * inputAlphaValue;
+ outputColor[2u] = (textComponent * textAlpha / outputColor[3u]) + (shadowComponent * shadowAlpha * (1.f - textAlpha) / outputColor[3u]);
+ }
+ }
+ else
+ {
+ // No blending!!!
+ std::fill( outputColor, outputColor + 4u, 0.f );
+
+ const float textAlpha = textColor[3u];
+ const float shadowAlpha = shadowColor[3u] * inputShadowOffsetAlphaValue;
+
+ // Write shadow first.
+ if( shadowAlpha > Dali::Math::MACHINE_EPSILON_1000 )
+ {
+ outputColor[0u] = shadowColor[0u] * inputShadowOffsetAlphaValue;
+ outputColor[1u] = shadowColor[1u] * inputShadowOffsetAlphaValue;
+ outputColor[2u] = shadowColor[2u] * inputShadowOffsetAlphaValue;
+ outputColor[3u] = shadowAlpha;
+ }
+
+ // Write character on top.
+ if( textAlpha > Dali::Math::MACHINE_EPSILON_1000 )
+ {
+ outputColor[0u] = textColor[0u];
+ outputColor[1u] = textColor[1u];
+ outputColor[2u] = textColor[2u];
+ outputColor[3u] = textAlpha;
+ }
+ }
+
+ // Write the color into the output pixel buffer.
+ const unsigned int outputIndex = 4u * (rows + columnIndex);
+ *(outputPixelBufferPtr + outputIndex + 0u) = static_cast<unsigned char>( TO_UCHAR * outputColor[0u] );
+ *(outputPixelBufferPtr + outputIndex + 1u) = static_cast<unsigned char>( TO_UCHAR * outputColor[1u] );
+ *(outputPixelBufferPtr + outputIndex + 2u) = static_cast<unsigned char>( TO_UCHAR * outputColor[2u] );
+ *(outputPixelBufferPtr + outputIndex + 3u) = static_cast<unsigned char>( TO_UCHAR * outputColor[3u] );
+ }
+ }
+
+ // Returns the pixel buffer.
+ return outputPixelBuffer;
+}
+
+Devel::PixelBuffer ConvertToRgba8888(Devel::PixelBuffer pixelBuffer, const Vector4& color, bool multiplyByAlpha)
+{
+ if (Dali::Pixel::A8 != pixelBuffer.GetPixelFormat())
+ {
+ // Does nothing.
+ return pixelBuffer;
+ }
+
+ const unsigned int width = pixelBuffer.GetWidth();
+ const unsigned int height = pixelBuffer.GetHeight();
+ Devel::PixelBuffer newPixelBuffer = Devel::PixelBuffer::New( width, height, Dali::Pixel::RGBA8888 );
+
+ unsigned char* dstBuffer = newPixelBuffer.GetBuffer();
+ const unsigned char* const srcBuffer = pixelBuffer.GetBuffer();
+
+ const unsigned char r = static_cast<unsigned char>( TO_UCHAR * color.r );
+ const unsigned char g = static_cast<unsigned char>( TO_UCHAR * color.g );
+ const unsigned char b = static_cast<unsigned char>( TO_UCHAR * color.b );
+
+ unsigned char dstColor[4];
+ for( unsigned int j = 0u; j < height; ++j )
+ {
+ const unsigned int lineIndex = j * width;
+ for( unsigned int i=0u; i < width; ++i )
+ {
+ const unsigned int srcIndex = lineIndex + i;
+
+ const float srcAlpha = static_cast<float>( *( srcBuffer + srcIndex ) );
+
+ if( multiplyByAlpha )
+ {
+ dstColor[0u] = static_cast<unsigned char>( srcAlpha * color.r );
+ dstColor[1u] = static_cast<unsigned char>( srcAlpha * color.g );
+ dstColor[2u] = static_cast<unsigned char>( srcAlpha * color.b );
+ dstColor[3u] = static_cast<unsigned char>( srcAlpha * color.a );
+ }
+ else
+ {
+ dstColor[0u] = r;
+ dstColor[1u] = g;
+ dstColor[2u] = b;
+ dstColor[3u] = static_cast<unsigned char>( srcAlpha );
+ }
+
+ const unsigned int dstIndex = srcIndex * 4u;
+ memcpy( dstBuffer + dstIndex, dstColor, 4u );
+ }
+ }
+
+ return newPixelBuffer;
+}
+
+void UpdateBuffer(Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x, unsigned int y, bool blend)
+{
+ const Dali::Pixel::Format pixelFormat = dst.GetPixelFormat();
+ if( src.GetPixelFormat() != pixelFormat )
+ {
+ DALI_LOG_ERROR("PixelBuffer::SetBuffer. The pixel format of the new data must be the same of the current pixel buffer.");
+ return;
+ }
+
+ const unsigned int srcWidth = src.GetWidth();
+ const unsigned int srcHeight = src.GetHeight();
+ const unsigned int dstWidth = dst.GetWidth();
+ const unsigned int dstHeight = dst.GetHeight();
+
+ if( ( x > dstWidth ) ||
+ ( y > dstHeight ) ||
+ ( x + srcWidth > dstWidth ) ||
+ ( y + srcHeight > dstHeight ) )
+ {
+ DALI_LOG_ERROR("PixelBuffer::SetBuffer. The source pixel buffer is out of the boundaries of the destination pixel buffer.");
+ return;
+ }
+
+ const unsigned int bytesPerPixel = Dali::Pixel::GetBytesPerPixel(pixelFormat);
+ const unsigned int alphaIndex = bytesPerPixel - 1u;
+
+ const unsigned char* const srcBuffer = src.GetBuffer();
+ unsigned char* dstBuffer = dst.GetBuffer();
+
+ if( !blend )
+ {
+ const unsigned int currentLineSize = dstWidth * bytesPerPixel;
+ const unsigned int newLineSize = srcWidth * bytesPerPixel;
+ unsigned char* currentBuffer = dstBuffer + (y * dstWidth + x) * bytesPerPixel;
+ for (unsigned int j = 0u; j < srcHeight; ++j)
+ {
+ memcpy(currentBuffer + j * currentLineSize, srcBuffer + j * newLineSize, newLineSize);
+ }
+ }
+ else
+ {
+ float outputColor[4u];
+
+ // Blend the src pixel buffer with the dst pixel buffer as background.
+ //
+ // fgColor, fgAlpha, bgColor, bgAlpha
+ //
+ // alpha = 1 - ( 1 - fgAlpha ) * ( 1 - bgAlpha )
+ // color = ( fgColor * fgAlpha / alpha ) + ( bgColor * bgAlpha * ( 1 - fgAlpha ) / alpha )
+
+ // Jump till the 'x,y' position
+ const unsigned int dstWidthBytes = dstWidth * bytesPerPixel;
+ dstBuffer += ( y * dstWidthBytes + x * bytesPerPixel );
+
+ for (unsigned int j = 0u; j < srcHeight; ++j)
+ {
+ const unsigned int srcLineIndex = j * srcWidth;
+ for (unsigned int i = 0u; i < srcWidth; ++i)
+ {
+ const float srcAlpha = TO_FLOAT * static_cast<float>( *( srcBuffer + bytesPerPixel * ( srcLineIndex + i ) + alphaIndex ) );
+ const float dstAlpha = TO_FLOAT * static_cast<float>( *(dstBuffer + i*bytesPerPixel + alphaIndex) );
+
+ // Blends the alpha channel.
+ const float oneMinusSrcAlpha = 1.f - srcAlpha;
+ outputColor[alphaIndex] = 1.f - (oneMinusSrcAlpha * (1.f - dstAlpha));
+
+ // Blends the RGB channels.
+ const bool isOutputAlphaZero = outputColor[alphaIndex] < Dali::Math::MACHINE_EPSILON_1000;
+ if( isOutputAlphaZero )
+ {
+ std::fill( outputColor, outputColor + bytesPerPixel, 0.f );
+ }
+ else
+ {
+ const float srcAlphaOverOutputAlpha = srcAlpha / outputColor[alphaIndex]; // fgAlpha / alpha
+ const float dstAlphaOneMinusSrcAlphaOverOutputAlpha = dstAlpha * oneMinusSrcAlpha / outputColor[alphaIndex]; // bgAlpha * ( 1 - fgAlpha ) / alpha
+ for (unsigned int index = 0u; index < alphaIndex; ++index)
+ {
+ const float dstComponent = TO_FLOAT * static_cast<float>( *( dstBuffer + i * bytesPerPixel + index ) ) * dstAlpha;
+ const float srcComponent = TO_FLOAT * static_cast<float>(*(srcBuffer + bytesPerPixel * (srcLineIndex + i) + index) ) * srcAlpha;
+ outputColor[index] = ( srcComponent * srcAlphaOverOutputAlpha ) + ( dstComponent * dstAlphaOneMinusSrcAlphaOverOutputAlpha );
+ }
+ }
+
+ for (unsigned int index = 0u; index < bytesPerPixel; ++index)
+ {
+ *(dstBuffer + i * bytesPerPixel + index) = static_cast<unsigned char>( TO_UCHAR * outputColor[index] );
+ }
+ }
+
+ dstBuffer += dstWidthBytes;
+ }
+ }
+}
+
+} // namespace DevelText
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_UTILS_DEVEL_H
+#define DALI_TOOLKIT_TEXT_UTILS_DEVEL_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace DevelText
+{
+
+/**
+ * @brief Struct with the text and style parameters to be rendered into a pixel buffer.
+ */
+struct DALI_TOOLKIT_API RendererParameters
+{
+ RendererParameters()
+ : text{},
+ horizontalAlignment{ "begin" },
+ verticalAlignment{ "top" },
+ fontFamily{},
+ fontWeight{},
+ fontWidth{},
+ fontSlant{},
+ layout{ "singleLine" },
+ circularAlignment{ "begin" },
+ textColor{ Color::WHITE },
+ fontSize{ 0.f },
+ textWidth{ 0u },
+ textHeight{ 0u },
+ radius{ 0u },
+ beginAngle{ 0.f },
+ incrementAngle{ 0.f },
+ ellipsisEnabled{ true },
+ markupEnabled{ false },
+ isTextColorSet{ false }
+ {}
+
+ std::string text; ///< The text to be rendered encoded in utf8.
+
+ std::string horizontalAlignment; ///< The horizontal alignment: one of {"begin", "center", "end"}.
+ std::string verticalAlignment; ///< The vertical alignment: one of {"top", "center", "bottom"}.
+
+ std::string fontFamily; ///< The font's family.
+ std::string fontWeight; ///< The font's weight: one of {"thin", "ultraLight", "extraLight", "light", "demiLight", "semiLight", "book", "normal", "regular", "medium", "demiBold", "semiBold", "bold", "ultraBold", "extraBold", "black", "heavy", "extraBlack"}.
+ std::string fontWidth; ///< The font's width: one of {"ultraCondensed", "extraCondensed", "condensed", "semiCondensed", "normal", "semiExpanded", "expanded", "extraExpanded", "ultraExpanded"}.
+ std::string fontSlant; ///< The font's slant. one of {"normal", "roman", "italic", "oblique"}
+ std::string layout; ///< The type of layout: one of {"singleLine", "multiLine", "circular"}
+ std::string circularAlignment; ///< The text alignment within the arc: one of {"begin", "center", "end"}. The @p horizontalAlignment and @p verticalAlignment can be used to align the text within the text area.
+
+ Vector4 textColor; ///< The default text's color. Default is white.
+
+ float fontSize; ///< The font's size (in points).
+
+ unsigned int textWidth; ///< The width in pixels of the boundaries where the text is going to be laid-out.
+ unsigned int textHeight; ///< The height in pixels of the boundaries where the text is going to be laid-out.
+
+ unsigned int radius; ///< The radius in pixels of the circular text.
+ float beginAngle; ///< The begin angle in degrees of the text area on the circle. The top of the circle is 0°, the right side 90°, the bottom 180° and the left 270°.
+ float incrementAngle; ///< The increment angle in degrees of the text area on the circle. The @p incrementAngle defines a direction. If positive, the text will be laid out clockwise.
+
+ bool ellipsisEnabled:1; ///< Whether the ellipsis layout option is enabled.
+ bool markupEnabled:1; ///< Whether the mark-up processor is enabled.
+ bool isTextColorSet:1; ///< Whether a default color has been set.
+};
+
+/**
+ * @brief Struct with info of the embedded items layout.
+ */
+struct DALI_TOOLKIT_API EmbeddedItemInfo
+{
+ TextAbstraction::CharacterIndex characterIndex; ///< Index to the character within the string.
+ TextAbstraction::GlyphIndex glyphIndex; ///< Index to the glyph
+ Vector2 position; ///< The layout position within the buffer (top, left corner).
+ Size size; ///< The size within the buffer of the embedded item.
+ Size rotatedSize; ///< The rotated size within the buffer of the embedded item.
+ Degree angle; ///< Rotation angle of the pixel buffer in degrees.
+ TextAbstraction::ColorBlendingMode colorBlendingMode; ///< Whether the color of the image is multiplied by the color of the text.
+};
+
+/**
+* @brief Struct with the parameters needed to build a shadow for the given pixel buffer.
+*/
+struct DALI_TOOLKIT_API ShadowParameters
+{
+ Devel::PixelBuffer input; ///< The input pixel buffer used to create the shadow.
+ Vector4 textColor; ///< The color of the text.
+ Vector4 color; ///< The color of the shadow.
+ Vector2 offset; ///< The offset of the shadow.
+ bool blendShadow; ///< Whether to blend the shadow.
+};
+
+/**
+ * @brief Renders text into a pixel buffer.
+ *
+ * @note: Can process a mark-up string.
+ * @note: It does the font selection, RTL reordering, shaping and layouting.
+ * @note: The width of the pixel buffer may be different to the given @e textWidth
+ * due to some padding pixels added.
+ *
+ * The text is laid-out for the given size @e (textWidth,textHeight).
+ * If the @e multiLineEnabled option is enabled, the text will wrap in lines.
+ * If the @e ellipsisEnabled option is enabled, the text will be ellided if
+ * there is no more space for new lines.
+ *
+ * It won't be rendered the parts of the text exceeding the boundaries of
+ * the given width and height.
+ *
+ * If the given @e textHeight is zero, a big enough pixel buffer will be created
+ * to render the full text.
+ *
+ * If the given @e textWidth is zero, the 'natural size' of the text will be
+ * used to create the pixel buffer to render the full text.
+ *
+ * If the radius is not zero, the text will be laid-out following a circular path.
+ * In that case the text is laid-out in a single line.
+ *
+ * If the mark-up string contains embedded items, the @p embeddedItemLayout vector
+ * contains the layout info of each embedded item.
+ *
+ * @param[in] textParameters The text and style options.
+ * @param[out] embeddedItemLayout The layout info of the embedded items.
+ *
+ * @return A pixel buffer with the text rendered on it.
+ */
+DALI_TOOLKIT_API Devel::PixelBuffer Render( const RendererParameters& textParameters, Vector<EmbeddedItemInfo>& embeddedItemLayout );
+
+/**
+ * @brief Creates a shadow for the text given in the input pixel buffer.
+ *
+ * The function returns a RGBA8888 pixel buffer with the text and its shadow rendered on it.
+ *
+ * The pixel format of the @e input pixel buffer could be an A8 or an RGBA8888. If it's
+ * an A8 pixel buffer, it uses the given @e textColor to give color to the text. Otherwise
+ * it uses the color of the @e input pixel buffer.
+ *
+ * @param[in] shadowParameters The parameters needed to create the text's shadow.
+ *
+ * @return A pixel buffer with the text and the shadow rendered on it.
+ */
+DALI_TOOLKIT_API Devel::PixelBuffer CreateShadow(const ShadowParameters& shadowParameters);
+
+/**
+ * @brief Converts a @p pixelBuffer with pixel format A8 to RGBA8888 using the given @p color.
+ *
+ * @note Does nothing if the @p pixelBuffer is not A8.
+ *
+ * @param[in] pixelBuffer The pixel buffer with pixel format A8
+ * @param[in] color The color used to convert to RGBA8888
+ * @param[in] multiplyByAlpha Whether to multiply the @p color with the alpha value of the @p pixel @p buffer.
+ *
+ * @return The pixel buffer converted to RGBA8888.
+ */
+DALI_TOOLKIT_API Devel::PixelBuffer ConvertToRgba8888( Devel::PixelBuffer pixelBuffer, const Vector4& color, bool multiplyByAlpha );
+
+/**
+* @brief Updates the @p dst pixel buffer with the data from @p src pixel buffer.
+*
+* @note Both pixel buffers must have the same pixel format. Does nothing if both pixel format are different.
+* @note The function does nothing if the @p src pixel buffer doesn't fit into the @p dst pixel buffer.
+*
+* The @p src pixel buffer could be blended with the @p dst pixel buffer if @p blend is set to @e true.
+*
+* @param[in] src The pixel buffer from where the data is read.
+* @param[in] dst The pixel buffer where the data is written..
+* @param[in] x The top left corner's X within the destination pixel buffer.
+* @param[in] y The top left corner's y within the destination pixel buffer.
+* @param[in] blend Whether to blend the source pixel buffer with the destination pixel buffer as background.
+*/
+DALI_TOOLKIT_API void UpdateBuffer( Devel::PixelBuffer src, Devel::PixelBuffer dst, unsigned int x, unsigned int y, bool blend);
+
+} // namespace DevelText
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_UTILS_DEVEL_H
return ret;
}
-bool AccessibilityManager::AccessibilityActionReadIndicatorInformation()
-{
- Dali::Toolkit::AccessibilityManager handle( this );
- if( !mActionReadIndicatorInformationSignal.Empty() )
- {
- mActionReadIndicatorInformationSignal.Emit( handle );
- }
-
- // TODO: Read the information in the indicator
-
- return mIsAccessibilityTtsEnabled;
-}
-
bool AccessibilityManager::AccessibilityActionReadPauseResume()
{
Dali::Toolkit::AccessibilityManager handle( this );
virtual bool AccessibilityActionZoom();
/**
- * Perform the accessibility action to read the information in the indicator (by two fingers triple tap).
- * @return whether the accessibility action is performed or not.
- */
- virtual bool AccessibilityActionReadIndicatorInformation();
-
- /**
* Perform the accessibility action to pause/resume the current read out (by two fingers single tap).
* @return whether the accessibility action is performed or not.
*/
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
if( signalFeedbackInfo.mHasHapticFeedbackInfo || signalFeedbackInfo.mHasSoundFeedbackInfo )
{
- AddSignalInfo( themeInfo, signalFeedbackInfo );
+ AddSignalInfo( themeInfo, std::move( signalFeedbackInfo ) );
}
}
}
} // LoadFromString()
-void FeedbackStyle::AddSignalInfo( FeedbackStyleInfo& styleInfo, SignalFeedbackInfo signalInfo )
+void FeedbackStyle::AddSignalInfo( FeedbackStyleInfo& styleInfo, SignalFeedbackInfo&& signalInfo )
{
bool updated = false;
- std::vector<SignalFeedbackInfo>::iterator iter;
+ SignalFeedbackInfoContainer::iterator iter;
// If info exists for the signal then update it, else add new
for( iter = styleInfo.mSignalFeedbackInfoList.begin(); iter != styleInfo.mSignalFeedbackInfoList.end(); ++iter )
if( !updated )
{
- styleInfo.mSignalFeedbackInfoList.push_back( signalInfo );
+ styleInfo.mSignalFeedbackInfoList.emplace_back( std::move( signalInfo ) );
}
}
#define __DALI_INTERNAL_FEEDBACK_STYLE_H__
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* @param [in] styleInfo The information will be stored here.
* @param [in] signalInfo The information to add.
*/
- void AddSignalInfo( FeedbackStyleInfo& styleInfo, SignalFeedbackInfo signalInfo );
+ void AddSignalInfo( FeedbackStyleInfo& styleInfo, SignalFeedbackInfo&& signalInfo );
/**
* Map a pattern string to feedback pattern ID.
$(toolkit_src_dir)/text/logical-model-impl.cpp \
$(toolkit_src_dir)/text/markup-processor.cpp \
$(toolkit_src_dir)/text/markup-processor-color.cpp \
+ $(toolkit_src_dir)/text/markup-processor-embedded-item.cpp \
$(toolkit_src_dir)/text/markup-processor-font.cpp \
$(toolkit_src_dir)/text/markup-processor-helper-functions.cpp \
$(toolkit_src_dir)/text/multi-language-support.cpp \
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
LayoutLength measuredWidth = childLayout->GetMeasuredWidth() - padding.end - padding.start;
LayoutLength measuredHeight = childLayout->GetMeasuredHeight() - padding.bottom - padding.top;
- return YGSize{
- .width = measuredWidth.AsDecimal(),
- .height = measuredHeight.AsDecimal(),
- };
+ // Create struct instance first and manually set params to support all compiler versions
+ YGSize ygSize;
+ ygSize.width = measuredWidth.AsDecimal();
+ ygSize.height = measuredHeight.AsDecimal();
+ return ygSize;
}
void FlexLayout::SetChildrenStyle()
DetermineNumberOfColumns( availableContentWidth );
// Locations define the start, end,top and bottom of each cell.
- mLocations->CalculateLocations( mNumColumns, availableContentWidth.AsInteger(), availableContentHeight.AsInteger(), childCount, 0, 0 );
+ mLocations->CalculateLocations( mNumColumns, availableContentWidth.AsInteger(), availableContentHeight.AsInteger(), childCount );
SetMeasuredDimensions( ResolveSizeAndState( widthSize, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK ),
void GridLocations::CalculateLocations( int numberOfColumns,
unsigned int availableWidth,
unsigned int availableHeight,
- unsigned int numberOfCells,
- unsigned int columnWidth,
- unsigned int rowHeight )
+ unsigned int numberOfCells )
{
DALI_ASSERT_DEBUG( numberOfColumns > 0 && "number of columns should be greater than 0" );
numberOfColumns = std::max ( numberOfColumns, 1 );
// If number of cells not cleanly dividable by colums, add another row to house remainder cells.
numberOfRows += (numberOfCells%numberOfColumns)?1:0;
- unsigned int maxColumnWidth = availableWidth / numberOfColumns;
+ // Safe as numberOfColumns is guaranteed to be > 0
+ unsigned int columnWidth = availableWidth / numberOfColumns;
- if( columnWidth > 0 )
- {
- // Column width supplied so use this unless exceeds available width.
- columnWidth = std::min( columnWidth, maxColumnWidth );
- }
- else
- {
- // Column width not supplied so use calculated value
- columnWidth = maxColumnWidth;
- }
+ unsigned int rowHeight = availableHeight;
- unsigned int maxRowHeight = availableHeight / numberOfRows;
-
- if( rowHeight > 0 )
- {
- // Column height supplied so use this unless exceeds available height.
- rowHeight = std::min( rowHeight, maxRowHeight );
- }
- else
+ if( numberOfRows > 0 )
{
- // Column height not supplied so use calculated value
- rowHeight = maxRowHeight;
+ rowHeight = availableHeight / numberOfRows;
}
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "ColumWidth[%d] RowHeight[%d] NumberOfRows[%d] NumberOfColumns[%d]\n",
} // namespace Internal
} // namespace Toolkit
-} // namespace Dali
\ No newline at end of file
+} // namespace Dali
* Uses the given parameters to calculate the x,y coordinates of each cell and cell size.
*/
void CalculateLocations( int numberOfColumns, unsigned int availableWidth,
- unsigned int availableHeight, unsigned int numberOfCells,
- unsigned int columnWidth, unsigned int rowHeight );
+ unsigned int availableHeight, unsigned int numberOfCells );
LocationVector GetLocations();
} // namespace Toolkit
} // namespace Dali
-#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_GRID_LOCATIONS_H
\ No newline at end of file
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_GRID_LOCATIONS_H
{
if( !layoutPositionData.animated )
{
- actor.SetPosition( layoutPositionData.left, layoutPositionData.top );
- actor.SetSize( layoutPositionData.right - layoutPositionData.left, layoutPositionData.bottom - layoutPositionData.top );
+ actor.SetX( layoutPositionData.left );
+ actor.SetY( layoutPositionData.top );
+
+ actor.SetProperty( Actor::Property::SIZE_WIDTH, layoutPositionData.right - layoutPositionData.left );
+ actor.SetProperty( Actor::Property::SIZE_HEIGHT, layoutPositionData.bottom - layoutPositionData.top );
}
else
{
- actor.SetPosition( actor.GetCurrentPosition() );
- actor.SetSize( actor.GetCurrentSize() );
+ actor.SetX( actor.GetCurrentPosition().x );
+ actor.SetY( actor.GetCurrentPosition().y );
+
+ actor.SetProperty( Actor::Property::SIZE_WIDTH, actor.GetCurrentSize().x );
+ actor.SetProperty( Actor::Property::SIZE_HEIGHT, actor.GetCurrentSize().y );
}
}
}
-#ifndef __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__
-#define __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__
+#ifndef DALI_TOOLKIT_TEXT_CHARACTER_RUN_H
+#define DALI_TOOLKIT_TEXT_CHARACTER_RUN_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
struct CharacterRun
{
+ CharacterRun()
+ : characterIndex{ 0u },
+ numberOfCharacters{ 0u }
+ {}
+
+ CharacterRun( CharacterIndex characterIndex, Length numberOfCharacters )
+ : characterIndex{ characterIndex },
+ numberOfCharacters{ numberOfCharacters }
+ {}
+
CharacterIndex characterIndex; ///< Index to the first character.
Length numberOfCharacters; ///< Number of characters in the run.
};
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__
+#endif // DALI_TOOLKIT_TEXT_CHARACTER_RUN_H
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_EMBEDDED_ITEM_H
+#define DALI_TOOLKIT_TEXT_EMBEDDED_ITEM_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief An embedded item within the text.
+ *
+ * The @e url of the image is optional. If there is no image
+ * the layout engine will use the @e width and @e height to
+ * create a space inside the text. This gap can be filled later.
+ *
+ * A color blending mode can be set. The default is NONE, the
+ * image will use its own color. If MULTIPLY is set, the color
+ * of the image will be multiplied by the color of the text.
+ */
+struct EmbeddedItem
+{
+ CharacterIndex characterIndex; ///< The character's index of the embedded item within the string.
+ char* url; ///< The url path of the image.
+ Length urlLength; ///< The length of the url.
+ unsigned int width; ///< The width of the item.
+ unsigned int height; ///< The height of the item.
+ ColorBlendingMode colorBlendingMode; ///< Whether the color of the image is multiplied by the color of the text.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_EMBEDDED_ITEM_H
-#ifndef __DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H__
-#define __DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H__
+#ifndef DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H
+#define DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
struct FontDescriptionRun
{
+ /**
+ * Default constructor to set the default values of bitfields
+ */
+ FontDescriptionRun()
+ : characterRun{},
+ familyName{ nullptr },
+ familyLength{ 0u },
+ weight{ FontWeight::NONE },
+ width{ FontWidth::NONE },
+ slant{ FontSlant::NONE },
+ size{ 0u },
+ familyDefined{ false },
+ weightDefined{ false },
+ widthDefined{ false },
+ slantDefined{ false },
+ sizeDefined{ false }
+ {}
+
+ FontDescriptionRun( const CharacterRun& characterRun,
+ char* familyName,
+ Length familyLength,
+ FontWeight weight,
+ FontWidth width,
+ FontSlant slant,
+ PointSize26Dot6 size,
+ bool familyDefined,
+ bool weightDefined,
+ bool widthDefined,
+ bool slantDefined,
+ bool sizeDefined )
+ : characterRun{ characterRun },
+ familyName{ familyName },
+ familyLength{ familyLength },
+ weight{ weight },
+ width{ width },
+ slant{ slant },
+ size{ size },
+ familyDefined{ familyDefined },
+ weightDefined{ weightDefined },
+ widthDefined{ widthDefined },
+ slantDefined{ slantDefined },
+ sizeDefined{ sizeDefined }
+ {}
+
CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
char* familyName; ///< The font's family name.
Length familyLength; ///< The length of the font's family name.
FontSlant slant; ///< The font's slant.
PointSize26Dot6 size; ///< The font's size.
- bool familyDefined : 1; ///< Whether the font's family is defined.
- bool weightDefined : 1; ///< Whether the font's weight is defined.
- bool widthDefined : 1; ///< Whether the font's width is defined.
- bool slantDefined : 1; ///< Whether the font's slant is defined.
- bool sizeDefined : 1; ///< Whether the font's size is defined.
+ bool familyDefined : 1; ///< Whether the font's family is defined.
+ bool weightDefined : 1; ///< Whether the font's weight is defined.
+ bool widthDefined : 1; ///< Whether the font's width is defined.
+ bool slantDefined : 1; ///< Whether the font's slant is defined.
+ bool sizeDefined : 1; ///< Whether the font's size is defined.
};
} // namespace Text
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H__
+#endif // DALI_TOOLKIT_TEXT_FONT_DESCRIPTION_RUN_H
-#ifndef __DALI_TOOLKIT_TEXT_FONT_RUN_H__
-#define __DALI_TOOLKIT_TEXT_FONT_RUN_H__
+#ifndef DALI_TOOLKIT_TEXT_FONT_RUN_H
+#define DALI_TOOLKIT_TEXT_FONT_RUN_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
-// EXTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-list.h>
-
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/character-run.h>
*/
struct FontRun
{
- CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
- FontId fontId; ///< Font id of the run.
- bool softwareItalic:1; ///< Whether font needs software support to draw italic style
- bool softwareBold:1; ///< Whether font needs software support to draw bold style
+ CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
+ FontId fontId; ///< Font id of the run.
+ bool isItalicRequired:1; ///< Whether the italic style is required.
+ bool isBoldRequired:1; ///< Whether the bold style is required.
};
} // namespace Text
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_FONT_RUN_H__
+#endif // DALI_TOOLKIT_TEXT_FONT_RUN_H
const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex );
Text::FontMetrics fontMetrics;
- metrics->GetFontMetrics( firstGlyph.fontId, fontMetrics );
+ if( 0u != firstGlyph.fontId )
+ {
+ metrics->GetFontMetrics( firstGlyph.fontId, fontMetrics );
+ }
+ else if( 0u != firstGlyph.index )
+ {
+ // It may be an embedded image.
+ fontMetrics.ascender = firstGlyph.height;
+ fontMetrics.descender = 0.f;
+ fontMetrics.height = fontMetrics.ascender;
+ }
+
+ const bool isItalicFont = metrics->HasItalicStyle( firstGlyph.fontId );
glyphMetrics.fontId = firstGlyph.fontId;
glyphMetrics.fontHeight = fontMetrics.height;
- glyphMetrics.width = firstGlyph.width;
+ glyphMetrics.width = firstGlyph.width + ( ( firstGlyph.isItalicRequired && !isItalicFont ) ? static_cast<unsigned int>( TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE * static_cast<float>( firstGlyph.height ) ) : 0u );
glyphMetrics.advance = firstGlyph.advance;
glyphMetrics.ascender = fontMetrics.ascender;
glyphMetrics.xBearing = firstGlyph.xBearing;
- for( unsigned int i = 1u; i < numberOfGlyphs; ++i )
+ if( 1u < numberOfGlyphs )
{
- const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i );
+ const float widthInit = firstGlyph.xBearing;
+
+ for( unsigned int i = 1u; i < numberOfGlyphs; ++i )
+ {
+ const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i );
+
+ glyphMetrics.width = glyphMetrics.advance + glyphInfo.xBearing + glyphInfo.width + ( ( firstGlyph.isItalicRequired && !isItalicFont ) ? static_cast<unsigned int>( TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE * static_cast<float>( firstGlyph.height ) ) : 0u );
+ glyphMetrics.advance += glyphInfo.advance;
+
+ }
- glyphMetrics.advance += glyphInfo.advance;
- glyphMetrics.width += glyphInfo.width;
+ glyphMetrics.width -= widthInit;
}
}
const float MAX_FLOAT = std::numeric_limits<float>::max();
const bool RTL = true;
-const float CURSOR_WIDTH = 1.f;
const float LINE_SPACING= 0.f;
} //namespace
characterIndex( 0u ),
numberOfGlyphs( 0u ),
numberOfCharacters( 0u ),
- length( 0.f ),
- extraBearing( 0.f ),
- extraWidth( 0.f ),
- wsLengthEndOfLine( 0.f ),
- ascender( 0.f ),
+ ascender( -MAX_FLOAT ),
descender( MAX_FLOAT ),
- lineSpacing( 0.f )
+ lineSpacing( 0.f ),
+ penX( 0.f ),
+ previousAdvance( 0.f ),
+ length( 0.f ),
+ wsLengthEndOfLine( 0.f )
{}
~LineLayout()
characterIndex = 0u;
numberOfGlyphs = 0u;
numberOfCharacters = 0u;
- length = 0.f;
- extraBearing = 0.f;
- extraWidth = 0.f;
- wsLengthEndOfLine = 0.f;
ascender = 0.f;
descender = MAX_FLOAT;
}
CharacterIndex characterIndex; ///< Index of the first character to be laid-out.
Length numberOfGlyphs; ///< The number of glyph which fit in one line.
Length numberOfCharacters; ///< The number of characters which fit in one line.
- float length; ///< The addition of the advance metric of all the glyphs which fit in one line.
- float extraBearing; ///< The extra width to be added to the line's length when the bearing of the first glyph is negative.
- float extraWidth; ///< The extra width to be added to the line's length when the bearing + width of the last glyph is greater than the advance.
- float wsLengthEndOfLine; ///< The length of the white spaces at the end of the line.
float ascender; ///< The maximum ascender of all fonts in the line.
float descender; ///< The minimum descender of all fonts in the line.
float lineSpacing; ///< The line spacing
+ float penX; ///< The origin of the current glyph ( is the start point plus the accumulation of all advances ).
+ float previousAdvance; ///< The advance of the previous glyph.
+ float length; ///< The current length of the line.
+ float wsLengthEndOfLine; ///< The length of the white spaces at the end of the line.
};
struct Engine::Impl
{
Impl()
: mLayout( Layout::Engine::SINGLE_LINE_BOX ),
- mCursorWidth( CURSOR_WIDTH ),
- mDefaultLineSpacing( LINE_SPACING ),
- mPreviousCharacterExtraWidth( 0.0f )
+ mCursorWidth( 0.f ),
+ mDefaultLineSpacing( LINE_SPACING )
{
}
/**
* @brief Updates the line ascender and descender with the metrics of a new font.
*
- * @param[in] fontId The id of the new font.
+ * @param[in] glyphMetrics The metrics of the new font.
* @param[in,out] lineLayout The line layout.
*/
- void UpdateLineHeight( FontId fontId, LineLayout& lineLayout )
+ void UpdateLineHeight( const GlyphMetrics& glyphMetrics, LineLayout& lineLayout )
{
Text::FontMetrics fontMetrics;
- mMetrics->GetFontMetrics( fontId, fontMetrics );
-
- // Sets the maximum ascender.
- if( fontMetrics.ascender > lineLayout.ascender )
+ if( 0u != glyphMetrics.fontId )
{
- lineLayout.ascender = fontMetrics.ascender;
+ mMetrics->GetFontMetrics( glyphMetrics.fontId, fontMetrics );
}
-
- // Sets the minimum descender.
- if( fontMetrics.descender < lineLayout.descender )
+ else
{
- lineLayout.descender = fontMetrics.descender;
+ fontMetrics.ascender = glyphMetrics.fontHeight;
+ fontMetrics.descender = 0.f;
+ fontMetrics.height = fontMetrics.ascender;
+ fontMetrics.underlinePosition = 0.f;
+ fontMetrics.underlineThickness = 1.f;
}
+ // Sets the maximum ascender.
+ lineLayout.ascender = std::max( lineLayout.ascender, fontMetrics.ascender );
+
+ // Sets the minimum descender.
+ lineLayout.descender = std::min( lineLayout.descender, fontMetrics.descender );
+
// set the line spacing
lineLayout.lineSpacing = mDefaultLineSpacing;
}
{
lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters;
lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs;
- lineLayout.length += tmpLineLayout.length;
- if( 0.f < tmpLineLayout.length )
- {
- lineLayout.length += lineLayout.wsLengthEndOfLine;
+ lineLayout.penX = tmpLineLayout.penX;
+ lineLayout.previousAdvance = tmpLineLayout.previousAdvance;
- lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
- }
- else
- {
- lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine;
- }
+ lineLayout.length = tmpLineLayout.length;
+ lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
- if( tmpLineLayout.ascender > lineLayout.ascender )
- {
- lineLayout.ascender = tmpLineLayout.ascender;
- }
+ // Sets the maximum ascender.
+ lineLayout.ascender = std::max( lineLayout.ascender, tmpLineLayout.ascender );
- if( tmpLineLayout.descender < lineLayout.descender )
- {
- lineLayout.descender = tmpLineLayout.descender;
- }
+ // Sets the minimum descender.
+ lineLayout.descender = std::min( lineLayout.descender, tmpLineLayout.descender );
}
/**
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " initial glyph index : %d\n", lineLayout.glyphIndex );
- // Stores temporary line layout which has not been added to the final line layout.
- LineLayout tmpLineLayout;
const bool isMultiline = mLayout == MULTI_LINE_BOX;
const bool isWordLaidOut = parameters.lineWrapMode == Text::LineWrap::WORD;
// Set the direction of the first character of the line.
lineLayout.characterIndex = *( parameters.glyphsToCharactersBuffer + lineLayout.glyphIndex );
- const CharacterDirection firstCharacterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + lineLayout.characterIndex );
- CharacterDirection previousCharacterDirection = firstCharacterDirection;
- const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
- float tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ // Stores temporary line layout which has not been added to the final line layout.
+ LineLayout tmpLineLayout;
+
+ // Initialize the start point.
- float tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
+ // The initial start point is zero. However it needs a correction according the 'x' bearing of the first glyph.
+ // i.e. if the bearing of the first glyph is negative it may exceed the boundaries of the text area.
+ // It needs to add as well space for the cursor if the text is in edit mode and extra space in case the text is outlined.
+ tmpLineLayout.penX = -glyphMetrics.xBearing + mCursorWidth + parameters.outlineWidth;
- tmpLineLayout.length += mCursorWidth; // Added to give some space to the cursor.
+ // Initialize the advance of the previous glyph.
+ tmpLineLayout.previousAdvance = 0.f;
// Calculate the line height if there is no characters.
FontId lastFontId = glyphMetrics.fontId;
- UpdateLineHeight( lastFontId, tmpLineLayout );
+ UpdateLineHeight( glyphMetrics, tmpLineLayout );
bool oneWordLaidOut = false;
// If it's different the ascender and descender need to be updated.
if( lastFontId != glyphMetrics.fontId )
{
- UpdateLineHeight( glyphMetrics.fontId, tmpLineLayout );
+ UpdateLineHeight( glyphMetrics, tmpLineLayout );
lastFontId = glyphMetrics.fontId;
}
const Character character = *( parameters.textBuffer + characterFirstIndex );
const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character );
- // Used to restore the temporal line layout when a single word does not fit in the control's width and is split by character.
- const float previousTmpLineLength = tmpLineLayout.length;
- const float previousTmpExtraBearing = tmpExtraBearing;
- const float previousTmpExtraWidth = tmpExtraWidth;
+ // Calculate the length of the line.
- // Get the character's direction.
- const CharacterDirection characterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + characterFirstIndex );
+ // Used to restore the temporal line layout when a single word does not fit in the control's width and is split by character.
+ const float previousTmpPenX = tmpLineLayout.penX;
+ const float previousTmpAdvance = tmpLineLayout.previousAdvance;
+ const float previousTmpLength = tmpLineLayout.length;
+ const float previousTmpWsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
- // Increase the accumulated length.
if( isWhiteSpace )
{
// Add the length to the length of white spaces at the end of the line.
}
else
{
- // Add as well any previous white space length.
- tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphMetrics.advance;
-
- // An extra space may be added to the line for the first and last glyph of the line.
- // If the bearing of the first glyph is negative, its positive value needs to be added.
- // If the bearing plus the width of the last glyph is greater than the advance, the difference
- // needs to be added.
-
- if( characterDirection == paragraphDirection )
- {
- if( RTL == characterDirection )
- {
- // <--
- // | Rrrrr|
- // or
- // | Rllrrr|
- // or
- // |lllrrrrr|
- // | Rll|
- //
-
- tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
- }
- else // LTR
- {
- // -->
- // |lllL |
- // or
- // |llrrL |
- // or
- // |lllllrrr|
- // |rrL |
- //
-
- const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
- tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
- tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
- }
- }
- else
- {
- if( characterDirection != previousCharacterDirection )
- {
- if( RTL == characterDirection )
- {
- // -->
- // |lllR |
-
- const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
- tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
- tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
- }
- else // LTR
- {
- // <--
- // | Lrrrr|
-
- tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
- }
- }
- else if( characterDirection == firstCharacterDirection )
- {
- if( RTL == characterDirection )
- {
- // -->
- // |llllllrr|
- // |Rr |
-
- tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
- }
- else // LTR
- {
- // <--
- // |llllrrrr|
- // | llL|
-
- const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
- tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
- tmpExtraWidth = std::max( mPreviousCharacterExtraWidth - glyphMetrics.advance, tmpExtraWidth );
- }
- }
- }
+ tmpLineLayout.penX += tmpLineLayout.previousAdvance + tmpLineLayout.wsLengthEndOfLine;
+ tmpLineLayout.previousAdvance = ( glyphMetrics.advance + parameters.interGlyphExtraAdvance );
+ tmpLineLayout.length = tmpLineLayout.penX + glyphMetrics.xBearing + glyphMetrics.width;
// Clear the white space length at the end of the line.
tmpLineLayout.wsLengthEndOfLine = 0.f;
}
- // If calculation is end but wsLengthEndOfLine is exist, it means end of text is space.
- // Merge remained length.
- if ( !parameters.ignoreSpaceAfterText && glyphIndex == lastGlyphOfParagraphPlusOne-1 && tmpLineLayout.wsLengthEndOfLine > 0 )
- {
- tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine;
- tmpLineLayout.wsLengthEndOfLine = 0u;
- }
-
- // Save the current extra width to compare with the next one
- mPreviousCharacterExtraWidth = tmpExtraWidth;
-
// Check if the accumulated length fits in the width of the box.
- if( ( completelyFill || isMultiline ) && !(parameters.ignoreSpaceAfterText && isWhiteSpace) &&
- ( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
+ if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
+ ( tmpLineLayout.length > parameters.boundingBox.width ) )
{
// Current word does not fit in the box's width.
if( !oneWordLaidOut || completelyFill )
{
tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
- tmpLineLayout.length = previousTmpLineLength;
- tmpExtraBearing = previousTmpExtraBearing;
- tmpExtraWidth = previousTmpExtraWidth;
+
+ tmpLineLayout.penX = previousTmpPenX;
+ tmpLineLayout.previousAdvance = previousTmpAdvance;
+ tmpLineLayout.length = previousTmpLength;
+ tmpLineLayout.wsLengthEndOfLine = previousTmpWsLengthEndOfLine;
}
// Add part of the word to the line layout.
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Current word does not fit.\n" );
}
- lineLayout.extraBearing = tmpExtraBearing;
- lineLayout.extraWidth = tmpExtraWidth;
-
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox.\n" );
return;
paragraphDirection = *( parameters.characterDirectionBuffer + 1u + characterLastIndex );
}
- lineLayout.extraBearing = tmpExtraBearing;
- lineLayout.extraWidth = tmpExtraWidth;
-
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Must break\n" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
tmpLineLayout.Clear();
}
- previousCharacterDirection = characterDirection;
glyphIndex += numberOfGLyphsInGroup;
}
- lineLayout.extraBearing = tmpExtraBearing;
- lineLayout.extraWidth = tmpExtraWidth;
-
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
}
void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
Length numberOfGlyphs,
float outlineWidth,
+ float interGlyphExtraAdvance,
Vector2* glyphPositionsBuffer )
{
// Traverse the glyphs and set the positions.
// so the penX position needs to be moved to the right.
const GlyphInfo& glyph = *glyphsBuffer;
- float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing + outlineWidth : outlineWidth;
-
+ float penX = -glyph.xBearing + mCursorWidth + outlineWidth;
for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
{
const GlyphInfo& glyph = *( glyphsBuffer + i );
Vector2& position = *( glyphPositionsBuffer + i );
- position.x = penX + glyph.xBearing;
+ position.x = std::round( penX + glyph.xBearing );
position.y = -glyph.yBearing;
- penX += glyph.advance;
+ penX += ( glyph.advance + interGlyphExtraAdvance );
}
}
const bool ellipsis = isAutoScrollEnabled ? ( penY - layout.descender > layoutParameters.boundingBox.height ) :
( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
( ( mLayout == SINGLE_LINE_BOX ) &&
- ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) );
+ ( layout.length > layoutParameters.boundingBox.width ) ) );
if( ellipsis )
{
lineRun->characterRun.characterIndex = ellipsisLayout.characterIndex;
lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
lineRun->width = ellipsisLayout.length;
- lineRun->extraLength = ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f;
+ lineRun->extraLength = std::ceil( ellipsisLayout.wsLengthEndOfLine );
lineRun->ascender = ellipsisLayout.ascender;
lineRun->descender = ellipsisLayout.descender;
lineRun->direction = !RTL;
SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
ellipsisLayout.numberOfGlyphs,
layoutParameters.outlineWidth,
+ layoutParameters.interGlyphExtraAdvance,
glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
}
if( isLastLine && !layoutParameters.isLastNewParagraph )
{
- const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
+ const float width = layout.length + layout.wsLengthEndOfLine;
if( MULTI_LINE_BOX == mLayout )
{
lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
}
else
{
- lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
- lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+ lineRun.width = layout.length;
+ lineRun.extraLength = std::ceil( layout.wsLengthEndOfLine );
}
+
+ // Rounds upward to avoid a non integer size.
+ lineRun.width = std::ceil( lineRun.width );
+
lineRun.ascender = layout.ascender;
lineRun.descender = layout.descender;
lineRun.direction = !RTL;
const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
Text::FontMetrics fontMetrics;
- mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+ if( 0u != glyphInfo.fontId )
+ {
+ mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+ }
LineRun& lineRun = *( linesBuffer + numberOfLines );
++numberOfLines;
UpdateLayoutSize( lines,
layoutSize );
+ // Rounds upward to avoid a non integer size.
+ layoutSize.height = std::ceil( layoutSize.height );
+
// Nothing else do if there are no glyphs to layout.
return false;
}
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText width too small!\n\n" );
lines.Resize( numberOfLines );
+
+ // Rounds upward to avoid a non integer size.
+ layoutSize.height = std::ceil( layoutSize.height );
+
return false;
}
SetGlyphPositions( layoutParameters.glyphsBuffer + index,
layout.numberOfGlyphs,
layoutParameters.outlineWidth,
+ layoutParameters.interGlyphExtraAdvance,
glyphPositionsBuffer + index - layoutParameters.startGlyphIndex );
// Updates the vertical pen's position.
lines.Resize( numberOfLines );
}
+ // Rounds upward to avoid a non integer size.
+ layoutSize.height = std::ceil( layoutSize.height );
+
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
return true;
const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap;
const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) );
- float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing - layoutParameters.outlineWidth : -layoutParameters.outlineWidth;
+ float penX = -glyph.xBearing + layoutParameters.outlineWidth + mCursorWidth;
Vector2* glyphPositionsBuffer = glyphPositions.Begin();
const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex );
Vector2& position = *( glyphPositionsBuffer + glyphIndex );
- position.x = penX + glyph.xBearing;
- penX += glyph.advance;
+ position.x = std::round( penX + glyph.xBearing );
+ penX += ( glyph.advance + layoutParameters.interGlyphExtraAdvance );
}
}
}
line.alignmentOffset -= line.extraLength;
}
- line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
+ line.alignmentOffset = std::floor( line.alignmentOffset ); // floor() avoids pixel alignment issues.
break;
}
case HorizontalAlignment::END:
Type mLayout;
float mCursorWidth;
float mDefaultLineSpacing;
- float mPreviousCharacterExtraWidth;
IntrusivePtr<Metrics> mMetrics;
};
estimatedNumberOfLines( 0u ),
lineWrapMode( lineWrapMode ),
outlineWidth( outlineWidth ),
- isLastNewParagraph( false ),
ignoreSpaceAfterText( ignoreSpaceAfterText ),
- matchSystemLanguageDirection ( matchSystemLanguageDirection )
+ matchSystemLanguageDirection ( matchSystemLanguageDirection ),
+ interGlyphExtraAdvance( 0.f ),
+ isLastNewParagraph( false )
{}
Vector2 boundingBox; ///< The size of the box containing the text.
Length estimatedNumberOfLines; ///< The estimated number of lines.
Text::LineWrap::Mode lineWrapMode; ///< The line wrap mode for moving to next line.
float outlineWidth; ///< The outline width.
- bool isLastNewParagraph:1; ///< Whether the last character is a new paragraph character.
bool ignoreSpaceAfterText:1; ///< Whether ignoring spaces after text or not. Default is true.
bool matchSystemLanguageDirection:1; ///< Whether match align for system language direction or not. Default is false.
+ float interGlyphExtraAdvance; ///< Extra advance added to each glyph.
+ bool isLastNewParagraph:1; ///< Whether the last character is a new paragraph character.
};
} // namespace Layout
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
it != endIt;
++it )
{
- delete (*it).familyName;
+ delete[] (*it).familyName;
}
fontDescriptionRuns.Clear();
}
+void FreeEmbeddedItems( Vector<EmbeddedItem>& embeddedItem )
+{
+ for( Vector<EmbeddedItem>::Iterator it = embeddedItem.Begin(),
+ endIt = embeddedItem.End();
+ it != endIt;
+ ++it )
+ {
+ EmbeddedItem& item = *it;
+ delete[] item.url;
+ }
+
+ embeddedItem.Clear();
+}
+
LogicalModelPtr LogicalModel::New()
{
return LogicalModelPtr( new LogicalModel() );
}
}
+void LogicalModel::ClearEmbeddedImages()
+{
+ FreeEmbeddedItems( mEmbeddedItems );
+}
+
LogicalModel::~LogicalModel()
{
ClearFontDescriptionRuns();
+ ClearEmbeddedImages();
}
LogicalModel::LogicalModel()
-#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
-#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
+#ifndef DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H
+#define DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
#include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/embedded-item.h>
#include <dali-toolkit/internal/text/font-run.h>
#include <dali-toolkit/internal/text/font-description-run.h>
#include <dali-toolkit/internal/text/paragraph-run.h>
Length numberOfCharacters,
Vector<ParagraphRunIndex>& paragraphs );
+ // Embedded images
+
+ /**
+ * @brief Clears the embedded images.
+ */
+ void ClearEmbeddedImages();
+
protected:
/**
Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
Vector<CharacterDirection> mCharacterDirections; ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ).
Vector<BidirectionalLineInfoRun> mBidirectionalLineInfo;
+ Vector<EmbeddedItem> mEmbeddedItems;
BidirectionalLineRunIndex mBidirectionalLineIndex; ///< The last fetched bidirectional line info.
};
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
+#endif // DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/embedded-item.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+const std::string XHTML_URL_ATTRIBUTE("url");
+const std::string XHTML_WIDTH_ATTRIBUTE("width");
+const std::string XHTML_HEIGHT_ATTRIBUTE("height");
+const std::string XHTML_COLOR_BLENDING_ATTRIBUTE("color-blending");
+
+const std::string NONE("none");
+const std::string MULTIPLY("multiply");
+}
+
+void ProcessEmbeddedItem( const Tag& tag, EmbeddedItem& embeddedItem )
+{
+ embeddedItem.url = nullptr;
+ embeddedItem.urlLength = 0u;
+ embeddedItem.width = 0u;
+ embeddedItem.height = 0u;
+ embeddedItem.colorBlendingMode = ColorBlendingMode::NONE;
+
+ for( Vector<Attribute>::ConstIterator it = tag.attributes.Begin(),
+ endIt = tag.attributes.End();
+ it != endIt;
+ ++it )
+ {
+ const Attribute& attribute( *it );
+ if( TokenComparison(XHTML_URL_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength ) )
+ {
+ embeddedItem.urlLength = attribute.valueLength;
+ embeddedItem.url = new char[embeddedItem.urlLength];
+ memcpy(embeddedItem.url, attribute.valueBuffer, embeddedItem.urlLength);
+ // The memory is freed when the font run is removed from the logical model.
+ }
+ else if (TokenComparison(XHTML_WIDTH_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ embeddedItem.width = StringToUint(attribute.valueBuffer);
+ }
+ else if (TokenComparison(XHTML_HEIGHT_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ embeddedItem.height = StringToUint(attribute.valueBuffer);
+ }
+ else if (TokenComparison(XHTML_COLOR_BLENDING_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength))
+ {
+ if (TokenComparison(MULTIPLY, attribute.valueBuffer, attribute.valueLength))
+ {
+ embeddedItem.colorBlendingMode = ColorBlendingMode::MULTIPLY;
+ }
+ }
+ }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
+
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+struct Tag;
+struct EmbeddedItem;
+
+/**
+ * @brief Retrieves the @e embedded @e item from the @p tag.
+ *
+ * @param[in] tag The embedded item tag and its attributes.
+ * @param[in,out] embeddedItem The embedded item.
+ */
+void ProcessEmbeddedItem( const Tag& tag, EmbeddedItem& embeddedItem );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
for( ; ( WHITE_SPACE != *stringBuffer ) && ( stringBuffer < stringEndBuffer ); ++stringBuffer );
}
+unsigned int StringToUint( const char* const uintStr )
+{
+ return static_cast<unsigned int>( strtoul( uintStr, NULL, 10 ) );
+}
+
unsigned int StringToHex( const char* const uintStr )
{
return static_cast<unsigned int>( strtoul( uintStr, NULL, 16 ) );
const char* const stringEndBuffer );
/**
+* @brief Converts a string into an unsigned int.
+*
+* @param[in] uintStr An unsigned int packed inside a string.
+*
+* @return The unsigned int value.
+*/
+unsigned int StringToUint( const char* const uintStr );
+
+/**
* @brief Converts a string into an hexadecimal unsigned int.
*
* @param[in] uintStr An hexadecimal unsigned int packed inside a string.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/character-set-conversion.h>
#include <dali-toolkit/internal/text/markup-processor-color.h>
+#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
#include <dali-toolkit/internal/text/markup-processor-font.h>
#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
#include <dali-toolkit/internal/text/xhtml-entities.h>
-
-
namespace Dali
{
const std::string XHTML_SHADOW_TAG("shadow");
const std::string XHTML_GLOW_TAG("glow");
const std::string XHTML_OUTLINE_TAG("outline");
+const std::string XHTML_ITEM_TAG("item");
const char LESS_THAN = '<';
const char GREATER_THAN = '>';
const char CHAR_ARRAY_END = '\0';
const char HEX_CODE = 'x';
-const char WHITE_SPACE = 0x20; // ASCII value of the white space.
+const char WHITE_SPACE = 0x20; // ASCII value of the white space.
// Range 1 0x0u < XHTML_DECIMAL_ENTITY_RANGE <= 0xD7FFu
// Range 2 0xE000u < XHTML_DECIMAL_ENTITY_RANGE <= 0xFFFDu
bool isQuotationOpen = false;
bool attributesFound = false;
tag.isEndTag = false;
+ bool isPreviousLessThan = false;
+ bool isPreviousSlash = false;
const char character = *markupStringBuffer;
if( LESS_THAN == character ) // '<'
{
tag.buffer = NULL;
tag.length = 0u;
+ isPreviousLessThan = true;
// if the iterator is pointing to a '<' character, then check if it's a mark-up tag is needed.
++markupStringBuffer;
{
const char character = *markupStringBuffer;
- if( SLASH == character ) // '/'
+ if( !isQuotationOpen && ( SLASH == character ) ) // '/'
{
- // if the tag has a '/' then it's an end or empty tag.
- tag.isEndTag = true;
+ if (isPreviousLessThan)
+ {
+ tag.isEndTag = true;
+ }
+ else
+ {
+ // if the tag has a '/' it may be an end tag.
+ isPreviousSlash = true;
+ }
- if( ( markupStringBuffer + 1u < markupStringEndBuffer ) && ( WHITE_SPACE >= *( markupStringBuffer + 1u ) ) && ( !isQuotationOpen ) )
+ isPreviousLessThan = false;
+ if( ( markupStringBuffer + 1u < markupStringEndBuffer ) && ( WHITE_SPACE >= *( markupStringBuffer + 1u ) ) )
{
++markupStringBuffer;
SkipWhiteSpace( markupStringBuffer, markupStringEndBuffer );
else if( GREATER_THAN == character ) // '>'
{
isTag = true;
+ if (isPreviousSlash)
+ {
+ tag.isEndTag = true;
+ }
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
else if( QUOTATION_MARK == character )
{
isQuotationOpen = !isQuotationOpen;
++tag.length;
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
else if( WHITE_SPACE >= character ) // ' '
{
// If it's not any of the 'special' characters then just add it to the tag string.
++tag.length;
+
+ isPreviousSlash = false;
+ isPreviousLessThan = false;
}
}
}
void ProcessMarkupString( const std::string& markupString, MarkupProcessData& markupProcessData )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "markupString: %s\n", markupString.c_str() );
+
// Reserve space for the plain text.
const Length markupStringSize = markupString.size();
markupProcessData.markupProcessedText.reserve( markupStringSize );
CharacterIndex characterIndex = 0u;
for( ; markupStringBuffer < markupStringEndBuffer; )
{
+ tag.attributes.Clear();
if( IsTag( markupStringBuffer,
markupStringEndBuffer,
tag ) )
// Pop the top of the stack and set the number of characters of the run.
}
} // <outline></outline>
+ else if (TokenComparison(XHTML_ITEM_TAG, tag.buffer, tag.length))
+ {
+ if (tag.isEndTag)
+ {
+ // Create an embedded item instance.
+ EmbeddedItem item;
+ item.characterIndex = characterIndex;
+ ProcessEmbeddedItem(tag, item);
+
+ markupProcessData.items.PushBack(item);
+
+ // Insert white space character that will be replaced by the item.
+ markupProcessData.markupProcessedText.append( 1u, WHITE_SPACE );
+ ++characterIndex;
+ }
+ }
} // end if( IsTag() )
else if( markupStringBuffer < markupStringEndBuffer )
{
else
{
markupProcessData.colorRuns.Resize( colorRunIndex );
+
+#ifdef DEBUG_ENABLED
+ for( unsigned int i=0; i<colorRunIndex; ++i )
+ {
+ ColorRun& run = markupProcessData.colorRuns[i];
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a );
+ }
+#endif
}
}
-#ifndef __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
-#define __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/embedded-item.h>
#include <dali-toolkit/internal/text/font-description-run.h>
namespace Dali
struct MarkupProcessData
{
MarkupProcessData( Vector<ColorRun>& colorRuns,
- Vector<FontDescriptionRun>& fontRuns )
+ Vector<FontDescriptionRun>& fontRuns,
+ Vector<EmbeddedItem>& items )
: colorRuns( colorRuns ),
fontRuns( fontRuns ),
+ items(items),
markupProcessedText()
{}
Vector<ColorRun>& colorRuns; ///< The color runs.
Vector<FontDescriptionRun>& fontRuns; ///< The font description runs.
-
+ Vector<EmbeddedItem>& items; ///< The embedded items.
std::string markupProcessedText; ///< The mark-up string.
};
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
return mFontClient.GetGlyphMetrics( array, size, mGlyphType, true ); // inline for performance
}
+ /**
+ * @brief Whether the font has Italic style.
+ *
+ * @param[in] fontId The font identifier.
+ *
+ * @return true if the font has italic style.
+ */
+ bool HasItalicStyle( FontId fontId ) const
+ {
+ return mFontClient.HasItalicStyle( fontId );
+ }
+
protected:
/**
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
currentFontRun.characterRun.characterIndex = startIndex;
currentFontRun.characterRun.numberOfCharacters = 0u;
currentFontRun.fontId = 0u;
+ currentFontRun.isBoldRequired = false;
+ currentFontRun.isItalicRequired = false;
// Get the font client.
TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
bool isPreviousEmojiScript = false;
- // Description of fallback font which is selected at current iteration.
- TextAbstraction::FontDescription selectedFontDescription;
-
CharacterIndex lastCharacter = startIndex + numberOfCharacters;
for( Length index = startIndex; index < lastCharacter; ++index )
{
// Get the current character.
const Character character = *( textBuffer + index );
- bool needSoftwareBoldening = false;
- bool needSoftwareItalic = false;
+ bool isItalicRequired = false;
+ bool isBoldRequired = false;
// new description for current character
TextAbstraction::FontDescription currentFontDescription;
currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters;
currentFontRun.characterRun.numberOfCharacters = 0u;
currentFontRun.fontId = fontId;
+ currentFontRun.isItalicRequired = false;
+ currentFontRun.isBoldRequired = false;
}
// If the given font is not valid, it means either:
}
#endif
- if( fontId != currentFontRun.fontId )
- {
- fontClient.GetDescription(fontId,selectedFontDescription);
- }
-
- // Developer sets bold to character but selected font cannot support it
- needSoftwareBoldening = ( currentFontDescription.weight >= TextAbstraction::FontWeight::BOLD ) && ( selectedFontDescription.weight < TextAbstraction::FontWeight::BOLD );
+ // Whether bols style is required.
+ isBoldRequired = ( currentFontDescription.weight >= TextAbstraction::FontWeight::BOLD );
- // Developer sets italic to character but selected font cannot support it
- needSoftwareItalic = ( currentFontDescription.slant == TextAbstraction::FontSlant::ITALIC ) && ( selectedFontDescription.slant < TextAbstraction::FontSlant::ITALIC );
+ // Whether italic style is required.
+ isItalicRequired = ( currentFontDescription.slant >= TextAbstraction::FontSlant::ITALIC );
// The font is now validated.
if( ( fontId != currentFontRun.fontId ) ||
isNewParagraphCharacter ||
// If font id is same as previous but style is diffrent, initialize new one
- ( ( fontId == currentFontRun.fontId ) && ( ( needSoftwareBoldening != currentFontRun.softwareBold ) || ( needSoftwareItalic != currentFontRun.softwareItalic ) ) ) )
+ ( ( fontId == currentFontRun.fontId ) && ( ( isBoldRequired != currentFontRun.isBoldRequired ) || ( isItalicRequired != currentFontRun.isItalicRequired ) ) ) )
{
// Current run needs to be stored and a new one initialized.
currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters;
currentFontRun.characterRun.numberOfCharacters = 0u;
currentFontRun.fontId = fontId;
- currentFontRun.softwareItalic = needSoftwareItalic;
- currentFontRun.softwareBold = needSoftwareBoldening;
+ currentFontRun.isBoldRequired = isBoldRequired;
+ currentFontRun.isItalicRequired = isItalicRequired;
}
// Add one more character to the run.
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
- const uint32_t outlineWidth,
+ const Toolkit::AtlasGlyphManager::GlyphStyle& style,
const PixelData& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
GlyphRecordEntry record;
record.mIndex = glyph.index;
- record.mOutlineWidth = outlineWidth;
record.mImageId = slot.mImageId;
record.mCount = 1;
+ record.mOutlineWidth = style.outline;
+ record.isItalic = style.isItalic;
+ record.isBold = style.isBold;
// Have glyph records been created for this fontId ?
bool foundGlyph = false;
}
bool AtlasGlyphManager::IsCached( Text::FontId fontId,
- Text::GlyphIndex index,
- uint32_t outlineWidth,
- Dali::Toolkit::AtlasManager::AtlasSlot& slot )
+ Text::GlyphIndex index,
+ const Toolkit::AtlasGlyphManager::GlyphStyle& style,
+ Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
fontGlyphRecordIt != mFontGlyphRecords.end();
glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
++glyphRecordIt )
{
- if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth )
+ if ( ( glyphRecordIt->mIndex == index ) &&
+ ( glyphRecordIt->mOutlineWidth == style.outline ) &&
+ ( glyphRecordIt->isItalic == style.isItalic ) &&
+ ( glyphRecordIt->isBold == style.isBold ) )
{
slot.mImageId = glyphRecordIt->mImageId;
slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
return mMetrics;
}
-void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta )
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, const Toolkit::AtlasGlyphManager::GlyphStyle& style, int32_t delta )
{
if( 0 != delta )
{
glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
++glyphRecordIt )
{
- if ( glyphRecordIt->mIndex == index && glyphRecordIt->mOutlineWidth == outlineWidth )
+ if ( ( glyphRecordIt->mIndex == index ) &&
+ ( glyphRecordIt->mOutlineWidth == style.outline ) &&
+ ( glyphRecordIt->isItalic == style.isItalic ) &&
+ ( glyphRecordIt->isBold == style.isBold ) )
{
glyphRecordIt->mCount += delta;
DALI_ASSERT_DEBUG( glyphRecordIt->mCount >= 0 && "Glyph ref-count should not be negative" );
-#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
-#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
+#ifndef DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H
+#define DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
struct GlyphRecordEntry
{
Text::GlyphIndex mIndex;
- uint32_t mOutlineWidth;
uint32_t mImageId;
int32_t mCount;
+ uint16_t mOutlineWidth;
+ bool isItalic:1;
+ bool isBold:1;
};
struct FontGlyphRecord
* @copydoc Toolkit::AtlasGlyphManager::Add
*/
void Add( const Text::GlyphInfo& glyph,
- const uint32_t outlineWidth,
+ const Toolkit::AtlasGlyphManager::GlyphStyle& style,
const PixelData& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
*/
bool IsCached( Text::FontId fontId,
Text::GlyphIndex index,
- uint32_t outlineWidth,
+ const Toolkit::AtlasGlyphManager::GlyphStyle& style,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
/**
/**
* @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount
*/
- void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta );
+ void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, const Toolkit::AtlasGlyphManager::GlyphStyle& style, int32_t delta );
/**
* @copydoc Toolkit::AtlasGlyphManager::GetTextures
} // namespace Dali
-#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
+#endif // DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
}
void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
- const uint32_t outlineWidth,
+ const GlyphStyle& style,
const PixelData& bitmap,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Add( glyph, outlineWidth, bitmap, slot );
+ GetImplementation(*this).Add( glyph, style, bitmap, slot );
}
void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
bool AtlasGlyphManager::IsCached( Text::FontId fontId,
Text::GlyphIndex index,
- uint32_t outlineWidth,
+ const GlyphStyle& style,
AtlasManager::AtlasSlot& slot )
{
- return GetImplementation(*this).IsCached( fontId, index, outlineWidth, slot );
+ return GetImplementation(*this).IsCached( fontId, index, style, slot );
}
void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight )
return GetImplementation(*this).GetMetrics();
}
-void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta )
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, const GlyphStyle& style, int32_t delta )
{
- GetImplementation(*this).AdjustReferenceCount( fontId, index, outlineWidth, delta );
+ GetImplementation(*this).AdjustReferenceCount( fontId, index, style, delta );
}
} // namespace Toolkit
-#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__
-#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__
+#ifndef DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H
+#define DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
AtlasManager::Metrics mAtlasMetrics; ///< metrics from the Atlas Manager
};
+ struct GlyphStyle
+ {
+ GlyphStyle()
+ : outline{ 0u },
+ isItalic{ false },
+ isBold{ false }
+ {}
+
+ uint16_t outline; ///< The outline width of this glyph
+ bool isItalic:1; ///< Whether the glyph is italic.
+ bool isBold:1; ///< Whether the glyph is bold.
+ };
+
/**
* @brief Create a AtlasGlyphManager handle.
*
* @brief Ask Atlas Manager to add a glyph
*
* @param[in] glyph glyph to add to an atlas
- * @param[in] outlineWidth the outline width of the glyph
+ * @param[in] style The style of this glyph
* @param[in] bitmap bitmap to use for glyph addition
* @param[out] slot information returned by atlas manager for addition
*/
void Add( const Text::GlyphInfo& glyph,
- const uint32_t outlineWidth,
+ const GlyphStyle& style,
const PixelData& bitmap,
AtlasManager::AtlasSlot& slot );
*
* @param[in] fontId The font that this glyph comes from
* @param[in] index The GlyphIndex of this glyph
- * @param[in] outlineWidth The outline width of this glyph
+ * @param[in] style The style of this glyph
* @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached )
*
* @return Whether glyph is cached or not ?
*/
bool IsCached( Text::FontId fontId,
Text::GlyphIndex index,
- uint32_t outlineWidth,
+ const GlyphStyle& style,
AtlasManager::AtlasSlot& slot );
/**
*
* @param[in] fontId The font this image came from
* @param[in] index The index of the glyph
- * @param[in] outlineWidth The outline width of the glyph
+ * @param[in] style The style of this glyph
* @param[in] delta The adjustment to make to the reference count
*/
- void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, uint32_t outlineWidth, int32_t delta );
+ void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, const GlyphStyle& style, int32_t delta );
private:
} // namespace Dali
-#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__
+#endif // DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
const float ONE( 1.0f );
const uint32_t DEFAULT_ATLAS_WIDTH = 512u;
const uint32_t DEFAULT_ATLAS_HEIGHT = 512u;
-const uint32_t NO_OUTLINE = 0;
+const uint16_t NO_OUTLINE = 0u;
}
struct AtlasRenderer::Impl
struct TextCacheEntry
{
TextCacheEntry()
- : mFontId( 0 ),
- mIndex( 0 ),
- mOutlineWidth( 0 ),
- mImageId( 0 )
+ : mFontId{ 0u },
+ mIndex{ 0u },
+ mImageId{ 0u },
+ mOutlineWidth{ 0u },
+ isItalic{ false },
+ isBold{ false }
{
}
FontId mFontId;
Text::GlyphIndex mIndex;
- uint32_t mOutlineWidth;
uint32_t mImageId;
+ uint16_t mOutlineWidth;
+ bool isItalic:1;
+ bool isBold:1;
};
Impl()
return false;
}
- void CacheGlyph( const GlyphInfo& glyph, FontId lastFontId, uint32_t outline, AtlasManager::AtlasSlot& slot )
+ void CacheGlyph( const GlyphInfo& glyph, FontId lastFontId, const AtlasGlyphManager::GlyphStyle& style, AtlasManager::AtlasSlot& slot )
{
- const bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, outline, slot ); // Check FontGlyphRecord vector for entry with glyph index and fontId
+ const bool glyphNotCached = !mGlyphManager.IsCached( glyph.fontId, glyph.index, style, 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" );
PixelData bitmap;
// Whether the glyph is an outline.
- const bool isOutline = 0u != outline;
+ const bool isOutline = 0u != style.outline;
// Whether the current glyph is a color one.
const bool isColorGlyph = mFontClient.IsColorGlyph( glyph.fontId, glyph.index );
mFontClient.CreateBitmap( glyph.fontId,
glyph.index,
- glyph.softwareItalic,
- glyph.softwareBold,
+ glyph.isItalicRequired,
+ glyph.isBoldRequired,
glyphBufferData,
- outline );
+ style.outline );
// Create the pixel data.
bitmap = PixelData::New( glyphBufferData.buffer,
blockSize.mNeededBlockHeight );
// Locate a new slot for our glyph
- mGlyphManager.Add( glyph, outline, bitmap, slot ); // slot will be 0 is glyph not added
+ mGlyphManager.Add( glyph, style, bitmap, slot ); // slot will be 0 is glyph not added
}
}
}
else
{
// We have 2+ copies of the same glyph
- mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, outline, 1 ); //increment
+ mGlyphManager.AdjustReferenceCount( glyph.fontId, glyph.index, style, 1 ); //increment
}
}
void GenerateMesh( const GlyphInfo& glyph,
const Vector2& position,
const Vector4& color,
- uint32_t outline,
+ uint16_t outline,
AtlasManager::AtlasSlot& slot,
bool underlineGlyph,
float currentUnderlinePosition,
textCacheEntry.mImageId = slot.mImageId;
textCacheEntry.mIndex = glyph.index;
textCacheEntry.mOutlineWidth = outline;
+ textCacheEntry.isItalic = glyph.isItalicRequired;
+ textCacheEntry.isBold = glyph.isBoldRequired;
newTextCache.PushBack( textCacheEntry );
const bool underlineEnabled = view.IsUnderlineEnabled();
const Vector4& underlineColor( view.GetUnderlineColor() );
const float underlineHeight = view.GetUnderlineHeight();
- const unsigned int outlineWidth = view.GetOutlineWidth();
+ const uint16_t outlineWidth = view.GetOutlineWidth();
const Vector4& outlineColor( view.GetOutlineColor() );
const bool isOutline = 0u != outlineWidth;
lastUnderlinedFontId = glyph.fontId;
} // underline
+ AtlasGlyphManager::GlyphStyle style;
+ style.isItalic = glyph.isItalicRequired;
+ style.isBold = glyph.isBoldRequired;
+
// Retrieves and caches the glyph's bitmap.
- CacheGlyph( glyph, lastFontId, NO_OUTLINE, slot );
+ CacheGlyph( glyph, lastFontId, style, slot );
// Retrieves and caches the outline glyph's bitmap.
if( isOutline )
{
- CacheGlyph( glyph, lastFontId, outlineWidth, slotOutline );
+ style.outline = outlineWidth;
+ CacheGlyph( glyph, lastFontId, style, slotOutline );
}
// Move the origin (0,0) of the mesh to the center of the actor
{
for( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter )
{
- mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, oldTextIter->mOutlineWidth, -1/*decrement*/ );
+ AtlasGlyphManager::GlyphStyle style;
+ style.outline = oldTextIter->mOutlineWidth;
+ style.isItalic = oldTextIter->isItalic;
+ style.isBold = oldTextIter->isBold;
+ mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, style, -1/*decrement*/ );
}
mTextCache.Resize( 0 );
}
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// Retrieves the layout size.
const Size& layoutSize = mModel->GetLayoutSize();
- const float outlineWidth = mModel->GetOutlineWidth();
+ const int outlineWidth = static_cast<int>( mModel->GetOutlineWidth() );
// Set the offset for the horizontal alignment according to the text direction and outline width.
int penX = 0;
}
case HorizontalAlignment::END:
{
- penX += ( textDirection == Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ) ? -outlineWidth * 2.0f : outlineWidth * 2.0f;
+ penX += ( textDirection == Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT ) ? -outlineWidth * 2 : outlineWidth * 2;
break;
}
}
// Set the offset for the vertical alignment.
- int penY = 0;
+ int penY = 0u;
switch( mModel->GetVerticalAlignment() )
{
{
// Generate the outline if enabled
- const float outlineWidth = mModel->GetOutlineWidth();
- if ( outlineWidth > Math::MACHINE_EPSILON_1 )
+ const uint16_t outlineWidth = mModel->GetOutlineWidth();
+ if ( outlineWidth != 0u )
{
// Create the image buffer for outline
Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer( bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs -1 );
}
// Retrieves the glyph's outline width
- float outlineWidth = mModel->GetOutlineWidth();
+ float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
if( style == Typesetter::STYLE_OUTLINE )
{
{
fontClient.CreateBitmap( glyphInfo->fontId,
glyphInfo->index,
- glyphInfo->softwareItalic,
- glyphInfo->softwareBold,
+ glyphInfo->isItalicRequired,
+ glyphInfo->isBoldRequired,
glyphData.glyphBitmap,
- outlineWidth );
+ static_cast<int>( outlineWidth ) );
}
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return mModel->GetOutlineColor();
}
-float ViewModel::GetOutlineWidth() const
+uint16_t ViewModel::GetOutlineWidth() const
{
return mModel->GetOutlineWidth();
}
glyphInfo = ellipsisGlyph;
// Change the 'x' and 'y' position of the ellipsis glyph.
-
- if( position.x > firstPenX )
- {
- position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
- }
-
position.x += ellipsisGlyph.xBearing;
position.y = penY - ellipsisGlyph.yBearing;
/**
* @copydoc ModelInterface::GetOutlineWidth()
*/
- virtual float GetOutlineWidth() const;
+ virtual uint16_t GetOutlineWidth() const;
/**
* @copydoc ModelInterface::GetBackgroundColor()
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// There is no way to know the number of glyphs before shaping the text.
// To avoid reallocations it's reserved space for a slightly biger number of glyphs than the number of characters.
+ GlyphInfo glyphInfo;
+ glyphInfo.isItalicRequired = false;
+ glyphInfo.isBoldRequired = false;
+
const Length currentNumberOfGlyphs = glyphs.Count();
const Length numberOfGlyphsReserved = static_cast<Length>( numberOfCharacters * 1.3f );
- glyphs.Resize( currentNumberOfGlyphs + numberOfGlyphsReserved );
+ glyphs.Resize( currentNumberOfGlyphs + numberOfGlyphsReserved, glyphInfo );
glyphToCharacterMap.Resize( currentNumberOfGlyphs + numberOfGlyphsReserved );
// The actual number of glyphs.
currentFontId = fontRun.fontId;
currentScript = scriptRun.script;
- bool softwareItalic = fontRun.softwareItalic;
- bool softwareBold = fontRun.softwareBold;
+ const bool isItalicRequired = fontRun.isItalicRequired;
+ const bool isBoldRequired = fontRun.isBoldRequired;
// Get the min index to the last character of both runs.
CharacterIndex currentIndex = min( fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters,
Vector<CharacterIndex> tmpGlyphToCharacterMap;
GlyphInfo glyphInfo;
- glyphInfo.softwareItalic = softwareItalic;
- glyphInfo.softwareBold = softwareBold;
+ glyphInfo.isItalicRequired = isItalicRequired;
+ glyphInfo.isBoldRequired = isBoldRequired;
tmpGlyphs.Resize( numberOfGlyphs, glyphInfo );
tmpGlyphToCharacterMap.Resize( numberOfGlyphs );
float ConvertToEven( float value )
{
int intValue(static_cast<int>( value ));
- return static_cast<float>(intValue % 2 == 0) ? intValue : (intValue + 1);
+ return static_cast<float>( intValue + ( intValue & 1 ) );
}
} // namespace
mImpl->mModel->mVisualModel->SetTextColor( mImpl->mTextColor );
MarkupProcessData markupProcessData( mImpl->mModel->mLogicalModel->mColorRuns,
- mImpl->mModel->mLogicalModel->mFontDescriptionRuns );
+ mImpl->mModel->mLogicalModel->mFontDescriptionRuns,
+ mImpl->mModel->mLogicalModel->mEmbeddedItems );
Length textSize = 0u;
const uint8_t* utf8 = NULL;
return mImpl->mModel->mVisualModel->GetOutlineColor();
}
-void Controller::SetOutlineWidth( unsigned int width )
+void Controller::SetOutlineWidth( uint16_t width )
{
mImpl->mModel->mVisualModel->SetOutlineWidth( width );
mImpl->RequestRelayout();
}
-unsigned int Controller::GetOutlineWidth() const
+uint16_t Controller::GetOutlineWidth() const
{
return mImpl->mModel->mVisualModel->GetOutlineWidth();
}
mImpl->mEventData->mInputStyle.textColor = color;
mImpl->mEventData->mInputStyle.isDefaultColor = false;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
mImpl->mEventData->mInputStyle.familyName = fontFamily;
mImpl->mEventData->mInputStyle.isFamilyDefined = true;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
mImpl->mEventData->mInputStyle.weight = weight;
mImpl->mEventData->mInputStyle.isWeightDefined = true;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
mImpl->mEventData->mInputStyle.width = width;
mImpl->mEventData->mInputStyle.isWidthDefined = true;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
mImpl->mEventData->mInputStyle.slant = slant;
mImpl->mEventData->mInputStyle.isSlantDefined = true;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
mImpl->mEventData->mInputStyle.size = size;
mImpl->mEventData->mInputStyle.isSizeDefined = true;
- if( EventData::SELECTING == mImpl->mEventData->mState )
+ if( EventData::SELECTING == mImpl->mEventData->mState || EventData::EDITING == mImpl->mEventData->mState || EventData::INACTIVE == mImpl->mEventData->mState )
{
CharacterIndex startOfSelectedText = 0u;
Length lengthOfSelectedText = 0u;
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", this, keyString.c_str() );
- // InputMethodContext is no longer handling key-events
- mImpl->ClearPreEditFlag();
+ if( !keyString.empty() )
+ {
+ // InputMethodContext is no longer handling key-events
+ mImpl->ClearPreEditFlag();
- InsertText( keyString, COMMIT );
- textChanged = true;
+ InsertText( keyString, COMMIT );
+
+ textChanged = true;
+
+ // Will request for relayout.
+ relayoutNeeded = true;
+ }
- // Will request for relayout.
- relayoutNeeded = true;
}
if ( ( mImpl->mEventData->mState != EventData::INTERRUPTED ) &&
mImpl->mModel->mLogicalModel->RetrieveStyle( styleIndex, style );
// Whether to add a new text color run.
- const bool addColorRun = ( style.textColor != mImpl->mEventData->mInputStyle.textColor );
+ const bool addColorRun = ( style.textColor != mImpl->mEventData->mInputStyle.textColor ) && !mImpl->mEventData->mInputStyle.isDefaultColor;
// Whether to add a new font run.
- const bool addFontNameRun = style.familyName != mImpl->mEventData->mInputStyle.familyName;
- const bool addFontWeightRun = style.weight != mImpl->mEventData->mInputStyle.weight;
- const bool addFontWidthRun = style.width != mImpl->mEventData->mInputStyle.width;
- const bool addFontSlantRun = style.slant != mImpl->mEventData->mInputStyle.slant;
- const bool addFontSizeRun = style.size != mImpl->mEventData->mInputStyle.size;
+ const bool addFontNameRun = ( style.familyName != mImpl->mEventData->mInputStyle.familyName ) && mImpl->mEventData->mInputStyle.isFamilyDefined;
+ const bool addFontWeightRun = ( style.weight != mImpl->mEventData->mInputStyle.weight ) && mImpl->mEventData->mInputStyle.isWeightDefined;
+ const bool addFontWidthRun = ( style.width != mImpl->mEventData->mInputStyle.width ) && mImpl->mEventData->mInputStyle.isWidthDefined;
+ const bool addFontSlantRun = ( style.slant != mImpl->mEventData->mInputStyle.slant ) && mImpl->mEventData->mInputStyle.isSlantDefined;
+ const bool addFontSizeRun = ( style.size != mImpl->mEventData->mInputStyle.size ) && mImpl->mEventData->mInputStyle.isSizeDefined ;
// Add style runs.
if( addColorRun )
// Reset buffers.
mImpl->mModel->mLogicalModel->mText.Clear();
+ // Reset the embedded images buffer.
+ mImpl->mModel->mLogicalModel->ClearEmbeddedImages();
+
// We have cleared everything including the placeholder-text
mImpl->PlaceholderCleared();
*
* @param[in] width The width in pixels of the outline, 0 indicates no outline
*/
- void SetOutlineWidth( unsigned int width );
+ void SetOutlineWidth( uint16_t width );
/**
* @brief Retrieves the width of an outline
*
* @return The width of the outline.
*/
- unsigned int GetOutlineWidth() const;
+ uint16_t GetOutlineWidth() const;
/**
* @brief Set the background color.
typedef TextAbstraction::LineBreakInfo LineBreakInfo; ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace).
typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace).
typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left.
+typedef TextAbstraction::ColorBlendingMode ColorBlendingMode; ///< Defines how a color is blended.
+typedef TextAbstraction::ColorIndex ColorIndex; ///< An index into an array of colors.
typedef uint32_t GlyphIndex; ///< An index into an array of glyphs.
typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs.
typedef uint32_t BidirectionalLineRunIndex; ///< An index into an array of bidirectional line info.
typedef uint32_t LineIndex; ///< An index into an array of lines.
typedef uint32_t ParagraphRunIndex; ///< An index into an array of paragraphs.
-typedef uint32_t ColorIndex; ///< An index into an array of colors.
} // namespace Text
bool& colorDefined,
Vector4& color,
bool& widthDefined,
- unsigned int& width )
+ uint16_t& width )
{
const unsigned int numberOfItems = underlinePropertiesMap.Count();
{
/// Width key.
widthDefined = true;
- width = static_cast<unsigned int>( valueGet.second.Get<float>() );
+ width = static_cast<uint16_t>( valueGet.second.Get<float>() );
}
}
{
Property::Map map;
- const std::string enabledStr = enabled ? TRUE_TOKEN : FALSE_TOKEN;
- map.Insert( ENABLE_KEY, enabledStr );
-
- std::string colorStr;
- Vector4ToColorString( color, colorStr );
- map.Insert( COLOR_KEY, colorStr );
-
- std::string heightStr;
- FloatToString( height, heightStr );
- map.Insert( HEIGHT_KEY, heightStr );
+ map.Insert( ENABLE_KEY, enabled );
+ map.Insert( COLOR_KEY, color );
+ map.Insert( HEIGHT_KEY, height );
value = map;
}
bool colorDefined = false;
Vector4 color;
bool widthDefined = false;
- unsigned int width = 0u;
+ uint16_t width = 0u;
bool empty = true;
else
{
const Vector4& color = controller->GetOutlineColor();
- const unsigned int width = controller->GetOutlineWidth();
+ const uint16_t width = controller->GetOutlineWidth();
Property::Map map;
map.Insert( COLOR_KEY, color );
#define DALI_TOOLKIT_TEXT_MODEL_INTERFACE_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* @return The width of the outline.
*/
- virtual float GetOutlineWidth() const = 0;
+ virtual uint16_t GetOutlineWidth() const = 0;
/**
* @brief Retrieves the background color.
return mVisualModel->GetOutlineColor();
}
-float Model::GetOutlineWidth() const
+uint16_t Model::GetOutlineWidth() const
{
return mVisualModel->GetOutlineWidth();
}
/**
* @copydoc ModelInterface::GetOutlineWidth()
*/
- virtual float GetOutlineWidth() const override;
+ virtual uint16_t GetOutlineWidth() const override;
/**
* @copydoc ModelInterface::GetBackgroundColor()
-#ifndef __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__
-#define __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__
+#ifndef DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H
+#define DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* @return The width of the outline.
*/
- virtual unsigned int GetOutlineWidth() const = 0;
+ virtual uint16_t GetOutlineWidth() const = 0;
};
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__
+#endif // DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return Vector4::ZERO;
}
-unsigned int View::GetOutlineWidth() const
+uint16_t View::GetOutlineWidth() const
{
if( mImpl->mVisualModel )
{
-#ifndef __DALI_TOOLKIT_TEXT_VIEW_H__
-#define __DALI_TOOLKIT_TEXT_VIEW_H__
+#ifndef DALI_TOOLKIT_TEXT_VIEW_H
+#define DALI_TOOLKIT_TEXT_VIEW_H
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineWidth()
*/
- virtual unsigned int GetOutlineWidth() const;
+ virtual uint16_t GetOutlineWidth() const;
private:
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_VIEW_H__
+#endif // DALI_TOOLKIT_TEXT_VIEW_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
mUnderlineHeight = height;
}
-void VisualModel::SetOutlineWidth( unsigned int width )
+void VisualModel::SetOutlineWidth( uint16_t width )
{
mOutlineWidth = width;
}
return mUnderlineHeight;
}
-unsigned int VisualModel::GetOutlineWidth() const
+uint16_t VisualModel::GetOutlineWidth() const
{
return mOutlineWidth;
}
mControlSize(),
mShadowOffset(),
mUnderlineHeight( 0.0f ),
- mOutlineWidth( 0u ),
mShadowBlurRadius( 0.0f ),
+ mOutlineWidth( 0u ),
mNaturalSize(),
mLayoutSize(),
mCachedLineIndex( 0u ),
-#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
-#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
+#ifndef DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H
+#define DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* @param[in] width The width in pixels of the outline, 0 indicates no outline
*/
- void SetOutlineWidth( unsigned int width );
+ void SetOutlineWidth( uint16_t width );
/**
* @brief Retrieves the width of an outline
*
* @return The width of the outline.
*/
- unsigned int GetOutlineWidth() const;
+ uint16_t GetOutlineWidth() const;
/**
* @brief Sets the text's background color.
Size mControlSize; ///< The size of the UI control.
Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow
float mUnderlineHeight; ///< Fixed height for underline to override font metrics.
- unsigned int mOutlineWidth; ///< Width of outline.
float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur.
+ uint16_t mOutlineWidth; ///< Width of outline.
private:
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
+#endif // DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H
{
case DevelAnimatedVectorImageVisual::Action::PLAY:
{
- if( IsOnStage() )
+ if( IsOnStage() && mVisualSize != Vector2::ZERO )
{
mVectorRasterizeThread.PlayAnimation();
if( attributes.Get( progress ) )
{
mVectorRasterizeThread.SetCurrentProgress( progress );
+
+ if( mVectorRasterizeThread.GetPlayState() != DevelImageVisual::PlayState::PLAYING )
+ {
+ mVectorRasterizeThread.RenderFrame();
+ Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger rendering
+ }
}
break;
}
#include <dali/devel-api/adaptor-framework/thread-settings.h>
#include <dali/integration-api/adaptors/adaptor.h>
#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
+#include <chrono>
+#include <thread>
namespace Dali
{
{
constexpr auto LOOP_FOREVER = -1;
+constexpr auto NANOSECONDS_PER_SECOND( 1e+9 );
#if defined(DEBUG_ENABLED)
Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" );
#endif
+inline void ResetToStart( bool& updated, uint32_t& value, uint32_t startValue, ConditionalWait& conditionalWait )
+{
+ ConditionalWait::ScopedLock lock( conditionalWait );
+ if( !updated )
+ {
+ value = startValue;
+ }
+}
+
} // unnamed namespace
VectorRasterizeThread::VectorRasterizeThread( const std::string& url )
: mUrl( url ),
mVectorRenderer(),
mConditionalWait(),
- mMutex(),
mResourceReadyTrigger(),
mAnimationFinishedTrigger(),
mPlayRange( 0.0f, 1.0f ),
mPlayState( DevelImageVisual::PlayState::STOPPED ),
+ mFrameDurationNanoSeconds( 0 ),
mProgress( 0.0f ),
+ mFrameRate( 60.0f ),
mCurrentFrame( 0 ),
mTotalFrame( 0 ),
mStartFrame( 0 ),
mNeedRender( false ),
mDestroyThread( false ),
mResourceReady( false ),
+ mCurrentFrameUpdated( false ),
mLogFactory( Dali::Adaptor::Get().GetLogFactory() )
{
mVectorRenderer = VectorAnimationRenderer::New( mUrl );
//TODO: check the return value
StartRender();
- while( IsThreadReady() )
+ while( !mDestroyThread )
{
Rasterize();
}
{
mPlayState = DevelImageVisual::PlayState::STOPPED;
- // Reset the current frame and the current loop
- mCurrentFrame = mStartFrame;
- mCurrentLoop = 0;
-
DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" );
}
}
ConditionalWait::ScopedLock lock( mConditionalWait );
mLoopCount = count;
-
- // Reset progress
- mCurrentLoop = 0;
}
}
{
mCurrentFrame = mStartFrame;
+ mCurrentFrameUpdated = true;
mResourceReady = false;
}
else if( mEndFrame < mCurrentFrame )
{
mCurrentFrame = mEndFrame;
+ mCurrentFrameUpdated = true;
mResourceReady = false;
}
}
if( mTotalFrame != 0 )
{
mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f );
+ mCurrentFrameUpdated = true;
}
mResourceReady = false;
return mResourceReady;
}
-bool VectorRasterizeThread::IsThreadReady()
-{
- ConditionalWait::ScopedLock lock( mConditionalWait );
-
- if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread )
- {
- DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" );
-
- mConditionalWait.Wait( lock );
- }
-
- // Keep the thread alive if this thread is NOT to be destroyed
- return !mDestroyThread;
-}
-
bool VectorRasterizeThread::StartRender()
{
//TODO: check the return value
mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame );
- DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d (%d, %d)]\n", mTotalFrame, mStartFrame, mEndFrame );
+ mFrameRate = mVectorRenderer.GetFrameRate();
+ mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate;
+
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartRender: Renderer is started [%d, %f fps]\n", mTotalFrame, mFrameRate );
return true;
}
void VectorRasterizeThread::Rasterize()
{
- DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [%d]\n", mCurrentFrame );
-
- bool needRender, resourceReady;
+ bool resourceReady;
+ uint32_t currentFrame, startFrame, endFrame;
+ int32_t loopCount;
+ DevelImageVisual::PlayState playState;
{
ConditionalWait::ScopedLock lock( mConditionalWait );
- needRender = mNeedRender;
+
+ if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread )
+ {
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait\n" );
+
+ if( mPlayState == DevelImageVisual::PlayState::STOPPED )
+ {
+ // Reset the current frame and the current loop
+ mCurrentFrame = mStartFrame;
+ mCurrentLoop = 0;
+ }
+ mConditionalWait.Wait( lock );
+ }
+
resourceReady = mResourceReady;
+ currentFrame = mCurrentFrame++;
+ startFrame = mStartFrame;
+ endFrame = mEndFrame;
+ loopCount = mLoopCount;
+ playState = mPlayState;
+
+ mNeedRender = false;
+ mResourceReady = true;
+ mCurrentFrameUpdated = false;
}
+ auto currentFrameStartTime = std::chrono::system_clock::now();
+
// Rasterize
- mVectorRenderer.Render( mCurrentFrame );
+ mVectorRenderer.Render( currentFrame );
- if( mPlayState == DevelImageVisual::PlayState::PLAYING )
+ if( playState == DevelImageVisual::PlayState::PLAYING )
{
- if( ++mCurrentFrame >= mEndFrame )
+ if( currentFrame >= endFrame )
{
- if( mLoopCount < 0 )
+ if( loopCount < 0 )
{
// repeat forever
- mCurrentFrame = mStartFrame;
+ ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it.
}
else
{
mCurrentLoop++;
- if( mCurrentLoop >= mLoopCount )
+ if( mCurrentLoop >= loopCount )
{
- // Animation is finished
mPlayState = DevelImageVisual::PlayState::STOPPED;
- // Reset the current frame and the current loop
- mCurrentFrame = mStartFrame;
- mCurrentLoop = 0;
-
+ // Animation is finished
mAnimationFinishedTrigger->Trigger();
DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" );
}
else
{
- mCurrentFrame = mStartFrame;
+ ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait );
}
}
}
}
- if( needRender )
- {
- mNeedRender = false;
- }
-
if( !resourceReady )
{
DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" );
mResourceReadyTrigger->Trigger();
- mResourceReady = true;
}
+
+ auto timeToSleepUntil = currentFrameStartTime + std::chrono::nanoseconds( mFrameDurationNanoSeconds );
+
+#if defined(DEBUG_ENABLED)
+ auto sleepDuration = std::chrono::duration_cast< std::chrono::milliseconds >( timeToSleepUntil - std::chrono::system_clock::now() );
+
+ DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [current = %d, sleep duration = %lld]\n", mCurrentFrame, sleepDuration.count() );
+#endif
+
+ std::this_thread::sleep_until( timeToSleepUntil );
}
} // namespace Internal
private:
/**
- * @brief Called by the rasterize thread which ensures a wait if required.
- * @return false if the thread should stop.
- */
- bool IsThreadReady();
-
- /**
* @brief Start rendering
*/
bool StartRender();
std::string mUrl;
VectorAnimationRenderer mVectorRenderer;
ConditionalWait mConditionalWait;
- Dali::Mutex mMutex;
std::unique_ptr< EventThreadCallback > mResourceReadyTrigger;
std::unique_ptr< EventThreadCallback > mAnimationFinishedTrigger;
Vector2 mPlayRange;
DevelImageVisual::PlayState mPlayState;
+ int64_t mFrameDurationNanoSeconds;
float mProgress;
+ float mFrameRate;
uint32_t mCurrentFrame;
uint32_t mTotalFrame;
uint32_t mStartFrame;
bool mNeedRender;
bool mDestroyThread; ///< Whether the thread be destroyed
bool mResourceReady;
+ bool mCurrentFrameUpdated;
const Dali::LogFactoryInterface& mLogFactory; ///< The log factory
};
mLoading( false ),
mOrientationCorrection( true )
{
+ EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
mLoading( false ),
mOrientationCorrection( true )
{
+ EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
ImageVisual::~ImageVisual()
atlasUploadObserver = this;
}
- auto preMultiplyOnLoad = mFactoryCache.GetPreMultiplyOnLoad() && !mImpl->mCustomShader
+ auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
: TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
{
if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() )
{
- bool preMultiplyOnLoad = mFactoryCache.GetPreMultiplyOnLoad() && !mImpl->mCustomShader ? true : false;
+ bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
mId = mLoader.Load( mImageUrl.GetUrl(), mBorder, preMultiplyOnLoad );
mBorder(),
mAuxiliaryImageAlpha( 0.0f )
{
+ EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
NPatchVisual::~NPatchVisual()
{
// First check if the requested Texture is cached.
const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
- maskTextureId, preMultiplyOnLoad );
+ maskTextureId );
TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
textureInfo.useAtlas, textureInfo.atlasRect,
textureInfo.preMultiplied );
}
+ break;
}
case CANCELLED:
case LOAD_FINISHED:
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlas,
- TextureId maskTextureId,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad)
+ TextureId maskTextureId )
{
std::string hashTarget( url );
const size_t urlLength = hashTarget.length();
}
}
- auto premultipliedIndex = hashTarget.length();
- hashTarget.resize( premultipliedIndex + 1 );
- switch( preMultiplyOnLoad )
- {
- case TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD:
- {
- hashTarget[ premultipliedIndex ] = 't';
- break;
- }
- case TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY:
- {
- hashTarget[ premultipliedIndex ] = 'f';
- break;
- }
- }
-
return Dali::CalculateHash( hashTarget );
}
{
// We have a match, now we check all the original parameters in case of a hash collision.
TextureInfo& textureInfo( mTextureInfoContainer[i] );
- auto multiplyOnLoad = textureInfo.preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD :
- TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
if( ( url == textureInfo.url.GetUrl() ) &&
( useAtlas == textureInfo.useAtlas ) &&
( maskTextureId == textureInfo.maskTextureId ) &&
( size == textureInfo.desiredSize ) &&
- ( preMultiplyOnLoad == multiplyOnLoad ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
samplingMode == textureInfo.samplingMode ) ) )
{
- // The found Texture is a match.
- cacheIndex = i;
- break;
+ // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
+ // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
+ if( ( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD && textureInfo.preMultiplyOnLoad )
+ || ( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY && !textureInfo.preMultiplied ) )
+ {
+ // The found Texture is a match.
+ cacheIndex = i;
+ break;
+ }
}
}
}
TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
- TextureId maskTextureId,
- MultiplyOnLoad preMultiplyOnLoad);
+ TextureId maskTextureId );
+
/**
* @brief Looks up a cached texture by its hash.
* If found, the given parameters are used to check there is no hash-collision.
#include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <dali/devel-api/adaptor-framework/singleton-service.h>
// INTERNAL INCLUDES
AccessibilityManager::AccessibilityActionSignalType& AccessibilityManager::ActionReadIndicatorInformationSignal()
{
+ DALI_LOG_WARNING_NOFN("DEPRECATION WARNING: ActionReadIndicatorInformationSignal is deprecated and will be removed from next release.\n" );
+
return GetImpl(*this).ActionReadIndicatorInformationSignal();
}
AccessibilityActionSignalType& ActionZoomSignal();
/**
+ * @DEPRECATED_1_4.9
* @brief This is emitted when accessibility action is received to read the information
* in the indicator (by two fingers triple tap).
*
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 4;
-const unsigned int TOOLKIT_MICRO_VERSION = 7;
+const unsigned int TOOLKIT_MICRO_VERSION = 13;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
**/
+
+/*
+ * In the original file, static analysis complains about return type from decode methods
+ * not being testable against Error constant (due to difference of type sizes).
+ *
+ * Modified decode methods to return error through an out parameter instead.
+ */
+
#ifndef BASEN_HPP
#define BASEN_HPP
return dictionary[index];
}
- static char decode(char c)
+ /*
+ * In the original file, error code was passed through return value, but used int -1 (out of range of char).
+ * Separated error value from return value by using out parameter.
+ */
+ static char decode(char c, bool& error)
{
+ error=false;
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
- return Error;
+ error=true;
+ return 0;
}
};
return dictionary[index];
}
- static char decode(char c)
+ /*
+ * In the original file, error code was passed through return value, but used int -1 (out of range of char).
+ * Separated error value from return value by using out parameter.
+ */
+ static char decode(char c, bool& error)
{
+ error=false;
if (c >= 'A' && c <= 'Z') {
return c - 'A';
} else if (c >= '2' && c <= '7') {
return c - '2' + 26;
}
- return Error;
+ error=true;
+ return 0;
}
};
return dictionary[index];
}
- static char decode(char c)
+ /*
+ * In the original file, error code was passed through return value, but used int -1 (out of range of char).
+ * Separated error value from return value by using out parameter.
+ */
+ static char decode(char c, bool& error)
{
+ error=false;
const int alph_len = 26;
if (c >= 'A' && c <= 'Z') {
return c - 'A';
} else if (c == '/') {
return c - '/' + alph_len * 2 + 11;
}
- return Error;
+ error=true;
+ return 0;
}
};
++iter;
continue;
}
- char value = ConversionTraits::decode(*iter);
- if (value == Error) {
+
+ /*
+ * In the original file, error value was out of range of return type.
+ * Separated error value from return value by using out parameter.
+ */
+ bool error=false;
+ char value = ConversionTraits::decode(*iter, error);
+ if (error) {
// malformed data, but let's go on...
++iter;
continue;
Name: dali-toolkit
Summary: Dali 3D engine Toolkit
-Version: 1.4.7
+Version: 1.4.13
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT