[dali_1.4.8] Merge branch 'devel/master' 95/200395/1
authorDavid Steele <david.steele@samsung.com>
Fri, 22 Feb 2019 14:33:05 +0000 (14:33 +0000)
committerDavid Steele <david.steele@samsung.com>
Fri, 22 Feb 2019 14:33:06 +0000 (14:33 +0000)
Change-Id: Ice0bb6f5889715e07f8be4bbca7c44957de85d1a

57 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp [changed mode: 0644->0755]
automated-tests/src/dali-toolkit/utc-Dali-AbsoluteLayout.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/text/bitmap-font.cpp [new file with mode: 0755]
dali-toolkit/devel-api/text/bitmap-font.h [new file with mode: 0755]
dali-toolkit/devel-api/text/text-utils-devel.cpp [new file with mode: 0755]
dali-toolkit/devel-api/text/text-utils-devel.h [new file with mode: 0755]
dali-toolkit/internal/file.list
dali-toolkit/internal/layouting/layout-controller-impl.cpp
dali-toolkit/internal/text/embedded-item.h [new file with mode: 0755]
dali-toolkit/internal/text/font-run.h
dali-toolkit/internal/text/glyph-metrics-helper.cpp [changed mode: 0644->0755]
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/logical-model-impl.cpp [changed mode: 0644->0755]
dali-toolkit/internal/text/logical-model-impl.h [changed mode: 0644->0755]
dali-toolkit/internal/text/markup-processor-embedded-item.cpp [new file with mode: 0755]
dali-toolkit/internal/text/markup-processor-embedded-item.h [new file with mode: 0755]
dali-toolkit/internal/text/markup-processor-helper-functions.cpp [changed mode: 0644->0755]
dali-toolkit/internal/text/markup-processor-helper-functions.h [changed mode: 0644->0755]
dali-toolkit/internal/text/markup-processor.cpp
dali-toolkit/internal/text/markup-processor.h [changed mode: 0644->0755]
dali-toolkit/internal/text/metrics.h [changed mode: 0644->0755]
dali-toolkit/internal/text/multi-language-support-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-typesetter.cpp
dali-toolkit/internal/text/rendering/view-model.cpp
dali-toolkit/internal/text/rendering/view-model.h
dali-toolkit/internal/text/shaper.cpp
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-definitions.h [changed mode: 0644->0755]
dali-toolkit/internal/text/text-effects-style.cpp
dali-toolkit/internal/text/text-model-interface.h
dali-toolkit/internal/text/text-model.cpp
dali-toolkit/internal/text/text-model.h
dali-toolkit/internal/text/text-view-interface.h [changed mode: 0644->0755]
dali-toolkit/internal/text/text-view.cpp [changed mode: 0644->0755]
dali-toolkit/internal/text/text-view.h [changed mode: 0644->0755]
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/texture-manager-impl.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/third-party/base-n/basen.hpp
packaging/dali-toolkit.spec

index 746299b..093f4fb 100755 (executable)
@@ -16,6 +16,7 @@ SET(TC_SOURCES
  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
index 84df087..e3ccad8 100755 (executable)
@@ -108,7 +108,8 @@ void CreateTextModel( const std::string& text,
   visualModel = VisualModel::New();
 
   MarkupProcessData markupProcessData( logicalModel->mColorRuns,
-                                       logicalModel->mFontDescriptionRuns );
+                                       logicalModel->mFontDescriptionRuns,
+                                       logicalModel->mEmbeddedItems );
 
   Length textSize = 0u;
   const uint8_t* utf8 = NULL;
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Circular.cpp
new file mode 100755 (executable)
index 0000000..4c94126
--- /dev/null
@@ -0,0 +1,893 @@
+/*
+ * 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;
+}
index 7007170..779eb56 100755 (executable)
@@ -36,6 +36,7 @@ using namespace Text;
 
 namespace
 {
+
   ///////////////////////////////////////////////////////////
 
   struct TokenComparisonData
@@ -182,9 +183,20 @@ namespace
 
     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;
old mode 100644 (file)
new mode 100755 (executable)
index 65a56da..b26d11b
@@ -55,8 +55,8 @@ struct GlyphInfoData
   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 )
@@ -93,11 +93,11 @@ 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;
   }
@@ -551,14 +551,14 @@ int UtcDaliTextSoftwareStyling(void)
 
   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, 4857u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, true },
+    { 2u, 7316u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true, true },
+    { 2u, 4364u, 0.f, 0.f, 0.f, 0.f, 15.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, 7316u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, false, true },
     { 2u, 4364u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true,  false },
   };
 
index 395e8f9..98ea974 100644 (file)
@@ -69,7 +69,6 @@ int UtcDaliLayouting_AbsoluteLayoutAssignment(void)
   END_TEST;
 }
 
-
 int UtcDaliLayouting_AbsoluteLayout01(void)
 {
   ToolkitTestApplication application;
@@ -120,3 +119,43 @@ int UtcDaliLayouting_AbsoluteLayout01(void)
 
   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;
+}
index 3e3b0e3..251b339 100755 (executable)
@@ -761,9 +761,9 @@ int UtcDaliTextEditorSetPropertyP(void)
   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 );
 
@@ -2596,9 +2596,9 @@ int utcDaliTextEditorUnderPropertyStringP(void)
   // 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 );
index 39cd605..8b1005f 100755 (executable)
@@ -806,9 +806,9 @@ int UtcDaliTextFieldSetPropertyP(void)
   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 );
index 551acf2..1208543 100755 (executable)
@@ -372,9 +372,9 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   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 );
@@ -465,9 +465,9 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
 
   // 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 );
 
@@ -479,9 +479,9 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   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 );
 
@@ -496,9 +496,9 @@ int UtcDaliToolkitTextLabelSetPropertyP(void)
   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 );
 
@@ -646,8 +646,8 @@ int UtcDaliToolkitTextlabelAtlasRenderP(void)
   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;
index c4df701..4e259e1 100644 (file)
@@ -1193,7 +1193,7 @@ int UtcDaliVisualGetPropertyMap10(void)
   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) );
index 115156e..25be5fa 100755 (executable)
@@ -47,6 +47,8 @@ devel_api_src_files = \
   $(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 \
@@ -182,7 +184,9 @@ devel_api_text_controls_header_files = \
   $(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
diff --git a/dali-toolkit/devel-api/text/bitmap-font.cpp b/dali-toolkit/devel-api/text/bitmap-font.cpp
new file mode 100755 (executable)
index 0000000..1e0e9c6
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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
diff --git a/dali-toolkit/devel-api/text/bitmap-font.h b/dali-toolkit/devel-api/text/bitmap-font.h
new file mode 100755 (executable)
index 0000000..ca068b4
--- /dev/null
@@ -0,0 +1,107 @@
+#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
diff --git a/dali-toolkit/devel-api/text/text-utils-devel.cpp b/dali-toolkit/devel-api/text/text-utils-devel.cpp
new file mode 100755 (executable)
index 0000000..3a286ad
--- /dev/null
@@ -0,0 +1,1360 @@
+/*
+ * 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;
+
+  // 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
diff --git a/dali-toolkit/devel-api/text/text-utils-devel.h b/dali-toolkit/devel-api/text/text-utils-devel.h
new file mode 100755 (executable)
index 0000000..83c6ea9
--- /dev/null
@@ -0,0 +1,201 @@
+#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
index 3a0375e..be6c728 100755 (executable)
@@ -135,6 +135,7 @@ toolkit_src_files = \
    $(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 \
index 9d0b947..b0637b3 100644 (file)
@@ -347,13 +347,19 @@ void LayoutController::PerformLayoutPositioning( LayoutPositionDataArray& layout
     {
       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 );
       }
     }
   }
diff --git a/dali-toolkit/internal/text/embedded-item.h b/dali-toolkit/internal/text/embedded-item.h
new file mode 100755 (executable)
index 0000000..496c207
--- /dev/null
@@ -0,0 +1,60 @@
+#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
index a787558..8190fcd 100644 (file)
@@ -1,8 +1,8 @@
-#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.
@@ -18,9 +18,6 @@
  *
  */
 
-// EXTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-list.h>
-
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-run.h>
 
@@ -38,10 +35,10 @@ namespace Text
  */
 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
@@ -50,4 +47,4 @@ struct FontRun
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_FONT_RUN_H__
+#endif // DALI_TOOLKIT_TEXT_FONT_RUN_H
old mode 100644 (file)
new mode 100755 (executable)
index 9c7c8ec..ef9098c
@@ -58,21 +58,41 @@ void GetGlyphsMetrics( GlyphIndex glyphIndex,
   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;
   }
 }
 
index f97a8ea..5594c01 100755 (executable)
@@ -117,26 +117,31 @@ struct Engine::Impl
   /**
    * @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;
   }
@@ -158,22 +163,18 @@ struct Engine::Impl
     {
       lineLayout.length += lineLayout.wsLengthEndOfLine;
 
-      lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
+    lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
     }
     else
     {
       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 );
   }
 
   /**
@@ -239,7 +240,7 @@ struct Engine::Impl
 
     // Calculate the line height if there is no characters.
     FontId lastFontId = glyphMetrics.fontId;
-    UpdateLineHeight( lastFontId, tmpLineLayout );
+    UpdateLineHeight( glyphMetrics, tmpLineLayout );
 
     bool oneWordLaidOut = false;
 
@@ -266,7 +267,7 @@ struct Engine::Impl
       // 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;
       }
 
@@ -572,7 +573,7 @@ struct Engine::Impl
     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 )
     {
@@ -613,7 +614,7 @@ struct Engine::Impl
       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 > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f );
       lineRun->ascender = ellipsisLayout.ascender;
       lineRun->descender = ellipsisLayout.descender;
       lineRun->direction = !RTL;
@@ -679,8 +680,12 @@ struct Engine::Impl
     else
     {
       lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
-      lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+      lineRun.extraLength = std::ceil( ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f );
     }
+
+    // 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;
@@ -716,7 +721,10 @@ struct Engine::Impl
     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;
@@ -832,6 +840,9 @@ struct Engine::Impl
       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;
     }
@@ -910,6 +921,10 @@ struct Engine::Impl
         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;
       }
 
@@ -1041,6 +1056,9 @@ struct Engine::Impl
       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;
old mode 100644 (file)
new mode 100755 (executable)
index 9b66925..6fbabb1
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -44,6 +44,20 @@ void FreeFontFamilyNames( Vector<FontDescriptionRun>& fontDescriptionRuns )
   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() );
@@ -550,9 +564,15 @@ void LogicalModel::FindParagraphs( CharacterIndex index,
   }
 }
 
+void LogicalModel::ClearEmbeddedImages()
+{
+  FreeEmbeddedItems( mEmbeddedItems );
+}
+
 LogicalModel::~LogicalModel()
 {
   ClearFontDescriptionRuns();
+  ClearEmbeddedImages();
 }
 
 LogicalModel::LogicalModel()
old mode 100644 (file)
new mode 100755 (executable)
index 9f2fa31..b2fc5a1
@@ -1,8 +1,8 @@
-#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.
@@ -27,6 +27,7 @@
 #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>
@@ -177,6 +178,13 @@ public:
                        Length numberOfCharacters,
                        Vector<ParagraphRunIndex>& paragraphs );
 
+  // Embedded images
+
+  /**
+   * @brief Clears the embedded images.
+   */
+  void ClearEmbeddedImages();
+
 protected:
 
   /**
@@ -210,6 +218,7 @@ public:
   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.
 };
@@ -220,4 +229,4 @@ public:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__
+#endif // DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H
diff --git a/dali-toolkit/internal/text/markup-processor-embedded-item.cpp b/dali-toolkit/internal/text/markup-processor-embedded-item.cpp
new file mode 100755 (executable)
index 0000000..7751c01
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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
diff --git a/dali-toolkit/internal/text/markup-processor-embedded-item.h b/dali-toolkit/internal/text/markup-processor-embedded-item.h
new file mode 100755 (executable)
index 0000000..6333c35
--- /dev/null
@@ -0,0 +1,47 @@
+#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
old mode 100644 (file)
new mode 100755 (executable)
index 76d9a6a..6c133ae
@@ -92,6 +92,11 @@ void JumpToWhiteSpace( const char*& stringBuffer,
   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 ) );
old mode 100644 (file)
new mode 100755 (executable)
index d1ecbc8..2b0cafb
@@ -95,6 +95,15 @@ void JumpToWhiteSpace( const char*& stringBuffer,
                        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.
index 25b4616..4565b9d 100755 (executable)
 // 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
 {
 
@@ -53,6 +52,7 @@ const std::string XHTML_U_TAG("u");
 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   = '>';
@@ -66,7 +66,7 @@ const char SEMI_COLON     = ';';
 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
@@ -310,12 +310,15 @@ bool IsTag( const char*& markupStringBuffer,
   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;
@@ -327,12 +330,20 @@ bool IsTag( const char*& 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 );
@@ -342,11 +353,21 @@ bool IsTag( const char*& markupStringBuffer,
         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 ) // ' '
         {
@@ -366,6 +387,9 @@ bool IsTag( const char*& markupStringBuffer,
 
           // If it's not any of the 'special' characters then just add it to the tag string.
           ++tag.length;
+
+          isPreviousSlash = false;
+          isPreviousLessThan = false;
         }
       }
     }
@@ -466,6 +490,8 @@ bool XHTMLNumericEntityToUtf8 ( const char* markupText, char* utf8 )
 
 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 );
@@ -489,6 +515,7 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
   CharacterIndex characterIndex = 0u;
   for( ; markupStringBuffer < markupStringEndBuffer; )
   {
+    tag.attributes.Clear();
     if( IsTag( markupStringBuffer,
                markupStringEndBuffer,
                tag ) )
@@ -654,6 +681,22 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
           // 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 )
     {
@@ -753,6 +796,14 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
   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
   }
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 0c43300..de66e7f
@@ -1,8 +1,8 @@
-#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.
@@ -24,6 +24,7 @@
 
 // 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
@@ -41,15 +42,17 @@ namespace Text
 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.
 };
 
@@ -67,4 +70,4 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
old mode 100644 (file)
new mode 100755 (executable)
index ad4ed41..868dba3
@@ -87,6 +87,18 @@ public:
     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:
 
   /**
index 607d159..81d815c 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -435,6 +435,8 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
   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();
@@ -448,16 +450,13 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
   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;
@@ -536,6 +535,8 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       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:
@@ -676,22 +677,17 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     }
 #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.
 
@@ -706,8 +702,8 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
       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.
index 957fd8e..3fd324d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -44,7 +44,7 @@ AtlasGlyphManager::AtlasGlyphManager()
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
-                             const uint32_t outlineWidth,
+                             const Toolkit::AtlasGlyphManager::GlyphStyle& style,
                              const PixelData& bitmap,
                              Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
@@ -63,9 +63,11 @@ void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
 
   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;
@@ -99,9 +101,9 @@ void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
 }
 
 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();
@@ -113,7 +115,10 @@ bool AtlasGlyphManager::IsCached( Text::FontId fontId,
             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 );
@@ -174,7 +179,7 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
   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 )
   {
@@ -190,7 +195,10 @@ void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIn
               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" );
index 0d32834..3d2613e 100644 (file)
@@ -1,8 +1,8 @@
-#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.
@@ -51,9 +51,11 @@ public:
   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
@@ -71,7 +73,7 @@ public:
    * @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 );
 
@@ -87,7 +89,7 @@ public:
    */
   bool IsCached( Text::FontId fontId,
                  Text::GlyphIndex index,
-                 uint32_t outlineWidth,
+                 const Toolkit::AtlasGlyphManager::GlyphStyle& style,
                  Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
   /**
@@ -108,7 +110,7 @@ public:
   /**
    * @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
@@ -158,4 +160,4 @@ inline Internal::AtlasGlyphManager& GetImplementation(Toolkit::AtlasGlyphManager
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
+#endif // DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H
index bd6850d..357f431 100644 (file)
@@ -1,5 +1,5 @@
  /*
- * 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.
@@ -69,11 +69,11 @@ AtlasGlyphManager::AtlasGlyphManager(Internal::AtlasGlyphManager *impl)
 }
 
 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,
@@ -87,10 +87,10 @@ 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 )
@@ -118,9 +118,9 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
   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
index c41415e..592017b 100644 (file)
@@ -1,8 +1,8 @@
-#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.
@@ -55,6 +55,19 @@ public:
     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.
    *
@@ -80,12 +93,12 @@ public:
    * @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 );
 
@@ -105,14 +118,14 @@ public:
    *
    * @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 );
 
   /**
@@ -164,10 +177,10 @@ public:
    *
    * @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:
 
@@ -179,4 +192,4 @@ private:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__
+#endif // DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H
index e06b958..dddb301 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -93,7 +93,7 @@ const float HALF( 0.5f );
 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
@@ -168,17 +168,21 @@ 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()
@@ -211,9 +215,9 @@ struct AtlasRenderer::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" );
 
@@ -243,7 +247,7 @@ struct AtlasRenderer::Impl
       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 );
@@ -257,10 +261,10 @@ struct AtlasRenderer::Impl
 
         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,
@@ -292,21 +296,21 @@ struct AtlasRenderer::Impl
                                          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,
@@ -324,6 +328,8 @@ struct AtlasRenderer::Impl
     textCacheEntry.mImageId = slot.mImageId;
     textCacheEntry.mIndex = glyph.index;
     textCacheEntry.mOutlineWidth = outline;
+    textCacheEntry.isItalic = glyph.isItalicRequired;
+    textCacheEntry.isBold = glyph.isBoldRequired;
 
     newTextCache.PushBack( textCacheEntry );
 
@@ -445,7 +451,7 @@ struct AtlasRenderer::Impl
     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;
 
@@ -528,13 +534,18 @@ struct AtlasRenderer::Impl
           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
@@ -655,7 +666,11 @@ struct AtlasRenderer::Impl
   {
     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 );
   }
index 8018054..de6b712 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -285,7 +285,7 @@ PixelData Typesetter::Render( const Vector2& size, Toolkit::DevelText::TextDirec
   // 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;
@@ -304,13 +304,13 @@ PixelData Typesetter::Render( const Vector2& size, Toolkit::DevelText::TextDirec
     }
     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() )
   {
@@ -390,8 +390,8 @@ PixelData Typesetter::Render( const Vector2& size, Toolkit::DevelText::TextDirec
   {
 
     // 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 );
@@ -505,7 +505,7 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth
     }
 
     // Retrieves the glyph's outline width
-    float outlineWidth = mModel->GetOutlineWidth();
+    float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
 
     if( style == Typesetter::STYLE_OUTLINE )
     {
@@ -672,10 +672,10 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth
       {
         fontClient.CreateBitmap( glyphInfo->fontId,
                                  glyphInfo->index,
-                                 glyphInfo->softwareItalic,
-                                 glyphInfo->softwareBold,
+                                 glyphInfo->isItalicRequired,
+                                 glyphInfo->isBoldRequired,
                                  glyphData.glyphBitmap,
-                                 outlineWidth );
+                                 static_cast<int>( outlineWidth ) );
       }
 
 
index 3543fce..9be8215 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -203,7 +203,7 @@ const Vector4& ViewModel::GetOutlineColor() const
   return mModel->GetOutlineColor();
 }
 
-float ViewModel::GetOutlineWidth() const
+uint16_t ViewModel::GetOutlineWidth() const
 {
   return mModel->GetOutlineWidth();
 }
index 65cf48c..bc7d45f 100755 (executable)
@@ -191,7 +191,7 @@ public:
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
-  virtual float GetOutlineWidth() const;
+  virtual uint16_t GetOutlineWidth() const;
 
   /**
    * @copydoc ModelInterface::GetBackgroundColor()
index 624c443..593e1e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -111,9 +111,13 @@ void ShapeText( const Vector<Character>& text,
   // 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.
@@ -137,8 +141,8 @@ void ShapeText( const Vector<Character>& text,
 
     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,
@@ -174,8 +178,8 @@ void ShapeText( const Vector<Character>& text,
     Vector<CharacterIndex> tmpGlyphToCharacterMap;
 
     GlyphInfo glyphInfo;
-    glyphInfo.softwareItalic = softwareItalic;
-    glyphInfo.softwareBold = softwareBold;
+    glyphInfo.isItalicRequired = isItalicRequired;
+    glyphInfo.isBoldRequired = isBoldRequired;
 
     tmpGlyphs.Resize( numberOfGlyphs, glyphInfo );
     tmpGlyphToCharacterMap.Resize( numberOfGlyphs );
index 1468941..6e6bfaa 100755 (executable)
@@ -65,7 +65,7 @@ const char * const PLACEHOLDER_ELLIPSIS = "ellipsis";
 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
@@ -556,7 +556,8 @@ void Controller::SetText( const std::string& text )
     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;
@@ -1241,14 +1242,14 @@ const Vector4& Controller::GetOutlineColor() const
   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();
 }
@@ -3939,6 +3940,9 @@ void Controller::ResetText()
   // 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();
 
index 33f1f8f..592b19d 100755 (executable)
@@ -861,14 +861,14 @@ public: // Default style & Input style
    *
    * @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.
old mode 100644 (file)
new mode 100755 (executable)
index 2884119..e98e08e
@@ -51,6 +51,8 @@ typedef TextAbstraction::Script             Script;             ///< The charact
 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.
@@ -60,7 +62,6 @@ typedef uint32_t                         BidirectionalRunIndex;     ///< An inde
 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
 
index f65655b..d5f8ff1 100755 (executable)
@@ -175,7 +175,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
                                bool& colorDefined,
                                Vector4& color,
                                bool& widthDefined,
-                               unsigned int& width )
+                               uint16_t& width )
 {
   const unsigned int numberOfItems = underlinePropertiesMap.Count();
 
@@ -194,7 +194,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
     {
       /// Width key.
       widthDefined = true;
-      width = static_cast<unsigned int>( valueGet.second.Get<float>() );
+      width = static_cast<uint16_t>( valueGet.second.Get<float>() );
     }
   }
 
@@ -358,16 +358,9 @@ void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, E
         {
           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;
         }
@@ -594,7 +587,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu
         bool colorDefined = false;
         Vector4 color;
         bool widthDefined = false;
-        unsigned int width = 0u;
+        uint16_t width = 0u;
 
         bool empty = true;
 
@@ -675,7 +668,7 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff
         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 );
index f2a82ad..a301d03 100755 (executable)
@@ -2,7 +2,7 @@
 #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.
@@ -238,7 +238,7 @@ public:
    *
    * @return The width of the outline.
    */
-  virtual float GetOutlineWidth() const = 0;
+  virtual uint16_t GetOutlineWidth() const = 0;
 
   /**
    * @brief Retrieves the background color.
index 474b3ae..da87e0c 100755 (executable)
@@ -162,7 +162,7 @@ const Vector4& Model::GetOutlineColor() const
   return mVisualModel->GetOutlineColor();
 }
 
-float Model::GetOutlineWidth() const
+uint16_t Model::GetOutlineWidth() const
 {
   return mVisualModel->GetOutlineWidth();
 }
index f4fbd7b..3230e47 100755 (executable)
@@ -191,7 +191,7 @@ public:
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
-  virtual float GetOutlineWidth() const override;
+  virtual uint16_t GetOutlineWidth() const override;
 
   /**
    * @copydoc ModelInterface::GetBackgroundColor()
old mode 100644 (file)
new mode 100755 (executable)
index 96f9005..9e8020c
@@ -1,8 +1,8 @@
-#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.
@@ -185,7 +185,7 @@ public:
    *
    * @return The width of the outline.
    */
-  virtual unsigned int GetOutlineWidth() const = 0;
+  virtual uint16_t GetOutlineWidth() const = 0;
 
 };
 
@@ -195,4 +195,4 @@ public:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__
+#endif // DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H
old mode 100644 (file)
new mode 100755 (executable)
index 62c0008..929c17c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -411,7 +411,7 @@ const Vector4& View::GetOutlineColor() const
   return Vector4::ZERO;
 }
 
-unsigned int View::GetOutlineWidth() const
+uint16_t View::GetOutlineWidth() const
 {
   if( mImpl->mVisualModel )
   {
old mode 100644 (file)
new mode 100755 (executable)
index 51426de..e7d1942
@@ -1,8 +1,8 @@
-#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.
@@ -139,7 +139,7 @@ public:
   /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineWidth()
    */
-  virtual unsigned int GetOutlineWidth() const;
+  virtual uint16_t GetOutlineWidth() const;
 
 private:
 
@@ -160,4 +160,4 @@ private:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_VIEW_H__
+#endif // DALI_TOOLKIT_TEXT_VIEW_H
index bd567a4..3b1f5b7 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -373,7 +373,7 @@ void VisualModel::SetUnderlineHeight( float height )
   mUnderlineHeight = height;
 }
 
-void VisualModel::SetOutlineWidth( unsigned int width )
+void VisualModel::SetOutlineWidth( uint16_t width )
 {
   mOutlineWidth = width;
 }
@@ -428,7 +428,7 @@ float VisualModel::GetUnderlineHeight() const
   return mUnderlineHeight;
 }
 
-unsigned int VisualModel::GetOutlineWidth() const
+uint16_t VisualModel::GetOutlineWidth() const
 {
   return mOutlineWidth;
 }
@@ -473,8 +473,8 @@ VisualModel::VisualModel()
   mControlSize(),
   mShadowOffset(),
   mUnderlineHeight( 0.0f ),
-  mOutlineWidth( 0u ),
   mShadowBlurRadius( 0.0f ),
+  mOutlineWidth( 0u ),
   mNaturalSize(),
   mLayoutSize(),
   mCachedLineIndex( 0u ),
index 1cb6b4d..4b82cef 100755 (executable)
@@ -1,8 +1,8 @@
-#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.
@@ -320,14 +320,14 @@ public:
    *
    * @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.
@@ -398,8 +398,8 @@ public:
   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:
 
@@ -422,4 +422,4 @@ public:
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
+#endif // DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H
index bbef5e4..fad510b 100644 (file)
@@ -953,39 +953,41 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur
                                   const Vector4& atlasRectangle, bool preMultiplied )
 {
   Toolkit::Visual::ResourceStatus resourceStatus;
-  Actor actor = mPlacementActor.GetHandle();
-  if( actor )
+  if( mImpl->mRenderer )
   {
-    if( mImpl->mRenderer )
+    if( usingAtlas )
     {
-      if( usingAtlas )
-      {
-        mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
-      }
+      mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mAtlasRect );
+    }
 
-      EnablePreMultipliedAlpha( preMultiplied );
+    EnablePreMultipliedAlpha( preMultiplied );
 
+    Actor actor = mPlacementActor.GetHandle();
+    if( actor )
+    {
       actor.AddRenderer( mImpl->mRenderer );
       // reset the weak handle so that the renderer only get added to actor once
       mPlacementActor.Reset();
-      if( loadingSuccess )
-      {
-        Sampler sampler = Sampler::New();
-        sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
-        textureSet.SetSampler( 0u, sampler );
-        mImpl->mRenderer.SetTextures(textureSet);
-      }
-      else
-      {
-        Image brokenImage = mFactoryCache.GetBrokenVisualImage();
+    }
+
+    if( loadingSuccess )
+    {
+      Sampler sampler = Sampler::New();
+      sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
+      textureSet.SetSampler( 0u, sampler );
+      mImpl->mRenderer.SetTextures(textureSet);
+    }
+    else
+    {
+      Image brokenImage = mFactoryCache.GetBrokenVisualImage();
 
-        textureSet = TextureSet::New();
-        mImpl->mRenderer.SetTextures( textureSet );
+      textureSet = TextureSet::New();
+      mImpl->mRenderer.SetTextures( textureSet );
 
-        ApplyImageToSampler( brokenImage );
-      }
+      ApplyImageToSampler( brokenImage );
     }
   }
+
   // Storing TextureSet needed when renderer staged.
   if( ! mImpl->mRenderer )
   {
index 7847924..5e9910d 100644 (file)
@@ -663,6 +663,7 @@ void TextureManager::LoadOrQueueTexture( TextureInfo& textureInfo, TextureUpload
                                   textureInfo.useAtlas, textureInfo.atlasRect,
                                   textureInfo.preMultiplied );
       }
+      break;
     }
     case CANCELLED:
     case LOAD_FINISHED:
index cde291d..5fb7031 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 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 = 8;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 3ed31e8..7954e5b 100644 (file)
  * 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
 
@@ -92,14 +100,20 @@ struct b16_conversion_traits
         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;
     }
 };
 
@@ -117,14 +131,20 @@ struct b32_conversion_traits
         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;
     }
 };
 
@@ -142,8 +162,13 @@ struct b64_conversion_traits
         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';
@@ -156,7 +181,8 @@ struct b64_conversion_traits
         } else if (c == '/') {
             return c - '/' + alph_len * 2 + 11;
         }
-        return Error;
+        error=true;
+        return 0;
     }
 };
 
@@ -172,8 +198,14 @@ void decode(Iter1 start, Iter1 end, Iter2 out)
             ++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;
index 458b448..f474f51 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.4.7
+Version:    1.4.8
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT