Text improvement 73/197773/28
authorJoogab Yun <joogab.yun@samsung.com>
Wed, 16 Jan 2019 07:18:38 +0000 (16:18 +0900)
committerVíctor Cebollada <v.cebollada@samsung.com>
Tue, 19 Feb 2019 07:28:17 +0000 (07:28 +0000)
1. Text - Layout text & icons.
* Feature added to layout text and icons.
  Icons can be added using the mark-up string feature.

  i.e.
   "Hello <item 'url'='icon.png'/>"

  The icon can be resized with the 'width' and 'height' properties.

  "Hello <item 'url'='icon.png' 'width'=24 'height'=24/>"

  Optionally only a size can be specified. The layout engine will layout the text with the gaps of the given size and
  retrieve the layout info of those gaps. It's the responsability of the user to fill the pixel buffer with the images.

* New 'item' tag added to the mark-up processor.

2. Text - Bitmap fonts
* Add support for bitmap fonts.

3. Text renderer utils - Set color to glyphs.
* Required to set the color of the embedded items
  and the glyphs of the bitmap fonts.
* Attribute added to the <item> tag that
  specifies if the color of the item has to be
  blended with the color of the text.
* <color> tag processed and sent to the
  TextRenderer class in adaptor.

* The color of font and bitmap font glyphs can be set
  individually with the <color> tag in a markup string
  or globally if the default color is set.
  If no default color is set, font glyphs will be white
  and bitmap font glyphs will use their colors.

* By default embedded items will use their colors. If
  the attribute 'color-blending' is set to 'multiply'
  the color of the text will be multiplied by the color
  of the item image. If the image is white the result
  will be the color of the text.

  "Hello <item 'url'='image.png' 'color-blending'='multiply'>

4. Text Utils - Render color Emojis.

* Cairo renders Emojis in black and white. This
  patch tells the Cairo renderer whether each
  glyph is an Emoji.

5. Circular text implementation.
* New parameters added to the DevelText::RendererParameters
  struct for circular text.
  - layout: The type of layout: one of {"singleLine",
    "multiLine", "circular"}
  - circularAlignment: The text alignment within the arc:
    one of {"begin", "center", "end"}
  - radius: The radius in pixels of the circular text.
    Measured from the center to the top of the line.
  - 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°.
  - 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.

  @note the horizontalAlignment and verticalAlignment can
  be used to align the whole text within the text area.

* Example: How to set parameters for circular text from
  a C++ application

  Dali::Toolkit::DevelText::RendererParameters textParameters;
  textParameters.text = "Hello world, this is a demo of circular text.";
  textParameters.horizontalAlignment = "center";
  textParameters.verticalAlignment = "center";
  textParameters.circularAlignment = "center";
  textParameters.layout = "circular";
  textParameters.textColor = Color::BLACK;
  textParameters.fontSize = 16.f;
  textParameters.textWidth = 360u;
  textParameters.textHeight = 360u;
  textParameters.radius = 130u;
  textParameters.beginAngle = 180.f;
  textParameters.incrementAngle = 360.f;
  textParameters.ellipsisEnabled = true;

6. Text Utils - Rotate emojis/embedded items.
* Retrieves the layout for rotated embedded items
  added in a second step.
* When the emoji glyph is the one that is replaced
  by the ellipsis glyph, the 'isEmoji' vector pased
  to the cairo-renderer needs to be updated to
  state that '...' is not an emoji.

7. Software italic/bold issues fixed.
* Fixes issues with the synthesis of bold and italic style by software.

Change-Id: I74129ae2e79e23e825a2ef92baa651d7db4e1e57

46 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]
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/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

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-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
  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,
   visualModel = VisualModel::New();
 
   MarkupProcessData markupProcessData( logicalModel->mColorRuns,
-                                       logicalModel->mFontDescriptionRuns );
+                                       logicalModel->mFontDescriptionRuns,
+                                       logicalModel->mEmbeddedItems );
 
   Length textSize = 0u;
   const uint8_t* utf8 = NULL;
 
   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
 {
 
 namespace
 {
+
   ///////////////////////////////////////////////////////////
 
   struct TokenComparisonData
   ///////////////////////////////////////////////////////////
 
   struct TokenComparisonData
@@ -182,9 +183,20 @@ namespace
 
     Vector<ColorRun> colorRuns;
     Vector<FontDescriptionRun> fontRuns;
 
     Vector<ColorRun> colorRuns;
     Vector<FontDescriptionRun> fontRuns;
-    MarkupProcessData markupProcessData( colorRuns, fontRuns );
+    Vector<EmbeddedItem> items;
+    MarkupProcessData markupProcessData( colorRuns, fontRuns, items );
     ProcessMarkupString( data.xHTMLEntityString, markupProcessData );
 
     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;
     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)
   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 )
 };
 
 bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
@@ -93,11 +93,11 @@ bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
   {
     return false;
   }
   {
     return false;
   }
-  if( glyphData.softwareItalic != glyph.softwareItalic )
+  if( glyphData.isItalicRequired != glyph.isItalicRequired )
   {
     return false;
   }
   {
     return false;
   }
-  if( glyphData.softwareBold != glyph.softwareBold )
+  if( glyphData.isBoldRequired != glyph.isBoldRequired )
   {
     return false;
   }
   {
     return false;
   }
@@ -551,14 +551,14 @@ int UtcDaliTextSoftwareStyling(void)
 
   struct GlyphInfoData glyphs01[] =
   {
 
   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 },
   };
   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 },
   };
 
     { 2u, 4364u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f, true,  false },
   };
 
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)/layouting/layout-transition-data.cpp \
   $(devel_api_src_dir)/scripting/script.cpp \
   $(devel_api_src_dir)/styling/style-manager-devel.cpp \
+  $(devel_api_src_dir)/text/bitmap-font.cpp \
+  $(devel_api_src_dir)/text/text-utils-devel.cpp \
   $(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \
   $(devel_api_src_dir)/transition-effects/cube-transition-effect.cpp \
   $(devel_api_src_dir)/transition-effects/cube-transition-fold-effect.cpp \
   $(devel_api_src_dir)/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)/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
 
 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/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 \
    $(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 \
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.
  *
  * 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>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/character-run.h>
 
@@ -38,10 +35,10 @@ namespace Text
  */
 struct FontRun
 {
  */
 struct FontRun
 {
-  CharacterRun characterRun;      ///< The initial character index and the number of characters of the run.
-  FontId       fontId;            ///< Font id of the run.
-  bool         softwareItalic:1;    ///< Whether font needs software support to draw italic style
-  bool         softwareBold:1;      ///< Whether font needs software support to draw bold style
+  CharacterRun characterRun;       ///< The initial character index and the number of characters of the run.
+  FontId       fontId;             ///< Font id of the run.
+  bool         isItalicRequired:1; ///< Whether the italic style is required.
+  bool         isBoldRequired:1;   ///< Whether the bold style is required.
 };
 
 } // namespace Text
 };
 
 } // namespace Text
@@ -50,4 +47,4 @@ struct FontRun
 
 } // namespace Dali
 
 
 } // 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;
   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.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;
 
   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.
    *
   /**
    * @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.
    */
    * @param[in,out] lineLayout The line layout.
    */
-  void UpdateLineHeight( FontId fontId, LineLayout& lineLayout )
+  void UpdateLineHeight( const GlyphMetrics& glyphMetrics, LineLayout& lineLayout )
   {
     Text::FontMetrics fontMetrics;
   {
     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;
   }
     // set the line spacing
     lineLayout.lineSpacing = mDefaultLineSpacing;
   }
@@ -158,22 +163,18 @@ struct Engine::Impl
     {
       lineLayout.length += lineLayout.wsLengthEndOfLine;
 
     {
       lineLayout.length += lineLayout.wsLengthEndOfLine;
 
-      lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
+    lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
     }
     else
     {
       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;
 
     // Calculate the line height if there is no characters.
     FontId lastFontId = glyphMetrics.fontId;
-    UpdateLineHeight( lastFontId, tmpLineLayout );
+    UpdateLineHeight( glyphMetrics, tmpLineLayout );
 
     bool oneWordLaidOut = false;
 
 
     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 )
       {
       // 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;
       }
 
         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 ) &&
     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 )
     {
 
     if( ellipsis )
     {
@@ -613,7 +614,7 @@ struct Engine::Impl
       lineRun->characterRun.characterIndex = ellipsisLayout.characterIndex;
       lineRun->characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
       lineRun->width = ellipsisLayout.length;
       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;
       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;
     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;
     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;
     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;
 
     LineRun& lineRun = *( linesBuffer + numberOfLines );
     ++numberOfLines;
@@ -832,6 +840,9 @@ struct Engine::Impl
       UpdateLayoutSize( lines,
                         layoutSize );
 
       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;
     }
       // 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 );
         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;
       }
 
         return false;
       }
 
@@ -1041,6 +1056,9 @@ struct Engine::Impl
       lines.Resize( numberOfLines );
     }
 
       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;
     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.
  *
  * 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();
 }
 
   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() );
 LogicalModelPtr LogicalModel::New()
 {
   return LogicalModelPtr( new LogicalModel() );
@@ -550,9 +564,15 @@ void LogicalModel::FindParagraphs( CharacterIndex index,
   }
 }
 
   }
 }
 
+void LogicalModel::ClearEmbeddedImages()
+{
+  FreeEmbeddedItems( mEmbeddedItems );
+}
+
 LogicalModel::~LogicalModel()
 {
   ClearFontDescriptionRuns();
 LogicalModel::~LogicalModel()
 {
   ClearFontDescriptionRuns();
+  ClearEmbeddedImages();
 }
 
 LogicalModel::LogicalModel()
 }
 
 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.
  *
  * 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/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>
 #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 );
 
                        Length numberOfCharacters,
                        Vector<ParagraphRunIndex>& paragraphs );
 
+  // Embedded images
+
+  /**
+   * @brief Clears the embedded images.
+   */
+  void ClearEmbeddedImages();
+
 protected:
 
   /**
 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<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.
 };
 
   BidirectionalLineRunIndex             mBidirectionalLineIndex;           ///< The last fetched bidirectional line info.
 };
@@ -220,4 +229,4 @@ public:
 
 } // namespace Dali
 
 
 } // 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 );
 }
 
   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 ) );
 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 );
 
 /**
                        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.
  * @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>
 // 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>
 
 #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
 {
 
 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_SHADOW_TAG("shadow");
 const std::string XHTML_GLOW_TAG("glow");
 const std::string XHTML_OUTLINE_TAG("outline");
+const std::string XHTML_ITEM_TAG("item");
 
 const char LESS_THAN      = '<';
 const char GREATER_THAN   = '>';
 
 const char 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 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
 
 // 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 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;
 
   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;
 
     // 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;
 
       {
         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 );
           {
             ++markupStringBuffer;
             SkipWhiteSpace( markupStringBuffer, markupStringEndBuffer );
@@ -342,11 +353,21 @@ bool IsTag( const char*& markupStringBuffer,
         else if( GREATER_THAN == character ) // '>'
         {
           isTag = true;
         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;
         }
         else if( QUOTATION_MARK == character )
         {
           isQuotationOpen = !isQuotationOpen;
           ++tag.length;
+
+          isPreviousSlash = false;
+          isPreviousLessThan = false;
         }
         else if( WHITE_SPACE >= character ) // ' '
         {
         }
         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;
 
           // 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 )
 {
 
 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 );
   // 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; )
   {
   CharacterIndex characterIndex = 0u;
   for( ; markupStringBuffer < markupStringEndBuffer; )
   {
+    tag.attributes.Clear();
     if( IsTag( markupStringBuffer,
                markupStringEndBuffer,
                tag ) )
     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>
           // 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 )
     {
     }  // end if( IsTag() )
     else if( markupStringBuffer < markupStringEndBuffer )
     {
@@ -753,6 +796,14 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
   else
   {
     markupProcessData.colorRuns.Resize( colorRunIndex );
   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.
  *
  * 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>
 
 // 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
 #include <dali-toolkit/internal/text/font-description-run.h>
 
 namespace Dali
@@ -41,15 +42,17 @@ namespace Text
 struct MarkupProcessData
 {
 MarkupProcessData( Vector<ColorRun>& colorRuns,
 struct MarkupProcessData
 {
 MarkupProcessData( Vector<ColorRun>& colorRuns,
-                   Vector<FontDescriptionRun>& fontRuns )
+                   Vector<FontDescriptionRun>& fontRuns,
+                   Vector<EmbeddedItem>& items )
   : colorRuns( colorRuns ),
     fontRuns( fontRuns ),
   : colorRuns( colorRuns ),
     fontRuns( fontRuns ),
+    items(items),
     markupProcessedText()
   {}
 
   Vector<ColorRun>&           colorRuns;           ///< The color runs.
   Vector<FontDescriptionRun>& fontRuns;            ///< The font description runs.
     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.
 };
 
   std::string                 markupProcessedText; ///< The mark-up string.
 };
 
@@ -67,4 +70,4 @@ void ProcessMarkupString( const std::string& markupString, MarkupProcessData& ma
 
 } // namespace Dali
 
 
 } // 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
   }
 
     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:
 
   /**
 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.
  *
  * 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.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();
 
   // Get the font client.
   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
@@ -448,16 +450,13 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
 
   bool isPreviousEmojiScript = false;
 
 
   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 );
   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;
 
     // 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.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:
     }
 
     // If the given font is not valid, it means either:
@@ -676,22 +677,17 @@ void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
     }
 #endif
 
     }
 #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
 
     // 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.
 
     {
       // 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.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.
     }
 
     // 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.
  *
  * 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,
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
-                             const uint32_t outlineWidth,
+                             const Toolkit::AtlasGlyphManager::GlyphStyle& style,
                              const PixelData& bitmap,
                              Dali::Toolkit::AtlasManager::AtlasSlot& slot )
 {
                              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;
 
   GlyphRecordEntry record;
   record.mIndex = glyph.index;
-  record.mOutlineWidth = outlineWidth;
   record.mImageId = slot.mImageId;
   record.mCount = 1;
   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;
 
   // 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,
 }
 
 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();
 {
   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 )
       {
             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 );
         {
           slot.mImageId = glyphRecordIt->mImageId;
           slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
@@ -174,7 +179,7 @@ const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
   return mMetrics;
 }
 
   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 )
   {
 {
   if( 0 != delta )
   {
@@ -190,7 +195,10 @@ void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIn
               glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
               ++glyphRecordIt )
         {
               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" );
           {
             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.
  *
  * 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;
   struct GlyphRecordEntry
   {
     Text::GlyphIndex mIndex;
-    uint32_t mOutlineWidth;
     uint32_t mImageId;
     int32_t mCount;
     uint32_t mImageId;
     int32_t mCount;
+    uint16_t mOutlineWidth;
+    bool isItalic:1;
+    bool isBold:1;
   };
 
   struct FontGlyphRecord
   };
 
   struct FontGlyphRecord
@@ -71,7 +73,7 @@ public:
    * @copydoc Toolkit::AtlasGlyphManager::Add
    */
   void Add( const Text::GlyphInfo& glyph,
    * @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 );
 
             const PixelData& bitmap,
             Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
@@ -87,7 +89,7 @@ public:
    */
   bool IsCached( Text::FontId fontId,
                  Text::GlyphIndex index,
    */
   bool IsCached( Text::FontId fontId,
                  Text::GlyphIndex index,
-                 uint32_t outlineWidth,
+                 const Toolkit::AtlasGlyphManager::GlyphStyle& style,
                  Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
   /**
                  Dali::Toolkit::AtlasManager::AtlasSlot& slot );
 
   /**
@@ -108,7 +110,7 @@ public:
   /**
    * @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount
    */
   /**
    * @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
 
   /**
    * @copydoc Toolkit::AtlasGlyphManager::GetTextures
@@ -158,4 +160,4 @@ inline Internal::AtlasGlyphManager& GetImplementation(Toolkit::AtlasGlyphManager
 
 } // namespace Dali
 
 
 } // 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.
  *
  * 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,
 }
 
 void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
-                             const uint32_t outlineWidth,
+                             const GlyphStyle& style,
                              const PixelData& bitmap,
                              AtlasManager::AtlasSlot& slot )
 {
                              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,
 }
 
 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,
 
 bool AtlasGlyphManager::IsCached( Text::FontId fontId,
                                   Text::GlyphIndex index,
-                                  uint32_t outlineWidth,
+                                  const GlyphStyle& style,
                                   AtlasManager::AtlasSlot& slot )
 {
                                   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 )
 }
 
 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();
 }
 
   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
 }
 
 } // 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.
  *
  * 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
   };
 
     AtlasManager::Metrics mAtlasMetrics;    ///< metrics from the Atlas Manager
   };
 
+  struct GlyphStyle
+  {
+    GlyphStyle()
+    : outline{ 0u },
+      isItalic{ false },
+      isBold{ false }
+    {}
+
+    uint16_t outline; ///< The outline width of this glyph
+    bool isItalic:1;  ///< Whether the glyph is italic.
+    bool isBold:1;    ///< Whether the glyph is bold.
+  };
+
   /**
    * @brief Create a AtlasGlyphManager handle.
    *
   /**
    * @brief 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
    * @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,
    * @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 );
 
             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] 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,
    * @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 );
 
   /**
                  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] 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
    */
    * @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:
 
 
 private:
 
@@ -179,4 +192,4 @@ private:
 
 } // namespace Dali
 
 
 } // 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.
  *
  * 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 float ONE( 1.0f );
 const uint32_t DEFAULT_ATLAS_WIDTH = 512u;
 const uint32_t DEFAULT_ATLAS_HEIGHT = 512u;
-const uint32_t NO_OUTLINE = 0;
+const uint16_t NO_OUTLINE = 0u;
 }
 
 struct AtlasRenderer::Impl
 }
 
 struct AtlasRenderer::Impl
@@ -168,17 +168,21 @@ struct AtlasRenderer::Impl
   struct TextCacheEntry
   {
     TextCacheEntry()
   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;
     {
     }
 
     FontId mFontId;
     Text::GlyphIndex mIndex;
-    uint32_t mOutlineWidth;
     uint32_t mImageId;
     uint32_t mImageId;
+    uint16_t mOutlineWidth;
+    bool isItalic:1;
+    bool isBold:1;
   };
 
   Impl()
   };
 
   Impl()
@@ -211,9 +215,9 @@ struct AtlasRenderer::Impl
     return false;
   }
 
     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" );
 
 
     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.
       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 );
 
       // 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,
 
         mFontClient.CreateBitmap( glyph.fontId,
                                   glyph.index,
-                                  glyph.softwareItalic,
-                                  glyph.softwareBold,
+                                  glyph.isItalicRequired,
+                                  glyph.isBoldRequired,
                                   glyphBufferData,
                                   glyphBufferData,
-                                  outline );
+                                  style.outline );
 
         // Create the pixel data.
         bitmap = PixelData::New( glyphBufferData.buffer,
 
         // 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
                                          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
         }
       }
     }
     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,
     }
   }
 
   void GenerateMesh( const GlyphInfo& glyph,
                      const Vector2& position,
                      const Vector4& color,
-                     uint32_t outline,
+                     uint16_t outline,
                      AtlasManager::AtlasSlot& slot,
                      bool underlineGlyph,
                      float currentUnderlinePosition,
                      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.mImageId = slot.mImageId;
     textCacheEntry.mIndex = glyph.index;
     textCacheEntry.mOutlineWidth = outline;
+    textCacheEntry.isItalic = glyph.isItalicRequired;
+    textCacheEntry.isBold = glyph.isBoldRequired;
 
     newTextCache.PushBack( textCacheEntry );
 
 
     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 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;
 
     const Vector4& outlineColor( view.GetOutlineColor() );
     const bool isOutline = 0u != outlineWidth;
 
@@ -528,13 +534,18 @@ struct AtlasRenderer::Impl
           lastUnderlinedFontId = glyph.fontId;
         } // underline
 
           lastUnderlinedFontId = glyph.fontId;
         } // underline
 
+        AtlasGlyphManager::GlyphStyle style;
+        style.isItalic = glyph.isItalicRequired;
+        style.isBold = glyph.isBoldRequired;
+
         // Retrieves and caches the glyph's bitmap.
         // 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 )
         {
 
         // 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
         }
 
         // 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 )
     {
   {
     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 );
   }
     }
     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.
  *
  * 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();
 
   // 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;
 
   // 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:
     {
     }
     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.
       break;
     }
   }
 
   // Set the offset for the vertical alignment.
-  int penY = 0;
+  int penY = 0u;
 
   switch( mModel->GetVerticalAlignment() )
   {
 
   switch( mModel->GetVerticalAlignment() )
   {
@@ -390,8 +390,8 @@ PixelData Typesetter::Render( const Vector2& size, Toolkit::DevelText::TextDirec
   {
 
     // Generate the outline if enabled
   {
 
     // 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 );
     {
       // 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
     }
 
     // Retrieves the glyph's outline width
-    float outlineWidth = mModel->GetOutlineWidth();
+    float outlineWidth = static_cast<float>( mModel->GetOutlineWidth() );
 
     if( style == Typesetter::STYLE_OUTLINE )
     {
 
     if( style == Typesetter::STYLE_OUTLINE )
     {
@@ -672,10 +672,10 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer( const unsigned int bufferWidth
       {
         fontClient.CreateBitmap( glyphInfo->fontId,
                                  glyphInfo->index,
       {
         fontClient.CreateBitmap( glyphInfo->fontId,
                                  glyphInfo->index,
-                                 glyphInfo->softwareItalic,
-                                 glyphInfo->softwareBold,
+                                 glyphInfo->isItalicRequired,
+                                 glyphInfo->isBoldRequired,
                                  glyphData.glyphBitmap,
                                  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.
  *
  * 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();
 }
 
   return mModel->GetOutlineColor();
 }
 
-float ViewModel::GetOutlineWidth() const
+uint16_t ViewModel::GetOutlineWidth() const
 {
   return mModel->GetOutlineWidth();
 }
 {
   return mModel->GetOutlineWidth();
 }
index 65cf48c..bc7d45f 100755 (executable)
@@ -191,7 +191,7 @@ public:
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
-  virtual float GetOutlineWidth() const;
+  virtual uint16_t GetOutlineWidth() const;
 
   /**
    * @copydoc ModelInterface::GetBackgroundColor()
 
   /**
    * @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.
  *
  * 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.
 
   // 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 );
   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.
   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;
 
     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,
 
     // 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;
     Vector<CharacterIndex> tmpGlyphToCharacterMap;
 
     GlyphInfo glyphInfo;
-    glyphInfo.softwareItalic = softwareItalic;
-    glyphInfo.softwareBold = softwareBold;
+    glyphInfo.isItalicRequired = isItalicRequired;
+    glyphInfo.isBoldRequired = isBoldRequired;
 
     tmpGlyphs.Resize( numberOfGlyphs, glyphInfo );
     tmpGlyphToCharacterMap.Resize( numberOfGlyphs );
 
     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 ));
 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
 }
 
 } // 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->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;
 
     Length textSize = 0u;
     const uint8_t* utf8 = NULL;
@@ -1241,14 +1242,14 @@ const Vector4& Controller::GetOutlineColor() const
   return mImpl->mModel->mVisualModel->GetOutlineColor();
 }
 
   return mImpl->mModel->mVisualModel->GetOutlineColor();
 }
 
-void Controller::SetOutlineWidth( unsigned int width )
+void Controller::SetOutlineWidth( uint16_t width )
 {
   mImpl->mModel->mVisualModel->SetOutlineWidth( width );
 
   mImpl->RequestRelayout();
 }
 
 {
   mImpl->mModel->mVisualModel->SetOutlineWidth( width );
 
   mImpl->RequestRelayout();
 }
 
-unsigned int Controller::GetOutlineWidth() const
+uint16_t Controller::GetOutlineWidth() const
 {
   return mImpl->mModel->mVisualModel->GetOutlineWidth();
 }
 {
   return mImpl->mModel->mVisualModel->GetOutlineWidth();
 }
@@ -3939,6 +3940,9 @@ void Controller::ResetText()
   // Reset buffers.
   mImpl->mModel->mLogicalModel->mText.Clear();
 
   // 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();
 
   // 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
    */
    *
    * @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.
    */
 
   /**
    * @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.
 
   /**
    * @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::LineBreakInfo      LineBreakInfo;      ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace).
 typedef TextAbstraction::WordBreakInfo      WordBreakInfo;      ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace).
 typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left.
+typedef TextAbstraction::ColorBlendingMode  ColorBlendingMode;  ///< Defines how a color is blended.
+typedef TextAbstraction::ColorIndex         ColorIndex;         ///< An index into an array of colors.
 
 typedef uint32_t                         GlyphIndex;                ///< An index into an array of glyphs.
 typedef uint32_t                         ScriptRunIndex;            ///< An index into an array of script runs.
 
 typedef uint32_t                         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                         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
 
 
 } // namespace Text
 
index f65655b..015bee3 100755 (executable)
@@ -175,7 +175,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
                                bool& colorDefined,
                                Vector4& color,
                                bool& widthDefined,
                                bool& colorDefined,
                                Vector4& color,
                                bool& widthDefined,
-                               unsigned int& width )
+                               uint16_t& width )
 {
   const unsigned int numberOfItems = underlinePropertiesMap.Count();
 
 {
   const unsigned int numberOfItems = underlinePropertiesMap.Count();
 
@@ -194,7 +194,7 @@ bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
     {
       /// Width key.
       widthDefined = true;
     {
       /// Width key.
       widthDefined = true;
-      width = static_cast<unsigned int>( valueGet.second.Get<float>() );
+      width = static_cast<uint16_t>( valueGet.second.Get<float>() );
     }
   }
 
     }
   }
 
@@ -594,7 +594,7 @@ bool SetOutlineProperties( ControllerPtr controller, const Property::Value& valu
         bool colorDefined = false;
         Vector4 color;
         bool widthDefined = false;
         bool colorDefined = false;
         Vector4 color;
         bool widthDefined = false;
-        unsigned int width = 0u;
+        uint16_t width = 0u;
 
         bool empty = true;
 
 
         bool empty = true;
 
@@ -675,7 +675,7 @@ void GetOutlineProperties( ControllerPtr controller, Property::Value& value, Eff
         else
         {
           const Vector4& color = controller->GetOutlineColor();
         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 );
 
           Property::Map map;
           map.Insert( COLOR_KEY, color );
index f2a82ad..a301d03 100755 (executable)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_MODEL_INTERFACE_H
 
 /*
 #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.
  *
  * 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.
    */
    *
    * @return The width of the outline.
    */
-  virtual float GetOutlineWidth() const = 0;
+  virtual uint16_t GetOutlineWidth() const = 0;
 
   /**
    * @brief Retrieves the background color.
 
   /**
    * @brief Retrieves the background color.
index 474b3ae..da87e0c 100755 (executable)
@@ -162,7 +162,7 @@ const Vector4& Model::GetOutlineColor() const
   return mVisualModel->GetOutlineColor();
 }
 
   return mVisualModel->GetOutlineColor();
 }
 
-float Model::GetOutlineWidth() const
+uint16_t Model::GetOutlineWidth() const
 {
   return mVisualModel->GetOutlineWidth();
 }
 {
   return mVisualModel->GetOutlineWidth();
 }
index f4fbd7b..3230e47 100755 (executable)
@@ -191,7 +191,7 @@ public:
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
   /**
    * @copydoc ModelInterface::GetOutlineWidth()
    */
-  virtual float GetOutlineWidth() const override;
+  virtual uint16_t GetOutlineWidth() const override;
 
   /**
    * @copydoc ModelInterface::GetBackgroundColor()
 
   /**
    * @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.
  *
  * 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.
    */
    *
    * @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
 
 
 } // 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.
  *
  * 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;
 }
 
   return Vector4::ZERO;
 }
 
-unsigned int View::GetOutlineWidth() const
+uint16_t View::GetOutlineWidth() const
 {
   if( mImpl->mVisualModel )
   {
 {
   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.
  *
  * 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()
    */
   /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineWidth()
    */
-  virtual unsigned int GetOutlineWidth() const;
+  virtual uint16_t GetOutlineWidth() const;
 
 private:
 
 
 private:
 
@@ -160,4 +160,4 @@ private:
 
 } // namespace Dali
 
 
 } // 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.
  *
  * 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;
 }
 
   mUnderlineHeight = height;
 }
 
-void VisualModel::SetOutlineWidth( unsigned int width )
+void VisualModel::SetOutlineWidth( uint16_t width )
 {
   mOutlineWidth = width;
 }
 {
   mOutlineWidth = width;
 }
@@ -428,7 +428,7 @@ float VisualModel::GetUnderlineHeight() const
   return mUnderlineHeight;
 }
 
   return mUnderlineHeight;
 }
 
-unsigned int VisualModel::GetOutlineWidth() const
+uint16_t VisualModel::GetOutlineWidth() const
 {
   return mOutlineWidth;
 }
 {
   return mOutlineWidth;
 }
@@ -473,8 +473,8 @@ VisualModel::VisualModel()
   mControlSize(),
   mShadowOffset(),
   mUnderlineHeight( 0.0f ),
   mControlSize(),
   mShadowOffset(),
   mUnderlineHeight( 0.0f ),
-  mOutlineWidth( 0u ),
   mShadowBlurRadius( 0.0f ),
   mShadowBlurRadius( 0.0f ),
+  mOutlineWidth( 0u ),
   mNaturalSize(),
   mLayoutSize(),
   mCachedLineIndex( 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.
  *
  * 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
    */
    *
    * @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.
    */
 
   /**
    * @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.
 
   /**
    * @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.
   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.
   float                  mShadowBlurRadius;     ///< Blur radius of shadow, 0 indicates no blur.
+  uint16_t           mOutlineWidth;         ///< Width of outline.
 
 private:
 
 
 private:
 
@@ -422,4 +422,4 @@ public:
 
 } // namespace Dali
 
 
 } // namespace Dali
 
-#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__
+#endif // DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H