[dali_1.1.28] Merge branch 'devel/master' 53/64453/1
authorVictor Cebollada <v.cebollada@samsung.com>
Fri, 1 Apr 2016 08:33:50 +0000 (09:33 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Fri, 1 Apr 2016 08:36:53 +0000 (09:36 +0100)
Change-Id: Id3ae12681e5204a192924496b764dd004a7c1634

54 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-BidirectionalSupport.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-LogicalModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h
automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp
dali-toolkit/devel-api/builder/tree-node.cpp
dali-toolkit/devel-api/builder/tree-node.h
dali-toolkit/devel-api/controls/bloom-view/bloom-view.cpp
dali-toolkit/devel-api/controls/bloom-view/bloom-view.h
dali-toolkit/devel-api/controls/shadow-view/shadow-view.cpp
dali-toolkit/devel-api/controls/shadow-view/shadow-view.h
dali-toolkit/internal/builder/builder-get-is.inl.h
dali-toolkit/internal/builder/builder-impl-debug.cpp [new file with mode: 0644]
dali-toolkit/internal/builder/builder-impl-debug.h [new file with mode: 0644]
dali-toolkit/internal/builder/builder-impl.cpp
dali-toolkit/internal/builder/builder-impl.h
dali-toolkit/internal/builder/builder-set-property.cpp
dali-toolkit/internal/builder/builder-set-property.h [new file with mode: 0644]
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.h
dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp
dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.h
dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp
dali-toolkit/internal/controls/shadow-view/shadow-view-impl.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-engine.h
dali-toolkit/internal/text/layouts/layout-parameters.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-run-container.h
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.cpp
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 0852234..7696421 100644 (file)
@@ -15,6 +15,7 @@ SET(TC_SOURCES
  utc-Dali-BidirectionalSupport.cpp
  utc-Dali-Text-Shaping.cpp
  utc-Dali-VisualModel.cpp
+ utc-Dali-Text-Layout.cpp
 )
 
 # Append list of test harness files (Won't get parsed for test cases)
index 92ee580..f61e539 100644 (file)
@@ -86,6 +86,8 @@ struct ReorderLinesData
   unsigned int  numberOfCharacters; ///< The number of characters.
   unsigned int  numberOfLineInfo;   ///< The number or reordered lines.
   BidiLineData* bidiLineData;       ///< The bidirectional line info.
+  unsigned int  numberOfLines;      ///< The number of laid-out lines.
+  bool*         lineDirections;     ///< The directions of the lines.
 };
 
 struct GetMirroredTextData
@@ -115,8 +117,12 @@ bool SetBidirectionalInfoTest( const SetBidirectionalInfoData& data )
   Size layoutSize;
 
   // Create the model.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
@@ -215,8 +221,12 @@ bool ReorderLinesTest( const ReorderLinesData& data )
   Size layoutSize;
 
   // Create the model.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
@@ -302,6 +312,26 @@ bool ReorderLinesTest( const ReorderLinesData& data )
     }
   }
 
+  if( data.numberOfLines != visualModel->mLines.Count() )
+  {
+    std::cout << "Different number of lines : " << visualModel->mLines.Count() << ", expected : " << data.numberOfLines << std::endl;
+
+    unsigned int index = 0u;
+    for( Vector<LineRun>::ConstIterator it = visualModel->mLines.Begin(),
+           endIt = visualModel->mLines.End();
+         it != endIt;
+         ++it, ++index )
+    {
+      const LineRun& line = *it;
+
+      if( line.direction != *( data.lineDirections + index ) )
+      {
+        std::cout << "  Different line direction : " << line.direction << ", expected : " << *( data.lineDirections + index ) << std::endl;
+        return false;
+      }
+    }
+  }
+
   return true;
 }
 
@@ -314,8 +344,12 @@ bool GetMirroredTextTest( const GetMirroredTextData& data )
   Size layoutSize;
 
   // Create the model.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
@@ -382,8 +416,12 @@ bool GetCharactersDirectionTest( const GetCharactersDirectionData& data )
   Size layoutSize;
 
   // Create the model.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
@@ -673,6 +711,9 @@ int UtcDaliReorderLines(void)
     },
   };
 
+  bool directions02[] = { false, false, false, false, false, false };
+  bool directions03[] = { false, false, false, false, false, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true };
+
   struct ReorderLinesData data[] =
   {
     {
@@ -681,7 +722,9 @@ int UtcDaliReorderLines(void)
       0u,
       0u,
       0u,
-      bidiLine01
+      bidiLine01,
+      0u,
+      NULL
     },
     {
       "Left to right text only.",
@@ -689,7 +732,9 @@ int UtcDaliReorderLines(void)
       0u,
       51u,
       0u,
-      bidiLine02
+      bidiLine02,
+      6u,
+      directions02
     },
     {
       "Bidirectional paragraphs.",
@@ -697,7 +742,9 @@ int UtcDaliReorderLines(void)
       0u,
       195u,
       16u,
-      bidiLine03
+      bidiLine03,
+      20u,
+      directions03
     },
     {
       "Bidirectional paragraphs. Update initial paragraphs.",
@@ -705,7 +752,9 @@ int UtcDaliReorderLines(void)
       0u,
       44u,
       16u,
-      bidiLine03
+      bidiLine03,
+      20u,
+      directions03
     },
     {
       "Bidirectional paragraphs. Update middle paragraphs.",
@@ -713,7 +762,9 @@ int UtcDaliReorderLines(void)
       44u,
       54u,
       16u,
-      bidiLine03
+      bidiLine03,
+      20u,
+      directions03
     },
     {
       "Bidirectional paragraphs. Update final paragraphs.",
@@ -721,7 +772,9 @@ int UtcDaliReorderLines(void)
       142u,
       53u,
       16u,
-      bidiLine03
+      bidiLine03,
+      20u,
+      directions03
     },
   };
   const unsigned int numberOfTests = 6u;
index b18e1e6..9ec9930 100644 (file)
@@ -60,8 +60,12 @@ bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
   Size layoutSize;
 
   // Create the model with the whole text.
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    data.textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
new file mode 100644 (file)
index 0000000..d849430
--- /dev/null
@@ -0,0 +1,4978 @@
+/*
+ * Copyright (c) 2016 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 <stdlib.h>
+#include <unistd.h>
+
+#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-model.h>
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the LayoutEngine methods.
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
+
+struct LayoutTextData
+{
+  std::string          description;
+  std::string          text;
+  Size                 textArea;
+  unsigned int         numberOfFonts;
+  FontDescriptionRun*  fontDescriptions;
+  Size                 layoutSize;
+  unsigned int         totalNumberOfGlyphs;
+  float*               positions;
+  unsigned int         numberOfLines;
+  LineRun*             lines;
+  LayoutEngine::Layout layout;
+  unsigned int         startIndex;
+  unsigned int         numberOfGlyphs;
+  bool                 ellipsis:1;
+  bool                 updated:1;
+};
+
+void Print( const LineRun& line )
+{
+  std::cout << "        glyph run, index : " << line.glyphRun.glyphIndex << ", num glyphs : " << line.glyphRun.numberOfGlyphs << std::endl;
+  std::cout << "    character run, index : " << line.characterRun.characterIndex << ", num chars : " << line.characterRun.numberOfCharacters << std::endl;
+  std::cout << "                   width : " << line.width << std::endl;
+  std::cout << "                ascender : " << line.ascender << std::endl;
+  std::cout << "               descender : " << line.descender << std::endl;
+  std::cout << "             extraLength : " << line.extraLength << std::endl;
+  std::cout << "         alignmentOffset : " << line.alignmentOffset << std::endl;
+  std::cout << "               direction : " << line.direction << std::endl;
+  std::cout << "                ellipsis : " << line.ellipsis << std::endl;
+}
+
+bool LayoutTextTest( const LayoutTextData& data )
+{
+  // Load some fonts.
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.SetDpi( 96u, 96u );
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+
+  // 1) Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  if( 0u != data.numberOfFonts )
+  {
+    fontDescriptionRuns.Insert( fontDescriptionRuns.End(),
+                                data.fontDescriptions,
+                                data.fontDescriptions + data.numberOfFonts );
+  }
+
+  LayoutOptions options;
+  options.reorder = false;
+  options.align = false;
+  CreateTextModel( data.text,
+                   data.textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  // 2) Clear the layout.
+  Vector<LineRun>& lines = visualModel->mLines;
+
+  const Length numberOfCharacters = logicalModel->mText.Count();
+  const bool isLastNewParagraph = ( 0u == numberOfCharacters ) ? false : TextAbstraction::IsNewParagraph( *( logicalModel->mText.Begin() + ( numberOfCharacters - 1u ) ) );
+  const GlyphIndex lastGlyphIndex = data.startIndex + data.numberOfGlyphs - 1u;
+  const bool removeLastLine = isLastNewParagraph && ( lastGlyphIndex + 1u == visualModel->mGlyphs.Count() );
+
+  LineIndex startRemoveIndex = 0u;
+
+  if( 0u != lines.Count() )
+  {
+    startRemoveIndex = lines.Count();
+    LineIndex endRemoveIndex = startRemoveIndex;
+    ClearGlyphRuns( data.startIndex,
+                    lastGlyphIndex + ( removeLastLine ? 1u : 0u ),
+                    lines,
+                    startRemoveIndex,
+                    endRemoveIndex );
+
+    // Update the character runs of the lines.
+    const CharacterIndex* const glyphsToCharactersBuffer = visualModel->mGlyphsToCharacters.Begin();
+    const Length* const charactersPerGlyph = visualModel->mCharactersPerGlyph.Begin();
+    const CharacterIndex startCharacterIndex = *( glyphsToCharactersBuffer + data.startIndex );
+    const CharacterIndex lastCharacterIndex = *( glyphsToCharactersBuffer + lastGlyphIndex ) + *( charactersPerGlyph + lastGlyphIndex ) - 1u;
+    ClearCharacterRuns( startCharacterIndex,
+                        lastCharacterIndex + ( removeLastLine ? 1u : 0u ),
+                        lines,
+                        startRemoveIndex,
+                        endRemoveIndex );
+
+    lines.Erase( lines.Begin() + startRemoveIndex,
+                 lines.Begin() + endRemoveIndex );
+  }
+
+  Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+
+  glyphPositions.Erase( glyphPositions.Begin() + data.startIndex,
+                        glyphPositions.Begin() + data.startIndex + data.numberOfGlyphs );
+
+  // 3) Layout
+  MetricsPtr metrics = Metrics::New( fontClient );
+
+  LayoutEngine engine;
+  engine.SetMetrics( metrics );
+  engine.SetTextEllipsisEnabled( data.ellipsis );
+  engine.SetLayout( data.layout );
+
+  const Length totalNumberOfGlyphs = visualModel->mGlyphs.Count();
+
+  LayoutParameters layoutParameters( data.textArea,
+                                     logicalModel->mText.Begin(),
+                                     logicalModel->mLineBreakInfo.Begin(),
+                                     logicalModel->mWordBreakInfo.Begin(),
+                                     ( 0u != logicalModel->mCharacterDirections.Count() ) ? logicalModel->mCharacterDirections.Begin() : NULL,
+                                     visualModel->mGlyphs.Begin(),
+                                     visualModel->mGlyphsToCharacters.Begin(),
+                                     visualModel->mCharactersPerGlyph.Begin(),
+                                     visualModel->mCharactersToGlyph.Begin(),
+                                     visualModel->mGlyphsPerCharacter.Begin(),
+                                     totalNumberOfGlyphs );
+
+  layoutParameters.isLastNewParagraph = isLastNewParagraph;
+
+  // The initial glyph and the number of glyphs to layout.
+  layoutParameters.startGlyphIndex = data.startIndex;
+  layoutParameters.numberOfGlyphs = data.numberOfGlyphs;
+  layoutParameters.startLineIndex = startRemoveIndex;
+
+  layoutSize = Vector2::ZERO;
+
+  const bool updated = engine.LayoutText( layoutParameters,
+                                          glyphPositions,
+                                          lines,
+                                          layoutSize );
+
+  // 4) Compare the results.
+
+  if( updated != data.updated )
+  {
+    std::cout << "  Different updated bool : " << updated << ", expected : " << data.updated << std::endl;
+    return false;
+  }
+
+  if( layoutSize != data.layoutSize )
+  {
+    std::cout << "  Different layout size : " << layoutSize << ", expected : " << data.layoutSize << std::endl;
+    return false;
+  }
+
+  for( unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index )
+  {
+    const Vector2& position = *( glyphPositions.Begin() + index );
+
+    if( fabsf( position.x - *( data.positions + 2u * index ) ) > Math::MACHINE_EPSILON_1000 )
+    {
+      std::cout << "  Different position for glyph " << index << " x : " << position.x << ", expected : " << *( data.positions + 2u * index ) << std::endl;
+      return false;
+    }
+    if( fabsf( position.y - *( data.positions + 2u * index + 1u ) ) > Math::MACHINE_EPSILON_1000 )
+    {
+      std::cout << "  Different position for glyph " << index << " y : " << position.y << ", expected : " << *( data.positions + 2u * index + 1u ) << std::endl;
+      return false;
+    }
+  }
+
+  if( lines.Count() != data.numberOfLines )
+  {
+    std::cout << "  Different number of lines : " << lines.Count() << ", expected : " << data.numberOfLines << std::endl;
+    return false;
+  }
+
+  for( unsigned int index = 0u; index < data.numberOfLines; ++index )
+  {
+    const LineRun& line = *( lines.Begin() + index );
+    const LineRun& expectedLine = *( data.lines + index );
+
+    if( line.glyphRun.glyphIndex != expectedLine.glyphRun.glyphIndex )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+    if( line.glyphRun.numberOfGlyphs != expectedLine.glyphRun.numberOfGlyphs )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( line.characterRun.characterIndex != expectedLine.characterRun.characterIndex )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+    if( line.characterRun.numberOfCharacters != expectedLine.characterRun.numberOfCharacters )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( fabsf( line.width - expectedLine.width ) > Math::MACHINE_EPSILON_1 )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( fabsf( line.ascender - expectedLine.ascender ) > Math::MACHINE_EPSILON_1 )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( fabsf( line.descender - expectedLine.descender ) > Math::MACHINE_EPSILON_1 )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( fabsf( line.extraLength - expectedLine.extraLength ) > Math::MACHINE_EPSILON_1 )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    if( line.ellipsis != expectedLine.ellipsis )
+    {
+      std::cout << "  Different line info for line : " << index << std::endl;
+      Print( line );
+      std::cout << "  expected" << std::endl;
+      Print( expectedLine );
+      return false;
+    }
+
+    // Do not compare the alignment offset as it's not calculated in the layout.
+    // Do not compare the line direction as it's not set in the layout.
+  }
+
+  return true;
+}
+
+//////////////////////////////////////////////////////////
+
+struct ReLayoutRightToLeftLinesData
+{
+  std::string         description;
+  std::string         text;
+  Size                textArea;
+  unsigned int        numberOfFonts;
+  FontDescriptionRun* fontDescriptions;
+  unsigned int        totalNumberOfGlyphs;
+  float*              positions;
+  unsigned int        startIndex;
+  unsigned int        numberOfCharacters;
+};
+
+bool ReLayoutRightToLeftLinesTest( const ReLayoutRightToLeftLinesData& data )
+{
+  // Load some fonts.
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.SetDpi( 96u, 96u );
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+
+  // 1) Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  if( 0u != data.numberOfFonts )
+  {
+    fontDescriptionRuns.Insert( fontDescriptionRuns.End(),
+                                data.fontDescriptions,
+                                data.fontDescriptions + data.numberOfFonts );
+  }
+
+  LayoutOptions options;
+  options.reorder = false;
+  options.align = false;
+  CreateTextModel( data.text,
+                   data.textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  // 2) Call the ReLayoutRightToLeftLines() method.
+  MetricsPtr metrics = Metrics::New( fontClient );
+
+  LayoutEngine engine;
+  engine.SetMetrics( metrics );
+
+  LayoutParameters layoutParameters( data.textArea,
+                                     logicalModel->mText.Begin(),
+                                     logicalModel->mLineBreakInfo.Begin(),
+                                     logicalModel->mWordBreakInfo.Begin(),
+                                     ( 0u != logicalModel->mCharacterDirections.Count() ) ? logicalModel->mCharacterDirections.Begin() : NULL,
+                                     visualModel->mGlyphs.Begin(),
+                                     visualModel->mGlyphsToCharacters.Begin(),
+                                     visualModel->mCharactersPerGlyph.Begin(),
+                                     visualModel->mCharactersToGlyph.Begin(),
+                                     visualModel->mGlyphsPerCharacter.Begin(),
+                                     visualModel->mGlyphs.Count() );
+
+  layoutParameters.numberOfBidirectionalInfoRuns = logicalModel->mBidirectionalLineInfo.Count();
+  layoutParameters.lineBidirectionalInfoRunsBuffer = logicalModel->mBidirectionalLineInfo.Begin();
+
+  engine.ReLayoutRightToLeftLines( layoutParameters,
+                                   data.startIndex,
+                                   data.numberOfCharacters,
+                                   visualModel->mGlyphPositions );
+
+  // 3) Compare the results.
+  Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+
+  if( data.totalNumberOfGlyphs != visualModel->mGlyphs.Count() )
+  {
+    std::cout << "  Different number of glyphs : " << visualModel->mGlyphs.Count() << ", expected : " << data.totalNumberOfGlyphs << std::endl;
+    return false;
+  }
+
+  for( unsigned int index = 0u; index < data.totalNumberOfGlyphs; ++index )
+  {
+    const Vector2& position = *( glyphPositions.Begin() + index );
+
+    if( fabsf( position.x - *( data.positions + 2u * index ) ) > Math::MACHINE_EPSILON_1000 )
+    {
+      std::cout << "  Different position for glyph " << index << " x : " << position.x << ", expected : " << *( data.positions + 2u * index ) << std::endl;
+      return false;
+    }
+    if( fabsf( position.y - *( data.positions + 2u * index + 1u ) ) > Math::MACHINE_EPSILON_1000 )
+    {
+      std::cout << "  Different position for glyph " << index << " y : " << position.y << ", expected : " << *( data.positions + 2u * index + 1u ) << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+//////////////////////////////////////////////////////////
+
+struct AlignData
+{
+  std::string                       description;
+  std::string                       text;
+  Size                              textArea;
+  unsigned int                      numberOfFonts;
+  FontDescriptionRun*               fontDescriptions;
+  LayoutEngine::HorizontalAlignment horizontalAlignment;
+  LayoutEngine::VerticalAlignment   verticalAlignment;
+  unsigned int                      startIndex;
+  unsigned int                      numberOfCharacters;
+  unsigned int                      numberOfLines;
+  float*                            lineOffsets;
+};
+
+bool AlignTest( const AlignData& data )
+{
+  // Load some fonts.
+  TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+  fontClient.SetDpi( 96u, 96u );
+
+  char* pathNamePtr = get_current_dir_name();
+  const std::string pathName( pathNamePtr );
+  free( pathNamePtr );
+
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansHebrewRegular.ttf" );
+  fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansArabicRegular.ttf" );
+
+  // 1) Create the model.
+  LogicalModelPtr logicalModel = LogicalModel::New();
+  VisualModelPtr visualModel = VisualModel::New();
+  Size layoutSize;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  if( 0u != data.numberOfFonts )
+  {
+    fontDescriptionRuns.Insert( fontDescriptionRuns.End(),
+                                data.fontDescriptions,
+                                data.fontDescriptions + data.numberOfFonts );
+  }
+
+  LayoutOptions options;
+  options.align = false;
+  CreateTextModel( data.text,
+                   data.textArea,
+                   fontDescriptionRuns,
+                   options,
+                   layoutSize,
+                   logicalModel,
+                   visualModel );
+
+  // Call the Align method.
+  MetricsPtr metrics = Metrics::New( fontClient );
+
+  LayoutEngine engine;
+  engine.SetMetrics( metrics );
+
+  engine.SetHorizontalAlignment( data.horizontalAlignment );
+  engine.SetVerticalAlignment( data.verticalAlignment );
+
+  engine.Align( data.textArea,
+                data.startIndex,
+                data.numberOfCharacters,
+                visualModel->mLines );
+
+  // Compare results.
+  if( data.numberOfLines != visualModel->mLines.Count() )
+  {
+    std::cout << "  Different number of lines : " << visualModel->mLines.Count() << ", expected : " << data.numberOfLines << std::endl;
+    return false;
+  }
+
+  const LineRun* const linesBuffer = visualModel->mLines.Begin();
+  for( unsigned int index = 0u; index < data.numberOfLines; ++index )
+  {
+    const LineRun& line = *( linesBuffer + index );
+
+    if( line.alignmentOffset != *( data.lineOffsets + index ) )
+    {
+      std::cout << "  different line offset for index " << index << " : " << line.alignmentOffset << ", expected : " << *( data.lineOffsets + index ) << std::endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+//
+// UtcDaliTextLayoutSetGetLayout
+// UtcDaliTextLayoutSetGetTextEllipsisEnabled
+// UtcDaliTextLayoutSetGetHorizontalAlignment
+// UtcDaliTextLayoutSetGetVerticalAlignment
+// UtcDaliTextLayoutSetGetCursorWidth
+// UtcDaliTextLayoutNoText
+// UtcDaliTextLayoutSmallTextArea01
+// UtcDaliTextLayoutSmallTextArea02
+// UtcDaliTextLayoutMultilineText01
+// UtcDaliTextLayoutMultilineText02
+// UtcDaliTextLayoutMultilineText03
+// UtcDaliTextLayoutMultilineText04
+// UtcDaliTextLayoutMultilineText05
+// UtcDaliTextUpdateLayout01
+// UtcDaliTextUpdateLayout02
+// UtcDaliTextUpdateLayout03
+// UtcDaliTextLayoutEllipsis01
+// UtcDaliTextLayoutEllipsis02
+// UtcDaliTextLayoutEllipsis03
+// UtcDaliTextLayoutEllipsis04
+// UtcDaliTextLayoutEllipsis04
+// UtcDaliTextReorderLayout01
+// UtcDaliTextReorderLayout02
+// UtcDaliTextReorderLayout03
+// UtcDaliTextReorderLayout04
+// UtcDaliTextAlign01
+// UtcDaliTextAlign02
+// UtcDaliTextAlign03
+// UtcDaliTextAlign04
+// UtcDaliTextAlign05
+// UtcDaliTextAlign06
+// UtcDaliTextAlign07
+// UtcDaliTextAlign08
+// UtcDaliTextAlign09
+//
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextLayoutSetGetLayout(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutSetGetLayout");
+
+  LayoutEngine engine;
+
+  DALI_TEST_CHECK( LayoutEngine::SINGLE_LINE_BOX == engine.GetLayout() );
+
+  engine.SetLayout( LayoutEngine::MULTI_LINE_BOX );
+  DALI_TEST_CHECK( LayoutEngine::MULTI_LINE_BOX == engine.GetLayout() );
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSetGetTextEllipsisEnabled(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutSetGetTextEllipsisEnabled");
+
+  LayoutEngine engine;
+
+  DALI_TEST_CHECK( !engine.GetTextEllipsisEnabled() );
+
+  engine.SetTextEllipsisEnabled( true );
+  DALI_TEST_CHECK( engine.GetTextEllipsisEnabled() );
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSetGetHorizontalAlignment(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" ");
+
+  LayoutEngine engine;
+
+  DALI_TEST_CHECK( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == engine.GetHorizontalAlignment() );
+
+  engine.SetHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_END );
+  DALI_TEST_CHECK( LayoutEngine::HORIZONTAL_ALIGN_END == engine.GetHorizontalAlignment() );
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSetGetVerticalAlignment(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutSetGetVerticalAlignment");
+
+  LayoutEngine engine;
+
+  DALI_TEST_CHECK( LayoutEngine::VERTICAL_ALIGN_TOP == engine.GetVerticalAlignment() );
+
+  engine.SetVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP );
+  DALI_TEST_CHECK( LayoutEngine::VERTICAL_ALIGN_TOP == engine.GetVerticalAlignment() );
+
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSetGetCursorWidth(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" ");
+
+  LayoutEngine engine;
+
+  DALI_TEST_EQUALS( 1, engine.GetCursorWidth(), TEST_LOCATION );
+
+  engine.SetCursorWidth( 2 );
+  DALI_TEST_EQUALS( 2, engine.GetCursorWidth(), TEST_LOCATION );
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutNoText(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutNoText");
+
+  Size textArea(100.f, 60.f);
+  Size layoutSize = Vector2::ZERO;
+  LayoutTextData data =
+  {
+    "No text",
+    "",
+    textArea,
+    0u,
+    NULL,
+    layoutSize,
+    0u,
+    NULL,
+    0u,
+    NULL,
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    0u,
+    false,
+    false
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSmallTextArea01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutSmallTextArea01");
+
+  // Won't layout the text in multi-line if the width is too small.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun;
+  fontDescriptionRun.characterRun.characterIndex = 0u;
+  fontDescriptionRun.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun.familyLength = fontFamily.size();
+  fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
+  memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength );
+  fontDescriptionRun.familyDefined = true;
+  fontDescriptionRun.weightDefined = false;
+  fontDescriptionRun.widthDefined = false;
+  fontDescriptionRun.slantDefined = false;
+  fontDescriptionRun.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun );
+  Size textArea(1.f, 1.f);
+  Size layoutSize = Vector2::ZERO;
+  LayoutTextData data =
+  {
+    "Layout text in a small area",
+    "Hello world",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    0u,
+    NULL,
+    0u,
+    NULL,
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    11u,
+    false,
+    false
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutSmallTextArea02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutSmallTextArea02");
+
+  // Will layout the text in single line as it can be scrolled.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun;
+  fontDescriptionRun.characterRun.characterIndex = 0u;
+  fontDescriptionRun.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun.familyLength = fontFamily.size();
+  fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
+  memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength );
+  fontDescriptionRun.familyDefined = true;
+  fontDescriptionRun.weightDefined = false;
+  fontDescriptionRun.widthDefined = false;
+  fontDescriptionRun.slantDefined = false;
+  fontDescriptionRun.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun );
+  Size textArea(1.f, 1.f);
+  Size layoutSize(80.f, 20.f);
+  float positions[] = { 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f };
+  struct LineRun line =
+  {
+    { 0u, 11u },
+    { 0u, 11u },
+    80.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line );
+
+  LayoutTextData data =
+  {
+    "Layout text in a small area",
+    "Hello world",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    11u,
+    positions,
+    1u,
+    lines.Begin(),
+    LayoutEngine::SINGLE_LINE_BOX,
+    0u,
+    11u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutMultilineText01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutMultilineText01");
+
+  // Layout some lines of left to right text.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun1;
+  fontDescriptionRun1.characterRun.characterIndex = 0u;
+  fontDescriptionRun1.characterRun.numberOfCharacters = 18u;
+  fontDescriptionRun1.familyLength = fontFamily.size();
+  fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
+  memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength );
+  fontDescriptionRun1.familyDefined = true;
+  fontDescriptionRun1.weightDefined = false;
+  fontDescriptionRun1.widthDefined = false;
+  fontDescriptionRun1.slantDefined = false;
+  fontDescriptionRun1.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun2;
+  fontDescriptionRun2.characterRun.characterIndex = 18u;
+  fontDescriptionRun2.characterRun.numberOfCharacters = 31u;
+  fontDescriptionRun2.familyLength = fontFamily.size();
+  fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength];
+  memcpy( fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength );
+  fontDescriptionRun2.familyDefined = true;
+  fontDescriptionRun2.weightDefined = false;
+  fontDescriptionRun2.widthDefined = false;
+  fontDescriptionRun2.slantDefined = false;
+  fontDescriptionRun2.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun1 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun2 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(95.f, 97.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 32.f, 42.f, 23.f,
+    1.f, 43.f, 9.f, 46.f, 17.f, 46.f, 27.f, 46.f, 36.f, 46.f, 45.f, 44.f, 51.f, 55.f,
+    1.f, 62.f, 11.f, 62.f, 15.f, 62.f, 26.f, 65.f, 35.f, 65.f, 41.f, 65.f, 50.f, 65.f, 59.f, 63.f, 65.f, 74.f,
+    1.f, 81.f, 5.f, 81.f, 9.f, 84.f, 19.f, 84.f, 28.f, 84.f, 35.f, 93.f, 41.f, 84.f, 50.f, 81.f, 54.f, 93.f, 59.f, 82.f, 66.f, 84.f, 75.f, 84.f, 83.f, 82.f, 91.f, 91.f
+  };
+  struct LineRun line0 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line1 =
+  {
+    { 12u, 6u },
+    { 12u, 6u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line2 =
+  {
+    { 18u, 7u },
+    { 18u, 7u },
+    52.f,
+    15.f,
+    -4.f,
+    5.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line3 =
+  {
+    { 25u, 9u },
+    { 25u, 10u },
+    66.f,
+    15.f,
+    -4.f,
+    5.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line4 =
+  {
+    { 34u, 14u },
+    { 35u, 14u },
+    95.f,
+    15.f,
+    -4.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line0 );
+  lines.PushBack( line1 );
+  lines.PushBack( line2 );
+  lines.PushBack( line3 );
+  lines.PushBack( line4 );
+
+  LayoutTextData data =
+  {
+    "Layout simple multi-line text",
+    "Hello world demo.\n"
+    "Layout different lines of text.",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    48u,
+    positions,
+    5u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    48u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutMultilineText02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutMultilineText02");
+
+  // Layout some lines of bidirectional text.
+
+  const std::string fontFamily1( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun1;
+  fontDescriptionRun1.characterRun.characterIndex = 0u;
+  fontDescriptionRun1.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun1.familyLength = fontFamily1.size();
+  fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
+  memcpy( fontDescriptionRun1.familyName, fontFamily1.c_str(), fontDescriptionRun1.familyLength );
+  fontDescriptionRun1.familyDefined = true;
+  fontDescriptionRun1.weightDefined = false;
+  fontDescriptionRun1.widthDefined = false;
+  fontDescriptionRun1.slantDefined = false;
+  fontDescriptionRun1.sizeDefined = false;
+
+  const std::string fontFamily2( "TizenSansHebrew" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun2;
+  fontDescriptionRun2.characterRun.characterIndex = 17u;
+  fontDescriptionRun2.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun2.familyLength = fontFamily2.size();
+  fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength];
+  memcpy( fontDescriptionRun2.familyName, fontFamily2.c_str(), fontDescriptionRun2.familyLength );
+  fontDescriptionRun2.familyDefined = true;
+  fontDescriptionRun2.weightDefined = false;
+  fontDescriptionRun2.widthDefined = false;
+  fontDescriptionRun2.slantDefined = false;
+  fontDescriptionRun2.sizeDefined = false;
+
+  const std::string fontFamily3( "TizenSansHebrew" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun3;
+  fontDescriptionRun3.characterRun.characterIndex = 28u;
+  fontDescriptionRun3.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun3.familyLength = fontFamily3.size();
+  fontDescriptionRun3.familyName = new char[fontDescriptionRun3.familyLength];
+  memcpy( fontDescriptionRun3.familyName, fontFamily3.c_str(), fontDescriptionRun3.familyLength );
+  fontDescriptionRun3.familyDefined = true;
+  fontDescriptionRun3.weightDefined = false;
+  fontDescriptionRun3.widthDefined = false;
+  fontDescriptionRun3.slantDefined = false;
+  fontDescriptionRun3.sizeDefined = false;
+
+  const std::string fontFamily4( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun4;
+  fontDescriptionRun4.characterRun.characterIndex = 38u;
+  fontDescriptionRun4.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun4.familyLength = fontFamily4.size();
+  fontDescriptionRun4.familyName = new char[fontDescriptionRun4.familyLength];
+  memcpy( fontDescriptionRun4.familyName, fontFamily4.c_str(), fontDescriptionRun4.familyLength );
+  fontDescriptionRun4.familyDefined = true;
+  fontDescriptionRun4.weightDefined = false;
+  fontDescriptionRun4.widthDefined = false;
+  fontDescriptionRun4.slantDefined = false;
+  fontDescriptionRun4.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun1 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun2 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun3 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun4 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(81.f, 120.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
+    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
+    1.f, 65.f, 12.f, 62.f, 19.f, 65.f, 24.f, 65.f, 32.f, 75.f, 37.f, 65.f, 45.f, 65.f, 50.f, 62.f, 58.f, 65.f, 66.f, 75.f,
+    1.f, 82.f, 10.f, 86.f, 18.f, 82.f, 22.f, 82.f, 25.f, 86.f, 34.f, 95.f, 38.f, 86.f, 49.f, 86.f, 59.f, 86.f, 65.f, 82.f, 68.f, 82.f, 77.f, 95.f,
+    0.f, 102.f, 10.f, 106.f, 18.f, 106.f, 30.f, 106.f, 39.f, 112.f
+  };
+  struct LineRun line0 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line1 =
+  {
+    { 12u, 10u },
+    { 12u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line2 =
+  {
+    { 22u, 6u },
+    { 22u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line3 =
+  {
+    { 28u, 10u },
+    { 28u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line4 =
+  {
+    { 38u, 12u },
+    { 38u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line5 =
+  {
+    { 50u, 5u },
+    { 50u, 5u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line0 );
+  lines.PushBack( line1 );
+  lines.PushBack( line2 );
+  lines.PushBack( line3 );
+  lines.PushBack( line4 );
+  lines.PushBack( line5 );
+
+  LayoutTextData data =
+  {
+    "Layout bidirectional text.",
+    "Hello world demo שלום עולם.\n"
+    "שלום עולם hello world demo.",
+    textArea,
+    4u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    55u,
+    positions,
+    6u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    55u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutMultilineText03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutMultilineText03");
+
+  // Layout a long word which doesn't fit in the width of the text area.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun;
+  fontDescriptionRun.characterRun.characterIndex = 0u;
+  fontDescriptionRun.characterRun.numberOfCharacters = 29u;
+  fontDescriptionRun.familyLength = fontFamily.size();
+  fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
+  memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength );
+  fontDescriptionRun.familyDefined = true;
+  fontDescriptionRun.weightDefined = false;
+  fontDescriptionRun.widthDefined = false;
+  fontDescriptionRun.slantDefined = false;
+  fontDescriptionRun.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(96.f, 60.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 6.f, 47.f, 6.f, 57.f, 6.f, 63.f, 2.f, 66.f, 2.f, 75.f, 2.f, 85.f, 6.f,
+    1.f, 26.f, 13.f, 26.f, 23.f, 22.f, 32.f, 26.f, 40.f, 22.f, 44.f, 22.f, 47.f, 26.f, 56.f, 26.f, 67.f, 26.f, 77.f, 26.f, 83.f, 22.f, 86.f, 22.f,
+    0.f, 42.f, 10.f, 46.f, 18.f, 46.f, 30.f, 46.f, 39.f, 52.f
+  };
+  struct LineRun line0 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    94.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line1 =
+  {
+    { 12u, 12u },
+    { 12u, 12u },
+    96.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line2 =
+  {
+    { 24u, 5u },
+    { 24u, 5u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line0 );
+  lines.PushBack( line1 );
+  lines.PushBack( line2 );
+
+  LayoutTextData data =
+  {
+    "Layout a long word which doesn't fit in the width of the text area.",
+    "Helloworlddemohelloworlddemo.",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    29u,
+    positions,
+    3u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    29u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutMultilineText04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutMultilineText04");
+
+  // Layout simple text ending with a \n. It has to add a void line at the end.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun;
+  fontDescriptionRun.characterRun.characterIndex = 0u;
+  fontDescriptionRun.characterRun.numberOfCharacters = 13u;
+  fontDescriptionRun.familyLength = fontFamily.size();
+  fontDescriptionRun.familyName = new char[fontDescriptionRun.familyLength];
+  memcpy( fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength );
+  fontDescriptionRun.familyDefined = true;
+  fontDescriptionRun.weightDefined = false;
+  fontDescriptionRun.widthDefined = false;
+  fontDescriptionRun.slantDefined = false;
+  fontDescriptionRun.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(83.f, 40.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 12.f, 82.f, 3.f
+  };
+  struct LineRun line0 =
+  {
+    { 0u, 13u },
+    { 0u, 13u },
+    83.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line1 =
+  {
+    { 13u, 0u },
+    { 13u, 0u },
+    0.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line0 );
+  lines.PushBack( line1 );
+
+  LayoutTextData data =
+  {
+    "Layout simple text ending with a \n.",
+    "Hello world.\n",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    13u,
+    positions,
+    2u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    13u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutMultilineText05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutMultilineText05");
+
+  // Layout simple text with one character with a different font size.
+
+  const std::string fontFamily( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun1;
+  fontDescriptionRun1.characterRun.characterIndex = 0u;
+  fontDescriptionRun1.characterRun.numberOfCharacters = 6u;
+  fontDescriptionRun1.familyLength = fontFamily.size();
+  fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
+  memcpy( fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength );
+  fontDescriptionRun1.familyDefined = true;
+  fontDescriptionRun1.weightDefined = false;
+  fontDescriptionRun1.widthDefined = false;
+  fontDescriptionRun1.slantDefined = false;
+  fontDescriptionRun1.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun2;
+  fontDescriptionRun2.characterRun.characterIndex = 6u;
+  fontDescriptionRun2.characterRun.numberOfCharacters = 1u;
+  fontDescriptionRun2.familyLength = fontFamily.size();
+  fontDescriptionRun2.familyName = new char[fontDescriptionRun2.familyLength];
+  memcpy( fontDescriptionRun2.familyName, fontFamily.c_str(), fontDescriptionRun2.familyLength );
+  fontDescriptionRun2.size = 1280u;
+  fontDescriptionRun2.familyDefined = true;
+  fontDescriptionRun2.weightDefined = false;
+  fontDescriptionRun2.widthDefined = false;
+  fontDescriptionRun2.slantDefined = false;
+  fontDescriptionRun2.sizeDefined = true;
+
+  FontDescriptionRun fontDescriptionRun3;
+  fontDescriptionRun3.characterRun.characterIndex = 7u;
+  fontDescriptionRun3.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun3.familyLength = fontFamily.size();
+  fontDescriptionRun3.familyName = new char[fontDescriptionRun3.familyLength];
+  memcpy( fontDescriptionRun3.familyName, fontFamily.c_str(), fontDescriptionRun3.familyLength );
+  fontDescriptionRun3.familyDefined = true;
+  fontDescriptionRun3.weightDefined = false;
+  fontDescriptionRun3.widthDefined = false;
+  fontDescriptionRun3.slantDefined = false;
+  fontDescriptionRun3.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun1 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun2 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun3 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(88.f, 53.f);
+  float positions[] =
+  {
+    1.f, 13.f, 12.f, 16.f, 20.f, 12.f, 24.f, 12.f, 27.f, 16.f, 36.f, 25.f, 40.f, 11.f, 59.f, 16.f, 69.f, 16.f, 75.f, 12.f, 78.f, 12.f, 87.f, 25.f,
+    0.f, 35.f, 10.f, 39.f, 18.f, 39.f, 30.f, 39.f, 39.f, 45.f
+  };
+  struct LineRun line0 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    88.f,
+    25.f,
+    -8.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line1 =
+  {
+    { 12u, 5u },
+    { 12u, 5u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line0 );
+  lines.PushBack( line1 );
+
+  LayoutTextData data =
+  {
+    "Layout simple text with one character with a different font size.",
+    "Hello world demo.",
+    textArea,
+    3u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    17u,
+    positions,
+    2u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    17u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextUpdateLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextUpdateLayout01");
+
+  // Layout some lines of bidirectional text. Update the paragraphs at the beginning.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 17u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 28u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 42u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 54u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 64u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun06.familyLength = fontHebrew.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun07;
+  fontDescriptionRun07.characterRun.characterIndex = 74u;
+  fontDescriptionRun07.characterRun.numberOfCharacters = 18u;
+  fontDescriptionRun07.familyLength = fontLatin.size();
+  fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength];
+  memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength );
+  fontDescriptionRun07.familyDefined = true;
+  fontDescriptionRun07.weightDefined = false;
+  fontDescriptionRun07.widthDefined = false;
+  fontDescriptionRun07.slantDefined = false;
+  fontDescriptionRun07.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun08;
+  fontDescriptionRun08.characterRun.characterIndex = 92u;
+  fontDescriptionRun08.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun08.familyLength = fontLatin.size();
+  fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength];
+  memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength );
+  fontDescriptionRun08.familyDefined = true;
+  fontDescriptionRun08.weightDefined = false;
+  fontDescriptionRun08.widthDefined = false;
+  fontDescriptionRun08.slantDefined = false;
+  fontDescriptionRun08.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun09;
+  fontDescriptionRun09.characterRun.characterIndex = 104u;
+  fontDescriptionRun09.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun09.familyLength = fontArabic.size();
+  fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength];
+  memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength );
+  fontDescriptionRun09.familyDefined = true;
+  fontDescriptionRun09.weightDefined = false;
+  fontDescriptionRun09.widthDefined = false;
+  fontDescriptionRun09.slantDefined = false;
+  fontDescriptionRun09.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun10;
+  fontDescriptionRun10.characterRun.characterIndex = 118u;
+  fontDescriptionRun10.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun10.familyLength = fontHebrew.size();
+  fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength];
+  memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength );
+  fontDescriptionRun10.familyDefined = true;
+  fontDescriptionRun10.weightDefined = false;
+  fontDescriptionRun10.widthDefined = false;
+  fontDescriptionRun10.slantDefined = false;
+  fontDescriptionRun10.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun11;
+  fontDescriptionRun11.characterRun.characterIndex = 128u;
+  fontDescriptionRun11.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun11.familyLength = fontLatin.size();
+  fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength];
+  memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength );
+  fontDescriptionRun11.familyDefined = true;
+  fontDescriptionRun11.weightDefined = false;
+  fontDescriptionRun11.widthDefined = false;
+  fontDescriptionRun11.slantDefined = false;
+  fontDescriptionRun11.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun12;
+  fontDescriptionRun12.characterRun.characterIndex = 145u;
+  fontDescriptionRun12.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun12.familyLength = fontHebrew.size();
+  fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength];
+  memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength );
+  fontDescriptionRun12.familyDefined = true;
+  fontDescriptionRun12.weightDefined = false;
+  fontDescriptionRun12.widthDefined = false;
+  fontDescriptionRun12.slantDefined = false;
+  fontDescriptionRun12.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun13;
+  fontDescriptionRun13.characterRun.characterIndex = 156u;
+  fontDescriptionRun13.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun13.familyLength = fontHebrew.size();
+  fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength];
+  memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength );
+  fontDescriptionRun13.familyDefined = true;
+  fontDescriptionRun13.weightDefined = false;
+  fontDescriptionRun13.widthDefined = false;
+  fontDescriptionRun13.slantDefined = false;
+  fontDescriptionRun13.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun14;
+  fontDescriptionRun14.characterRun.characterIndex = 166u;
+  fontDescriptionRun14.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun14.familyLength = fontLatin.size();
+  fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength];
+  memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength );
+  fontDescriptionRun14.familyDefined = true;
+  fontDescriptionRun14.weightDefined = false;
+  fontDescriptionRun14.widthDefined = false;
+  fontDescriptionRun14.slantDefined = false;
+  fontDescriptionRun14.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun15;
+  fontDescriptionRun15.characterRun.characterIndex = 178u;
+  fontDescriptionRun15.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun15.familyLength = fontArabic.size();
+  fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength];
+  memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength );
+  fontDescriptionRun15.familyDefined = true;
+  fontDescriptionRun15.weightDefined = false;
+  fontDescriptionRun15.widthDefined = false;
+  fontDescriptionRun15.slantDefined = false;
+  fontDescriptionRun15.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun07 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun08 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun09 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun10 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun11 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun12 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun13 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun14 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun15 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(92.f, 380.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
+    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
+    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
+    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
+    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
+    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
+    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
+    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
+    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
+    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
+    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
+    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
+    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
+    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
+    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
+    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
+    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+  };
+  struct LineRun line01 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line02 =
+  {
+    { 12u, 10u },
+    { 12u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line03 =
+  {
+    { 22u, 6u },
+    { 22u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line04 =
+  {
+    { 28u, 20u },
+    { 28u, 20u },
+    92.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line05 =
+  {
+    { 48u, 11u },
+    { 48u, 11u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line06 =
+  {
+    { 59u, 5u },
+    { 59u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line07 =
+  {
+    { 64u, 10u },
+    { 64u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line08 =
+  {
+    { 74u, 12u },
+    { 74u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line09 =
+  {
+    { 86u, 6u },
+    { 86u, 6u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line10 =
+  {
+    { 92u, 12u },
+    { 92u, 12u },
+    78.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line11 =
+  {
+    { 104u, 19u },
+    { 104u, 19u },
+    90.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line12 =
+  {
+    { 123u, 5u },
+    { 123u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line13 =
+  {
+    { 128u, 12u },
+    { 128u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line14 =
+  {
+    { 140u, 10u },
+    { 140u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line15 =
+  {
+    { 150u, 6u },
+    { 150u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line16 =
+  {
+    { 156u, 10u },
+    { 156u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line17 =
+  {
+    { 166u, 12u },
+    { 166u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line18 =
+  {
+    { 178u, 14u },
+    { 178u, 14u },
+    55.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line19 =
+  {
+    { 192u, 0u },
+    { 192u, 0u },
+    0.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+  lines.PushBack( line02 );
+  lines.PushBack( line03 );
+  lines.PushBack( line04 );
+  lines.PushBack( line05 );
+  lines.PushBack( line06 );
+  lines.PushBack( line07 );
+  lines.PushBack( line08 );
+  lines.PushBack( line09 );
+  lines.PushBack( line10 );
+  lines.PushBack( line11 );
+  lines.PushBack( line12 );
+  lines.PushBack( line13 );
+  lines.PushBack( line14 );
+  lines.PushBack( line15 );
+  lines.PushBack( line16 );
+  lines.PushBack( line17 );
+  lines.PushBack( line18 );
+  lines.PushBack( line19 );
+
+  LayoutTextData data =
+  {
+    "Layout bidirectional text.",
+    "Hello world demo שלום עולם.\n"
+    "مرحبا بالعالم hello world שלום עולם\n"
+    "שלום עולם hello world demo.\n"
+    "hello world مرحبا بالعالم שלום עולם\n"
+    "Hello world demo שלום עולם.\n"
+    "שלום עולם hello world مرحبا بالعالم\n",
+    textArea,
+    15u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    192u,
+    positions,
+    19u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    64u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextUpdateLayout02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextUpdateLayout02");
+
+  // Layout some lines of bidirectional text. Update the paragraphs at the middle.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 17u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 28u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 42u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 54u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 64u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun06.familyLength = fontHebrew.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun07;
+  fontDescriptionRun07.characterRun.characterIndex = 74u;
+  fontDescriptionRun07.characterRun.numberOfCharacters = 18u;
+  fontDescriptionRun07.familyLength = fontLatin.size();
+  fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength];
+  memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength );
+  fontDescriptionRun07.familyDefined = true;
+  fontDescriptionRun07.weightDefined = false;
+  fontDescriptionRun07.widthDefined = false;
+  fontDescriptionRun07.slantDefined = false;
+  fontDescriptionRun07.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun08;
+  fontDescriptionRun08.characterRun.characterIndex = 92u;
+  fontDescriptionRun08.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun08.familyLength = fontLatin.size();
+  fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength];
+  memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength );
+  fontDescriptionRun08.familyDefined = true;
+  fontDescriptionRun08.weightDefined = false;
+  fontDescriptionRun08.widthDefined = false;
+  fontDescriptionRun08.slantDefined = false;
+  fontDescriptionRun08.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun09;
+  fontDescriptionRun09.characterRun.characterIndex = 104u;
+  fontDescriptionRun09.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun09.familyLength = fontArabic.size();
+  fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength];
+  memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength );
+  fontDescriptionRun09.familyDefined = true;
+  fontDescriptionRun09.weightDefined = false;
+  fontDescriptionRun09.widthDefined = false;
+  fontDescriptionRun09.slantDefined = false;
+  fontDescriptionRun09.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun10;
+  fontDescriptionRun10.characterRun.characterIndex = 118u;
+  fontDescriptionRun10.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun10.familyLength = fontHebrew.size();
+  fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength];
+  memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength );
+  fontDescriptionRun10.familyDefined = true;
+  fontDescriptionRun10.weightDefined = false;
+  fontDescriptionRun10.widthDefined = false;
+  fontDescriptionRun10.slantDefined = false;
+  fontDescriptionRun10.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun11;
+  fontDescriptionRun11.characterRun.characterIndex = 128u;
+  fontDescriptionRun11.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun11.familyLength = fontLatin.size();
+  fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength];
+  memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength );
+  fontDescriptionRun11.familyDefined = true;
+  fontDescriptionRun11.weightDefined = false;
+  fontDescriptionRun11.widthDefined = false;
+  fontDescriptionRun11.slantDefined = false;
+  fontDescriptionRun11.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun12;
+  fontDescriptionRun12.characterRun.characterIndex = 145u;
+  fontDescriptionRun12.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun12.familyLength = fontHebrew.size();
+  fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength];
+  memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength );
+  fontDescriptionRun12.familyDefined = true;
+  fontDescriptionRun12.weightDefined = false;
+  fontDescriptionRun12.widthDefined = false;
+  fontDescriptionRun12.slantDefined = false;
+  fontDescriptionRun12.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun13;
+  fontDescriptionRun13.characterRun.characterIndex = 156u;
+  fontDescriptionRun13.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun13.familyLength = fontHebrew.size();
+  fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength];
+  memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength );
+  fontDescriptionRun13.familyDefined = true;
+  fontDescriptionRun13.weightDefined = false;
+  fontDescriptionRun13.widthDefined = false;
+  fontDescriptionRun13.slantDefined = false;
+  fontDescriptionRun13.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun14;
+  fontDescriptionRun14.characterRun.characterIndex = 166u;
+  fontDescriptionRun14.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun14.familyLength = fontLatin.size();
+  fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength];
+  memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength );
+  fontDescriptionRun14.familyDefined = true;
+  fontDescriptionRun14.weightDefined = false;
+  fontDescriptionRun14.widthDefined = false;
+  fontDescriptionRun14.slantDefined = false;
+  fontDescriptionRun14.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun15;
+  fontDescriptionRun15.characterRun.characterIndex = 178u;
+  fontDescriptionRun15.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun15.familyLength = fontArabic.size();
+  fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength];
+  memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength );
+  fontDescriptionRun15.familyDefined = true;
+  fontDescriptionRun15.weightDefined = false;
+  fontDescriptionRun15.widthDefined = false;
+  fontDescriptionRun15.slantDefined = false;
+  fontDescriptionRun15.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun07 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun08 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun09 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun10 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun11 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun12 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun13 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun14 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun15 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(92.f, 380.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
+    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
+    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
+    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
+    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
+    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
+    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
+    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
+    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
+    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
+    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
+    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
+    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
+    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
+    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
+    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
+    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+  };
+  struct LineRun line01 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line02 =
+  {
+    { 12u, 10u },
+    { 12u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line03 =
+  {
+    { 22u, 6u },
+    { 22u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line04 =
+  {
+    { 28u, 20u },
+    { 28u, 20u },
+    92.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line05 =
+  {
+    { 48u, 11u },
+    { 48u, 11u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line06 =
+  {
+    { 59u, 5u },
+    { 59u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line07 =
+  {
+    { 64u, 10u },
+    { 64u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line08 =
+  {
+    { 74u, 12u },
+    { 74u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line09 =
+  {
+    { 86u, 6u },
+    { 86u, 6u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line10 =
+  {
+    { 92u, 12u },
+    { 92u, 12u },
+    78.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line11 =
+  {
+    { 104u, 19u },
+    { 104u, 19u },
+    90.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line12 =
+  {
+    { 123u, 5u },
+    { 123u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line13 =
+  {
+    { 128u, 12u },
+    { 128u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line14 =
+  {
+    { 140u, 10u },
+    { 140u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line15 =
+  {
+    { 150u, 6u },
+    { 150u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line16 =
+  {
+    { 156u, 10u },
+    { 156u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line17 =
+  {
+    { 166u, 12u },
+    { 166u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line18 =
+  {
+    { 178u, 14u },
+    { 178u, 14u },
+    55.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line19 =
+  {
+    { 192u, 0u },
+    { 192u, 0u },
+    0.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+  lines.PushBack( line02 );
+  lines.PushBack( line03 );
+  lines.PushBack( line04 );
+  lines.PushBack( line05 );
+  lines.PushBack( line06 );
+  lines.PushBack( line07 );
+  lines.PushBack( line08 );
+  lines.PushBack( line09 );
+  lines.PushBack( line10 );
+  lines.PushBack( line11 );
+  lines.PushBack( line12 );
+  lines.PushBack( line13 );
+  lines.PushBack( line14 );
+  lines.PushBack( line15 );
+  lines.PushBack( line16 );
+  lines.PushBack( line17 );
+  lines.PushBack( line18 );
+  lines.PushBack( line19 );
+
+  LayoutTextData data =
+  {
+    "Layout bidirectional text.",
+    "Hello world demo שלום עולם.\n"
+    "مرحبا بالعالم hello world שלום עולם\n"
+    "שלום עולם hello world demo.\n"
+    "hello world مرحبا بالعالم שלום עולם\n"
+    "Hello world demo שלום עולם.\n"
+    "שלום עולם hello world مرحبا بالعالم\n",
+    textArea,
+    15u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    192u,
+    positions,
+    19u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    64u,
+    64u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextUpdateLayout03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextUpdateLayout03");
+
+  // Layout some lines of bidirectional text. Update the paragraphs at the middle.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 17u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 28u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 42u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 54u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 64u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun06.familyLength = fontHebrew.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontHebrew.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun07;
+  fontDescriptionRun07.characterRun.characterIndex = 74u;
+  fontDescriptionRun07.characterRun.numberOfCharacters = 18u;
+  fontDescriptionRun07.familyLength = fontLatin.size();
+  fontDescriptionRun07.familyName = new char[fontDescriptionRun07.familyLength];
+  memcpy( fontDescriptionRun07.familyName, fontLatin.c_str(), fontDescriptionRun07.familyLength );
+  fontDescriptionRun07.familyDefined = true;
+  fontDescriptionRun07.weightDefined = false;
+  fontDescriptionRun07.widthDefined = false;
+  fontDescriptionRun07.slantDefined = false;
+  fontDescriptionRun07.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun08;
+  fontDescriptionRun08.characterRun.characterIndex = 92u;
+  fontDescriptionRun08.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun08.familyLength = fontLatin.size();
+  fontDescriptionRun08.familyName = new char[fontDescriptionRun08.familyLength];
+  memcpy( fontDescriptionRun08.familyName, fontLatin.c_str(), fontDescriptionRun08.familyLength );
+  fontDescriptionRun08.familyDefined = true;
+  fontDescriptionRun08.weightDefined = false;
+  fontDescriptionRun08.widthDefined = false;
+  fontDescriptionRun08.slantDefined = false;
+  fontDescriptionRun08.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun09;
+  fontDescriptionRun09.characterRun.characterIndex = 104u;
+  fontDescriptionRun09.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun09.familyLength = fontArabic.size();
+  fontDescriptionRun09.familyName = new char[fontDescriptionRun09.familyLength];
+  memcpy( fontDescriptionRun09.familyName, fontArabic.c_str(), fontDescriptionRun09.familyLength );
+  fontDescriptionRun09.familyDefined = true;
+  fontDescriptionRun09.weightDefined = false;
+  fontDescriptionRun09.widthDefined = false;
+  fontDescriptionRun09.slantDefined = false;
+  fontDescriptionRun09.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun10;
+  fontDescriptionRun10.characterRun.characterIndex = 118u;
+  fontDescriptionRun10.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun10.familyLength = fontHebrew.size();
+  fontDescriptionRun10.familyName = new char[fontDescriptionRun10.familyLength];
+  memcpy( fontDescriptionRun10.familyName, fontHebrew.c_str(), fontDescriptionRun10.familyLength );
+  fontDescriptionRun10.familyDefined = true;
+  fontDescriptionRun10.weightDefined = false;
+  fontDescriptionRun10.widthDefined = false;
+  fontDescriptionRun10.slantDefined = false;
+  fontDescriptionRun10.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun11;
+  fontDescriptionRun11.characterRun.characterIndex = 128u;
+  fontDescriptionRun11.characterRun.numberOfCharacters = 17u;
+  fontDescriptionRun11.familyLength = fontLatin.size();
+  fontDescriptionRun11.familyName = new char[fontDescriptionRun11.familyLength];
+  memcpy( fontDescriptionRun11.familyName, fontLatin.c_str(), fontDescriptionRun11.familyLength );
+  fontDescriptionRun11.familyDefined = true;
+  fontDescriptionRun11.weightDefined = false;
+  fontDescriptionRun11.widthDefined = false;
+  fontDescriptionRun11.slantDefined = false;
+  fontDescriptionRun11.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun12;
+  fontDescriptionRun12.characterRun.characterIndex = 145u;
+  fontDescriptionRun12.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun12.familyLength = fontHebrew.size();
+  fontDescriptionRun12.familyName = new char[fontDescriptionRun12.familyLength];
+  memcpy( fontDescriptionRun12.familyName, fontHebrew.c_str(), fontDescriptionRun12.familyLength );
+  fontDescriptionRun12.familyDefined = true;
+  fontDescriptionRun12.weightDefined = false;
+  fontDescriptionRun12.widthDefined = false;
+  fontDescriptionRun12.slantDefined = false;
+  fontDescriptionRun12.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun13;
+  fontDescriptionRun13.characterRun.characterIndex = 156u;
+  fontDescriptionRun13.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun13.familyLength = fontHebrew.size();
+  fontDescriptionRun13.familyName = new char[fontDescriptionRun13.familyLength];
+  memcpy( fontDescriptionRun13.familyName, fontHebrew.c_str(), fontDescriptionRun13.familyLength );
+  fontDescriptionRun13.familyDefined = true;
+  fontDescriptionRun13.weightDefined = false;
+  fontDescriptionRun13.widthDefined = false;
+  fontDescriptionRun13.slantDefined = false;
+  fontDescriptionRun13.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun14;
+  fontDescriptionRun14.characterRun.characterIndex = 166u;
+  fontDescriptionRun14.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun14.familyLength = fontLatin.size();
+  fontDescriptionRun14.familyName = new char[fontDescriptionRun14.familyLength];
+  memcpy( fontDescriptionRun14.familyName, fontLatin.c_str(), fontDescriptionRun14.familyLength );
+  fontDescriptionRun14.familyDefined = true;
+  fontDescriptionRun14.weightDefined = false;
+  fontDescriptionRun14.widthDefined = false;
+  fontDescriptionRun14.slantDefined = false;
+  fontDescriptionRun14.sizeDefined = false;
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun15;
+  fontDescriptionRun15.characterRun.characterIndex = 178u;
+  fontDescriptionRun15.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun15.familyLength = fontArabic.size();
+  fontDescriptionRun15.familyName = new char[fontDescriptionRun15.familyLength];
+  memcpy( fontDescriptionRun15.familyName, fontArabic.c_str(), fontDescriptionRun15.familyLength );
+  fontDescriptionRun15.familyDefined = true;
+  fontDescriptionRun15.weightDefined = false;
+  fontDescriptionRun15.widthDefined = false;
+  fontDescriptionRun15.slantDefined = false;
+  fontDescriptionRun15.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun07 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun08 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun09 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun10 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun11 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun12 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun13 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun14 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun15 );
+  Size textArea(100.f, 300.f);
+  Size layoutSize(92.f, 380.f);
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
+    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
+    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
+    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
+    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
+    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
+    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
+    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
+    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
+    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
+    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
+    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
+    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
+    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
+    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
+    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
+    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+  };
+  struct LineRun line01 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line02 =
+  {
+    { 12u, 10u },
+    { 12u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line03 =
+  {
+    { 22u, 6u },
+    { 22u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line04 =
+  {
+    { 28u, 20u },
+    { 28u, 20u },
+    92.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line05 =
+  {
+    { 48u, 11u },
+    { 48u, 11u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line06 =
+  {
+    { 59u, 5u },
+    { 59u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line07 =
+  {
+    { 64u, 10u },
+    { 64u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line08 =
+  {
+    { 74u, 12u },
+    { 74u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line09 =
+  {
+    { 86u, 6u },
+    { 86u, 6u },
+    43.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line10 =
+  {
+    { 92u, 12u },
+    { 92u, 12u },
+    78.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line11 =
+  {
+    { 104u, 19u },
+    { 104u, 19u },
+    90.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line12 =
+  {
+    { 123u, 5u },
+    { 123u, 5u },
+    31.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line13 =
+  {
+    { 128u, 12u },
+    { 128u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line14 =
+  {
+    { 140u, 10u },
+    { 140u, 10u },
+    76.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line15 =
+  {
+    { 150u, 6u },
+    { 150u, 6u },
+    36.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line16 =
+  {
+    { 156u, 10u },
+    { 156u, 10u },
+    67.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line17 =
+  {
+    { 166u, 12u },
+    { 166u, 12u },
+    79.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line18 =
+  {
+    { 178u, 14u },
+    { 178u, 14u },
+    55.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line19 =
+  {
+    { 192u, 0u },
+    { 192u, 0u },
+    0.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    false
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+  lines.PushBack( line02 );
+  lines.PushBack( line03 );
+  lines.PushBack( line04 );
+  lines.PushBack( line05 );
+  lines.PushBack( line06 );
+  lines.PushBack( line07 );
+  lines.PushBack( line08 );
+  lines.PushBack( line09 );
+  lines.PushBack( line10 );
+  lines.PushBack( line11 );
+  lines.PushBack( line12 );
+  lines.PushBack( line13 );
+  lines.PushBack( line14 );
+  lines.PushBack( line15 );
+  lines.PushBack( line16 );
+  lines.PushBack( line17 );
+  lines.PushBack( line18 );
+  lines.PushBack( line19 );
+
+  LayoutTextData data =
+  {
+    "Layout bidirectional text.",
+    "Hello world demo שלום עולם.\n"
+    "مرحبا بالعالم hello world שלום עולם\n"
+    "שלום עולם hello world demo.\n"
+    "hello world مرحبا بالعالم שלום עולם\n"
+    "Hello world demo שלום עולם.\n"
+    "שלום עולם hello world مرحبا بالعالم\n",
+    textArea,
+    15u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    192u,
+    positions,
+    19u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    128u,
+    64u,
+    false,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutEllipsis01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutEllipsis01");
+
+  // Layout single-line LTR text with ellipsis.
+
+  const std::string fontLatin( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 51u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+
+  struct LineRun line01 =
+  {
+    { 0u, 13u },
+    { 0u, 13u },
+    93.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    true
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, 83.f, 2.f
+  };
+
+  Size textArea( 100.f, 50.f );
+  Size layoutSize( 100.f, 20.f );
+
+  LayoutTextData data =
+  {
+    "Layout single-line LTR text with ellipsis.",
+    "Hello world demo hello world demo hello world demo.",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    13u,
+    positions,
+    1u,
+    lines.Begin(),
+    LayoutEngine::SINGLE_LINE_BOX,
+    0u,
+    51u,
+    true,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutEllipsis02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutEllipsis02");
+
+  // Layout multi-line LTR text with ellipsis.
+
+  const std::string fontLatin( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 51u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+
+  struct LineRun line01 =
+  {
+    { 0u, 12u },
+    { 0u, 12u },
+    81.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line02 =
+  {
+    { 12u, 12u },
+    { 12u, 12u },
+    93.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    true
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+  lines.PushBack( line02 );
+
+  float positions[] =
+  {
+    1.f,  3.f, 12.f,  6.f, 20.f,  2.f, 24.f,  2.f, 27.f,  6.f, 36.f, 15.f, 40.f,  6.f, 51.f,  6.f, 61.f,  6.f, 67.f,  2.f, 70.f,  2.f, 79.f, 15.f,
+    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 22.f, 53.f, 26.f, 61.f, 22.f, 65.f, 22.f, 68.f, 26.f, 77.f, 35.f, 81.f, 26.f
+  };
+
+  Size textArea( 100.f, 50.f );
+  Size layoutSize( 100.f, 60.f );
+
+  LayoutTextData data =
+  {
+    "Layout multi-line LTR text with ellipsis.",
+    "Hello world demo hello world demo hello world demo.",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    24u,
+    positions,
+    2u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    51u,
+    true,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutEllipsis03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutEllipsis03");
+
+  // Layout single-line RTL text with ellipsis.
+
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun01.familyLength = fontHebrew.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 10u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun02.familyLength = fontArabic.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 24u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun03.familyLength = fontHebrew.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontHebrew.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 34u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun04.familyLength = fontArabic.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontArabic.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 58u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 15u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  struct LineRun line01 =
+  {
+    { 0u, 16u },
+    { 0u, 16u },
+    95.f,
+    15.f,
+    -5.f,
+    0.f,
+    0.f,
+    false,
+    true
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+
+  float positions[] =
+  {
+    1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f,
+  };
+
+  Size textArea( 100.f, 50.f );
+  Size layoutSize( 100.f, 20.f );
+
+  LayoutTextData data =
+  {
+    "Layout single-line RTL text with ellipsis.",
+    "שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    16u,
+    positions,
+    1u,
+    lines.Begin(),
+    LayoutEngine::SINGLE_LINE_BOX,
+    0u,
+    72u,
+    true,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextLayoutEllipsis04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextLayoutEllipsis04");
+
+  // Layout multi-line RTL text with ellipsis.
+
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun01.familyLength = fontHebrew.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 10u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun02.familyLength = fontArabic.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 24u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun03.familyLength = fontHebrew.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontHebrew.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 34u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun04.familyLength = fontArabic.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontArabic.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 58u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 15u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  struct LineRun line01 =
+  {
+    { 0u, 16u },
+    { 0u, 16u },
+    96.f,
+    15.f,
+    -5.f,
+    3.f,
+    0.f,
+    false,
+    false
+  };
+  struct LineRun line02 =
+  {
+    { 16u, 18u },
+    { 16u, 18u },
+    97.f,
+    15.f,
+    -5.f,
+    4.f,
+    0.f,
+    false,
+    true
+  };
+  Vector<LineRun> lines;
+  lines.PushBack( line01 );
+  lines.PushBack( line02 );
+
+  float positions[] =
+  {
+    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f,  4.f, 94.f, 15.f,
+    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f, 32.f, 25.f, 43.f, 22.f, 50.f, 25.f, 55.f, 25.f, 63.f, 35.f, 68.f, 25.f, 76.f, 25.f, 81.f, 22.f, 89.f, 25.f, 97.f, 35.f
+  };
+
+  Size textArea( 100.f, 50.f );
+  Size layoutSize( 100.f, 60.f );
+
+  LayoutTextData data =
+  {
+    "Layout single-line RTL text with ellipsis.",
+    "שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم שלום עולם مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    layoutSize,
+    34u,
+    positions,
+    2u,
+    lines.Begin(),
+    LayoutEngine::MULTI_LINE_BOX,
+    0u,
+    72u,
+    true,
+    true
+  };
+
+  if( !LayoutTextTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextReorderLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextReorderLayout01");
+
+  // Reorder lines. No right to left characters.
+
+  const std::string fontLatin( "TizenSans" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 11u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+
+  float positions[] =
+  {
+    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f
+  };
+
+  Size textArea( 100.f, 300.f );
+
+  ReLayoutRightToLeftLinesData data =
+  {
+    "Text with no right to left text.",
+    "Hello world",
+    textArea,
+    1u,
+    fontDescriptionRuns.Begin(),
+    11u,
+    positions,
+    0u,
+    11u
+  };
+
+  if( !ReLayoutRightToLeftLinesTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextReorderLayout02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextReorderLayout02");
+
+  // Reorder lines of the first paragraph.
+
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun01.familyLength = fontHebrew.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 10u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun02.familyLength = fontArabic.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 24u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 38u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun04.familyLength = fontHebrew.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 58u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 15u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] =
+  {
+    87.f,  5.f, 79.f,  2.f, 74.f,  5.f, 66.f,  5.f, 61.f, 15.f, 53.f,  5.f, 48.f,  5.f, 41.f,  2.f, 32.f,  5.f, 27.f, 15.f, 20.f,  7.f, 15.f,  9.f,  8.f,  8.f,  5.f,  8.f,  4.f,  4.f,  0.f, 15.f,
+    23.f, 28.f, 22.f, 24.f, 17.f, 24.f, 12.f, 27.f, 10.f, 24.f,  5.f, 24.f,  0.f, 27.f,  0.f, 35.f,
+    0.f, 47.f, 7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f,
+    1.f, 65.f, 9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f,
+    1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f,
+    0.f, 108.f, 5.f, 104.f, 6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f
+  };
+
+  Size textArea( 100.f, 300.f );
+
+  ReLayoutRightToLeftLinesData data =
+  {
+    "Paragraphs with right to left text.",
+    "שלום עולם مرحبا بالعالم\n"
+    "مرحبا بالعالم שלום עולם\n"
+    "שלום עולם مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    72u,
+    positions,
+    0u,
+    24u
+  };
+
+  if( !ReLayoutRightToLeftLinesTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextReorderLayout03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextReorderLayout03");
+
+  // Reorder lines of the mid paragraph.
+
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun01.familyLength = fontHebrew.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 10u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun02.familyLength = fontArabic.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 24u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 38u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun04.familyLength = fontHebrew.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 58u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 15u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] =
+  {
+    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f, 4.f, 94.f, 15.f,
+    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f,
+    86.f, 47.f, 81.f, 49.f, 74.f, 48.f, 71.f, 48.f, 70.f, 44.f, 66.f, 55.f, 62.f, 48.f, 61.f, 44.f, 56.f, 44.f, 51.f, 47.f, 49.f, 44.f, 44.f, 44.f, 39.f, 47.f, 36.f, 55.f, 26.f, 45.f, 18.f, 42.f, 13.f, 45.f,  5.f, 45.f,  0.f, 55.f,
+    22.f, 65.f, 17.f, 65.f, 10.f, 62.f,  1.f, 65.f,  0.f, 75.f,
+    1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f,
+    0.f, 108.f,  5.f, 104.f,  6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f
+  };
+
+  Size textArea( 100.f, 300.f );
+
+  ReLayoutRightToLeftLinesData data =
+  {
+    "Paragraphs with right to left text.",
+    "שלום עולם مرحبا بالعالم\n"
+    "مرحبا بالعالم שלום עולם\n"
+    "שלום עולם مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    72u,
+    positions,
+    24u,
+    24u
+  };
+
+  if( !ReLayoutRightToLeftLinesTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextReorderLayout04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextReorderLayout04");
+
+  // Reorder lines of the last paragraph.
+
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun01.familyLength = fontHebrew.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontHebrew.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 10u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun02.familyLength = fontArabic.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontArabic.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 24u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 38u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun04.familyLength = fontHebrew.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontHebrew.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun05.familyLength = fontHebrew.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontHebrew.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 58u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 15u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] =
+  {
+    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f, 4.f, 94.f, 15.f,
+    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f,
+    0.f, 47.f,  7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f,
+    1.f, 65.f,  9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f,
+    87.f, 85.f, 79.f, 82.f, 74.f, 85.f, 66.f, 85.f, 61.f, 95.f, 53.f, 85.f, 48.f, 85.f, 41.f, 82.f, 32.f, 85.f, 27.f, 95.f, 20.f, 87.f, 15.f, 89.f,  8.f, 88.f,  5.f, 88.f,  4.f, 84.f,  0.f, 95.f,
+    28.f, 108.f, 27.f, 104.f, 22.f, 104.f, 17.f, 107.f, 15.f, 104.f, 10.f, 104.f,  5.f, 107.f,  2.f, 113.f
+  };
+
+  Size textArea( 100.f, 300.f );
+
+  ReLayoutRightToLeftLinesData data =
+  {
+    "Paragraphs with right to left text.",
+    "שלום עולם مرحبا بالعالم\n"
+    "مرحبا بالعالم שלום עולם\n"
+    "שלום עולם مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    72u,
+    positions,
+    48u,
+    24u
+  };
+
+  if( !ReLayoutRightToLeftLinesTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign01");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Begin alignment for the first paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_BEGIN,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    0u,
+    22u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign02");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, 2.f, 60.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Begin alignment for the mid paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_BEGIN,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    22u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign03");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Begin alignment for the last paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_BEGIN,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    48u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign04");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 10.f, 16.f, 0.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Center alignment for the first paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_CENTER,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    0u,
+    22u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign05");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, -1.f, 30.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Center alignment for the mid paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_CENTER,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    22u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign06(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign06");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, 0.f, 0.f, 10.f, 20.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "Center alignment for the last paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_CENTER,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    48u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign07(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign07");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 20.f, 33.f, 0.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "End alignment for the first paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_END,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    0u,
+    22u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign08(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign08");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, -4.f, 0.f, 0.f, 0.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "End alignment for the mid paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_END,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    22u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+int UtcDaliTextAlign09(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliTextAlign09");
+
+  // Calculate text alignment.
+
+  const std::string fontLatin( "TizenSans" );
+  const std::string fontHebrew( "TizenSansHebrew" );
+  const std::string fontArabic( "TizenSansArabic" );
+
+  // Set a known font description
+  FontDescriptionRun fontDescriptionRun01;
+  fontDescriptionRun01.characterRun.characterIndex = 0u;
+  fontDescriptionRun01.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun01.familyLength = fontLatin.size();
+  fontDescriptionRun01.familyName = new char[fontDescriptionRun01.familyLength];
+  memcpy( fontDescriptionRun01.familyName, fontLatin.c_str(), fontDescriptionRun01.familyLength );
+  fontDescriptionRun01.familyDefined = true;
+  fontDescriptionRun01.weightDefined = false;
+  fontDescriptionRun01.widthDefined = false;
+  fontDescriptionRun01.slantDefined = false;
+  fontDescriptionRun01.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun02;
+  fontDescriptionRun02.characterRun.characterIndex = 12u;
+  fontDescriptionRun02.characterRun.numberOfCharacters = 10u;
+  fontDescriptionRun02.familyLength = fontHebrew.size();
+  fontDescriptionRun02.familyName = new char[fontDescriptionRun02.familyLength];
+  memcpy( fontDescriptionRun02.familyName, fontHebrew.c_str(), fontDescriptionRun02.familyLength );
+  fontDescriptionRun02.familyDefined = true;
+  fontDescriptionRun02.weightDefined = false;
+  fontDescriptionRun02.widthDefined = false;
+  fontDescriptionRun02.slantDefined = false;
+  fontDescriptionRun02.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun03;
+  fontDescriptionRun03.characterRun.characterIndex = 22u;
+  fontDescriptionRun03.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun03.familyLength = fontArabic.size();
+  fontDescriptionRun03.familyName = new char[fontDescriptionRun03.familyLength];
+  memcpy( fontDescriptionRun03.familyName, fontArabic.c_str(), fontDescriptionRun03.familyLength );
+  fontDescriptionRun03.familyDefined = true;
+  fontDescriptionRun03.weightDefined = false;
+  fontDescriptionRun03.widthDefined = false;
+  fontDescriptionRun03.slantDefined = false;
+  fontDescriptionRun03.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun04;
+  fontDescriptionRun04.characterRun.characterIndex = 36u;
+  fontDescriptionRun04.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun04.familyLength = fontLatin.size();
+  fontDescriptionRun04.familyName = new char[fontDescriptionRun04.familyLength];
+  memcpy( fontDescriptionRun04.familyName, fontLatin.c_str(), fontDescriptionRun04.familyLength );
+  fontDescriptionRun04.familyDefined = true;
+  fontDescriptionRun04.weightDefined = false;
+  fontDescriptionRun04.widthDefined = false;
+  fontDescriptionRun04.slantDefined = false;
+  fontDescriptionRun04.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun05;
+  fontDescriptionRun05.characterRun.characterIndex = 48u;
+  fontDescriptionRun05.characterRun.numberOfCharacters = 12u;
+  fontDescriptionRun05.familyLength = fontLatin.size();
+  fontDescriptionRun05.familyName = new char[fontDescriptionRun05.familyLength];
+  memcpy( fontDescriptionRun05.familyName, fontLatin.c_str(), fontDescriptionRun05.familyLength );
+  fontDescriptionRun05.familyDefined = true;
+  fontDescriptionRun05.weightDefined = false;
+  fontDescriptionRun05.widthDefined = false;
+  fontDescriptionRun05.slantDefined = false;
+  fontDescriptionRun05.sizeDefined = false;
+
+  FontDescriptionRun fontDescriptionRun06;
+  fontDescriptionRun06.characterRun.characterIndex = 60u;
+  fontDescriptionRun06.characterRun.numberOfCharacters = 14u;
+  fontDescriptionRun06.familyLength = fontArabic.size();
+  fontDescriptionRun06.familyName = new char[fontDescriptionRun06.familyLength];
+  memcpy( fontDescriptionRun06.familyName, fontArabic.c_str(), fontDescriptionRun06.familyLength );
+  fontDescriptionRun06.familyDefined = true;
+  fontDescriptionRun06.weightDefined = false;
+  fontDescriptionRun06.widthDefined = false;
+  fontDescriptionRun06.slantDefined = false;
+  fontDescriptionRun06.sizeDefined = false;
+
+  Vector<FontDescriptionRun> fontDescriptionRuns;
+  fontDescriptionRuns.PushBack( fontDescriptionRun01 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun02 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun03 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun04 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun05 );
+  fontDescriptionRuns.PushBack( fontDescriptionRun06 );
+
+  float positions[] = { 0.f, 0.f, 0.f, 0.f, 20.f, 40.f };
+
+  Size textArea( 100.f, 300.f );
+  AlignData data =
+  {
+    "End alignment for the last paragraph.",
+    "Hello world שלום עולם\nمرحبا بالعالم Hello world\nHello world مرحبا بالعالم.",
+    textArea,
+    6u,
+    fontDescriptionRuns.Begin(),
+    LayoutEngine::HORIZONTAL_ALIGN_END,
+    LayoutEngine::VERTICAL_ALIGN_TOP,
+    48u,
+    26u,
+    6u,
+    positions
+  };
+
+  if( !AlignTest( data ) )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
index f602e8a..7fc8f71 100644 (file)
@@ -245,7 +245,6 @@ bool ValidateFontTest( const ValidateFontsData& data )
   const FontId defaultFontId = fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + data.defaultFont,
                                                      data.defaultFontSize );
 
-  // To be completed ...
   Vector<FontRun> fontRuns;
 
   // 3) Validate the fonts.
index 0dd3144..9e830ec 100644 (file)
@@ -117,8 +117,12 @@ bool ShapeInfoTest( const ShapeInfoData& data )
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
index 18faa9e..fdde254 100644 (file)
@@ -70,8 +70,12 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
@@ -142,8 +146,12 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
   Size textArea(100.f, 60.f);
   Size layoutSize;
 
+  const Vector<FontDescriptionRun> fontDescriptions;
+  const LayoutOptions options;
   CreateTextModel( data.text,
                    textArea,
+                   fontDescriptions,
+                   options,
                    layoutSize,
                    logicalModel,
                    visualModel );
index 10ef2a0..bf5f24b 100644 (file)
@@ -72,6 +72,8 @@ LIST(APPEND TC_SOURCES
    dali-toolkit-test-utils/toolkit-tts-player.cpp
    dali-toolkit-test-utils/dummy-control.cpp
    dali-toolkit-test-utils/dali-test-suite-utils.cpp
+   dali-toolkit-test-utils/test-animation-data.cpp
+   dali-toolkit-test-utils/test-button.cpp
    dali-toolkit-test-utils/test-application.cpp
    dali-toolkit-test-utils/test-platform-abstraction.cpp
    dali-toolkit-test-utils/test-gesture-manager.cpp
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.cpp
new file mode 100644 (file)
index 0000000..57c1e41
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 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 <dali/dali.h>
+#include <test-animation-data.h>
+
+using namespace Dali;
+
+namespace Test
+{
+
+TestAnimationData::TestAnimationData()
+{
+}
+
+TestAnimationData::~TestAnimationData()
+{
+}
+
+TestAnimationData::AnimationDataElement::AnimationDataElement()
+: alphaFunction( AlphaFunction::DEFAULT ),
+  timePeriodDelay( 0.0f ),
+  timePeriodDuration( 1.0f )
+{
+}
+
+void TestAnimationData::Add( AnimationDataElement* animationDataElement )
+{
+  mAnimationDataList.PushBack( animationDataElement );
+}
+
+std::size_t TestAnimationData::Size() const
+{
+  return mAnimationDataList.Size();
+}
+
+void TestAnimationData::Clear()
+{
+  AnimationDataList::Iterator end = mAnimationDataList.End();
+  for( AnimationDataList::Iterator iter = mAnimationDataList.Begin(); iter != end; ++iter )
+  {
+    delete ( *iter );
+  }
+  mAnimationDataList.Clear();
+}
+
+
+void NewAnimator( const Property::Map& map, TestAnimationData::AnimationDataElement& element )
+{
+  // Now set the properties, or create children
+  for( unsigned int i = 0, animationMapCount = map.Count(); i < animationMapCount; ++i )
+  {
+    const StringValuePair& pair( map.GetPair( i ) );
+    const std::string& key( pair.first );
+    const Property::Value& value( pair.second );
+
+    if( key == "actor" || key == "target" )
+    {
+      element.target = value.Get< std::string >();
+    }
+    else if( key == "property" )
+    {
+      element.property = value.Get< std::string >();
+    }
+    else if( key == "value" )
+    {
+      element.value = value;
+    }
+    else if( key == "alphaFunction" )
+    {
+      std::string alphaFunctionValue = value.Get< std::string >();
+
+      if( alphaFunctionValue == "LINEAR" )
+      {
+        element.alphaFunction = AlphaFunction::LINEAR;
+      }
+      else if( alphaFunctionValue == "REVERSE" )
+      {
+        element.alphaFunction = AlphaFunction::REVERSE;
+      }
+      else if( alphaFunctionValue == "EASE_IN_SQUARE" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_IN_SQUARE;
+      }
+      else if( alphaFunctionValue == "EASE_OUT_SQUARE" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_OUT_SQUARE;
+      }
+      else if( alphaFunctionValue == "EASE_IN" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_IN;
+      }
+      else if( alphaFunctionValue == "EASE_OUT" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_OUT;
+      }
+      else if( alphaFunctionValue == "EASE_IN_OUT" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_IN_OUT;
+      }
+      else if( alphaFunctionValue == "EASE_IN_SINE" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_IN_SINE;
+      }
+      else if( alphaFunctionValue == "EASE_OUT_SINE" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_OUT_SINE;
+      }
+      else if( alphaFunctionValue == "EASE_IN_OUT_SINE" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_IN_OUT_SINE;
+      }
+      else if( alphaFunctionValue == "BOUNCE" )
+      {
+        element.alphaFunction = AlphaFunction::BOUNCE;
+      }
+      else if( alphaFunctionValue == "SIN" )
+      {
+        element.alphaFunction = AlphaFunction::SIN;
+      }
+      else if( alphaFunctionValue == "EASE_OUT_BACK" )
+      {
+        element.alphaFunction = AlphaFunction::EASE_OUT_BACK;
+      }
+    }
+    else if( key == "timePeriod" )
+    {
+      Property::Map timeMap = value.Get< Property::Map >();
+      for( unsigned int i = 0; i < timeMap.Count(); ++i )
+      {
+        const StringValuePair& pair( timeMap.GetPair( i ) );
+        if( pair.first == "delay" )
+        {
+          element.timePeriodDelay = pair.second.Get< float >();
+        }
+        else if( pair.first == "duration" )
+        {
+          element.timePeriodDuration = pair.second.Get< float >();
+        }
+      }
+    }
+    else if( key == "animator" )
+    {
+      if( value.GetType() == Property::MAP )
+      {
+        Property::Map* map = value.GetMap();
+        const Property::Map& mapref = *map;
+        NewAnimator( mapref, element ); // Merge the map into element
+      }
+    }
+  }
+}
+
+void NewAnimation( const Property::Map& map, TestAnimationData& outputAnimationData )
+{
+  TestAnimationData::AnimationDataElement* element = new TestAnimationData::AnimationDataElement();
+  NewAnimator( map, *element );
+
+  outputAnimationData.Add( element );
+}
+
+void NewAnimation( const Property::Array& array, TestAnimationData& outputAnimationData )
+{
+  for(unsigned int i=0; i<array.Size(); ++i )
+  {
+    TestAnimationData::AnimationDataElement* element = new TestAnimationData::AnimationDataElement();
+    const Property::Value& value = array.GetElementAt(i);
+    if( value.GetType() == Property::MAP )
+    {
+      Property::Map* map = value.GetMap();
+      NewAnimator( *map, *element );
+      outputAnimationData.Add( element );
+    }
+  }
+}
+
+} // Test
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-animation-data.h
new file mode 100644 (file)
index 0000000..ffd5b17
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef DALI_TOOLKIT_TEST_TEST_ANIMATION_DATA_H
+#define DALI_TOOLKIT_TEST_TEST_ANIMATION_DATA_H
+
+/*
+ * Copyright (c) 2016 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 <dali/dali.h>
+#include <string>
+
+namespace Test
+{
+
+class TestAnimationData
+{
+public:
+  TestAnimationData();
+  ~TestAnimationData();
+
+  /**
+   * @brief AnimationDataElement Describes one part of an animation.
+   */
+  struct AnimationDataElement
+  {
+    std::string target;
+    std::string property;
+    Dali::Property::Value value;
+    Dali::AlphaFunction::BuiltinFunction alphaFunction;
+    float timePeriodDelay;
+    float timePeriodDuration;
+
+    AnimationDataElement();
+  };
+
+  /**
+   * @brief AnimationData holds the required data required to define an
+   * animation to be performed on a property source.
+   */
+  typedef Dali::Vector< AnimationDataElement* > AnimationDataList;
+
+  /**
+   * @brief Adds one AnimationDataElement to the list to describe one animation.
+   * @param[in] animationDataElement A pre-populated struct to add
+   */
+  void Add( AnimationDataElement* animationDataElement );
+
+  std::size_t Size() const;
+
+  void Clear();
+
+  AnimationDataList mAnimationDataList;
+};
+
+void NewAnimator( const Dali::Property::Map& map, TestAnimationData::AnimationDataElement& element );
+void NewAnimation( const Dali::Property::Map& map, TestAnimationData& outputAnimationData );
+void NewAnimation( const Dali::Property::Array& array, TestAnimationData& outputAnimationData );
+} // Test
+
+#endif  //DALI_TOOLKIT_TEST_TEST_ANIMATION_DATA_H
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.cpp
new file mode 100644 (file)
index 0000000..cbecb9b
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2016 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 <dali/dali.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <test-button.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+Property::Value ConvertAnimationMap( const Test::TestAnimationData& animationMap )
+{
+  // We have a data structure. Now convert it back into an array:
+  Property::Array animators;
+  for( unsigned int i=0; i<animationMap.Size(); ++i )
+  {
+    Property::Map animator;
+    animator.Insert( "target", Property::Value(animationMap.mAnimationDataList[i]->target ));
+    animator.Insert( "property", Property::Value(animationMap.mAnimationDataList[i]->property ));
+    animator.Insert( "value", Property::Value(animationMap.mAnimationDataList[i]->value ));
+    animator.Insert( "alphaFunction", Property::Value(animationMap.mAnimationDataList[i]->alphaFunction ));
+    animator.Insert( "timePeriodDelay", Property::Value(animationMap.mAnimationDataList[i]->timePeriodDelay ));
+    animator.Insert( "timePeriodDuration", Property::Value(animationMap.mAnimationDataList[i]->timePeriodDuration ));
+    animators.PushBack( animator );
+  }
+  Property::Value animation( animators );
+  return animation;
+}
+}
+
+namespace Test
+{
+namespace Impl
+{
+
+Test::TestButton TestButton::New()
+{
+  IntrusivePtr<TestButton> internalTestButton = new TestButton();
+  Test::TestButton button( *internalTestButton );
+  internalTestButton->Initialize();
+  return button;
+}
+
+TestButton::TestButton()
+: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS|REQUIRES_STYLE_CHANGE_SIGNALS ) )
+{
+}
+
+TestButton::~TestButton()
+{
+}
+
+void TestButton::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+  Test::TestButton button = Test::TestButton::DownCast( Dali::BaseHandle( object ) );
+
+  if ( button )
+  {
+    switch ( index )
+    {
+      case Test::TestButton::Property::PRESS_TRANSITION:
+      {
+        if( value.GetType() == Property::MAP )
+        {
+          Property::Map* valueMap = value.GetMap();
+          TestButton& buttonImpl = GetImpl(button);
+          buttonImpl.mPressTransitionData.Clear();
+          NewAnimation( *valueMap, buttonImpl.mPressTransitionData );
+        }
+        else if( value.GetType() == Property::ARRAY )
+        {
+          Property::Array* valueArray = value.GetArray();
+          TestButton& buttonImpl = GetImpl(button);
+          buttonImpl.mPressTransitionData.Clear();
+          NewAnimation( *valueArray, buttonImpl.mPressTransitionData );
+        }
+        break;
+      }
+    }
+  }
+}
+
+Property::Value TestButton::GetProperty( BaseObject* object, Property::Index propertyIndex )
+{
+  Test::TestButton button = Test::TestButton::DownCast( Dali::BaseHandle( object ) );
+
+  if ( button )
+  {
+    TestButton& buttonImpl = GetImpl(button);
+    switch ( propertyIndex )
+    {
+      case Test::TestButton::Property::PRESS_TRANSITION:
+      {
+        return ConvertAnimationMap(buttonImpl.mPressTransitionData);
+        break;
+      }
+      case Test::TestButton::Property::RELEASE_TRANSITION:
+      {
+        return ConvertAnimationMap(buttonImpl.mReleaseTransitionData);
+        break;
+      }
+      case Test::TestButton::Property::DISABLED_TRANSITION:
+      {
+        return ConvertAnimationMap(buttonImpl.mDisabledTransitionData);
+        break;
+      }
+      case Test::TestButton::Property::ENABLED_TRANSITION:
+      {
+        return ConvertAnimationMap(buttonImpl.mEnabledTransitionData);
+        break;
+      }
+    }
+  }
+  return Property::Value();
+}
+
+BaseHandle Create()
+{
+  return TestButton::New();
+}
+
+// Generates typeRegistration static variable.
+DALI_TYPE_REGISTRATION_BEGIN( Test::TestButton, Dali::Toolkit::Control, Create )
+
+DALI_PROPERTY_REGISTRATION( Test, TestButton, "pressTransition", ARRAY, PRESS_TRANSITION )
+DALI_PROPERTY_REGISTRATION( Test, TestButton, "releaseTransition", ARRAY, RELEASE_TRANSITION)
+DALI_PROPERTY_REGISTRATION( Test, TestButton, "disabledTransition", ARRAY, DISABLED_TRANSITION )
+DALI_PROPERTY_REGISTRATION( Test, TestButton, "enabledTransition", ARRAY, ENABLED_TRANSITION )
+
+DALI_TYPE_REGISTRATION_END()
+
+} // Impl Namespace
+
+TestButton::TestButton()
+: Control()
+{
+}
+
+TestButton::TestButton(const TestButton& button)
+: Control( button )
+{
+}
+
+TestButton::TestButton(Impl::TestButton& impl)
+: Control(impl)
+{
+}
+
+TestButton::TestButton(Dali::Internal::CustomActor* internal)
+: Control(internal)
+{
+  VerifyCustomActorPointer<Impl::TestButton>(internal);
+}
+
+TestButton& TestButton::operator=( const TestButton& button)
+{
+  if(&button != this)
+  {
+    Control::operator=(button);
+  }
+  return *this;
+}
+
+TestButton::~TestButton()
+{
+}
+
+TestButton TestButton::New()
+{
+  return Impl::TestButton::New();
+}
+
+TestButton TestButton::DownCast( BaseHandle handle )
+{
+  return Control::DownCast<TestButton,Impl::TestButton>(handle);
+}
+
+} // namespace Test
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-button.h
new file mode 100644 (file)
index 0000000..5dd5ac3
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef DALI_TOOLKIT_TEST_TEST_BUTTON_H
+#define DALI_TOOLKIT_TEST_TEST_BUTTON_H
+
+/*
+ * Copyright (c) 2016 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 <dali-toolkit/dali-toolkit.h>
+#include <test-animation-data.h>
+
+namespace Test
+{
+namespace Impl
+{
+class TestButton;
+}
+
+class TestButton : public Dali::Toolkit::Control
+{
+public:
+  enum PropertyRange
+  {
+    PROPERTY_START_INDEX = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1,
+    PROPERTY_END_INDEX =   PROPERTY_START_INDEX + 1000
+  };
+  struct Property
+  {
+    enum
+    {
+      PRESS_TRANSITION = PROPERTY_START_INDEX,
+      RELEASE_TRANSITION,
+      DISABLED_TRANSITION,
+      ENABLED_TRANSITION
+    };
+  };
+  TestButton();
+  TestButton(const TestButton& button);
+  TestButton(Impl::TestButton& impl);
+  TestButton(Dali::Internal::CustomActor* internal);
+  TestButton& operator=( const TestButton& button);
+  ~TestButton();
+  static TestButton New();
+  static TestButton DownCast( Dali::BaseHandle handle );
+};
+
+namespace Impl
+{
+
+class TestButton : public Dali::Toolkit::Internal::Control
+{
+public:
+  static Test::TestButton New();
+
+  static void SetProperty( Dali::BaseObject* object,
+                           Dali::Property::Index index,
+                           const Dali::Property::Value& value );
+
+  static Dali::Property::Value GetProperty( Dali::BaseObject* object,
+                                            Dali::Property::Index propertyIndex );
+
+protected:
+  TestButton();
+  virtual ~TestButton();
+
+public:
+  Test::TestAnimationData mPressTransitionData;
+  Test::TestAnimationData mReleaseTransitionData;
+  Test::TestAnimationData mDisabledTransitionData;
+  Test::TestAnimationData mEnabledTransitionData;
+};
+
+inline TestButton& GetImpl( Test::TestButton& handle )
+{
+  DALI_ASSERT_ALWAYS( handle );
+  Dali::RefObject& object = handle.GetImplementation();
+  return static_cast<TestButton&>( object );
+}
+
+inline const TestButton& GetImpl( const Test::TestButton& handle )
+{
+  DALI_ASSERT_ALWAYS( handle );
+  const Dali::RefObject& object = handle.GetImplementation();
+  return static_cast<const TestButton&>( object );
+}
+
+} // Impl
+} // Test
+
+
+
+#endif // DALI_TOOLKIT_TEST_TEST_BUTTON_H
index 6786bc5..5bde6be 100644 (file)
@@ -97,6 +97,8 @@ void ClearModelData( CharacterIndex characterIndex,
 
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
+                      const Vector<FontDescriptionRun>& fontDescriptions,
+                      const LayoutOptions& options,
                       Size& layoutSize,
                       LogicalModelPtr logicalModel,
                       VisualModelPtr visualModel )
@@ -142,6 +144,7 @@ void CreateTextModel( const std::string& text,
 
   // 4) Set the font info
   Vector<FontDescriptionRun>& fontDescriptionRuns = logicalModel->mFontDescriptionRuns;
+  fontDescriptionRuns = fontDescriptions;
   Vector<FontRun>& validFonts = logicalModel->mFontRuns;
 
   // The default font id.
@@ -262,27 +265,29 @@ void CreateTextModel( const std::string& text,
   // Set the layout parameters.
   const Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   const Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+
   LayoutParameters layoutParameters( textArea,
                                      utf32Characters.Begin(),
                                      lineBreakInfo.Begin(),
                                      wordBreakInfo.Begin(),
                                      ( 0u != characterDirections.Count() ) ? characterDirections.Begin() : NULL,
-                                     glyphs.Count(),
                                      glyphs.Begin(),
                                      glyphsToCharactersMap.Begin(),
-                                     charactersPerGlyph.Begin() );
-
-  // Get the character to glyph conversion table and set into the layout.
-  layoutParameters.charactersToGlyphsBuffer = charactersToGlyph.Begin();
-  // Get the glyphs per character table and set into the layout.
-  layoutParameters.glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+                                     charactersPerGlyph.Begin(),
+                                     charactersToGlyph.Begin(),
+                                     glyphsPerCharacter.Begin(),
+                                     numberOfGlyphs );
 
   Vector<LineRun>& lines = visualModel->mLines;
 
   Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
   glyphPositions.Resize( numberOfGlyphs );
 
-  layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( logicalModel->mText.Count() - 1u ) ) );
+  layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( utf32Characters.Begin() + ( numberOfCharacters - 1u ) ) );
+
+  // The initial glyph and the number of glyphs to layout.
+  layoutParameters.startGlyphIndex = 0u;
+  layoutParameters.numberOfGlyphs = numberOfGlyphs;
 
   layoutEngine.LayoutText( layoutParameters,
                            glyphPositions,
@@ -315,9 +320,22 @@ void CreateTextModel( const std::string& text,
                                          0u,
                                          numberOfCharacters );
 
-    // Re-layout the text. Reorder those lines with right to left characters.
-    layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
-                                           glyphPositions );
+    if( options.reorder )
+    {
+      // Re-layout the text. Reorder those lines with right to left characters.
+      layoutEngine.ReLayoutRightToLeftLines( layoutParameters,
+                                             0u,
+                                             numberOfCharacters,
+                                             glyphPositions );
+    }
+  }
+
+  if( options.align )
+  {
+    layoutEngine.Align( textArea,
+                        0u,
+                        numberOfCharacters,
+                        lines );
   }
 }
 
index 02dbbcd..631b151 100644 (file)
@@ -34,17 +34,35 @@ namespace Text
 {
 
 /**
+ * @brief Some layout options.
+ */
+struct LayoutOptions
+{
+  LayoutOptions()
+  : reorder( true ),
+    align( true )
+  {}
+
+  bool reorder : 1; ///< Whether to reorder the bidirectional lines.
+  bool align   : 1; ///< Whether to align the lines.
+};
+
+/**
  * @brief Creates and fills all the vectors of a text model: characters in utf32, segmentation info,
  * scripts, fonts, bidi info, glyphs, conversion tables, etc.
  *
  * @param[in] text The given text.
  * @param[in] textArea The area where to layout the text.
+ * @param[in] fontDescriptions The fonts to be used.
+ * @param[in] options Layout options.
  * @param[out] layoutSize The laid-out size.
- * @param[out] Pointer to a logical text model instance.
- * @param[out] Pointer to a visual text model instance.
+ * @param[out] logicalModel Pointer to a logical text model instance.
+ * @param[out] visualModel Pointer to a visual text model instance.
  */
 void CreateTextModel( const std::string& text,
                       const Size& textArea,
+                      const Vector<FontDescriptionRun>& fontDescriptions,
+                      const LayoutOptions& options,
                       Size& layoutSize,
                       LogicalModelPtr logicalModel,
                       VisualModelPtr visualModel );
index 653325c..8b06fd1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2014-2016 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/devel-api/builder/builder.h>
 #include <dali/integration-api/events/touch-event-integ.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+#include <test-button.h>
+#include <test-animation-data.h>
 
 #define STRINGIFY(A)#A
 
@@ -1455,3 +1459,194 @@ int UtcDaliBuilderPathConstraintsP(void)
 
   END_TEST;
 }
+
+#define CHECK_MAP_ELEMENT( xMap, xKey, xType, xPropType, xExpected, xLocation ) \
+  {                                                                       \
+    Property::Value* value = xMap->Find( xKey );                          \
+    DALI_TEST_EQUALS( value==NULL, false, xLocation);                     \
+    if( value != NULL )                                                   \
+    {                                                                     \
+      DALI_TEST_EQUALS( value->GetType(), xPropType, xLocation );         \
+      xType result;                                                       \
+      value->Get(result);                                                 \
+      DALI_TEST_EQUALS( result, xExpected, TEST_LOCATION );               \
+      std::ostringstream oss;                                             \
+      oss << "Animation element " << xKey << "= " << result << std::endl; \
+      tet_printf( oss.str().c_str() );                                    \
+    }                                                                     \
+    else                                                                  \
+    {                                                                     \
+      tet_printf("Can't find map element " xKey "\n");                    \
+    }                                                                     \
+  }
+
+
+int UtcDaliBuilderMapping01(void)
+{
+  ToolkitTestApplication application;
+
+  const char* json =
+    "{\n"
+    "  \"mappings\":\n"
+    "  {\n"
+    "    \"buttonPressFadeOut\":{\n"
+    "      \"alphaFunction\":\"EASE_OUT\",\n"
+    "      \"timePeriod\":{\n"
+    "        \"delay\":0.0,\n"
+    "        \"duration\":0.4\n"
+    "      }\n"
+    "    },\n"
+    "    \"buttonPressFadeIn\":{\n"
+    "      \"alphaFunction\":\"EASE_IN\",\n"
+    "      \"timePeriod\":{\n"
+    "        \"delay\":0.4,\n"
+    "        \"duration\":0.5\n"
+    "      }\n"
+    "    },\n"
+    "    \"transition:buttonPressed\":\n"
+    "    [\n"
+    "      {\n"
+    "        \"target\": \"unselectedBackgroundRenderer\",\n"
+    "        \"property\": \"opacity\",\n"
+    "        \"value\": 0,\n"
+    "        \"animator\":\"<buttonPressFadeOut>\"\n"
+    "      }\n"
+    "    ],\n"
+    "    \"transition:buttonReleased\":\n"
+    "    [\n"
+    "      {\n"
+    "        \"target\": \"unselectedBackgroundRenderer\",\n"
+    "        \"property\": \"opacity\",\n"
+    "        \"value\": 1,\n"
+    "        \"animator\":\"<buttonPressFadeIn>\"\n"
+    "      },\n"
+    "      {\n"
+    "        \"target\": \"unselectedForegroundRenderer\",\n"
+    "        \"property\": \"scale\",\n"
+    "        \"value\": [ 1, 1, 1 ],\n"
+    "        \"animator\":\"<buttonPressFadeIn>\"\n"
+    "      },\n"
+    "      {\n"
+    "        \"target\": \"selectedBackgroundRenderer\",\n"
+    "        \"property\": \"opacity\",\n"
+    "        \"value\": 0,\n"
+    "        \"animator\": \"<buttonPressFadeOut>\"\n"
+    "      },\n"
+    "      {\n"
+    "        \"target\": \"selectedForegroundRenderer\",\n"
+    "        \"property\": \"scale\",\n"
+    "        \"value\": [ 0, 0, 0 ],\n"
+    "        \"animator\":\"<buttonPressFadeOut>\"\n"
+    "      }\n"
+    "    ]\n"
+    "  },\n"
+    "  \"styles\":\n"
+    "  {\n"
+    "    \"testbutton\":\n"
+    "    {\n"
+    "      \"pressTransition\":\"<transition:buttonPressed>\",\n"
+    "      \"releaseTransition\":\"<transition:buttonReleased>\"\n"
+    "    }\n"
+    "  }\n"
+    "}\n";
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+
+  Test::TestButton testButton = Test::TestButton::New();
+  Stage::GetCurrent().Add( testButton );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( builder.ApplyStyle( "testbutton", testButton ) );
+
+  // Now check that it has loaded the transition correctly:
+  Property::Value transition = testButton.GetProperty(Test::TestButton::Property::PRESS_TRANSITION);
+  DALI_TEST_EQUALS( transition.GetType(), Property::ARRAY, TEST_LOCATION );
+  Property::Array* array = transition.GetArray();
+
+  DALI_TEST_EQUALS( array->Size(), 1, TEST_LOCATION );
+  Property::Value element = array->GetElementAt(0);
+  DALI_TEST_CHECK( element.GetType() == Property::MAP );
+  Property::Map* map = element.GetMap();
+
+  CHECK_MAP_ELEMENT(map, "target", std::string, Property::STRING, "unselectedBackgroundRenderer", TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "property", std::string, Property::STRING, "opacity", TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "alphaFunction", int, Property::INTEGER, (int)Dali::AlphaFunction::EASE_OUT, TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "timePeriodDelay", float, Property::FLOAT, 0.0f, TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "timePeriodDuration", float, Property::FLOAT, 0.4f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+
+int UtcDaliBuilderMappingCycleCheck(void)
+{
+  ToolkitTestApplication application;
+
+  std::string json(
+    "{\n"
+    "  \"mappings\":\n"
+    "  {\n"
+    "    \"cyclicKey1\":\"<cyclicKey1>\",\n"
+    "    \"cyclicKey2\":\"<cyclicKey3>\",\n"
+    "    \"cyclicKey3\":\"<cyclicKey2>\",\n"
+    "    \"FadeOut\":{\n"
+    "      \"alphaFunction\":\"EASE_IN\",\n"
+    "      \"timePeriod\":{\n"
+    "        \"delay\":\"<cyclicKey3>\",\n"
+    "        \"duration\":0.6\n"
+    "      }\n"
+    "    },\n"
+    "    \"transition:buttonPressed\":\n"
+    "    [\n"
+    "      {\n"
+    "        \"target\": \"<cyclicKey1>\",\n"
+    "        \"property\": \"<cyclicKey2>\",\n"
+    "        \"value\": 0,\n"
+    "        \"animator\":\"<FadeOut>\"\n"
+    "      }\n"
+    "    ]\n"
+    "  },\n"
+    "  \"styles\":\n"
+    "  {\n"
+    "    \"testbutton\":\n"
+    "    {\n"
+    "      \"pressTransition\":\"<transition:buttonPressed>\",\n"
+    "      \"releaseTransition\":\"<cyclicKey2>\",\n"
+    "      \"disabledTransition\":\"<cyclicKey3>\",\n"
+    "      \"enabledTransition\":\"<unknownKey>\"\n"
+    "    }\n"
+    "  }\n"
+    "}\n");
+
+  Builder builder = Builder::New();
+  builder.LoadFromString( json );
+
+  Test::TestButton testButton = Test::TestButton::New();
+  Stage::GetCurrent().Add( testButton );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( builder.ApplyStyle( "testbutton", testButton ) );
+
+  // Now check that it has loaded the transition correctly:
+  Property::Value transition = testButton.GetProperty(Test::TestButton::Property::PRESS_TRANSITION);
+  DALI_TEST_EQUALS( transition.GetType(), Property::ARRAY, TEST_LOCATION );
+  Property::Array* array = transition.GetArray();
+
+  DALI_TEST_EQUALS( array->Size(), 1, TEST_LOCATION );
+  Property::Value element = array->GetElementAt(0);
+  DALI_TEST_CHECK( element.GetType() == Property::MAP );
+  Property::Map* map = element.GetMap();
+
+  CHECK_MAP_ELEMENT(map, "target", std::string, Property::STRING, "", TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "property", std::string, Property::STRING, "", TEST_LOCATION);
+  CHECK_MAP_ELEMENT(map, "timePeriodDuration", float, Property::FLOAT, 0.6f, TEST_LOCATION);
+
+  END_TEST;
+}
index 3ecb1d5..8515280 100644 (file)
@@ -195,4 +195,3 @@ bool TreeNode::ConstIterator::operator!=( const TreeNode::ConstIterator& rhs ) c
 } // namespace Toolkit
 
 } // namespace Dali
-
index 893caee..6da465a 100644 (file)
@@ -56,7 +56,7 @@ public:
     STRING,
     INTEGER,
     FLOAT,
-    BOOLEAN,
+    BOOLEAN
   };
 
   /*
index c7cfc9e..2f71883 100644 (file)
@@ -77,16 +77,6 @@ BloomView BloomView::DownCast( BaseHandle handle )
   return Control::DownCast<BloomView, Internal::BloomView>(handle);
 }
 
-void BloomView::Add(Actor child)
-{
-  GetImpl(*this).Add(child);
-}
-
-void BloomView::Remove(Actor child)
-{
-  GetImpl(*this).Remove(child);
-}
-
 void BloomView::Activate()
 {
   GetImpl(*this).Activate();
index 0d37cea..9353f13 100644 (file)
@@ -154,30 +154,6 @@ public:
                               const float downsampleWidthScale, const float downsampleHeightScale);
 
   /**
-   * Adds a child Actor to this Actor.
-   * NOTE! if the child already has a parent, it will be removed from old parent
-   * and reparented to this actor. This may change childs position, color, shader effect,
-   * scale etc as it now inherits them from this actor
-   * @pre This Actor (the parent) has been initialized.
-   * @pre The child actor has been initialized.
-   * @pre The child actor is not the same as the parent actor.
-   * @pre The actor is not the Root actor
-   * @param [in] child The child.
-   * @post The child will be referenced by its parent. This means that the child will be kept alive,
-   * even if the handle passed into this method is reset or destroyed.
-   */
-  void Add(Actor child);
-
-  /**
-   * Removes a child Actor from this Actor.
-   * If the actor was not a child of this actor, this is a no-op.
-   * @pre This Actor (the parent) has been initialized.
-   * @pre The child actor is not the same as the parent actor.
-   * @param [in] child The child.
-   */
-  void Remove(Actor child);
-
-  /**
    * Start rendering the BloomView. Must be called after you Add() it to the stage.
    */
   void Activate();
index 5afc638..a969dc2 100644 (file)
@@ -84,16 +84,6 @@ ShadowView ShadowView::DownCast( BaseHandle handle )
   return Control::DownCast<ShadowView, Internal::ShadowView>(handle);
 }
 
-void ShadowView::Add(Actor child)
-{
-  GetImpl(*this).Add(child);
-}
-
-void ShadowView::Remove(Actor child)
-{
-  GetImpl(*this).Remove(child);
-}
-
 void ShadowView::SetShadowPlaneBackground(Actor shadowPlaneBackground)
 {
   GetImpl(*this).SetShadowPlaneBackground(shadowPlaneBackground);
index d6039f2..9ddea7c 100644 (file)
@@ -154,30 +154,6 @@ public:
   static ShadowView New(float downsampleWidthScale, float downsampleHeightScale);
 
   /**
-   * Adds a child Actor to this Actor.
-   * NOTE! if the child already has a parent, it will be removed from old parent
-   * and reparented to this actor. This may change childs position, color, shader effect,
-   * scale etc as it now inherits them from this actor
-   * @pre This Actor (the parent) has been initialized.
-   * @pre The child actor has been initialized.
-   * @pre The child actor is not the same as the parent actor.
-   * @pre The actor is not the Root actor
-   * @param [in] child The child.
-   * @post The child will be referenced by its parent. This means that the child will be kept alive,
-   * even if the handle passed into this method is reset or destroyed.
-   */
-  void Add(Actor child);
-
-  /**
-   * Removes a child Actor from this Actor.
-   * If the actor was not a child of this actor, this is a no-op.
-   * @pre This Actor (the parent) has been initialized.
-   * @pre The child actor is not the same as the parent actor.
-   * @param [in] child The child.
-   */
-  void Remove(Actor child);
-
-  /**
    * Set the Shadow Plane Background for the shadow effect.
    *
    * @param[in] shadowPlaneBackground An actor representing the shadow
index 2efc4db..d13b70b 100644 (file)
@@ -57,6 +57,7 @@ inline OptionalString IsString(const OptionalChild& node)
     return OptionalString();
   }
 }
+
 inline OptionalFloat IsFloat(const OptionalChild& node)
 {
   OptionalFloat ret;
@@ -109,6 +110,7 @@ inline OptionalBoolean IsBoolean(const OptionalChild& node)
   }
 }
 
+
 // copy N Numbers
 template <typename T>
 inline bool CopyNumbers(TreeNode::ConstIterator iter, int N, T& vector)
diff --git a/dali-toolkit/internal/builder/builder-impl-debug.cpp b/dali-toolkit/internal/builder/builder-impl-debug.cpp
new file mode 100644 (file)
index 0000000..2e89d71
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 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.
+ */
+
+#ifdef DEBUG_ENABLED
+#include <dali-toolkit/internal/builder/builder-impl-debug.h>
+#include <dali-toolkit/internal/builder/builder-impl.h>
+#include <dali-toolkit/internal/builder/builder-get-is.inl.h>
+#include <iostream>
+#include <cstring>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+void LogTree( const Toolkit::JsonParser& parser )
+{
+  if( OptionalChild constants = IsChild(parser.GetRoot(), "constants") )
+  {
+    for(TreeNode::ConstIterator iter = (*constants).CBegin();
+        iter != (*constants).CEnd(); ++iter)
+    {
+      if( ( (*iter).first && strcmp( (*iter).first, "DUMP_TREE" ) == 0 ) ||
+          ( (*iter).second.GetType() == TreeNode::STRING && strcmp( (*iter).second.GetString(), "DUMP_TREE" ) == 0 ) )
+      {
+        std::ostringstream oss;
+        parser.Write(oss, 2);
+        std::cout << oss.str() << std::endl;
+      }
+    }
+  }
+}
+
+std::string PropertyValueToString( const Property::Value& value )
+{
+  std::ostringstream oss;
+  oss << value;
+
+  return oss.str();
+}
+
+} // Internal
+} // Toolkit
+} // Dali
+
+#endif // DEBUG_ENABLED
diff --git a/dali-toolkit/internal/builder/builder-impl-debug.h b/dali-toolkit/internal/builder/builder-impl-debug.h
new file mode 100644 (file)
index 0000000..8d30929
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef DALI_TOOLKIT_INTERNAL_BUILDER_IMPL_DEBUG_H
+#define DALI_TOOLKIT_INTERNAL_BUILDER_IMPL_DEBUG_H
+
+/*
+ * Copyright (c) 2016 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 <dali/integration-api/debug.h>
+#include <dali-toolkit/devel-api/builder/json-parser.h>
+
+#if defined( DEBUG_ENABLED )
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+#define DUMP_PARSE_TREE(parser)  LogTree(parser)
+#define DUMP_TEST_MAPPINGS(parser)                                      \
+  OptionalChild mappings = IsChild( parser.GetRoot(), KEYNAME_MAPPINGS ); \
+  if( mappings )                                                        \
+  {                                                                     \
+    std::ostringstream oss;                                             \
+    oss << "Mappings: {" << std::endl;                                  \
+    for( TreeNode::ConstIterator iter = (*mappings).CBegin(); iter != (*mappings).CEnd(); ++iter ) \
+    {                                                                   \
+      Property::Value value;                                            \
+      bool converted = GetPropertyMap(*mappings, (*iter).first, Property::NONE, value ); \
+      if( converted )                                                   \
+      {                                                                 \
+        oss << "  " << (*iter).first << ":" << value << std::endl;      \
+      }                                                                 \
+    }                                                                   \
+    oss << "}" << std::endl;                                            \
+    DALI_LOG_INFO( gFilterScript, Debug::Verbose, oss.str().c_str() );  \
+  }
+
+
+void LogTree( const Toolkit::JsonParser& mParser );
+
+std::string PropertyValueToString( const Property::Value& value );
+
+
+} // Internal
+} // Toolkit
+} // Dali
+
+#else
+
+#define DUMP_PARSE_TREE(parser)
+#define DUMP_TEST_MAPPINGS(parser)
+
+#endif // DEBUG_ENABLED
+#endif // DALI_TOOLKIT_INTERNAL_BUILDER_IMPL_DEBUG_H
index f7b89e1..2cf23db 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <sys/stat.h>
 #include <sstream>
+
 #include <dali/public-api/render-tasks/render-task-list.h>
 #include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
 #include <dali-toolkit/internal/builder/builder-filesystem.h>
 #include <dali-toolkit/internal/builder/builder-declarations.h>
+#include <dali-toolkit/internal/builder/builder-set-property.h>
 #include <dali-toolkit/internal/builder/replacement.h>
+#include <dali-toolkit/internal/builder/tree-node-manipulator.h>
+
+#include <dali-toolkit/internal/builder/builder-impl-debug.h>
 
 namespace Dali
 {
@@ -52,10 +57,6 @@ namespace Internal
 class Replacement;
 
 extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder );
-extern void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value );
-extern void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements );
-extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
-extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements );
 extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
 extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
 extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant );
@@ -76,108 +77,28 @@ const std::string KEYNAME_SIGNALS   = "signals";
 const std::string KEYNAME_NAME      = "name";
 const std::string KEYNAME_TEMPLATES = "templates";
 const std::string KEYNAME_INCLUDES  = "includes";
+const std::string KEYNAME_MAPPINGS  = "mappings";
 
 typedef std::vector<const TreeNode*> TreeNodeList;
 
-template <typename T>
-std::string ToString(const T& value)
-{
-  std::stringstream ss;
-  ss << value;
-  return ss.str();
-}
-
-template <>
-std::string ToString(const Rect<int>& value)
-{
-  std::stringstream ss;
-  ss << value.x << "," << value.y << "," << value.width << "," << value.height;
-  return ss.str();
-}
-
-#if defined(DEBUG_ENABLED)
 
-std::string PropertyValueToString( const Property::Value& value )
+bool GetMappingKey( const std::string& str, std::string& key )
 {
-  std::string ret;
-
-  switch( value.GetType() )
+  bool result = false;
+  std::string test( str );
+  if( ! test.empty() )
   {
-    case Property::NONE:
-    {
-      ret = "NONE";
-      break;
-    }            ///< No type
-    case Property::BOOLEAN:
-    {
-      ret = value.Get<bool>() ? "True" : "False";
-      break;
-    }
-    case Property::FLOAT:
-    {
-
-      ret = ToString( value.Get<float>() );
-      break;
-    }
-    case Property::INTEGER:
-    {
-      ret = ToString( value.Get<int>() );
-      break;
-    }
-    case Property::VECTOR2:
-    {
-      ret = ToString( value.Get<Vector2>() );
-      break;
-    }
-    case Property::VECTOR3:
-    {
-      ret = ToString( value.Get<Vector3>() );
-      break;
-    }
-    case Property::VECTOR4:
-    {
-      ret = ToString( value.Get<Vector4>() );
-      break;
-    }
-    case Property::MATRIX3:
-    {
-      ret = ToString( value.Get<Matrix3>() );
-      break;
-    }
-    case Property::MATRIX:
+    if( test.at(0) == '<' )
     {
-      ret = ToString( value.Get<Matrix>() );
-      break;
-    }
-    case Property::RECTANGLE:
-    {
-      ret = ToString( value.Get< Rect<int> >() );
-      break;
-    }
-    case Property::ROTATION:
-    {
-      break;
-    }
-    case Property::STRING:
-    {
-      ret = value.Get<std::string>();
-      break;
-    }
-    case Property::ARRAY:
-    {
-      ret = std::string("Array Size=") + ToString( value.Get<Property::Array>().Size() );
-      break;
-    }
-    case Property::MAP:
-    {
-      ret = std::string("Map Size=") + ToString( value.Get<Property::Map>().Count() );
-      break;
+      if( test.at(test.length()-1) == '>' )
+      {
+        key = test.substr( 1, test.length()-2 );
+        result = true;
+      }
     }
   }
-
-  return ret;
+  return result;
 }
-#endif // DEBUG_ENABLED
 
 /*
  * Recursively collects all stylesin a node (An array of style names).
@@ -219,6 +140,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
 {
   if( handle )
   {
+
     for( TreeNode::ConstIterator iter = node.CBegin(); iter != node.CEnd(); ++iter )
     {
       const TreeNode::KeyNodePair& keyChild = *iter;
@@ -226,16 +148,16 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
       std::string key( keyChild.first );
 
       // ignore special fields; type,actors,signals,styles
-      if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES)
+      if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES || key == KEYNAME_MAPPINGS )
       {
         continue;
       }
 
       // special field 'image' usually contains an json object description
       // although sometimes refers to a framebuffer
-      if( 0 == keyChild.second.Size() )
+      if( key == "image" )
       {
-        if(key == "image")
+        if( 0 == keyChild.second.Size() )
         {
           ImageActor imageActor = ImageActor::DownCast(handle);
           if(imageActor)
@@ -253,7 +175,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
       }
 
       // special field 'effect' references the shader effect instances
-      if(key == "effect")
+      if( key == "effect" )
       {
         ImageActor actor = ImageActor::DownCast(handle);
         if( actor )
@@ -296,15 +218,30 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace
       if( Property::INVALID_INDEX != index )
       {
         Property::Type type = propertyObject.GetPropertyType(index);
-
         Property::Value value;
-        if( !DeterminePropertyFromNode( keyChild.second, type, value, constant ) )
+        bool mapped = false;
+
+        // if node.value is a mapping, get the property value from the "mappings" table
+        if( keyChild.second.GetType() == TreeNode::STRING )
         {
-          // verbose as this might not be a problem
-          // eg parentOrigin can be a string which is picked up later
-          DALI_SCRIPT_VERBOSE("Could not convert property:%s\n", key.c_str());
+          std::string mappingKey;
+          if( GetMappingKey(keyChild.second.GetString(), mappingKey) )
+          {
+            OptionalChild mappingRoot = IsChild( mParser.GetRoot(), KEYNAME_MAPPINGS );
+            mapped = GetPropertyMap( *mappingRoot, mappingKey.c_str(), type, value );
+          }
         }
-        else
+        if( ! mapped )
+        {
+          mapped = DeterminePropertyFromNode( keyChild.second, type, value, constant );
+          if( ! mapped )
+          {
+            // verbose as this might not be a problem
+            // eg parentOrigin can be a string which is picked up later
+            DALI_SCRIPT_VERBOSE("Could not convert property:%s\n", key.c_str());
+          }
+        }
+        if( mapped )
         {
           DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d Value '%s'\n", key.c_str(), index, value.GetType(), PropertyValueToString(value).c_str() );
 
@@ -972,7 +909,7 @@ Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name )
 
 bool Builder::IsLinearConstrainer( const std::string& name )
 {
-  //Search the LinearConstrainer in the LUT
+  // Search the LinearConstrainer in the LUT
   size_t count( mLinearConstrainerLut.size() );
   for( size_t i(0); i!=count; ++i )
   {
@@ -1104,6 +1041,118 @@ Animation Builder::CreateAnimation( const std::string& animationName )
   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
 }
 
+bool Builder::ConvertChildValue( const TreeNode& mappingRoot, KeyStack& keyStack, Property::Value& child )
+{
+  bool result = false;
+
+  switch( child.GetType() )
+  {
+    case Property::STRING:
+    {
+      std::string value;
+      if( child.Get( value ) )
+      {
+        std::string key;
+        if( GetMappingKey( value, key ) )
+        {
+          // Check key for cycles:
+          result=true;
+          for( KeyStack::iterator iter = keyStack.begin() ; iter != keyStack.end(); ++iter )
+          {
+            if( key.compare(*iter) == 0 )
+            {
+              // key is already in stack; stop.
+              DALI_LOG_WARNING("Detected cycle in stylesheet mapping table:%s\n", key.c_str());
+              child = Property::Value("");
+              result=false;
+              break;
+            }
+          }
+
+          if( result )
+          {
+            // The following call will overwrite the child with the value
+            // from the mapping.
+            RecursePropertyMap( mappingRoot, keyStack, key.c_str(), Property::NONE, child );
+            result = true;
+          }
+        }
+      }
+      break;
+    }
+
+    case Property::MAP:
+    {
+      Property::Map* map = child.GetMap();
+      for( Property::Map::SizeType i=0; i < map->Count(); ++i )
+      {
+        Property::Value& child = map->GetValue(i);
+        ConvertChildValue(mappingRoot, keyStack, child);
+      }
+      break;
+    }
+
+    case Property::ARRAY:
+    {
+      Property::Array* array = child.GetArray();
+      for( Property::Array::SizeType i=0; i < array->Count(); ++i )
+      {
+        Property::Value& child = array->GetElementAt(i);
+        ConvertChildValue(mappingRoot, keyStack, child);
+      }
+      break;
+    }
+
+    default:
+      // Ignore other types.
+      break;
+  }
+
+  return result;
+}
+
+bool Builder::RecursePropertyMap( const TreeNode& mappingRoot, KeyStack& keyStack, const char* theKey, Property::Type propertyType, Property::Value& value )
+{
+  Replacement replacer( mReplacementMap );
+  bool result = false;
+
+  keyStack.push_back( theKey );
+
+  for( TreeNode::ConstIterator iter = mappingRoot.CBegin(); iter != mappingRoot.CEnd(); ++iter )
+  {
+    std::string aKey( (*iter).first );
+    if( aKey.compare( theKey ) == 0 )
+    {
+      if( propertyType == Property::NONE )
+      {
+        DeterminePropertyFromNode( (*iter).second, value, replacer );
+        result = true;
+      }
+      else
+      {
+        result = DeterminePropertyFromNode( (*iter).second, propertyType, value, replacer );
+      }
+
+      if( result )
+      {
+        ConvertChildValue(mappingRoot, keyStack, value);
+      }
+      break;
+    }
+  }
+  keyStack.pop_back();
+
+  return result;
+}
+
+
+bool Builder::GetPropertyMap( const TreeNode& mappingRoot, const char* theKey, Property::Type propertyType, Property::Value& value )
+{
+  KeyStack keyStack;
+  return RecursePropertyMap( mappingRoot, keyStack, theKey, propertyType, value );
+}
+
+
 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
 {
   // parser to get constants and includes only
@@ -1153,6 +1202,9 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U
     }
   }
 
+  DUMP_PARSE_TREE(parser); // This macro only writes out if DEBUG is enabled and the "DUMP_TREE" constant is defined in the stylesheet.
+  DUMP_TEST_MAPPINGS(parser);
+
   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
 }
 
index f046504..a5d6f06 100644 (file)
@@ -258,6 +258,9 @@ private:
 
   Property::Map mReplacementMap;
 
+  typedef std::vector< TreeNode::KeyNodePair > MappingsLut;
+  MappingsLut mCompleteMappings;
+
   BaseHandle Create( const std::string& templateName, const Replacement& constant );
 
   BaseHandle DoCreate( const TreeNode& root, const TreeNode& node, Actor parent, const Replacement& replacements );
@@ -270,6 +273,39 @@ private:
 
   Animation CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor );
 
+  typedef std::vector<const char*> KeyStack;
+
+  /**
+   * Tests if the value is a string delimited by <>. If it is, then it attempts to
+   * change the value to the mapping from a matching key in the mappings table.
+   * @param[in] mappingRoot The JSON node containing the mappings
+   * @param[in,out] keyStack the stack of visited keys
+   * @param[in,out] value The string value to test and write back to.
+   * @return true if the value was converted, false otherwise.
+   */
+  bool ConvertChildValue( const TreeNode& mappingRoot, KeyStack& keyStack, Property::Value& value );
+
+  /**
+   * Find the key in the mapping table, if it's present, then generate a property value for it (of the given type if available), recursing as necessary, and stopping if any cycles
+   * are detected.
+   * @param[in] mappingRoot The JSON node containing the mappings
+   * @param[in] theKey The key to search for
+   * @param[in,out] keyStack the stack of visited keys
+   * @param[in] propertyType The property type if known, or NONE
+   * @param[in,out] value The string value to test and write back to.
+   */
+  bool RecursePropertyMap( const TreeNode& mappingRoot, KeyStack& keyStack, const char* theKey, Property::Type propertyType, Property::Value& value );
+
+  /**
+   * Find the key in the mapping table, if it's present, then generate a property value for it (of the given type if available), recursing as necessary, and stopping if any cycles
+   * are detected.
+   * @param[in] mappingRoot The JSON node containing the mappings
+   * @param[in] theKey The key to search for
+   * @param[in] propertyType The property type if known, or NONE
+   * @param[in,out] value The string value to test and write back to.
+   */
+  bool GetPropertyMap( const TreeNode& mappingRoot, const char* theKey, Property::Type propertyType, Property::Value& value );
+
   void ApplyProperties( const TreeNode& root, const TreeNode& node,
                         Dali::Handle& handle, const Replacement& constant );
 
index d17a392..d64a04c 100644 (file)
@@ -25,7 +25,7 @@
 #include <dali-toolkit/internal/builder/builder-impl.h>
 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
 #include <dali-toolkit/internal/builder/replacement.h>
-
+#include <dali-toolkit/internal/builder/builder-set-property.h>
 
 namespace Dali
 {
@@ -36,46 +36,6 @@ namespace Toolkit
 namespace Internal
 {
 
-/*
- * Set a property value from a tree node.
- * This function determines the type of the property from the format of the string in the node.
- * This is not always possible and if the type cannot be determined then then the type will default to Array.
- * @param node  The node string to convert from
- * @param value The property value to set
- */
-void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value );
-
-/*
- * Set a property value from a tree node as SetPropertyFromNode() above
- * This function determines the type of the property from the format of the string in the node.
- * This is not always possible and if the type cannot be determined then then the type will default to Array.
- * @param node  The node string to convert from
- * @param value The property value to set
- * @param replacement The overriding replacement map (if any)
- */
-void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value,
-                          const Replacement& replacement );
-
-/*
- * Set a property value as the given type from a tree node.
- * @param node The node string to convert from
- * @param type The property type to convert to.
- * @param value The property value to set
- * @return true if the string could be converted to the correct type.
- */
-bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
-
-/*
- * Set a property value as the given type from a tree node as SetPropertyFromNode() above
- * @param node The node string to convert from
- * @param type The property type to convert to.
- * @param value The property value to set
- * @param replacement The overriding replacement map (if any)
- * @return true if the string could be converted to the correct type.
- */
-bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value,
-                          const Replacement& replacement );
-
 
 namespace
 {
@@ -103,13 +63,12 @@ Vector4 HexStringToVector4( const char* s )
  * A property value type can be forced when its unknown by a disambiguation convention in the json
  * ie  "myarray": [1,2,3,4] ; would be a vector but
  *     "myarray": {"typeCast":"array", "value":[1,2,3,4]} would be an array
- * @param child The node whos string to search for a disambiguated type
+ * @param child The node whose string to search for a disambiguated type
  * @param value The value to set
- * @param overrideMap The user overriding constant map
- * @param defaultMap The default map.
+ * @param replacement The user overriding constant map
  * @return True if child contained a disambiguated string that could be converted.
  */
-bool Disambiguated(const TreeNode& child, // ConstantLut& constantLut,
+bool Disambiguated(const TreeNode& child,
                    Dali::Property::Value& value,
                    const Replacement& replacement )
 {
@@ -175,7 +134,7 @@ bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Prope
 }
 
 bool DeterminePropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value,
-                          const Replacement& replacer )
+                                const Replacement& replacer )
 {
   bool done = false;
 
@@ -406,7 +365,7 @@ void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value )
 }
 
 void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value,
-                          const Replacement& replacer )
+                                const Replacement& replacer )
 {
 
   TreeNode::NodeType nodeType = node.GetType();
@@ -517,7 +476,6 @@ void DeterminePropertyFromNode( const TreeNode& node, Property::Value& value,
         }
         else
         {
-          // string always succeeds with the current json parser so its last
           value = *aString;
         }
       } // if aBool
diff --git a/dali-toolkit/internal/builder/builder-set-property.h b/dali-toolkit/internal/builder/builder-set-property.h
new file mode 100644 (file)
index 0000000..a9ae431
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef DALI_TOOLKIT_INTERNAL_BUILDER_SET_PROPERTY_H
+#define DALI_TOOLKIT_INTERNAL_BUILDER_SET_PROPERTY_H
+
+/*
+ * Copyright (c) 2016 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 Internal
+{
+
+/**
+ * Set a property value from a tree node.
+ * This function determines the type of the property from the format of the string in the node.
+ * This is not always possible and if the type cannot be determined then then the type will default to Array.
+ * @param node  The node string to convert from
+ * @param value The property value to set
+ */
+void DeterminePropertyFromNode( const TreeNode&  node,
+                                Property::Value& value );
+
+/**
+ * Set a property value from a tree node as DeterminePropertyFromNode() above
+ * This function determines the type of the property from the format of the string in the node.
+ * This is not always possible and if the type cannot be determined then then the type will default to Array.
+ * @param node  The node string to convert from
+ * @param value The property value to set
+ * @param replacement The overriding replacement map (if any)
+ */
+void DeterminePropertyFromNode( const TreeNode&    node,
+                                Property::Value&   value,
+                                const Replacement& replacement );
+
+/**
+ * Set a property value as the given type from a tree node.
+ * @param node The node string to convert from
+ * @param type The property type to convert to.
+ * @param value The property value to set
+ * @return true if the string could be converted to the correct type.
+ */
+bool DeterminePropertyFromNode( const TreeNode&  node,
+                                Property::Type   type,
+                                Property::Value& value );
+
+/**
+ * Set a property value as the given type from a tree node as DeterminePropertyFromNode() above
+ * @param node The node string to convert from
+ * @param type The property type to convert to.
+ * @param value The property value to set
+ * @param replacement The overriding replacement map (if any)
+ * @return true if the string could be converted to the correct type.
+ */
+bool DeterminePropertyFromNode( const TreeNode&    node,
+                                Property::Type     type,
+                                Property::Value&   value,
+                                const Replacement& replacement );
+
+
+} // Internal namespace
+} // Toolkit namespace
+} // Dali namespace
+
+#endif //DALI_TOOLKIT_INTERNAL_BUILDER_SET_PROPERTY_H
index 750d6fe..4d088d1 100644 (file)
@@ -149,6 +149,7 @@ BloomView::BloomView()
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New() )
   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
@@ -172,6 +173,7 @@ BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCur
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New())
   , mBloomThresholdPropertyIndex(Property::INVALID_INDEX)
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mBloomIntensityPropertyIndex(Property::INVALID_INDEX)
@@ -213,24 +215,6 @@ Toolkit::BloomView BloomView::New(const unsigned int blurNumSamples, const float
   return handle;
 }
 
-/////////////////////////////////////////////////////////////
-// for creating a subtree for all user added child actors, so that we can have them exclusive to the mRenderChildrenTask and our other actors exclusive to our other tasks
-// TODO: overloading Actor::Add()/Remove() not nice since breaks polymorphism. Need another method to pass ownership of added child actors to our internal actor root.
-void BloomView::Add(Actor child)
-{
-  mChildrenRoot.Add(child);
-}
-
-void BloomView::Remove(Actor child)
-{
-  mChildrenRoot.Remove(child);
-}
-
-
-
-
-
-
 ///////////////////////////////////////////////////////////
 //
 // Private methods
@@ -240,6 +224,7 @@ void BloomView::OnInitialize()
 {
   // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
   mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
+  mInternalRoot.SetParentOrigin( ParentOrigin::CENTER );
 
   //////////////////////////////////////////////////////
   // Create actors
@@ -291,12 +276,13 @@ void BloomView::OnInitialize()
   ////////////////////////////////
   // Connect to actor tree
   Self().Add( mChildrenRoot );
-  Self().Add( mBloomExtractImageActor );
-  Self().Add( mGaussianBlurView );
-  Self().Add( mCompositeImageActor );
-  Self().Add( mTargetImageActor );
-  Self().Add( mRenderDownsampledCamera );
-  Self().Add( mRenderFullSizeCamera );
+  Self().Add( mInternalRoot );
+  mInternalRoot.Add( mBloomExtractImageActor );
+  mInternalRoot.Add( mGaussianBlurView );
+  mInternalRoot.Add( mCompositeImageActor );
+  mInternalRoot.Add( mTargetImageActor );
+  mInternalRoot.Add( mRenderDownsampledCamera );
+  mInternalRoot.Add( mRenderFullSizeCamera );
 
   // bind properties for / set shader constants to defaults
   SetupProperties();
@@ -327,10 +313,23 @@ void BloomView::OnSizeSet(const Vector3& targetSize)
   }
 }
 
+void BloomView::OnControlChildAdd( Actor& child )
+{
+  if( child != mChildrenRoot && child != mInternalRoot)
+  {
+    mChildrenRoot.Add( child );
+  }
+}
+
+void BloomView::OnControlChildRemove( Actor& child )
+{
+  mChildrenRoot.Remove( child );
+}
+
 void BloomView::AllocateResources()
 {
   // size of render targets etc is based on the size of this actor, ignoring z
-  if(mTargetSize != mLastSize)
+  if(mTargetSize != mLastSize || !mActivated)
   {
     mLastSize = mTargetSize;
 
@@ -464,6 +463,9 @@ void BloomView::Deactivate()
   // stop render tasks processing
   // Note: render target resources are automatically freed since we set the Image::Unused flag
   RemoveRenderTasks();
+  mRenderTargetForRenderingChildren.Reset();
+  mBloomExtractTarget.Reset();
+  mOutputRenderTarget.Reset();
   mActivated = false;
 }
 
index 207ce92..cc42f64 100644 (file)
@@ -70,10 +70,6 @@ public:
   static Dali::Toolkit::BloomView New();
   static Dali::Toolkit::BloomView New( const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat,
                                               const float downsampleWidthScale, const float downsampleHeightScale);
-
-  void Add(Actor child);
-  void Remove(Actor child);
-
   void Activate();
   void Deactivate();
 
@@ -89,6 +85,16 @@ private:
   virtual void OnInitialize();
   virtual void OnSizeSet(const Vector3& targetSize);
 
+  /**
+   * @copydoc Control::OnControlChildAdd()
+   */
+  virtual void OnControlChildAdd( Actor& child );
+
+  /**
+   * @copydoc Control::OnControlChildRemove()
+   */
+  virtual void OnControlChildRemove( Actor& child );
+
   void AllocateResources();
   void CreateRenderTasks();
   void RemoveRenderTasks();
@@ -117,6 +123,8 @@ private:
   /////////////////////////////////////////////////////////////
   // for creating a subtree for all user added child actors, so that we can have them exclusive to the mRenderChildrenTask and our other actors exclusive to our other tasks
   Actor mChildrenRoot;
+  // for creating a subtree for the internal actors
+  Actor mInternalRoot;
 
   /////////////////////////////////////////////////////////////
   // for mapping offscreen renders to render target sizes
index 0cdde34..8a608f1 100644 (file)
@@ -37,7 +37,6 @@
 // pixel format / size - set from JSON
 // aspect ratio property needs to be able to be constrained also for cameras, not possible currently. Therefore changing aspect ratio of GaussianBlurView won't currently work
 // default near clip value
-// mChildrenRoot Add()/Remove() overloads - better solution
 // Manager object - re-use render targets if there are multiple GaussianBlurViews created
 
 
@@ -133,6 +132,7 @@ GaussianBlurView::GaussianBlurView()
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New())
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mActivated( false )
 {
@@ -156,6 +156,7 @@ GaussianBlurView::GaussianBlurView( const unsigned int numSamples, const float b
   , mTargetSize(Vector2::ZERO)
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
+  , mInternalRoot(Actor::New())
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
   , mActivated( false )
 {
@@ -199,7 +200,7 @@ Toolkit::GaussianBlurView GaussianBlurView::New(const unsigned int numSamples, c
 
 /////////////////////////////////////////////////////////////
 // for creating a subtree for all user added child actors, so that we can have them exclusive to the mRenderChildrenTask and our other actors exclusive to our other tasks
-// TODO: overloading Actor::Add()/Remove() not nice since breaks polymorphism. Need another method to pass ownership of added child actors to our internal actor root.
+// DEPRECATED: overloading Actor::Add()/Remove() not nice since breaks polymorphism. Need another method to pass ownership of added child actors to our internal actor root.
 void GaussianBlurView::Add(Actor child)
 {
   mChildrenRoot.Add(child);
@@ -250,6 +251,7 @@ void GaussianBlurView::OnInitialize()
 {
   // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task
   mChildrenRoot.SetParentOrigin(ParentOrigin::CENTER);
+  mInternalRoot.SetParentOrigin(ParentOrigin::CENTER);
 
   //////////////////////////////////////////////////////
   // Create shaders
@@ -277,7 +279,8 @@ void GaussianBlurView::OnInitialize()
   mImageActorVertBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
   // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
-  mBlurStrengthPropertyIndex = Self().RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
+  Actor self = Self();
+  mBlurStrengthPropertyIndex = self.RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
 
   // Create an ImageActor for compositing the blur and the original child actors render
   if(!mBlurUserImage)
@@ -287,7 +290,7 @@ void GaussianBlurView::OnInitialize()
     mImageActorComposite.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
 
     Constraint blurStrengthConstraint = Constraint::New<float>( mImageActorComposite, Actor::Property::COLOR_ALPHA, EqualToConstraint());
-    blurStrengthConstraint.AddSource( ParentSource(mBlurStrengthPropertyIndex) );
+    blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) );
     blurStrengthConstraint.Apply();
 
     // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
@@ -303,9 +306,9 @@ void GaussianBlurView::OnInitialize()
 
     //////////////////////////////////////////////////////
     // Connect to actor tree
-    Self().Add( mImageActorComposite );
-    Self().Add( mTargetActor );
-    Self().Add( mRenderFullSizeCamera );
+    mInternalRoot.Add( mImageActorComposite );
+    mInternalRoot.Add( mTargetActor );
+    mInternalRoot.Add( mRenderFullSizeCamera );
   }
 
 
@@ -319,9 +322,10 @@ void GaussianBlurView::OnInitialize()
   //////////////////////////////////////////////////////
   // Connect to actor tree
   Self().Add( mChildrenRoot );
-  Self().Add( mImageActorHorizBlur );
-  Self().Add( mImageActorVertBlur );
-  Self().Add( mRenderDownsampledCamera );
+  Self().Add( mInternalRoot );
+  mInternalRoot.Add( mImageActorHorizBlur );
+  mInternalRoot.Add( mImageActorVertBlur );
+  mInternalRoot.Add( mRenderDownsampledCamera );
 }
 
 
@@ -353,6 +357,19 @@ void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
   }
 }
 
+void GaussianBlurView::OnControlChildAdd( Actor& child )
+{
+  if( child != mChildrenRoot && child != mInternalRoot)
+  {
+    mChildrenRoot.Add( child );
+  }
+}
+
+void GaussianBlurView::OnControlChildRemove( Actor& child )
+{
+  mChildrenRoot.Remove( child );
+}
+
 void GaussianBlurView::AllocateResources()
 {
   // size of render targets etc is based on the size of this actor, ignoring z
index 7f38489..1d8332e 100644 (file)
@@ -98,6 +98,16 @@ private:
   virtual void OnInitialize();
   virtual void OnSizeSet(const Vector3& targetSize);
 
+  /**
+   * @copydoc Control::OnControlChildAdd()
+   */
+  virtual void OnControlChildAdd( Actor& child );
+
+  /**
+   * @copydoc Control::OnControlChildRemove()
+   */
+  virtual void OnControlChildRemove( Actor& child );
+
   void SetBlurBellCurveWidth(float blurBellCurveWidth);
   float CalcGaussianWeight(float x);
   void SetShaderConstants();
@@ -138,6 +148,8 @@ private:
   /////////////////////////////////////////////////////////////
   // for creating a subtree for all user added child actors, so that we can have them exclusive to the mRenderChildrenTask and our other actors exclusive to our other tasks
   Actor mChildrenRoot;
+  // for creating a subtree for the internal actors
+  Actor mInternalRoot;
 
   /////////////////////////////////////////////////////////////
   // for mapping offscreen renders to render target sizes
index 950c819..d3f3f87 100644 (file)
@@ -36,7 +36,6 @@
 // pixel format / size - set from JSON
 // aspect ratio property needs to be able to be constrained also for cameras. (now do-able)
 // default near clip value
-// mChildrenRoot Add()/Remove() overloads - better solution
 
 
 /////////////////////////////////////////////////////////
@@ -148,19 +147,6 @@ Toolkit::ShadowView ShadowView::New(float downsampleWidthScale, float downsample
   return handle;
 }
 
-/////////////////////////////////////////////////////////////
-// for creating a subtree for all user added child actors.
-// TODO: overloading Actor::Add()/Remove() not nice since breaks polymorphism. Need another method to pass ownership of added child actors to our internal actor root.
-void ShadowView::Add(Actor child)
-{
-  mChildrenRoot.Add(child);
-}
-
-void ShadowView::Remove(Actor child)
-{
-  mChildrenRoot.Remove(child);
-}
-
 void ShadowView::SetShadowPlaneBackground(Actor shadowPlaneBackground)
 {
   mShadowPlaneBg = shadowPlaneBackground;
@@ -307,8 +293,17 @@ void ShadowView::OnInitialize()
   blurStrengthConstraint.Apply();
 }
 
-void ShadowView::OnSizeSet(const Vector3& targetSize)
+void ShadowView::OnControlChildAdd( Actor& child )
+{
+  if( child != mChildrenRoot && child != mBlurRootActor)
+  {
+    mChildrenRoot.Add( child );
+  }
+}
+
+void ShadowView::OnControlChildRemove( Actor& child )
 {
+  mChildrenRoot.Remove( child );
 }
 
 void ShadowView::ConstrainCamera()
index 68e1c33..9f7d9d6 100644 (file)
@@ -72,16 +72,6 @@ public:
   static Dali::Toolkit::ShadowView New(float downsampleWidthScale, float downsampleHeightScale);
 
   /**
-   * @copydoc Dali::Toolkit::ShadowView::Add(Actor child)
-   */
-  void Add(Actor child);
-
-  /**
-   * @copydoc Dali::Toolkit::ShadowView::Remove(Actor child)
-   */
-  void Remove(Actor child);
-
-  /**
    * @copydoc Dali::Toolkit::ShadowView::SetShadowPlaneBackground(Actor shadowPlaneBackground)
    */
   void SetShadowPlaneBackground(Actor shadowPlaneBackground);
@@ -126,7 +116,16 @@ public:
 private:
 
   virtual void OnInitialize();
-  virtual void OnSizeSet(const Vector3& targetSize);
+
+  /**
+   * @copydoc Control::OnControlChildAdd()
+   */
+  virtual void OnControlChildAdd( Actor& child );
+
+  /**
+   * @copydoc Control::OnControlChildRemove()
+   */
+  virtual void OnControlChildRemove( Actor& child );
 
   /**
    * Constrain the camera actor to the position of the point light, pointing
index a029c83..f0c3fc6 100644 (file)
@@ -883,9 +883,11 @@ void TextEditor::RenderText()
 
   if( mRenderableActor )
   {
-    const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset();
+    // TODO: Scroll and alignment needs to be refactored.
+    const Vector2& alignmentOffset = mController->GetAlignmentOffset();
+    const Vector2& scrollOffset = mController->GetScrollPosition();
 
-    mRenderableActor.SetPosition( offset.x, offset.y );
+    mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y );
 
     Actor clipRootActor;
     if( mClipper )
index a0417df..981b228 100644 (file)
@@ -1089,9 +1089,11 @@ void TextField::RenderText()
 
   if( mRenderableActor )
   {
-    const Vector2 offset = mController->GetScrollPosition() + mController->GetAlignmentOffset();
+    // TODO: Scroll and alignment needs to be refactored.
+    const Vector2& alignmentOffset = mController->GetAlignmentOffset();
+    const Vector2& scrollOffset = mController->GetScrollPosition();
 
-    mRenderableActor.SetPosition( offset.x, offset.y );
+    mRenderableActor.SetPosition( scrollOffset.x, alignmentOffset.y + scrollOffset.y );
 
     Actor clipRootActor;
     if( mClipper )
index f717bbf..7ad0bfb 100644 (file)
@@ -546,8 +546,9 @@ void TextLabel::RenderText()
 
     if( renderableActor )
     {
+      // TODO: Scroll and alignment needs to be refactored.
       const Vector2& alignmentOffset = mController->GetAlignmentOffset();
-      renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
+      renderableActor.SetPosition( 0.f, alignmentOffset.y );
 
       self.Add( renderableActor );
     }
index 31487fe..293531d 100644 (file)
@@ -4,6 +4,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/builder/builder-actor.cpp \
    $(toolkit_src_dir)/builder/builder-animations.cpp \
    $(toolkit_src_dir)/builder/builder-impl.cpp \
+   $(toolkit_src_dir)/builder/builder-impl-debug.cpp \
    $(toolkit_src_dir)/builder/builder-set-property.cpp \
    $(toolkit_src_dir)/builder/builder-signals.cpp \
    $(toolkit_src_dir)/builder/json-parser-state.cpp \
@@ -123,5 +124,3 @@ toolkit_src_files = \
    $(toolkit_src_dir)/transition-effects/cube-transition-wave-effect-impl.cpp \
    $(toolkit_src_dir)/scripting/script-impl.cpp \
    $(toolkit_src_dir)/scripting/script-plugin-proxy.cpp
-
-
index ad513a8..9d81116 100644 (file)
@@ -47,6 +47,26 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 const bool RTL = true;
 const float CURSOR_WIDTH = 1.f;
 
+Length CountParagraphs( const LayoutParameters& layoutParameters )
+{
+  Length numberOfParagraphs = 0u;
+
+  const CharacterIndex startCharacterIndex = *( layoutParameters.glyphsToCharactersBuffer + layoutParameters.startGlyphIndex );
+
+  const GlyphIndex lastGlyphIndex = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs - 1u;
+  const CharacterIndex lastCharacterIndexPlusOne = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex );
+
+  for( CharacterIndex index = startCharacterIndex; index < lastCharacterIndexPlusOne; ++index )
+  {
+    if( TextAbstraction::LINE_MUST_BREAK == *( layoutParameters.lineBreakInfoBuffer + index ) )
+    {
+      ++numberOfParagraphs;
+    }
+  }
+
+  return numberOfParagraphs;
+}
+
 } //namespace
 
 /**
@@ -172,7 +192,7 @@ struct LayoutEngine::Impl
    * @note This method lais out text as it were left to right. At this point is not possible to reorder the line
    *       because the number of characters of the line is not known (one of the responsabilities of this method
    *       is calculate that). Due to glyph's 'x' bearing, width and advance, when right to left or mixed right to left
-   *       and left to right text is laid out, it can be small differences in the line length. One solution is to
+   *       and left to right text is laid-out, it can be small differences in the line length. One solution is to
    *       reorder and re-lay out the text after this method and add or remove one extra glyph if needed. However,
    *       this method calculates which are the first and last glyphs of the line (the ones that causes the
    *       differences). This is a good point to check if there is problems with the text exceeding the boundaries
@@ -219,8 +239,9 @@ struct LayoutEngine::Impl
 
     bool oneWordLaidOut = false;
 
+    const GlyphIndex lastGlyphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
-         glyphIndex < parameters.totalNumberOfGlyphs;
+         glyphIndex < lastGlyphPlusOne;
          ++glyphIndex )
     {
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  glyph index : %d\n", glyphIndex );
@@ -369,7 +390,7 @@ struct LayoutEngine::Impl
         {
           DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  Break the word by character\n" );
 
-          // The word's with doesn't fit in the control's with. It needs to be split by character.
+          // The word doesn't fit in the control's width. It needs to be split by character.
           if( tmpLineLayout.numberOfGlyphs > 0u )
           {
             tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
@@ -420,7 +441,7 @@ struct LayoutEngine::Impl
           ( TextAbstraction::WORD_BREAK == wordBreakInfo ) )
       {
         oneWordLaidOut = true;
-        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  One word laid out\n" );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  One word laid-out\n" );
 
         // Current glyph is the last one of the current word.
         // Add the temporal layout to the current one.
@@ -438,6 +459,34 @@ struct LayoutEngine::Impl
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
   }
 
+  /**
+   * @brief Calculates the vertical offset to add to the new laid-out glyphs.
+   *
+   * @pre @p lineIndex must be between 0 and the number of lines (both inclusive).
+   *
+   * @param[in] lines The previously laid-out lines.
+   * @param[in] lineIndex Index to the line where the new laid-out lines are inserted.
+   *
+   * @return The vertical offset of the lines starting from the beginning to the line @p lineIndex.
+   */
+  float SetParagraphOffset( const Vector<LineRun>& lines,
+                            LineIndex lineIndex )
+  {
+    float offset = 0.f;
+
+    for( Vector<LineRun>::ConstIterator it = lines.Begin(),
+           endIt = lines.Begin() + lineIndex;
+         it != endIt;
+         ++it )
+    {
+      const LineRun& line = *it;
+
+      offset += line.ascender + -line.descender;
+    }
+
+    return offset;
+  }
+
   void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
                           Length numberOfGlyphs,
                           float penY,
@@ -464,19 +513,327 @@ struct LayoutEngine::Impl
     }
   }
 
+  /**
+   * @brief Resizes the line buffer.
+   *
+   * @param[in,out] lines The vector of lines. Used when the layout is created from scratch.
+   * @param[in,out] newLines The vector of lines used instead of @p lines when the layout is updated.
+   * @param[in,out] linesCapacity The capacity of the vector (either lines or newLines).
+   * @param[in] updateCurrentBuffer Whether the layout is updated.
+   *
+   * @return Pointer to either lines or newLines.
+   */
+  LineRun* ResizeLinesBuffer( Vector<LineRun>& lines,
+                              Vector<LineRun>& newLines,
+                              Length& linesCapacity,
+                              bool updateCurrentBuffer )
+  {
+    LineRun* linesBuffer = NULL;
+    // Reserve more space for the next lines.
+    linesCapacity *= 2u;
+    if( updateCurrentBuffer )
+    {
+      newLines.Resize( linesCapacity );
+      linesBuffer = newLines.Begin();
+    }
+    else
+    {
+      lines.Resize( linesCapacity );
+      linesBuffer = lines.Begin();
+    }
+
+    return linesBuffer;
+  }
+
+  /**
+   * Ellipsis a line if it exceeds the width's of the bounding box.
+   *
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in] layout The line layout.
+   * @param[in,out] layoutSize The text's layout size.
+   * @param[in,out] linesBuffer Pointer to the line's buffer.
+   * @param[in,out] glyphPositionsBuffer Pointer to the position's buffer.
+   * @param[in,out] numberOfLines The number of laid-out lines.
+   * @param[in] penY The vertical layout position.
+   * @param[in] currentParagraphDirection The current paragraph's direction.
+   *
+   * return Whether the line is ellipsized.
+   */
+  bool EllipsisLine( const LayoutParameters& layoutParameters,
+                     const LineLayout& layout,
+                     Size& layoutSize,
+                     LineRun* linesBuffer,
+                     Vector2* glyphPositionsBuffer,
+                     Length& numberOfLines,
+                     float penY,
+                     CharacterDirection currentParagraphDirection )
+  {
+    const bool ellipsis = ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
+                            ( ( mLayout == SINGLE_LINE_BOX ) &&
+                              ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) );
+
+    if( ellipsis )
+    {
+      // Do not layout more lines if ellipsis is enabled.
+
+      // The last line needs to be completely filled with characters.
+      // Part of a word may be used.
+
+      LineRun* lineRun = NULL;
+      LineLayout ellipsisLayout;
+      if( 0u != numberOfLines )
+      {
+        // Get the last line and layout it again with the 'completelyFill' flag to true.
+        lineRun = linesBuffer + ( numberOfLines - 1u );
+
+        penY -= layout.ascender - lineRun->descender;
+
+        ellipsisLayout.glyphIndex = lineRun->glyphRun.glyphIndex;
+      }
+      else
+      {
+        // At least there is space reserved for one line.
+        lineRun = linesBuffer;
+
+        lineRun->glyphRun.glyphIndex = 0u;
+        ellipsisLayout.glyphIndex = 0u;
+
+        ++numberOfLines;
+      }
+
+      GetLineLayoutForBox( layoutParameters,
+                           ellipsisLayout,
+                           currentParagraphDirection,
+                           true );
+
+      lineRun->glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
+      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->ascender = ellipsisLayout.ascender;
+      lineRun->descender = ellipsisLayout.descender;
+      lineRun->direction = !RTL;
+      lineRun->ellipsis = true;
+
+      layoutSize.width = layoutParameters.boundingBox.width;
+      layoutSize.height += ( lineRun->ascender + -lineRun->descender );
+
+      SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
+                         ellipsisLayout.numberOfGlyphs,
+                         penY,
+                         glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
+    }
+
+    return ellipsis;
+  }
+
+  /**
+   * @brief Updates the text layout with a new laid-out line.
+   *
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in] layout The line layout.
+   * @param[in,out] layoutSize The text's layout size.
+   * @param[in,out] linesBuffer Pointer to the line's buffer.
+   * @param[in] index Index to the vector of glyphs.
+   * @param[in,out] numberOfLines The number of laid-out lines.
+   * @param[in] isLastLine Whether the laid-out line is the last one.
+   */
+  void UpdateTextLayout( const LayoutParameters& layoutParameters,
+                         const LineLayout& layout,
+                         Size& layoutSize,
+                         LineRun* linesBuffer,
+                         GlyphIndex index,
+                         Length& numberOfLines,
+                         bool isLastLine )
+  {
+    LineRun& lineRun = *( linesBuffer + numberOfLines );
+    ++numberOfLines;
+
+    lineRun.glyphRun.glyphIndex = index;
+    lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
+    lineRun.characterRun.characterIndex = layout.characterIndex;
+    lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
+    if( isLastLine && !layoutParameters.isLastNewParagraph )
+    {
+      const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
+      if( MULTI_LINE_BOX == mLayout )
+      {
+        lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
+      }
+      else
+      {
+        lineRun.width = width;
+      }
+
+      lineRun.extraLength = 0.f;
+    }
+    else
+    {
+      lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
+      lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+    }
+    lineRun.ascender = layout.ascender;
+    lineRun.descender = layout.descender;
+    lineRun.direction = !RTL;
+    lineRun.ellipsis = false;
+
+    // Update the actual size.
+    if( lineRun.width > layoutSize.width )
+    {
+      layoutSize.width = lineRun.width;
+    }
+
+    layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+  }
+
+  /**
+   * @brief Updates the text layout with the last laid-out line.
+   *
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in] layout The line layout.
+   * @param[in,out] layoutSize The text's layout size.
+   * @param[in,out] linesBuffer Pointer to the line's buffer.
+   * @param[in] index Index to the vector of glyphs.
+   * @param[in,out] numberOfLines The number of laid-out lines.
+   */
+  void UpdateTextLayout( const LayoutParameters& layoutParameters,
+                         const LineLayout& layout,
+                         Size& layoutSize,
+                         LineRun* linesBuffer,
+                         GlyphIndex index,
+                         Length& numberOfLines )
+  {
+    // Need to add a new line with no characters but with height to increase the layoutSize.height
+    const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
+
+    Text::FontMetrics fontMetrics;
+    mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
+
+    LineRun& lineRun = *( linesBuffer + numberOfLines );
+    ++numberOfLines;
+
+    lineRun.glyphRun.glyphIndex = index + layout.numberOfGlyphs;
+    lineRun.glyphRun.numberOfGlyphs = 0u;
+    lineRun.characterRun.characterIndex = layout.characterIndex + layout.numberOfCharacters;
+    lineRun.characterRun.numberOfCharacters = 0u;
+    lineRun.width = 0.f;
+    lineRun.ascender = fontMetrics.ascender;
+    lineRun.descender = fontMetrics.descender;
+    lineRun.extraLength = 0.f;
+    lineRun.alignmentOffset = 0.f;
+    lineRun.direction = !RTL;
+    lineRun.ellipsis = false;
+
+    layoutSize.height += ( lineRun.ascender + -lineRun.descender );
+  }
+
+  /**
+   * @brief Updates the text's layout size adding the size of the previously laid-out lines.
+   *
+   * @param[in] lines The vector of lines (before the new laid-out lines are inserted).
+   * @param[in,out] layoutSize The text's layout size.
+   */
+  void UpdateLayoutSize( const Vector<LineRun>& lines,
+                         Size& layoutSize )
+  {
+    for( Vector<LineRun>::ConstIterator it = lines.Begin(),
+           endIt = lines.End();
+         it != endIt;
+         ++it )
+    {
+      const LineRun& line = *it;
+
+      if( line.width > layoutSize.width )
+      {
+        layoutSize.width = line.width;
+      }
+
+      layoutSize.height += ( line.ascender + -line.descender );
+    }
+  }
+
+  /**
+   * @brief Updates the indices of the character and glyph runs of the lines before the new lines are inserted.
+   *
+   * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in,out] lines The vector of lines (before the new laid-out lines are inserted).
+   * @param[in] characterOffset The offset to be added to the runs of characters.
+   * @param[in] glyphOffset The offset to be added to the runs of glyphs.
+   */
+  void UpdateLineIndexOffsets( const LayoutParameters& layoutParameters,
+                               Vector<LineRun>& lines,
+                               Length characterOffset,
+                               Length glyphOffset )
+  {
+    // Update the glyph and character runs.
+    for( Vector<LineRun>::Iterator it = lines.Begin() + layoutParameters.startLineIndex,
+           endIt = lines.End();
+         it != endIt;
+         ++it )
+    {
+      LineRun& line = *it;
+
+      line.glyphRun.glyphIndex = glyphOffset;
+      line.characterRun.characterIndex = characterOffset;
+
+      glyphOffset += line.glyphRun.numberOfGlyphs;
+      characterOffset += line.characterRun.numberOfCharacters;
+    }
+  }
+
   bool LayoutText( const LayoutParameters& layoutParameters,
                    Vector<Vector2>& glyphPositions,
                    Vector<LineRun>& lines,
-                   Size& actualSize )
+                   Size& layoutSize )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" );
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height );
 
+    if( 0u == layoutParameters.numberOfGlyphs )
+    {
+      // Nothing to do if there are no glyphs to layout.
+      return false;
+    }
+
     // Set the first paragraph's direction.
     CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL;
 
-    float penY = 0.f;
-    for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
+    // Whether the layout is being updated or set from scratch.
+    const bool updateCurrentBuffer = layoutParameters.numberOfGlyphs < layoutParameters.totalNumberOfGlyphs;
+
+    Vector2* glyphPositionsBuffer = NULL;
+    Vector<Vector2> newGlyphPositions;
+
+    LineRun* linesBuffer = NULL;
+    Vector<LineRun> newLines;
+
+    // Estimate the number of lines.
+    // TODO: In a next patch the paragraphs are properly managed and this can be removed.
+    Length linesCapacity = CountParagraphs( layoutParameters );
+    Length numberOfLines = 0u;
+
+    if( updateCurrentBuffer )
+    {
+      newGlyphPositions.Resize( layoutParameters.numberOfGlyphs );
+      glyphPositionsBuffer = newGlyphPositions.Begin();
+
+      newLines.Resize( linesCapacity );
+      linesBuffer = newLines.Begin();
+    }
+    else
+    {
+      glyphPositionsBuffer = glyphPositions.Begin();
+
+      lines.Resize( linesCapacity );
+      linesBuffer = lines.Begin();
+    }
+
+    float penY = SetParagraphOffset( lines,
+                                     layoutParameters.startLineIndex );
+
+    const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs;
+    for( GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne; )
     {
       CharacterDirection currentParagraphDirection = paragraphDirection;
 
@@ -498,6 +855,8 @@ struct LayoutEngine::Impl
       {
         // The width is too small and no characters are laid-out.
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText width too small!\n\n" );
+
+        lines.Resize( numberOfLines );
         return false;
       }
 
@@ -506,167 +865,155 @@ struct LayoutEngine::Impl
       penY += layout.ascender;
 
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  pen y %f\n", penY );
-      if( mEllipsisEnabled &&
-          ( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
-            ( ( mLayout == SINGLE_LINE_BOX ) &&
-              ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) ) )
-      {
-        // Do not layout more lines if ellipsis is enabled.
-
-        // The last line needs to be completely filled with characters.
-        // Part of a word may be used.
-
-        const Length numberOfLines = lines.Count();
-
-        LineRun lineRun;
-        LineLayout ellipsisLayout;
-        if( 0u != numberOfLines )
-        {
-          // Get the last line and layout it again with the 'completelyFill' flag to true.
-          lineRun = *( lines.Begin() + ( numberOfLines - 1u ) );
 
-          penY -= layout.ascender - lineRun.descender;
-
-          ellipsisLayout.glyphIndex = lineRun.glyphRun.glyphIndex;
-        }
-        else
-        {
-          lineRun.glyphRun.glyphIndex = 0u;
-          ellipsisLayout.glyphIndex = 0u;
-        }
-
-        GetLineLayoutForBox( layoutParameters,
-                             ellipsisLayout,
-                             currentParagraphDirection,
-                             true );
-
-        lineRun.glyphRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
-        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.ascender = ellipsisLayout.ascender;
-        lineRun.descender = ellipsisLayout.descender;
-        lineRun.direction = !RTL;
-        lineRun.ellipsis = true;
-
-        actualSize.width = layoutParameters.boundingBox.width;
-        actualSize.height += ( lineRun.ascender + -lineRun.descender );
-
-        SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun.glyphRun.glyphIndex,
-                           ellipsisLayout.numberOfGlyphs,
-                           penY,
-                           glyphPositions.Begin() + lineRun.glyphRun.glyphIndex );
-
-        if( 0u != numberOfLines )
-        {
-          // Set the last line with the ellipsis layout.
-          *( lines.Begin() + ( numberOfLines - 1u ) ) = lineRun;
-        }
-        else
-        {
-          // Push the line.
-          lines.PushBack( lineRun );
-        }
+      bool ellipsis = false;
+      if( mEllipsisEnabled )
+      {
+        // Does the ellipsis of the last line.
+        ellipsis = EllipsisLine( layoutParameters,
+                                 layout,
+                                 layoutSize,
+                                 linesBuffer,
+                                 glyphPositionsBuffer,
+                                 numberOfLines,
+                                 penY,
+                                 currentParagraphDirection );
+      }
 
+      if( ellipsis )
+      {
+        // No more lines to layout.
         break;
       }
       else
       {
+        // Whether the last line has been laid-out.
         const bool isLastLine = index + layout.numberOfGlyphs == layoutParameters.totalNumberOfGlyphs;
 
-        LineRun lineRun;
-        lineRun.glyphRun.glyphIndex = index;
-        lineRun.glyphRun.numberOfGlyphs = layout.numberOfGlyphs;
-        lineRun.characterRun.characterIndex = layout.characterIndex;
-        lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters;
-        if( isLastLine && !layoutParameters.isLastNewParagraph )
+        if( numberOfLines == linesCapacity )
         {
-          const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
-          if( MULTI_LINE_BOX == mLayout )
-          {
-            lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
-          }
-          else
-          {
-            lineRun.width = width;
-          }
-
-          lineRun.extraLength = 0.f;
+          // Reserve more space for the next lines.
+          linesBuffer = ResizeLinesBuffer( lines,
+                                           newLines,
+                                           linesCapacity,
+                                           updateCurrentBuffer );
         }
-        else
-        {
-          lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
-          lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
-        }
-        lineRun.ascender = layout.ascender;
-        lineRun.descender = layout.descender;
-        lineRun.direction = !RTL;
-        lineRun.ellipsis = false;
 
-        lines.PushBack( lineRun );
+        // Updates the current text's layout with the line's layout.
+        UpdateTextLayout( layoutParameters,
+                          layout,
+                          layoutSize,
+                          linesBuffer,
+                          index,
+                          numberOfLines,
+                          isLastLine );
 
-        // Update the actual size.
-        if( lineRun.width > actualSize.width )
+        if( isLastLine &&
+            layoutParameters.isLastNewParagraph &&
+            ( mLayout == MULTI_LINE_BOX ) )
         {
-          actualSize.width = lineRun.width;
-        }
+          // The last character of the text is a new paragraph character.
+          // An extra line with no characters is added to increase the text's height
+          // in order to place the cursor.
+
+          if( numberOfLines == linesCapacity )
+          {
+            // Reserve more space for the next lines.
+            linesBuffer = ResizeLinesBuffer( lines,
+                                             newLines,
+                                             linesCapacity,
+                                             updateCurrentBuffer );
+          }
 
-        actualSize.height += ( lineRun.ascender + -lineRun.descender );
+          UpdateTextLayout( layoutParameters,
+                            layout,
+                            layoutSize,
+                            linesBuffer,
+                            index,
+                            numberOfLines );
+        } // whether to add a last line.
 
+        // Sets the positions of the glyphs.
         SetGlyphPositions( layoutParameters.glyphsBuffer + index,
                            layout.numberOfGlyphs,
                            penY,
-                           glyphPositions.Begin() + index );
+                           glyphPositionsBuffer + index - layoutParameters.startGlyphIndex );
 
+        // Updates the vertical pen's position.
         penY += -layout.descender;
 
         // Increase the glyph index.
         index += layout.numberOfGlyphs;
 
-        if( isLastLine &&
-            layoutParameters.isLastNewParagraph &&
-            ( mLayout == MULTI_LINE_BOX ) )
-        {
-          // Need to add a new line with no characters but with height to increase the actualSize.height
-          const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
-
-          Text::FontMetrics fontMetrics;
-          mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
-
-          LineRun lineRun;
-          lineRun.glyphRun.glyphIndex = 0u;
-          lineRun.glyphRun.numberOfGlyphs = 0u;
-          lineRun.characterRun.characterIndex = 0u;
-          lineRun.characterRun.numberOfCharacters = 0u;
-          lineRun.width = 0.f;
-          lineRun.ascender = fontMetrics.ascender;
-          lineRun.descender = fontMetrics.descender;
-          lineRun.extraLength = 0.f;
-          lineRun.alignmentOffset = 0.f;
-          lineRun.direction = !RTL;
-          lineRun.ellipsis = false;
-
-          actualSize.height += ( lineRun.ascender + -lineRun.descender );
-
-          lines.PushBack( lineRun );
-        }
-      }
+      } // no ellipsis
     } // end for() traversing glyphs.
 
+    if( updateCurrentBuffer )
+    {
+      glyphPositions.Insert( glyphPositions.Begin() + layoutParameters.startGlyphIndex,
+                             newGlyphPositions.Begin(),
+                             newGlyphPositions.End() );
+
+      newLines.Resize( numberOfLines );
+
+      // Current text's layout size adds only the newly laid-out lines.
+      // Updates the layout size with the previously laid-out lines.
+      UpdateLayoutSize( lines,
+                        layoutSize );
+
+      if( 0u != newLines.Count() )
+      {
+        const LineRun& lastLine = *( newLines.End() - 1u );
+
+        const Length characterOffset = lastLine.characterRun.characterIndex + lastLine.characterRun.numberOfCharacters;
+        const Length glyphOffset = lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs;
+
+        // Update the indices of the runs before the new laid-out lines are inserted.
+        UpdateLineIndexOffsets( layoutParameters,
+                                lines,
+                                characterOffset,
+                                glyphOffset );
+
+        // Insert the lines.
+        lines.Insert( lines.Begin() + layoutParameters.startLineIndex,
+                      newLines.Begin(),
+                      newLines.End() );
+      }
+    }
+    else
+    {
+      lines.Resize( numberOfLines );
+    }
+
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
 
     return true;
   }
 
   void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                 CharacterIndex startIndex,
+                                 Length numberOfCharacters,
                                  Vector<Vector2>& glyphPositions )
   {
+    const CharacterIndex lastCharacterIndex = startIndex + numberOfCharacters;
+
     // Traverses the paragraphs with right to left characters.
     for( LineIndex lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex )
     {
       const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer + lineIndex );
 
+      if( startIndex >= bidiLine.characterRun.characterIndex + bidiLine.characterRun.numberOfCharacters )
+      {
+        // Do not reorder the line if it has been already reordered.
+        continue;
+      }
+
+      if( bidiLine.characterRun.characterIndex >= lastCharacterIndex )
+      {
+        // Do not reorder the lines after the last requested character.
+        break;
+      }
+
       const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap;
       const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) );
 
@@ -702,48 +1049,71 @@ struct LayoutEngine::Impl
     }
   }
 
-  void Align( const Size& layoutSize,
+  void Align( const Size& size,
+              CharacterIndex startIndex,
+              Length numberOfCharacters,
               Vector<LineRun>& lines )
   {
-    // Traverse all lines and align the glyphs.
+    const CharacterIndex lastCharacterPlusOne = startIndex + numberOfCharacters;
 
+    // Traverse all lines and align the glyphs.
     for( Vector<LineRun>::Iterator it = lines.Begin(), endIt = lines.End();
          it != endIt;
          ++it )
     {
       LineRun& line = *it;
-      const bool isLastLine = lines.End() == it + 1u;
 
-      // Calculate the alignment offset accordingly with the align option,
-      // the box width, line length, and the paragraphs direction.
-      CalculateHorizontalAlignment( layoutSize.width,
-                                    line,
-                                    isLastLine );
+      if( line.characterRun.characterIndex < startIndex )
+      {
+        // Do not align lines which have already been aligned.
+        continue;
+      }
+
+      if( line.characterRun.characterIndex >= lastCharacterPlusOne )
+      {
+        // Do not align lines beyond the last laid-out character.
+        break;
+      }
+
+      // Calculate the line's alignment offset accordingly with the align option,
+      // the box width, line length, and the paragraph's direction.
+      CalculateHorizontalAlignment( size.width,
+                                    line );
     }
   }
 
   void CalculateHorizontalAlignment( float boxWidth,
-                                     LineRun& line,
-                                     bool isLastLine )
+                                     LineRun& line )
   {
     line.alignmentOffset = 0.f;
     const bool isRTL = RTL == line.direction;
     float lineLength = line.width;
 
     HorizontalAlignment alignment = mHorizontalAlignment;
-    if( isRTL &&
-        ( HORIZONTAL_ALIGN_CENTER != alignment ) )
+    if( isRTL )
     {
-      if( HORIZONTAL_ALIGN_BEGIN == alignment )
-      {
-        alignment = HORIZONTAL_ALIGN_END;
-      }
-      else
+      // Swap the alignment type if the line is right to left.
+      switch( alignment )
       {
-        alignment = HORIZONTAL_ALIGN_BEGIN;
+        case HORIZONTAL_ALIGN_BEGIN:
+        {
+          alignment = HORIZONTAL_ALIGN_END;
+          break;
+        }
+        case HORIZONTAL_ALIGN_CENTER:
+        {
+          // Nothing to do.
+          break;
+        }
+        case HORIZONTAL_ALIGN_END:
+        {
+          alignment = HORIZONTAL_ALIGN_BEGIN;
+          break;
+        }
       }
     }
 
+    // Calculate the horizontal line offset.
     switch( alignment )
     {
       case HORIZONTAL_ALIGN_BEGIN:
@@ -754,39 +1124,16 @@ struct LayoutEngine::Impl
         {
           // 'Remove' the white spaces at the end of the line (which are at the beginning in visual order)
           line.alignmentOffset -= line.extraLength;
-
-          if( isLastLine )
-          {
-            line.alignmentOffset += std::min( line.extraLength, boxWidth - lineLength );
-          }
         }
         break;
       }
       case HORIZONTAL_ALIGN_CENTER:
       {
-        if( isLastLine && !isRTL )
-        {
-          // Add the length of the white saces at the end of the line.
-          lineLength += line.extraLength;
-          if( lineLength > boxWidth )
-          {
-            // The line's length is longer than the box's width.
-            // Set the line's offset to 0 and nothing else to do.
-            line.alignmentOffset = 0.f;
-            break;
-          }
-        }
-
         line.alignmentOffset = 0.5f * ( boxWidth - lineLength );
 
         if( isRTL )
         {
           line.alignmentOffset -= line.extraLength;
-
-          if( isLastLine )
-          {
-            line.alignmentOffset += 0.5f * std::min( line.extraLength, boxWidth - lineLength );
-          }
         }
 
         line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
@@ -794,16 +1141,6 @@ struct LayoutEngine::Impl
       }
       case HORIZONTAL_ALIGN_END:
       {
-        if( isLastLine && !isRTL )
-        {
-          lineLength += line.extraLength;
-          if( lineLength > boxWidth )
-          {
-            line.alignmentOffset = 0.f;
-            break;
-          }
-        }
-
         if( isRTL )
         {
           lineLength += line.extraLength;
@@ -846,7 +1183,7 @@ void LayoutEngine::SetLayout( Layout layout )
   mImpl->mLayout = layout;
 }
 
-unsigned int LayoutEngine::GetLayout() const
+LayoutEngine::Layout LayoutEngine::GetLayout() const
 {
   return mImpl->mLayout;
 }
@@ -894,25 +1231,33 @@ int LayoutEngine::GetCursorWidth() const
 bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters,
                                Vector<Vector2>& glyphPositions,
                                Vector<LineRun>& lines,
-                               Size& actualSize )
+                               Size& layoutSize )
 {
   return mImpl->LayoutText( layoutParameters,
                             glyphPositions,
                             lines,
-                            actualSize );
+                            layoutSize );
 }
 
 void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                             CharacterIndex startIndex,
+                                             Length numberOfCharacters,
                                              Vector<Vector2>& glyphPositions )
 {
   mImpl->ReLayoutRightToLeftLines( layoutParameters,
+                                   startIndex,
+                                   numberOfCharacters,
                                    glyphPositions );
 }
 
-void LayoutEngine::Align( const Size& layoutSize,
+void LayoutEngine::Align( const Size& size,
+                          CharacterIndex startIndex,
+                          Length numberOfCharacters,
                           Vector<LineRun>& lines )
 {
-  mImpl->Align( layoutSize,
+  mImpl->Align( size,
+                startIndex,
+                numberOfCharacters,
                 lines );
 }
 
index f866f3e..e672c53 100644 (file)
@@ -93,7 +93,7 @@ public:
    *
    * @return The required layout.
    */
-  unsigned int GetLayout() const;
+  Layout GetLayout() const;
 
   /**
    * @brief Enable or disable the text ellipsis.
@@ -155,14 +155,14 @@ public:
    * @param[in] layoutParameters The parameters needed to layout the text.
    * @param[out] glyphPositions The positions of all the glyphs.
    * @param[out] lines The laid-out lines.
-   * @param[out] actualSize The size of the text after it has been laid-out.
+   * @param[out] layoutSize The size of the text after it has been laid-out.
    *
    * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character.
    */
   bool LayoutText( const LayoutParameters& layoutParameters,
                    Vector<Vector2>& glyphPositions,
                    Vector<LineRun>& lines,
-                   Size& actualSize );
+                   Size& layoutSize );
 
   /**
    * @brief Re-lays out those lines with right to left characters.
@@ -170,18 +170,26 @@ public:
    * It doesn't change the phisical position of the glyphs in the model but sets their new position.
    *
    * @param[in] layoutParameters The parameters needed to layout the text.
+   * @param[in] startIndex Character index of the line from where the lines are reordered.
+   * @param[in] numberOfCharacters The number of characters.
    * @param[in,out] glyphPositions The positions of all the glyphs.
    */
   void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters,
+                                 CharacterIndex startIndex,
+                                 Length numberOfCharacters,
                                  Vector<Vector2>& glyphPositions );
 
   /**
    * @brief Aligns the laid out lines.
    *
-   * @param[in] layoutSize The size of the laid out the text.
+   * @param[in] size The size of the container where the text is laid-out.
+   * @param[in] startIndex Character index of the line from where the lines are aligned.
+   * @param[in] numberOfCharacters The number of characters.
    * @param[in,out] lines The laid-out lines.
    */
-  void Align( const Size& layoutSize,
+  void Align( const Size& size,
+              CharacterIndex startIndex,
+              Length numberOfCharacters,
               Vector<LineRun>& lines );
 
 private:
index 78746ff..238dade 100644 (file)
@@ -47,49 +47,60 @@ struct LayoutParameters
    * @param[in] textBuffer The text buffer.
    * @param[in] lineBreakInfoBuffer The line break info.
    * @param[in] wordBreakInfoBuffer The word break info.
-   * @param[in] totalNumberOfGlyphs The number of glyphs.
-   * @param[in] glyphsBuffer A vector with glyphs.
+   * @param[in] characterDirectionBuffer Vector with the direction of each character.
+   * @param[in] glyphsBuffer Vector with glyphs.
    * @param[in] glyphsToCharactersBuffer Vector with indices pointing the first character of each glyph.
    * @param[in] charactersPerGlyphBuffer Vector with the number of characters that forms each glyph.
+   * @param[in] charactersToGlyphsBuffer Vector with indices pointing the first glyph of each character.
+   * @param[in] glyphsPerCharacterBuffer Vector with the number of glyphs shaped from the character.
+   * @param[in] totalNumberOfGlyphs The number of glyphs.
    */
   LayoutParameters( const Vector2& boundingBox,
                     const Character* const textBuffer,
                     const LineBreakInfo* const lineBreakInfoBuffer,
                     const WordBreakInfo* const wordBreakInfoBuffer,
                     const CharacterDirection* const characterDirectionBuffer,
-                    Length totalNumberOfGlyphs,
                     const GlyphInfo* const glyphsBuffer,
                     const CharacterIndex* const glyphsToCharactersBuffer,
-                    const Length* const charactersPerGlyphBuffer )
+                    const Length* const charactersPerGlyphBuffer,
+                    const GlyphIndex* const charactersToGlyphsBuffer,
+                    const Length* const glyphsPerCharacterBuffer,
+                    Length totalNumberOfGlyphs )
   : boundingBox( boundingBox ),
     textBuffer( textBuffer ),
     lineBreakInfoBuffer( lineBreakInfoBuffer ),
     wordBreakInfoBuffer( wordBreakInfoBuffer ),
     characterDirectionBuffer( characterDirectionBuffer ),
-    totalNumberOfGlyphs( totalNumberOfGlyphs ),
     glyphsBuffer( glyphsBuffer ),
     glyphsToCharactersBuffer( glyphsToCharactersBuffer ),
     charactersPerGlyphBuffer( charactersPerGlyphBuffer ),
-    charactersToGlyphsBuffer( NULL ),
-    glyphsPerCharacterBuffer( NULL ),
+    charactersToGlyphsBuffer( charactersToGlyphsBuffer ),
+    glyphsPerCharacterBuffer( glyphsPerCharacterBuffer ),
     lineBidirectionalInfoRunsBuffer( NULL ),
     numberOfBidirectionalInfoRuns( 0u ),
+    startGlyphIndex( 0u ),
+    numberOfGlyphs( 0u ),
+    totalNumberOfGlyphs( totalNumberOfGlyphs ),
+    startLineIndex( 0u ),
     isLastNewParagraph( false )
   {}
 
-  Vector2                         boundingBox;
-  const Character* const          textBuffer;
-  const LineBreakInfo* const      lineBreakInfoBuffer;
-  const WordBreakInfo* const      wordBreakInfoBuffer;
-  const CharacterDirection* const characterDirectionBuffer;
-  Length                          totalNumberOfGlyphs;
-  const GlyphInfo* const          glyphsBuffer;
-  const CharacterIndex* const     glyphsToCharactersBuffer;
-  const Length* const             charactersPerGlyphBuffer;
-  GlyphIndex*                     charactersToGlyphsBuffer;        ///< The character to glyph conversion table.
-  Length*                         glyphsPerCharacterBuffer;        ///< The number of glyphs per character.
+  Vector2                         boundingBox;                     ///< The size of the box containing the text.
+  const Character* const          textBuffer;                      ///< The text buffer.
+  const LineBreakInfo* const      lineBreakInfoBuffer;             ///< The line break info.
+  const WordBreakInfo* const      wordBreakInfoBuffer;             ///< The word break info.
+  const CharacterDirection* const characterDirectionBuffer;        ///< Vector with the direction of each character.
+  const GlyphInfo* const          glyphsBuffer;                    ///< Vector with glyphs.
+  const CharacterIndex* const     glyphsToCharactersBuffer;        ///< Vector with indices pointing the first character of each glyph.
+  const Length* const             charactersPerGlyphBuffer;        ///< Vector with the number of characters that forms each glyph.
+  const GlyphIndex* const         charactersToGlyphsBuffer;        ///< Vector with indices pointing the first glyph of each character.
+  const Length* const             glyphsPerCharacterBuffer;        ///< Vector with the number of glyphs shaped from the character.
   BidirectionalLineInfoRun*       lineBidirectionalInfoRunsBuffer; ///< Bidirectional conversion tables per line.
   Length                          numberOfBidirectionalInfoRuns;   ///< The number of lines with bidirectional info.
+  GlyphIndex                      startGlyphIndex;                 ///< Index to the first glyph to layout.
+  Length                          numberOfGlyphs;                  ///< The number of glyphs to layout.
+  Length                          totalNumberOfGlyphs;             ///< The number of glyphs.
+  LineIndex                       startLineIndex;                  ///< The line index where to insert the new lines.
   bool                            isLastNewParagraph;              ///< Whether the last character is a new paragraph character.
 };
 
index f4692dc..88b2857 100644 (file)
@@ -176,7 +176,8 @@ struct AtlasRenderer::Impl
     mDepth = depth;
 
     const Vector2& actorSize( view.GetControlSize() );
-    const Vector2 halfActorSize( actorSize * 0.5f );
+    const Vector2& textSize( view.GetLayoutSize() );
+    const Vector2 halfTextSize( textSize * 0.5f );
     const Vector2& shadowOffset( view.GetShadowOffset() );
     const Vector4& shadowColor( view.GetShadowColor() );
     const bool underlineEnabled( view.IsUnderlineEnabled() );
@@ -323,7 +324,7 @@ struct AtlasRenderer::Impl
         }
 
         // Move the origin (0,0) of the mesh to the center of the actor
-        const Vector2 position = *( positionsBuffer + i ) - halfActorSize;
+        const Vector2 position = *( positionsBuffer + i ) - halfTextSize;
 
         // Generate mesh data for this quad, plugging in our supplied position
         AtlasManager::Mesh2D newMesh;
@@ -395,7 +396,7 @@ struct AtlasRenderer::Impl
       {
         MeshRecord& meshRecord = *it;
 
-        Actor actor = CreateMeshActor( meshRecord, actorSize );
+        Actor actor = CreateMeshActor( meshRecord, textSize );
 
         // Create an effect if necessary
         if( style == STYLE_DROP_SHADOW )
@@ -416,7 +417,7 @@ struct AtlasRenderer::Impl
           containerActor.SetParentOrigin( ParentOrigin::CENTER );
           containerActor.SetSize( actorSize );
 
-          Actor shadowActor = CreateMeshActor( meshRecord, actorSize );
+          Actor shadowActor = CreateMeshActor( meshRecord, textSize );
 #if defined(DEBUG_ENABLED)
           shadowActor.SetName( "Text Shadow renderable actor" );
 #endif
@@ -427,8 +428,6 @@ struct AtlasRenderer::Impl
             Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) );
             int depthIndex = renderer.GetProperty<int>(Dali::Renderer::Property::DEPTH_INDEX);
             renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex - 1 );
-            shadowActor.SetParentOrigin( ParentOrigin::CENTER );
-            shadowActor.SetSize( actorSize );
             containerActor.Add( shadowActor );
             containerActor.Add( actor );
             actor = containerActor;
@@ -498,7 +497,11 @@ struct AtlasRenderer::Impl
     actor.SetName( "Text renderable actor" );
 #endif
     actor.AddRenderer( renderer );
-    actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned
+
+    // Keep all of the origins aligned
+    actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+    actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
     actor.SetSize( actorSize );
     actor.RegisterProperty("uOffset", Vector2::ZERO );
     return actor;
index c2c2fa8..d681730 100644 (file)
@@ -678,7 +678,7 @@ void Controller::Impl::OnPanEvent( const Event& event )
   if( Gesture::Started    == state ||
       Gesture::Continuing == state )
   {
-    const Vector2& actualSize = mVisualModel->GetActualSize();
+    const Vector2& actualSize = mVisualModel->GetLayoutSize();
     const Vector2 currentScroll = mEventData->mScrollPosition;
 
     if( mEventData->mHorizontalScrollingEnabled )
@@ -833,7 +833,7 @@ void Controller::Impl::OnHandleEvent( const Event& event )
   else if( HANDLE_SCROLLING == state )
   {
     const float xSpeed = event.p2.mFloat;
-    const Vector2& actualSize = mVisualModel->GetActualSize();
+    const Vector2& actualSize = mVisualModel->GetLayoutSize();
     const Vector2 currentScrollPosition = mEventData->mScrollPosition;
 
     mEventData->mScrollPosition.x += xSpeed;
@@ -1904,6 +1904,25 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( isCurrentRightToLeft ? 0.f : glyphMetrics.advance );
     cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender );
   }
+
+  if( LayoutEngine::MULTI_LINE_BOX == mLayoutEngine.GetLayout() )
+  {
+    // If the text is editable and multi-line, the cursor position after a white space shouldn't exceed the boundaries of the text control.
+
+    // Note the white spaces laid-out at the end of the line might exceed the boundaries of the control.
+    // The reason is a wrapped line must not start with a white space so they are laid-out at the end of the line.
+
+    if( 0.f > cursorInfo.primaryPosition.x )
+    {
+      cursorInfo.primaryPosition.x = 0.f;
+    }
+
+    const float edgeWidth = mVisualModel->mControlSize.width - static_cast<float>( mEventData->mDecorator->GetCursorWidth() );
+    if( cursorInfo.primaryPosition.x > edgeWidth )
+    {
+      cursorInfo.primaryPosition.x = edgeWidth;
+    }
+  }
 }
 
 CharacterIndex Controller::Impl::CalculateNewCursorIndex( CharacterIndex index ) const
@@ -2074,17 +2093,18 @@ void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position )
   const float positionEnd = position.x + ( mEventData->mDecorator ? mEventData->mDecorator->GetCursorWidth() : 0.f );
 
   // Transform the position to decorator coords.
-  const float offset = mEventData->mScrollPosition.x + mAlignmentOffset.x;
+  const float alignment = IsShowingRealText() ? mAlignmentOffset.x : 0.f;
+  const float offset = mEventData->mScrollPosition.x + alignment;
   const float decoratorPositionBegin = position.x + offset;
   const float decoratorPositionEnd = positionEnd + offset;
 
   if( decoratorPositionBegin < 0.f )
   {
-    mEventData->mScrollPosition.x = -position.x - mAlignmentOffset.x;
+    mEventData->mScrollPosition.x = -position.x - alignment;
   }
   else if( decoratorPositionEnd > mVisualModel->mControlSize.width )
   {
-    mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - mAlignmentOffset.x;
+    mEventData->mScrollPosition.x = mVisualModel->mControlSize.width - positionEnd - alignment;
   }
 }
 
@@ -2096,7 +2116,7 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo )
   // Calculate the offset to match the cursor position before the character was deleted.
   mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x;
 
-  ClampHorizontalScroll( mVisualModel->GetActualSize() );
+  ClampHorizontalScroll( mVisualModel->GetLayoutSize() );
 }
 
 void Controller::Impl::RequestRelayout()
index 9ee83cc..f88ca8d 100644 (file)
@@ -514,7 +514,7 @@ struct Controller::Impl
    *
    * @pre mEventData must not be NULL. (there is a text-input or selection capabilities).
    *
-   * @param[in] position A position in decorator coords.
+   * @param[in] position A position in text coords.
    *
    * This method is called after inserting text, moving the cursor with the grab handle or the keypad,
    * or moving the selection handles.
@@ -526,7 +526,7 @@ struct Controller::Impl
    *
    * This method is called after deleting text.
    */
-  void ScrollTextToMatchCursor( const CursorInfo& cursorInfo);
+  void ScrollTextToMatchCursor( const CursorInfo& cursorInfo );
 
   ControlInterface& mControlInterface;     ///< Reference to the text controller.
   LogicalModelPtr mLogicalModel;           ///< Pointer to the logical model.
index 740e948..153a36c 100644 (file)
@@ -43,7 +43,6 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 const unsigned int POINTS_PER_INCH = 72;
 
 const std::string EMPTY_STRING("");
-const unsigned int ZERO = 0u;
 
 float ConvertToEven( float value )
 {
@@ -1041,7 +1040,7 @@ float Controller::GetHeightForWidth( float width )
   }
   else
   {
-    layoutSize = mImpl->mVisualModel->GetActualSize();
+    layoutSize = mImpl->mVisualModel->GetLayoutSize();
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height );
   }
 
@@ -1065,6 +1064,7 @@ bool Controller::Relayout( const Size& size )
     return glyphsRemoved;
   }
 
+  // Whether a new size has been set.
   const bool newSize = ( size != mImpl->mVisualModel->mControlSize );
 
   if( newSize )
@@ -1327,6 +1327,11 @@ bool Controller::DoRelayout( const Size& size,
 
     if( 0u == numberOfGlyphs )
     {
+      if( UPDATE_ACTUAL_SIZE & operations )
+      {
+        mImpl->mVisualModel->SetLayoutSize( Size::ZERO );
+      }
+
       // Nothing else to do if there is no glyphs.
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout no glyphs, view updated true\n" );
       return true;
@@ -1339,6 +1344,8 @@ bool Controller::DoRelayout( const Size& size,
     const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
     const Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
     const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin();
+    const Vector<GlyphIndex>& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph;
+    const Vector<Length>& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter;
 
     // Set the layout parameters.
     LayoutParameters layoutParameters( size,
@@ -1346,10 +1353,12 @@ bool Controller::DoRelayout( const Size& size,
                                        lineBreakInfo.Begin(),
                                        wordBreakInfo.Begin(),
                                        ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL,
-                                       numberOfGlyphs,
                                        glyphs.Begin(),
                                        glyphsToCharactersMap.Begin(),
-                                       charactersPerGlyph.Begin() );
+                                       charactersPerGlyph.Begin(),
+                                       charactersToGlyph.Begin(),
+                                       glyphsPerCharacter.Begin(),
+                                       numberOfGlyphs );
 
     // The laid-out lines.
     // It's not possible to know in how many lines the text is going to be laid-out,
@@ -1370,6 +1379,10 @@ bool Controller::DoRelayout( const Size& size,
     // Whether the last character is a new paragraph character.
     layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) );
 
+    // The initial glyph and the number of glyphs to layout.
+    layoutParameters.startGlyphIndex = 0u;
+    layoutParameters.numberOfGlyphs = numberOfGlyphs;
+
     // Update the visual model.
     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
                                                    glyphPositions,
@@ -1390,7 +1403,7 @@ bool Controller::DoRelayout( const Size& size,
           // Get the lines
           const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
           const CharacterIndex startIndex = 0u;
-          Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
+          const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
 
           // Reorder the lines.
           bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
@@ -1410,13 +1423,10 @@ bool Controller::DoRelayout( const Size& size,
                                                        startIndex,
                                                        requestedNumberOfCharacters );
 
-          // Get the character to glyph conversion table and set into the layout.
-          layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin();
-          // Get the glyphs per character table and set into the layout.
-          layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin();
-
           // Re-layout the text. Reorder those lines with right to left characters.
           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
+                                                         startIndex,
+                                                         requestedNumberOfCharacters,
                                                          glyphPositions );
 
           // Free the allocated memory used to store the conversion table in the bidirectional line info run.
@@ -1438,13 +1448,13 @@ bool Controller::DoRelayout( const Size& size,
       // Sets the actual size.
       if( UPDATE_ACTUAL_SIZE & operations )
       {
-        mImpl->mVisualModel->SetActualSize( layoutSize );
+        mImpl->mVisualModel->SetLayoutSize( layoutSize );
       }
     } // view updated
   }
   else
   {
-    layoutSize = mImpl->mVisualModel->GetActualSize();
+    layoutSize = mImpl->mVisualModel->GetLayoutSize();
   }
 
   if( ALIGN & operations )
@@ -1452,7 +1462,12 @@ bool Controller::DoRelayout( const Size& size,
     // The laid-out lines.
     Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
 
-    mImpl->mLayoutEngine.Align( layoutSize,
+    const CharacterIndex startIndex = 0u;
+    const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
+
+    mImpl->mLayoutEngine.Align( size,
+                                startIndex,
+                                requestedNumberOfCharacters,
                                 lines );
 
     viewUpdated = true;
@@ -1525,49 +1540,62 @@ LayoutEngine::VerticalAlignment Controller::GetVerticalAlignment() const
   return mImpl->mLayoutEngine.GetVerticalAlignment();
 }
 
-void Controller::CalculateTextAlignment( const Size& size )
+void Controller::CalculateTextAlignment( const Size& controlSize )
 {
-  // Get the direction of the first character.
-  const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u );
+  Size layoutSize = mImpl->mVisualModel->GetLayoutSize();
 
-  Size actualSize = mImpl->mVisualModel->GetActualSize();
-  if( fabsf( actualSize.height ) < Math::MACHINE_EPSILON_1000 )
+  if( fabsf( layoutSize.height ) < Math::MACHINE_EPSILON_1000 )
   {
     // Get the line height of the default font.
-    actualSize.height = mImpl->GetDefaultFontLineHeight();
+    layoutSize.height = mImpl->GetDefaultFontLineHeight();
   }
 
-  // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END;
-  LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment();
-  if( firstParagraphDirection &&
-      ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) )
+  if( LayoutEngine::SINGLE_LINE_BOX == mImpl->mLayoutEngine.GetLayout() )
   {
-    if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment )
-    {
-      horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END;
-    }
-    else
-    {
-      horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN;
-    }
-  }
+    // Get the direction of the first character.
+    const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u );
 
-  switch( horizontalAlignment )
-  {
-    case LayoutEngine::HORIZONTAL_ALIGN_BEGIN:
+    // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END;
+    LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment();
+    if( firstParagraphDirection )
     {
-      mImpl->mAlignmentOffset.x = 0.f;
-      break;
-    }
-    case LayoutEngine::HORIZONTAL_ALIGN_CENTER:
-    {
-      mImpl->mAlignmentOffset.x = floorf( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment.
-      break;
+      switch( horizontalAlignment )
+      {
+        case LayoutEngine::HORIZONTAL_ALIGN_BEGIN:
+        {
+          horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END;
+          break;
+        }
+        case LayoutEngine::HORIZONTAL_ALIGN_CENTER:
+        {
+          // Nothing to do.
+          break;
+        }
+        case LayoutEngine::HORIZONTAL_ALIGN_END:
+        {
+          horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN;
+          break;
+        }
+      }
     }
-    case LayoutEngine::HORIZONTAL_ALIGN_END:
+
+    switch( horizontalAlignment )
     {
-      mImpl->mAlignmentOffset.x = size.width - actualSize.width;
-      break;
+      case LayoutEngine::HORIZONTAL_ALIGN_BEGIN:
+      {
+        mImpl->mAlignmentOffset.x = 0.f;
+        break;
+      }
+      case LayoutEngine::HORIZONTAL_ALIGN_CENTER:
+      {
+        mImpl->mAlignmentOffset.x = floorf( 0.5f * ( controlSize.width - layoutSize.width ) ); // try to avoid pixel alignment.
+        break;
+      }
+      case LayoutEngine::HORIZONTAL_ALIGN_END:
+      {
+        mImpl->mAlignmentOffset.x = controlSize.width - layoutSize.width;
+        break;
+      }
     }
   }
 
@@ -1581,12 +1609,12 @@ void Controller::CalculateTextAlignment( const Size& size )
     }
     case LayoutEngine::VERTICAL_ALIGN_CENTER:
     {
-      mImpl->mAlignmentOffset.y = floorf( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment.
+      mImpl->mAlignmentOffset.y = floorf( 0.5f * ( controlSize.height - layoutSize.height ) ); // try to avoid pixel alignment.
       break;
     }
     case LayoutEngine::VERTICAL_ALIGN_BOTTOM:
     {
-      mImpl->mAlignmentOffset.y = size.height - actualSize.height;
+      mImpl->mAlignmentOffset.y = controlSize.height - layoutSize.height;
       break;
     }
   }
@@ -1815,7 +1843,7 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
     const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count();
 
     // Restrict new text to fit within Maximum characters setting
-    Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
+    Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
     maxLengthReached = ( characterCount > maxSizeOfNewText );
 
     // The cursor position.
index 67d0373..37d7b00 100644 (file)
@@ -47,12 +47,12 @@ void ClearCharacterRuns( CharacterIndex startIndex,
                          uint32_t& endRemoveIndex )
 {
   T* runsBuffer = runs.Begin();
+  T* run = runsBuffer;
 
   const Length length = runs.Count();
-  for( Length index = 0u; index < length; ++index )
+  Length index = 0u;
+  for( index = 0u; index < length; ++index )
   {
-    T* run = ( runsBuffer + index );
-
     if( ( run->characterRun.characterIndex <= endIndex ) &&
         ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
     {
@@ -62,37 +62,36 @@ void ClearCharacterRuns( CharacterIndex startIndex,
       startRemoveIndex = index;
       break;
     }
+
+    ++run;
   }
 
-  for( Length index = startRemoveIndex; index < length; ++index )
+  run = ( runsBuffer + startRemoveIndex );
+  for( index = startRemoveIndex; index < length; ++index )
   {
-    T* run = ( runsBuffer + index );
-
-    if( ( run->characterRun.characterIndex <= endIndex ) &&
-        ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
-    {
-      // Update the index to the last run to be removed.
-      endRemoveIndex = index + 1u;
-    }
-    else
+    if( ( run->characterRun.characterIndex > endIndex ) ||
+        ( startIndex >= run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
     {
       // Run found. Nothing else to do.
       break;
     }
+    ++run;
   }
+  endRemoveIndex = index;
 
   // The number of characters to remove.
   const Length numberOfCharactersRemoved = 1u + endIndex - startIndex;
 
   // Update the character index of the next runs.
+  run = runsBuffer;
   for( Length index = 0u; index < length; ++index )
   {
-    T* run = ( runsBuffer + index );
-
     if( run->characterRun.characterIndex > startIndex )
     {
       run->characterRun.characterIndex -= numberOfCharactersRemoved;
     }
+
+    ++run;
   }
 }
 
@@ -259,6 +258,94 @@ void UpdateCharacterRuns( CharacterIndex index,
   }
 }
 
+/**
+ * @brief Clears the runs starting from the given glyph index.
+ *
+ * @param[in] startIndex The starting glyph index used to remove runs.
+ * @param[in] endIndex The ending glyph index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ * @param[out] startRemoveIndex The index to the first run to be removed.
+ * @param[out] endRemoveIndex The index to the last run to be removed.
+ */
+template< typename T >
+void ClearGlyphRuns( GlyphIndex startIndex,
+                     GlyphIndex endIndex,
+                     Vector<T>& runs,
+                     uint32_t& startRemoveIndex,
+                     uint32_t& endRemoveIndex )
+{
+  T* runsBuffer = runs.Begin();
+  T* run = runsBuffer;
+
+  const Length length = runs.Count();
+  Length index = 0u;
+  for( index = 0u; index < length; ++index )
+  {
+    if( ( run->glyphRun.glyphIndex <= endIndex ) &&
+        ( startIndex < run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) )
+    {
+      // Run found.
+
+      // Set the index to the first run to be removed.
+      startRemoveIndex = index;
+      break;
+    }
+    ++run;
+  }
+
+  run = ( runsBuffer + startRemoveIndex );
+  for( index = startRemoveIndex; index < length; ++index )
+  {
+    if( ( run->glyphRun.glyphIndex > endIndex ) ||
+        ( startIndex >= run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) )
+    {
+      // Run found. Nothing else to do.
+    }
+
+    ++run;
+  }
+  endRemoveIndex = index;
+
+  // The number of glyphs to remove.
+  const Length numberOfGlyphsRemoved = 1u + endIndex - startIndex;
+
+  // Update the glyph index of the next runs.
+  run = runsBuffer;
+  for( Length index = 0u; index < length; ++index )
+  {
+
+    if( run->glyphRun.glyphIndex > startIndex )
+    {
+      run->glyphRun.glyphIndex -= numberOfGlyphsRemoved;
+    }
+  }
+}
+
+/**
+ * @brief Clears the runs starting from the given glyph index.
+ *
+ * @param[in] startIndex The starting glyph index used to remove runs.
+ * @param[in] endIndex The ending glyph index used to remove runs.
+ * @param[in,out] runs The text's runs.
+ */
+template< typename T >
+void ClearGlyphRuns( GlyphIndex startIndex,
+                     GlyphIndex endIndex,
+                     Vector<T>& runs )
+{
+  uint32_t startRemoveIndex = runs.Count();
+  uint32_t endRemoveIndex = startRemoveIndex;
+  ClearGlyphRuns( startIndex,
+                  endIndex,
+                  runs,
+                  startRemoveIndex,
+                  endRemoveIndex );
+
+  // Remove all remaining runs.
+  T* runBuffer = runs.Begin();
+  runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
+}
+
 } // namespace Text
 
 } // namespace Toolkit
index 409f9d7..c121f77 100644 (file)
@@ -65,6 +65,14 @@ public:
   virtual const Vector2& GetControlSize() const = 0;
 
   /**
+   * @brief Retrieves the text's layout size.
+   *
+   * @return The text's size. Note that this may be larger than the control size,
+   * in the case where text is scrolling/clipped.
+   */
+  virtual const Vector2& GetLayoutSize() const = 0;
+
+  /**
    * Retrieves the number of glyphs.
    *
    * @return The number of glyphs.
index 2921700..d57b2ec 100644 (file)
@@ -65,6 +65,16 @@ const Vector2& View::GetControlSize() const
   return Vector2::ZERO;
 }
 
+const Vector2& View::GetLayoutSize() const
+{
+  if ( mImpl->mVisualModel )
+  {
+    return mImpl->mVisualModel->GetLayoutSize();
+  }
+
+  return Vector2::ZERO;
+}
+
 Length View::GetNumberOfGlyphs() const
 {
   if( mImpl->mVisualModel )
index 899474d..0067f94 100644 (file)
@@ -61,6 +61,11 @@ public:
   virtual const Vector2& GetControlSize() const;
 
   /**
+   * @copydoc Dali::Toolkit::Text::ViewInterface::GetLayoutSize()
+   */
+  virtual const Vector2& GetLayoutSize() const;
+
+  /**
    * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfGlyphs()
    */
   virtual Length GetNumberOfGlyphs() const;
index 3e9c123..138ce54 100644 (file)
@@ -315,14 +315,14 @@ const Vector2& VisualModel::GetNaturalSize() const
   return mNaturalSize;
 }
 
-void VisualModel::SetActualSize( const Vector2& size )
+void VisualModel::SetLayoutSize( const Vector2& size )
 {
-  mActualSize = size;
+  mLayoutSize = size;
 }
 
-const Vector2& VisualModel::GetActualSize() const
+const Vector2& VisualModel::GetLayoutSize() const
 {
-  return mActualSize;
+  return mLayoutSize;
 }
 
 void VisualModel::SetTextColor( const Vector4& textColor )
@@ -414,7 +414,7 @@ VisualModel::VisualModel()
   mShadowOffset( Vector2::ZERO ),
   mUnderlineHeight( 0.0f ),
   mNaturalSize(),
-  mActualSize(),
+  mLayoutSize(),
   mCachedLineIndex( 0u ),
   mUnderlineEnabled( false ),
   mUnderlineColorSet( false )
index eb2e5a0..a0339a4 100644 (file)
@@ -174,18 +174,18 @@ public:
   const Vector2& GetNaturalSize() const;
 
   /**
-   * @brief Sets the text's actual size after it has been laid out.
+   * @brief Sets the text's layout size.
    *
    * @param[in] size The text's size.
    */
-  void SetActualSize( const Vector2& size );
+  void SetLayoutSize( const Vector2& size );
 
   /**
-   * @brief Retrieves the text's actual size after it has been laid out.
+   * @brief Retrieves the text's layout size.
    *
    * @return The text's size.
    */
-  const Vector2& GetActualSize() const;
+  const Vector2& GetLayoutSize() const;
 
   /**
    * @brief Set the text's color
@@ -318,7 +318,7 @@ public:
 private:
 
   Size                   mNaturalSize;        ///< Size of the text with no line wrapping.
-  Size                   mActualSize;         ///< Size of the laid-out text considering the layout properties set.
+  Size                   mLayoutSize;         ///< Size of the laid-out text considering the layout properties set.
 
   // Caches to increase performance in some consecutive operations.
   LineIndex mCachedLineIndex; ///< Used to increase performance in consecutive calls to GetLineOfGlyph() or GetLineOfCharacter() with consecutive glyphs or characters.
index 15d7fcc..524943d 100644 (file)
@@ -187,6 +187,7 @@ public:
                               bool blurUserImage = false);
 
   /**
+   * @DEPRECATED_1_1.28 Use Actor::Add(Actor) instead
    * @brief Adds a child Actor to this Actor.
    * @SINCE_1_0.0
    * @param [in] child The child.
@@ -203,6 +204,7 @@ public:
   void Add(Actor child);
 
   /**
+   * @DEPRECATED_1_1.28 Use Actor::Remove(Actor) instead
    * @brief Removes a child Actor from this Actor.
    *
    * If the actor was not a child of this actor, this is a no-op.
index f465285..95d3f93 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 27;
+const unsigned int TOOLKIT_MICRO_VERSION = 28;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index e25029c..02da954 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    The OpenGLES Canvas Core Library Toolkit
-Version:    1.1.27
+Version:    1.1.28
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-2-Clause and MIT