Moved Text Controller & Markup Processor to sub-folders 31/277731/3
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 12 Jul 2022 11:33:41 +0000 (12:33 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 13 Jul 2022 09:52:14 +0000 (10:52 +0100)
Change-Id: If5a17c1c568584840ec7f07ebe24cd72bc6a0356

127 files changed:
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.h
automated-tests/src/dali-toolkit-internal/utc-Dali-LineHelperFunctions.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Ellipsis.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Typesetter.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-ViewModel.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextEditor-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-TextLabel-internal.cpp
dali-toolkit/devel-api/text/text-utils-devel.cpp
dali-toolkit/internal/controls/text-controls/common-text-utils.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-editor-property-handler.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/controls/text-controls/text-field-property-handler.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.h
dali-toolkit/internal/file.list
dali-toolkit/internal/text/controller/text-controller-background-actor.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-background-actor.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-event-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-event-handler.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-event-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-impl.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-input-font-handler.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-input-properties.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-input-properties.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-relayouter.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-relayouter.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-text-updater.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller-text-updater.h [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller.cpp [new file with mode: 0644]
dali-toolkit/internal/text/controller/text-controller.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-anchor.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-anchor.h [deleted file]
dali-toolkit/internal/text/markup-processor-attribute-helper-functions.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h [deleted file]
dali-toolkit/internal/text/markup-processor-background.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-background.h [deleted file]
dali-toolkit/internal/text/markup-processor-character-spacing.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-character-spacing.h [deleted file]
dali-toolkit/internal/text/markup-processor-color.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-color.h [deleted file]
dali-toolkit/internal/text/markup-processor-embedded-item.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-embedded-item.h [deleted file]
dali-toolkit/internal/text/markup-processor-font.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-font.h [deleted file]
dali-toolkit/internal/text/markup-processor-helper-functions.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-helper-functions.h [deleted file]
dali-toolkit/internal/text/markup-processor-paragraph.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-paragraph.h [deleted file]
dali-toolkit/internal/text/markup-processor-span.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-span.h [deleted file]
dali-toolkit/internal/text/markup-processor-strikethrough.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-strikethrough.h [deleted file]
dali-toolkit/internal/text/markup-processor-underline.cpp [deleted file]
dali-toolkit/internal/text/markup-processor-underline.h [deleted file]
dali-toolkit/internal/text/markup-processor.cpp [deleted file]
dali-toolkit/internal/text/markup-processor.h [deleted file]
dali-toolkit/internal/text/markup-processor/markup-processor-anchor.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-anchor.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-background.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-background.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-color.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-color.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-font.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-span.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-span.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-underline.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor-underline.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor/markup-processor.h [new file with mode: 0644]
dali-toolkit/internal/text/property-string-parser.cpp
dali-toolkit/internal/text/text-controller-background-actor.cpp [deleted file]
dali-toolkit/internal/text/text-controller-background-actor.h [deleted file]
dali-toolkit/internal/text/text-controller-event-handler.cpp [deleted file]
dali-toolkit/internal/text/text-controller-event-handler.h [deleted file]
dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp [deleted file]
dali-toolkit/internal/text/text-controller-impl-data-clearer.h [deleted file]
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp [deleted file]
dali-toolkit/internal/text/text-controller-impl-event-handler.h [deleted file]
dali-toolkit/internal/text/text-controller-impl-model-updater.cpp [deleted file]
dali-toolkit/internal/text/text-controller-impl-model-updater.h [deleted file]
dali-toolkit/internal/text/text-controller-impl.cpp [deleted file]
dali-toolkit/internal/text/text-controller-impl.h [deleted file]
dali-toolkit/internal/text/text-controller-input-font-handler.cpp [deleted file]
dali-toolkit/internal/text/text-controller-input-font-handler.h [deleted file]
dali-toolkit/internal/text/text-controller-input-properties.cpp [deleted file]
dali-toolkit/internal/text/text-controller-input-properties.h [deleted file]
dali-toolkit/internal/text/text-controller-placeholder-handler.cpp [deleted file]
dali-toolkit/internal/text/text-controller-placeholder-handler.h [deleted file]
dali-toolkit/internal/text/text-controller-relayouter.cpp [deleted file]
dali-toolkit/internal/text/text-controller-relayouter.h [deleted file]
dali-toolkit/internal/text/text-controller-text-updater.cpp [deleted file]
dali-toolkit/internal/text/text-controller-text-updater.h [deleted file]
dali-toolkit/internal/text/text-controller.cpp [deleted file]
dali-toolkit/internal/text/text-controller.h [deleted file]
dali-toolkit/internal/text/text-effects-style.cpp
dali-toolkit/internal/text/text-effects-style.h
dali-toolkit/internal/text/text-font-style.cpp
dali-toolkit/internal/text/text-font-style.h
dali-toolkit/internal/text/text-selection-handle-controller.cpp
dali-toolkit/internal/text/text-selection-handle-controller.h
dali-toolkit/internal/visuals/text/text-visual.h

index 5b8469d08e02a0e60733fa212e44556ad9e342ac..5fc934913027ac70943121ad4f3484faec6dd9dd 100644 (file)
 #include <dali-toolkit/internal/text/hyphenator.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
 
 namespace Dali
 {
index 00bf3d5dd6fb25ba62fc91e71fe053fa3c4befcf..b064bfa3877055cd325bf340dc0426f40fc917fe 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/metrics.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-model.h>
 
 namespace Dali
index 2930c6d8e55b78daa40209aa1dd9f3af8dea7bdc..92113fc842362b024b916e7a5b88663ad38b3a6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -22,9 +22,9 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/internal/text/line-helper-functions.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 #include <toolkit-text-utils.h>
 
 using namespace Dali;
index b079ce32ae1c5f6cb6ffbca372390c1e2690c83f..53b45f2c168bfc3f10a018a3901fbf9ed5d247d4 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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 <toolkit-text-utils.h>
 #include <dali/devel-api/events/key-event-devel.h>
 #include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
 
 using namespace Dali;
 using namespace Toolkit;
index 75d8bb47d0e0c28b7be138d7a146fb2bd3f97cc1..a0a27c9052e94a357cd036037ca0881c51c4bb48 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -25,7 +25,7 @@
 #include <dali-toolkit/internal/text/font-description-run.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-view.h>
 
 
index 36117f7ed7528e49d17e406f275f5b09bee84240..3efd9aa1bf7f72cc595beb163b2c288b837c3a44 100644 (file)
@@ -24,8 +24,8 @@
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor.h>
 #include <dali-toolkit/internal/text/text-definitions.h>
 #include <dali-toolkit/internal/text/text-io.h>
 #include <toolkit-text-utils.h>
index 462a883a9979786cd958ef8b73c03c7ffbf3ecbf..c64458acf895908c43547697e0a1ef0a3a9810ec 100644 (file)
@@ -25,9 +25,9 @@
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/devel-api/text/bitmap-font.h>
 #include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 #include <dali/devel-api/text-abstraction/bitmap-font.h>
 #include <toolkit-environment-variable.h>
 #include <toolkit-text-utils.h>
index a3ad9010d72867d9e1effb5a99df00c28ce65e9b..daabc0b03f97b41c4dafde1fc4fc71613308c9e6 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -23,9 +23,9 @@
 #include <dali-toolkit/dali-toolkit.h>
 #include <toolkit-text-utils.h>
 #include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 
 using namespace Dali;
 using namespace Toolkit;
index f768255aa7ffa5cb9859f636219ac69b720ec74e..16dfc514349d9fd0c4892eb867d1ae9f11215ac2 100644 (file)
@@ -23,8 +23,8 @@
 
 #include <dali-toolkit/internal/controls/text-controls/text-editor-impl.h>
 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -1441,4 +1441,4 @@ int UtcDaliTextEditorMarkupSpanCharacterSpacing(void)
   }
 
   END_TEST;
-}
\ No newline at end of file
+}
index da3ffc39f61785ee3a7d8ff38cf874728a2a2c00..06eefbc35635a8d98147c774816cc738e8f853ee 100644 (file)
@@ -22,9 +22,9 @@
 #include <dali-toolkit/dali-toolkit.h>
 
 #include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -1350,4 +1350,4 @@ int UtcDaliTextFieldMarkupSpanCharacterSpacing(void)
   }
 
   END_TEST;
-}
\ No newline at end of file
+}
index d9a3c047650650f31437f6d507f19b02f3128e80..4f152390919ec1ba25dfe56e5747ac26ec9b5721 100644 (file)
 #include <dali-toolkit/dali-toolkit.h>
 
 #include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
 #include <dali-toolkit/internal/text/rendering/view-model.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -1337,4 +1337,4 @@ int UtcDaliTextLabelMarkupSpanCharacterSpacing(void)
   }
 
   END_TEST;
-}
\ No newline at end of file
+}
index d1d69001779c4585bff91d15e5c4ce9b767ec4ba..401b82f75f26e33f2881fd980ff3ebebe2b8e882 100644 (file)
@@ -34,7 +34,7 @@
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
 #include <dali-toolkit/internal/text/segmentation.h>
index a0d0ad48c6e0fc10e8ca46e753e388ed5b925a53..a21dc86fe28e7d9c1b1f55f6f7f36492fd87e0f4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_TEXT_CONTROLS_COMMON_TEXT_UTILS_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -29,7 +29,7 @@
 #include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
 
index c62988addfa416273f32851755ef62b83e76470d..aaa58f7e604e6c855d2a842d6ea3514ffce3ce24 100644 (file)
@@ -37,7 +37,7 @@
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
 #include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 #include <dali-toolkit/internal/text/text-vertical-scroller.h>
index 403f777cfb939df8e22c49a5a46d68ece8d37eeb..067023aa0a744c1c5c8846f5ff7c35d6de06c5c4 100644 (file)
@@ -20,7 +20,7 @@
 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
 
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
index 6c4faa607fbe15722a96247bedb178dcacf96edd..bed947de499e59dd00840a901643404c90ba1610 100644 (file)
@@ -34,7 +34,7 @@
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-editable-control-interface.h>
 #include <dali-toolkit/internal/text/text-selectable-control-interface.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
index f1247f9e465d728af8234a20d1ace53fb1531e56..45af9b7ad68466d00028e68ec3135449379c5cc6 100644 (file)
@@ -21,7 +21,7 @@
 #include <dali-toolkit/devel-api/text/rendering-backend.h>
 
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-effects-style.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 #include <dali-toolkit/internal/text/text-font-style.h>
index 49f9197ea94272affbf34fb433ac27ee44d2f3a4..f4dac1d684d778e8ba5fcf3acd9f6b2b22e78d3a 100644 (file)
@@ -29,7 +29,7 @@
 #include <dali-toolkit/internal/text/rendering/text-renderer.h>
 #include <dali-toolkit/internal/text/text-anchor-control-interface.h>
 #include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/text-scroller-interface.h>
 #include <dali-toolkit/internal/text/text-scroller.h>
 #include <dali-toolkit/internal/visuals/text/text-visual.h>
index 6edbd75829d57d4def06ab37ad9088137eca002f..2d71f4b26eedb788aa2f44e26d398a11890fdc7f 100644 (file)
@@ -150,19 +150,6 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/cursor-helper-functions.cpp
    ${toolkit_src_dir}/text/glyph-metrics-helper.cpp
    ${toolkit_src_dir}/text/logical-model-impl.cpp
-   ${toolkit_src_dir}/text/markup-processor.cpp
-   ${toolkit_src_dir}/text/markup-processor-color.cpp
-   ${toolkit_src_dir}/text/markup-processor-embedded-item.cpp
-   ${toolkit_src_dir}/text/markup-processor-anchor.cpp
-   ${toolkit_src_dir}/text/markup-processor-font.cpp
-   ${toolkit_src_dir}/text/markup-processor-background.cpp
-   ${toolkit_src_dir}/text/markup-processor-paragraph.cpp
-   ${toolkit_src_dir}/text/markup-processor-span.cpp
-   ${toolkit_src_dir}/text/markup-processor-strikethrough.cpp
-   ${toolkit_src_dir}/text/markup-processor-underline.cpp
-   ${toolkit_src_dir}/text/markup-processor-character-spacing.cpp
-   ${toolkit_src_dir}/text/markup-processor-helper-functions.cpp
-   ${toolkit_src_dir}/text/markup-processor-attribute-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support.cpp
    ${toolkit_src_dir}/text/hidden-text.cpp
    ${toolkit_src_dir}/text/input-filter.cpp
@@ -172,18 +159,6 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/shaper.cpp
    ${toolkit_src_dir}/text/hyphenator.cpp
    ${toolkit_src_dir}/text/text-enumerations-impl.cpp
-   ${toolkit_src_dir}/text/text-controller.cpp
-   ${toolkit_src_dir}/text/text-controller-background-actor.cpp
-   ${toolkit_src_dir}/text/text-controller-event-handler.cpp
-   ${toolkit_src_dir}/text/text-controller-impl.cpp
-   ${toolkit_src_dir}/text/text-controller-impl-data-clearer.cpp
-   ${toolkit_src_dir}/text/text-controller-impl-event-handler.cpp
-   ${toolkit_src_dir}/text/text-controller-impl-model-updater.cpp
-   ${toolkit_src_dir}/text/text-controller-input-font-handler.cpp
-   ${toolkit_src_dir}/text/text-controller-input-properties.cpp
-   ${toolkit_src_dir}/text/text-controller-placeholder-handler.cpp
-   ${toolkit_src_dir}/text/text-controller-relayouter.cpp
-   ${toolkit_src_dir}/text/text-controller-text-updater.cpp
    ${toolkit_src_dir}/text/text-effects-style.cpp
    ${toolkit_src_dir}/text/text-font-style.cpp
    ${toolkit_src_dir}/text/text-io.cpp
@@ -195,8 +170,33 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/text/text-view-interface.cpp
    ${toolkit_src_dir}/text/visual-model-impl.cpp
    ${toolkit_src_dir}/text/decorator/text-decorator.cpp
+   ${toolkit_src_dir}/text/controller/text-controller.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-background-actor.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-event-handler.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-impl.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-impl-data-clearer.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-impl-event-handler.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-impl-model-updater.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-input-font-handler.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-input-properties.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-placeholder-handler.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-relayouter.cpp
+   ${toolkit_src_dir}/text/controller/text-controller-text-updater.cpp
    ${toolkit_src_dir}/text/layouts/layout-engine-helper-functions.cpp
    ${toolkit_src_dir}/text/layouts/layout-engine.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-color.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-embedded-item.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-anchor.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-font.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-background.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-paragraph.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-span.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-strikethrough.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-underline.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-character-spacing.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-helper-functions.cpp
+   ${toolkit_src_dir}/text/markup-processor/markup-processor-attribute-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-helper-functions.cpp
    ${toolkit_src_dir}/text/multi-language-support-impl.cpp
    ${toolkit_src_dir}/text/rendering/text-backend.cpp
diff --git a/dali-toolkit/internal/text/controller/text-controller-background-actor.cpp b/dali-toolkit/internal/text/controller/text-controller-background-actor.cpp
new file mode 100644 (file)
index 0000000..666d794
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-background-actor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/rendering/renderer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
+#include <dali-toolkit/internal/text/text-view.h>
+
+namespace Dali::Toolkit::Text
+{
+namespace
+{
+struct BackgroundVertex
+{
+  Vector2 mPosition; ///< Vertex posiiton
+  Vector4 mColor;    ///< Vertex color
+};
+
+struct BackgroundMesh
+{
+  Vector<BackgroundVertex> mVertices; ///< container of vertices
+  Vector<unsigned short>   mIndices;  ///< container of indices
+};
+} // unnamed namespace
+
+Length CalculateBackgroundLineHeight(LineRun lineRun)
+{
+  Length height = lineRun.ascender + -(lineRun.descender);
+
+  if(lineRun.lineSpacing > 0)
+  {
+    height += lineRun.lineSpacing;
+  }
+
+  return height;
+}
+
+Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, const LogicalModelPtr& textLogicalModel, Shader& textShaderBackground)
+{
+  // NOTE: Currently we only support background color for left-to-right text.
+
+  Actor actor;
+
+  Length numberOfGlyphs = textView.GetNumberOfGlyphs();
+  if(numberOfGlyphs > 0u)
+  {
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize(numberOfGlyphs);
+
+    Vector<Vector2> positions;
+    positions.Resize(numberOfGlyphs);
+
+    // Get the line where the glyphs are laid-out.
+    const LineRun* lineRun         = textVisualModel->mLines.Begin();
+    float          alignmentOffset = lineRun->alignmentOffset;
+    numberOfGlyphs                 = textView.GetGlyphs(glyphs.Begin(),
+                                        positions.Begin(),
+                                        alignmentOffset,
+                                        0u,
+                                        numberOfGlyphs);
+
+    glyphs.Resize(numberOfGlyphs);
+    positions.Resize(numberOfGlyphs);
+
+    const GlyphInfo* const glyphsBuffer    = glyphs.Begin();
+    const Vector2* const   positionsBuffer = positions.Begin();
+
+    BackgroundMesh mesh;
+    mesh.mVertices.Reserve(4u * glyphs.Size());
+    mesh.mIndices.Reserve(6u * glyphs.Size());
+
+    const Vector2 textSize = textView.GetLayoutSize();
+
+    const float offsetX = alignmentOffset + textSize.width * 0.5f;
+    const float offsetY = textSize.height * 0.5f;
+
+    const Vector4* const    backgroundColorsBuffer       = textView.GetBackgroundColors();
+    const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices();
+    const Vector4&          defaultBackgroundColor       = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
+    const float             modelCharacterSpacing        = textVisualModel->GetCharacterSpacing();
+    Vector<CharacterIndex>& glyphToCharacterMap          = textVisualModel->mGlyphsToCharacters;
+    const CharacterIndex*   glyphToCharacterMapBuffer    = glyphToCharacterMap.Begin();
+    float                   calculatedAdvance            = 0.f;
+
+    // Get the character-spacing runs.
+    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns();
+
+    Vector4   quad;
+    uint32_t  numberOfQuads = 0u;
+    Length    yLineOffset   = 0;
+    Length    prevLineIndex = 0;
+    LineIndex lineIndex;
+
+    for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
+    {
+      const GlyphInfo& glyph = *(glyphsBuffer + i);
+
+      // Get the background color of the character.
+      // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
+      const bool       isMarkupBackground       = textView.IsMarkupBackgroundColorSet();
+      const ColorIndex backgroundColorIndex     = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u;
+      const bool       isDefaultBackgroundColor = (0u == backgroundColorIndex);
+      const Vector4&   backgroundColor          = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
+
+      lineIndex         = textVisualModel->GetLineOfGlyph(i);
+      Length lineHeight = CalculateBackgroundLineHeight(lineRun[lineIndex]);
+
+      if(lineIndex != prevLineIndex)
+      {
+        yLineOffset += CalculateBackgroundLineHeight(lineRun[prevLineIndex]);
+
+        if(lineRun[prevLineIndex].lineSpacing < 0)
+        {
+          yLineOffset += lineRun[prevLineIndex].lineSpacing;
+        }
+      }
+
+      // Only create quads for glyphs with a background color
+      if(backgroundColor != Color::TRANSPARENT)
+      {
+        const float characterSpacing = GetGlyphCharacterSpacing(i, characterSpacingGlyphRuns, modelCharacterSpacing);
+
+        const Vector2 position = *(positionsBuffer + i);
+        calculatedAdvance      = GetCalculatedAdvance(*(textLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + i))), characterSpacing, glyph.advance);
+
+        if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
+        {
+          quad.x = position.x;
+          quad.y = yLineOffset;
+          quad.z = quad.x + std::max(calculatedAdvance, glyph.xBearing + glyph.width);
+          quad.w = lineHeight;
+        }
+        else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
+        {
+          quad.x = position.x;
+          quad.y = yLineOffset;
+          quad.z = quad.x - glyph.xBearing + calculatedAdvance;
+          quad.w = quad.y + lineHeight;
+        }
+        else if(i == glyphSize - 1u) // The last glyph in the whole text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = yLineOffset;
+          quad.z = quad.x + std::max(calculatedAdvance, glyph.xBearing + glyph.width);
+          quad.w = quad.y + lineHeight;
+        }
+        else // The glyph in the middle of the text
+        {
+          quad.x = position.x - glyph.xBearing;
+          quad.y = yLineOffset;
+          quad.z = quad.x + calculatedAdvance;
+          quad.w = quad.y + lineHeight;
+        }
+
+        BackgroundVertex vertex;
+
+        // Top left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor      = backgroundColor;
+        mesh.mVertices.PushBack(vertex);
+
+        // Top right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.y - offsetY;
+        vertex.mColor      = backgroundColor;
+        mesh.mVertices.PushBack(vertex);
+
+        // Bottom left
+        vertex.mPosition.x = quad.x - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor      = backgroundColor;
+        mesh.mVertices.PushBack(vertex);
+
+        // Bottom right
+        vertex.mPosition.x = quad.z - offsetX;
+        vertex.mPosition.y = quad.w - offsetY;
+        vertex.mColor      = backgroundColor;
+        mesh.mVertices.PushBack(vertex);
+
+        // Six indices in counter clockwise winding
+        mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
+        mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
+        mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
+        mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
+        mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
+        mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
+
+        numberOfQuads++;
+      }
+
+      if(lineIndex != prevLineIndex)
+      {
+        prevLineIndex = lineIndex;
+      }
+    }
+
+    // Only create the background actor if there are glyphs with background color
+    if(mesh.mVertices.Count() > 0u)
+    {
+      Property::Map quadVertexFormat;
+      quadVertexFormat["aPosition"] = Property::VECTOR2;
+      quadVertexFormat["aColor"]    = Property::VECTOR4;
+
+      VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
+      quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
+
+      Geometry quadGeometry = Geometry::New();
+      quadGeometry.AddVertexBuffer(quadVertices);
+      quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
+
+      if(!textShaderBackground)
+      {
+        textShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
+      }
+
+      Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, textShaderBackground);
+      renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
+      renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
+
+      actor = Actor::New();
+      actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
+      actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+      actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+      actor.SetProperty(Actor::Property::SIZE, textSize);
+      actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
+      actor.AddRenderer(renderer);
+    }
+  }
+
+  return actor;
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller-background-actor.h b/dali-toolkit/internal/text/controller/text-controller-background-actor.h
new file mode 100644 (file)
index 0000000..41b549c
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/rendering/shader.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/visual-model-impl.h>
+
+namespace Dali::Toolkit::Text
+{
+class View;
+
+/**
+ * @brief Create an actor that renders the text background color
+ *
+ * @param[in] textView The text view.
+ * @param[in] textVisualModel The text visual model.
+ * @param[in] textLogicalModel The text logical model.
+ * @param[in] textShaderBackground The text shader for background.
+ *
+ * @return the created actor or an empty handle if no background color needs to be rendered.
+ */
+Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, const LogicalModelPtr& textLogicalModel, Shader& textShaderBackground);
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-event-handler.cpp
new file mode 100644 (file)
index 0000000..e351342
--- /dev/null
@@ -0,0 +1,1026 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+#include <dali/devel-api/adaptor-framework/key-devel.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+const std::string KEY_C_NAME      = "c";
+const std::string KEY_V_NAME      = "v";
+const std::string KEY_X_NAME      = "x";
+const std::string KEY_A_NAME      = "a";
+const std::string KEY_INSERT_NAME = "Insert";
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void Controller::EventHandler::KeyboardFocusGainEvent(Controller& controller)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyboardFocusGainEvent");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if((EventData::INACTIVE == controller.mImpl->mEventData->mState) ||
+       (EventData::INTERRUPTED == controller.mImpl->mEventData->mState))
+    {
+      controller.mImpl->ChangeState(EventData::EDITING);
+      controller.mImpl->mEventData->mUpdateCursorPosition      = true; //If editing started without tap event, cursor update must be triggered.
+      controller.mImpl->mEventData->mUpdateInputStyle          = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition = true;
+    }
+    controller.mImpl->NotifyInputMethodContextMultiLineStatus();
+    if(controller.mImpl->IsShowingPlaceholderText())
+    {
+      // Show alternative placeholder-text when editing
+      PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
+    }
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+void Controller::EventHandler::KeyboardFocusLostEvent(Controller& controller)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyboardFocusLostEvent");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(EventData::INTERRUPTED != controller.mImpl->mEventData->mState)
+    {
+      // Init selection position
+      if(controller.mImpl->mEventData->mState == EventData::SELECTING)
+      {
+        uint32_t oldStart, oldEnd;
+        oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+        oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
+        controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
+        controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+        if(controller.mImpl->mSelectableControlInterface != nullptr)
+        {
+          controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mPrimaryCursorPosition, controller.mImpl->mEventData->mPrimaryCursorPosition);
+        }
+      }
+
+      controller.mImpl->ChangeState(EventData::INACTIVE);
+
+      if(!controller.mImpl->IsShowingRealText())
+      {
+        // Revert to regular placeholder-text when not editing
+        PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
+      }
+    }
+  }
+  controller.mImpl->RequestRelayout();
+}
+
+bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyEvent");
+
+  bool textChanged    = false;
+  bool relayoutNeeded = false;
+  bool isEditable     = controller.IsEditable() && controller.IsUserInteractionEnabled();
+
+  if((NULL != controller.mImpl->mEventData) &&
+     (keyEvent.GetState() == KeyEvent::DOWN))
+  {
+    int                keyCode   = keyEvent.GetKeyCode();
+    const std::string& keyString = keyEvent.GetKeyString();
+    const std::string  keyName   = keyEvent.GetKeyName();
+    // Key will produce same logical-key value when ctrl
+    // is down, regardless of language layout
+    const std::string logicalKey = keyEvent.GetLogicalKey();
+
+    const bool isNullKey = (0 == keyCode) && (keyString.empty());
+
+    // Pre-process to separate modifying events from non-modifying input events.
+    if(isNullKey)
+    {
+      // In some platforms arrive key events with no key code.
+      // Do nothing.
+      return false;
+    }
+    else if(Dali::DALI_KEY_ESCAPE == keyCode || Dali::DALI_KEY_BACK == keyCode || Dali::DALI_KEY_SEARCH == keyCode)
+    {
+      // Do nothing
+      return false;
+    }
+    else if((Dali::DALI_KEY_CURSOR_LEFT == keyCode) ||
+            (Dali::DALI_KEY_CURSOR_RIGHT == keyCode) ||
+            (Dali::DALI_KEY_CURSOR_UP == keyCode) ||
+            (Dali::DALI_KEY_CURSOR_DOWN == keyCode))
+    {
+      // If don't have any text, do nothing.
+      if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters || !isEditable)
+      {
+        return false;
+      }
+
+      uint32_t cursorPosition     = controller.mImpl->mEventData->mPrimaryCursorPosition;
+      uint32_t numberOfCharacters = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+      uint32_t cursorLine         = controller.mImpl->mModel->mVisualModel->GetLineOfCharacter(cursorPosition);
+      uint32_t numberOfLines      = controller.mImpl->mModel->GetNumberOfLines();
+
+      // Logic to determine whether this text control will lose focus or not.
+      if((Dali::DALI_KEY_CURSOR_LEFT == keyCode && 0 == cursorPosition && !keyEvent.IsShiftModifier()) ||
+         (Dali::DALI_KEY_CURSOR_RIGHT == keyCode && numberOfCharacters == cursorPosition && !keyEvent.IsShiftModifier()) ||
+         (Dali::DALI_KEY_CURSOR_DOWN == keyCode && cursorLine == numberOfLines - 1) ||
+         (Dali::DALI_KEY_CURSOR_DOWN == keyCode && numberOfCharacters == cursorPosition && cursorLine - 1 == numberOfLines - 1) ||
+         (Dali::DALI_KEY_CURSOR_UP == keyCode && cursorLine == 0) ||
+         (Dali::DALI_KEY_CURSOR_UP == keyCode && numberOfCharacters == cursorPosition && cursorLine == 1))
+      {
+        // Release the active highlight.
+        if(controller.mImpl->mEventData->mState == EventData::SELECTING)
+        {
+          uint32_t oldStart, oldEnd;
+          oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+          oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
+          controller.mImpl->ChangeState(EventData::EDITING);
+
+          // Update selection position.
+          controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
+          controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+          controller.mImpl->mEventData->mUpdateCursorPosition   = true;
+
+          if(controller.mImpl->mSelectableControlInterface != nullptr)
+          {
+            controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+          }
+
+          controller.mImpl->RequestRelayout();
+        }
+        return false;
+      }
+
+      controller.mImpl->mEventData->mCheckScrollAmount = true;
+      Event event(Event::CURSOR_KEY_EVENT);
+      event.p1.mInt  = keyCode;
+      event.p2.mBool = keyEvent.IsShiftModifier();
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+
+      // Will request for relayout.
+      relayoutNeeded = true;
+    }
+    else if(Dali::DevelKey::DALI_KEY_CONTROL_LEFT == keyCode || Dali::DevelKey::DALI_KEY_CONTROL_RIGHT == keyCode)
+    {
+      // Left or Right Control key event is received before Ctrl-C/V/X key event is received
+      // If not handle it here, any selected text will be deleted
+
+      // Do nothing
+      return false;
+    }
+    else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier() && isEditable)
+    {
+      bool consumed = false;
+      if(keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
+      {
+        // Ctrl-C or Ctrl+Insert to copy the selected text
+        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::COPY);
+        consumed = true;
+      }
+      else if(keyName == KEY_V_NAME || logicalKey == KEY_V_NAME)
+      {
+        // Ctrl-V to paste the copied text
+        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::PASTE);
+        consumed = true;
+      }
+      else if(keyName == KEY_X_NAME || logicalKey == KEY_X_NAME)
+      {
+        // Ctrl-X to cut the selected text
+        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::CUT);
+        consumed = true;
+      }
+      else if(keyName == KEY_A_NAME || logicalKey == KEY_A_NAME)
+      {
+        // Ctrl-A to select All the text
+        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::SELECT_ALL);
+        consumed = true;
+      }
+      return consumed;
+    }
+    else if((Dali::DALI_KEY_BACKSPACE == keyCode) ||
+            (Dali::DevelKey::DALI_KEY_DELETE == keyCode))
+    {
+      textChanged = DeleteEvent(controller, keyCode);
+
+      // Will request for relayout.
+      relayoutNeeded = true;
+    }
+    else if(IsKey(keyEvent, Dali::DALI_KEY_POWER) ||
+            IsKey(keyEvent, Dali::DALI_KEY_MENU) ||
+            IsKey(keyEvent, Dali::DALI_KEY_HOME))
+    {
+      // Power key/Menu/Home key behaviour does not allow edit mode to resume.
+      controller.mImpl->ChangeState(EventData::INACTIVE);
+
+      // Will request for relayout.
+      relayoutNeeded = true;
+
+      // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
+    }
+    else if((Dali::DALI_KEY_SHIFT_LEFT == keyCode) || (Dali::DALI_KEY_SHIFT_RIGHT == keyCode))
+    {
+      // DALI_KEY_SHIFT_LEFT or DALI_KEY_SHIFT_RIGHT is the key code for Shift. It's sent (by the InputMethodContext?) when the predictive text is enabled
+      // and a character is typed after the type of a upper case latin character.
+
+      // Do nothing.
+      return false;
+    }
+    else if((Dali::DALI_KEY_VOLUME_UP == keyCode) || (Dali::DALI_KEY_VOLUME_DOWN == keyCode))
+    {
+      // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
+      // Do nothing.
+      return false;
+    }
+    else
+    {
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
+      if(!isEditable) return false;
+
+      std::string refinedKey = keyString;
+      if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
+      {
+        bool accepted = false;
+        bool rejected = false;
+        accepted      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::ACCEPTED, keyString);
+        rejected      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::REJECTED, keyString);
+
+        if(!accepted)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the accepted filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
+        }
+        if(rejected)
+        {
+          // The filtered key is set to empty.
+          refinedKey = "";
+          // Signal emits when the character to be inserted is filtered by the rejected filter.
+          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
+        }
+      }
+
+      if(!refinedKey.empty())
+      {
+        // InputMethodContext is no longer handling key-events
+        controller.mImpl->ClearPreEditFlag();
+
+        TextUpdater::InsertText(controller, refinedKey, COMMIT);
+
+        textChanged = true;
+
+        // Will request for relayout.
+        relayoutNeeded = true;
+      }
+    }
+
+    if((controller.mImpl->mEventData->mState != EventData::INTERRUPTED) &&
+       (controller.mImpl->mEventData->mState != EventData::INACTIVE) &&
+       (!isNullKey) &&
+       (Dali::DALI_KEY_SHIFT_LEFT != keyCode) &&
+       (Dali::DALI_KEY_SHIFT_RIGHT != keyCode) &&
+       (Dali::DALI_KEY_VOLUME_UP != keyCode) &&
+       (Dali::DALI_KEY_VOLUME_DOWN != keyCode))
+    {
+      // Should not change the state if the key is the shift send by the InputMethodContext.
+      // Otherwise, when the state is SELECTING the text controller can't send the right
+      // surrounding info to the InputMethodContext.
+      controller.mImpl->ChangeState(EventData::EDITING);
+
+      // Will request for relayout.
+      relayoutNeeded = true;
+    }
+
+    if(relayoutNeeded)
+    {
+      controller.mImpl->RequestRelayout();
+    }
+  }
+  else if((NULL != controller.mImpl->mEventData) && (keyEvent.GetState() == KeyEvent::UP))
+  {
+    // Handles specific keys that require event propagation.
+    if(Dali::DALI_KEY_BACK == keyEvent.GetKeyCode())
+    {
+      // Do nothing
+      return false;
+    }
+  }
+
+  if(textChanged &&
+     (NULL != controller.mImpl->mEditableControlInterface))
+  {
+    // Do this last since it provides callbacks into application code
+    controller.mImpl->mEditableControlInterface->TextChanged(false);
+  }
+
+  return true;
+}
+
+void Controller::EventHandler::AnchorEvent(Controller& controller, float x, float y)
+{
+  if(!controller.mImpl->mMarkupProcessorEnabled ||
+     !controller.mImpl->mModel->mLogicalModel->mAnchors.Count() ||
+     !controller.mImpl->IsShowingRealText())
+  {
+    return;
+  }
+
+  CharacterIndex cursorPosition = 0u;
+
+  // Convert from control's coords to text's coords.
+  const float xPosition = x - controller.mImpl->mModel->mScrollPosition.x;
+  const float yPosition = y - controller.mImpl->mModel->mScrollPosition.y;
+
+  // Whether to touch point hits on a glyph.
+  bool matchedCharacter = false;
+  cursorPosition        = Text::GetClosestCursorIndex(controller.mImpl->mModel->mVisualModel,
+                                               controller.mImpl->mModel->mLogicalModel,
+                                               controller.mImpl->mMetrics,
+                                               xPosition,
+                                               yPosition,
+                                               CharacterHitTest::TAP,
+                                               matchedCharacter);
+
+  for(const auto& anchor : controller.mImpl->mModel->mLogicalModel->mAnchors)
+  {
+    // Anchor clicked if the calculated cursor position is within the range of anchor.
+    if(cursorPosition >= anchor.startIndex && cursorPosition < anchor.endIndex)
+    {
+      if(controller.mImpl->mAnchorControlInterface && anchor.href)
+      {
+        std::string href(anchor.href);
+        controller.mImpl->mAnchorControlInterface->AnchorClicked(href);
+        break;
+      }
+    }
+  }
+}
+
+void Controller::EventHandler::TapEvent(Controller& controller, unsigned int tapCount, float x, float y)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected TapEvent");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "TapEvent state:%d \n", controller.mImpl->mEventData->mState);
+    EventData::State state(controller.mImpl->mEventData->mState);
+    bool             relayoutNeeded(false); // to avoid unnecessary relayouts when tapping an empty text-field
+
+    if(controller.mImpl->IsClipboardVisible())
+    {
+      if(EventData::INACTIVE == state || EventData::EDITING == state)
+      {
+        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE);
+      }
+      relayoutNeeded = true;
+    }
+    else if(1u == tapCount)
+    {
+      if(EventData::EDITING_WITH_POPUP == state || EventData::EDITING_WITH_PASTE_POPUP == state)
+      {
+        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE); // If Popup shown hide it here so can be shown again if required.
+      }
+
+      if(controller.mImpl->IsShowingRealText() && (EventData::INACTIVE != state))
+      {
+        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE);
+        relayoutNeeded = true;
+      }
+      else
+      {
+        if(controller.mImpl->IsShowingPlaceholderText() && !controller.mImpl->IsFocusedPlaceholderAvailable())
+        {
+          // Hide placeholder text
+          TextUpdater::ResetText(controller);
+        }
+
+        if(EventData::INACTIVE == state)
+        {
+          controller.mImpl->ChangeState(EventData::EDITING);
+        }
+        else if(!controller.mImpl->IsClipboardEmpty())
+        {
+          controller.mImpl->ChangeState(EventData::EDITING_WITH_POPUP);
+        }
+        relayoutNeeded = true;
+      }
+    }
+    else if(2u == tapCount)
+    {
+      if(controller.mImpl->mEventData->mSelectionEnabled &&
+         controller.mImpl->IsShowingRealText())
+      {
+        relayoutNeeded                                       = true;
+        controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
+        controller.mImpl->mEventData->mIsRightHandleSelected = true;
+      }
+    }
+
+    // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
+    if(relayoutNeeded)
+    {
+      Event event(Event::TAP_EVENT);
+      event.p1.mUint  = tapCount;
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+
+      controller.mImpl->RequestRelayout();
+    }
+  }
+
+  // Reset keyboard as tap event has occurred.
+  controller.mImpl->ResetInputMethodContext();
+}
+
+void Controller::EventHandler::PanEvent(Controller& controller, GestureState state, const Vector2& displacement)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected PanEvent");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    Event event(Event::PAN_EVENT);
+    event.p1.mInt   = static_cast<int>(state);
+    event.p2.mFloat = displacement.x;
+    event.p3.mFloat = displacement.y;
+    controller.mImpl->mEventData->mEventQueue.push_back(event);
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+void Controller::EventHandler::LongPressEvent(Controller& controller, GestureState state, float x, float y)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected LongPressEvent");
+
+  if((state == GestureState::STARTED) &&
+     (NULL != controller.mImpl->mEventData))
+  {
+    // The 1st long-press on inactive text-field is treated as tap
+    if(EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      controller.mImpl->ChangeState(EventData::EDITING);
+
+      Event event(Event::TAP_EVENT);
+      event.p1.mUint  = 1;
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+
+      controller.mImpl->RequestRelayout();
+    }
+    else if(!controller.mImpl->IsShowingRealText())
+    {
+      Event event(Event::LONG_PRESS_EVENT);
+      event.p1.mInt   = static_cast<int>(state);
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+      controller.mImpl->RequestRelayout();
+    }
+    else if(!controller.mImpl->IsClipboardVisible())
+    {
+      // Reset the InputMethodContext to commit the pre-edit before selecting the text.
+      controller.mImpl->ResetInputMethodContext();
+
+      Event event(Event::LONG_PRESS_EVENT);
+      event.p1.mInt   = static_cast<int>(state);
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+      controller.mImpl->RequestRelayout();
+
+      controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
+      controller.mImpl->mEventData->mIsRightHandleSelected = true;
+    }
+  }
+}
+
+void Controller::EventHandler::SelectEvent(Controller& controller, float x, float y, SelectionType selectType)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(selectType == SelectionType::ALL)
+    {
+      Event event(Event::SELECT_ALL);
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+    }
+    else if(selectType == SelectionType::NONE)
+    {
+      Event event(Event::SELECT_NONE);
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+    }
+    else
+    {
+      Event event(Event::SELECT);
+      event.p2.mFloat = x;
+      event.p3.mFloat = y;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+    }
+
+    controller.mImpl->mEventData->mCheckScrollAmount     = true;
+    controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
+    controller.mImpl->mEventData->mIsRightHandleSelected = true;
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+void Controller::EventHandler::SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(selectType == SelectionType::RANGE)
+    {
+      Event event(Event::SELECT_RANGE);
+      event.p2.mUint = start;
+      event.p3.mUint = end;
+      controller.mImpl->mEventData->mEventQueue.push_back(event);
+    }
+
+    controller.mImpl->mEventData->mCheckScrollAmount     = true;
+    controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
+    controller.mImpl->mEventData->mIsRightHandleSelected = true;
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+void Controller::EventHandler::ProcessModifyEvents(Controller& controller)
+{
+  Vector<ModifyEvent>& events = controller.mImpl->mModifyEvents;
+
+  if(0u == events.Count())
+  {
+    // Nothing to do.
+    return;
+  }
+
+  for(Vector<ModifyEvent>::ConstIterator it    = events.Begin(),
+                                         endIt = events.End();
+      it != endIt;
+      ++it)
+  {
+    const ModifyEvent& event = *it;
+
+    if(ModifyEvent::TEXT_REPLACED == event.type)
+    {
+      // A (single) replace event should come first, otherwise we wasted time processing NOOP events
+      DALI_ASSERT_DEBUG(it == events.Begin() && "Unexpected TEXT_REPLACED event");
+
+      TextReplacedEvent(controller);
+    }
+    else if(ModifyEvent::TEXT_INSERTED == event.type)
+    {
+      TextInsertedEvent(controller);
+    }
+    else if(ModifyEvent::TEXT_DELETED == event.type)
+    {
+      // Placeholder-text cannot be deleted
+      if(!controller.mImpl->IsShowingPlaceholderText())
+      {
+        TextDeletedEvent(controller);
+      }
+    }
+  }
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    uint32_t oldStart, oldEnd;
+    oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
+    oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
+
+    // When the text is being modified, delay cursor blinking
+    controller.mImpl->mEventData->mDecorator->DelayCursorBlink();
+
+    // Update selection position after modifying the text
+    controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
+    controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
+
+    if(controller.mImpl->mSelectableControlInterface != nullptr && controller.mImpl->mEventData->mState == EventData::SELECTING)
+    {
+      controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
+    }
+  }
+
+  // DISCARD temporary text
+  events.Clear();
+}
+
+void Controller::EventHandler::TextReplacedEvent(Controller& controller)
+{
+  // The natural size needs to be re-calculated.
+  controller.mImpl->mRecalculateNaturalSize = true;
+
+  // The text direction needs to be updated.
+  controller.mImpl->mUpdateTextDirection = true;
+
+  // Apply modifications to the model
+  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
+}
+
+void Controller::EventHandler::TextInsertedEvent(Controller& controller)
+{
+  DALI_ASSERT_DEBUG(NULL != controller.mImpl->mEventData && "Unexpected TextInsertedEvent");
+
+  if(NULL == controller.mImpl->mEventData)
+  {
+    return;
+  }
+
+  controller.mImpl->mEventData->mCheckScrollAmount = true;
+
+  // The natural size needs to be re-calculated.
+  controller.mImpl->mRecalculateNaturalSize = true;
+
+  // The text direction needs to be updated.
+  controller.mImpl->mUpdateTextDirection = true;
+
+  // Apply modifications to the model; TODO - Optimize this
+  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
+}
+
+void Controller::EventHandler::TextDeletedEvent(Controller& controller)
+{
+  DALI_ASSERT_DEBUG(NULL != controller.mImpl->mEventData && "Unexpected TextDeletedEvent");
+
+  if(NULL == controller.mImpl->mEventData)
+  {
+    return;
+  }
+
+  if(!controller.IsEditable()) return;
+
+  controller.mImpl->mEventData->mCheckScrollAmount = true;
+
+  // The natural size needs to be re-calculated.
+  controller.mImpl->mRecalculateNaturalSize = true;
+
+  // The text direction needs to be updated.
+  controller.mImpl->mUpdateTextDirection = true;
+
+  // Apply modifications to the model; TODO - Optimize this
+  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
+}
+
+bool Controller::EventHandler::DeleteEvent(Controller& controller, int keyCode)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", &controller, keyCode);
+
+  bool removed = false;
+
+  if(NULL == controller.mImpl->mEventData)
+  {
+    return removed;
+  }
+
+  if(!controller.IsEditable()) return false;
+
+  // InputMethodContext is no longer handling key-events
+  controller.mImpl->ClearPreEditFlag();
+
+  if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+  {
+    removed = TextUpdater::RemoveSelectedText(controller);
+  }
+  else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE))
+  {
+    // Remove the character before the current cursor position
+    removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE);
+  }
+  else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) &&
+          (keyCode == Dali::DevelKey::DALI_KEY_DELETE))
+  {
+    // Remove the character after the current cursor position
+    removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE);
+  }
+
+  if(removed)
+  {
+    if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
+       !controller.mImpl->IsPlaceholderAvailable())
+    {
+      controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
+    }
+    else
+    {
+      PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
+    }
+    controller.mImpl->mEventData->mUpdateCursorPosition = true;
+    controller.mImpl->mEventData->mScrollAfterDelete    = true;
+  }
+
+  return removed;
+}
+
+InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextEvent(Controller& controller, InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
+{
+  // Whether the text needs to be relaid-out.
+  bool requestRelayout = false;
+
+  // Whether to retrieve the text and cursor position to be sent to the InputMethodContext.
+  bool retrieveText   = false;
+  bool retrieveCursor = false;
+
+  switch(inputMethodContextEvent.eventName)
+  {
+    case InputMethodContext::COMMIT:
+    {
+      TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::COMMIT);
+      requestRelayout = true;
+      retrieveCursor  = true;
+      break;
+    }
+    case InputMethodContext::PRE_EDIT:
+    {
+      TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT);
+      requestRelayout = true;
+      retrieveCursor  = true;
+      break;
+    }
+    case InputMethodContext::DELETE_SURROUNDING:
+    {
+      const bool textDeleted = TextUpdater::RemoveText(controller,
+                                                       inputMethodContextEvent.cursorOffset,
+                                                       inputMethodContextEvent.numberOfChars,
+                                                       DONT_UPDATE_INPUT_STYLE);
+
+      if(textDeleted)
+      {
+        if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
+           !controller.mImpl->IsPlaceholderAvailable())
+        {
+          controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
+        }
+        else
+        {
+          PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
+        }
+        controller.mImpl->mEventData->mUpdateCursorPosition = true;
+        controller.mImpl->mEventData->mScrollAfterDelete    = true;
+
+        requestRelayout = true;
+      }
+      break;
+    }
+    case InputMethodContext::GET_SURROUNDING:
+    {
+      retrieveText   = true;
+      retrieveCursor = true;
+      break;
+    }
+    case InputMethodContext::PRIVATE_COMMAND:
+    {
+      // PRIVATECOMMAND event is just for getting the private command message
+      retrieveText   = true;
+      retrieveCursor = true;
+      break;
+    }
+    case InputMethodContext::SELECTION_SET:
+    {
+      uint32_t start = static_cast<uint32_t>(inputMethodContextEvent.startIndex);
+      uint32_t end = static_cast<uint32_t>(inputMethodContextEvent.endIndex);
+      if(start == end)
+      {
+        controller.SetPrimaryCursorPosition(start, true);
+      }
+      else
+      {
+        controller.SelectText(start, end);
+      }
+
+      break;
+    }
+    case InputMethodContext::VOID:
+    {
+      // do nothing
+      break;
+    }
+  } // end switch
+
+  if(requestRelayout)
+  {
+    controller.mImpl->mOperationsPending = ALL_OPERATIONS;
+    controller.mImpl->RequestRelayout();
+  }
+
+  std::string    text;
+  CharacterIndex cursorPosition      = 0u;
+  Length         numberOfWhiteSpaces = 0u;
+
+  if(retrieveCursor)
+  {
+    numberOfWhiteSpaces = controller.mImpl->GetNumberOfWhiteSpaces(0u);
+
+    cursorPosition = controller.mImpl->GetLogicalCursorPosition();
+
+    if(cursorPosition < numberOfWhiteSpaces)
+    {
+      cursorPosition = 0u;
+    }
+    else
+    {
+      cursorPosition -= numberOfWhiteSpaces;
+    }
+  }
+
+  if(retrieveText)
+  {
+    if(!controller.mImpl->IsShowingPlaceholderText())
+    {
+      // Retrieves the normal text string.
+      controller.mImpl->GetText(numberOfWhiteSpaces, text);
+    }
+    else
+    {
+      // When the current text is Placeholder Text, the surrounding text should be empty string.
+      // It means DALi should send empty string ("") to IME.
+      text = "";
+    }
+  }
+
+  InputMethodContext::CallbackData callbackData((retrieveText || retrieveCursor), cursorPosition, text, false);
+
+  if(requestRelayout &&
+     (NULL != controller.mImpl->mEditableControlInterface))
+  {
+    // Do this last since it provides callbacks into application code
+    controller.mImpl->mEditableControlInterface->TextChanged(false);
+  }
+
+  return callbackData;
+}
+
+void Controller::EventHandler::PasteClipboardItemEvent(Controller& controller)
+{
+  // Retrieve the clipboard contents first
+  ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
+  std::string            stringToPaste(notifier.GetContent());
+
+  // Commit the current pre-edit text; the contents of the clipboard should be appended
+  controller.mImpl->ResetInputMethodContext();
+
+  // Temporary disable hiding clipboard
+  controller.mImpl->SetClipboardHideEnable(false);
+
+  // Paste
+  TextUpdater::PasteText(controller, stringToPaste);
+
+  controller.mImpl->SetClipboardHideEnable(true);
+}
+
+void Controller::EventHandler::DecorationEvent(Controller& controller, HandleType handleType, HandleState state, float x, float y)
+{
+  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected DecorationEvent");
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    switch(handleType)
+    {
+      case GRAB_HANDLE:
+      {
+        Event event(Event::GRAB_HANDLE_EVENT);
+        event.p1.mUint  = state;
+        event.p2.mFloat = x;
+        event.p3.mFloat = y;
+
+        controller.mImpl->mEventData->mEventQueue.push_back(event);
+        break;
+      }
+      case LEFT_SELECTION_HANDLE:
+      {
+        Event event(Event::LEFT_SELECTION_HANDLE_EVENT);
+        event.p1.mUint  = state;
+        event.p2.mFloat = x;
+        event.p3.mFloat = y;
+
+        controller.mImpl->mEventData->mEventQueue.push_back(event);
+        break;
+      }
+      case RIGHT_SELECTION_HANDLE:
+      {
+        Event event(Event::RIGHT_SELECTION_HANDLE_EVENT);
+        event.p1.mUint  = state;
+        event.p2.mFloat = x;
+        event.p3.mFloat = y;
+
+        controller.mImpl->mEventData->mEventQueue.push_back(event);
+        break;
+      }
+      case LEFT_SELECTION_HANDLE_MARKER:
+      case RIGHT_SELECTION_HANDLE_MARKER:
+      {
+        // Markers do not move the handles.
+        break;
+      }
+      case HANDLE_TYPE_COUNT:
+      {
+        DALI_ASSERT_DEBUG(!"Controller::HandleEvent. Unexpected handle type");
+      }
+    }
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+void Controller::EventHandler::TextPopupButtonTouched(Controller& controller, Dali::Toolkit::TextSelectionPopup::Buttons button)
+{
+  if(NULL == controller.mImpl->mEventData)
+  {
+    return;
+  }
+
+  switch(button)
+  {
+    case Toolkit::TextSelectionPopup::CUT:
+    {
+      controller.CutText();
+      break;
+    }
+    case Toolkit::TextSelectionPopup::COPY:
+    {
+      controller.CopyText();
+      break;
+    }
+    case Toolkit::TextSelectionPopup::PASTE:
+    {
+      controller.PasteText();
+      break;
+    }
+    case Toolkit::TextSelectionPopup::SELECT:
+    {
+      const Vector2& currentCursorPosition = controller.mImpl->mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
+
+      if(controller.mImpl->mEventData->mSelectionEnabled)
+      {
+        // Creates a SELECT event.
+        SelectEvent(controller, currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE);
+      }
+      break;
+    }
+    case Toolkit::TextSelectionPopup::SELECT_ALL:
+    {
+      // Creates a SELECT_ALL event
+      SelectEvent(controller, 0.f, 0.f, SelectionType::ALL);
+      break;
+    }
+    case Toolkit::TextSelectionPopup::CLIPBOARD:
+    {
+      controller.mImpl->ShowClipboard();
+      break;
+    }
+    case Toolkit::TextSelectionPopup::NONE:
+    {
+      // Nothing to do.
+      break;
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-event-handler.h b/dali-toolkit/internal/text/controller/text-controller-event-handler.h
new file mode 100644 (file)
index 0000000..3be57c2
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/input-method-context.h>
+#include <dali/public-api/events/gesture-enumerations.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/decorator/text-decorator.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Controller::EventHandler
+{
+  /// @copydoc Text::Controller::KeyboardFocusGainEvent
+  /// @param[in] controller A reference to the controller class
+  static void KeyboardFocusGainEvent(Controller& controller);
+
+  /// @copydoc Text::Controller::KeyboardFocusLostEvent
+  /// @param[in] controller A reference to the controller class
+  static void KeyboardFocusLostEvent(Controller& controller);
+
+  /// @copydoc Text::Controller::KeyEvent
+  /// @param[in] controller A reference to the controller class
+  static bool KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent);
+
+  /// @copydoc Text::Controller::AnchorEvent
+  /// @param[in] controller A reference to the controller class
+  static void AnchorEvent(Controller& controller, float x, float y);
+
+  /// @copydoc Text::Controller::TapEvent
+  /// @param[in] controller A reference to the controller class
+  static void TapEvent(Controller& controller, unsigned int tapCount, float x, float y);
+
+  /// @copydoc Text::Controller::PanEvent
+  /// @param[in] controller A reference to the controller class
+  static void PanEvent(Controller& controller, GestureState state, const Vector2& displacement);
+
+  /// @copydoc Text::Controller::LongPressEvent
+  /// @param[in] controller A reference to the controller class
+  static void LongPressEvent(Controller& controller, GestureState state, float x, float y);
+
+  /// @copydoc Text::Controller::SelectEvent
+  /// @param[in] controller A reference to the controller class
+  static void SelectEvent(Controller& controller, float x, float y, SelectionType selectType);
+
+  /**
+   * @brief Creates a selection event with a selection index.
+   *
+   * It could be called from the SelectText().
+   * The start and end parameters are passed through the event.
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] start The start selection position.
+   * @param[in] end The end selection position.
+   * @param[in] selection type like the range.
+   */
+  static void SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType);
+
+  /**
+   * @brief Process queued events which modify the model.
+   * @param[in] controller A reference to the controller class
+   */
+  static void ProcessModifyEvents(Controller& controller);
+
+  /**
+   * @brief Used to process an event queued from SetText()
+   * @param[in] controller A reference to the controller class
+   */
+  static void TextReplacedEvent(Controller& controller);
+
+  /**
+   * @brief Used to process an event queued from key events etc.
+   * @param[in] controller A reference to the controller class
+   */
+  static void TextInsertedEvent(Controller& controller);
+
+  /**
+   * @brief Used to process an event queued from backspace key etc.
+   * @param[in] controller A reference to the controller class
+   */
+  static void TextDeletedEvent(Controller& controller);
+
+  /**
+   * @brief Helper to KeyEvent() to handle the backspace or delete key case.
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] keyCode The keycode for the key pressed
+   * @return True if a character was deleted.
+   */
+  static bool DeleteEvent(Controller& controller, int keyCode);
+
+  static InputMethodContext::CallbackData OnInputMethodContextEvent(Controller&                          controller,
+                                                                    InputMethodContext&                  inputMethodContext,
+                                                                    const InputMethodContext::EventData& inputMethodContextEvent);
+
+  static void PasteClipboardItemEvent(Controller& controller);
+  static void DecorationEvent(Controller& controller, HandleType handleType, HandleState state, float x, float y);
+  static void TextPopupButtonTouched(Controller& controller, Dali::Toolkit::TextSelectionPopup::Buttons button);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.cpp b/dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.cpp
new file mode 100644 (file)
index 0000000..3822fb3
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+
+namespace Dali::Toolkit::Text
+{
+
+void ControllerImplDataClearer::ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations)
+{
+  ModelPtr& model = impl.mModel;
+
+  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
+  {
+    model->mLogicalModel->mLineBreakInfo.Clear();
+    model->mLogicalModel->mParagraphInfo.Clear();
+  }
+
+  if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
+  {
+    model->mLogicalModel->mScriptRuns.Clear();
+  }
+
+  if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
+  {
+    model->mLogicalModel->mFontRuns.Clear();
+  }
+
+  if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
+  {
+    if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
+    {
+      model->mLogicalModel->mBidirectionalParagraphInfo.Clear();
+      model->mLogicalModel->mCharacterDirections.Clear();
+    }
+
+    if(Controller::NO_OPERATION != (Controller::REORDER & operations))
+    {
+      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+      for(Vector<BidirectionalLineInfoRun>::Iterator it    = model->mLogicalModel->mBidirectionalLineInfo.Begin(),
+                                                     endIt = model->mLogicalModel->mBidirectionalLineInfo.End();
+          it != endIt;
+          ++it)
+      {
+        BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+        free(bidiLineInfo.visualToLogicalMap);
+        bidiLineInfo.visualToLogicalMap = NULL;
+      }
+      model->mLogicalModel->mBidirectionalLineInfo.Clear();
+    }
+  }
+
+  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
+  {
+    model->mVisualModel->mGlyphs.Clear();
+    model->mVisualModel->mGlyphsToCharacters.Clear();
+    model->mVisualModel->mCharactersToGlyph.Clear();
+    model->mVisualModel->mCharactersPerGlyph.Clear();
+    model->mVisualModel->mGlyphsPerCharacter.Clear();
+    model->mVisualModel->mGlyphPositions.Clear();
+  }
+
+  if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
+  {
+    model->mVisualModel->mLines.Clear();
+  }
+
+  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
+  {
+    model->mVisualModel->mColorIndices.Clear();
+    model->mVisualModel->mBackgroundColorIndices.Clear();
+  }
+}
+
+void ControllerImplDataClearer::ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+  const CharacterIndex endIndexPlusOne = endIndex + 1u;
+  ModelPtr& model = impl.mModel;
+
+  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
+  {
+    // Clear the line break info.
+    LineBreakInfo* lineBreakInfoBuffer = model->mLogicalModel->mLineBreakInfo.Begin();
+
+    model->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
+                                                     lineBreakInfoBuffer + endIndexPlusOne);
+
+    // Clear the paragraphs.
+    ClearCharacterRuns(startIndex,
+                       endIndex,
+                       model->mLogicalModel->mParagraphInfo);
+  }
+
+  if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
+  {
+    // Clear the scripts.
+    ClearCharacterRuns(startIndex,
+                       endIndex,
+                       model->mLogicalModel->mScriptRuns);
+  }
+
+  if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
+  {
+    // Clear the fonts.
+    ClearCharacterRuns(startIndex,
+                       endIndex,
+                       model->mLogicalModel->mFontRuns);
+  }
+
+  if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
+  {
+    if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
+    {
+      // Clear the bidirectional paragraph info.
+      ClearCharacterRuns(startIndex,
+                         endIndex,
+                         model->mLogicalModel->mBidirectionalParagraphInfo);
+
+      // Clear the character's directions.
+      CharacterDirection* characterDirectionsBuffer = model->mLogicalModel->mCharacterDirections.Begin();
+
+      model->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
+                                                       characterDirectionsBuffer + endIndexPlusOne);
+    }
+
+    if(Controller::NO_OPERATION != (Controller::REORDER & operations))
+    {
+      uint32_t startRemoveIndex = model->mLogicalModel->mBidirectionalLineInfo.Count();
+      uint32_t endRemoveIndex   = startRemoveIndex;
+      ClearCharacterRuns(startIndex,
+                         endIndex,
+                         model->mLogicalModel->mBidirectionalLineInfo,
+                         startRemoveIndex,
+                         endRemoveIndex);
+
+      BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = model->mLogicalModel->mBidirectionalLineInfo.Begin();
+
+      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+      for(Vector<BidirectionalLineInfoRun>::Iterator it    = bidirectionalLineInfoBuffer + startRemoveIndex,
+                                                     endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
+          it != endIt;
+          ++it)
+      {
+        BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+        free(bidiLineInfo.visualToLogicalMap);
+        bidiLineInfo.visualToLogicalMap = NULL;
+      }
+
+      model->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
+                                                         bidirectionalLineInfoBuffer + endRemoveIndex);
+    }
+  }
+}
+
+void ControllerImplDataClearer::ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+  const CharacterIndex endIndexPlusOne           = endIndex + 1u;
+  const Length         numberOfCharactersRemoved = endIndexPlusOne - startIndex;
+  ModelPtr&            model                     = impl.mModel;
+  TextUpdateInfo&      textUpdateInfo            = impl.mTextUpdateInfo;
+
+
+  // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
+  GlyphIndex* charactersToGlyphBuffer  = model->mVisualModel->mCharactersToGlyph.Begin();
+  Length*     glyphsPerCharacterBuffer = model->mVisualModel->mGlyphsPerCharacter.Begin();
+
+  const GlyphIndex endGlyphIndexPlusOne  = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
+  const Length     numberOfGlyphsRemoved = endGlyphIndexPlusOne - textUpdateInfo.mStartGlyphIndex;
+
+  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
+  {
+    // Update the character to glyph indices.
+    for(Vector<GlyphIndex>::Iterator it    = charactersToGlyphBuffer + endIndexPlusOne,
+                                     endIt = charactersToGlyphBuffer + model->mVisualModel->mCharactersToGlyph.Count();
+        it != endIt;
+        ++it)
+    {
+      CharacterIndex& index = *it;
+      index -= numberOfGlyphsRemoved;
+    }
+
+    // Clear the character to glyph conversion table.
+    model->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
+                                                  charactersToGlyphBuffer + endIndexPlusOne);
+
+    // Clear the glyphs per character table.
+    model->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
+                                                   glyphsPerCharacterBuffer + endIndexPlusOne);
+
+    // Clear the glyphs buffer.
+    GlyphInfo* glyphsBuffer = model->mVisualModel->mGlyphs.Begin();
+    model->mVisualModel->mGlyphs.Erase(glyphsBuffer + textUpdateInfo.mStartGlyphIndex,
+                                       glyphsBuffer + endGlyphIndexPlusOne);
+
+    CharacterIndex* glyphsToCharactersBuffer = model->mVisualModel->mGlyphsToCharacters.Begin();
+
+    // Update the glyph to character indices.
+    for(Vector<CharacterIndex>::Iterator it    = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
+                                         endIt = glyphsToCharactersBuffer + model->mVisualModel->mGlyphsToCharacters.Count();
+        it != endIt;
+        ++it)
+    {
+      CharacterIndex& index = *it;
+      index -= numberOfCharactersRemoved;
+    }
+
+    // Clear the glyphs to characters buffer.
+    model->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + textUpdateInfo.mStartGlyphIndex,
+                                                   glyphsToCharactersBuffer + endGlyphIndexPlusOne);
+
+    // Clear the characters per glyph buffer.
+    Length* charactersPerGlyphBuffer = model->mVisualModel->mCharactersPerGlyph.Begin();
+    model->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + textUpdateInfo.mStartGlyphIndex,
+                                                   charactersPerGlyphBuffer + endGlyphIndexPlusOne);
+
+    // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
+    if(0u != model->mVisualModel->mGlyphPositions.Count())
+    {
+      // Clear the positions buffer.
+      Vector2* positionsBuffer = model->mVisualModel->mGlyphPositions.Begin();
+      model->mVisualModel->mGlyphPositions.Erase(positionsBuffer + textUpdateInfo.mStartGlyphIndex,
+                                                 positionsBuffer + endGlyphIndexPlusOne);
+    }
+  }
+
+  if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
+  {
+    // Clear the lines.
+    uint32_t startRemoveIndex = model->mVisualModel->mLines.Count();
+    uint32_t endRemoveIndex   = startRemoveIndex;
+    ClearCharacterRuns(startIndex,
+                       endIndex,
+                       model->mVisualModel->mLines,
+                       startRemoveIndex,
+                       endRemoveIndex);
+
+    // Will update the glyph runs.
+    startRemoveIndex = model->mVisualModel->mLines.Count();
+    endRemoveIndex   = startRemoveIndex;
+    ClearGlyphRuns(textUpdateInfo.mStartGlyphIndex,
+                   endGlyphIndexPlusOne - 1u,
+                   model->mVisualModel->mLines,
+                   startRemoveIndex,
+                   endRemoveIndex);
+
+    // Set the line index from where to insert the new laid-out lines.
+    textUpdateInfo.mStartLineIndex = startRemoveIndex;
+
+    LineRun* linesBuffer = model->mVisualModel->mLines.Begin();
+    model->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
+                                      linesBuffer + endRemoveIndex);
+  }
+
+  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
+  {
+    if(0u != model->mVisualModel->mColorIndices.Count())
+    {
+      ColorIndex* colorIndexBuffer = model->mVisualModel->mColorIndices.Begin();
+      model->mVisualModel->mColorIndices.Erase(colorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
+                                                colorIndexBuffer + endGlyphIndexPlusOne);
+    }
+
+    if(0u != model->mVisualModel->mBackgroundColorIndices.Count())
+    {
+      ColorIndex* backgroundColorIndexBuffer = model->mVisualModel->mBackgroundColorIndices.Begin();
+      model->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
+                                                         backgroundColorIndexBuffer + endGlyphIndexPlusOne);
+    }
+  }
+}
+
+void ControllerImplDataClearer::ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
+{
+  TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+
+  if(textUpdateInfo.mClearAll ||
+     ((0u == startIndex) &&
+      (textUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
+  {
+    ClearFullModelData(impl, operations);
+  }
+  else
+  {
+    // Clear the model data related with characters.
+    ClearCharacterModelData(impl, startIndex, endIndex, operations);
+
+    // Clear the model data related with glyphs.
+    ClearGlyphModelData(impl, startIndex, endIndex, operations);
+  }
+
+  ModelPtr& model = impl.mModel;
+
+  // The estimated number of lines. Used to avoid reallocations when layouting.
+  textUpdateInfo.mEstimatedNumberOfLines = std::max(model->mVisualModel->mLines.Count(), model->mLogicalModel->mParagraphInfo.Count());
+
+  model->mVisualModel->ClearCaches();
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h b/dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h
new file mode 100644 (file)
index 0000000..878b285
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+
+namespace Dali::Toolkit::Text
+{
+
+/// Provides methods to clear some of the model data in the Text::Controller::Impl
+struct ControllerImplDataClearer
+{
+
+  /**
+   * @brief Helper to clear completely the parts of the model specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] impl The text controller impl.
+   * @param[in] operations The operations required.
+   */
+  static void ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations);
+
+  /**
+   * @brief Helper to clear completely the parts of the model related with the characters specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] impl The text controller impl.
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  static void ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+
+  /**
+   * @brief Helper to clear completely the parts of the model related with the glyphs specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   * @note Character indices are transformed to glyph indices.
+   *
+   * @param[in] impl The text controller impl.
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  static void ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+
+  /**
+   * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] impl The text controller impl.
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  static void ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
+};
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-impl-event-handler.cpp
new file mode 100644 (file)
index 0000000..9dcf07a
--- /dev/null
@@ -0,0 +1,1129 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/adaptor-framework/key.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+
+using namespace Dali;
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+bool ControllerImplEventHandler::ProcessInputEvents(Controller::Impl& impl)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::ProcessInputEvents\n");
+
+  EventData*& eventData = impl.mEventData;
+  if(NULL == eventData)
+  {
+    // Nothing to do if there is no text input.
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents no event data\n");
+    return false;
+  }
+
+  unsigned int oldPos = eventData->mPrimaryCursorPosition;
+
+  if(eventData->mDecorator)
+  {
+    for(std::vector<Event>::iterator iter = eventData->mEventQueue.begin();
+        iter != eventData->mEventQueue.end();
+        ++iter)
+    {
+      switch(iter->type)
+      {
+        case Event::CURSOR_KEY_EVENT:
+        {
+          OnCursorKeyEvent(impl, *iter);
+          break;
+        }
+        case Event::TAP_EVENT:
+        {
+          OnTapEvent(impl, *iter);
+          break;
+        }
+        case Event::LONG_PRESS_EVENT:
+        {
+          OnLongPressEvent(impl, *iter);
+          break;
+        }
+        case Event::PAN_EVENT:
+        {
+          OnPanEvent(impl, *iter);
+          break;
+        }
+        case Event::GRAB_HANDLE_EVENT:
+        case Event::LEFT_SELECTION_HANDLE_EVENT:
+        case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through
+        {
+          OnHandleEvent(impl, *iter);
+          break;
+        }
+        case Event::SELECT:
+        {
+          OnSelectEvent(impl, *iter);
+          break;
+        }
+        case Event::SELECT_ALL:
+        {
+          OnSelectAllEvent(impl);
+          break;
+        }
+        case Event::SELECT_NONE:
+        {
+          OnSelectNoneEvent(impl);
+          break;
+        }
+        case Event::SELECT_RANGE:
+        {
+          OnSelectRangeEvent(impl, *iter);
+          break;
+        }
+      }
+    }
+  }
+
+  if(eventData->mUpdateCursorPosition ||
+     eventData->mUpdateHighlightBox)
+  {
+    impl.NotifyInputMethodContext();
+  }
+
+  // The cursor must also be repositioned after inserts into the model
+  if(eventData->mUpdateCursorPosition)
+  {
+    // Updates the cursor position and scrolls the text to make it visible.
+    CursorInfo cursorInfo;
+
+    // Calculate the cursor position from the new cursor index.
+    impl.GetCursorPosition(eventData->mPrimaryCursorPosition, cursorInfo);
+
+    //only emit the event if the cursor is moved in current function.
+    if(nullptr != impl.mEditableControlInterface && eventData->mEventQueue.size() > 0)
+    {
+      impl.mEditableControlInterface->CursorPositionChanged(oldPos, eventData->mPrimaryCursorPosition);
+    }
+
+    if(eventData->mUpdateCursorHookPosition)
+    {
+      // Update the cursor hook position. Used to move the cursor with the keys 'up' and 'down'.
+      eventData->mCursorHookPositionX      = cursorInfo.primaryPosition.x;
+      eventData->mUpdateCursorHookPosition = false;
+    }
+
+    // Scroll first the text after delete ...
+    if(eventData->mScrollAfterDelete)
+    {
+      impl.ScrollTextToMatchCursor(cursorInfo);
+    }
+
+    // ... then, text can be scrolled to make the cursor visible.
+    if(eventData->mScrollAfterUpdatePosition)
+    {
+      const Vector2 currentCursorPosition(cursorInfo.primaryPosition.x, cursorInfo.lineOffset);
+      impl.ScrollToMakePositionVisible(currentCursorPosition, cursorInfo.lineHeight);
+    }
+    eventData->mScrollAfterUpdatePosition = false;
+    eventData->mScrollAfterDelete         = false;
+
+    impl.UpdateCursorPosition(cursorInfo);
+
+    eventData->mDecoratorUpdated         = true;
+    eventData->mUpdateCursorPosition     = false;
+    eventData->mUpdateGrabHandlePosition = false;
+  }
+
+  if(eventData->mUpdateHighlightBox ||
+     eventData->mUpdateLeftSelectionPosition ||
+     eventData->mUpdateRightSelectionPosition)
+  {
+    CursorInfo leftHandleInfo;
+    CursorInfo rightHandleInfo;
+
+    if(eventData->mUpdateHighlightBox)
+    {
+      impl.GetCursorPosition(eventData->mLeftSelectionPosition, leftHandleInfo);
+
+      impl.GetCursorPosition(eventData->mRightSelectionPosition, rightHandleInfo);
+
+      if(eventData->mScrollAfterUpdatePosition && (eventData->mIsLeftHandleSelected ? eventData->mUpdateLeftSelectionPosition : eventData->mUpdateRightSelectionPosition))
+      {
+        if(eventData->mIsLeftHandleSelected && eventData->mIsRightHandleSelected)
+        {
+          CursorInfo& infoLeft = leftHandleInfo;
+
+          const Vector2 currentCursorPositionLeft(infoLeft.primaryPosition.x, infoLeft.lineOffset);
+          impl.ScrollToMakePositionVisible(currentCursorPositionLeft, infoLeft.lineHeight);
+
+          CursorInfo& infoRight = rightHandleInfo;
+
+          const Vector2 currentCursorPositionRight(infoRight.primaryPosition.x, infoRight.lineOffset);
+          impl.ScrollToMakePositionVisible(currentCursorPositionRight, infoRight.lineHeight);
+        }
+        else
+        {
+          CursorInfo& info = eventData->mIsLeftHandleSelected ? leftHandleInfo : rightHandleInfo;
+
+          const Vector2 currentCursorPosition(info.primaryPosition.x, info.lineOffset);
+          impl.ScrollToMakePositionVisible(currentCursorPosition, info.lineHeight);
+        }
+      }
+    }
+
+    if(eventData->mUpdateLeftSelectionPosition)
+    {
+      impl.UpdateSelectionHandle(LEFT_SELECTION_HANDLE, leftHandleInfo);
+
+      impl.SetPopupButtons();
+      eventData->mDecoratorUpdated            = true;
+      eventData->mUpdateLeftSelectionPosition = false;
+    }
+
+    if(eventData->mUpdateRightSelectionPosition)
+    {
+      impl.UpdateSelectionHandle(RIGHT_SELECTION_HANDLE, rightHandleInfo);
+
+      impl.SetPopupButtons();
+      eventData->mDecoratorUpdated             = true;
+      eventData->mUpdateRightSelectionPosition = false;
+    }
+
+    if(eventData->mUpdateHighlightBox)
+    {
+      impl.RepositionSelectionHandles();
+
+      eventData->mUpdateLeftSelectionPosition  = false;
+      eventData->mUpdateRightSelectionPosition = false;
+      eventData->mUpdateHighlightBox           = false;
+      eventData->mIsLeftHandleSelected         = false;
+      eventData->mIsRightHandleSelected        = false;
+    }
+
+    eventData->mScrollAfterUpdatePosition = false;
+  }
+
+  if(eventData->mUpdateInputStyle)
+  {
+    // Keep a copy of the current input style.
+    InputStyle currentInputStyle;
+    currentInputStyle.Copy(eventData->mInputStyle);
+
+    // Set the default style first.
+    impl.RetrieveDefaultInputStyle(eventData->mInputStyle);
+
+    // Get the character index from the cursor index.
+    const CharacterIndex styleIndex = (eventData->mPrimaryCursorPosition > 0u) ? eventData->mPrimaryCursorPosition - 1u : 0u;
+
+    // Retrieve the style from the style runs stored in the logical model.
+    impl.mModel->mLogicalModel->RetrieveStyle(styleIndex, eventData->mInputStyle);
+
+    // Compare if the input style has changed.
+    const bool hasInputStyleChanged = !currentInputStyle.Equal(eventData->mInputStyle);
+
+    if(hasInputStyleChanged)
+    {
+      const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(eventData->mInputStyle);
+      // Queue the input style changed signal.
+      eventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
+    }
+
+    eventData->mUpdateInputStyle = false;
+  }
+
+  eventData->mEventQueue.clear();
+
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n");
+
+  const bool decoratorUpdated  = eventData->mDecoratorUpdated;
+  eventData->mDecoratorUpdated = false;
+
+  return decoratorUpdated;
+}
+
+void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const Event& event)
+{
+  if(NULL == impl.mEventData || !impl.IsShowingRealText())
+  {
+    // Nothing to do if there is no text input.
+    return;
+  }
+
+  int              keyCode         = event.p1.mInt;
+  bool             isShiftModifier = event.p2.mBool;
+  EventData&       eventData       = *impl.mEventData;
+  ModelPtr&        model           = impl.mModel;
+  LogicalModelPtr& logicalModel    = model->mLogicalModel;
+  VisualModelPtr&  visualModel     = model->mVisualModel;
+  uint32_t         oldSelStart     = eventData.mLeftSelectionPosition;
+  uint32_t         oldSelEnd       = eventData.mRightSelectionPosition;
+
+  CharacterIndex& primaryCursorPosition         = eventData.mPrimaryCursorPosition;
+  CharacterIndex  previousPrimaryCursorPosition = primaryCursorPosition;
+
+  if(Dali::DALI_KEY_CURSOR_LEFT == keyCode)
+  {
+    if(primaryCursorPosition > 0u)
+    {
+      if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible())
+      {
+        primaryCursorPosition = std::min(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+      }
+      else
+      {
+        primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition - 1u);
+      }
+    }
+  }
+  else if(Dali::DALI_KEY_CURSOR_RIGHT == keyCode)
+  {
+    if(logicalModel->mText.Count() > primaryCursorPosition)
+    {
+      if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible())
+      {
+        primaryCursorPosition = std::max(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+      }
+      else
+      {
+        primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition);
+      }
+    }
+  }
+  else if(Dali::DALI_KEY_CURSOR_UP == keyCode && !isShiftModifier)
+  {
+    // Ignore Shift-Up for text selection for now.
+
+    // Get first the line index of the current cursor position index.
+    CharacterIndex characterIndex = 0u;
+
+    if(primaryCursorPosition > 0u)
+    {
+      characterIndex = primaryCursorPosition - 1u;
+    }
+
+    const LineIndex lineIndex         = visualModel->GetLineOfCharacter(characterIndex);
+    const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex);
+    const LineIndex lastLineIndex     = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+    const bool      isLastLine        = (previousLineIndex == lastLineIndex);
+
+    // Retrieve the cursor position info.
+    CursorInfo cursorInfo;
+    impl.GetCursorPosition(primaryCursorPosition,
+                           cursorInfo);
+
+    // Get the line above.
+    const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex);
+
+    // Get the next hit 'y' point.
+    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line, isLastLine);
+
+    // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
+    bool matchedCharacter = false;
+    primaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
+                                                        logicalModel,
+                                                        impl.mMetrics,
+                                                        eventData.mCursorHookPositionX,
+                                                        hitPointY,
+                                                        CharacterHitTest::TAP,
+                                                        matchedCharacter);
+  }
+  else if(Dali::DALI_KEY_CURSOR_DOWN == keyCode && !isShiftModifier)
+  {
+    // Ignore Shift-Down for text selection for now.
+
+    // Get first the line index of the current cursor position index.
+    CharacterIndex characterIndex = 0u;
+
+    if(primaryCursorPosition > 0u)
+    {
+      characterIndex = primaryCursorPosition - 1u;
+    }
+
+    const LineIndex lineIndex = visualModel->GetLineOfCharacter(characterIndex);
+
+    if(lineIndex + 1u < visualModel->mLines.Count())
+    {
+      // Retrieve the cursor position info.
+      CursorInfo cursorInfo;
+      impl.GetCursorPosition(primaryCursorPosition, cursorInfo);
+
+      // Get the line below.
+      const LineRun& nextline = *(visualModel->mLines.Begin() + lineIndex + 1u);
+      const LineRun& currline = *(visualModel->mLines.Begin() + lineIndex);
+
+      // Get last line index
+      const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
+      const bool      isLastLine    = (lineIndex + 1u == lastLineIndex);
+
+      // Get the next hit 'y' point.
+      const float hitPointY = cursorInfo.lineOffset + GetLineHeight(currline, false) + 0.5f * GetLineHeight(nextline, isLastLine);
+
+      // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
+      bool matchedCharacter = false;
+      primaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
+                                                          logicalModel,
+                                                          impl.mMetrics,
+                                                          eventData.mCursorHookPositionX,
+                                                          hitPointY,
+                                                          CharacterHitTest::TAP,
+                                                          matchedCharacter);
+    }
+  }
+
+  if(!isShiftModifier && eventData.mState != EventData::SELECTING)
+  {
+    // Update selection position after moving the cursor
+    eventData.mLeftSelectionPosition  = primaryCursorPosition;
+    eventData.mRightSelectionPosition = primaryCursorPosition;
+
+    if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
+    {
+      impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+    }
+  }
+
+  if(isShiftModifier && impl.IsShowingRealText() && eventData.mShiftSelectionFlag)
+  {
+    // Handle text selection
+    bool selecting = false;
+
+    if(Dali::DALI_KEY_CURSOR_LEFT == keyCode || Dali::DALI_KEY_CURSOR_RIGHT == keyCode)
+    {
+      // Shift-Left/Right to select the text
+      int cursorPositionDelta = primaryCursorPosition - previousPrimaryCursorPosition;
+      if(cursorPositionDelta > 0 || eventData.mRightSelectionPosition > 0u) // Check the boundary
+      {
+        eventData.mRightSelectionPosition += cursorPositionDelta;
+        eventData.mPrimaryCursorPosition = eventData.mRightSelectionPosition;
+
+        if(impl.mSelectableControlInterface != nullptr)
+        {
+          impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+        }
+      }
+
+      if(impl.mSelectableControlInterface != nullptr && eventData.mLeftSelectionPosition == eventData.mRightSelectionPosition)
+      {
+        // If left selection position and right selection position are the same, the selection is canceled.
+        selecting = false;
+      }
+      else
+      {
+        selecting = true;
+      }
+    }
+    else if(eventData.mLeftSelectionPosition != eventData.mRightSelectionPosition)
+    {
+      // Show no grab handles and text highlight if Shift-Up/Down pressed but no selected text
+      selecting = true;
+    }
+
+    if(selecting)
+    {
+      // Notify the cursor position to the InputMethodContext.
+      if(eventData.mInputMethodContext)
+      {
+        eventData.mInputMethodContext.SetCursorPosition(primaryCursorPosition);
+        eventData.mInputMethodContext.NotifyCursorPosition();
+      }
+
+      impl.ChangeState(EventData::SELECTING);
+
+      eventData.mUpdateLeftSelectionPosition  = true;
+      eventData.mUpdateRightSelectionPosition = true;
+      eventData.mUpdateGrabHandlePosition     = true;
+      eventData.mUpdateHighlightBox           = true;
+
+      // Hide the text selection popup if select the text using keyboard instead of moving grab handles
+      if(eventData.mGrabHandlePopupEnabled)
+      {
+        eventData.mDecorator->SetPopupActive(false);
+      }
+    }
+    else
+    {
+      // If no selection, set a normal cursor.
+      impl.ChangeState(EventData::EDITING);
+      eventData.mUpdateCursorPosition = true;
+    }
+  }
+  else
+  {
+    // Handle normal cursor move
+    impl.ChangeState(EventData::EDITING);
+    eventData.mUpdateCursorPosition = true;
+  }
+
+  eventData.mUpdateInputStyle          = true;
+  eventData.mScrollAfterUpdatePosition = true;
+}
+
+void ControllerImplEventHandler::OnTapEvent(Controller::Impl& impl, const Event& event)
+{
+  if(impl.mEventData)
+  {
+    const unsigned int tapCount     = event.p1.mUint;
+    EventData&         eventData    = *impl.mEventData;
+    ModelPtr&          model        = impl.mModel;
+    LogicalModelPtr&   logicalModel = model->mLogicalModel;
+    VisualModelPtr&    visualModel  = model->mVisualModel;
+
+    if(1u == tapCount)
+    {
+      if(impl.IsShowingRealText())
+      {
+        // Convert from control's coords to text's coords.
+        const float xPosition   = event.p2.mFloat - model->mScrollPosition.x;
+        const float yPosition   = event.p3.mFloat - model->mScrollPosition.y;
+        uint32_t    oldSelStart = eventData.mLeftSelectionPosition;
+        uint32_t    oldSelEnd   = eventData.mRightSelectionPosition;
+
+        // Keep the tap 'x' position. Used to move the cursor.
+        eventData.mCursorHookPositionX = xPosition;
+
+        // Whether to touch point hits on a glyph.
+        bool matchedCharacter            = false;
+        eventData.mPrimaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
+                                                                       logicalModel,
+                                                                       impl.mMetrics,
+                                                                       xPosition,
+                                                                       yPosition,
+                                                                       CharacterHitTest::TAP,
+                                                                       matchedCharacter);
+
+        if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
+        {
+          impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mPrimaryCursorPosition, eventData.mPrimaryCursorPosition);
+        }
+
+        // When the cursor position is changing, delay cursor blinking
+        eventData.mDecorator->DelayCursorBlink();
+      }
+      else
+      {
+        eventData.mPrimaryCursorPosition = 0u;
+      }
+
+      // Update selection position after tapping
+      eventData.mLeftSelectionPosition  = eventData.mPrimaryCursorPosition;
+      eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition;
+
+      eventData.mUpdateCursorPosition      = true;
+      eventData.mUpdateGrabHandlePosition  = true;
+      eventData.mScrollAfterUpdatePosition = true;
+      eventData.mUpdateInputStyle          = true;
+
+      // Notify the cursor position to the InputMethodContext.
+      if(eventData.mInputMethodContext)
+      {
+        eventData.mInputMethodContext.SetCursorPosition(eventData.mPrimaryCursorPosition);
+        eventData.mInputMethodContext.NotifyCursorPosition();
+      }
+    }
+    else if(2u == tapCount)
+    {
+      if(eventData.mSelectionEnabled)
+      {
+        // Convert from control's coords to text's coords.
+        const float xPosition = event.p2.mFloat - model->mScrollPosition.x;
+        const float yPosition = event.p3.mFloat - model->mScrollPosition.y;
+
+        // Calculates the logical position from the x,y coords.
+        impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mDoubleTapAction);
+      }
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnPanEvent(Controller::Impl& impl, const Event& event)
+{
+  if(impl.mEventData)
+  {
+    EventData&    eventData = *impl.mEventData;
+    DecoratorPtr& decorator = eventData.mDecorator;
+
+    const bool isHorizontalScrollEnabled = decorator->IsHorizontalScrollEnabled();
+    const bool isVerticalScrollEnabled   = decorator->IsVerticalScrollEnabled();
+
+    if(!isHorizontalScrollEnabled && !isVerticalScrollEnabled)
+    {
+      // Nothing to do if scrolling is not enabled.
+      return;
+    }
+
+    const GestureState state = static_cast<GestureState>(event.p1.mInt);
+    switch(state)
+    {
+      case GestureState::STARTED:
+      {
+        // Will remove the cursor, handles or text's popup, ...
+        impl.ChangeState(EventData::TEXT_PANNING);
+        break;
+      }
+      case GestureState::CONTINUING:
+      {
+        ModelPtr& model = impl.mModel;
+
+        const Vector2& layoutSize     = model->mVisualModel->GetLayoutSize();
+        Vector2&       scrollPosition = model->mScrollPosition;
+        const Vector2  currentScroll  = scrollPosition;
+
+        if(isHorizontalScrollEnabled)
+        {
+          const float displacementX = event.p2.mFloat;
+          scrollPosition.x += displacementX;
+
+          impl.ClampHorizontalScroll(layoutSize);
+        }
+
+        if(isVerticalScrollEnabled)
+        {
+          const float displacementY = event.p3.mFloat;
+          scrollPosition.y += displacementY;
+
+          impl.ClampVerticalScroll(layoutSize);
+        }
+
+        decorator->UpdatePositions(scrollPosition - currentScroll);
+        break;
+      }
+      case GestureState::FINISHED:
+      case GestureState::CANCELLED: // FALLTHROUGH
+      {
+        // Will go back to the previous state to show the cursor, handles, the text's popup, ...
+        impl.ChangeState(eventData.mPreviousState);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnLongPressEvent(Controller::Impl& impl, const Event& event)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::OnLongPressEvent\n");
+
+  if(impl.mEventData)
+  {
+    EventData& eventData = *impl.mEventData;
+
+    if(!impl.IsShowingRealText() && (EventData::EDITING == eventData.mState))
+    {
+      impl.ChangeState(EventData::EDITING_WITH_POPUP);
+      eventData.mDecoratorUpdated = true;
+      eventData.mUpdateInputStyle = true;
+    }
+    else
+    {
+      if(eventData.mSelectionEnabled)
+      {
+        ModelPtr& model = impl.mModel;
+
+        // Convert from control's coords to text's coords.
+        const float xPosition = event.p2.mFloat - model->mScrollPosition.x;
+        const float yPosition = event.p3.mFloat - model->mScrollPosition.y;
+
+        // Calculates the logical position from the x,y coords.
+        impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mLongPressAction);
+      }
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnHandleEvent(Controller::Impl& impl, const Event& event)
+{
+  if(impl.mEventData)
+  {
+    const unsigned int state                    = event.p1.mUint;
+    const bool         handleStopScrolling      = (HANDLE_STOP_SCROLLING == state);
+    const bool         isSmoothHandlePanEnabled = impl.mEventData->mDecorator->IsSmoothHandlePanEnabled();
+
+    if(HANDLE_PRESSED == state)
+    {
+      OnHandlePressed(impl, event, isSmoothHandlePanEnabled);
+    } // end ( HANDLE_PRESSED == state )
+    else if((HANDLE_RELEASED == state) ||
+            handleStopScrolling)
+    {
+      OnHandleReleased(impl, event, isSmoothHandlePanEnabled, handleStopScrolling);
+    } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) )
+    else if(HANDLE_SCROLLING == state)
+    {
+      OnHandleScrolling(impl, event, isSmoothHandlePanEnabled);
+    } // end ( HANDLE_SCROLLING == state )
+  }
+}
+
+void ControllerImplEventHandler::OnSelectEvent(Controller::Impl& impl, const Event& event)
+{
+  if(impl.mEventData && impl.mEventData->mSelectionEnabled)
+  {
+    ModelPtr&      model          = impl.mModel;
+    const Vector2& scrollPosition = model->mScrollPosition;
+
+    // Convert from control's coords to text's coords.
+    const float xPosition = event.p2.mFloat - scrollPosition.x;
+    const float yPosition = event.p3.mFloat - scrollPosition.y;
+
+    // Calculates the logical position from the x,y coords.
+    impl.RepositionSelectionHandles(xPosition, yPosition, Controller::NoTextTap::HIGHLIGHT);
+  }
+}
+
+void ControllerImplEventHandler::OnSelectAllEvent(Controller::Impl& impl)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectAllEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false");
+
+  if(impl.mEventData)
+  {
+    EventData& eventData = *impl.mEventData;
+    if(eventData.mSelectionEnabled && eventData.mState != EventData::INACTIVE)
+    {
+      ModelPtr&      model          = impl.mModel;
+      const Vector2& scrollPosition = model->mScrollPosition;
+
+      // Calculates the logical position from the start.
+      impl.RepositionSelectionHandles(0.f - scrollPosition.x,
+                                      0.f - scrollPosition.y,
+                                      Controller::NoTextTap::HIGHLIGHT);
+
+      uint32_t oldStart = eventData.mLeftSelectionPosition;
+      uint32_t oldEnd   = eventData.mRightSelectionPosition;
+
+      eventData.mLeftSelectionPosition  = 0u;
+      eventData.mRightSelectionPosition = model->mLogicalModel->mText.Count();
+      eventData.mPrimaryCursorPosition  = eventData.mRightSelectionPosition;
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+      }
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnSelectNoneEvent(Controller::Impl& impl)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectNoneEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false");
+
+  if(impl.mEventData)
+  {
+    EventData& eventData = *impl.mEventData;
+    if(eventData.mSelectionEnabled && eventData.mState == EventData::SELECTING)
+    {
+      uint32_t oldStart = eventData.mLeftSelectionPosition;
+      uint32_t oldEnd   = eventData.mRightSelectionPosition;
+
+      eventData.mLeftSelectionPosition = eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition;
+      impl.ChangeState(EventData::EDITING);
+      eventData.mUpdateCursorPosition      = true;
+      eventData.mUpdateInputStyle          = true;
+      eventData.mScrollAfterUpdatePosition = true;
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+      }
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnSelectRangeEvent(Controller::Impl& impl, const Event& event)
+{
+  if(impl.mEventData && impl.mEventData->mSelectionEnabled && impl.mEventData->mState != EventData::INACTIVE)
+  {
+    ModelPtr&      model          = impl.mModel;
+    const Vector2& scrollPosition = model->mScrollPosition;
+
+    // Calculate the selection index.
+    const uint32_t length = static_cast<uint32_t>(model->mLogicalModel->mText.Count());
+    const uint32_t start  = std::min(event.p2.mUint, length);
+    const uint32_t end    = std::min(event.p3.mUint, length);
+
+    if(start != end)
+    {
+      uint32_t oldStart = impl.mEventData->mLeftSelectionPosition;
+      uint32_t oldEnd   = impl.mEventData->mRightSelectionPosition;
+
+      // Calculates the logical position from the x,y coords.
+      impl.RepositionSelectionHandles(0.f - scrollPosition.x, 0.f - scrollPosition.y, Controller::NoTextTap::HIGHLIGHT);
+
+      impl.mEventData->mLeftSelectionPosition  = start;
+      impl.mEventData->mRightSelectionPosition = end;
+      impl.mEventData->mPrimaryCursorPosition  = end;
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
+      }
+    }
+  }
+}
+
+void ControllerImplEventHandler::OnHandlePressed(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled)
+{
+  ModelPtr&      model          = impl.mModel;
+  const Vector2& scrollPosition = model->mScrollPosition;
+
+  // Convert from decorator's coords to text's coords.
+  const float xPosition = event.p2.mFloat - scrollPosition.x;
+  const float yPosition = event.p3.mFloat - scrollPosition.y;
+
+  // Need to calculate the handle's new position.
+  bool                 matchedCharacter  = false;
+  const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex(model->mVisualModel,
+                                                                       model->mLogicalModel,
+                                                                       impl.mMetrics,
+                                                                       xPosition,
+                                                                       yPosition,
+                                                                       CharacterHitTest::SCROLL,
+                                                                       matchedCharacter);
+
+  EventData& eventData = *impl.mEventData;
+  uint32_t   oldStart  = eventData.mLeftSelectionPosition;
+  uint32_t   oldEnd    = eventData.mRightSelectionPosition;
+
+  if(Event::GRAB_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::GRAB_HANDLE_PANNING);
+
+    if(handleNewPosition != eventData.mPrimaryCursorPosition)
+    {
+      // Updates the cursor position if the handle's new position is different than the current one.
+      eventData.mUpdateCursorPosition = true;
+      // Does not update the grab handle position if the smooth panning is enabled. (The decorator does it smooth).
+      eventData.mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
+      eventData.mPrimaryCursorPosition    = handleNewPosition;
+    }
+
+    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
+    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
+  }
+  else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
+
+    if((handleNewPosition != eventData.mLeftSelectionPosition) &&
+       (handleNewPosition != eventData.mRightSelectionPosition))
+    {
+      // Updates the highlight box if the handle's new position is different than the current one.
+      eventData.mUpdateHighlightBox = true;
+      // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
+      eventData.mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
+      eventData.mLeftSelectionPosition       = handleNewPosition;
+    }
+
+    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
+    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
+
+    // Will define the order to scroll the text to match the handle position.
+    eventData.mIsLeftHandleSelected  = true;
+    eventData.mIsRightHandleSelected = false;
+  }
+  else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
+
+    if((handleNewPosition != eventData.mRightSelectionPosition) &&
+       (handleNewPosition != eventData.mLeftSelectionPosition))
+    {
+      // Updates the highlight box if the handle's new position is different than the current one.
+      eventData.mUpdateHighlightBox = true;
+      // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
+      eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
+      eventData.mRightSelectionPosition       = handleNewPosition;
+    }
+
+    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
+    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
+
+    // Will define the order to scroll the text to match the handle position.
+    eventData.mIsLeftHandleSelected  = false;
+    eventData.mIsRightHandleSelected = true;
+  }
+
+  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
+  {
+    impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+  }
+}
+
+void ControllerImplEventHandler::OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling)
+{
+  CharacterIndex handlePosition = 0u;
+  if(handleStopScrolling || isSmoothHandlePanEnabled)
+  {
+    ModelPtr&      model          = impl.mModel;
+    const Vector2& scrollPosition = model->mScrollPosition;
+
+    // Convert from decorator's coords to text's coords.
+    const float xPosition = event.p2.mFloat - scrollPosition.x;
+    const float yPosition = event.p3.mFloat - scrollPosition.y;
+
+    bool matchedCharacter = false;
+    handlePosition        = Text::GetClosestCursorIndex(model->mVisualModel,
+                                                 model->mLogicalModel,
+                                                 impl.mMetrics,
+                                                 xPosition,
+                                                 yPosition,
+                                                 CharacterHitTest::SCROLL,
+                                                 matchedCharacter);
+  }
+
+  EventData& eventData = *impl.mEventData;
+  uint32_t   oldStart  = eventData.mLeftSelectionPosition;
+  uint32_t   oldEnd    = eventData.mRightSelectionPosition;
+
+  if(Event::GRAB_HANDLE_EVENT == event.type)
+  {
+    eventData.mUpdateCursorPosition     = true;
+    eventData.mUpdateGrabHandlePosition = true;
+    eventData.mUpdateInputStyle         = true;
+
+    if(!impl.IsClipboardEmpty())
+    {
+      impl.ChangeState(EventData::EDITING_WITH_PASTE_POPUP); // Moving grabhandle will show Paste Popup
+    }
+
+    if(handleStopScrolling || isSmoothHandlePanEnabled)
+    {
+      eventData.mScrollAfterUpdatePosition = true;
+      eventData.mPrimaryCursorPosition     = handlePosition;
+    }
+  }
+  else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::SELECTING);
+
+    eventData.mUpdateHighlightBox           = true;
+    eventData.mUpdateLeftSelectionPosition  = true;
+    eventData.mUpdateRightSelectionPosition = true;
+
+    if(handleStopScrolling || isSmoothHandlePanEnabled)
+    {
+      eventData.mScrollAfterUpdatePosition = true;
+
+      if((handlePosition != eventData.mRightSelectionPosition) &&
+         (handlePosition != eventData.mLeftSelectionPosition))
+      {
+        eventData.mLeftSelectionPosition = handlePosition;
+      }
+    }
+  }
+  else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::SELECTING);
+
+    eventData.mUpdateHighlightBox           = true;
+    eventData.mUpdateRightSelectionPosition = true;
+    eventData.mUpdateLeftSelectionPosition  = true;
+
+    if(handleStopScrolling || isSmoothHandlePanEnabled)
+    {
+      eventData.mScrollAfterUpdatePosition = true;
+      if((handlePosition != eventData.mRightSelectionPosition) &&
+         (handlePosition != eventData.mLeftSelectionPosition))
+      {
+        eventData.mRightSelectionPosition = handlePosition;
+      }
+    }
+  }
+
+  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
+  {
+    impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+  }
+
+  eventData.mDecoratorUpdated = true;
+}
+
+void ControllerImplEventHandler::OnHandleScrolling(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled)
+{
+  ModelPtr&       model          = impl.mModel;
+  Vector2&        scrollPosition = model->mScrollPosition;
+  VisualModelPtr& visualModel    = model->mVisualModel;
+
+  const float    xSpeed                = event.p2.mFloat;
+  const float    ySpeed                = event.p3.mFloat;
+  const Vector2& layoutSize            = visualModel->GetLayoutSize();
+  const Vector2  currentScrollPosition = scrollPosition;
+
+  scrollPosition.x += xSpeed;
+  scrollPosition.y += ySpeed;
+
+  impl.ClampHorizontalScroll(layoutSize);
+  impl.ClampVerticalScroll(layoutSize);
+
+  EventData&    eventData = *impl.mEventData;
+  DecoratorPtr& decorator = eventData.mDecorator;
+
+  bool endOfScroll = false;
+  if(Vector2::ZERO == (currentScrollPosition - scrollPosition))
+  {
+    // Notify the decorator there is no more text to scroll.
+    // The decorator won't send more scroll events.
+    decorator->NotifyEndOfScroll();
+    // Still need to set the position of the handle.
+    endOfScroll = true;
+  }
+
+  // Set the position of the handle.
+  const bool scrollRightDirection      = xSpeed > 0.f;
+  const bool scrollBottomDirection     = ySpeed > 0.f;
+  const bool leftSelectionHandleEvent  = Event::LEFT_SELECTION_HANDLE_EVENT == event.type;
+  const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type;
+
+  if(Event::GRAB_HANDLE_EVENT == event.type)
+  {
+    impl.ChangeState(EventData::GRAB_HANDLE_PANNING);
+
+    // Get the grab handle position in decorator coords.
+    Vector2 position = decorator->GetPosition(GRAB_HANDLE);
+
+    if(decorator->IsHorizontalScrollEnabled())
+    {
+      // Position the grag handle close to either the left or right edge.
+      position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width;
+    }
+
+    if(decorator->IsVerticalScrollEnabled())
+    {
+      position.x = eventData.mCursorHookPositionX;
+
+      // Position the grag handle close to either the top or bottom edge.
+      position.y = scrollBottomDirection ? 0.f : visualModel->mControlSize.height;
+    }
+
+    // Get the new handle position.
+    // The grab handle's position is in decorator's coords. Need to transforms to text's coords.
+    bool                 matchedCharacter = false;
+    const CharacterIndex handlePosition   = Text::GetClosestCursorIndex(visualModel,
+                                                                      impl.mModel->mLogicalModel,
+                                                                      impl.mMetrics,
+                                                                      position.x - scrollPosition.x,
+                                                                      position.y - scrollPosition.y,
+                                                                      CharacterHitTest::SCROLL,
+                                                                      matchedCharacter);
+
+    if(eventData.mPrimaryCursorPosition != handlePosition)
+    {
+      eventData.mUpdateCursorPosition      = true;
+      eventData.mUpdateGrabHandlePosition  = !isSmoothHandlePanEnabled;
+      eventData.mScrollAfterUpdatePosition = true;
+      eventData.mPrimaryCursorPosition     = handlePosition;
+    }
+    eventData.mUpdateInputStyle = eventData.mUpdateCursorPosition;
+
+    // Updates the decorator if the soft handle panning is enabled.
+    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
+  }
+  else if(leftSelectionHandleEvent || rightSelectionHandleEvent)
+  {
+    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
+
+    // Get the selection handle position in decorator coords.
+    Vector2 position = decorator->GetPosition(leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE);
+
+    if(decorator->IsHorizontalScrollEnabled())
+    {
+      // Position the selection handle close to either the left or right edge.
+      position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width;
+    }
+
+    if(decorator->IsVerticalScrollEnabled())
+    {
+      position.x = eventData.mCursorHookPositionX;
+
+      // Position the grag handle close to either the top or bottom edge.
+      position.y = scrollBottomDirection ? 0.f : visualModel->mControlSize.height;
+    }
+
+    // Get the new handle position.
+    // The selection handle's position is in decorator's coords. Need to transform to text's coords.
+    bool                 matchedCharacter = false;
+    const CharacterIndex handlePosition   = Text::GetClosestCursorIndex(visualModel,
+                                                                      impl.mModel->mLogicalModel,
+                                                                      impl.mMetrics,
+                                                                      position.x - scrollPosition.x,
+                                                                      position.y - scrollPosition.y,
+                                                                      CharacterHitTest::SCROLL,
+                                                                      matchedCharacter);
+    uint32_t             oldStart         = eventData.mLeftSelectionPosition;
+    uint32_t             oldEnd           = eventData.mRightSelectionPosition;
+
+    if(leftSelectionHandleEvent)
+    {
+      const bool differentHandles = (eventData.mLeftSelectionPosition != handlePosition) && (eventData.mRightSelectionPosition != handlePosition);
+
+      if(differentHandles || endOfScroll)
+      {
+        eventData.mUpdateHighlightBox           = true;
+        eventData.mUpdateLeftSelectionPosition  = !isSmoothHandlePanEnabled;
+        eventData.mUpdateRightSelectionPosition = isSmoothHandlePanEnabled;
+        eventData.mLeftSelectionPosition        = handlePosition;
+      }
+    }
+    else
+    {
+      const bool differentHandles = (eventData.mRightSelectionPosition != handlePosition) && (eventData.mLeftSelectionPosition != handlePosition);
+      if(differentHandles || endOfScroll)
+      {
+        eventData.mUpdateHighlightBox           = true;
+        eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
+        eventData.mUpdateLeftSelectionPosition  = isSmoothHandlePanEnabled;
+        eventData.mRightSelectionPosition       = handlePosition;
+      }
+    }
+
+    if(eventData.mUpdateLeftSelectionPosition || eventData.mUpdateRightSelectionPosition)
+    {
+      impl.RepositionSelectionHandles();
+
+      eventData.mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled;
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+      }
+    }
+  }
+  eventData.mDecoratorUpdated = true;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h b/dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h
new file mode 100644 (file)
index 0000000..ca93586
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * Contains all the event handling methods for Text::Controller::Impl
+ */
+struct ControllerImplEventHandler
+{
+  /**
+   * @brief Processes input events
+   *
+   * @param[in] impl A reference to Controller::Impl
+   * @return True if the decorator has been updated
+   */
+  static bool ProcessInputEvents(Controller::Impl& impl);
+
+  /**
+   * @brief Called by Controller::Impl when a cursor key event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnCursorKeyEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a tap event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnTapEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a pan event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnPanEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a long press event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnLongPressEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a handle event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnHandleEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a select event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnSelectEvent(Controller::Impl& controllerImpl, const Event& event);
+
+  /**
+   * @brief Called by Controller::Impl when a select all event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnSelectAllEvent(Controller::Impl& controllerImpl);
+
+  /**
+   * @brief Called by Controller::Impl when a select none event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnSelectNoneEvent(Controller::Impl& controllerImpl);
+
+  /**
+   * @brief Called by Controller::Impl when a select range event is received.
+   *
+   * @param controllerImpl A reference to Controller::Impl
+   * @param event The event
+   */
+  static void OnSelectRangeEvent(Controller::Impl& controllerImpl, const Event& event);
+
+private:
+  /**
+   * @brief Called by OnHandleEvent when we are in the Pressed state.
+   *
+   * @param impl A reference to Controller::Impl
+   * @param event The event
+   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
+   */
+  static void OnHandlePressed(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled);
+
+  /**
+   * @brief Called by OnHandleEvent when we are in the Released state.
+   *
+   * @param impl A reference to Controller::Impl
+   * @param event The event
+   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
+   * @param handleStopScrolling Whether we should handle stop scrolling or not
+   */
+  static void OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling);
+
+  /**
+   * @brief Called by OnHandleEvent when we are in the Scrolling state.
+   *
+   * @param impl A reference to Controller::Impl
+   * @param event The event
+   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
+   */
+  static void OnHandleScrolling(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.cpp
new file mode 100644 (file)
index 0000000..8b6b639
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/bidirectional-support.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/color-segmentation.h>
+#include <dali-toolkit/internal/text/hyphenator.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+
+namespace Dali::Toolkit::Text
+{
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
+// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+constexpr float         BRIGHTNESS_THRESHOLD = 0.179f;
+constexpr float         CONSTANT_R           = 0.2126f;
+constexpr float         CONSTANT_G           = 0.7152f;
+constexpr float         CONSTANT_B           = 0.0722f;
+constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
+constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
+constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
+constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
+constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
+constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
+constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
+} // namespace
+
+bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
+
+  // Calculate the operations to be done.
+  const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
+
+  if(Controller::NO_OPERATION == operations)
+  {
+    // Nothing to do if no operations are pending and required.
+    return false;
+  }
+
+  Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
+  Vector<Character>  displayCharacters;
+  bool               useHiddenText = false;
+  if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText)
+  {
+    impl.mHiddenInput->Substitute(srcCharacters, displayCharacters);
+    useHiddenText = true;
+  }
+
+  Vector<Character>& utf32Characters    = useHiddenText ? displayCharacters : srcCharacters;
+  const Length       numberOfCharacters = utf32Characters.Count();
+
+  // Index to the first character of the first paragraph to be updated.
+  CharacterIndex startIndex = 0u;
+  // Number of characters of the paragraphs to be removed.
+  Length paragraphCharacters = 0u;
+
+  impl.CalculateTextUpdateIndices(paragraphCharacters);
+
+  // Check whether the indices for updating the text is valid
+  if(numberOfCharacters > 0u &&
+     (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
+      impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
+  {
+    std::string currentText;
+    Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
+
+    DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
+    DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
+
+    // Dump mTextUpdateInfo
+    DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
+    DALI_LOG_ERROR("     mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
+    DALI_LOG_ERROR("     mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
+
+    return false;
+  }
+
+  startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
+
+  if(impl.mTextUpdateInfo.mClearAll ||
+     (0u != paragraphCharacters))
+  {
+    impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
+  }
+
+  impl.mTextUpdateInfo.mClearAll = false;
+
+  // Whether the model is updated.
+  bool updated = false;
+
+  Vector<LineBreakInfo>& lineBreakInfo               = impl.mModel->mLogicalModel->mLineBreakInfo;
+  const Length           requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
+
+  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
+  {
+    // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
+    // calculate the bidirectional info for each 'paragraph'.
+    // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
+    // is not shaped together).
+    lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
+
+    SetLineBreakInfo(utf32Characters,
+                     startIndex,
+                     requestedNumberOfCharacters,
+                     lineBreakInfo);
+
+    if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
+       impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
+    {
+      CharacterIndex end                 = startIndex + requestedNumberOfCharacters;
+      LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
+
+      for(CharacterIndex index = startIndex; index < end; index++)
+      {
+        CharacterIndex wordEnd = index;
+        while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
+        {
+          wordEnd++;
+        }
+
+        if((wordEnd + 1) == end) // add last char
+        {
+          wordEnd++;
+        }
+
+        Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
+
+        for(CharacterIndex i = 0; i < (wordEnd - index); i++)
+        {
+          if(hyphens[i])
+          {
+            *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
+          }
+        }
+
+        index = wordEnd;
+      }
+    }
+
+    // Create the paragraph info.
+    impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
+                                                    requestedNumberOfCharacters);
+    updated = true;
+  }
+
+  const bool getScripts    = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
+  const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
+
+  Vector<ScriptRun>& scripts    = impl.mModel->mLogicalModel->mScriptRuns;
+  Vector<FontRun>&   validFonts = impl.mModel->mLogicalModel->mFontRuns;
+
+  if(getScripts || validateFonts)
+  {
+    // Validates the fonts assigned by the application or assigns default ones.
+    // It makes sure all the characters are going to be rendered by the correct font.
+    MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+    if(getScripts)
+    {
+      // Retrieves the scripts used in the text.
+      multilanguageSupport.SetScripts(utf32Characters,
+                                      startIndex,
+                                      requestedNumberOfCharacters,
+                                      scripts);
+    }
+
+    if(validateFonts)
+    {
+      // Validate the fonts set through the mark-up string.
+      Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
+
+      // Get the default font's description.
+      TextAbstraction::FontDescription defaultFontDescription;
+      TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
+
+      //Get the number of points per one unit of point-size
+      uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
+
+      if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
+      {
+        // If the placeholder font is set specifically, only placeholder font is changed.
+        defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
+        if(impl.mEventData->mPlaceholderFont->sizeDefined)
+        {
+          defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
+        }
+      }
+      else if(nullptr != impl.mFontDefaults)
+      {
+        // Set the normal font and the placeholder font.
+        defaultFontDescription = impl.mFontDefaults->mFontDescription;
+
+        if(impl.mTextFitEnabled)
+        {
+          defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
+        }
+        else
+        {
+          defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
+        }
+      }
+
+      // Validates the fonts. If there is a character with no assigned font it sets a default one.
+      // After this call, fonts are validated.
+      multilanguageSupport.ValidateFonts(utf32Characters,
+                                         scripts,
+                                         fontDescriptionRuns,
+                                         defaultFontDescription,
+                                         defaultPointSize,
+                                         startIndex,
+                                         requestedNumberOfCharacters,
+                                         validFonts);
+    }
+    updated = true;
+  }
+
+  Vector<Character> mirroredUtf32Characters;
+  bool              textMirrored       = false;
+  const Length      numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
+  if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
+  {
+    Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
+    bidirectionalInfo.Reserve(numberOfParagraphs);
+
+    // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
+    SetBidirectionalInfo(utf32Characters,
+                         scripts,
+                         lineBreakInfo,
+                         startIndex,
+                         requestedNumberOfCharacters,
+                         bidirectionalInfo,
+                         (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
+                         impl.mLayoutDirection);
+
+    if(0u != bidirectionalInfo.Count())
+    {
+      // Only set the character directions if there is right to left characters.
+      Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
+      GetCharactersDirection(bidirectionalInfo,
+                             numberOfCharacters,
+                             startIndex,
+                             requestedNumberOfCharacters,
+                             directions);
+
+      // This paragraph has right to left text. Some characters may need to be mirrored.
+      // TODO: consider if the mirrored string can be stored as well.
+
+      textMirrored = GetMirroredText(utf32Characters,
+                                     directions,
+                                     bidirectionalInfo,
+                                     startIndex,
+                                     requestedNumberOfCharacters,
+                                     mirroredUtf32Characters);
+    }
+    else
+    {
+      // There is no right to left characters. Clear the directions vector.
+      impl.mModel->mLogicalModel->mCharacterDirections.Clear();
+    }
+    updated = true;
+  }
+
+  Vector<GlyphInfo>&      glyphs                = impl.mModel->mVisualModel->mGlyphs;
+  Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
+  Vector<Length>&         charactersPerGlyph    = impl.mModel->mVisualModel->mCharactersPerGlyph;
+  Vector<GlyphIndex>      newParagraphGlyphs;
+  newParagraphGlyphs.Reserve(numberOfParagraphs);
+
+  const Length currentNumberOfGlyphs = glyphs.Count();
+  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
+  {
+    const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
+    // Shapes the text.
+    ShapeText(textToShape,
+              lineBreakInfo,
+              scripts,
+              validFonts,
+              startIndex,
+              impl.mTextUpdateInfo.mStartGlyphIndex,
+              requestedNumberOfCharacters,
+              glyphs,
+              glyphsToCharactersMap,
+              charactersPerGlyph,
+              newParagraphGlyphs);
+
+    // Create the 'number of glyphs' per character and the glyph to character conversion tables.
+    impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
+    impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
+
+    updated = true;
+  }
+
+  const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
+
+  if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
+  {
+    GlyphInfo* glyphsBuffer = glyphs.Begin();
+    impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
+
+    // Update the width and advance of all new paragraph characters.
+    for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
+    {
+      const GlyphIndex index = *it;
+      GlyphInfo&       glyph = *(glyphsBuffer + index);
+
+      glyph.xBearing = 0.f;
+      glyph.width    = 0.f;
+      glyph.advance  = 0.f;
+    }
+    updated = true;
+  }
+
+  if((nullptr != impl.mEventData) &&
+     impl.mEventData->mPreEditFlag &&
+     (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
+  {
+    Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
+    impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
+    Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
+
+    // Check the type of preedit and run it.
+    for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
+    {
+      Dali::InputMethodContext::PreeditAttributeData attrData = *it;
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d  start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
+      type = attrData.preeditType;
+
+      // Check the number of commit characters for the start position.
+      unsigned int numberOfCommit  = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
+      Length       numberOfIndices = attrData.endIndex - attrData.startIndex;
+
+      switch(type)
+      {
+        case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
+        {
+          // Add the underline for the pre-edit text.
+          UnderlinedGlyphRun underlineRun;
+          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
+          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
+          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::REVERSE:
+        {
+          Vector4  textColor = impl.mModel->mVisualModel->GetTextColor();
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = textColor;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
+          if(backgroundColor.a == 0) // There is no text background color.
+          {
+            // Try use the control's background color.
+            if(nullptr != impl.mEditableControlInterface)
+            {
+              impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
+              if(backgroundColor.a == 0) // There is no control background color.
+              {
+                // Determines black or white color according to text color.
+                // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
+                float L         = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
+                backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
+              }
+            }
+          }
+
+          Vector<ColorRun> colorRuns;
+          colorRuns.Resize(1u);
+          ColorRun& colorRun                       = *(colorRuns.Begin());
+          colorRun.color                           = backgroundColor;
+          colorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          colorRun.characterRun.numberOfCharacters = numberOfIndices;
+          impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
+        {
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = LIGHT_BLUE;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
+        {
+          // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = BACKGROUND_SUB4;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          UnderlinedGlyphRun underlineRun;
+          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
+          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
+          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
+        {
+          // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = BACKGROUND_SUB5;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          UnderlinedGlyphRun underlineRun;
+          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
+          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
+          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
+        {
+          // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = BACKGROUND_SUB6;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          UnderlinedGlyphRun underlineRun;
+          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
+          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
+          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
+        {
+          // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
+          ColorRun backgroundColorRun;
+          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
+          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
+          backgroundColorRun.color                           = BACKGROUND_SUB7;
+          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
+
+          UnderlinedGlyphRun underlineRun;
+          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
+          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
+          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
+
+          //Mark-up processor case
+          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+          {
+            impl.CopyUnderlinedFromLogicalToVisualModels(false);
+          }
+          break;
+        }
+        case Dali::InputMethodContext::PreeditStyle::NONE:
+        default:
+        {
+          break;
+        }
+      }
+    }
+    attrs.Clear();
+    updated = true;
+  }
+
+  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
+  {
+    // Set the color runs in glyphs.
+    SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
+                             impl.mModel->mVisualModel->mCharactersToGlyph,
+                             impl.mModel->mVisualModel->mGlyphsPerCharacter,
+                             startIndex,
+                             impl.mTextUpdateInfo.mStartGlyphIndex,
+                             requestedNumberOfCharacters,
+                             impl.mModel->mVisualModel->mColors,
+                             impl.mModel->mVisualModel->mColorIndices);
+
+    // Set the background color runs in glyphs.
+    SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
+                             impl.mModel->mVisualModel->mCharactersToGlyph,
+                             impl.mModel->mVisualModel->mGlyphsPerCharacter,
+                             startIndex,
+                             impl.mTextUpdateInfo.mStartGlyphIndex,
+                             requestedNumberOfCharacters,
+                             impl.mModel->mVisualModel->mBackgroundColors,
+                             impl.mModel->mVisualModel->mBackgroundColorIndices);
+
+    updated = true;
+  }
+
+  if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
+     !((nullptr != impl.mEventData) &&
+       impl.mEventData->mPreEditFlag &&
+       (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
+  {
+    //Mark-up processor case
+    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
+    {
+      impl.CopyUnderlinedFromLogicalToVisualModels(true);
+      impl.CopyStrikethroughFromLogicalToVisualModels();
+      impl.CopyCharacterSpacingFromLogicalToVisualModels();
+    }
+
+    updated = true;
+  }
+
+  // The estimated number of lines. Used to avoid reallocations when layouting.
+  impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
+
+  // Set the previous number of characters for the next time the text is updated.
+  impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
+
+  return updated;
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h b/dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h
new file mode 100644 (file)
index 0000000..928d8c5
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+
+namespace Dali::Toolkit::Text
+{
+
+/**
+ * Contains methods for updating the models in the TextController
+ */
+struct ControllerImplModelUpdater
+{
+  using OperationsMask = Controller::OperationsMask;
+
+  /**
+   * @brief Updates the logical and visual models. Updates the style runs in the visual model when the text's styles changes.
+   *
+   * @param[in] impl A reference to the Controller::Impl class
+   * @param[in] operationsRequired The operations required
+   * @return true if mode has been modified.
+   */
+  static bool Update(Controller::Impl& impl, OperationsMask operationsRequired);
+};
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl.cpp b/dali-toolkit/internal/text/controller/text-controller-impl.cpp
new file mode 100644 (file)
index 0000000..e5086d6
--- /dev/null
@@ -0,0 +1,1981 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/rendering/renderer.h>
+#include <cmath>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/cursor-helper-functions.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl-data-clearer.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl-model-updater.h>
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-enumerations-impl.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+#include <dali-toolkit/internal/text/text-selection-handle-controller.h>
+#include <dali-toolkit/internal/text/underlined-glyph-run.h>
+
+using namespace Dali;
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
+
+const std::string EMPTY_STRING("");
+
+} // namespace
+
+namespace Dali::Toolkit::Text
+{
+namespace
+{
+void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const fontDefaults, const Vector4& textColor)
+{
+  // Sets the default text's color.
+  inputStyle.textColor      = textColor;
+  inputStyle.isDefaultColor = true;
+
+  inputStyle.familyName.clear();
+  inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
+  inputStyle.width  = TextAbstraction::FontWidth::NORMAL;
+  inputStyle.slant  = TextAbstraction::FontSlant::NORMAL;
+  inputStyle.size   = 0.f;
+
+  inputStyle.lineSpacing = 0.f;
+
+  inputStyle.underlineProperties.clear();
+  inputStyle.shadowProperties.clear();
+  inputStyle.embossProperties.clear();
+  inputStyle.outlineProperties.clear();
+
+  inputStyle.isFamilyDefined = false;
+  inputStyle.isWeightDefined = false;
+  inputStyle.isWidthDefined  = false;
+  inputStyle.isSlantDefined  = false;
+  inputStyle.isSizeDefined   = false;
+
+  inputStyle.isLineSpacingDefined = false;
+
+  inputStyle.isUnderlineDefined = false;
+  inputStyle.isShadowDefined    = false;
+  inputStyle.isEmbossDefined    = false;
+  inputStyle.isOutlineDefined   = false;
+
+  // Sets the default font's family name, weight, width, slant and size.
+  if(fontDefaults)
+  {
+    if(fontDefaults->familyDefined)
+    {
+      inputStyle.familyName      = fontDefaults->mFontDescription.family;
+      inputStyle.isFamilyDefined = true;
+    }
+
+    if(fontDefaults->weightDefined)
+    {
+      inputStyle.weight          = fontDefaults->mFontDescription.weight;
+      inputStyle.isWeightDefined = true;
+    }
+
+    if(fontDefaults->widthDefined)
+    {
+      inputStyle.width          = fontDefaults->mFontDescription.width;
+      inputStyle.isWidthDefined = true;
+    }
+
+    if(fontDefaults->slantDefined)
+    {
+      inputStyle.slant          = fontDefaults->mFontDescription.slant;
+      inputStyle.isSlantDefined = true;
+    }
+
+    if(fontDefaults->sizeDefined)
+    {
+      inputStyle.size          = fontDefaults->mDefaultPointSize;
+      inputStyle.isSizeDefined = true;
+    }
+  }
+}
+
+void ChangeTextControllerState(Controller::Impl& impl, EventData::State newState)
+{
+  EventData* eventData = impl.mEventData;
+
+  if(nullptr == eventData)
+  {
+    // Nothing to do if there is no text input.
+    return;
+  }
+
+  DecoratorPtr& decorator = eventData->mDecorator;
+  if(!decorator)
+  {
+    // Nothing to do if there is no decorator.
+    return;
+  }
+
+  DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d  newstate:%d\n", eventData->mState, newState);
+
+  if(eventData->mState != newState)
+  {
+    eventData->mPreviousState = eventData->mState;
+    eventData->mState         = newState;
+
+    switch(eventData->mState)
+    {
+      case EventData::INACTIVE:
+      {
+        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+        decorator->StopCursorBlink();
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+        decorator->SetPopupActive(false);
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::INTERRUPTED:
+      {
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+        decorator->SetPopupActive(false);
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::SELECTING:
+      {
+        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+        decorator->StopCursorBlink();
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
+          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
+        }
+        decorator->SetHighlightActive(true);
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          impl.SetPopupButtons();
+          decorator->SetPopupActive(true);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::EDITING:
+      {
+        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+        if(eventData->mCursorBlinkEnabled)
+        {
+          decorator->StartCursorBlink();
+        }
+        // Grab handle is not shown until a tap is received whilst EDITING
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          decorator->SetPopupActive(false);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+      case EventData::EDITING_WITH_POPUP:
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
+
+        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+        if(eventData->mCursorBlinkEnabled)
+        {
+          decorator->StartCursorBlink();
+        }
+        if(eventData->mSelectionEnabled)
+        {
+          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+          decorator->SetHighlightActive(false);
+        }
+        else if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(GRAB_HANDLE, true);
+        }
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          impl.SetPopupButtons();
+          decorator->SetPopupActive(true);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+      case EventData::EDITING_WITH_GRAB_HANDLE:
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
+
+        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+        if(eventData->mCursorBlinkEnabled)
+        {
+          decorator->StartCursorBlink();
+        }
+        // Grab handle is not shown until a tap is received whilst EDITING
+        if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(GRAB_HANDLE, true);
+        }
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          decorator->SetPopupActive(false);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::SELECTION_HANDLE_PANNING:
+      {
+        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+        decorator->StopCursorBlink();
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
+          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
+        }
+        decorator->SetHighlightActive(true);
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          decorator->SetPopupActive(false);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::GRAB_HANDLE_PANNING:
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
+
+        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+        if(eventData->mCursorBlinkEnabled)
+        {
+          decorator->StartCursorBlink();
+        }
+        if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(GRAB_HANDLE, true);
+        }
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          decorator->SetPopupActive(false);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::EDITING_WITH_PASTE_POPUP:
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
+
+        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+        if(eventData->mCursorBlinkEnabled)
+        {
+          decorator->StartCursorBlink();
+        }
+
+        if(eventData->mGrabHandleEnabled)
+        {
+          decorator->SetHandleActive(GRAB_HANDLE, true);
+        }
+        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+        decorator->SetHighlightActive(false);
+
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          impl.SetPopupButtons();
+          decorator->SetPopupActive(true);
+        }
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+
+      case EventData::TEXT_PANNING:
+      {
+        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+        decorator->StopCursorBlink();
+        decorator->SetHandleActive(GRAB_HANDLE, false);
+        if(eventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
+           decorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
+        {
+          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+          decorator->SetHighlightActive(true);
+        }
+
+        if(eventData->mGrabHandlePopupEnabled)
+        {
+          decorator->SetPopupActive(false);
+        }
+
+        eventData->mDecoratorUpdated = true;
+        break;
+      }
+    }
+  }
+}
+
+void UpdateCursorPositionForAlignment(Controller::Impl& impl, bool needFullAlignment)
+{
+  EventData* eventData = impl.mEventData;
+
+  // Set the flag to redo the alignment operation
+  impl.mOperationsPending = static_cast<Controller::OperationsMask>(impl.mOperationsPending | Controller::OperationsMask::ALIGN);
+
+  if(eventData)
+  {
+    // Note: mUpdateAlignment is currently only needed for horizontal alignment
+    eventData->mUpdateAlignment = needFullAlignment;
+
+    // Update the cursor if it's in editing mode
+    if(EventData::IsEditingState(eventData->mState))
+    {
+      impl.ChangeState(EventData::EDITING);
+      eventData->mUpdateCursorPosition = true;
+    }
+  }
+}
+
+} // unnamed Namespace
+
+EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
+: mDecorator(decorator),
+  mInputMethodContext(inputMethodContext),
+  mPlaceholderFont(nullptr),
+  mPlaceholderTextActive(),
+  mPlaceholderTextInactive(),
+  mPlaceholderTextColor(0.8f, 0.8f, 0.8f, 0.8f), // This color has been published in the Public API (placeholder-properties.h).
+  mEventQueue(),
+  mInputStyleChangedQueue(),
+  mPreviousState(INACTIVE),
+  mState(INACTIVE),
+  mPrimaryCursorPosition(0u),
+  mLeftSelectionPosition(0u),
+  mRightSelectionPosition(0u),
+  mPreEditStartPosition(0u),
+  mPreEditLength(0u),
+  mCursorHookPositionX(0.f),
+  mDoubleTapAction(Controller::NoTextTap::NO_ACTION),
+  mLongPressAction(Controller::NoTextTap::SHOW_SELECTION_POPUP),
+  mIsShowingPlaceholderText(false),
+  mPreEditFlag(false),
+  mDecoratorUpdated(false),
+  mCursorBlinkEnabled(true),
+  mGrabHandleEnabled(true),
+  mGrabHandlePopupEnabled(true),
+  mSelectionEnabled(true),
+  mUpdateCursorHookPosition(false),
+  mUpdateCursorPosition(false),
+  mUpdateGrabHandlePosition(false),
+  mUpdateLeftSelectionPosition(false),
+  mUpdateRightSelectionPosition(false),
+  mIsLeftHandleSelected(false),
+  mIsRightHandleSelected(false),
+  mUpdateHighlightBox(false),
+  mScrollAfterUpdatePosition(false),
+  mScrollAfterDelete(false),
+  mAllTextSelected(false),
+  mUpdateInputStyle(false),
+  mPasswordInput(false),
+  mCheckScrollAmount(false),
+  mIsPlaceholderPixelSize(false),
+  mIsPlaceholderElideEnabled(false),
+  mPlaceholderEllipsisFlag(false),
+  mShiftSelectionFlag(true),
+  mUpdateAlignment(false),
+  mEditingEnabled(true)
+{
+}
+
+bool Controller::Impl::ProcessInputEvents()
+{
+  return ControllerImplEventHandler::ProcessInputEvents(*this);
+}
+
+void Controller::Impl::NotifyInputMethodContext()
+{
+  if(mEventData && mEventData->mInputMethodContext)
+  {
+    CharacterIndex cursorPosition = GetLogicalCursorPosition();
+
+    const Length numberOfWhiteSpaces = GetNumberOfWhiteSpaces(0u);
+
+    // Update the cursor position by removing the initial white spaces.
+    if(cursorPosition < numberOfWhiteSpaces)
+    {
+      cursorPosition = 0u;
+    }
+    else
+    {
+      cursorPosition -= numberOfWhiteSpaces;
+    }
+
+    mEventData->mInputMethodContext.SetCursorPosition(cursorPosition);
+    mEventData->mInputMethodContext.NotifyCursorPosition();
+  }
+}
+
+void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
+{
+  if(mEventData && mEventData->mInputMethodContext)
+  {
+    Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
+    mEventData->mInputMethodContext.NotifyTextInputMultiLine(layout == Text::Layout::Engine::MULTI_LINE_BOX);
+  }
+}
+
+CharacterIndex Controller::Impl::GetLogicalCursorPosition() const
+{
+  CharacterIndex cursorPosition = 0u;
+
+  if(mEventData)
+  {
+    if((EventData::SELECTING == mEventData->mState) ||
+       (EventData::SELECTION_HANDLE_PANNING == mEventData->mState))
+    {
+      cursorPosition = std::min(mEventData->mRightSelectionPosition, mEventData->mLeftSelectionPosition);
+    }
+    else
+    {
+      cursorPosition = mEventData->mPrimaryCursorPosition;
+    }
+  }
+
+  return cursorPosition;
+}
+
+Length Controller::Impl::GetNumberOfWhiteSpaces(CharacterIndex index) const
+{
+  Length numberOfWhiteSpaces = 0u;
+
+  // Get the buffer to the text.
+  Character* utf32CharacterBuffer = mModel->mLogicalModel->mText.Begin();
+
+  const Length totalNumberOfCharacters = mModel->mLogicalModel->mText.Count();
+  for(; index < totalNumberOfCharacters; ++index, ++numberOfWhiteSpaces)
+  {
+    if(!TextAbstraction::IsWhiteSpace(*(utf32CharacterBuffer + index)))
+    {
+      break;
+    }
+  }
+
+  return numberOfWhiteSpaces;
+}
+
+void Controller::Impl::GetText(std::string& text) const
+{
+  if(!IsShowingPlaceholderText())
+  {
+    // Retrieves the text string.
+    GetText(0u, text);
+  }
+  else
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
+  }
+}
+
+void Controller::Impl::GetText(CharacterIndex index, std::string& text) const
+{
+  // Get the total number of characters.
+  Length numberOfCharacters = mModel->mLogicalModel->mText.Count();
+
+  // Retrieve the text.
+  if(0u != numberOfCharacters)
+  {
+    Utf32ToUtf8(mModel->mLogicalModel->mText.Begin() + index, numberOfCharacters - index, text);
+  }
+}
+
+Dali::LayoutDirection::Type Controller::Impl::GetLayoutDirection(Dali::Actor& actor) const
+{
+  if(mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
+     (mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mIsLayoutDirectionChanged))
+  {
+    Window window = DevelWindow::Get(actor);
+    return static_cast<Dali::LayoutDirection::Type>(window ? window.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>() : LayoutDirection::LEFT_TO_RIGHT);
+  }
+  else
+  {
+    return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+  }
+}
+
+Toolkit::DevelText::TextDirection::Type Controller::Impl::GetTextDirection()
+{
+  if(mUpdateTextDirection)
+  {
+    // Operations that can be done only once until the text changes.
+    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
+                                                                          GET_SCRIPTS |
+                                                                          VALIDATE_FONTS |
+                                                                          GET_LINE_BREAKS |
+                                                                          BIDI_INFO |
+                                                                          SHAPE_TEXT |
+                                                                          GET_GLYPH_METRICS);
+
+    // Set the update info to relayout the whole text.
+    mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
+    mTextUpdateInfo.mRequestedNumberOfCharacters = mModel->mLogicalModel->mText.Count();
+
+    // Make sure the model is up-to-date before layouting
+    UpdateModel(onlyOnceOperations);
+
+    Vector3 naturalSize;
+    Relayouter::DoRelayout(*this,
+                           Size(MAX_FLOAT, MAX_FLOAT),
+                           static_cast<OperationsMask>(onlyOnceOperations |
+                                                       LAYOUT | REORDER | UPDATE_DIRECTION),
+                           naturalSize.GetVectorXY());
+
+    // Do not do again the only once operations.
+    mOperationsPending = static_cast<OperationsMask>(mOperationsPending & ~onlyOnceOperations);
+
+    // Clear the update info. This info will be set the next time the text is updated.
+    mTextUpdateInfo.Clear();
+
+    // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
+    mTextUpdateInfo.mFullRelayoutNeeded = true;
+
+    mUpdateTextDirection = false;
+  }
+
+  return mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
+}
+
+void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
+{
+  mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+  mTextUpdateInfo.mStartGlyphIndex         = 0u;
+  mTextUpdateInfo.mStartLineIndex          = 0u;
+  numberOfCharacters                       = 0u;
+
+  const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
+  if(0u == numberOfParagraphs)
+  {
+    mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+    numberOfCharacters                       = 0u;
+
+    mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+
+    // Nothing else to do if there are no paragraphs.
+    return;
+  }
+
+  // Find the paragraphs to be updated.
+  Vector<ParagraphRunIndex> paragraphsToBeUpdated;
+  if(mTextUpdateInfo.mCharacterIndex >= mTextUpdateInfo.mPreviousNumberOfCharacters)
+  {
+    // Text is being added at the end of the current text.
+    if(mTextUpdateInfo.mIsLastCharacterNewParagraph)
+    {
+      // Text is being added in a new paragraph after the last character of the text.
+      mTextUpdateInfo.mParagraphCharacterIndex     = mTextUpdateInfo.mPreviousNumberOfCharacters;
+      numberOfCharacters                           = 0u;
+      mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+
+      mTextUpdateInfo.mStartGlyphIndex = mModel->mVisualModel->mGlyphs.Count();
+      mTextUpdateInfo.mStartLineIndex  = mModel->mVisualModel->mLines.Count() - 1u;
+
+      // Nothing else to do;
+      return;
+    }
+
+    paragraphsToBeUpdated.PushBack(numberOfParagraphs - 1u);
+  }
+  else
+  {
+    Length numberOfCharactersToUpdate = 0u;
+    if(mTextUpdateInfo.mFullRelayoutNeeded)
+    {
+      numberOfCharactersToUpdate = mTextUpdateInfo.mPreviousNumberOfCharacters;
+    }
+    else
+    {
+      numberOfCharactersToUpdate = (mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) ? mTextUpdateInfo.mNumberOfCharactersToRemove : 1u;
+    }
+    mModel->mLogicalModel->FindParagraphs(mTextUpdateInfo.mCharacterIndex,
+                                          numberOfCharactersToUpdate,
+                                          paragraphsToBeUpdated);
+  }
+
+  if(0u != paragraphsToBeUpdated.Count())
+  {
+    const ParagraphRunIndex firstParagraphIndex = *(paragraphsToBeUpdated.Begin());
+    const ParagraphRun&     firstParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + firstParagraphIndex);
+    mTextUpdateInfo.mParagraphCharacterIndex    = firstParagraph.characterRun.characterIndex;
+
+    ParagraphRunIndex   lastParagraphIndex = *(paragraphsToBeUpdated.End() - 1u);
+    const ParagraphRun& lastParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex);
+
+    if((mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) &&                                           // Some character are removed.
+       (lastParagraphIndex < numberOfParagraphs - 1u) &&                                               // There is a next paragraph.
+       ((lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters) == // The last removed character is the new paragraph character.
+        (mTextUpdateInfo.mCharacterIndex + mTextUpdateInfo.mNumberOfCharactersToRemove)))
+    {
+      // The new paragraph character of the last updated paragraph has been removed so is going to be merged with the next one.
+      const ParagraphRun& lastParagraph = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex + 1u);
+
+      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
+    }
+    else
+    {
+      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
+    }
+  }
+
+  mTextUpdateInfo.mRequestedNumberOfCharacters = numberOfCharacters + mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+  mTextUpdateInfo.mStartGlyphIndex             = *(mModel->mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex);
+}
+
+void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
+{
+  ControllerImplDataClearer::ClearModelData(*this, startIndex, endIndex, operations);
+}
+
+bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
+{
+  return ControllerImplModelUpdater::Update(*this, operationsRequired);
+}
+
+void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle)
+{
+  SetDefaultInputStyle(inputStyle, mFontDefaults, mTextColor);
+}
+
+float Controller::Impl::GetDefaultFontLineHeight()
+{
+  FontId defaultFontId = 0u;
+  if(nullptr == mFontDefaults)
+  {
+    TextAbstraction::FontDescription fontDescription;
+    defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * GetFontSizeScale());
+  }
+  else
+  {
+    defaultFontId = mFontDefaults->GetFontId(mFontClient, mFontDefaults->mDefaultPointSize * GetFontSizeScale());
+  }
+
+  Text::FontMetrics fontMetrics;
+  mMetrics->GetFontMetrics(defaultFontId, fontMetrics);
+
+  return (fontMetrics.ascender - fontMetrics.descender);
+}
+
+bool Controller::Impl::SetDefaultLineSpacing(float lineSpacing)
+{
+  if(std::fabs(lineSpacing - mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
+  {
+    mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
+
+    RelayoutAllCharacters();
+    return true;
+  }
+  return false;
+}
+
+bool Controller::Impl::SetDefaultLineSize(float lineSize)
+{
+  if(std::fabs(lineSize - mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
+  {
+    mLayoutEngine.SetDefaultLineSize(lineSize);
+
+    RelayoutAllCharacters();
+    return true;
+  }
+  return false;
+}
+
+bool Controller::Impl::SetRelativeLineSize(float relativeLineSize)
+{
+  if(std::fabs(relativeLineSize - GetRelativeLineSize()) > Math::MACHINE_EPSILON_1000)
+  {
+    mLayoutEngine.SetRelativeLineSize(relativeLineSize);
+
+    RelayoutAllCharacters();
+    return true;
+  }
+  return false;
+}
+
+float Controller::Impl::GetRelativeLineSize()
+{
+  return mLayoutEngine.GetRelativeLineSize();
+}
+
+string Controller::Impl::GetSelectedText()
+{
+  string text;
+  if(EventData::SELECTING == mEventData->mState)
+  {
+    RetrieveSelection(text, false);
+  }
+  return text;
+}
+
+string Controller::Impl::CopyText()
+{
+  string text;
+  RetrieveSelection(text, false);
+  SendSelectionToClipboard(false); // Text not modified
+
+  mEventData->mUpdateCursorPosition = true;
+
+  RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
+
+  return text;
+}
+
+string Controller::Impl::CutText()
+{
+  string text;
+  RetrieveSelection(text, false);
+
+  if(!IsEditable())
+  {
+    return EMPTY_STRING;
+  }
+
+  SendSelectionToClipboard(true); // Synchronous call to modify text
+  mOperationsPending = ALL_OPERATIONS;
+
+  if((0u != mModel->mLogicalModel->mText.Count()) ||
+     !IsPlaceholderAvailable())
+  {
+    QueueModifyEvent(ModifyEvent::TEXT_DELETED);
+  }
+  else
+  {
+    PlaceholderHandler::ShowPlaceholderText(*this);
+  }
+
+  mEventData->mUpdateCursorPosition = true;
+  mEventData->mScrollAfterDelete    = true;
+
+  RequestRelayout();
+
+  if(nullptr != mEditableControlInterface)
+  {
+    mEditableControlInterface->TextChanged(true);
+  }
+  return text;
+}
+
+void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
+{
+  if(nullptr == mEventData)
+  {
+    // Nothing to do if there is no text.
+    return;
+  }
+
+  if(mEventData->mSelectionEnabled && (pStart || pEnd))
+  {
+    uint32_t length   = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+    uint32_t oldStart = mEventData->mLeftSelectionPosition;
+    uint32_t oldEnd   = mEventData->mRightSelectionPosition;
+
+    if(pStart)
+    {
+      mEventData->mLeftSelectionPosition = std::min(*pStart, length);
+    }
+    if(pEnd)
+    {
+      mEventData->mRightSelectionPosition = std::min(*pEnd, length);
+    }
+
+    if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
+    {
+      ChangeState(EventData::EDITING);
+      mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
+      mEventData->mUpdateCursorPosition                                       = true;
+    }
+    else
+    {
+      ChangeState(EventData::SELECTING);
+      mEventData->mUpdateHighlightBox           = true;
+      mEventData->mUpdateLeftSelectionPosition  = true;
+      mEventData->mUpdateRightSelectionPosition = true;
+    }
+
+    if(mSelectableControlInterface != nullptr)
+    {
+      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+    }
+  }
+}
+
+CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
+{
+  if(nullptr == mEventData)
+  {
+    return 0;
+  }
+  return mEventData->mPrimaryCursorPosition;
+}
+
+bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
+{
+  if(nullptr == mEventData)
+  {
+    // Nothing to do if there is no text.
+    return false;
+  }
+
+  if(mEventData->mPrimaryCursorPosition == index && mEventData->mState != EventData::SELECTING)
+  {
+    // Nothing for same cursor position.
+    return false;
+  }
+
+  uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
+  uint32_t oldCursorPos              = mEventData->mPrimaryCursorPosition;
+  mEventData->mPrimaryCursorPosition = std::min(index, length);
+  // If there is no focus, only the value is updated.
+  if(focused)
+  {
+    bool     wasInSelectingState = mEventData->mState == EventData::SELECTING;
+    uint32_t oldStart            = mEventData->mLeftSelectionPosition;
+    uint32_t oldEnd              = mEventData->mRightSelectionPosition;
+    ChangeState(EventData::EDITING);
+    mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
+    mEventData->mUpdateCursorPosition                                        = true;
+
+    if(mSelectableControlInterface != nullptr && wasInSelectingState)
+    {
+      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
+    }
+
+    ScrollTextToMatchCursor();
+  }
+
+  if(nullptr != mEditableControlInterface)
+  {
+    mEditableControlInterface->CursorPositionChanged(oldCursorPos, mEventData->mPrimaryCursorPosition);
+  }
+
+  return true;
+}
+
+Uint32Pair Controller::Impl::GetTextSelectionRange() const
+{
+  Uint32Pair range;
+
+  if(mEventData)
+  {
+    range.first  = mEventData->mLeftSelectionPosition;
+    range.second = mEventData->mRightSelectionPosition;
+  }
+
+  return range;
+}
+
+bool Controller::Impl::IsEditable() const
+{
+  return mEventData && mEventData->mEditingEnabled;
+}
+
+void Controller::Impl::SetEditable(bool editable)
+{
+  if(mEventData)
+  {
+    mEventData->mEditingEnabled = editable;
+
+    if(mEventData->mDecorator)
+    {
+      bool decoratorEditable = editable && mIsUserInteractionEnabled;
+      mEventData->mDecorator->SetEditable(decoratorEditable);
+    }
+  }
+}
+
+void Controller::Impl::UpdateAfterFontChange(const std::string& newDefaultFont)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
+
+  if(!mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
+    mFontDefaults->mFontDescription.family = newDefaultFont;
+
+    ClearFontData();
+
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
+{
+  if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
+  {
+    // Nothing to select if handles are in the same place.
+    selectedText.clear();
+    return;
+  }
+
+  const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
+
+  //Get start and end position of selection
+  const CharacterIndex startOfSelectedText  = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
+  const Length         lengthOfSelectedText = (handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition) - startOfSelectedText;
+
+  Vector<Character>& utf32Characters    = mModel->mLogicalModel->mText;
+  const Length       numberOfCharacters = utf32Characters.Count();
+
+  // Validate the start and end selection points
+  if((startOfSelectedText + lengthOfSelectedText) <= numberOfCharacters)
+  {
+    //Get text as a UTF8 string
+    Utf32ToUtf8(&utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText);
+
+    if(deleteAfterRetrieval) // Only delete text if copied successfully
+    {
+      // Keep a copy of the current input style.
+      InputStyle currentInputStyle;
+      currentInputStyle.Copy(mEventData->mInputStyle);
+
+      // Set as input style the style of the first deleted character.
+      mModel->mLogicalModel->RetrieveStyle(startOfSelectedText, mEventData->mInputStyle);
+
+      // Compare if the input style has changed.
+      const bool hasInputStyleChanged = !currentInputStyle.Equal(mEventData->mInputStyle);
+
+      if(hasInputStyleChanged)
+      {
+        const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mEventData->mInputStyle);
+        // Queue the input style changed signal.
+        mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
+      }
+
+      mModel->mLogicalModel->UpdateTextStyleRuns(startOfSelectedText, -static_cast<int>(lengthOfSelectedText));
+
+      // Mark the paragraphs to be updated.
+      if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
+      {
+        mTextUpdateInfo.mCharacterIndex             = 0;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+        mTextUpdateInfo.mNumberOfCharactersToAdd    = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
+        mTextUpdateInfo.mClearAll                   = true;
+      }
+      else
+      {
+        mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+      }
+
+      // Delete text between handles
+      Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
+      Vector<Character>::Iterator last  = first + lengthOfSelectedText;
+      utf32Characters.Erase(first, last);
+
+      // Will show the cursor at the first character of the selection.
+      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
+    }
+    else
+    {
+      // Will show the cursor at the last character of the selection.
+      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
+    }
+
+    mEventData->mDecoratorUpdated = true;
+  }
+}
+
+void Controller::Impl::SetSelection(int start, int end)
+{
+  uint32_t oldStart = mEventData->mLeftSelectionPosition;
+  uint32_t oldEnd   = mEventData->mRightSelectionPosition;
+
+  mEventData->mLeftSelectionPosition  = start;
+  mEventData->mRightSelectionPosition = end;
+  mEventData->mUpdateCursorPosition   = true;
+
+  if(mSelectableControlInterface != nullptr)
+  {
+    mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
+  }
+}
+
+std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
+{
+  return {mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition};
+}
+
+void Controller::Impl::ShowClipboard()
+{
+  if(mClipboard)
+  {
+    mClipboard.ShowClipboard();
+  }
+}
+
+void Controller::Impl::HideClipboard()
+{
+  if(mClipboard && mClipboardHideEnabled)
+  {
+    mClipboard.HideClipboard();
+  }
+}
+
+void Controller::Impl::SetClipboardHideEnable(bool enable)
+{
+  mClipboardHideEnabled = enable;
+}
+
+bool Controller::Impl::CopyStringToClipboard(const std::string& source)
+{
+  //Send string to clipboard
+  return (mClipboard && mClipboard.SetItem(source));
+}
+
+void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
+{
+  std::string selectedText;
+  RetrieveSelection(selectedText, deleteAfterSending);
+  CopyStringToClipboard(selectedText);
+  ChangeState(EventData::EDITING);
+}
+
+void Controller::Impl::RequestGetTextFromClipboard()
+{
+  if(mClipboard)
+  {
+    mClipboard.RequestItem();
+  }
+}
+
+void Controller::Impl::RepositionSelectionHandles()
+{
+  SelectionHandleController::Reposition(*this);
+}
+void Controller::Impl::RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action)
+{
+  SelectionHandleController::Reposition(*this, visualX, visualY, action);
+}
+
+void Controller::Impl::SetPopupButtons()
+{
+  /**
+   *  Sets the Popup buttons to be shown depending on State.
+   *
+   *  If SELECTING :  CUT & COPY + ( PASTE & CLIPBOARD if content available to paste )
+   *
+   *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
+   */
+
+  bool                        isEditable    = IsEditable();
+  TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
+
+  if(EventData::SELECTING == mEventData->mState)
+  {
+    buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::COPY);
+    if(isEditable)
+    {
+      buttonsToShow = TextSelectionPopup::Buttons(buttonsToShow | TextSelectionPopup::CUT);
+    }
+
+    if(!IsClipboardEmpty())
+    {
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
+      }
+      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
+    }
+
+    if(!mEventData->mAllTextSelected)
+    {
+      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::SELECT_ALL));
+    }
+  }
+  else if(EventData::EDITING_WITH_POPUP == mEventData->mState)
+  {
+    if(mModel->mLogicalModel->mText.Count() && !IsShowingPlaceholderText())
+    {
+      buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL);
+    }
+
+    if(!IsClipboardEmpty())
+    {
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
+      }
+      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
+    }
+  }
+  else if(EventData::EDITING_WITH_PASTE_POPUP == mEventData->mState)
+  {
+    if(!IsClipboardEmpty())
+    {
+      if(isEditable)
+      {
+        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
+      }
+      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
+    }
+  }
+
+  mEventData->mDecorator->SetEnabledPopupButtons(buttonsToShow);
+}
+
+void Controller::Impl::ChangeState(EventData::State newState)
+{
+  ChangeTextControllerState(*this, newState);
+}
+
+void Controller::Impl::GetCursorPosition(CharacterIndex logical,
+                                         CursorInfo&    cursorInfo)
+{
+  if(!IsShowingRealText())
+  {
+    // Do not want to use the place-holder text to set the cursor position.
+
+    // Use the line's height of the font's family set to set the cursor's size.
+    // If there is no font's family set, use the default font.
+    // Use the current alignment to place the cursor at the beginning, center or end of the box.
+
+    cursorInfo.lineOffset          = 0.f;
+    cursorInfo.lineHeight          = GetDefaultFontLineHeight();
+    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
+
+    bool isRTL = false;
+    if(mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS)
+    {
+      isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
+    }
+
+    switch(mModel->mHorizontalAlignment)
+    {
+      case Text::HorizontalAlignment::BEGIN:
+      {
+        if(isRTL)
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
+        break;
+      }
+      case Text::HorizontalAlignment::CENTER:
+      {
+        cursorInfo.primaryPosition.x = floorf(0.5f * mModel->mVisualModel->mControlSize.width);
+        break;
+      }
+      case Text::HorizontalAlignment::END:
+      {
+        if(isRTL)
+        {
+          cursorInfo.primaryPosition.x = 0.f;
+        }
+        else
+        {
+          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
+        }
+        break;
+      }
+    }
+
+    // Nothing else to do.
+    return;
+  }
+
+  const bool                  isMultiLine = (Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout());
+  GetCursorPositionParameters parameters;
+  parameters.visualModel  = mModel->mVisualModel;
+  parameters.logicalModel = mModel->mLogicalModel;
+  parameters.metrics      = mMetrics;
+  parameters.logical      = logical;
+  parameters.isMultiline  = isMultiLine;
+
+  float defaultFontLineHeight = GetDefaultFontLineHeight();
+
+  Text::GetCursorPosition(parameters,
+                          defaultFontLineHeight,
+                          cursorInfo);
+
+  // Adds Outline offset.
+  const float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
+  cursorInfo.primaryPosition.x += outlineWidth;
+  cursorInfo.primaryPosition.y += outlineWidth;
+  cursorInfo.secondaryPosition.x += outlineWidth;
+  cursorInfo.secondaryPosition.y += outlineWidth;
+
+  if(isMultiLine)
+  {
+    // 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 = mModel->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
+{
+  if(nullptr == mEventData)
+  {
+    // Nothing to do if there is no text input.
+    return 0u;
+  }
+
+  CharacterIndex cursorIndex = mEventData->mPrimaryCursorPosition;
+
+  const GlyphIndex* const charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
+  const Length* const     charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
+
+  GlyphIndex glyphIndex         = *(charactersToGlyphBuffer + index);
+  Length     numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
+
+  if(numberOfCharacters > 1u)
+  {
+    const Script script = mModel->mLogicalModel->GetScript(index);
+    if(HasLigatureMustBreak(script))
+    {
+      // Prevents to jump the whole Latin ligatures like fi, ff, or Arabic ï»», ...
+      numberOfCharacters = 1u;
+    }
+  }
+  else
+  {
+    while(0u == numberOfCharacters)
+    {
+      ++glyphIndex;
+      numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
+    }
+  }
+
+  if(index < mEventData->mPrimaryCursorPosition)
+  {
+    cursorIndex -= numberOfCharacters;
+  }
+  else
+  {
+    cursorIndex += numberOfCharacters;
+  }
+
+  // Will update the cursor hook position.
+  mEventData->mUpdateCursorHookPosition = true;
+
+  return cursorIndex;
+}
+
+void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this);
+  if(nullptr == mEventData)
+  {
+    // Nothing to do if there is no text input.
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n");
+    return;
+  }
+
+  const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
+
+  mEventData->mDecorator->SetGlyphOffset(PRIMARY_CURSOR, cursorInfo.glyphOffset);
+
+  // Sets the cursor position.
+  mEventData->mDecorator->SetPosition(PRIMARY_CURSOR,
+                                      cursorPosition.x,
+                                      cursorPosition.y,
+                                      cursorInfo.primaryCursorHeight,
+                                      cursorInfo.lineHeight);
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y);
+
+  if(mEventData->mUpdateGrabHandlePosition)
+  {
+    // Sets the grab handle position.
+    mEventData->mDecorator->SetPosition(GRAB_HANDLE,
+                                        cursorPosition.x,
+                                        cursorInfo.lineOffset + mModel->mScrollPosition.y,
+                                        cursorInfo.lineHeight);
+  }
+
+  if(cursorInfo.isSecondaryCursor)
+  {
+    mEventData->mDecorator->SetPosition(SECONDARY_CURSOR,
+                                        cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x,
+                                        cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y,
+                                        cursorInfo.secondaryCursorHeight,
+                                        cursorInfo.lineHeight);
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x, cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y);
+  }
+
+  // Set which cursors are active according the state.
+  if(EventData::IsEditingState(mEventData->mState) || (EventData::GRAB_HANDLE_PANNING == mEventData->mState))
+  {
+    if(cursorInfo.isSecondaryCursor)
+    {
+      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_BOTH);
+    }
+    else
+    {
+      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
+    }
+  }
+  else
+  {
+    mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
+  }
+
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n");
+}
+
+void Controller::Impl::UpdateSelectionHandle(HandleType        handleType,
+                                             const CursorInfo& cursorInfo)
+{
+  SelectionHandleController::Update(*this, handleType, cursorInfo);
+}
+
+void Controller::Impl::ClampHorizontalScroll(const Vector2& layoutSize)
+{
+  // Clamp between -space & -alignment offset.
+
+  if(layoutSize.width > mModel->mVisualModel->mControlSize.width)
+  {
+    const float space         = (layoutSize.width - mModel->mVisualModel->mControlSize.width) + mModel->mAlignmentOffset;
+    mModel->mScrollPosition.x = (mModel->mScrollPosition.x < -space) ? -space : mModel->mScrollPosition.x;
+    mModel->mScrollPosition.x = (mModel->mScrollPosition.x > -mModel->mAlignmentOffset) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
+
+    mEventData->mDecoratorUpdated = true;
+  }
+  else
+  {
+    mModel->mScrollPosition.x = 0.f;
+  }
+}
+
+void Controller::Impl::ClampVerticalScroll(const Vector2& layoutSize)
+{
+  if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
+  {
+    // Nothing to do if the text is single line.
+    return;
+  }
+
+  // Clamp between -space & 0.
+  if(layoutSize.height > mModel->mVisualModel->mControlSize.height)
+  {
+    const float space         = (layoutSize.height - mModel->mVisualModel->mControlSize.height);
+    mModel->mScrollPosition.y = (mModel->mScrollPosition.y < -space) ? -space : mModel->mScrollPosition.y;
+    mModel->mScrollPosition.y = (mModel->mScrollPosition.y > 0.f) ? 0.f : mModel->mScrollPosition.y;
+
+    mEventData->mDecoratorUpdated = true;
+  }
+  else
+  {
+    mModel->mScrollPosition.y = 0.f;
+  }
+}
+
+void Controller::Impl::ScrollToMakePositionVisible(const Vector2& position, float lineHeight)
+{
+  const float cursorWidth = mEventData->mDecorator ? static_cast<float>(mEventData->mDecorator->GetCursorWidth()) : 0.f;
+
+  // position is in actor's coords.
+  const float positionEndX = position.x + cursorWidth;
+  const float positionEndY = position.y + lineHeight;
+
+  // Transform the position to decorator coords.
+  const float decoratorPositionBeginX = position.x + mModel->mScrollPosition.x;
+  const float decoratorPositionEndX   = positionEndX + mModel->mScrollPosition.x;
+
+  const float decoratorPositionBeginY = position.y + mModel->mScrollPosition.y;
+  const float decoratorPositionEndY   = positionEndY + mModel->mScrollPosition.y;
+
+  if(decoratorPositionBeginX < 0.f)
+  {
+    mModel->mScrollPosition.x = -position.x;
+  }
+  else if(decoratorPositionEndX > mModel->mVisualModel->mControlSize.width)
+  {
+    mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
+  }
+
+  if(Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout())
+  {
+    if(decoratorPositionBeginY < 0.f)
+    {
+      mModel->mScrollPosition.y = -position.y;
+    }
+    else if(decoratorPositionEndY > mModel->mVisualModel->mControlSize.height)
+    {
+      mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
+    }
+    else if(mModel->mLogicalModel->mText.Count() == 0u)
+    {
+      Relayouter::CalculateVerticalOffset(*this, mModel->mVisualModel->mControlSize);
+    }
+  }
+}
+
+void Controller::Impl::ScrollTextToMatchCursor(const CursorInfo& cursorInfo)
+{
+  // Get the current cursor position in decorator coords.
+  const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
+
+  const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter(mEventData->mPrimaryCursorPosition);
+
+  // Calculate the offset to match the cursor position before the character was deleted.
+  mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
+
+  //If text control has more than two lines and current line index is not last, calculate scrollpositionY
+  if(mModel->mVisualModel->mLines.Count() > 1u && lineIndex != mModel->mVisualModel->mLines.Count() - 1u)
+  {
+    const float currentCursorGlyphOffset = mEventData->mDecorator->GetGlyphOffset(PRIMARY_CURSOR);
+    mModel->mScrollPosition.y            = currentCursorPosition.y - cursorInfo.lineOffset - currentCursorGlyphOffset;
+  }
+
+  ClampHorizontalScroll(mModel->mVisualModel->GetLayoutSize());
+  ClampVerticalScroll(mModel->mVisualModel->GetLayoutSize());
+
+  // Makes the new cursor position visible if needed.
+  ScrollToMakePositionVisible(cursorInfo.primaryPosition, cursorInfo.lineHeight);
+}
+
+void Controller::Impl::ScrollTextToMatchCursor()
+{
+  CursorInfo cursorInfo;
+  GetCursorPosition(mEventData->mPrimaryCursorPosition, cursorInfo);
+  ScrollTextToMatchCursor(cursorInfo);
+}
+
+void Controller::Impl::RequestRelayout()
+{
+  if(nullptr != mControlInterface)
+  {
+    mControlInterface->RequestTextRelayout();
+  }
+}
+
+void Controller::Impl::RelayoutAllCharacters()
+{
+  // relayout all characters
+  mTextUpdateInfo.mCharacterIndex             = 0;
+  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
+  mOperationsPending                          = static_cast<OperationsMask>(mOperationsPending | LAYOUT);
+
+  mTextUpdateInfo.mFullRelayoutNeeded = true;
+
+  // Need to recalculate natural size
+  mRecalculateNaturalSize = true;
+
+  //remove selection
+  if((mEventData != nullptr) && (mEventData->mState == EventData::SELECTING))
+  {
+    ChangeState(EventData::EDITING);
+  }
+
+  RequestRelayout();
+}
+
+bool Controller::Impl::IsInputStyleChangedSignalsQueueEmpty()
+{
+  return (NULL == mEventData) || (0u == mEventData->mInputStyleChangedQueue.Count());
+}
+
+void Controller::Impl::ProcessInputStyleChangedSignals()
+{
+  if(mEventData)
+  {
+    if(mEditableControlInterface)
+    {
+      // Emit the input style changed signal for each mask
+      std::for_each(mEventData->mInputStyleChangedQueue.begin(),
+                    mEventData->mInputStyleChangedQueue.end(),
+                    [&](const auto mask) { mEditableControlInterface->InputStyleChanged(mask); });
+    }
+
+    mEventData->mInputStyleChangedQueue.Clear();
+  }
+}
+
+void Controller::Impl::ScrollBy(Vector2 scroll)
+{
+  if(mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
+  {
+    const Vector2& layoutSize    = mModel->mVisualModel->GetLayoutSize();
+    const Vector2  currentScroll = mModel->mScrollPosition;
+
+    scroll.x = -scroll.x;
+    scroll.y = -scroll.y;
+
+    if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
+    {
+      mModel->mScrollPosition.x += scroll.x;
+      ClampHorizontalScroll(layoutSize);
+    }
+
+    if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
+    {
+      mModel->mScrollPosition.y += scroll.y;
+      ClampVerticalScroll(layoutSize);
+    }
+
+    if(mModel->mScrollPosition != currentScroll)
+    {
+      mEventData->mDecorator->UpdatePositions(mModel->mScrollPosition - currentScroll);
+      RequestRelayout();
+    }
+  }
+}
+
+bool Controller::Impl::IsScrollable(const Vector2& displacement)
+{
+  bool isScrollable = false;
+  if(mEventData)
+  {
+    const bool isHorizontalScrollEnabled = mEventData->mDecorator->IsHorizontalScrollEnabled();
+    const bool isVerticalScrollEnabled   = mEventData->mDecorator->IsVerticalScrollEnabled();
+    if(isHorizontalScrollEnabled ||isVerticalScrollEnabled)
+    {
+      const Vector2& targetSize = mModel->mVisualModel->mControlSize;
+      const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
+      const Vector2& scrollPosition = mModel->mScrollPosition;
+
+      if(isHorizontalScrollEnabled)
+      {
+        const float displacementX = displacement.x;
+        const float positionX = scrollPosition.x + displacementX;
+        if(layoutSize.width > targetSize.width && -positionX > 0.f && -positionX < layoutSize.width - targetSize.width)
+        {
+          isScrollable = true;
+        }
+      }
+
+      if(isVerticalScrollEnabled)
+      {
+        const float displacementY = displacement.y;
+        const float positionY = scrollPosition.y + displacementY;
+        if(layoutSize.height > targetSize.height && -positionY > 0 && -positionY < layoutSize.height - targetSize.height)
+        {
+          isScrollable = true;
+        }
+      }
+    }
+  }
+  return isScrollable;
+}
+
+float Controller::Impl::GetHorizontalScrollPosition()
+{
+  // Scroll values are negative internally so we convert them to positive numbers
+  return mEventData ? -mModel->mScrollPosition.x : 0.0f;
+}
+
+float Controller::Impl::GetVerticalScrollPosition()
+{
+  // Scroll values are negative internally so we convert them to positive numbers
+  return mEventData ? -mModel->mScrollPosition.y : 0.0f;
+}
+
+Vector3 Controller::Impl::GetAnchorPosition(Anchor anchor) const
+{
+  //TODO
+  return Vector3(10.f, 10.f, 10.f);
+}
+
+Vector2 Controller::Impl::GetAnchorSize(Anchor anchor) const
+{
+  //TODO
+  return Vector2(10.f, 10.f);
+}
+
+Toolkit::TextAnchor Controller::Impl::CreateAnchorActor(Anchor anchor)
+{
+  auto actor = Toolkit::TextAnchor::New();
+  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  const Vector3 anchorPosition = GetAnchorPosition(anchor);
+  actor.SetProperty(Actor::Property::POSITION, anchorPosition);
+  const Vector2 anchorSize = GetAnchorSize(anchor);
+  actor.SetProperty(Actor::Property::SIZE, anchorSize);
+  std::string anchorText(mModel->mLogicalModel->mText.Begin() + anchor.startIndex, mModel->mLogicalModel->mText.Begin() + anchor.endIndex);
+  actor.SetProperty(Actor::Property::NAME, anchorText);
+  actor.SetProperty(Toolkit::TextAnchor::Property::URI, std::string(anchor.href));
+  actor.SetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX, static_cast<int>(anchor.startIndex));
+  actor.SetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX, static_cast<int>(anchor.endIndex));
+  return actor;
+}
+
+void Controller::Impl::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+  /* TODO: Now actors are created/destroyed in every "RenderText" function call. Even when we add just 1 character,
+           we need to create and destroy potentially many actors. Some optimization can be considered here.
+           Maybe a "dirty" flag in mLogicalModel? */
+  anchorActors.clear();
+  for(auto& anchor : mModel->mLogicalModel->mAnchors)
+  {
+    auto actor = CreateAnchorActor(anchor);
+    anchorActors.push_back(actor);
+  }
+}
+
+int32_t Controller::Impl::GetAnchorIndex(size_t characterOffset) const
+{
+  Vector<Anchor>::Iterator it = mModel->mLogicalModel->mAnchors.Begin();
+
+  while(it != mModel->mLogicalModel->mAnchors.End() && (it->startIndex > characterOffset || it->endIndex <= characterOffset))
+  {
+    it++;
+  }
+
+  return it == mModel->mLogicalModel->mAnchors.End() ? -1 : it - mModel->mLogicalModel->mAnchors.Begin();
+}
+
+void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
+{
+  //Underlined character runs for markup-processor
+  const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
+  const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
+  const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
+
+  if(shouldClearPreUnderlineRuns)
+  {
+    mModel->mVisualModel->mUnderlineRuns.Clear();
+  }
+
+  for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
+  {
+    CharacterIndex characterIndex     = it->characterRun.characterIndex;
+    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
+
+    if(numberOfCharacters == 0)
+    {
+      continue;
+    }
+
+    // Create one run for all glyphs of all run's characters that has same properties
+    // This enhance performance and reduce the needed memory to store glyphs-runs
+    UnderlinedGlyphRun underlineGlyphRun;
+    underlineGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
+    underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
+    //Copy properties (attributes)
+    underlineGlyphRun.properties = it->properties;
+
+    for(Length index = 1u; index < numberOfCharacters; index++)
+    {
+      underlineGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
+    }
+
+    mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
+  }
+}
+
+void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
+{
+  //Strikethrough character runs from markup-processor
+  const Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns = mModel->mLogicalModel->mStrikethroughCharacterRuns;
+  const Vector<GlyphIndex>&                charactersToGlyph          = mModel->mVisualModel->mCharactersToGlyph;
+  const Vector<Length>&                    glyphsPerCharacter         = mModel->mVisualModel->mGlyphsPerCharacter;
+
+  mModel->mVisualModel->mStrikethroughRuns.Clear();
+
+  for(Vector<StrikethroughCharacterRun>::ConstIterator it = strikethroughCharacterRuns.Begin(), endIt = strikethroughCharacterRuns.End(); it != endIt; ++it)
+  {
+    CharacterIndex characterIndex     = it->characterRun.characterIndex;
+    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
+
+    if(numberOfCharacters == 0)
+    {
+      continue;
+    }
+
+    StrikethroughGlyphRun strikethroughGlyphRun;
+    strikethroughGlyphRun.properties              = it->properties;
+    strikethroughGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
+    strikethroughGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
+
+    for(Length index = 1u; index < numberOfCharacters; index++)
+    {
+      strikethroughGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
+    }
+
+    mModel->mVisualModel->mStrikethroughRuns.PushBack(strikethroughGlyphRun);
+  }
+}
+
+void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels()
+{
+  //CharacterSpacing character runs from markup-processor
+  const Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns;
+  const Vector<GlyphIndex>&                   charactersToGlyph             = mModel->mVisualModel->mCharactersToGlyph;
+  const Vector<Length>&                       glyphsPerCharacter            = mModel->mVisualModel->mGlyphsPerCharacter;
+
+  mModel->mVisualModel->mCharacterSpacingRuns.Clear();
+
+  for(Vector<CharacterSpacingCharacterRun>::ConstIterator it = characterSpacingCharacterRuns.Begin(), endIt = characterSpacingCharacterRuns.End(); it != endIt; ++it)
+  {
+    const CharacterIndex& characterIndex     = it->characterRun.characterIndex;
+    const Length&         numberOfCharacters = it->characterRun.numberOfCharacters;
+
+    if(numberOfCharacters == 0)
+    {
+      continue;
+    }
+
+    CharacterSpacingGlyphRun characterSpacingGlyphRun;
+    characterSpacingGlyphRun.value                   = it->value;
+    characterSpacingGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
+    characterSpacingGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
+
+    for(Length index = 1u; index < numberOfCharacters; index++)
+    {
+      characterSpacingGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
+    }
+
+    mModel->mVisualModel->mCharacterSpacingRuns.PushBack(characterSpacingGlyphRun);
+  }
+}
+
+void Controller::Impl::SetAutoScrollEnabled(bool enable)
+{
+  if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
+  {
+    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+                                                     LAYOUT |
+                                                     ALIGN |
+                                                     UPDATE_LAYOUT_SIZE |
+                                                     REORDER);
+
+    if(enable)
+    {
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
+      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | UPDATE_DIRECTION);
+    }
+    else
+    {
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
+    }
+
+    mIsAutoScrollEnabled = enable;
+    RequestRelayout();
+  }
+  else
+  {
+    DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
+    mIsAutoScrollEnabled = false;
+  }
+}
+
+void Controller::Impl::SetEnableCursorBlink(bool enable)
+{
+  DALI_ASSERT_DEBUG(NULL != mEventData && "TextInput disabled");
+
+  if(mEventData)
+  {
+    mEventData->mCursorBlinkEnabled = enable;
+
+    if(!enable && mEventData->mDecorator)
+    {
+      mEventData->mDecorator->StopCursorBlink();
+    }
+  }
+}
+
+void Controller::Impl::SetMultiLineEnabled(bool enable)
+{
+  const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
+
+  if(layout != mLayoutEngine.GetLayout())
+  {
+    // Set the layout type.
+    mLayoutEngine.SetLayout(layout);
+
+    // Set the flags to redo the layout operations
+    const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
+                                                                        UPDATE_LAYOUT_SIZE |
+                                                                        ALIGN |
+                                                                        REORDER);
+
+    mTextUpdateInfo.mFullRelayoutNeeded = true;
+    mOperationsPending                  = static_cast<OperationsMask>(mOperationsPending | layoutOperations);
+
+    // Need to recalculate natural size
+    mRecalculateNaturalSize = true;
+
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
+{
+  if(alignment != mModel->mHorizontalAlignment)
+  {
+    // Set the alignment.
+    mModel->mHorizontalAlignment = alignment;
+    UpdateCursorPositionForAlignment(*this, true);
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::SetVerticalAlignment(VerticalAlignment::Type alignment)
+{
+  if(alignment != mModel->mVerticalAlignment)
+  {
+    // Set the alignment.
+    mModel->mVerticalAlignment = alignment;
+    UpdateCursorPositionForAlignment(*this, false);
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
+{
+  if(lineWrapMode != mModel->mLineWrapMode)
+  {
+    // Update Text layout for applying wrap mode
+    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+                                                     ALIGN |
+                                                     LAYOUT |
+                                                     UPDATE_LAYOUT_SIZE |
+                                                     REORDER);
+
+    if((mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
+       (mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
+    {
+      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | GET_LINE_BREAKS);
+    }
+
+    // Set the text wrap mode.
+    mModel->mLineWrapMode = lineWrapMode;
+
+    mTextUpdateInfo.mCharacterIndex             = 0u;
+    mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+    mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
+
+    // Request relayout
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::SetDefaultColor(const Vector4& color)
+{
+  mTextColor = color;
+
+  if(!IsShowingPlaceholderText())
+  {
+    mModel->mVisualModel->SetTextColor(color);
+    mModel->mLogicalModel->mColorRuns.Clear();
+    mOperationsPending = static_cast<OperationsMask>(mOperationsPending | COLOR);
+    RequestRelayout();
+  }
+}
+
+void Controller::Impl::SetUserInteractionEnabled(bool enabled)
+{
+  mIsUserInteractionEnabled = enabled;
+
+  if(mEventData && mEventData->mDecorator)
+  {
+    bool editable = mEventData->mEditingEnabled && enabled;
+    mEventData->mDecorator->SetEditable(editable);
+  }
+}
+
+void Controller::Impl::ClearFontData()
+{
+  if(mFontDefaults)
+  {
+    mFontDefaults->mFontId = 0u; // Remove old font ID
+  }
+
+  // Set flags to update the model.
+  mTextUpdateInfo.mCharacterIndex             = 0u;
+  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
+  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
+
+  mTextUpdateInfo.mClearAll           = true;
+  mTextUpdateInfo.mFullRelayoutNeeded = true;
+  mRecalculateNaturalSize             = true;
+
+  mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
+                                                   VALIDATE_FONTS |
+                                                   SHAPE_TEXT |
+                                                   BIDI_INFO |
+                                                   GET_GLYPH_METRICS |
+                                                   LAYOUT |
+                                                   UPDATE_LAYOUT_SIZE |
+                                                   REORDER |
+                                                   ALIGN);
+}
+
+void Controller::Impl::ClearStyleData()
+{
+  mModel->mLogicalModel->mColorRuns.Clear();
+  mModel->mLogicalModel->ClearFontDescriptionRuns();
+  mModel->mLogicalModel->ClearStrikethroughRuns();
+}
+
+void Controller::Impl::ResetScrollPosition()
+{
+  if(mEventData)
+  {
+    // Reset the scroll position.
+    mModel->mScrollPosition                = Vector2::ZERO;
+    mEventData->mScrollAfterUpdatePosition = true;
+  }
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller-impl.h b/dali-toolkit/internal/text/controller/text-controller-impl.h
new file mode 100644 (file)
index 0000000..faa8772
--- /dev/null
@@ -0,0 +1,1050 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/clipboard.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/public-api/rendering/shader.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
+#include <dali-toolkit/internal/text/input-style.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/text-model.h>
+#include <dali-toolkit/internal/text/text-view.h>
+#include <dali-toolkit/public-api/styling/style-manager.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+const float DEFAULT_TEXTFIT_MIN            = 10.f;
+const float DEFAULT_TEXTFIT_MAX            = 100.f;
+const float DEFAULT_TEXTFIT_STEP           = 1.f;
+const float DEFAULT_FONT_SIZE_SCALE        = 1.f;
+const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f;
+
+//Forward declarations
+struct CursorInfo;
+struct FontDefaults;
+struct ControllerImplEventHandler;
+struct ControllerImplModelUpdater;
+struct SelectionHandleController;
+
+class SelectableControlInterface;
+class AnchorControlInterface;
+
+struct Event
+{
+  // Used to queue input events until DoRelayout()
+  enum Type
+  {
+    CURSOR_KEY_EVENT,
+    TAP_EVENT,
+    PAN_EVENT,
+    LONG_PRESS_EVENT,
+    GRAB_HANDLE_EVENT,
+    LEFT_SELECTION_HANDLE_EVENT,
+    RIGHT_SELECTION_HANDLE_EVENT,
+    SELECT,
+    SELECT_ALL,
+    SELECT_NONE,
+    SELECT_RANGE,
+  };
+
+  union Param
+  {
+    int          mInt;
+    unsigned int mUint;
+    float        mFloat;
+    bool         mBool;
+  };
+
+  Event(Type eventType)
+  : type(eventType)
+  {
+    p1.mInt = 0;
+    p2.mInt = 0;
+    p3.mInt = 0;
+  }
+
+  Type  type;
+  Param p1;
+  Param p2;
+  Param p3;
+};
+
+struct EventData
+{
+  enum State
+  {
+    INACTIVE,
+    INTERRUPTED,
+    SELECTING,
+    EDITING,
+    EDITING_WITH_POPUP,
+    EDITING_WITH_GRAB_HANDLE,
+    EDITING_WITH_PASTE_POPUP,
+    GRAB_HANDLE_PANNING,
+    SELECTION_HANDLE_PANNING,
+    TEXT_PANNING
+  };
+
+  EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext);
+
+  ~EventData() = default;
+
+  static bool IsEditingState(State stateToCheck)
+  {
+    return (stateToCheck == EDITING || stateToCheck == EDITING_WITH_POPUP || stateToCheck == EDITING_WITH_GRAB_HANDLE || stateToCheck == EDITING_WITH_PASTE_POPUP);
+  }
+
+  DecoratorPtr                  mDecorator;               ///< Pointer to the decorator.
+  InputMethodContext            mInputMethodContext;      ///< The Input Method Framework Manager.
+  std::unique_ptr<FontDefaults> mPlaceholderFont;         ///< The placeholder default font.
+  std::string                   mPlaceholderTextActive;   ///< The text to display when the TextField is empty with key-input focus.
+  std::string                   mPlaceholderTextInactive; ///< The text to display when the TextField is empty and inactive.
+  Vector4                       mPlaceholderTextColor;    ///< The in/active placeholder text color.
+
+  /**
+   * This is used to delay handling events until after the model has been updated.
+   * The number of updates to the model is minimized to improve performance.
+   */
+  std::vector<Event> mEventQueue; ///< The queue of touch events etc.
+
+  Vector<InputStyle::Mask> mInputStyleChangedQueue; ///< Queue of changes in the input style. Used to emit the signal in the iddle callback.
+
+  InputStyle mInputStyle; ///< The style to be set to the new inputed text.
+
+  State mPreviousState; ///< Stores the current state before it's updated with the new one.
+  State mState;         ///< Selection mode, edit mode etc.
+
+  CharacterIndex mPrimaryCursorPosition;  ///< Index into logical model for primary cursor.
+  CharacterIndex mLeftSelectionPosition;  ///< Index into logical model for left selection handle.
+  CharacterIndex mRightSelectionPosition; ///< Index into logical model for right selection handle.
+
+  CharacterIndex mPreEditStartPosition; ///< Used to remove the pre-edit text if necessary.
+  Length         mPreEditLength;        ///< Used to remove the pre-edit text if necessary.
+
+  float mCursorHookPositionX; ///< Used to move the cursor with the keys or when scrolling the text vertically with the handles.
+
+  Controller::NoTextTap::Action mDoubleTapAction; ///< Action to be done when there is a double tap on top of 'no text'
+  Controller::NoTextTap::Action mLongPressAction; ///< Action to be done when there is a long press on top of 'no text'
+
+  bool mIsShowingPlaceholderText : 1;     ///< True if the place-holder text is being displayed.
+  bool mPreEditFlag : 1;                  ///< True if the model contains text in pre-edit state.
+  bool mDecoratorUpdated : 1;             ///< True if the decorator was updated during event processing.
+  bool mCursorBlinkEnabled : 1;           ///< True if cursor should blink when active.
+  bool mGrabHandleEnabled : 1;            ///< True if grab handle is enabled.
+  bool mGrabHandlePopupEnabled : 1;       ///< True if the grab handle popu-up should be shown.
+  bool mSelectionEnabled : 1;             ///< True if selection handles, highlight etc. are enabled.
+  bool mUpdateCursorHookPosition : 1;     ///< True if the cursor hook position must be updated. Used to move the cursor with the keys 'up' and 'down'.
+  bool mUpdateCursorPosition : 1;         ///< True if the visual position of the cursor must be recalculated.
+  bool mUpdateGrabHandlePosition : 1;     ///< True if the visual position of the grab handle must be recalculated.
+  bool mUpdateLeftSelectionPosition : 1;  ///< True if the visual position of the left selection handle must be recalculated.
+  bool mUpdateRightSelectionPosition : 1; ///< True if the visual position of the right selection handle must be recalculated.
+  bool mIsLeftHandleSelected : 1;         ///< Whether is the left handle the one which is selected.
+  bool mIsRightHandleSelected : 1;        ///< Whether is the right handle the one which is selected.
+  bool mUpdateHighlightBox : 1;           ///< True if the text selection high light box must be updated.
+  bool mScrollAfterUpdatePosition : 1;    ///< Whether to scroll after the cursor position is updated.
+  bool mScrollAfterDelete : 1;            ///< Whether to scroll after delete characters.
+  bool mAllTextSelected : 1;              ///< True if the selection handles are selecting all the text.
+  bool mUpdateInputStyle : 1;             ///< Whether to update the input style after moving the cursor.
+  bool mPasswordInput : 1;                ///< True if password input is enabled.
+  bool mCheckScrollAmount : 1;            ///< Whether to check scrolled amount after updating the position
+  bool mIsPlaceholderPixelSize : 1;       ///< True if the placeholder font size is set as pixel size.
+  bool mIsPlaceholderElideEnabled : 1;    ///< True if the placeholder text's elide is enabled.
+  bool mPlaceholderEllipsisFlag : 1;      ///< True if the text controller sets the placeholder ellipsis.
+  bool mShiftSelectionFlag : 1;           ///< True if the text selection using Shift key is enabled.
+  bool mUpdateAlignment : 1;              ///< True if the whole text needs to be full aligned..
+  bool mEditingEnabled : 1;               ///< True if the editing is enabled, false otherwise.
+};
+
+struct ModifyEvent
+{
+  enum Type
+  {
+    TEXT_REPLACED, ///< The entire text was replaced
+    TEXT_INSERTED, ///< Insert characters at the current cursor position
+    TEXT_DELETED   ///< Characters were deleted
+  };
+
+  Type type;
+};
+
+struct FontDefaults
+{
+  FontDefaults()
+  : mFontDescription(),
+    mDefaultPointSize(0.f),
+    mFitPointSize(0.f),
+    mFontId(0u),
+    familyDefined(false),
+    weightDefined(false),
+    widthDefined(false),
+    slantDefined(false),
+    sizeDefined(false)
+  {
+    // Initially use the default platform font
+    TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+    fontClient.GetDefaultPlatformFontDescription(mFontDescription);
+  }
+
+  FontId GetFontId(TextAbstraction::FontClient& fontClient, float fontPointSize)
+  {
+    if(!mFontId)
+    {
+      const PointSize26Dot6 pointSize = static_cast<PointSize26Dot6>(fontPointSize * 64.f);
+      mFontId                         = fontClient.GetFontId(mFontDescription, pointSize);
+    }
+
+    return mFontId;
+  }
+
+  TextAbstraction::FontDescription mFontDescription;  ///< The default font's description.
+  float                            mDefaultPointSize; ///< The default font's point size.
+  float                            mFitPointSize;     ///< The fit font's point size.
+  FontId                           mFontId;           ///< The font's id of the default font.
+  bool                             familyDefined : 1; ///< Whether the default font's family name is defined.
+  bool                             weightDefined : 1; ///< Whether the default font's weight is defined.
+  bool                             widthDefined : 1;  ///< Whether the default font's width is defined.
+  bool                             slantDefined : 1;  ///< Whether the default font's slant is defined.
+  bool                             sizeDefined : 1;   ///< Whether the default font's point size is defined.
+};
+
+/**
+ * @brief Stores indices used to update the text.
+ * Stores the character index where the text is updated and the number of characters removed and added.
+ * Stores as well indices to the first and the last paragraphs to be updated.
+ */
+struct TextUpdateInfo
+{
+  TextUpdateInfo()
+  : mCharacterIndex(0u),
+    mNumberOfCharactersToRemove(0u),
+    mNumberOfCharactersToAdd(0u),
+    mPreviousNumberOfCharacters(0u),
+    mParagraphCharacterIndex(0u),
+    mRequestedNumberOfCharacters(0u),
+    mStartGlyphIndex(0u),
+    mStartLineIndex(0u),
+    mEstimatedNumberOfLines(0u),
+    mClearAll(true),
+    mFullRelayoutNeeded(true),
+    mIsLastCharacterNewParagraph(false)
+  {
+  }
+
+  ~TextUpdateInfo()
+  {
+  }
+
+  CharacterIndex mCharacterIndex;             ///< Index to the first character to be updated.
+  Length         mNumberOfCharactersToRemove; ///< The number of characters to be removed.
+  Length         mNumberOfCharactersToAdd;    ///< The number of characters to be added.
+  Length         mPreviousNumberOfCharacters; ///< The number of characters before the text update.
+
+  CharacterIndex mParagraphCharacterIndex;     ///< Index of the first character of the first paragraph to be updated.
+  Length         mRequestedNumberOfCharacters; ///< The requested number of characters.
+  GlyphIndex     mStartGlyphIndex;
+  LineIndex      mStartLineIndex;
+  Length         mEstimatedNumberOfLines; ///< The estimated number of lines. Used to avoid reallocations when layouting.
+
+  bool mClearAll : 1;                    ///< Whether the whole text is cleared. i.e. when the text is reset.
+  bool mFullRelayoutNeeded : 1;          ///< Whether a full re-layout is needed. i.e. when a new size is set to the text control.
+  bool mIsLastCharacterNewParagraph : 1; ///< Whether the last character is a new paragraph character.
+
+  void Clear()
+  {
+    // Clear all info except the mPreviousNumberOfCharacters member.
+    mCharacterIndex              = static_cast<CharacterIndex>(-1);
+    mNumberOfCharactersToRemove  = 0u;
+    mNumberOfCharactersToAdd     = 0u;
+    mParagraphCharacterIndex     = 0u;
+    mRequestedNumberOfCharacters = 0u;
+    mStartGlyphIndex             = 0u;
+    mStartLineIndex              = 0u;
+    mEstimatedNumberOfLines      = 0u;
+    mClearAll                    = false;
+    mFullRelayoutNeeded          = false;
+    mIsLastCharacterNewParagraph = false;
+  }
+};
+
+struct UnderlineDefaults
+{
+  std::string properties;
+  // TODO: complete with underline parameters.
+};
+
+struct ShadowDefaults
+{
+  std::string properties;
+  // TODO: complete with shadow parameters.
+};
+
+struct EmbossDefaults
+{
+  std::string properties;
+  // TODO: complete with emboss parameters.
+};
+
+struct OutlineDefaults
+{
+  std::string properties;
+  // TODO: complete with outline parameters.
+};
+
+struct Controller::Impl
+{
+  Impl(ControlInterface*           controlInterface,
+       EditableControlInterface*   editableControlInterface,
+       SelectableControlInterface* selectableControlInterface,
+       AnchorControlInterface*     anchorControlInterface)
+  : mControlInterface(controlInterface),
+    mEditableControlInterface(editableControlInterface),
+    mSelectableControlInterface(selectableControlInterface),
+    mAnchorControlInterface(anchorControlInterface),
+    mModel(),
+    mFontDefaults(NULL),
+    mUnderlineDefaults(NULL),
+    mShadowDefaults(NULL),
+    mEmbossDefaults(NULL),
+    mOutlineDefaults(NULL),
+    mEventData(NULL),
+    mFontClient(),
+    mClipboard(),
+    mView(),
+    mMetrics(),
+    mModifyEvents(),
+    mTextColor(Color::BLACK),
+    mTextUpdateInfo(),
+    mOperationsPending(NO_OPERATION),
+    mMaximumNumberOfCharacters(50u),
+    mHiddenInput(NULL),
+    mInputFilter(nullptr),
+    mRecalculateNaturalSize(true),
+    mMarkupProcessorEnabled(false),
+    mClipboardHideEnabled(true),
+    mIsAutoScrollEnabled(false),
+    mIsAutoScrollMaxTextureExceeded(false),
+    mUpdateTextDirection(true),
+    mIsTextDirectionRTL(false),
+    mUnderlineSetByString(false),
+    mShadowSetByString(false),
+    mOutlineSetByString(false),
+    mFontStyleSetByString(false),
+    mStrikethroughSetByString(false),
+    mShouldClearFocusOnEscape(true),
+    mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
+    mTextFitMinSize(DEFAULT_TEXTFIT_MIN),
+    mTextFitMaxSize(DEFAULT_TEXTFIT_MAX),
+    mTextFitStepSize(DEFAULT_TEXTFIT_STEP),
+    mFontSizeScale(DEFAULT_FONT_SIZE_SCALE),
+    mDisabledColorOpacity(DEFAULT_DISABLED_COLOR_OPACITY),
+    mFontSizeScaleEnabled(true),
+    mTextFitEnabled(false),
+    mTextFitChanged(false),
+    mIsLayoutDirectionChanged(false),
+    mIsUserInteractionEnabled(true)
+  {
+    mModel = Model::New();
+
+    mFontClient = TextAbstraction::FontClient::Get();
+    mClipboard  = Clipboard::Get();
+
+    mView.SetVisualModel(mModel->mVisualModel);
+    mView.SetLogicalModel(mModel->mLogicalModel);
+
+    // Use this to access FontClient i.e. to get down-scaled Emoji metrics.
+    mMetrics = Metrics::New(mFontClient);
+    mLayoutEngine.SetMetrics(mMetrics);
+
+    // Set the text properties to default
+    mModel->mVisualModel->SetUnderlineEnabled(false);
+    mModel->mVisualModel->SetUnderlineHeight(0.0f);
+
+    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+    if(styleManager)
+    {
+      const Property::Map& config                  = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+      const auto           clearFocusOnEscapeValue = config.Find("clearFocusOnEscape", Property::Type::BOOLEAN);
+
+      // Default is true. If config don't have "clearFocusOnEscape" property, make it true.
+      mShouldClearFocusOnEscape = (!clearFocusOnEscapeValue || clearFocusOnEscapeValue->Get<bool>());
+    }
+  }
+
+  ~Impl()
+  {
+    delete mHiddenInput;
+    delete mFontDefaults;
+    delete mUnderlineDefaults;
+    delete mShadowDefaults;
+    delete mEmbossDefaults;
+    delete mOutlineDefaults;
+    delete mEventData;
+  }
+
+  // Text Controller Implementation.
+
+  /**
+   * @copydoc Text::Controller::RequestRelayout()
+   */
+  void RequestRelayout();
+
+  /**
+   * @brief Request a relayout using the ControlInterface.
+   */
+  void QueueModifyEvent(ModifyEvent::Type type)
+  {
+    if(ModifyEvent::TEXT_REPLACED == type)
+    {
+      // Cancel previously queued inserts etc.
+      mModifyEvents.Clear();
+    }
+
+    ModifyEvent event;
+    event.type = type;
+    mModifyEvents.PushBack(event);
+
+    // The event will be processed during relayout
+    RequestRelayout();
+  }
+
+  /**
+   * @brief Helper to move the cursor, grab handle etc.
+   */
+  bool ProcessInputEvents();
+
+  /**
+   * @brief Helper to check whether any place-holder text is available.
+   */
+  bool IsPlaceholderAvailable() const
+  {
+    return (mEventData &&
+            (!mEventData->mPlaceholderTextInactive.empty() ||
+             !mEventData->mPlaceholderTextActive.empty()));
+  }
+
+  bool IsShowingPlaceholderText() const
+  {
+    return (mEventData && mEventData->mIsShowingPlaceholderText);
+  }
+
+  /**
+   * @brief Helper to check whether active place-holder text is available.
+   */
+  bool IsFocusedPlaceholderAvailable() const
+  {
+    return (mEventData && !mEventData->mPlaceholderTextActive.empty());
+  }
+
+  bool IsShowingRealText() const
+  {
+    return (!IsShowingPlaceholderText() &&
+            0u != mModel->mLogicalModel->mText.Count());
+  }
+
+  /**
+   * @brief Called when placeholder-text is hidden
+   */
+  void PlaceholderCleared()
+  {
+    if(mEventData)
+    {
+      mEventData->mIsShowingPlaceholderText = false;
+
+      // Remove mPlaceholderTextColor
+      mModel->mVisualModel->SetTextColor(mTextColor);
+    }
+  }
+
+  void ClearPreEditFlag()
+  {
+    if(mEventData)
+    {
+      mEventData->mPreEditFlag          = false;
+      mEventData->mPreEditStartPosition = 0;
+      mEventData->mPreEditLength        = 0;
+    }
+  }
+
+  void ResetInputMethodContext()
+  {
+    if(mEventData)
+    {
+      // Reset incase we are in a pre-edit state.
+      if(mEventData->mInputMethodContext)
+      {
+        mEventData->mInputMethodContext.Reset(); // Will trigger a message ( commit, get surrounding )
+      }
+
+      ClearPreEditFlag();
+    }
+  }
+
+  float GetFontSizeScale()
+  {
+    return mFontSizeScaleEnabled ? mFontSizeScale : 1.0f;
+  }
+
+  /**
+   * @brief Helper to notify InputMethodContext with surrounding text & cursor changes.
+   */
+  void NotifyInputMethodContext();
+
+  /**
+   * @brief Helper to notify InputMethodContext with multi line status.
+   */
+  void NotifyInputMethodContextMultiLineStatus();
+
+  /**
+   * @brief Retrieve the current cursor position.
+   *
+   * @return The cursor position.
+   */
+  CharacterIndex GetLogicalCursorPosition() const;
+
+  /**
+   * @brief Retrieves the number of consecutive white spaces starting from the given @p index.
+   *
+   * @param[in] index The character index from where to count the number of consecutive white spaces.
+   *
+   * @return The number of consecutive white spaces.
+   */
+  Length GetNumberOfWhiteSpaces(CharacterIndex index) const;
+
+  /**
+   * @brief Retrieve any text previously set.
+   *
+   * @param[out] text A string of UTF-8 characters.
+   */
+  void GetText(std::string& text) const;
+
+  /**
+   * @brief Retrieve any text previously set starting from the given @p index.
+   *
+   * @param[in] index The character index from where to retrieve the text.
+   * @param[out] text A string of UTF-8 characters.
+   *
+   * @see Dali::Toolkit::Text::Controller::GetText()
+   */
+  void GetText(CharacterIndex index, std::string& text) const;
+
+  bool IsClipboardEmpty()
+  {
+    bool result(mClipboard && mClipboard.NumberOfItems());
+    return !result; // If NumberOfItems greater than 0, return false
+  }
+
+  bool IsClipboardVisible()
+  {
+    bool result(mClipboard && mClipboard.IsVisible());
+    return result;
+  }
+
+  /**
+   * @copydoc Controller::GetLayoutDirection()
+   */
+  Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
+
+  /**
+   * @brief Checks text direction.
+   * @return The text direction.
+   */
+  Toolkit::DevelText::TextDirection::Type GetTextDirection();
+
+  /**
+   * @brief Calculates the start character index of the first paragraph to be updated and
+   * the end character index of the last paragraph to be updated.
+   *
+   * @param[out] numberOfCharacters The number of characters to be updated.
+   */
+  void CalculateTextUpdateIndices(Length& numberOfCharacters);
+
+  /**
+   * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  void ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations);
+
+  /**
+   * @brief Updates the logical and visual models. Updates the style runs in the visual model when the text's styles changes.
+   *
+   * When text or style changes the model is set with some operations pending.
+   * When i.e. the text's size or a relayout is required this method is called
+   * with a given @p operationsRequired parameter. The operations required are
+   * matched with the operations pending to perform the minimum number of operations.
+   *
+   * @param[in] operationsRequired The operations required.
+   *
+   * @return @e true if the model has been modified.
+   */
+  bool UpdateModel(OperationsMask operationsRequired);
+
+  /**
+   * @brief Retreieves the default style.
+   *
+   * @param[out] inputStyle The default style.
+   */
+  void RetrieveDefaultInputStyle(InputStyle& inputStyle);
+
+  /**
+   * @brief Retrieve the line height of the default font.
+   */
+  float GetDefaultFontLineHeight();
+
+  /**
+   * @copydoc Controller::SetDefaultLineSpacing
+   */
+  bool SetDefaultLineSpacing(float lineSpacing);
+
+  /**
+   * @copydoc Controller::SetDefaultLineSize
+   */
+  bool SetDefaultLineSize(float lineSize);
+
+  /**
+   * @copydoc Controller::SetRelativeLineSize
+   */
+  bool SetRelativeLineSize(float relativeLineSize);
+
+  /**
+   * @copydoc Controller::GetRelativeLineSize
+   */
+  float GetRelativeLineSize();
+
+  /**
+   * @copydoc Text::Controller::GetPrimaryCursorPosition()
+   */
+  CharacterIndex GetPrimaryCursorPosition() const;
+
+  /**
+   * @copydoc Text::Controller::SetPrimaryCursorPosition()
+   */
+  bool SetPrimaryCursorPosition(CharacterIndex index, bool focused);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetSelectedText()
+   */
+  string GetSelectedText();
+
+  /**
+   * @copydoc Text::EditableControlInterface::CopyText()
+   */
+  string CopyText();
+
+  /**
+   * @copydoc Text::EditableControlInterface::CutText()
+   */
+  string CutText();
+
+  /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEndf);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const;
+
+  /**
+   * @copydoc Text::EditableControlInterface::IsEditable()
+   */
+  bool IsEditable() const;
+
+  /**
+   * @copydoc Text::EditableControlInterface::SetEditable()
+   */
+  void SetEditable(bool editable);
+
+  /**
+   * @copydoc Controller::UpdateAfterFontChange
+   */
+  void UpdateAfterFontChange(const std::string& newDefaultFont);
+
+  /**
+   * @brief Retrieves the selected text. It removes the text if the @p deleteAfterRetrieval parameter is @e true.
+   *
+   * @param[out] selectedText The selected text encoded in utf8.
+   * @param[in] deleteAfterRetrieval Whether the text should be deleted after retrieval.
+   */
+  void RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval);
+
+  void SetSelection(int start, int end);
+
+  std::pair<int, int> GetSelectionIndexes() const;
+
+  void ShowClipboard();
+
+  void HideClipboard();
+
+  void SetClipboardHideEnable(bool enable);
+
+  bool CopyStringToClipboard(const std::string& source);
+
+  void SendSelectionToClipboard(bool deleteAfterSending);
+
+  void RequestGetTextFromClipboard();
+
+  void RepositionSelectionHandles();
+  void RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action);
+
+  void SetPopupButtons();
+
+  void ChangeState(EventData::State newState);
+
+  /**
+   * @brief Calculates the cursor's position for a given character index in the logical order.
+   *
+   * It retrieves as well the line's height and the cursor's height and
+   * if there is a valid alternative cursor, its position and height.
+   *
+   * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
+   * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
+   */
+  void GetCursorPosition(CharacterIndex logical,
+                         CursorInfo&    cursorInfo);
+
+  /**
+   * @brief Calculates the new cursor index.
+   *
+   * It takes into account that in some scripts multiple characters can form a glyph and all of them
+   * need to be jumped with one key event.
+   *
+   * @param[in] index The initial new index.
+   *
+   * @return The new cursor index.
+   */
+  CharacterIndex CalculateNewCursorIndex(CharacterIndex index) const;
+
+  /**
+   * @brief Updates the cursor position.
+   *
+   * Sets the cursor's position into the decorator. It transforms the cursor's position into decorator's coords.
+   * It sets the position of the secondary cursor if it's a valid one.
+   * Sets which cursors are active.
+   *
+   * @param[in] cursorInfo Contains the selection handle position in Actor's coords.
+   *
+   */
+  void UpdateCursorPosition(const CursorInfo& cursorInfo);
+
+  /**
+   * @brief Updates the position of the given selection handle. It transforms the handle's position into decorator's coords.
+   *
+   * @param[in] handleType One of the selection handles.
+   * @param[in] cursorInfo Contains the selection handle position in Actor's coords.
+   */
+  void UpdateSelectionHandle(HandleType        handleType,
+                             const CursorInfo& cursorInfo);
+
+  /**
+   * @biref Clamps the horizontal scrolling to get the control always filled with text.
+   *
+   * @param[in] layoutSize The size of the laid out text.
+   */
+  void ClampHorizontalScroll(const Vector2& layoutSize);
+
+  /**
+   * @biref Clamps the vertical scrolling to get the control always filled with text.
+   *
+   * @param[in] layoutSize The size of the laid out text.
+   */
+  void ClampVerticalScroll(const Vector2& layoutSize);
+
+  /**
+   * @brief Scrolls the text to make a position visible.
+   *
+   * @pre mEventData must not be NULL. (there is a text-input or selection capabilities).
+   *
+   * @param[in] position A position in text coords.
+   * @param[in] lineHeight The line height for the given position.
+   *
+   * This method is called after inserting text, moving the cursor with the grab handle or the keypad,
+   * or moving the selection handles.
+   */
+  void ScrollToMakePositionVisible(const Vector2& position, float lineHeight);
+
+  /**
+   * @brief Scrolls the text to make the cursor visible.
+   *
+   * This method is called after deleting text.
+   */
+  void ScrollTextToMatchCursor(const CursorInfo& cursorInfo);
+
+  /**
+   * @brief Scrolls the text to make primary cursor visible.
+   */
+  void ScrollTextToMatchCursor();
+
+  /**
+   * @brief Create an actor that renders the text background color
+   *
+   * @return the created actor or an empty handle if no background color needs to be rendered.
+   */
+  Actor CreateBackgroundActor();
+
+  /**
+   * @brief fill needed relayout parameters whenever a property is changed and a re-layout is needed for the entire text.
+   */
+  void RelayoutAllCharacters();
+
+  /**
+   * @copydoc Controller::IsInputStyleChangedSignalsQueueEmpty
+   */
+  bool IsInputStyleChangedSignalsQueueEmpty();
+
+  /**
+   * @copydoc Controller::ProcessInputStyleChangedSignals
+   */
+  void ProcessInputStyleChangedSignals();
+
+  /**
+   * @copydoc Controller::ScrollBy()
+   */
+  void ScrollBy(Vector2 scroll);
+
+  /**
+   * @copydoc Controller::IsScrollable()
+   */
+  bool IsScrollable(const Vector2& displacement);
+
+  /**
+   * @copydoc Controller::GetHorizontalScrollPosition()
+   */
+  float GetHorizontalScrollPosition();
+
+  /**
+   * @copydoc Controller::GetVerticalScrollPosition()
+   */
+  float GetVerticalScrollPosition();
+
+  /**
+   * @copydoc Controller::SetAutoScrollEnabled()
+   */
+  void SetAutoScrollEnabled(bool enable);
+
+  /**
+   * @copydoc Controller::SetEnableCursorBlink()
+   */
+  void SetEnableCursorBlink(bool enable);
+
+  /**
+   * @copydoc Controller::SetMultiLineEnabled()
+   */
+  void SetMultiLineEnabled(bool enable);
+
+  /**
+   * @copydoc Controller::SetHorizontalAlignment()
+   */
+  void SetHorizontalAlignment(HorizontalAlignment::Type alignment);
+
+  /**
+   * @copydoc Controller::SetVerticalAlignment()
+   */
+  void SetVerticalAlignment(VerticalAlignment::Type alignment);
+
+  /**
+   * @copydoc Controller::SetLineWrapMode()
+   */
+  void SetLineWrapMode(Text::LineWrap::Mode textWarpMode);
+
+  /**
+   * @copydoc Controller::SetDefaultColor()
+   */
+  void SetDefaultColor(const Vector4& color);
+
+  /**
+   * @copydoc Controller::SetUserInteractionEnabled()
+   */
+  void SetUserInteractionEnabled(bool enabled);
+
+  /**
+   * @brief Helper to clear font-specific data (only).
+   */
+  void ClearFontData();
+
+  /**
+   * @brief Helper to clear text's style data.
+   */
+  void ClearStyleData();
+
+  /**
+   * @brief Used to reset the scroll position after setting a new text.
+   */
+  void ResetScrollPosition();
+
+  /**
+   * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
+   *
+   * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
+   */
+  void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
+
+  /**
+   * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
+   *
+   * @param[in] characterOffset A position in text coords.
+   *
+   * @return the 0-based index in anchor vector (-1 if an anchor not found)
+   */
+  int32_t GetAnchorIndex(size_t characterOffset) const;
+
+  /**
+   * @brief Return the geometrical position of an anchor relative to the parent origin point.
+   *
+   * @param[in] anchor An anchor.
+   *
+   * @return The x, y, z coordinates of an anchor.
+   */
+  Vector3 GetAnchorPosition(Anchor anchor) const;
+
+  /**
+   * @brief Return the size of an anchor expresed as a vector containing anchor's width and height.
+   *
+   * @param[in] anchor An anchor.
+   *
+   * @return The width and height of an anchor.
+   */
+  Vector2 GetAnchorSize(Anchor anchor) const;
+
+  /**
+   * @brief Return the actor representing an anchor.
+   *
+   * @param[in] anchor An anchor.
+   *
+   * @return The actor representing an anchor.
+   */
+  Toolkit::TextAnchor CreateAnchorActor(Anchor anchor);
+
+public:
+  /**
+   * @brief Gets implementation from the controller handle.
+   * @param controller The text controller
+   * @return The implementation of the Controller
+   */
+  static Impl& GetImplementation(Text::Controller& controller)
+  {
+    return *controller.mImpl;
+  }
+
+private:
+  // Declared private and left undefined to avoid copies.
+  Impl(const Impl&);
+  // Declared private and left undefined to avoid copies.
+  Impl& operator=(const Impl&);
+
+  /**
+   * @brief Copy Underlined-Character-Runs from Logical-Model to Underlined-Glyph-Runs in Visual-Model
+   *
+   * @param shouldClearPreUnderlineRuns Whether should clear the existing Underlined-Glyph-Runs in Visual-Model
+   */
+  void CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns);
+
+  /**
+   * @brief Copy strikethrough-Character-Runs from Logical-Model to strikethrough-Glyph-Runs in Visual-Model
+   *
+   */
+  void CopyStrikethroughFromLogicalToVisualModels();
+
+  /**
+   * @brief Copy CharacterSpacing-Character-Runs from Logical-Model to CharacterSpacing-Glyph-Runs in Visual-Model
+   *
+   */
+  void CopyCharacterSpacingFromLogicalToVisualModels();
+
+public:
+  ControlInterface*            mControlInterface;           ///< Reference to the text controller.
+  EditableControlInterface*    mEditableControlInterface;   ///< Reference to the editable text controller.
+  SelectableControlInterface*  mSelectableControlInterface; ///< Reference to the selectable text controller.
+  AnchorControlInterface*      mAnchorControlInterface;     ///< Reference to the anchor controller.
+  ModelPtr                     mModel;                      ///< Pointer to the text's model.
+  FontDefaults*                mFontDefaults;               ///< Avoid allocating this when the user does not specify a font.
+  UnderlineDefaults*           mUnderlineDefaults;          ///< Avoid allocating this when the user does not specify underline parameters.
+  ShadowDefaults*              mShadowDefaults;             ///< Avoid allocating this when the user does not specify shadow parameters.
+  EmbossDefaults*              mEmbossDefaults;             ///< Avoid allocating this when the user does not specify emboss parameters.
+  OutlineDefaults*             mOutlineDefaults;            ///< Avoid allocating this when the user does not specify outline parameters.
+  EventData*                   mEventData;                  ///< Avoid allocating everything for text input until EnableTextInput().
+  TextAbstraction::FontClient  mFontClient;                 ///< Handle to the font client.
+  Clipboard                    mClipboard;                  ///< Handle to the system clipboard
+  View                         mView;                       ///< The view interface to the rendering back-end.
+  MetricsPtr                   mMetrics;                    ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
+  Layout::Engine               mLayoutEngine;               ///< The layout engine.
+  Vector<ModifyEvent>          mModifyEvents;               ///< Temporary stores the text set until the next relayout.
+  Vector4                      mTextColor;                  ///< The regular text color
+  TextUpdateInfo               mTextUpdateInfo;             ///< Info of the characters updated.
+  OperationsMask               mOperationsPending;          ///< Operations pending to be done to layout the text.
+  Length                       mMaximumNumberOfCharacters;  ///< Maximum number of characters that can be inserted.
+  HiddenText*                  mHiddenInput;                ///< Avoid allocating this when the user does not specify hidden input mode.
+  std::unique_ptr<InputFilter> mInputFilter;                ///< Avoid allocating this when the user does not specify input filter mode.
+  Vector2                      mTextFitContentSize;         ///< Size of Text fit content
+
+  bool               mRecalculateNaturalSize : 1;         ///< Whether the natural size needs to be recalculated.
+  bool               mMarkupProcessorEnabled : 1;         ///< Whether the mark-up procesor is enabled.
+  bool               mClipboardHideEnabled : 1;           ///< Whether the ClipboardHide function work or not
+  bool               mIsAutoScrollEnabled : 1;            ///< Whether auto text scrolling is enabled.
+  bool               mIsAutoScrollMaxTextureExceeded : 1; ///< Whether auto text scrolling is exceed max texture size.
+  bool               mUpdateTextDirection : 1;            ///< Whether the text direction needs to be updated.
+  CharacterDirection mIsTextDirectionRTL : 1;             ///< Whether the text direction is right to left or not
+
+  bool                  mUnderlineSetByString : 1;     ///< Set when underline is set by string (legacy) instead of map
+  bool                  mShadowSetByString : 1;        ///< Set when shadow is set by string (legacy) instead of map
+  bool                  mOutlineSetByString : 1;       ///< Set when outline is set by string (legacy) instead of map
+  bool                  mFontStyleSetByString : 1;     ///< Set when font style is set by string (legacy) instead of map
+  bool                  mStrikethroughSetByString : 1; ///< Set when strikethrough is set by string (legacy) instead of map
+  bool                  mShouldClearFocusOnEscape : 1; ///< Whether text control should clear key input focus
+  LayoutDirection::Type mLayoutDirection;              ///< Current system language direction
+
+  Shader mShaderBackground; ///< The shader for text background.
+
+  float mTextFitMinSize;               ///< Minimum Font Size for text fit. Default 10
+  float mTextFitMaxSize;               ///< Maximum Font Size for text fit. Default 100
+  float mTextFitStepSize;              ///< Step Size for font intervalse. Default 1
+  float mFontSizeScale;                ///< Scale value for Font Size. Default 1.0
+  float mDisabledColorOpacity;         ///< Color opacity when disabled.
+  bool  mFontSizeScaleEnabled : 1;     ///< Whether the font size scale is enabled.
+  bool  mTextFitEnabled : 1;           ///< Whether the text's fit is enabled.
+  bool  mTextFitChanged : 1;           ///< Whether the text fit property has changed.
+  bool  mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
+  bool  mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled.
+
+private:
+  friend ControllerImplEventHandler;
+  friend ControllerImplModelUpdater;
+  friend SelectionHandleController;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.cpp
new file mode 100644 (file)
index 0000000..a1e6214
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-input-font-handler.h>
+
+// EXTERNAL INCLUDES
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+/**
+ * @brief Adds a new font description run for the selected text.
+ *
+ * The new font parameters are added after the call to this method.
+ *
+ * @param[in] eventData The event data pointer.
+ * @param[in] logicalModel The logical model where to add the new font description run.
+ * @param[out] startOfSelectedText Index to the first selected character.
+ * @param[out] lengthOfSelectedText Number of selected characters.
+ */
+FontDescriptionRun& UpdateSelectionFontStyleRun(EventData*      eventData,
+                                                LogicalModelPtr logicalModel,
+                                                CharacterIndex& startOfSelectedText,
+                                                Length&         lengthOfSelectedText)
+{
+  const bool handlesCrossed = eventData->mLeftSelectionPosition > eventData->mRightSelectionPosition;
+
+  // Get start and end position of selection
+  startOfSelectedText  = handlesCrossed ? eventData->mRightSelectionPosition : eventData->mLeftSelectionPosition;
+  lengthOfSelectedText = (handlesCrossed ? eventData->mLeftSelectionPosition : eventData->mRightSelectionPosition) - startOfSelectedText;
+
+  // Add the font run.
+  const VectorBase::SizeType numberOfRuns = logicalModel->mFontDescriptionRuns.Count();
+  logicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
+
+  FontDescriptionRun& fontDescriptionRun = *(logicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
+
+  fontDescriptionRun.characterRun.characterIndex     = startOfSelectedText;
+  fontDescriptionRun.characterRun.numberOfCharacters = lengthOfSelectedText;
+
+  // Recalculate the selection highlight as the metrics may have changed.
+  eventData->mUpdateLeftSelectionPosition  = true;
+  eventData->mUpdateRightSelectionPosition = true;
+  eventData->mUpdateHighlightBox           = true;
+
+  return fontDescriptionRun;
+}
+
+} // unnamed namespace
+
+void Controller::InputFontHandler::SetInputFontFamily(Controller& controller, const std::string& fontFamily)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.familyName      = fontFamily;
+    controller.mImpl->mEventData->mInputStyle.isFamilyDefined = true;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      CharacterIndex startOfSelectedText  = 0u;
+      Length         lengthOfSelectedText = 0u;
+
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        // Update a font description run for the selecting state.
+        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
+                                                                             controller.mImpl->mModel->mLogicalModel,
+                                                                             startOfSelectedText,
+                                                                             lengthOfSelectedText);
+
+        fontDescriptionRun.familyLength = fontFamily.size();
+        fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
+        memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
+        fontDescriptionRun.familyDefined = true;
+
+        // The memory allocated for the font family name is freed when the font description is removed from the logical model.
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
+                                                                         VALIDATE_FONTS |
+                                                                         SHAPE_TEXT |
+                                                                         GET_GLYPH_METRICS |
+                                                                         LAYOUT |
+                                                                         UPDATE_LAYOUT_SIZE |
+                                                                         REORDER |
+                                                                         ALIGN);
+      controller.mImpl->mRecalculateNaturalSize = true;
+      controller.mImpl->RequestRelayout();
+
+      // As the font changes, recalculate the handle positions is needed.
+      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
+      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
+      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
+    }
+  }
+}
+
+const std::string& Controller::InputFontHandler::GetInputFontFamily(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mInputStyle.familyName;
+  }
+
+  // Return the default font's family if there is no EventData.
+  return controller.GetDefaultFontFamily();
+}
+
+void Controller::InputFontHandler::SetInputFontWeight(const Controller& controller, FontWeight weight)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.weight          = weight;
+    controller.mImpl->mEventData->mInputStyle.isWeightDefined = true;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      CharacterIndex startOfSelectedText  = 0u;
+      Length         lengthOfSelectedText = 0u;
+
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        // Update a font description run for the selecting state.
+        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
+                                                                             controller.mImpl->mModel->mLogicalModel,
+                                                                             startOfSelectedText,
+                                                                             lengthOfSelectedText);
+
+        fontDescriptionRun.weight        = weight;
+        fontDescriptionRun.weightDefined = true;
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
+                                                                         VALIDATE_FONTS |
+                                                                         SHAPE_TEXT |
+                                                                         GET_GLYPH_METRICS |
+                                                                         LAYOUT |
+                                                                         UPDATE_LAYOUT_SIZE |
+                                                                         REORDER |
+                                                                         ALIGN);
+      controller.mImpl->mRecalculateNaturalSize = true;
+      controller.mImpl->RequestRelayout();
+
+      // As the font might change, recalculate the handle positions is needed.
+      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
+      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
+      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
+    }
+  }
+}
+
+bool Controller::InputFontHandler::IsInputFontWeightDefined(const Controller& controller)
+{
+  bool defined = false;
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    defined = controller.mImpl->mEventData->mInputStyle.isWeightDefined;
+  }
+
+  return defined;
+}
+
+FontWeight Controller::InputFontHandler::GetInputFontWeight(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mInputStyle.weight;
+  }
+
+  return controller.GetDefaultFontWeight();
+}
+
+void Controller::InputFontHandler::SetInputFontWidth(Controller& controller, FontWidth width)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.width          = width;
+    controller.mImpl->mEventData->mInputStyle.isWidthDefined = true;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      CharacterIndex startOfSelectedText  = 0u;
+      Length         lengthOfSelectedText = 0u;
+
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        // Update a font description run for the selecting state.
+        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
+                                                                             controller.mImpl->mModel->mLogicalModel,
+                                                                             startOfSelectedText,
+                                                                             lengthOfSelectedText);
+
+        fontDescriptionRun.width        = width;
+        fontDescriptionRun.widthDefined = true;
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
+                                                                         VALIDATE_FONTS |
+                                                                         SHAPE_TEXT |
+                                                                         GET_GLYPH_METRICS |
+                                                                         LAYOUT |
+                                                                         UPDATE_LAYOUT_SIZE |
+                                                                         REORDER |
+                                                                         ALIGN);
+      controller.mImpl->mRecalculateNaturalSize = true;
+      controller.mImpl->RequestRelayout();
+
+      // As the font might change, recalculate the handle positions is needed.
+      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
+      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
+      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
+    }
+  }
+}
+
+bool Controller::InputFontHandler::IsInputFontWidthDefined(const Controller& controller)
+{
+  bool defined = false;
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    defined = controller.mImpl->mEventData->mInputStyle.isWidthDefined;
+  }
+
+  return defined;
+}
+
+FontWidth Controller::InputFontHandler::GetInputFontWidth(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mInputStyle.width;
+  }
+
+  return controller.GetDefaultFontWidth();
+}
+
+void Controller::InputFontHandler::SetInputFontSlant(Controller& controller, FontSlant slant)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.slant          = slant;
+    controller.mImpl->mEventData->mInputStyle.isSlantDefined = true;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      CharacterIndex startOfSelectedText  = 0u;
+      Length         lengthOfSelectedText = 0u;
+
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        // Update a font description run for the selecting state.
+        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
+                                                                             controller.mImpl->mModel->mLogicalModel,
+                                                                             startOfSelectedText,
+                                                                             lengthOfSelectedText);
+
+        fontDescriptionRun.slant        = slant;
+        fontDescriptionRun.slantDefined = true;
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
+                                                                         VALIDATE_FONTS |
+                                                                         SHAPE_TEXT |
+                                                                         GET_GLYPH_METRICS |
+                                                                         LAYOUT |
+                                                                         UPDATE_LAYOUT_SIZE |
+                                                                         REORDER |
+                                                                         ALIGN);
+      controller.mImpl->mRecalculateNaturalSize = true;
+      controller.mImpl->RequestRelayout();
+
+      // As the font might change, recalculate the handle positions is needed.
+      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
+      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
+      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
+    }
+  }
+}
+
+bool Controller::InputFontHandler::IsInputFontSlantDefined(const Controller& controller)
+{
+  bool defined = false;
+
+  if(NULL != controller.mImpl->mEventData)
+  {
+    defined = controller.mImpl->mEventData->mInputStyle.isSlantDefined;
+  }
+
+  return defined;
+}
+
+FontSlant Controller::InputFontHandler::GetInputFontSlant(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mInputStyle.slant;
+  }
+
+  return controller.GetDefaultFontSlant();
+}
+
+void Controller::InputFontHandler::SetInputFontPointSize(Controller& controller, float size)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.size          = size;
+    controller.mImpl->mEventData->mInputStyle.isSizeDefined = true;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      CharacterIndex startOfSelectedText  = 0u;
+      Length         lengthOfSelectedText = 0u;
+
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        // Update a font description run for the selecting state.
+        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
+                                                                             controller.mImpl->mModel->mLogicalModel,
+                                                                             startOfSelectedText,
+                                                                             lengthOfSelectedText);
+
+        fontDescriptionRun.size        = static_cast<PointSize26Dot6>(size * controller.mImpl->GetFontSizeScale() * 64.f);
+        fontDescriptionRun.sizeDefined = true;
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
+                                                                         VALIDATE_FONTS |
+                                                                         SHAPE_TEXT |
+                                                                         GET_GLYPH_METRICS |
+                                                                         LAYOUT |
+                                                                         UPDATE_LAYOUT_SIZE |
+                                                                         REORDER |
+                                                                         ALIGN);
+      controller.mImpl->mRecalculateNaturalSize = true;
+      controller.mImpl->RequestRelayout();
+
+      // As the font might change, recalculate the handle positions is needed.
+      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
+      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
+      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
+      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
+    }
+  }
+}
+
+float Controller::InputFontHandler::GetInputFontPointSize(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mInputStyle.size;
+  }
+
+  // Return the default font's point size if there is no EventData.
+  return controller.GetDefaultFontSize(Text::Controller::POINT_SIZE);
+}
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h b/dali-toolkit/internal/text/controller/text-controller-input-font-handler.h
new file mode 100644 (file)
index 0000000..2ac7464
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Controller::InputFontHandler
+{
+  static void               SetInputFontFamily(Controller& controller, const std::string& fontFamily);
+  static const std::string& GetInputFontFamily(const Controller& controller);
+  static void               SetInputFontWeight(const Controller& controller, FontWeight weight);
+  static bool               IsInputFontWeightDefined(const Controller& controller);
+  static FontWeight         GetInputFontWeight(const Controller& controller);
+  static void               SetInputFontWidth(Controller& controller, FontWidth width);
+  static bool               IsInputFontWidthDefined(const Controller& controller);
+  static FontWidth          GetInputFontWidth(const Controller& controller);
+  static void               SetInputFontSlant(Controller& controller, FontSlant slant);
+  static bool               IsInputFontSlantDefined(const Controller& controller);
+  static FontSlant          GetInputFontSlant(const Controller& controller);
+  static void               SetInputFontPointSize(Controller& controller, float size);
+  static float              GetInputFontPointSize(const Controller& controller);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp b/dali-toolkit/internal/text/controller/text-controller-input-properties.cpp
new file mode 100644 (file)
index 0000000..f410187
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-input-properties.h>
+
+// EXTERNAL INCLUDES
+//#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+//#include <dali/devel-api/adaptor-framework/window-devel.h>
+//#include <dali/integration-api/debug.h>
+#include <memory.h>
+#include <cmath>
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-input-font-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
+#include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+
+namespace
+{
+const std::string EMPTY_STRING("");
+}
+
+namespace Dali::Toolkit::Text
+{
+
+void Controller::InputProperties::SetInputColor(Controller& controller, const Vector4& color)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.textColor      = color;
+    controller.mImpl->mEventData->mInputStyle.isDefaultColor = false;
+
+    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
+    {
+      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
+      {
+        const bool handlesCrossed = controller.mImpl->mEventData->mLeftSelectionPosition > controller.mImpl->mEventData->mRightSelectionPosition;
+
+        // Get start and end position of selection
+        const CharacterIndex startOfSelectedText  = handlesCrossed ? controller.mImpl->mEventData->mRightSelectionPosition : controller.mImpl->mEventData->mLeftSelectionPosition;
+        const Length         lengthOfSelectedText = (handlesCrossed ? controller.mImpl->mEventData->mLeftSelectionPosition : controller.mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
+
+        // Add the color run.
+        const VectorBase::SizeType numberOfRuns = controller.mImpl->mModel->mLogicalModel->mColorRuns.Count();
+        controller.mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
+
+        ColorRun& colorRun                       = *(controller.mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
+        colorRun.color                           = color;
+        colorRun.characterRun.characterIndex     = startOfSelectedText;
+        colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
+
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
+      }
+      else
+      {
+        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
+      }
+
+      // Request to relayout.
+      controller.mImpl->mOperationsPending = static_cast<OperationsMask>(controller.mImpl->mOperationsPending | COLOR);
+      controller.mImpl->RequestRelayout();
+    }
+  }
+}
+
+const Vector4& Controller::InputProperties::GetInputColor(const Controller& controller)
+{
+  // Return event text input color if we have it, otherwise just return the default text's color
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.textColor : controller.mImpl->mTextColor;
+}
+
+void Controller::InputProperties::SetInputLineSpacing(Controller& controller, float lineSpacing)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
+    controller.mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
+  }
+}
+
+float Controller::InputProperties::GetInputLineSpacing(const Controller& controller)
+{
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.lineSpacing : 0.0f;
+}
+
+void Controller::InputProperties::SetInputShadowProperties(Controller& controller, const std::string& shadowProperties)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
+  }
+}
+
+const std::string& Controller::InputProperties::GetInputShadowProperties(const Controller& controller)
+{
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING;
+}
+
+void Controller::InputProperties::SetInputUnderlineProperties(Controller& controller, const std::string& underlineProperties)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
+  }
+}
+
+const std::string& Controller::InputProperties::GetInputUnderlineProperties(const Controller& controller)
+{
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING;
+}
+
+void Controller::InputProperties::SetInputEmbossProperties(Controller& controller, const std::string& embossProperties)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
+  }
+}
+
+const std::string& Controller::InputProperties::GetInputEmbossProperties(const Controller& controller)
+{
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.embossProperties : controller.GetDefaultEmbossProperties();
+}
+
+void Controller::InputProperties::SetInputOutlineProperties(Controller& controller, const std::string& outlineProperties)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
+  }
+}
+
+const std::string& Controller::InputProperties::GetInputOutlineProperties(const Controller& controller)
+{
+  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.outlineProperties : controller.GetDefaultOutlineProperties();
+}
+
+void Controller::InputProperties::SetInputModePassword(Controller& controller, bool passwordInput)
+{
+  if(controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mPasswordInput = passwordInput;
+  }
+}
+
+bool Controller::InputProperties::IsInputModePassword(Controller& controller)
+{
+  return controller.mImpl->mEventData && controller.mImpl->mEventData->mPasswordInput;
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller-input-properties.h b/dali-toolkit/internal/text/controller/text-controller-input-properties.h
new file mode 100644 (file)
index 0000000..b0736f7
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/input-method-context.h>
+#include <dali/public-api/events/gesture.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+
+namespace Dali::Toolkit::Text
+{
+struct Controller::InputProperties
+{
+  static void SetInputColor(Controller& controller, const Vector4& color);
+
+  static const Vector4& GetInputColor(const Controller& controller);
+
+  static void SetInputLineSpacing(Controller& controller, float lineSpacing);
+
+  static float GetInputLineSpacing(const Controller& controller);
+
+  static void SetInputShadowProperties(Controller& controller, const std::string& shadowProperties);
+
+  static const std::string& GetInputShadowProperties(const Controller& controller);
+
+  static void SetInputUnderlineProperties(Controller& controller, const std::string& underlineProperties);
+
+  static const std::string& GetInputUnderlineProperties(const Controller& controller);
+
+  static void SetInputEmbossProperties(Controller& controller, const std::string& embossProperties);
+
+  static const std::string& GetInputEmbossProperties(const Controller& controller);
+
+  static void SetInputOutlineProperties(Controller& controller, const std::string& outlineProperties);
+
+  static const std::string& GetInputOutlineProperties(const Controller& controller);
+
+  static void SetInputModePassword(Controller& controller, bool passwordInput);
+
+  static bool IsInputModePassword(Controller& controller);
+};
+
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.cpp
new file mode 100644 (file)
index 0000000..da15a43
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-font-style.h>
+#include <dali-toolkit/public-api/controls/text-controls/placeholder-properties.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+const std::string EMPTY_STRING("");
+
+const char* const PLACEHOLDER_TEXT         = "text";
+const char* const PLACEHOLDER_TEXT_FOCUSED = "textFocused";
+const char* const PLACEHOLDER_COLOR        = "color";
+const char* const PLACEHOLDER_FONT_FAMILY  = "fontFamily";
+const char* const PLACEHOLDER_FONT_STYLE   = "fontStyle";
+const char* const PLACEHOLDER_POINT_SIZE   = "pointSize";
+const char* const PLACEHOLDER_PIXEL_SIZE   = "pixelSize";
+const char* const PLACEHOLDER_ELLIPSIS     = "ellipsis";
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void Controller::PlaceholderHandler::SetPlaceholderTextElideEnabled(Controller& controller, bool enabled)
+{
+  controller.mImpl->mEventData->mIsPlaceholderElideEnabled = enabled;
+  controller.mImpl->mEventData->mPlaceholderEllipsisFlag   = true;
+
+  // Update placeholder if there is no text
+  if(controller.mImpl->IsShowingPlaceholderText() ||
+     (0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
+  {
+    ShowPlaceholderText(*controller.mImpl);
+  }
+}
+
+bool Controller::PlaceholderHandler::IsPlaceholderTextElideEnabled(const Controller& controller)
+{
+  return controller.mImpl->mEventData->mIsPlaceholderElideEnabled;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderText(Controller& controller, PlaceholderType type, const std::string& text)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(PLACEHOLDER_TYPE_INACTIVE == type)
+    {
+      controller.mImpl->mEventData->mPlaceholderTextInactive = text;
+    }
+    else
+    {
+      controller.mImpl->mEventData->mPlaceholderTextActive = text;
+    }
+
+    // Update placeholder if there is no text
+    if(controller.mImpl->IsShowingPlaceholderText() ||
+       (0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
+    {
+      ShowPlaceholderText(*controller.mImpl);
+    }
+  }
+}
+
+void Controller::PlaceholderHandler::GetPlaceholderText(const Controller& controller, PlaceholderType type, std::string& text)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(PLACEHOLDER_TYPE_INACTIVE == type)
+    {
+      text = controller.mImpl->mEventData->mPlaceholderTextInactive;
+    }
+    else
+    {
+      text = controller.mImpl->mEventData->mPlaceholderTextActive;
+    }
+  }
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderFontFamily(Controller& controller, const std::string& placeholderTextFontFamily)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    // if mPlaceholderFont is null, create an instance.
+    CreatePlaceholderFont(controller);
+
+    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.family = placeholderTextFontFamily;
+    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetPlaceholderFontFamily %s\n", placeholderTextFontFamily.c_str());
+    controller.mImpl->mEventData->mPlaceholderFont->familyDefined = !placeholderTextFontFamily.empty();
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+const std::string& Controller::PlaceholderHandler::GetPlaceholderFontFamily(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.family;
+  }
+
+  return EMPTY_STRING;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderTextFontWeight(Controller& controller, FontWeight weight)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    // if mPlaceholderFont is null, create an instance.
+    CreatePlaceholderFont(controller);
+
+    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.weight = weight;
+    controller.mImpl->mEventData->mPlaceholderFont->weightDefined           = true;
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+bool Controller::PlaceholderHandler::IsPlaceholderTextFontWeightDefined(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->weightDefined;
+  }
+  return false;
+}
+
+FontWeight Controller::PlaceholderHandler::GetPlaceholderTextFontWeight(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.weight;
+  }
+
+  return TextAbstraction::FontWeight::NORMAL;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderTextFontWidth(Controller& controller, FontWidth width)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    // if mPlaceholderFont is null, create an instance.
+    CreatePlaceholderFont(controller);
+
+    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.width = width;
+    controller.mImpl->mEventData->mPlaceholderFont->widthDefined           = true;
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+bool Controller::PlaceholderHandler::IsPlaceholderTextFontWidthDefined(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->widthDefined;
+  }
+  return false;
+}
+
+FontWidth Controller::PlaceholderHandler::GetPlaceholderTextFontWidth(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.width;
+  }
+
+  return TextAbstraction::FontWidth::NORMAL;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderTextFontSlant(Controller& controller, FontSlant slant)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    // if mPlaceholderFont is null, create an instance.
+    CreatePlaceholderFont(controller);
+
+    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.slant = slant;
+    controller.mImpl->mEventData->mPlaceholderFont->slantDefined           = true;
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+bool Controller::PlaceholderHandler::IsPlaceholderTextFontSlantDefined(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->slantDefined;
+  }
+  return false;
+}
+
+FontSlant Controller::PlaceholderHandler::GetPlaceholderTextFontSlant(const Controller& controller)
+{
+  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
+  {
+    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.slant;
+  }
+
+  return TextAbstraction::FontSlant::NORMAL;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderTextFontSize(Controller& controller, float fontSize, FontSizeType type)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    // if mPlaceholderFont is null, create an instance.
+    CreatePlaceholderFont(controller);
+
+    switch(type)
+    {
+      case POINT_SIZE:
+      {
+        controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize = fontSize;
+        controller.mImpl->mEventData->mPlaceholderFont->sizeDefined       = true;
+        controller.mImpl->mEventData->mIsPlaceholderPixelSize             = false; // Font size flag
+        break;
+      }
+      case PIXEL_SIZE:
+      {
+        // Point size = Pixel size * 72.f / DPI
+        unsigned int                horizontalDpi = 0u;
+        unsigned int                verticalDpi   = 0u;
+        TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
+        fontClient.GetDpi(horizontalDpi, verticalDpi);
+
+        controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
+        controller.mImpl->mEventData->mPlaceholderFont->sizeDefined       = true;
+        controller.mImpl->mEventData->mIsPlaceholderPixelSize             = true; // Font size flag
+        break;
+      }
+    }
+
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+float Controller::PlaceholderHandler::GetPlaceholderTextFontSize(const Controller& controller, FontSizeType type)
+{
+  float value = 0.0f;
+  if(NULL != controller.mImpl->mEventData)
+  {
+    switch(type)
+    {
+      case POINT_SIZE:
+      {
+        if(NULL != controller.mImpl->mEventData->mPlaceholderFont)
+        {
+          value = controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize;
+        }
+        else
+        {
+          // If the placeholder text font size is not set, then return the default font size.
+          value = controller.GetDefaultFontSize(POINT_SIZE);
+        }
+        break;
+      }
+      case PIXEL_SIZE:
+      {
+        if(NULL != controller.mImpl->mEventData->mPlaceholderFont)
+        {
+          // Pixel size = Point size * DPI / 72.f
+          unsigned int                horizontalDpi = 0u;
+          unsigned int                verticalDpi   = 0u;
+          TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
+          fontClient.GetDpi(horizontalDpi, verticalDpi);
+
+          value = controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
+        }
+        else
+        {
+          // If the placeholder text font size is not set, then return the default font size.
+          value = controller.GetDefaultFontSize(PIXEL_SIZE);
+        }
+        break;
+      }
+    }
+    return value;
+  }
+
+  return value;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderTextColor(Controller& controller, const Vector4& textColor)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    controller.mImpl->mEventData->mPlaceholderTextColor = textColor;
+  }
+
+  if(controller.mImpl->IsShowingPlaceholderText())
+  {
+    controller.mImpl->mModel->mVisualModel->SetTextColor(textColor);
+    controller.mImpl->mModel->mLogicalModel->mColorRuns.Clear();
+    controller.mImpl->mOperationsPending = static_cast<OperationsMask>(controller.mImpl->mOperationsPending | COLOR);
+    controller.mImpl->RequestRelayout();
+  }
+}
+
+const Vector4& Controller::PlaceholderHandler::GetPlaceholderTextColor(const Controller& controller)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    return controller.mImpl->mEventData->mPlaceholderTextColor;
+  }
+
+  return Color::BLACK;
+}
+
+void Controller::PlaceholderHandler::SetPlaceholderProperty(Controller& controller, const Property::Map& map)
+{
+  const Property::Map::SizeType count = map.Count();
+
+  for(Property::Map::SizeType position = 0; position < count; ++position)
+  {
+    KeyValuePair     keyValue = map.GetKeyValue(position);
+    Property::Key&   key      = keyValue.first;
+    Property::Value& value    = keyValue.second;
+
+    if(key == Toolkit::Text::PlaceHolder::Property::TEXT || key == PLACEHOLDER_TEXT)
+    {
+      std::string text = "";
+      value.Get(text);
+      SetPlaceholderText(controller, Controller::PLACEHOLDER_TYPE_INACTIVE, text);
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::TEXT_FOCUSED || key == PLACEHOLDER_TEXT_FOCUSED)
+    {
+      std::string text = "";
+      value.Get(text);
+      SetPlaceholderText(controller, Controller::PLACEHOLDER_TYPE_ACTIVE, text);
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::COLOR || key == PLACEHOLDER_COLOR)
+    {
+      Vector4 textColor;
+      value.Get(textColor);
+      if(GetPlaceholderTextColor(controller) != textColor)
+      {
+        SetPlaceholderTextColor(controller, textColor);
+      }
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::FONT_FAMILY || key == PLACEHOLDER_FONT_FAMILY)
+    {
+      std::string fontFamily = "";
+      value.Get(fontFamily);
+      SetPlaceholderFontFamily(controller, fontFamily);
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::FONT_STYLE || key == PLACEHOLDER_FONT_STYLE)
+    {
+      SetFontStyleProperty(&controller, value, Text::FontStyle::PLACEHOLDER);
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::POINT_SIZE || key == PLACEHOLDER_POINT_SIZE)
+    {
+      float pointSize;
+      value.Get(pointSize);
+      if(!Equals(GetPlaceholderTextFontSize(controller, Text::Controller::POINT_SIZE), pointSize))
+      {
+        SetPlaceholderTextFontSize(controller, pointSize, Text::Controller::POINT_SIZE);
+      }
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::PIXEL_SIZE || key == PLACEHOLDER_PIXEL_SIZE)
+    {
+      float pixelSize;
+      value.Get(pixelSize);
+      if(!Equals(GetPlaceholderTextFontSize(controller, Text::Controller::PIXEL_SIZE), pixelSize))
+      {
+        SetPlaceholderTextFontSize(controller, pixelSize, Text::Controller::PIXEL_SIZE);
+      }
+    }
+    else if(key == Toolkit::Text::PlaceHolder::Property::ELLIPSIS || key == PLACEHOLDER_ELLIPSIS)
+    {
+      bool ellipsis;
+      value.Get(ellipsis);
+      SetPlaceholderTextElideEnabled(controller, ellipsis);
+    }
+  }
+}
+
+void Controller::PlaceholderHandler::GetPlaceholderProperty(Controller& controller, Property::Map& map)
+{
+  if(NULL != controller.mImpl->mEventData)
+  {
+    if(!controller.mImpl->mEventData->mPlaceholderTextActive.empty())
+    {
+      map[Text::PlaceHolder::Property::TEXT_FOCUSED] = controller.mImpl->mEventData->mPlaceholderTextActive;
+    }
+    if(!controller.mImpl->mEventData->mPlaceholderTextInactive.empty())
+    {
+      map[Text::PlaceHolder::Property::TEXT] = controller.mImpl->mEventData->mPlaceholderTextInactive;
+    }
+
+    map[Text::PlaceHolder::Property::COLOR]       = controller.mImpl->mEventData->mPlaceholderTextColor;
+    map[Text::PlaceHolder::Property::FONT_FAMILY] = GetPlaceholderFontFamily(controller);
+
+    Property::Value fontStyleMapGet;
+    GetFontStyleProperty(&controller, fontStyleMapGet, Text::FontStyle::PLACEHOLDER);
+    map[Text::PlaceHolder::Property::FONT_STYLE] = fontStyleMapGet;
+
+    // Choose font size : POINT_SIZE or PIXEL_SIZE
+    if(!controller.mImpl->mEventData->mIsPlaceholderPixelSize)
+    {
+      map[Text::PlaceHolder::Property::POINT_SIZE] = GetPlaceholderTextFontSize(controller, Text::Controller::POINT_SIZE);
+    }
+    else
+    {
+      map[Text::PlaceHolder::Property::PIXEL_SIZE] = GetPlaceholderTextFontSize(controller, Text::Controller::PIXEL_SIZE);
+    }
+
+    if(controller.mImpl->mEventData->mPlaceholderEllipsisFlag)
+    {
+      map[Text::PlaceHolder::Property::ELLIPSIS] = IsPlaceholderTextElideEnabled(controller);
+    }
+  }
+}
+
+void Controller::PlaceholderHandler::ShowPlaceholderText(Controller::Impl& impl)
+{
+  if(impl.IsPlaceholderAvailable())
+  {
+    EventData*& eventData = impl.mEventData;
+    DALI_ASSERT_DEBUG(eventData && "No placeholder text available");
+
+    if(NULL == eventData)
+    {
+      return;
+    }
+
+    eventData->mIsShowingPlaceholderText = true;
+
+    // Disable handles when showing place-holder text
+    DecoratorPtr& decorator = eventData->mDecorator;
+    decorator->SetHandleActive(GRAB_HANDLE, false);
+    decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
+    decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
+
+    const char* text(NULL);
+    size_t      size(0);
+
+    // TODO - Switch Placeholder text when changing state
+    std::string& placeholderTextActive = eventData->mPlaceholderTextActive;
+    if((EventData::INACTIVE != eventData->mState) &&
+       (0u != placeholderTextActive.c_str()))
+    {
+      text = placeholderTextActive.c_str();
+      size = placeholderTextActive.size();
+    }
+    else
+    {
+      std::string& placeholderTextInactive = eventData->mPlaceholderTextInactive;
+      text                                 = placeholderTextInactive.c_str();
+      size                                 = placeholderTextInactive.size();
+    }
+
+    TextUpdateInfo& textUpdateInfo             = impl.mTextUpdateInfo;
+    textUpdateInfo.mCharacterIndex             = 0u;
+    textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
+
+    // Reset model for showing placeholder.
+    ModelPtr&        model        = impl.mModel;
+    LogicalModelPtr& logicalModel = model->mLogicalModel;
+    logicalModel->mText.Clear();
+    model->mVisualModel->SetTextColor(eventData->mPlaceholderTextColor);
+
+    // Convert text into UTF-32
+    Vector<Character>& utf32Characters = logicalModel->mText;
+    utf32Characters.Resize(size);
+
+    // This is a bit horrible but std::string returns a (signed) char*
+    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text);
+
+    // Transform a text array encoded in utf8 into an array encoded in utf32.
+    // It returns the actual number of characters.
+    const Length characterCount = Utf8ToUtf32(utf8, size, utf32Characters.Begin());
+    utf32Characters.Resize(characterCount);
+
+    // The characters to be added.
+    textUpdateInfo.mNumberOfCharactersToAdd = characterCount;
+
+    // Reset the cursor position
+    eventData->mPrimaryCursorPosition = 0;
+
+    // The natural size needs to be re-calculated.
+    impl.mRecalculateNaturalSize = true;
+
+    // The text direction needs to be updated.
+    impl.mUpdateTextDirection = true;
+
+    // Apply modifications to the model
+    impl.mOperationsPending = ALL_OPERATIONS;
+
+    // Update the rest of the model during size negotiation
+    impl.QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
+  }
+}
+
+void Controller::PlaceholderHandler::CreatePlaceholderFont(Controller& controller)
+{
+  if(nullptr == controller.mImpl->mEventData->mPlaceholderFont)
+  {
+    controller.mImpl->mEventData->mPlaceholderFont = std::unique_ptr<FontDefaults>(new FontDefaults());
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h b/dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h
new file mode 100644 (file)
index 0000000..c7107c9
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/object/property-map.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Controller::PlaceholderHandler
+{
+  static void               SetPlaceholderTextElideEnabled(Controller& controller, bool enabled);
+  static bool               IsPlaceholderTextElideEnabled(const Controller& controller);
+  static void               SetPlaceholderText(Controller& controller, PlaceholderType type, const std::string& text);
+  static void               GetPlaceholderText(const Controller& controller, PlaceholderType type, std::string& text);
+  static void               SetPlaceholderFontFamily(Controller& controller, const std::string& placeholderTextFontFamily);
+  static const std::string& GetPlaceholderFontFamily(const Controller& controller);
+  static void               SetPlaceholderTextFontWeight(Controller& controller, FontWeight weight);
+  static bool               IsPlaceholderTextFontWeightDefined(const Controller& controller);
+  static FontWeight         GetPlaceholderTextFontWeight(const Controller& controller);
+  static void               SetPlaceholderTextFontWidth(Controller& controller, FontWidth width);
+  static bool               IsPlaceholderTextFontWidthDefined(const Controller& controller);
+  static FontWidth          GetPlaceholderTextFontWidth(const Controller& controller);
+  static void               SetPlaceholderTextFontSlant(Controller& controller, FontSlant slant);
+  static bool               IsPlaceholderTextFontSlantDefined(const Controller& controller);
+  static FontSlant          GetPlaceholderTextFontSlant(const Controller& controller);
+  static void               SetPlaceholderTextFontSize(Controller& controller, float fontSize, FontSizeType type);
+  static float              GetPlaceholderTextFontSize(const Controller& controller, FontSizeType type);
+  static void               SetPlaceholderTextColor(Controller& controller, const Vector4& textColor);
+  static const Vector4&     GetPlaceholderTextColor(const Controller& controller);
+  static void               SetPlaceholderProperty(Controller& controller, const Property::Map& map);
+  static void               GetPlaceholderProperty(Controller& controller, Property::Map& map);
+  static void               ShowPlaceholderText(Controller::Impl& impl);
+  static void               CreatePlaceholderFont(Controller& controller);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-relayouter.cpp b/dali-toolkit/internal/text/controller/text-controller-relayouter.cpp
new file mode 100644 (file)
index 0000000..3b0c4c3
--- /dev/null
@@ -0,0 +1,869 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
+
+float ConvertToEven(float value)
+{
+  int intValue(static_cast<int>(value));
+  return static_cast<float>(intValue + (intValue & 1));
+}
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->CalculateLayoutSizeOnRequiredControllerSize\n");
+  Size calculatedLayoutSize;
+
+  Controller::Impl& impl        = *controller.mImpl;
+  ModelPtr&         model       = impl.mModel;
+  VisualModelPtr&   visualModel = model->mVisualModel;
+
+  // Operations that can be done only once until the text changes.
+  const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
+                                                                        GET_SCRIPTS |
+                                                                        VALIDATE_FONTS |
+                                                                        GET_LINE_BREAKS |
+                                                                        BIDI_INFO |
+                                                                        SHAPE_TEXT |
+                                                                        GET_GLYPH_METRICS);
+
+  const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT | ALIGN | REORDER);
+
+  // Set the update info to relayout the whole text.
+  TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+  if((0 == textUpdateInfo.mNumberOfCharactersToAdd) &&
+     (0 == textUpdateInfo.mPreviousNumberOfCharacters) &&
+     ((visualModel->mControlSize.width < Math::MACHINE_EPSILON_1000) || (visualModel->mControlSize.height < Math::MACHINE_EPSILON_1000)))
+  {
+    textUpdateInfo.mNumberOfCharactersToAdd = model->mLogicalModel->mText.Count();
+  }
+  textUpdateInfo.mParagraphCharacterIndex     = 0u;
+  textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count();
+
+  // Get a reference to the pending operations member
+  OperationsMask& operationsPending = impl.mOperationsPending;
+
+  // Store the actual control's size to restore later.
+  const Size actualControlSize = visualModel->mControlSize;
+
+  // Whether the text control is editable
+  const bool isEditable = NULL != impl.mEventData;
+
+  if(!isEditable)
+  {
+    impl.UpdateModel(onlyOnceOperations);
+
+    // Layout the text for the new width.
+    operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask);
+
+    DoRelayout(impl,
+               requestedControllerSize,
+               static_cast<OperationsMask>(onlyOnceOperations | requestedOperationsMask),
+               calculatedLayoutSize);
+
+    textUpdateInfo.Clear();
+    textUpdateInfo.mClearAll = true;
+
+    // Do not do again the only once operations.
+    operationsPending = static_cast<OperationsMask>(operationsPending & ~onlyOnceOperations);
+  }
+  else
+  {
+    // This is to keep Index to the first character to be updated.
+    // Then restore it after calling Clear method.
+    auto updateInfoCharIndexBackup = textUpdateInfo.mCharacterIndex;
+
+    // Layout the text for the new width.
+    // Apply the pending operations, requested operations and the only once operations.
+    // Then remove onlyOnceOperations
+    operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask | onlyOnceOperations);
+
+    // Make sure the model is up-to-date before layouting
+    impl.UpdateModel(static_cast<OperationsMask>(operationsPending & ~UPDATE_LAYOUT_SIZE));
+
+    DoRelayout(impl,
+               requestedControllerSize,
+               static_cast<OperationsMask>(operationsPending & ~UPDATE_LAYOUT_SIZE),
+               calculatedLayoutSize);
+
+    // Clear the update info. This info will be set the next time the text is updated.
+    textUpdateInfo.Clear();
+
+    //TODO: Refactor "DoRelayout" and extract common code of size calculation without modifying attributes of mVisualModel,
+    //TODO: then calculate GlyphPositions. Lines, Size, Layout for Natural-Size
+    //TODO: and utilize the values in OperationsPending and TextUpdateInfo without changing the original one.
+    //TODO: Also it will improve performance because there is no need todo FullRelyout on the next need for layouting.
+
+    // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
+    // By this no need to take backup and restore it.
+    textUpdateInfo.mFullRelayoutNeeded = true;
+
+    // Restore mCharacterIndex. Because "Clear" set it to the maximum integer.
+    // The "CalculateTextUpdateIndices" does not work proprely because the mCharacterIndex will be greater than mPreviousNumberOfCharacters.
+    // Which apply an assumption to update only the last  paragraph. That could cause many of out of index crashes.
+    textUpdateInfo.mCharacterIndex = updateInfoCharIndexBackup;
+  }
+
+  // Do the size related operations again.
+  operationsPending = static_cast<OperationsMask>(operationsPending | sizeOperations);
+
+  // Restore the actual control's size.
+  visualModel->mControlSize = actualControlSize;
+
+  return calculatedLayoutSize;
+}
+
+Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
+  Vector3 naturalSizeVec3;
+
+  // Make sure the model is up-to-date before layouting
+  EventHandler::ProcessModifyEvents(controller);
+
+  Controller::Impl& impl        = *controller.mImpl;
+  ModelPtr&         model       = impl.mModel;
+  VisualModelPtr&   visualModel = model->mVisualModel;
+
+  if(impl.mRecalculateNaturalSize)
+  {
+    Size naturalSize;
+
+    // Layout the text for the new width.
+    OperationsMask requestedOperationsMask  = static_cast<OperationsMask>(LAYOUT | REORDER);
+    Size           sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
+
+    naturalSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeMaxWidthAndMaxHeight, requestedOperationsMask);
+
+    // Stores the natural size to avoid recalculate it again
+    // unless the text/style changes.
+    visualModel->SetNaturalSize(naturalSize);
+    naturalSizeVec3 = naturalSize;
+
+    impl.mRecalculateNaturalSize = false;
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
+  }
+  else
+  {
+    naturalSizeVec3 = visualModel->GetNaturalSize();
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
+  }
+
+  naturalSizeVec3.x = ConvertToEven(naturalSizeVec3.x);
+  naturalSizeVec3.y = ConvertToEven(naturalSizeVec3.y);
+
+  return naturalSizeVec3;
+}
+
+bool Controller::Relayouter::CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize)
+{
+  Size              textSize;
+  Controller::Impl& impl            = *controller.mImpl;
+  TextUpdateInfo&   textUpdateInfo  = impl.mTextUpdateInfo;
+  impl.mFontDefaults->mFitPointSize = pointSize;
+  impl.mFontDefaults->sizeDefined   = true;
+  impl.ClearFontData();
+
+  // Operations that can be done only once until the text changes.
+  const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
+                                                                        GET_SCRIPTS |
+                                                                        VALIDATE_FONTS |
+                                                                        GET_LINE_BREAKS |
+                                                                        BIDI_INFO |
+                                                                        SHAPE_TEXT |
+                                                                        GET_GLYPH_METRICS);
+
+  textUpdateInfo.mParagraphCharacterIndex     = 0u;
+  textUpdateInfo.mRequestedNumberOfCharacters = impl.mModel->mLogicalModel->mText.Count();
+
+  // Make sure the model is up-to-date before layouting
+  impl.UpdateModel(onlyOnceOperations);
+
+  DoRelayout(impl,
+             Size(layoutSize.width, MAX_FLOAT),
+             static_cast<OperationsMask>(onlyOnceOperations | LAYOUT),
+             textSize);
+
+  // Clear the update info. This info will be set the next time the text is updated.
+  textUpdateInfo.Clear();
+  textUpdateInfo.mClearAll = true;
+
+  if(textSize.width > layoutSize.width || textSize.height > layoutSize.height)
+  {
+    return false;
+  }
+  return true;
+}
+
+void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const Size& layoutSize)
+{
+  Controller::Impl& impl = *controller.mImpl;
+
+  const OperationsMask operations = impl.mOperationsPending;
+  if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations) || impl.mTextFitContentSize != layoutSize)
+  {
+    ModelPtr& model = impl.mModel;
+
+    bool  actualellipsis      = model->mElideEnabled;
+    float minPointSize        = impl.mTextFitMinSize;
+    float maxPointSize        = impl.mTextFitMaxSize;
+    float pointInterval       = impl.mTextFitStepSize;
+    float currentFitPointSize = impl.mFontDefaults->mFitPointSize;
+
+    model->mElideEnabled = false;
+    Vector<float> pointSizeArray;
+
+    // check zero value
+    if(pointInterval < 1.f)
+    {
+      impl.mTextFitStepSize = pointInterval = 1.0f;
+    }
+
+    pointSizeArray.Reserve(static_cast<unsigned int>(ceil((maxPointSize - minPointSize) / pointInterval)));
+
+    for(float i = minPointSize; i < maxPointSize; i += pointInterval)
+    {
+      pointSizeArray.PushBack(i);
+    }
+
+    pointSizeArray.PushBack(maxPointSize);
+
+    int bestSizeIndex = 0;
+    int min           = bestSizeIndex + 1;
+    int max           = pointSizeArray.Size() - 1;
+    while(min <= max)
+    {
+      int destI = (min + max) / 2;
+
+      if(CheckForTextFit(controller, pointSizeArray[destI], layoutSize))
+      {
+        bestSizeIndex = min;
+        min           = destI + 1;
+      }
+      else
+      {
+        max           = destI - 1;
+        bestSizeIndex = max;
+      }
+    }
+
+    model->mElideEnabled = actualellipsis;
+    if(currentFitPointSize != pointSizeArray[bestSizeIndex])
+    {
+      impl.mTextFitChanged = true;
+    }
+    impl.mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
+    impl.mFontDefaults->sizeDefined   = true;
+    impl.ClearFontData();
+  }
+}
+
+float Controller::Relayouter::GetHeightForWidth(Controller& controller, float width)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width);
+
+  // Make sure the model is up-to-date before layouting
+  EventHandler::ProcessModifyEvents(controller);
+
+  Controller::Impl& impl           = *controller.mImpl;
+  ModelPtr&         model          = impl.mModel;
+  VisualModelPtr&   visualModel    = model->mVisualModel;
+  TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
+
+  Size layoutSize;
+
+  if(fabsf(width - visualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 ||
+     textUpdateInfo.mFullRelayoutNeeded ||
+     textUpdateInfo.mClearAll)
+  {
+    // Layout the text for the new width.
+    OperationsMask requestedOperationsMask        = static_cast<OperationsMask>(LAYOUT);
+    Size           sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT);
+
+    layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask);
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
+  }
+  else
+  {
+    layoutSize = visualModel->GetLayoutSize();
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height);
+  }
+
+  return layoutSize.height;
+}
+
+Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controller, const Size& size, Dali::LayoutDirection::Type layoutDirection)
+{
+  Controller::Impl& impl           = *controller.mImpl;
+  ModelPtr&         model          = impl.mModel;
+  VisualModelPtr&   visualModel    = model->mVisualModel;
+  TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
+
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", &controller, size.width, size.height, impl.mIsAutoScrollEnabled ? "true" : "false");
+
+  UpdateTextType updateTextType = NONE_UPDATED;
+
+  if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
+  {
+    if(0u != visualModel->mGlyphPositions.Count())
+    {
+      visualModel->mGlyphPositions.Clear();
+      updateTextType = MODEL_UPDATED;
+    }
+
+    // Clear the update info. This info will be set the next time the text is updated.
+    textUpdateInfo.Clear();
+
+    // Not worth to relayout if width or height is equal to zero.
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n");
+
+    return updateTextType;
+  }
+
+  // Whether a new size has been set.
+  const bool newSize = (size != visualModel->mControlSize);
+
+  // Get a reference to the pending operations member
+  OperationsMask& operationsPending = impl.mOperationsPending;
+
+  if(newSize)
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", visualModel->mControlSize.width, visualModel->mControlSize.height);
+
+    if((0 == textUpdateInfo.mNumberOfCharactersToAdd) &&
+       (0 == textUpdateInfo.mPreviousNumberOfCharacters) &&
+       ((visualModel->mControlSize.width < Math::MACHINE_EPSILON_1000) || (visualModel->mControlSize.height < Math::MACHINE_EPSILON_1000)))
+    {
+      textUpdateInfo.mNumberOfCharactersToAdd = model->mLogicalModel->mText.Count();
+    }
+
+    // Layout operations that need to be done if the size changes.
+    operationsPending = static_cast<OperationsMask>(operationsPending |
+                                                    LAYOUT |
+                                                    ALIGN |
+                                                    UPDATE_LAYOUT_SIZE |
+                                                    REORDER);
+    // Set the update info to relayout the whole text.
+    textUpdateInfo.mFullRelayoutNeeded = true;
+    textUpdateInfo.mCharacterIndex     = 0u;
+
+    // Store the size used to layout the text.
+    visualModel->mControlSize = size;
+  }
+
+  // Whether there are modify events.
+  if(0u != impl.mModifyEvents.Count())
+  {
+    // Style operations that need to be done if the text is modified.
+    operationsPending = static_cast<OperationsMask>(operationsPending | COLOR);
+  }
+
+  // Set the update info to elide the text.
+  if(model->mElideEnabled ||
+     ((NULL != impl.mEventData) && impl.mEventData->mIsPlaceholderElideEnabled))
+  {
+    // Update Text layout for applying elided
+    operationsPending                  = static_cast<OperationsMask>(operationsPending |
+                                                    ALIGN |
+                                                    LAYOUT |
+                                                    UPDATE_LAYOUT_SIZE |
+                                                    REORDER);
+    textUpdateInfo.mFullRelayoutNeeded = true;
+    textUpdateInfo.mCharacterIndex     = 0u;
+  }
+
+  bool layoutDirectionChanged = false;
+  if(impl.mLayoutDirection != layoutDirection)
+  {
+    // Flag to indicate that the layout direction has changed.
+    layoutDirectionChanged = true;
+    // Clear the update info. This info will be set the next time the text is updated.
+    textUpdateInfo.mClearAll = true;
+    // Apply modifications to the model
+    // Shape the text again is needed because characters like '()[]{}' have to be mirrored and the glyphs generated again.
+    operationsPending     = static_cast<OperationsMask>(operationsPending |
+                                                    GET_GLYPH_METRICS |
+                                                    SHAPE_TEXT |
+                                                    UPDATE_DIRECTION |
+                                                    ALIGN |
+                                                    LAYOUT |
+                                                    BIDI_INFO |
+                                                    REORDER);
+    impl.mLayoutDirection = layoutDirection;
+  }
+
+  // Make sure the model is up-to-date before layouting.
+  EventHandler::ProcessModifyEvents(controller);
+  bool updated = impl.UpdateModel(operationsPending);
+
+  // Layout the text.
+  Size layoutSize;
+  updated = DoRelayout(impl, size, operationsPending, layoutSize) || updated;
+
+  if(updated)
+  {
+    updateTextType = MODEL_UPDATED;
+  }
+
+  // Do not re-do any operation until something changes.
+  operationsPending          = NO_OPERATION;
+  model->mScrollPositionLast = model->mScrollPosition;
+
+  // Whether the text control is editable
+  const bool isEditable = NULL != impl.mEventData;
+
+  // Keep the current offset as it will be used to update the decorator's positions (if the size changes).
+  Vector2 offset;
+  if(newSize && isEditable)
+  {
+    offset = model->mScrollPosition;
+  }
+
+  if(!isEditable || !controller.IsMultiLineEnabled())
+  {
+    // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
+    CalculateVerticalOffset(impl, size);
+  }
+  else // TextEditor
+  {
+    // If layoutSize is bigger than size, vertical align has no meaning.
+    if(layoutSize.y < size.y)
+    {
+      CalculateVerticalOffset(impl, size);
+      if(impl.mEventData)
+      {
+        impl.mEventData->mScrollAfterDelete = false;
+      }
+    }
+  }
+
+  if(isEditable)
+  {
+    if(newSize || layoutDirectionChanged)
+    {
+      // If there is a new size or layout direction is changed, the scroll position needs to be clamped.
+      impl.ClampHorizontalScroll(layoutSize);
+
+      // Update the decorator's positions is needed if there is a new size.
+      impl.mEventData->mDecorator->UpdatePositions(model->mScrollPosition - offset);
+
+      // All decorator elements need to be updated.
+      if(EventData::IsEditingState(impl.mEventData->mState))
+      {
+        impl.mEventData->mScrollAfterUpdatePosition = true;
+        impl.mEventData->mUpdateCursorPosition      = true;
+        impl.mEventData->mUpdateGrabHandlePosition  = true;
+      }
+      else if(impl.mEventData->mState == EventData::SELECTING)
+      {
+        impl.mEventData->mUpdateHighlightBox = true;
+      }
+    }
+
+    // Move the cursor, grab handle etc.
+    if(impl.ProcessInputEvents())
+    {
+      updateTextType = static_cast<UpdateTextType>(updateTextType | DECORATOR_UPDATED);
+    }
+  }
+
+  // Clear the update info. This info will be set the next time the text is updated.
+  textUpdateInfo.Clear();
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout\n");
+
+  return updateTextType;
+}
+
+bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayouter::DoRelayout %p size %f,%f\n", &impl, size.width, size.height);
+  bool viewUpdated(false);
+
+  // Calculate the operations to be done.
+  const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
+
+  TextUpdateInfo&      textUpdateInfo              = impl.mTextUpdateInfo;
+  const CharacterIndex startIndex                  = textUpdateInfo.mParagraphCharacterIndex;
+  const Length         requestedNumberOfCharacters = textUpdateInfo.mRequestedNumberOfCharacters;
+
+  // Get the current layout size.
+  VisualModelPtr& visualModel = impl.mModel->mVisualModel;
+  layoutSize                  = visualModel->GetLayoutSize();
+
+  if(NO_OPERATION != (LAYOUT & operations))
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n");
+
+    // Some vectors with data needed to layout and reorder may be void
+    // after the first time the text has been laid out.
+    // Fill the vectors again.
+
+    // Calculate the number of glyphs to layout.
+    const Vector<GlyphIndex>& charactersToGlyph        = visualModel->mCharactersToGlyph;
+    const Vector<Length>&     glyphsPerCharacter       = visualModel->mGlyphsPerCharacter;
+    const GlyphIndex* const   charactersToGlyphBuffer  = charactersToGlyph.Begin();
+    const Length* const       glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+
+    const CharacterIndex lastIndex       = startIndex + ((requestedNumberOfCharacters > 0u) ? requestedNumberOfCharacters - 1u : 0u);
+    const GlyphIndex     startGlyphIndex = textUpdateInfo.mStartGlyphIndex;
+
+    // Make sure the index is not out of bound
+    if(charactersToGlyph.Count() != glyphsPerCharacter.Count() ||
+       requestedNumberOfCharacters > charactersToGlyph.Count() ||
+       (lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u))
+    {
+      std::string currentText;
+      impl.GetText(currentText);
+
+      DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n");
+      DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str());
+      DALI_LOG_ERROR("startIndex: %u, lastIndex: %u, requestedNumberOfCharacters: %u, charactersToGlyph.Count = %lu, glyphsPerCharacter.Count = %lu\n", startIndex, lastIndex, requestedNumberOfCharacters, charactersToGlyph.Count(), glyphsPerCharacter.Count());
+
+      return false;
+    }
+
+    const Length numberOfGlyphs      = (requestedNumberOfCharacters > 0u) ? *(charactersToGlyphBuffer + lastIndex) + *(glyphsPerCharacterBuffer + lastIndex) - startGlyphIndex : 0u;
+    const Length totalNumberOfGlyphs = visualModel->mGlyphs.Count();
+
+    if(0u == totalNumberOfGlyphs)
+    {
+      if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
+      {
+        visualModel->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;
+    }
+
+    // Set the layout parameters.
+    Layout::Parameters layoutParameters(size, impl.mModel);
+
+    // Resize the vector of positions to have the same size than the vector of glyphs.
+    Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+    glyphPositions.Resize(totalNumberOfGlyphs);
+
+    // Whether the last character is a new paragraph character.
+    const Character* const textBuffer           = impl.mModel->mLogicalModel->mText.Begin();
+    textUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph(*(textBuffer + (impl.mModel->mLogicalModel->mText.Count() - 1u)));
+    layoutParameters.isLastNewParagraph         = textUpdateInfo.mIsLastCharacterNewParagraph;
+
+    // The initial glyph and the number of glyphs to layout.
+    layoutParameters.startGlyphIndex        = startGlyphIndex;
+    layoutParameters.numberOfGlyphs         = numberOfGlyphs;
+    layoutParameters.startLineIndex         = textUpdateInfo.mStartLineIndex;
+    layoutParameters.estimatedNumberOfLines = textUpdateInfo.mEstimatedNumberOfLines;
+
+    // Update the ellipsis
+    bool elideTextEnabled = impl.mModel->mElideEnabled;
+    auto ellipsisPosition = impl.mModel->mEllipsisPosition;
+
+    if(NULL != impl.mEventData)
+    {
+      if(impl.mEventData->mPlaceholderEllipsisFlag && impl.IsShowingPlaceholderText())
+      {
+        elideTextEnabled = impl.mEventData->mIsPlaceholderElideEnabled;
+      }
+      else if(EventData::INACTIVE != impl.mEventData->mState)
+      {
+        // Disable ellipsis when editing
+        elideTextEnabled = false;
+      }
+
+      // Reset the scroll position in inactive state
+      if(elideTextEnabled && (impl.mEventData->mState == EventData::INACTIVE))
+      {
+        impl.ResetScrollPosition();
+      }
+    }
+
+    // Update the visual model.
+    bool isAutoScrollEnabled            = impl.mIsAutoScrollEnabled;
+    bool isAutoScrollMaxTextureExceeded = impl.mIsAutoScrollMaxTextureExceeded;
+
+    Size newLayoutSize;
+    viewUpdated               = impl.mLayoutEngine.LayoutText(layoutParameters,
+                                                newLayoutSize,
+                                                elideTextEnabled,
+                                                isAutoScrollEnabled,
+                                                isAutoScrollMaxTextureExceeded,
+                                                ellipsisPosition);
+    impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
+
+    viewUpdated = viewUpdated || (newLayoutSize != layoutSize);
+
+    if(viewUpdated)
+    {
+      layoutSize = newLayoutSize;
+
+      if(NO_OPERATION != (UPDATE_DIRECTION & operations))
+      {
+        impl.mIsTextDirectionRTL = false;
+      }
+
+      if((NO_OPERATION != (UPDATE_DIRECTION & operations)) && !visualModel->mLines.Empty())
+      {
+        impl.mIsTextDirectionRTL = visualModel->mLines[0u].direction;
+      }
+
+      // Sets the layout size.
+      if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
+      {
+        visualModel->SetLayoutSize(layoutSize);
+      }
+    } // view updated
+  }
+
+  if(NO_OPERATION != (ALIGN & operations))
+  {
+    DoRelayoutHorizontalAlignment(impl, size, startIndex, requestedNumberOfCharacters);
+    viewUpdated = true;
+  }
+#if defined(DEBUG_ENABLED)
+  std::string currentText;
+  impl.GetText(currentText);
+  DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::Relayouter::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &impl, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
+#endif
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayouter::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
+  return viewUpdated;
+}
+
+void Controller::Relayouter::DoRelayoutHorizontalAlignment(Controller::Impl&    impl,
+                                                           const Size&          size,
+                                                           const CharacterIndex startIndex,
+                                                           const Length         requestedNumberOfCharacters)
+{
+  // The visualModel
+  VisualModelPtr& visualModel = impl.mModel->mVisualModel;
+
+  // The laid-out lines.
+  Vector<LineRun>& lines = visualModel->mLines;
+
+  CharacterIndex alignStartIndex                  = startIndex;
+  Length         alignRequestedNumberOfCharacters = requestedNumberOfCharacters;
+
+  // the whole text needs to be full aligned.
+  // If you do not do a full aligned, only the last line of the multiline input is aligned.
+  if(impl.mEventData && impl.mEventData->mUpdateAlignment)
+  {
+    alignStartIndex                   = 0u;
+    alignRequestedNumberOfCharacters  = impl.mModel->mLogicalModel->mText.Count();
+    impl.mEventData->mUpdateAlignment = false;
+  }
+
+  // If there is no BoundedParagraphRuns then apply the alignment of controller.
+  // Check whether the layout is single line. It's needed to apply one alignment for single-line.
+  // In single-line layout case we need to check whether to follow the alignment of controller or the first BoundedParagraph.
+  // Apply BoundedParagraph's alignment if and only if there is one BoundedParagraph contains all characters. Otherwise follow controller's alignment.
+  const bool isFollowControllerAlignment = ((impl.mModel->GetNumberOfBoundedParagraphRuns() == 0u) ||
+                                            ((Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout()) &&
+                                             (impl.mModel->GetBoundedParagraphRuns()[0].characterRun.numberOfCharacters != impl.mModel->mLogicalModel->mText.Count())));
+
+  if(isFollowControllerAlignment)
+  {
+    // Need to align with the control's size as the text may contain lines
+    // starting either with left to right text or right to left.
+    impl.mLayoutEngine.Align(size,
+                             alignStartIndex,
+                             alignRequestedNumberOfCharacters,
+                             impl.mModel->mHorizontalAlignment,
+                             lines,
+                             impl.mModel->mAlignmentOffset,
+                             impl.mLayoutDirection,
+                             (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
+  }
+  else
+  {
+    //Override the controller horizontal-alignment by horizontal-alignment of bounded paragraph.
+    const Length&                      numberOfBoundedParagraphRuns = impl.mModel->GetNumberOfBoundedParagraphRuns();
+    const Vector<BoundedParagraphRun>& boundedParagraphRuns         = impl.mModel->GetBoundedParagraphRuns();
+    const CharacterIndex               alignEndIndex                = alignStartIndex + alignRequestedNumberOfCharacters - 1u;
+
+    Length alignIndex               = alignStartIndex;
+    Length boundedParagraphRunIndex = 0u;
+
+    while(alignIndex <= alignEndIndex && boundedParagraphRunIndex < numberOfBoundedParagraphRuns)
+    {
+      //BP: BoundedParagraph
+      const BoundedParagraphRun& boundedParagraphRun   = boundedParagraphRuns[boundedParagraphRunIndex];
+      const CharacterIndex&      characterStartIndexBP = boundedParagraphRun.characterRun.characterIndex;
+      const Length&              numberOfCharactersBP  = boundedParagraphRun.characterRun.numberOfCharacters;
+      const CharacterIndex       characterEndIndexBP   = characterStartIndexBP + numberOfCharactersBP - 1u;
+
+      CharacterIndex                  decidedAlignStartIndex         = alignIndex;
+      Length                          decidedAlignNumberOfCharacters = alignEndIndex - alignIndex + 1u;
+      Text::HorizontalAlignment::Type decidedHorizontalAlignment     = impl.mModel->mHorizontalAlignment;
+
+      /*
+         * Shortcuts to explain indexes cases:
+         *
+         * AS: Alignment Start Index
+         * AE: Alignment End Index
+         * PS: Paragraph Start Index
+         * PE: Paragraph End Index
+         * B: BoundedParagraph Alignment
+         * M: Model Alignment
+         *
+         */
+
+      if(alignIndex < characterStartIndexBP && characterStartIndexBP <= alignEndIndex) /// AS.MMMMMM.PS--------AE
+      {
+        // Alignment from "Alignment Start Index" to index before "Paragraph Start Index" according to "Model Alignment"
+        decidedAlignStartIndex         = alignIndex;
+        decidedAlignNumberOfCharacters = characterStartIndexBP - alignIndex;
+        decidedHorizontalAlignment     = impl.mModel->mHorizontalAlignment;
+
+        // Need to re-heck the case of current bounded paragraph
+        alignIndex = characterStartIndexBP; // Shift AS to be PS
+      }
+      else if((characterStartIndexBP <= alignIndex && alignIndex <= characterEndIndexBP) ||     /// ---PS.BBBBBBB.AS.BBBBBBB.PE---
+              (characterStartIndexBP <= alignEndIndex && alignEndIndex <= characterEndIndexBP)) /// ---PS.BBBBBB.AE.BBBBBBB.PE---
+      {
+        // Alignment from "Paragraph Start Index" to "Paragraph End Index" according to "BoundedParagraph Alignment"
+        decidedAlignStartIndex         = characterStartIndexBP;
+        decidedAlignNumberOfCharacters = numberOfCharactersBP;
+        decidedHorizontalAlignment     = boundedParagraphRun.horizontalAlignmentDefined ? boundedParagraphRun.horizontalAlignment : impl.mModel->mHorizontalAlignment;
+
+        alignIndex = characterEndIndexBP + 1u; // Shift AS to be after PE direct
+        boundedParagraphRunIndex++;            // Align then check the case of next bounded paragraph
+      }
+      else
+      {
+        boundedParagraphRunIndex++; // Check the case of next bounded paragraph
+        continue;
+      }
+
+      impl.mLayoutEngine.Align(size,
+                               decidedAlignStartIndex,
+                               decidedAlignNumberOfCharacters,
+                               decidedHorizontalAlignment,
+                               lines,
+                               impl.mModel->mAlignmentOffset,
+                               impl.mLayoutDirection,
+                               (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
+    }
+
+    //Align the remaining that is not aligned
+    if(alignIndex <= alignEndIndex)
+    {
+      impl.mLayoutEngine.Align(size,
+                               alignIndex,
+                               (alignEndIndex - alignIndex + 1u),
+                               impl.mModel->mHorizontalAlignment,
+                               lines,
+                               impl.mModel->mAlignmentOffset,
+                               impl.mLayoutDirection,
+                               (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
+    }
+  }
+}
+
+void Controller::Relayouter::CalculateVerticalOffset(Controller::Impl& impl, const Size& controlSize)
+{
+  ModelPtr&       model                 = impl.mModel;
+  VisualModelPtr& visualModel           = model->mVisualModel;
+  Size            layoutSize            = model->mVisualModel->GetLayoutSize();
+  Size            oldLayoutSize         = layoutSize;
+  float           offsetY               = 0.f;
+  bool            needRecalc            = false;
+  float           defaultFontLineHeight = impl.GetDefaultFontLineHeight();
+
+  if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
+  {
+    // Get the line height of the default font.
+    layoutSize.height = defaultFontLineHeight;
+  }
+
+  // Whether the text control is editable
+  const bool isEditable = NULL != impl.mEventData;
+  if(isEditable && layoutSize.height != defaultFontLineHeight && impl.IsShowingPlaceholderText())
+  {
+    // This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
+    // This situation occurs when the size of placeholder text is different from the default text.
+    layoutSize.height = defaultFontLineHeight;
+    needRecalc        = true;
+  }
+
+  switch(model->mVerticalAlignment)
+  {
+    case VerticalAlignment::TOP:
+    {
+      model->mScrollPosition.y = 0.f;
+      offsetY                  = 0.f;
+      break;
+    }
+    case VerticalAlignment::CENTER:
+    {
+      model->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
+      if(needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
+      break;
+    }
+    case VerticalAlignment::BOTTOM:
+    {
+      model->mScrollPosition.y = controlSize.height - layoutSize.height;
+      if(needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
+      break;
+    }
+  }
+
+  if(needRecalc)
+  {
+    // Update glyphPositions according to recalculation.
+    const Length     positionCount  = visualModel->mGlyphPositions.Count();
+    Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
+    for(Length index = 0u; index < positionCount; index++)
+    {
+      glyphPositions[index].y += offsetY;
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-relayouter.h b/dali-toolkit/internal/text/controller/text-controller-relayouter.h
new file mode 100644 (file)
index 0000000..ca4e666
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * Contains all the relayouting related methods for Text::Controller
+ */
+struct Controller::Relayouter
+{
+  /**
+   * @brief Called by the Controller to retrieve the natural size.
+   *
+   * @param[in] controller A reference to the controller class
+   * @return
+   */
+  static Vector3 GetNaturalSize(Controller& controller);
+
+  /**
+   * @brief Called by the Controller to check if the text fits.
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] pointSize The point size
+   * @param[in] layoutSize The layout size
+   * @return
+   */
+  static bool CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize);
+
+  /**
+   * @brief Calculates the point size for text for given layout()
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] layoutSize The layout size
+   */
+  static void FitPointSizeforLayout(Controller& controller, const Size& layoutSize);
+
+  /**
+   * @brief Called by the Controller to get the height for a particular width.
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] width The width we want the height for
+   * @return
+   */
+  static float GetHeightForWidth(Controller& controller, float width);
+
+  /**
+   * @brief Called by the Controller to do the relayout itself.
+   *
+   * @param[in] controller A reference to the controller class
+   * @param[in] size The size to set
+   * @param[in] layoutDirection The layout direction
+   * @return
+   */
+  static Controller::UpdateTextType Relayout(Controller& controller, const Size& size, Dali::LayoutDirection::Type layoutDirection);
+
+  /**
+   * @brief Called by the Controller to do certain operations when relayouting.
+   *
+   * @param[in] impl A reference to the controller impl class
+   * @param[in] size The size to set
+   * @param[in] operationsRequired The operations we need to do
+   * @param[in/out] layoutSize The Layout size which can be updated depending on the result of the performed operations
+   * @return
+   */
+
+  static bool DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize);
+
+  /**
+   * @brief Called by the Controller to calculate the veritcal offset give the control size.
+   *
+   * @param[in] impl A reference to the controller impl class
+   * @param[in] controlSize The control size
+   */
+  static void CalculateVerticalOffset(Controller::Impl& impl, const Size& controlSize);
+
+  /**
+  * @brief Calculates the layout size of control according to @p requestedControllerSize and @p requestedOperationsMask
+  *
+  * GetNaturalSize() and GetHeightForWidth() calls this method.
+  *
+  * @param[in] controller The controller to calcualte size on it.
+  * @param[in] requestedControllerSize The requested size of controller to calcualte layout size on it.
+  * @param[in] requestedOperationsMask The requested operations-mask to calcualte layout size according to it.
+  *
+  * @return The calculated layout-size.
+  */
+  static Size CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask);
+
+private:
+  /**
+   * @brief Called by the DoRelayout to do HorizontalAlignment operation when relayouting.
+   *
+   * @param[in] impl A reference to the controller impl class
+   * @param[in] size The size to set
+   * @param[in] startIndex The start index for relayouting
+   * @param[in] requestedNumberOfCharacters The number Of characters for relayouting
+   */
+
+  static void DoRelayoutHorizontalAlignment(Controller::Impl& impl, const Size& size, const CharacterIndex startIndex, const Length requestedNumberOfCharacters);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller-text-updater.cpp b/dali-toolkit/internal/text/controller/text-controller-text-updater.cpp
new file mode 100644 (file)
index 0000000..addb91a
--- /dev/null
@@ -0,0 +1,833 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/characters-helper-functions.h>
+#include <dali-toolkit/internal/text/emoji-helper.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void Controller::TextUpdater::SetText(Controller& controller, const std::string& text)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText\n");
+
+  Controller::Impl& impl = *controller.mImpl;
+
+  // Reset keyboard as text changed
+  impl.ResetInputMethodContext();
+
+  // Remove the previously set text and style.
+  ResetText(controller);
+
+  // Remove the style.
+  impl.ClearStyleData();
+
+  CharacterIndex lastCursorIndex = 0u;
+
+  EventData*& eventData = impl.mEventData;
+
+  if(nullptr != eventData)
+  {
+    // If popup shown then hide it by switching to Editing state
+    if((EventData::SELECTING == eventData->mState) ||
+       (EventData::EDITING_WITH_POPUP == eventData->mState) ||
+       (EventData::EDITING_WITH_GRAB_HANDLE == eventData->mState) ||
+       (EventData::EDITING_WITH_PASTE_POPUP == eventData->mState))
+    {
+      if((impl.mSelectableControlInterface != nullptr) && (EventData::SELECTING == eventData->mState))
+      {
+        impl.mSelectableControlInterface->SelectionChanged(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition, eventData->mPrimaryCursorPosition, eventData->mPrimaryCursorPosition);
+      }
+
+      impl.ChangeState(EventData::EDITING);
+    }
+  }
+
+  if(!text.empty())
+  {
+    ModelPtr&        model        = impl.mModel;
+    LogicalModelPtr& logicalModel = model->mLogicalModel;
+    model->mVisualModel->SetTextColor(impl.mTextColor);
+
+    MarkupProcessData markupProcessData(logicalModel->mColorRuns,
+                                        logicalModel->mFontDescriptionRuns,
+                                        logicalModel->mEmbeddedItems,
+                                        logicalModel->mAnchors,
+                                        logicalModel->mUnderlinedCharacterRuns,
+                                        logicalModel->mBackgroundColorRuns,
+                                        logicalModel->mStrikethroughCharacterRuns,
+                                        logicalModel->mBoundedParagraphRuns,
+                                        logicalModel->mCharacterSpacingCharacterRuns);
+
+    Length         textSize = 0u;
+    const uint8_t* utf8     = NULL;
+    if(impl.mMarkupProcessorEnabled)
+    {
+      ProcessMarkupString(text, markupProcessData);
+      textSize = markupProcessData.markupProcessedText.size();
+
+      // This is a bit horrible but std::string returns a (signed) char*
+      utf8 = reinterpret_cast<const uint8_t*>(markupProcessData.markupProcessedText.c_str());
+    }
+    else
+    {
+      textSize = text.size();
+
+      // This is a bit horrible but std::string returns a (signed) char*
+      utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
+    }
+
+    //  Convert text into UTF-32
+    Vector<Character>& utf32Characters = logicalModel->mText;
+    utf32Characters.Resize(textSize);
+
+    // Transform a text array encoded in utf8 into an array encoded in utf32.
+    // It returns the actual number of characters.
+    Length characterCount = Utf8ToUtf32(utf8, textSize, utf32Characters.Begin());
+    utf32Characters.Resize(characterCount);
+
+    DALI_ASSERT_DEBUG(textSize >= characterCount && "Invalid UTF32 conversion length");
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", &controller, textSize, logicalModel->mText.Count());
+
+    // The characters to be added.
+    impl.mTextUpdateInfo.mNumberOfCharactersToAdd = logicalModel->mText.Count();
+
+    // To reset the cursor position
+    lastCursorIndex = characterCount;
+
+    // Update the rest of the model during size negotiation
+    impl.QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
+
+    // The natural size needs to be re-calculated.
+    impl.mRecalculateNaturalSize = true;
+
+    // The text direction needs to be updated.
+    impl.mUpdateTextDirection = true;
+
+    // Apply modifications to the model
+    impl.mOperationsPending = ALL_OPERATIONS;
+  }
+  else
+  {
+    PlaceholderHandler::ShowPlaceholderText(impl);
+  }
+
+  unsigned int oldCursorPos = (nullptr != eventData ? eventData->mPrimaryCursorPosition : 0);
+
+  // Resets the cursor position.
+  controller.ResetCursorPosition(lastCursorIndex);
+
+  // Scrolls the text to make the cursor visible.
+  impl.ResetScrollPosition();
+
+  impl.RequestRelayout();
+
+  if(nullptr != eventData)
+  {
+    // Cancel previously queued events
+    eventData->mEventQueue.clear();
+  }
+
+  // Do this last since it provides callbacks into application code.
+  if(NULL != impl.mEditableControlInterface)
+  {
+    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, lastCursorIndex);
+    impl.mEditableControlInterface->TextChanged(true);
+  }
+}
+
+void Controller::TextUpdater::InsertText(Controller& controller, const std::string& text, Controller::InsertType type)
+{
+  Controller::Impl& impl      = *controller.mImpl;
+  EventData*&       eventData = impl.mEventData;
+
+  DALI_ASSERT_DEBUG(nullptr != eventData && "Unexpected InsertText")
+
+  if(NULL == eventData)
+  {
+    return;
+  }
+
+  bool         removedPrevious  = false;
+  bool         removedSelected  = false;
+  bool         maxLengthReached = false;
+  unsigned int oldCursorPos     = eventData->mPrimaryCursorPosition;
+
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPrimaryCursorPosition %d mPreEditFlag %d mPreEditStartPosition %d mPreEditLength %d\n", &controller, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"), eventData->mPrimaryCursorPosition, eventData->mPreEditFlag, eventData->mPreEditStartPosition, eventData->mPreEditLength);
+
+  ModelPtr&        model        = impl.mModel;
+  LogicalModelPtr& logicalModel = model->mLogicalModel;
+
+  // TODO: At the moment the underline runs are only for pre-edit.
+  model->mVisualModel->mUnderlineRuns.Clear();
+
+  // Remove the previous InputMethodContext pre-edit.
+  if(eventData->mPreEditFlag && (0u != eventData->mPreEditLength))
+  {
+    removedPrevious = RemoveText(controller,
+                                 -static_cast<int>(eventData->mPrimaryCursorPosition - eventData->mPreEditStartPosition),
+                                 eventData->mPreEditLength,
+                                 DONT_UPDATE_INPUT_STYLE);
+
+    eventData->mPrimaryCursorPosition = eventData->mPreEditStartPosition;
+    eventData->mPreEditLength         = 0u;
+  }
+  else
+  {
+    // Remove the previous Selection.
+    removedSelected = RemoveSelectedText(controller);
+  }
+
+  Vector<Character> utf32Characters;
+  Length            characterCount = 0u;
+
+  if(!text.empty())
+  {
+    //  Convert text into UTF-32
+    utf32Characters.Resize(text.size());
+
+    // This is a bit horrible but std::string returns a (signed) char*
+    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
+
+    // Transform a text array encoded in utf8 into an array encoded in utf32.
+    // It returns the actual number of characters.
+    characterCount = Utf8ToUtf32(utf8, text.size(), utf32Characters.Begin());
+    utf32Characters.Resize(characterCount);
+
+    DALI_ASSERT_DEBUG(text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count());
+  }
+
+  if(0u != utf32Characters.Count()) // Check if Utf8ToUtf32 conversion succeeded
+  {
+    // The placeholder text is no longer needed
+    if(impl.IsShowingPlaceholderText())
+    {
+      ResetText(controller);
+    }
+
+    impl.ChangeState(EventData::EDITING);
+
+    // Handle the InputMethodContext (predicitive text) state changes
+    if(COMMIT == type)
+    {
+      // InputMethodContext is no longer handling key-events
+      impl.ClearPreEditFlag();
+    }
+    else // PRE_EDIT
+    {
+      if(!eventData->mPreEditFlag)
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Entered PreEdit state\n");
+
+        // Record the start of the pre-edit text
+        eventData->mPreEditStartPosition = eventData->mPrimaryCursorPosition;
+      }
+
+      eventData->mPreEditLength = utf32Characters.Count();
+      eventData->mPreEditFlag   = true;
+
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", eventData->mPreEditStartPosition, eventData->mPreEditLength);
+    }
+
+    const Length numberOfCharactersInModel = logicalModel->mText.Count();
+
+    // Restrict new text to fit within Maximum characters setting.
+    Length temp_length      = (impl.mMaximumNumberOfCharacters > numberOfCharactersInModel ? impl.mMaximumNumberOfCharacters - numberOfCharactersInModel : 0);
+    Length maxSizeOfNewText = std::min(temp_length, characterCount);
+    maxLengthReached        = (characterCount > maxSizeOfNewText);
+
+    // The cursor position.
+    CharacterIndex& cursorIndex = eventData->mPrimaryCursorPosition;
+
+    // Update the text's style.
+
+    // Updates the text style runs by adding characters.
+    logicalModel->UpdateTextStyleRuns(cursorIndex, maxSizeOfNewText);
+
+    // Get the character index from the cursor index.
+    const CharacterIndex styleIndex = (cursorIndex > 0u) ? cursorIndex - 1u : 0u;
+
+    // Retrieve the text's style for the given index.
+    InputStyle style;
+    impl.RetrieveDefaultInputStyle(style);
+    logicalModel->RetrieveStyle(styleIndex, style);
+
+    InputStyle& inputStyle = eventData->mInputStyle;
+
+    // Whether to add a new text color run.
+    const bool addColorRun = (style.textColor != inputStyle.textColor) && !inputStyle.isDefaultColor;
+
+    // Whether to add a new font run.
+    const bool addFontNameRun   = (style.familyName != inputStyle.familyName) && inputStyle.isFamilyDefined;
+    const bool addFontWeightRun = (style.weight != inputStyle.weight) && inputStyle.isWeightDefined;
+    const bool addFontWidthRun  = (style.width != inputStyle.width) && inputStyle.isWidthDefined;
+    const bool addFontSlantRun  = (style.slant != inputStyle.slant) && inputStyle.isSlantDefined;
+    const bool addFontSizeRun   = (style.size != inputStyle.size) && inputStyle.isSizeDefined;
+
+    // Add style runs.
+    if(addColorRun)
+    {
+      const VectorBase::SizeType numberOfRuns = logicalModel->mColorRuns.Count();
+      logicalModel->mColorRuns.Resize(numberOfRuns + 1u);
+
+      ColorRun& colorRun                       = *(logicalModel->mColorRuns.Begin() + numberOfRuns);
+      colorRun.color                           = inputStyle.textColor;
+      colorRun.characterRun.characterIndex     = cursorIndex;
+      colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
+    }
+
+    if(addFontNameRun ||
+       addFontWeightRun ||
+       addFontWidthRun ||
+       addFontSlantRun ||
+       addFontSizeRun)
+    {
+      const VectorBase::SizeType numberOfRuns = logicalModel->mFontDescriptionRuns.Count();
+      logicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
+
+      FontDescriptionRun& fontDescriptionRun = *(logicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
+
+      if(addFontNameRun)
+      {
+        fontDescriptionRun.familyLength = inputStyle.familyName.size();
+        fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
+        memcpy(fontDescriptionRun.familyName, inputStyle.familyName.c_str(), fontDescriptionRun.familyLength);
+        fontDescriptionRun.familyDefined = true;
+
+        // The memory allocated for the font family name is freed when the font description is removed from the logical model.
+      }
+
+      if(addFontWeightRun)
+      {
+        fontDescriptionRun.weight        = inputStyle.weight;
+        fontDescriptionRun.weightDefined = true;
+      }
+
+      if(addFontWidthRun)
+      {
+        fontDescriptionRun.width        = inputStyle.width;
+        fontDescriptionRun.widthDefined = true;
+      }
+
+      if(addFontSlantRun)
+      {
+        fontDescriptionRun.slant        = inputStyle.slant;
+        fontDescriptionRun.slantDefined = true;
+      }
+
+      if(addFontSizeRun)
+      {
+        fontDescriptionRun.size        = static_cast<PointSize26Dot6>(inputStyle.size * impl.GetFontSizeScale() * 64.f);
+        fontDescriptionRun.sizeDefined = true;
+      }
+
+      fontDescriptionRun.characterRun.characterIndex     = cursorIndex;
+      fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
+    }
+
+    // Insert at current cursor position.
+    Vector<Character>& modifyText = logicalModel->mText;
+
+    auto pos = modifyText.End();
+    if(cursorIndex < numberOfCharactersInModel)
+    {
+      pos = modifyText.Begin() + cursorIndex;
+    }
+    unsigned int realPos = pos - modifyText.Begin();
+    modifyText.Insert(pos, utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
+
+    if(NULL != impl.mEditableControlInterface)
+    {
+      impl.mEditableControlInterface->TextInserted(realPos, maxSizeOfNewText, text);
+    }
+
+    TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+
+    // Mark the first paragraph to be updated.
+    if(Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout())
+    {
+      textUpdateInfo.mCharacterIndex             = 0;
+      textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
+      textUpdateInfo.mNumberOfCharactersToAdd    = numberOfCharactersInModel + maxSizeOfNewText;
+      textUpdateInfo.mClearAll                   = true;
+    }
+    else
+    {
+      textUpdateInfo.mCharacterIndex = std::min(cursorIndex, textUpdateInfo.mCharacterIndex);
+      textUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
+    }
+
+    if(impl.mMarkupProcessorEnabled)
+    {
+      InsertTextAnchor(controller, maxSizeOfNewText, cursorIndex);
+    }
+
+    // Update the cursor index.
+    cursorIndex += maxSizeOfNewText;
+
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition);
+  }
+
+  if((0u == logicalModel->mText.Count()) &&
+     impl.IsPlaceholderAvailable())
+  {
+    // Show place-holder if empty after removing the pre-edit text
+    PlaceholderHandler::ShowPlaceholderText(impl);
+    eventData->mUpdateCursorPosition = true;
+    impl.ClearPreEditFlag();
+  }
+  else if(removedPrevious ||
+          removedSelected ||
+          (0 != utf32Characters.Count()))
+  {
+    // Queue an inserted event
+    impl.QueueModifyEvent(ModifyEvent::TEXT_INSERTED);
+
+    eventData->mUpdateCursorPosition = true;
+    if(removedSelected)
+    {
+      eventData->mScrollAfterDelete = true;
+    }
+    else
+    {
+      eventData->mScrollAfterUpdatePosition = true;
+    }
+  }
+
+  if(nullptr != impl.mEditableControlInterface)
+  {
+    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, eventData->mPrimaryCursorPosition);
+  }
+
+  if(maxLengthReached)
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", logicalModel->mText.Count());
+
+    impl.ResetInputMethodContext();
+
+    if(NULL != impl.mEditableControlInterface)
+    {
+      // Do this last since it provides callbacks into application code
+      impl.mEditableControlInterface->MaxLengthReached();
+    }
+  }
+}
+
+void Controller::TextUpdater::PasteText(Controller& controller, const std::string& stringToPaste)
+{
+  InsertText(controller, stringToPaste, Text::Controller::COMMIT);
+  Controller::Impl& impl = *controller.mImpl;
+  impl.ChangeState(EventData::EDITING);
+  impl.RequestRelayout();
+
+  if(NULL != impl.mEditableControlInterface)
+  {
+    // Do this last since it provides callbacks into application code
+    impl.mEditableControlInterface->TextChanged(true);
+  }
+}
+
+bool Controller::TextUpdater::RemoveText(
+  Controller&          controller,
+  int                  cursorOffset,
+  int                  numberOfCharacters,
+  UpdateInputStyleType type)
+{
+  bool removed = false;
+  bool removeAll = false;
+
+  Controller::Impl& impl      = *controller.mImpl;
+  EventData*&       eventData = impl.mEventData;
+
+  if(nullptr == eventData)
+  {
+    return removed;
+  }
+
+  ModelPtr&        model        = impl.mModel;
+  LogicalModelPtr& logicalModel = model->mLogicalModel;
+  VisualModelPtr&  visualModel  = model->mVisualModel;
+
+  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", &controller, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters);
+
+  if(!impl.IsShowingPlaceholderText())
+  {
+    // Delete at current cursor position
+    Vector<Character>& currentText         = logicalModel->mText;
+    CharacterIndex&    previousCursorIndex = eventData->mPrimaryCursorPosition;
+
+    CharacterIndex cursorIndex = 0;
+
+    // Validate the cursor position & number of characters
+    if((static_cast<int>(eventData->mPrimaryCursorPosition) + cursorOffset) >= 0)
+    {
+      cursorIndex = eventData->mPrimaryCursorPosition + cursorOffset;
+    }
+
+    //Handle Emoji clustering for cursor handling
+    // Deletion case: this is handling the deletion cases when the cursor is before or after Emoji
+    //  - Before: when use delete key and cursor is before Emoji (cursorOffset = -1)
+    //  - After: when use backspace key and cursor is after Emoji (cursorOffset = 0)
+
+    const Script script = logicalModel->GetScript(cursorIndex);
+    if((numberOfCharacters == 1u) &&
+       (IsOneOfEmojiScripts(script)))
+    {
+      //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts.
+      CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, cursorIndex);
+      Length       actualNumberOfCharacters = emojiClusteredCharacters.numberOfCharacters;
+
+      //Set cursorIndex at the first characterIndex of clustred Emoji
+      cursorIndex = emojiClusteredCharacters.characterIndex;
+
+      numberOfCharacters = actualNumberOfCharacters;
+    }
+
+    if((cursorIndex + numberOfCharacters) > currentText.Count())
+    {
+      numberOfCharacters = currentText.Count() - cursorIndex;
+    }
+
+    if((cursorIndex == 0) && (currentText.Count() - numberOfCharacters == 0))
+    {
+      removeAll = true;
+    }
+
+    TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
+
+    if(eventData->mPreEditFlag || removeAll || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
+       ((cursorIndex + numberOfCharacters) <= textUpdateInfo.mPreviousNumberOfCharacters))
+    {
+      // Mark the paragraphs to be updated.
+      if(Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout())
+      {
+        textUpdateInfo.mCharacterIndex             = 0;
+        textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
+        textUpdateInfo.mNumberOfCharactersToAdd    = textUpdateInfo.mPreviousNumberOfCharacters - numberOfCharacters;
+        textUpdateInfo.mClearAll                   = true;
+      }
+      else
+      {
+        textUpdateInfo.mCharacterIndex = std::min(cursorIndex, textUpdateInfo.mCharacterIndex);
+        textUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
+      }
+
+      // Update the input style and remove the text's style before removing the text.
+
+      if(UPDATE_INPUT_STYLE == type)
+      {
+        InputStyle& eventDataInputStyle = eventData->mInputStyle;
+
+        // Keep a copy of the current input style.
+        InputStyle currentInputStyle;
+        currentInputStyle.Copy(eventDataInputStyle);
+
+        // Set first the default input style.
+        impl.RetrieveDefaultInputStyle(eventDataInputStyle);
+
+        // Update the input style.
+        logicalModel->RetrieveStyle(cursorIndex, eventDataInputStyle);
+
+        // Compare if the input style has changed.
+        const bool hasInputStyleChanged = !currentInputStyle.Equal(eventDataInputStyle);
+
+        if(hasInputStyleChanged)
+        {
+          const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(eventDataInputStyle);
+          // Queue the input style changed signal.
+          eventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
+        }
+      }
+
+      // If the number of current text and the number of characters to be deleted are same,
+      // it means all texts should be removed and all Preedit variables should be initialized.
+      if(removeAll)
+      {
+        impl.ClearPreEditFlag();
+        textUpdateInfo.mNumberOfCharactersToAdd = 0;
+      }
+
+      // Updates the text style runs by removing characters. Runs with no characters are removed.
+      logicalModel->UpdateTextStyleRuns(cursorIndex, -numberOfCharacters);
+
+      // Remove the characters.
+      Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
+      Vector<Character>::Iterator last  = first + numberOfCharacters;
+
+      if(NULL != impl.mEditableControlInterface)
+      {
+        std::string utf8;
+        Utf32ToUtf8(first, numberOfCharacters, utf8);
+        impl.mEditableControlInterface->TextDeleted(cursorIndex, numberOfCharacters, utf8);
+      }
+
+      currentText.Erase(first, last);
+
+      if(impl.mMarkupProcessorEnabled)
+      {
+        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
+      }
+
+      if(nullptr != impl.mEditableControlInterface)
+      {
+        impl.mEditableControlInterface->CursorPositionChanged(previousCursorIndex, cursorIndex);
+      }
+
+      // Cursor position retreat
+      previousCursorIndex = cursorIndex;
+
+      eventData->mScrollAfterDelete = true;
+
+      if(EventData::INACTIVE == eventData->mState)
+      {
+        impl.ChangeState(EventData::EDITING);
+      }
+
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", &controller, numberOfCharacters);
+      removeAll = false;
+      removed = true;
+    }
+  }
+
+  return removed;
+}
+
+bool Controller::TextUpdater::RemoveSelectedText(Controller& controller)
+{
+  bool textRemoved(false);
+
+  Controller::Impl& impl = *controller.mImpl;
+
+  if(EventData::SELECTING == impl.mEventData->mState)
+  {
+    std::string removedString;
+    uint32_t    oldSelStart = impl.mEventData->mLeftSelectionPosition;
+    uint32_t    oldSelEnd   = impl.mEventData->mRightSelectionPosition;
+
+    impl.RetrieveSelection(removedString, true);
+
+    if(!removedString.empty())
+    {
+      textRemoved = true;
+      impl.ChangeState(EventData::EDITING);
+
+      if(impl.mMarkupProcessorEnabled)
+      {
+        int             cursorOffset        = -1;
+        int             numberOfCharacters  = removedString.length();
+        CharacterIndex& cursorIndex         = impl.mEventData->mPrimaryCursorPosition;
+        CharacterIndex  previousCursorIndex = cursorIndex + numberOfCharacters;
+
+        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
+      }
+
+      if(impl.mSelectableControlInterface != nullptr)
+      {
+        impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, impl.mEventData->mPrimaryCursorPosition, impl.mEventData->mPrimaryCursorPosition);
+      }
+    }
+  }
+
+  return textRemoved;
+}
+
+void Controller::TextUpdater::ResetText(Controller& controller)
+{
+  Controller::Impl& impl         = *controller.mImpl;
+  LogicalModelPtr&  logicalModel = impl.mModel->mLogicalModel;
+
+  // Reset buffers.
+  logicalModel->mText.Clear();
+
+  // Reset the embedded images buffer.
+  logicalModel->ClearEmbeddedImages();
+
+  // Reset the anchors buffer.
+  logicalModel->ClearAnchors();
+
+  // We have cleared everything including the placeholder-text
+  impl.PlaceholderCleared();
+
+  impl.mTextUpdateInfo.mCharacterIndex             = 0u;
+  impl.mTextUpdateInfo.mNumberOfCharactersToRemove = impl.mTextUpdateInfo.mPreviousNumberOfCharacters;
+  impl.mTextUpdateInfo.mNumberOfCharactersToAdd    = 0u;
+
+  // Clear any previous text.
+  impl.mTextUpdateInfo.mClearAll = true;
+
+  // The natural size needs to be re-calculated.
+  impl.mRecalculateNaturalSize = true;
+
+  // The text direction needs to be updated.
+  impl.mUpdateTextDirection = true;
+
+  // Apply modifications to the model
+  impl.mOperationsPending = ALL_OPERATIONS;
+}
+
+void Controller::TextUpdater::InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex)
+{
+  Controller::Impl& impl         = *controller.mImpl;
+  ModelPtr&         model        = impl.mModel;
+  LogicalModelPtr&  logicalModel = model->mLogicalModel;
+
+  for(auto& anchor : logicalModel->mAnchors)
+  {
+    if(anchor.endIndex < previousCursorIndex) //      [anchor]  CUR
+    {
+      continue;
+    }
+    if(anchor.startIndex < previousCursorIndex) //      [anCURr]
+    {
+      anchor.endIndex += numberOfCharacters;
+    }
+    else // CUR  [anchor]
+    {
+      anchor.startIndex += numberOfCharacters;
+      anchor.endIndex += numberOfCharacters;
+    }
+    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::InsertTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
+  }
+}
+
+void Controller::TextUpdater::RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
+{
+  Controller::Impl&        impl         = *controller.mImpl;
+  ModelPtr&                model        = impl.mModel;
+  LogicalModelPtr&         logicalModel = model->mLogicalModel;
+  Vector<Anchor>::Iterator it           = logicalModel->mAnchors.Begin();
+
+  while(it != logicalModel->mAnchors.End())
+  {
+    Anchor& anchor = *it;
+
+    if(anchor.endIndex <= previousCursorIndex && cursorOffset == 0) // [anchor]    CUR >>
+    {
+      // Nothing happens.
+    }
+    else if(anchor.endIndex <= previousCursorIndex && cursorOffset == -1) // [anchor] << CUR
+    {
+      int endIndex = anchor.endIndex;
+      int offset   = previousCursorIndex - endIndex;
+      int index    = endIndex - (numberOfCharacters - offset);
+
+      if(index < endIndex)
+      {
+        endIndex = index;
+      }
+
+      if((int)anchor.startIndex >= endIndex)
+      {
+        if(anchor.href)
+        {
+          delete[] anchor.href;
+        }
+        it = logicalModel->mAnchors.Erase(it);
+        continue;
+      }
+      else
+      {
+        anchor.endIndex = endIndex;
+      }
+    }
+    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == -1) // << CUR    [anchor]
+    {
+      anchor.startIndex -= numberOfCharacters;
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == 0) //    CUR >> [anchor]
+    {
+      int startIndex = anchor.startIndex;
+      int endIndex   = anchor.endIndex;
+      int index      = previousCursorIndex + numberOfCharacters - 1;
+
+      if(startIndex > index)
+      {
+        anchor.startIndex -= numberOfCharacters;
+        anchor.endIndex -= numberOfCharacters;
+      }
+      else if(endIndex > index + 1)
+      {
+        anchor.endIndex -= numberOfCharacters;
+      }
+      else
+      {
+        if(anchor.href)
+        {
+          delete[] anchor.href;
+        }
+        it = logicalModel->mAnchors.Erase(it);
+        continue;
+      }
+    }
+    else if(cursorOffset == -1) // [<< CUR]
+    {
+      int startIndex = anchor.startIndex;
+      int index      = previousCursorIndex - numberOfCharacters;
+
+      if(startIndex >= index)
+      {
+        anchor.startIndex = index;
+      }
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else if(cursorOffset == 0) // [CUR >>]
+    {
+      anchor.endIndex -= numberOfCharacters;
+    }
+    else
+    {
+      // When this condition is reached, someting is wrong.
+      DALI_LOG_ERROR("Controller::RemoveTextAnchor[%p] Invaild state cursorOffset[%d]\n", &controller, cursorOffset);
+    }
+
+    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
+
+    it++;
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/controller/text-controller-text-updater.h b/dali-toolkit/internal/text/controller/text-controller-text-updater.h
new file mode 100644 (file)
index 0000000..47403f6
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef DALI_TOOLKIT_TEXT_UPDATER_H
+#define DALI_TOOLKIT_TEXT_UPDATER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Methods that update the text
+ */
+struct Controller::TextUpdater
+{
+  /// @copydoc Text::Contoller::SetText
+  /// @param[in] controller The controller
+  static void SetText(Controller& controller, const std::string& text);
+
+  /**
+   * @brief Called by editable UI controls when key events are received.
+   *
+   * @param[in] controller The controller
+   * @param[in] text The text to insert.
+   * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
+   */
+  static void InsertText(Controller& controller, const std::string& text, Controller::InsertType type);
+
+  /// @copydoc Text::EditableControlInterface::PasteText()
+  /// @param[in] controller The controller
+  static void PasteText(Controller& controller, const std::string& stringToPaste);
+
+  /**
+   * @brief Remove a given number of characters
+   *
+   * When predictve text is used the pre-edit text is removed and inserted again with the new characters.
+   * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input
+   * style when pre-edit text is removed.
+   *
+   * @param[in] controller The controller
+   * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
+   * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
+   * @param[in] type Whether to update the input style.
+   * @return True if the remove was successful.
+   */
+  static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type);
+
+  /**
+   * @brief Checks if text is selected and if so removes it.
+   * @param[in] controller The controller
+   * @return true if text was removed
+   */
+  static bool RemoveSelectedText(Controller& controller);
+
+  /**
+   * @brief Used to remove the text included the placeholder text.
+   * @param[in] controller The controller
+   */
+  static void ResetText(Controller& controller);
+
+  /**
+   * @brief Update anchor position from given number of inserted characters.
+   *
+   * @param[in] controller The controller
+   * @param[in] numberOfCharacters The number of inserted characters.
+   * @param[in] previousCursorIndex A cursor position before event occurs.
+   */
+  static void InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex);
+
+  /**
+   * @brief Update anchor position from given number of removed characters.
+   *
+   * @param[in] controller The controller
+   * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
+   * @param[in] numberOfCharacters The number of removed characters.
+   * @param[in] previousCursorIndex A cursor position before event occurs.
+   */
+  static void RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex);
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_UPDATER_H
diff --git a/dali-toolkit/internal/text/controller/text-controller.cpp b/dali-toolkit/internal/text/controller/text-controller.cpp
new file mode 100644 (file)
index 0000000..5f775f7
--- /dev/null
@@ -0,0 +1,1707 @@
+/*
+ * Copyright (c) 2022 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.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/text/controller/text-controller.h>
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/integration-api/debug.h>
+#include <memory.h>
+#include <cmath>
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/controller/text-controller-background-actor.h>
+#include <dali-toolkit/internal/text/controller/text-controller-event-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl.h>
+#include <dali-toolkit/internal/text/controller/text-controller-input-font-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-input-properties.h>
+#include <dali-toolkit/internal/text/controller/text-controller-placeholder-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-relayouter.h>
+#include <dali-toolkit/internal/text/controller/text-controller-text-updater.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-geometry.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
+const std::string EMPTY_STRING("");
+
+template<typename Type>
+void EnsureCreated(Type*& object)
+{
+  if(!object)
+  {
+    object = new Type();
+  }
+}
+
+template<typename Type>
+void EnsureCreated(std::unique_ptr<Type>& object)
+{
+  if(!object)
+  {
+    object = std::unique_ptr<Type>(new Type());
+  }
+}
+
+template<typename Type, typename Arg1>
+void EnsureCreated(Type*& object, Arg1 arg1)
+{
+  if(!object)
+  {
+    object = new Type(arg1);
+  }
+}
+
+template<typename Type, typename Arg1, typename Arg2>
+void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
+{
+  if(!object)
+  {
+    object = new Type(arg1, arg2);
+  }
+}
+
+float GetDpi()
+{
+  unsigned int                      horizontalDpi = 0u;
+  unsigned int                      verticalDpi   = 0u;
+  Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
+  fontClient.GetDpi(horizontalDpi, verticalDpi);
+  return static_cast<float>(horizontalDpi);
+}
+
+float ConvertPixelToPoint(float pixel)
+{
+  return pixel * 72.0f / GetDpi();
+}
+
+float ConvertPointToPixel(float point)
+{
+  // Pixel size = Point size * DPI / 72.f
+  return point * GetDpi() / 72.0f;
+}
+
+void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
+{
+  if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
+  {
+    // Update the cursor position if it's in editing mode
+    eventData->mDecoratorUpdated     = true;
+    eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
+  }
+}
+
+} // namespace
+
+namespace Dali::Toolkit::Text
+{
+void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
+{
+  if(!decorator)
+  {
+    delete mImpl->mEventData;
+    mImpl->mEventData = NULL;
+
+    // Nothing else to do.
+    return;
+  }
+
+  EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
+}
+
+void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
+{
+  // Metrics for bitmap & vector based glyphs are different
+  mImpl->mMetrics->SetGlyphType(glyphType);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+void Controller::SetMarkupProcessorEnabled(bool enable)
+{
+  if(enable != mImpl->mMarkupProcessorEnabled)
+  {
+    //If Text was already set, call the SetText again for enabling or disabling markup
+    mImpl->mMarkupProcessorEnabled = enable;
+    std::string text;
+    GetText(text);
+    SetText(text);
+  }
+
+  mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
+}
+
+bool Controller::IsMarkupProcessorEnabled() const
+{
+  return mImpl->mMarkupProcessorEnabled;
+}
+
+bool Controller::HasAnchors() const
+{
+  return (mImpl->mMarkupProcessorEnabled && mImpl->mModel->mLogicalModel->mAnchors.Count() && mImpl->IsShowingRealText());
+}
+
+void Controller::SetAutoScrollEnabled(bool enable)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable) ? "true" : "false", (mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) ? "true" : "false", this);
+  mImpl->SetAutoScrollEnabled(enable);
+}
+
+void Controller::SetAutoScrollMaxTextureExceeded(bool exceed)
+{
+  mImpl->mIsAutoScrollMaxTextureExceeded = exceed;
+}
+
+bool Controller::IsAutoScrollEnabled() const
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
+  return mImpl->mIsAutoScrollEnabled;
+}
+
+CharacterDirection Controller::GetAutoScrollDirection() const
+{
+  return mImpl->mIsTextDirectionRTL;
+}
+
+float Controller::GetAutoScrollLineAlignment() const
+{
+  float offset = 0.f;
+  if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
+  {
+    offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
+  }
+  return offset;
+}
+
+void Controller::SetHorizontalScrollEnabled(bool enable)
+{
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
+  {
+    mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
+  }
+}
+
+bool Controller::IsHorizontalScrollEnabled() const
+{
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
+}
+
+void Controller::SetVerticalScrollEnabled(bool enable)
+{
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
+  {
+    mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
+  }
+}
+
+bool Controller::IsVerticalScrollEnabled() const
+{
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
+}
+
+void Controller::SetSmoothHandlePanEnabled(bool enable)
+{
+  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
+  {
+    mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
+  }
+}
+
+bool Controller::IsSmoothHandlePanEnabled() const
+{
+  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
+}
+
+void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
+{
+  mImpl->mMaximumNumberOfCharacters = maxCharacters;
+}
+
+int Controller::GetMaximumNumberOfCharacters()
+{
+  return mImpl->mMaximumNumberOfCharacters;
+}
+
+void Controller::SetEnableCursorBlink(bool enable)
+{
+  mImpl->SetEnableCursorBlink(enable);
+}
+
+bool Controller::GetEnableCursorBlink() const
+{
+  return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
+}
+
+void Controller::SetMultiLineEnabled(bool enable)
+{
+  mImpl->SetMultiLineEnabled(enable);
+}
+
+bool Controller::IsMultiLineEnabled() const
+{
+  return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
+}
+
+void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
+{
+  mImpl->SetHorizontalAlignment(alignment);
+}
+
+Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
+{
+  return mImpl->mModel->mHorizontalAlignment;
+}
+
+void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
+{
+  mImpl->SetVerticalAlignment(alignment);
+}
+
+VerticalAlignment::Type Controller::GetVerticalAlignment() const
+{
+  return mImpl->mModel->mVerticalAlignment;
+}
+
+bool Controller::IsIgnoreSpacesAfterText() const
+{
+  return mImpl->mModel->mIgnoreSpacesAfterText;
+}
+
+void Controller::SetIgnoreSpacesAfterText(bool ignore)
+{
+  mImpl->mModel->mIgnoreSpacesAfterText = ignore;
+}
+
+void Controller::ChangedLayoutDirection()
+{
+  mImpl->mIsLayoutDirectionChanged = true;
+}
+
+void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
+{
+  mImpl->mModel->mMatchLayoutDirection = type;
+}
+
+DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
+{
+  return mImpl->mModel->mMatchLayoutDirection;
+}
+
+void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
+{
+  mImpl->mLayoutDirection = layoutDirection;
+}
+
+Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
+{
+  return mImpl->GetLayoutDirection(actor);
+}
+
+bool Controller::IsShowingRealText() const
+{
+  return mImpl->IsShowingRealText();
+}
+
+void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
+{
+  mImpl->SetLineWrapMode(lineWrapMode);
+}
+
+Text::LineWrap::Mode Controller::GetLineWrapMode() const
+{
+  return mImpl->mModel->mLineWrapMode;
+}
+
+void Controller::SetTextElideEnabled(bool enabled)
+{
+  mImpl->mModel->mElideEnabled = enabled;
+  mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
+}
+
+bool Controller::IsTextElideEnabled() const
+{
+  return mImpl->mModel->mElideEnabled;
+}
+
+void Controller::SetTextFitEnabled(bool enabled)
+{
+  mImpl->mTextFitEnabled = enabled;
+}
+
+bool Controller::IsTextFitEnabled() const
+{
+  return mImpl->mTextFitEnabled;
+}
+
+void Controller::SetTextFitChanged(bool changed)
+{
+  mImpl->mTextFitChanged = changed;
+}
+
+bool Controller::IsTextFitChanged() const
+{
+  return mImpl->mTextFitChanged;
+}
+
+void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
+{
+  mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
+}
+
+float Controller::GetTextFitMinSize() const
+{
+  return mImpl->mTextFitMinSize;
+}
+
+void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
+{
+  mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
+}
+
+float Controller::GetTextFitMaxSize() const
+{
+  return mImpl->mTextFitMaxSize;
+}
+
+void Controller::SetTextFitStepSize(float step, FontSizeType type)
+{
+  mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
+}
+
+float Controller::GetTextFitStepSize() const
+{
+  return mImpl->mTextFitStepSize;
+}
+
+void Controller::SetTextFitContentSize(Vector2 size)
+{
+  mImpl->mTextFitContentSize = size;
+}
+
+Vector2 Controller::GetTextFitContentSize() const
+{
+  return mImpl->mTextFitContentSize;
+}
+
+float Controller::GetTextFitPointSize() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFitPointSize : 0.0f;
+}
+
+void Controller::SetPlaceholderTextElideEnabled(bool enabled)
+{
+  PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
+}
+
+bool Controller::IsPlaceholderTextElideEnabled() const
+{
+  return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
+}
+
+void Controller::SetSelectionEnabled(bool enabled)
+{
+  mImpl->mEventData->mSelectionEnabled = enabled;
+}
+
+bool Controller::IsSelectionEnabled() const
+{
+  return mImpl->mEventData->mSelectionEnabled;
+}
+
+void Controller::SetShiftSelectionEnabled(bool enabled)
+{
+  mImpl->mEventData->mShiftSelectionFlag = enabled;
+}
+
+bool Controller::IsShiftSelectionEnabled() const
+{
+  return mImpl->mEventData->mShiftSelectionFlag;
+}
+
+void Controller::SetGrabHandleEnabled(bool enabled)
+{
+  mImpl->mEventData->mGrabHandleEnabled = enabled;
+}
+
+bool Controller::IsGrabHandleEnabled() const
+{
+  return mImpl->mEventData->mGrabHandleEnabled;
+}
+
+void Controller::SetGrabHandlePopupEnabled(bool enabled)
+{
+  mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
+}
+
+bool Controller::IsGrabHandlePopupEnabled() const
+{
+  return mImpl->mEventData->mGrabHandlePopupEnabled;
+}
+
+void Controller::SetText(const std::string& text)
+{
+  TextUpdater::SetText(*this, text);
+}
+
+void Controller::GetText(std::string& text) const
+{
+  mImpl->GetText(text);
+}
+
+void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
+{
+  PlaceholderHandler::SetPlaceholderText(*this, type, text);
+}
+
+void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
+{
+  PlaceholderHandler::GetPlaceholderText(*this, type, text);
+}
+
+void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
+{
+  mImpl->UpdateAfterFontChange(newDefaultFont);
+}
+
+void Controller::RetrieveSelection(std::string& selectedText) const
+{
+  mImpl->RetrieveSelection(selectedText, false);
+}
+
+void Controller::SetSelection(int start, int end)
+{
+  mImpl->SetSelection(start, end);
+}
+
+std::pair<int, int> Controller::GetSelectionIndexes() const
+{
+  return mImpl->GetSelectionIndexes();
+}
+
+void Controller::CopyStringToClipboard(const std::string& source)
+{
+  mImpl->CopyStringToClipboard(source);
+}
+
+void Controller::SendSelectionToClipboard(bool deleteAfterSending)
+{
+  mImpl->SendSelectionToClipboard(deleteAfterSending);
+}
+
+void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
+{
+  EnsureCreated(mImpl->mFontDefaults);
+
+  mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
+  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
+  mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+const std::string& Controller::GetDefaultFontFamily() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
+}
+
+void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
+{
+  PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
+}
+
+const std::string& Controller::GetPlaceholderFontFamily() const
+{
+  return PlaceholderHandler::GetPlaceholderFontFamily(*this);
+}
+
+void Controller::SetDefaultFontWeight(FontWeight weight)
+{
+  EnsureCreated(mImpl->mFontDefaults);
+
+  mImpl->mFontDefaults->mFontDescription.weight = weight;
+  mImpl->mFontDefaults->weightDefined           = true;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsDefaultFontWeightDefined() const
+{
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
+}
+
+FontWeight Controller::GetDefaultFontWeight() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
+}
+
+void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
+{
+  PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
+}
+
+bool Controller::IsPlaceholderTextFontWeightDefined() const
+{
+  return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
+}
+
+FontWeight Controller::GetPlaceholderTextFontWeight() const
+{
+  return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
+}
+
+void Controller::SetDefaultFontWidth(FontWidth width)
+{
+  EnsureCreated(mImpl->mFontDefaults);
+
+  mImpl->mFontDefaults->mFontDescription.width = width;
+  mImpl->mFontDefaults->widthDefined           = true;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsDefaultFontWidthDefined() const
+{
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
+}
+
+FontWidth Controller::GetDefaultFontWidth() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
+}
+
+void Controller::SetPlaceholderTextFontWidth(FontWidth width)
+{
+  PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
+}
+
+bool Controller::IsPlaceholderTextFontWidthDefined() const
+{
+  return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
+}
+
+FontWidth Controller::GetPlaceholderTextFontWidth() const
+{
+  return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
+}
+
+void Controller::SetDefaultFontSlant(FontSlant slant)
+{
+  EnsureCreated(mImpl->mFontDefaults);
+
+  mImpl->mFontDefaults->mFontDescription.slant = slant;
+  mImpl->mFontDefaults->slantDefined           = true;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsDefaultFontSlantDefined() const
+{
+  return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
+}
+
+FontSlant Controller::GetDefaultFontSlant() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
+}
+
+void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
+{
+  PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
+}
+
+bool Controller::IsPlaceholderTextFontSlantDefined() const
+{
+  return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
+}
+
+FontSlant Controller::GetPlaceholderTextFontSlant() const
+{
+  return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
+}
+
+void Controller::SetFontSizeScale(float scale)
+{
+  mImpl->mFontSizeScale = scale;
+
+  // No relayout is required
+  if(!mImpl->mFontSizeScaleEnabled) return;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetFontSizeScale() const
+{
+  return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
+}
+
+void Controller::SetFontSizeScaleEnabled(bool enabled)
+{
+  mImpl->mFontSizeScaleEnabled = enabled;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsFontSizeScaleEnabled() const
+{
+  return mImpl->mFontSizeScaleEnabled;
+}
+
+void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
+{
+  EnsureCreated(mImpl->mFontDefaults);
+
+  mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
+  mImpl->mFontDefaults->sizeDefined       = true;
+
+  // Update the cursor position if it's in editing mode
+  UpdateCursorPosition(mImpl->mEventData);
+
+  // Clear the font-specific data
+  mImpl->ClearFontData();
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetDefaultFontSize(FontSizeType type) const
+{
+  if(mImpl->mFontDefaults)
+  {
+    return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
+  }
+  return 0.0f;
+}
+
+void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
+{
+  PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
+}
+
+float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
+{
+  return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
+}
+
+void Controller::SetDefaultColor(const Vector4& color)
+{
+  mImpl->SetDefaultColor(color);
+}
+
+const Vector4& Controller::GetDefaultColor() const
+{
+  return mImpl->mTextColor;
+}
+
+void Controller::SetDisabledColorOpacity(float opacity)
+{
+  mImpl->mDisabledColorOpacity = opacity;
+}
+
+float Controller::GetDisabledColorOpacity() const
+{
+  return mImpl->mDisabledColorOpacity;
+}
+
+void Controller::SetUserInteractionEnabled(bool enabled)
+{
+  mImpl->SetUserInteractionEnabled(enabled);
+}
+
+bool Controller::IsUserInteractionEnabled() const
+{
+  return mImpl->mIsUserInteractionEnabled;
+}
+
+void Controller::SetPlaceholderTextColor(const Vector4& textColor)
+{
+  PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
+}
+
+const Vector4& Controller::GetPlaceholderTextColor() const
+{
+  return PlaceholderHandler::GetPlaceholderTextColor(*this);
+}
+
+void Controller::SetShadowOffset(const Vector2& shadowOffset)
+{
+  mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
+  mImpl->RequestRelayout();
+}
+
+const Vector2& Controller::GetShadowOffset() const
+{
+  return mImpl->mModel->mVisualModel->GetShadowOffset();
+}
+
+void Controller::SetShadowColor(const Vector4& shadowColor)
+{
+  mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetShadowColor() const
+{
+  return mImpl->mModel->mVisualModel->GetShadowColor();
+}
+
+void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
+{
+  if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
+  {
+    mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
+    mImpl->RequestRelayout();
+  }
+}
+
+const float& Controller::GetShadowBlurRadius() const
+{
+  return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
+}
+
+void Controller::SetUnderlineColor(const Vector4& color)
+{
+  mImpl->mModel->mVisualModel->SetUnderlineColor(color);
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetUnderlineColor() const
+{
+  return mImpl->mModel->mVisualModel->GetUnderlineColor();
+}
+
+void Controller::SetUnderlineEnabled(bool enabled)
+{
+  mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsUnderlineEnabled() const
+{
+  return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
+}
+
+void Controller::SetUnderlineHeight(float height)
+{
+  mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetUnderlineHeight() const
+{
+  return mImpl->mModel->mVisualModel->GetUnderlineHeight();
+}
+
+void Controller::SetUnderlineType(Text::Underline::Type type)
+{
+  mImpl->mModel->mVisualModel->SetUnderlineType(type);
+
+  mImpl->RequestRelayout();
+}
+
+Text::Underline::Type Controller::GetUnderlineType() const
+{
+  return mImpl->mModel->mVisualModel->GetUnderlineType();
+}
+
+void Controller::SetDashedUnderlineWidth(float width)
+{
+  mImpl->mModel->mVisualModel->SetDashedUnderlineWidth(width);
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetDashedUnderlineWidth() const
+{
+  return mImpl->mModel->mVisualModel->GetDashedUnderlineWidth();
+}
+
+void Controller::SetDashedUnderlineGap(float gap)
+{
+  mImpl->mModel->mVisualModel->SetDashedUnderlineGap(gap);
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetDashedUnderlineGap() const
+{
+  return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
+}
+
+void Controller::SetOutlineColor(const Vector4& color)
+{
+  mImpl->mModel->mVisualModel->SetOutlineColor(color);
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetOutlineColor() const
+{
+  return mImpl->mModel->mVisualModel->GetOutlineColor();
+}
+
+void Controller::SetOutlineWidth(uint16_t width)
+{
+  mImpl->mModel->mVisualModel->SetOutlineWidth(width);
+  mImpl->RequestRelayout();
+}
+
+uint16_t Controller::GetOutlineWidth() const
+{
+  return mImpl->mModel->mVisualModel->GetOutlineWidth();
+}
+
+void Controller::SetBackgroundColor(const Vector4& color)
+{
+  mImpl->mModel->mVisualModel->SetBackgroundColor(color);
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetBackgroundColor() const
+{
+  return mImpl->mModel->mVisualModel->GetBackgroundColor();
+}
+
+void Controller::SetBackgroundEnabled(bool enabled)
+{
+  mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsBackgroundEnabled() const
+{
+  return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
+}
+
+void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
+{
+  EnsureCreated(mImpl->mEmbossDefaults);
+  mImpl->mEmbossDefaults->properties = embossProperties;
+}
+
+const std::string& Controller::GetDefaultEmbossProperties() const
+{
+  return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
+}
+
+void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
+{
+  EnsureCreated(mImpl->mOutlineDefaults);
+  mImpl->mOutlineDefaults->properties = outlineProperties;
+}
+
+const std::string& Controller::GetDefaultOutlineProperties() const
+{
+  return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
+}
+
+bool Controller::SetDefaultLineSpacing(float lineSpacing)
+{
+  return mImpl->SetDefaultLineSpacing(lineSpacing);
+}
+
+float Controller::GetDefaultLineSpacing() const
+{
+  return mImpl->mLayoutEngine.GetDefaultLineSpacing();
+}
+
+bool Controller::SetDefaultLineSize(float lineSize)
+{
+  return mImpl->SetDefaultLineSize(lineSize);
+}
+
+float Controller::GetDefaultLineSize() const
+{
+  return mImpl->mLayoutEngine.GetDefaultLineSize();
+}
+
+bool Controller::SetRelativeLineSize(float relativeLineSize)
+{
+  return mImpl->SetRelativeLineSize(relativeLineSize);
+}
+
+float Controller::GetRelativeLineSize() const
+{
+  return mImpl->GetRelativeLineSize();
+}
+
+void Controller::SetInputColor(const Vector4& color)
+{
+  InputProperties::SetInputColor(*this, color);
+}
+
+const Vector4& Controller::GetInputColor() const
+{
+  return InputProperties::GetInputColor(*this);
+}
+
+void Controller::SetInputFontFamily(const std::string& fontFamily)
+{
+  InputFontHandler::SetInputFontFamily(*this, fontFamily);
+}
+
+const std::string& Controller::GetInputFontFamily() const
+{
+  return InputFontHandler::GetInputFontFamily(*this);
+}
+
+void Controller::SetInputFontWeight(FontWeight weight)
+{
+  InputFontHandler::SetInputFontWeight(*this, weight);
+}
+
+bool Controller::IsInputFontWeightDefined() const
+{
+  return InputFontHandler::IsInputFontWeightDefined(*this);
+}
+
+FontWeight Controller::GetInputFontWeight() const
+{
+  return InputFontHandler::GetInputFontWeight(*this);
+}
+
+void Controller::SetInputFontWidth(FontWidth width)
+{
+  InputFontHandler::SetInputFontWidth(*this, width);
+}
+
+bool Controller::IsInputFontWidthDefined() const
+{
+  return InputFontHandler::IsInputFontWidthDefined(*this);
+}
+
+FontWidth Controller::GetInputFontWidth() const
+{
+  return InputFontHandler::GetInputFontWidth(*this);
+}
+
+void Controller::SetInputFontSlant(FontSlant slant)
+{
+  InputFontHandler::SetInputFontSlant(*this, slant);
+}
+
+bool Controller::IsInputFontSlantDefined() const
+{
+  return InputFontHandler::IsInputFontSlantDefined(*this);
+}
+
+FontSlant Controller::GetInputFontSlant() const
+{
+  return InputFontHandler::GetInputFontSlant(*this);
+}
+
+void Controller::SetInputFontPointSize(float size)
+{
+  InputFontHandler::SetInputFontPointSize(*this, size);
+}
+
+float Controller::GetInputFontPointSize() const
+{
+  return InputFontHandler::GetInputFontPointSize(*this);
+}
+
+void Controller::SetInputLineSpacing(float lineSpacing)
+{
+  InputProperties::SetInputLineSpacing(*this, lineSpacing);
+}
+
+float Controller::GetInputLineSpacing() const
+{
+  return InputProperties::GetInputLineSpacing(*this);
+}
+
+void Controller::SetInputShadowProperties(const std::string& shadowProperties)
+{
+  InputProperties::SetInputShadowProperties(*this, shadowProperties);
+}
+
+const std::string& Controller::GetInputShadowProperties() const
+{
+  return InputProperties::GetInputShadowProperties(*this);
+}
+
+void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
+{
+  InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
+}
+
+const std::string& Controller::GetInputUnderlineProperties() const
+{
+  return InputProperties::GetInputUnderlineProperties(*this);
+}
+
+void Controller::SetInputEmbossProperties(const std::string& embossProperties)
+{
+  InputProperties::SetInputEmbossProperties(*this, embossProperties);
+}
+
+const std::string& Controller::GetInputEmbossProperties() const
+{
+  return InputProperties::GetInputEmbossProperties(*this);
+}
+
+void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
+{
+  InputProperties::SetInputOutlineProperties(*this, outlineProperties);
+}
+
+const std::string& Controller::GetInputOutlineProperties() const
+{
+  return InputProperties::GetInputOutlineProperties(*this);
+}
+
+void Controller::SetInputModePassword(bool passwordInput)
+{
+  InputProperties::SetInputModePassword(*this, passwordInput);
+}
+
+bool Controller::IsInputModePassword()
+{
+  return InputProperties::IsInputModePassword(*this);
+}
+
+void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
+{
+  if(mImpl->mEventData)
+  {
+    mImpl->mEventData->mDoubleTapAction = action;
+  }
+}
+
+Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
+{
+  return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
+}
+
+void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
+{
+  if(mImpl->mEventData)
+  {
+    mImpl->mEventData->mLongPressAction = action;
+  }
+}
+
+Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
+{
+  return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
+}
+
+bool Controller::IsUnderlineSetByString()
+{
+  return mImpl->mUnderlineSetByString;
+}
+
+void Controller::UnderlineSetByString(bool setByString)
+{
+  mImpl->mUnderlineSetByString = setByString;
+}
+
+bool Controller::IsShadowSetByString()
+{
+  return mImpl->mShadowSetByString;
+}
+
+void Controller::ShadowSetByString(bool setByString)
+{
+  mImpl->mShadowSetByString = setByString;
+}
+
+bool Controller::IsOutlineSetByString()
+{
+  return mImpl->mOutlineSetByString;
+}
+
+void Controller::OutlineSetByString(bool setByString)
+{
+  mImpl->mOutlineSetByString = setByString;
+}
+
+bool Controller::IsFontStyleSetByString()
+{
+  return mImpl->mFontStyleSetByString;
+}
+
+void Controller::FontStyleSetByString(bool setByString)
+{
+  mImpl->mFontStyleSetByString = setByString;
+}
+
+void Controller::SetStrikethroughHeight(float height)
+{
+  mImpl->mModel->mVisualModel->SetStrikethroughHeight(height);
+
+  mImpl->RequestRelayout();
+}
+
+float Controller::GetStrikethroughHeight() const
+{
+  return mImpl->mModel->mVisualModel->GetStrikethroughHeight();
+}
+
+void Controller::SetStrikethroughColor(const Vector4& color)
+{
+  mImpl->mModel->mVisualModel->SetStrikethroughColor(color);
+
+  mImpl->RequestRelayout();
+}
+
+const Vector4& Controller::GetStrikethroughColor() const
+{
+  return mImpl->mModel->mVisualModel->GetStrikethroughColor();
+}
+
+void Controller::SetStrikethroughEnabled(bool enabled)
+{
+  mImpl->mModel->mVisualModel->SetStrikethroughEnabled(enabled);
+
+  mImpl->RequestRelayout();
+}
+
+bool Controller::IsStrikethroughEnabled() const
+{
+  return mImpl->mModel->mVisualModel->IsStrikethroughEnabled();
+}
+
+void Controller::SetInputStrikethroughProperties(const std::string& strikethroughProperties)
+{
+  if(NULL != mImpl->mEventData)
+  {
+    mImpl->mEventData->mInputStyle.strikethroughProperties = strikethroughProperties;
+  }
+}
+
+const std::string& Controller::GetInputStrikethroughProperties() const
+{
+  return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
+}
+
+bool Controller::IsStrikethroughSetByString()
+{
+  return mImpl->mStrikethroughSetByString;
+}
+
+void Controller::StrikethroughSetByString(bool setByString)
+{
+  mImpl->mStrikethroughSetByString = setByString;
+}
+
+Layout::Engine& Controller::GetLayoutEngine()
+{
+  return mImpl->mLayoutEngine;
+}
+
+View& Controller::GetView()
+{
+  return mImpl->mView;
+}
+
+Vector3 Controller::GetNaturalSize()
+{
+  return Relayouter::GetNaturalSize(*this);
+}
+
+bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
+{
+  return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
+}
+
+void Controller::FitPointSizeforLayout(Size layoutSize)
+{
+  Relayouter::FitPointSizeforLayout(*this, layoutSize);
+}
+
+float Controller::GetHeightForWidth(float width)
+{
+  return Relayouter::GetHeightForWidth(*this, width);
+}
+
+int Controller::GetLineCount(float width)
+{
+  GetHeightForWidth(width);
+  return mImpl->mModel->GetNumberOfLines();
+}
+
+const ModelInterface* const Controller::GetTextModel() const
+{
+  return mImpl->mModel.Get();
+}
+
+float Controller::GetScrollAmountByUserInput()
+{
+  float scrollAmount = 0.0f;
+
+  if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
+  {
+    scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
+    mImpl->mEventData->mCheckScrollAmount = false;
+  }
+  return scrollAmount;
+}
+
+bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
+{
+  const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
+  bool           isScrolled;
+
+  controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
+  layoutHeight   = layout.height;
+  scrollPosition = mImpl->mModel->mScrollPosition.y;
+  isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
+  return isScrolled;
+}
+
+void Controller::SetHiddenInputOption(const Property::Map& options)
+{
+  EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
+  mImpl->mHiddenInput->SetProperties(options);
+}
+
+void Controller::GetHiddenInputOption(Property::Map& options)
+{
+  if(mImpl->mHiddenInput)
+  {
+    mImpl->mHiddenInput->GetProperties(options);
+  }
+}
+
+void Controller::SetInputFilterOption(const Property::Map& options)
+{
+  EnsureCreated(mImpl->mInputFilter);
+  mImpl->mInputFilter->SetProperties(options);
+}
+
+void Controller::GetInputFilterOption(Property::Map& options)
+{
+  if(mImpl->mInputFilter)
+  {
+    mImpl->mInputFilter->GetProperties(options);
+  }
+}
+
+void Controller::SetPlaceholderProperty(const Property::Map& map)
+{
+  PlaceholderHandler::SetPlaceholderProperty(*this, map);
+}
+
+void Controller::GetPlaceholderProperty(Property::Map& map)
+{
+  PlaceholderHandler::GetPlaceholderProperty(*this, map);
+}
+
+Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
+{
+  // Make sure the model is up-to-date before layouting
+  EventHandler::ProcessModifyEvents(*this);
+
+  return mImpl->GetTextDirection();
+}
+
+Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
+{
+  return mImpl->mModel->GetVerticalLineAlignment();
+}
+
+void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
+{
+  mImpl->mModel->mVerticalLineAlignment = alignment;
+}
+
+Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
+{
+  return mImpl->mModel->GetEllipsisPosition();
+}
+
+void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
+{
+  mImpl->mModel->mEllipsisPosition = ellipsisPosition;
+  mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
+}
+
+void Controller::SetCharacterSpacing(float characterSpacing)
+{
+  mImpl->mModel->mVisualModel->SetCharacterSpacing(characterSpacing);
+
+  mImpl->RelayoutAllCharacters();
+  mImpl->RequestRelayout();
+}
+
+const float Controller::GetCharacterSpacing() const
+{
+  return mImpl->mModel->mVisualModel->GetCharacterSpacing();
+}
+
+Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
+{
+  return Relayouter::Relayout(*this, size, layoutDirection);
+}
+
+void Controller::RequestRelayout()
+{
+  mImpl->RequestRelayout();
+}
+
+Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
+{
+  Vector<Vector2> sizesList;
+  Vector<Vector2> positionsList;
+
+  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
+  return sizesList;
+}
+
+Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
+{
+  Vector<Vector2> sizesList;
+  Vector<Vector2> positionsList;
+
+  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
+  return positionsList;
+}
+
+Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
+{
+  Vector<Vector2> sizeList;
+  Vector<Vector2> positionList;
+
+  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
+
+  if(sizeList.Empty() || sizeList.Size() != positionList.Size())
+  {
+    return {0, 0, 0, 0};
+  }
+
+  auto minX      = positionList[0].x;
+  auto minY      = positionList[0].y;
+  auto maxRight  = positionList[0].x + sizeList[0].x;
+  auto maxBottom = positionList[0].y + sizeList[0].y;
+
+  for(unsigned int i = 1; i < sizeList.Size(); i++)
+  {
+    minX      = std::min(minX, positionList[i].x);
+    minY      = std::min(minY, positionList[i].y);
+    maxRight  = std::max(maxRight, positionList[i].x + sizeList[i].x);
+    maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
+  }
+
+  return {minX, minY, maxRight - minX, maxBottom - minY};
+}
+
+bool Controller::IsInputStyleChangedSignalsQueueEmpty()
+{
+  return mImpl->IsInputStyleChangedSignalsQueueEmpty();
+}
+
+void Controller::ProcessInputStyleChangedSignals()
+{
+  mImpl->ProcessInputStyleChangedSignals();
+}
+
+void Controller::KeyboardFocusGainEvent()
+{
+  EventHandler::KeyboardFocusGainEvent(*this);
+}
+
+void Controller::KeyboardFocusLostEvent()
+{
+  EventHandler::KeyboardFocusLostEvent(*this);
+}
+
+bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
+{
+  return EventHandler::KeyEvent(*this, keyEvent);
+}
+
+void Controller::AnchorEvent(float x, float y)
+{
+  EventHandler::AnchorEvent(*this, x, y);
+}
+
+void Controller::TapEvent(unsigned int tapCount, float x, float y)
+{
+  EventHandler::TapEvent(*this, tapCount, x, y);
+}
+
+void Controller::PanEvent(GestureState state, const Vector2& displacement)
+{
+  EventHandler::PanEvent(*this, state, displacement);
+}
+
+void Controller::LongPressEvent(GestureState state, float x, float y)
+{
+  EventHandler::LongPressEvent(*this, state, x, y);
+}
+
+void Controller::SelectEvent(float x, float y, SelectionType selectType)
+{
+  EventHandler::SelectEvent(*this, x, y, selectType);
+}
+
+void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
+{
+  if(mImpl->mEventData)
+  {
+    mImpl->mEventData->mCheckScrollAmount     = true;
+    mImpl->mEventData->mIsLeftHandleSelected  = true;
+    mImpl->mEventData->mIsRightHandleSelected = true;
+    mImpl->SetTextSelectionRange(start, end);
+    mImpl->RequestRelayout();
+    EventHandler::KeyboardFocusGainEvent(*this);
+  }
+}
+
+Uint32Pair Controller::GetTextSelectionRange() const
+{
+  return mImpl->GetTextSelectionRange();
+}
+
+CharacterIndex Controller::GetPrimaryCursorPosition() const
+{
+  return mImpl->GetPrimaryCursorPosition();
+}
+
+bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
+{
+  if(mImpl->mEventData)
+  {
+    mImpl->mEventData->mCheckScrollAmount     = true;
+    mImpl->mEventData->mIsLeftHandleSelected  = true;
+    mImpl->mEventData->mIsRightHandleSelected = true;
+    mImpl->mEventData->mCheckScrollAmount     = true;
+    if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
+    {
+      EventHandler::KeyboardFocusGainEvent(*this);
+      return true;
+    }
+  }
+  return false;
+}
+
+void Controller::SelectWholeText()
+{
+  EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
+}
+
+void Controller::SelectNone()
+{
+  EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
+}
+
+void Controller::SelectText(const uint32_t start, const uint32_t end)
+{
+  EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
+}
+
+string Controller::GetSelectedText() const
+{
+  return mImpl->GetSelectedText();
+}
+
+string Controller::CopyText()
+{
+  return mImpl->CopyText();
+}
+
+string Controller::CutText()
+{
+  return mImpl->CutText();
+}
+
+void Controller::PasteText()
+{
+  mImpl->RequestGetTextFromClipboard(); // Request clipboard service to retrieve an item
+}
+
+InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
+{
+  return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
+}
+
+void Controller::PasteClipboardItemEvent()
+{
+  EventHandler::PasteClipboardItemEvent(*this);
+}
+
+void Controller::GetTargetSize(Vector2& targetSize)
+{
+  targetSize = mImpl->mModel->mVisualModel->mControlSize;
+}
+
+void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
+{
+  if(mImpl->mEditableControlInterface)
+  {
+    mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
+  }
+}
+
+bool Controller::IsEditable() const
+{
+  return mImpl->IsEditable();
+}
+
+void Controller::SetEditable(bool editable)
+{
+  mImpl->SetEditable(editable);
+}
+
+void Controller::ScrollBy(Vector2 scroll)
+{
+  mImpl->ScrollBy(scroll);
+}
+
+bool Controller::IsScrollable(const Vector2& displacement)
+{
+  return mImpl->IsScrollable(displacement);
+}
+
+float Controller::GetHorizontalScrollPosition()
+{
+  return mImpl->GetHorizontalScrollPosition();
+}
+
+float Controller::GetVerticalScrollPosition()
+{
+  return mImpl->GetVerticalScrollPosition();
+}
+
+void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
+{
+  EventHandler::DecorationEvent(*this, handleType, state, x, y);
+}
+
+void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
+{
+  EventHandler::TextPopupButtonTouched(*this, button);
+}
+
+void Controller::DisplayTimeExpired()
+{
+  mImpl->mEventData->mUpdateCursorPosition = true;
+  // Apply modifications to the model
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+
+  mImpl->RequestRelayout();
+}
+
+void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
+{
+  // Reset the cursor position
+  if(NULL != mImpl->mEventData)
+  {
+    mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
+
+    // Update the cursor if it's in editing mode.
+    if(EventData::IsEditingState(mImpl->mEventData->mState))
+    {
+      mImpl->mEventData->mUpdateCursorPosition = true;
+    }
+  }
+}
+
+CharacterIndex Controller::GetCursorPosition()
+{
+  return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
+}
+
+void Controller::SetControlInterface(ControlInterface* controlInterface)
+{
+  mImpl->mControlInterface = controlInterface;
+}
+
+void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
+{
+  mImpl->mAnchorControlInterface = anchorControlInterface;
+}
+
+bool Controller::ShouldClearFocusOnEscape() const
+{
+  return mImpl->mShouldClearFocusOnEscape;
+}
+
+Actor Controller::CreateBackgroundActor()
+{
+  return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mModel->mLogicalModel, mImpl->mShaderBackground);
+}
+
+void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
+{
+  mImpl->GetAnchorActors(anchorActors);
+}
+
+int Controller::GetAnchorIndex(size_t characterOffset)
+{
+  return mImpl->GetAnchorIndex(characterOffset);
+}
+
+Controller::Controller(ControlInterface*           controlInterface,
+                       EditableControlInterface*   editableControlInterface,
+                       SelectableControlInterface* selectableControlInterface,
+                       AnchorControlInterface*     anchorControlInterface)
+: mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
+{
+}
+
+Controller::~Controller()
+{
+  delete mImpl;
+}
+
+} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/controller/text-controller.h b/dali-toolkit/internal/text/controller/text-controller.h
new file mode 100644 (file)
index 0000000..09305d2
--- /dev/null
@@ -0,0 +1,2075 @@
+#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_H
+#define DALI_TOOLKIT_TEXT_CONTROLLER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/input-method-context.h>
+#include <dali/public-api/events/gesture.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
+#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
+#include <dali-toolkit/internal/text/decorator/text-decorator.h>
+#include <dali-toolkit/internal/text/hidden-text.h>
+#include <dali-toolkit/internal/text/input-filter.h>
+#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/text/text-anchor-control-interface.h>
+#include <dali-toolkit/internal/text/text-model-interface.h>
+#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
+#include <dali-toolkit/public-api/text/text-enumerations.h>
+
+namespace Dali::Toolkit::Text
+{
+class Controller;
+class ControlInterface;
+class EditableControlInterface;
+class View;
+class RenderingController;
+
+/**
+   * @brief Text selection operations .
+   */
+enum SelectionType
+{
+  INTERACTIVE = 0x0000, ///< Select the word where the cursor is located.
+  ALL         = 0x0001, ///< Select the whole text.
+  NONE        = 0x0002, ///< Unselect the whole text.
+  RANGE       = 0x0003  ///< Select the range text.
+};
+
+typedef IntrusivePtr<Controller> ControllerPtr;
+
+/**
+ * @brief A Text Controller is used by UI Controls which display text.
+ *
+ * It manipulates the Logical & Visual text models on behalf of the UI Controls.
+ * It provides a view of the text that can be used by rendering back-ends.
+ *
+ * For selectable/editable UI controls, the controller handles input events from the UI control
+ * and decorations (grab handles etc) via the Decorator::ControllerInterface interface.
+ *
+ * The text selection popup button callbacks are as well handled via the TextSelectionPopupCallbackInterface interface.
+ */
+class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface, public HiddenText::Observer
+{
+public: // Enumerated types.
+  /**
+   * @brief Text related operations to be done in the relayout process.
+   */
+  enum OperationsMask
+  {
+    NO_OPERATION       = 0x0000,
+    CONVERT_TO_UTF32   = 0x0001,
+    GET_SCRIPTS        = 0x0002,
+    VALIDATE_FONTS     = 0x0004,
+    GET_LINE_BREAKS    = 0x0008,
+    BIDI_INFO          = 0x0010,
+    SHAPE_TEXT         = 0x0020,
+    GET_GLYPH_METRICS  = 0x0040,
+    LAYOUT             = 0x0080,
+    UPDATE_LAYOUT_SIZE = 0x0100,
+    REORDER            = 0x0200,
+    ALIGN              = 0x0400,
+    COLOR              = 0x0800,
+    UPDATE_DIRECTION   = 0x1000,
+    ALL_OPERATIONS     = 0xFFFF
+  };
+
+  /**
+   * @brief Used to distinguish between regular key events and InputMethodContext events
+   */
+  enum InsertType
+  {
+    COMMIT,
+    PRE_EDIT
+  };
+
+  /**
+   * @brief Used to specify whether to update the input style.
+   */
+  enum UpdateInputStyleType
+  {
+    UPDATE_INPUT_STYLE,
+    DONT_UPDATE_INPUT_STYLE
+  };
+
+  /**
+   * @brief Used to specify what has been updated after the Relayout() method has been called.
+   */
+  enum UpdateTextType
+  {
+    NONE_UPDATED      = 0x0, ///< Nothing has been updated.
+    MODEL_UPDATED     = 0x1, ///< The text's model has been updated.
+    DECORATOR_UPDATED = 0x2  ///< The decoration has been updated.
+  };
+
+  /**
+   * @brief Different placeholder-text can be shown when the control is active/inactive.
+   */
+  enum PlaceholderType
+  {
+    PLACEHOLDER_TYPE_ACTIVE,
+    PLACEHOLDER_TYPE_INACTIVE,
+  };
+
+  /**
+   * @brief Enumeration for Font Size Type.
+   */
+  enum FontSizeType
+  {
+    POINT_SIZE, // The size of font in points.
+    PIXEL_SIZE  // The size of font in pixels.
+  };
+
+  struct NoTextTap
+  {
+    enum Action
+    {
+      NO_ACTION,           ///< Does no action if there is a tap on top of an area with no text.
+      HIGHLIGHT,           ///< Highlights the nearest text (at the beginning or end of the text) and shows the text's selection popup.
+      SHOW_SELECTION_POPUP ///< Shows the text's selection popup.
+    };
+  };
+
+  struct TextFitInfo
+  {
+    enum Property
+    {
+      TEXT_FIT_ENABLE,
+      TEXT_FIT_MIN_SIZE,
+      TEXT_FIT_MAX_SIZE,
+      TEXT_FIT_STEP_SIZE,
+      TEXT_FIT_FONT_SIZE_TYPE
+    };
+  };
+
+public: // Constructor.
+  /**
+   * @brief Create a new instance of a Controller.
+   *
+   * @return A pointer to a new Controller.
+   */
+  static ControllerPtr New()
+  {
+    return ControllerPtr(new Controller());
+  }
+
+  /**
+   * @brief Create a new instance of a Controller.
+   *
+   * @param[in] controlInterface The control's interface.
+   *
+   * @return A pointer to a new Controller.
+   */
+  static ControllerPtr New(ControlInterface* controlInterface)
+  {
+    return ControllerPtr(new Controller(controlInterface));
+  }
+
+  /**
+   * @brief Create a new instance of a Controller.
+   *
+   * @param[in] controlInterface The control's interface.
+   * @param[in] editableControlInterface The editable control's interface.
+   * @param[in] selectableControlInterface The selectable control's interface.
+   * @param[in] anchorControlInterface The anchor control's interface.
+   *
+   * @return A pointer to a new Controller.
+   */
+  static ControllerPtr New(ControlInterface*           controlInterface,
+                           EditableControlInterface*   editableControlInterface,
+                           SelectableControlInterface* selectableControlInterface,
+                           AnchorControlInterface*     anchorControlInterface)
+  {
+    return ControllerPtr(new Controller(controlInterface,
+                                        editableControlInterface,
+                                        selectableControlInterface,
+                                        anchorControlInterface));
+  }
+
+public: // Configure the text controller.
+  /**
+   * @brief Called to enable text input.
+   *
+   * @note Selectable or editable controls should call this once after Controller::New().
+   * @param[in] decorator Used to create cursor, selection handle decorations etc.
+   * @param[in] inputMethodContext Used to manager ime.
+   */
+  void EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext);
+
+  /**
+   * @brief Used to switch between bitmap & vector based glyphs
+   *
+   * @param[in] glyphType The type of glyph; note that metrics for bitmap & vector based glyphs are different.
+   */
+  void SetGlyphType(TextAbstraction::GlyphType glyphType);
+
+  /**
+   * @brief Enables/disables the mark-up processor.
+   *
+   * By default is disabled.
+   *
+   * @param[in] enable Whether to enable the mark-up processor.
+   */
+  void SetMarkupProcessorEnabled(bool enable);
+
+  /**
+   * @brief Retrieves whether the mark-up processor is enabled.
+   *
+   * By default is disabled.
+   *
+   * @return @e true if the mark-up processor is enabled, otherwise returns @e false.
+   */
+  bool IsMarkupProcessorEnabled() const;
+
+  /**
+   * @brief Retrieves whether the current text contains anchors.
+   *
+   * @return @e true if the current text contains anchors. @e false.
+   */
+  bool HasAnchors() const;
+
+  /**
+   * @brief Enables/disables the auto text scrolling
+   *
+   * By default is disabled.
+   *
+   * @param[in] enable Whether to enable the auto scrolling
+   */
+  void SetAutoScrollEnabled(bool enable);
+
+  /**
+   * @brief Whether the auto scrolling texture exceed max texture.
+   *
+   * By default is false.
+   *
+   * @param[in] exceed Whether the auto scrolling texture exceed max texture.
+   */
+  void SetAutoScrollMaxTextureExceeded(bool exceed);
+
+  /**
+   * @brief Retrieves whether auto text scrolling is enabled.
+   *
+   * By default is disabled.
+   *
+   * @return @e true if auto scrolling is enabled, otherwise returns @e false.
+   */
+  bool IsAutoScrollEnabled() const;
+
+  /**
+   * @brief Get direction of the text from the first line of text,
+   * @return bool rtl (right to left) is true
+   */
+  CharacterDirection GetAutoScrollDirection() const;
+
+  /**
+   * @brief Get the alignment offset of the first line of text.
+   *
+   * @return The alignment offset.
+   */
+  float GetAutoScrollLineAlignment() const;
+
+  /**
+   * @brief Enables the horizontal scrolling.
+   *
+   * @param[in] enable Whether to enable the horizontal scrolling.
+   */
+  void SetHorizontalScrollEnabled(bool enable);
+
+  /**
+   * @brief Retrieves whether the horizontal scrolling is enabled.
+   *
+   * @return @e true if the horizontal scrolling is enabled, otherwise it returns @e false.
+   */
+  bool IsHorizontalScrollEnabled() const;
+
+  /**
+   * @brief Enables the vertical scrolling.
+   *
+   * @param[in] enable Whether to enable the vertical scrolling.
+   */
+  void SetVerticalScrollEnabled(bool enable);
+
+  /**
+   * @brief Retrieves whether the verticall scrolling is enabled.
+   *
+   * @return @e true if the vertical scrolling is enabled, otherwise it returns @e false.
+   */
+  bool IsVerticalScrollEnabled() const;
+
+  /**
+   * @brief Enables the smooth handle panning.
+   *
+   * @param[in] enable Whether to enable the smooth handle panning.
+   */
+  void SetSmoothHandlePanEnabled(bool enable);
+
+  /**
+   * @brief Retrieves whether the smooth handle panning is enabled.
+   *
+   * @return @e true if the smooth handle panning is enabled.
+   */
+  bool IsSmoothHandlePanEnabled() const;
+
+  /**
+   * @brief Sets the maximum number of characters that can be inserted into the TextModel
+   *
+   * @param[in] maxCharacters maximum number of characters to be accepted
+   */
+  void SetMaximumNumberOfCharacters(Length maxCharacters);
+
+  /**
+   * @brief Sets the maximum number of characters that can be inserted into the TextModel
+   *
+   * @param[in] maxCharacters maximum number of characters to be accepted
+   */
+  int GetMaximumNumberOfCharacters();
+
+  /**
+   * @brief Called to enable/disable cursor blink.
+   *
+   * @note Only editable controls should calls this.
+   * @param[in] enabled Whether the cursor should blink or not.
+   */
+  void SetEnableCursorBlink(bool enable);
+
+  /**
+   * @brief Query whether cursor blink is enabled.
+   *
+   * @return Whether the cursor should blink or not.
+   */
+  bool GetEnableCursorBlink() const;
+
+  /**
+   * @brief Whether to enable the multi-line layout.
+   *
+   * @param[in] enable \e true enables the multi-line (by default)
+   */
+  void SetMultiLineEnabled(bool enable);
+
+  /**
+   * @return Whether the multi-line layout is enabled.
+   */
+  bool IsMultiLineEnabled() const;
+
+  /**
+   * @brief Sets the text's horizontal alignment.
+   *
+   * @param[in] alignment The horizontal alignment.
+   */
+  void SetHorizontalAlignment(HorizontalAlignment::Type alignment);
+
+  /**
+   * @copydoc ModelInterface::GetHorizontalAlignment()
+   */
+  HorizontalAlignment::Type GetHorizontalAlignment() const;
+
+  /**
+   * @brief Sets the text's vertical alignment.
+   *
+   * @param[in] alignment The vertical alignment.
+   */
+  void SetVerticalAlignment(VerticalAlignment::Type alignment);
+
+  /**
+   * @copydoc ModelInterface::GetVerticalAlignment()
+   */
+  VerticalAlignment::Type GetVerticalAlignment() const;
+
+  /**
+   * @brief Sets the text's wrap mode
+   * @param[in] text wrap mode The unit of wrapping
+   */
+  void SetLineWrapMode(Text::LineWrap::Mode textWarpMode);
+
+  /**
+   * @brief Retrieve text wrap mode previously set.
+   * @return text wrap mode
+   */
+  Text::LineWrap::Mode GetLineWrapMode() const;
+
+  /**
+   * @brief Enable or disable the text elide.
+   *
+   * @param[in] enabled Whether to enable the text elide.
+   */
+  void SetTextElideEnabled(bool enabled);
+
+  /**
+   * @copydoc ModelInterface::IsTextElideEnabled()
+   */
+  bool IsTextElideEnabled() const;
+
+  /**
+   * @brief Enable or disable the text fit.
+   *
+   * @param[in] enabled Whether to enable the text fit.
+   */
+  void SetTextFitEnabled(bool enabled);
+
+  /**
+   * @brief Whether the text fit is enabled or not.
+   *
+   * @return True if the text fit is enabled
+   */
+  bool IsTextFitEnabled() const;
+
+  /**
+   * @brief Sets minimum size valid for text fit.
+   *
+   * @param[in] minimum size value.
+   * @param[in] type The font size type is point size or pixel size
+   */
+  void SetTextFitMinSize(float pointSize, FontSizeType type);
+
+  /**
+   * @brief Retrieves the minimum point size valid for text fit.
+   *
+   * @return The minimum point size valid for text fit
+   */
+  float GetTextFitMinSize() const;
+
+  /**
+   * @brief Sets maximum size valid for text fit.
+   *
+   * @param[in] maximum size value.
+   * @param[in] type The font size type is point size or pixel size
+   */
+  void SetTextFitMaxSize(float pointSize, FontSizeType type);
+
+  /**
+   * @brief Retrieves the maximum point size valid for text fit.
+   *
+   * @return The maximum point size valid for text fit
+   */
+  float GetTextFitMaxSize() const;
+
+  /**
+   * @brief Sets step size for font increase valid for text fit.
+   *
+   * @param[in] step size value.
+   * @param[in] type The font size type is point size or pixel size
+   */
+  void SetTextFitStepSize(float step, FontSizeType type);
+
+  /**
+   * @brief Retrieves the step point size valid for text fit.
+   *
+   * @return The step point size valid for text fit
+   */
+  float GetTextFitStepSize() const;
+
+  /**
+   * @brief Sets content size valid for text fit.
+   *
+   * @param[in] Content size value.
+   */
+  void SetTextFitContentSize(Vector2 size);
+
+  /**
+   * @brief Retrieves the content size valid for text fit.
+   *
+   * @return The content size valid for text fit
+   */
+  Vector2 GetTextFitContentSize() const;
+
+  /**
+   * @brief Retrieve the fited point size.
+   *
+   * @return The fited point size.
+   */
+  float GetTextFitPointSize() const;
+
+  /**
+   * @brief Sets whether the text fit properties have changed.
+   *
+   * @param[in] changed Whether to changed the text fit.
+   */
+  void SetTextFitChanged(bool changed);
+
+  /**
+   * @brief Whether the text fit properties are changed or not.
+   *
+   * @return True if the text fit properties are changed
+   */
+  bool IsTextFitChanged() const;
+
+  /**
+   * @brief Sets disabled color opacity.
+   *
+   * @param[in] opacity The color opacity value in disabled state.
+   */
+  void SetDisabledColorOpacity(float opacity);
+
+  /**
+   * @brief Retrieves the disabled color opacity.
+   *
+   * @return The disabled color opacity value for disabled state.
+   */
+  float GetDisabledColorOpacity() const;
+
+  /**
+   * @brief Enable or disable the placeholder text elide.
+   * @param enabled Whether to enable the placeholder text elide.
+   */
+  void SetPlaceholderTextElideEnabled(bool enabled);
+
+  /**
+   * @brief Whether the placeholder text elide property is enabled.
+   * @return True if the placeholder text elide property is enabled, false otherwise.
+   */
+  bool IsPlaceholderTextElideEnabled() const;
+
+  /**
+   * @brief Enable or disable the text selection.
+   * @param[in] enabled Whether to enable the text selection.
+   */
+  void SetSelectionEnabled(bool enabled);
+
+  /**
+   * @brief Whether the text selection is enabled or not.
+   * @return True if the text selection is enabled
+   */
+  bool IsSelectionEnabled() const;
+
+  /**
+   * @brief Enable or disable the text selection using Shift key.
+   * @param enabled Whether to enable the text selection using Shift key
+   */
+  void SetShiftSelectionEnabled(bool enabled);
+
+  /**
+   * @brief Whether the text selection using Shift key is enabled or not.
+   * @return True if the text selection using Shift key is enabled
+   */
+  bool IsShiftSelectionEnabled() const;
+
+  /**
+   * @brief Enable or disable the grab handles for text selection.
+   *
+   * @param[in] enabled Whether to enable the grab handles
+   */
+  void SetGrabHandleEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether the grab handles are enabled.
+   *
+   * @return True if the grab handles are enabled
+   */
+  bool IsGrabHandleEnabled() const;
+
+  /**
+   * @brief Enable or disable the grab handles for text selection.
+   *
+   * @param[in] enabled Whether to enable the grab handles
+   */
+  void SetGrabHandlePopupEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether the grab handles are enabled.
+   *
+   * @return True if the grab handles are enabled
+   */
+  bool IsGrabHandlePopupEnabled() const;
+
+  /**
+   * @brief Sets input type to password
+   *
+   * @note The string is displayed hidden character
+   *
+   * @param[in] passwordInput True if password input is enabled.
+   */
+  void SetInputModePassword(bool passwordInput);
+
+  /**
+   * @brief Returns whether the input mode type is set as password.
+   *
+   * @return True if input mode type is password
+   */
+  bool IsInputModePassword();
+
+  /**
+   * @brief Sets the action when there is a double tap event on top of a text area with no text.
+   *
+   * @param[in] action The action to do.
+   */
+  void SetNoTextDoubleTapAction(NoTextTap::Action action);
+
+  /**
+   * @brief Retrieves the action when there is a double tap event on top of a text area with no text.
+   *
+   * @return The action to do.
+   */
+  NoTextTap::Action GetNoTextDoubleTapAction() const;
+
+  /**
+   * @briefSets the action when there is a long press event on top of a text area with no text.
+   *
+   * @param[in] action The action to do.
+   */
+  void SetNoTextLongPressAction(NoTextTap::Action action);
+
+  /**
+   * @brief Retrieves the action when there is a long press event on top of a text area with no text.
+   *
+   * @return The action to do.
+   */
+  NoTextTap::Action GetNoTextLongPressAction() const;
+
+  /**
+   * @brief Query if Underline settings were provided by string or map
+   * @return bool true if set by string
+   */
+  bool IsUnderlineSetByString();
+
+  /**
+   * Set method underline setting were set by
+   * @param[in] bool, true if set by string
+   */
+  void UnderlineSetByString(bool setByString);
+
+  /**
+   * @brief Query if shadow settings were provided by string or map
+   * @return bool true if set by string
+   */
+  bool IsShadowSetByString();
+
+  /**
+   * Set method shadow setting were set by
+   * @param[in] bool, true if set by string
+   */
+  void ShadowSetByString(bool setByString);
+
+  /**
+   * @brief Query if outline settings were provided by string or map
+   * @return bool true if set by string
+   */
+  bool IsOutlineSetByString();
+
+  /**
+   * Set method outline setting were set by
+   * @param[in] bool, true if set by string
+   */
+  void OutlineSetByString(bool setByString);
+
+  /**
+   * @brief Query if font style settings were provided by string or map
+   * @return bool true if set by string
+   */
+  bool IsFontStyleSetByString();
+
+  /**
+   * Set method font style setting were set by
+   * @param[in] bool, true if set by string
+   */
+  void FontStyleSetByString(bool setByString);
+
+  /**
+   * @brief Query if Strikethrough settings were provided by string or map
+   * @return bool true if set by string
+   */
+  bool IsStrikethroughSetByString();
+
+  /**
+   * Set method Strikethrough setting were set by
+   * @param[in] bool, true if set by string
+   */
+  void StrikethroughSetByString(bool setByString);
+
+  /**
+   * @brief Set the override used for strikethrough height, 0 indicates height will be supplied by font metrics
+   *
+   * @param[in] height The height in pixels of the strikethrough
+   */
+  void SetStrikethroughHeight(float height);
+
+  /**
+   * @brief Retrieves the override height of an strikethrough, 0 indicates height is supplied by font metrics
+   *
+   * @return The height of the strikethrough, or 0 if height is not overrided.
+   */
+  float GetStrikethroughHeight() const;
+
+  /**
+   * @brief Set the strikethrough color.
+   *
+   * @param[in] color color of strikethrough.
+   */
+  void SetStrikethroughColor(const Vector4& color);
+
+  /**
+   * @brief Retrieve the strikethrough color.
+   *
+   * @return The strikethrough color.
+   */
+  const Vector4& GetStrikethroughColor() const;
+
+  /**
+   * @brief Set the strikethrough enabled flag.
+   *
+   * @param[in] enabled The strikethrough enabled flag.
+   */
+  void SetStrikethroughEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether the text has a strikethrough or not.
+   *
+   * @return The strikethrough state.
+   */
+  bool IsStrikethroughEnabled() const;
+
+public: // Update.
+  /**
+   * @brief Replaces any text previously set.
+   *
+   * @note This will be converted into UTF-32 when stored in the text model.
+   * @param[in] text A string of UTF-8 characters.
+   */
+  void SetText(const std::string& text);
+
+  /**
+   * @brief Retrieve any text previously set.
+   *
+   * @param[out] text A string of UTF-8 characters.
+   */
+  void GetText(std::string& text) const;
+
+  /**
+   * @brief Replaces any placeholder text previously set.
+   *
+   * @param[in] type Different placeholder-text can be shown when the control is active/inactive.
+   * @param[in] text A string of UTF-8 characters.
+   */
+  void SetPlaceholderText(PlaceholderType type, const std::string& text);
+
+  /**
+   * @brief Retrieve any placeholder text previously set.
+   *
+   * @param[in] type Different placeholder-text can be shown when the control is active/inactive.
+   * @param[out] A string of UTF-8 characters.
+   */
+  void GetPlaceholderText(PlaceholderType type, std::string& text) const;
+
+  /**
+   * @ brief Update the text after a font change
+   * @param[in] newDefaultFont The new font to change to
+   */
+  void UpdateAfterFontChange(const std::string& newDefaultFont);
+
+  /**
+   * @brief The method acquires currently selected text
+   * @param selectedText variable to place selected text in
+   */
+  void RetrieveSelection(std::string& selectedText) const;
+
+  /**
+   * @brief The method sets selection in given range
+   * @param start index of first character
+   * @param end   index of first character after selection
+   */
+  void SetSelection(int start, int end);
+
+  /**
+   * @brief This method retrieve indexes of current selection
+   *
+   * @return a pair, where first element is left index of selection and second is the right one
+   */
+  std::pair<int, int> GetSelectionIndexes() const;
+
+  /**
+   * Place string in system clipboard
+   * @param source std::string
+   */
+  void CopyStringToClipboard(const std::string& source);
+
+  /**
+   * Place currently selected text in system clipboard
+   * @param deleteAfterSending flag pointing if text should be deleted after sending to clipboard
+   */
+  void SendSelectionToClipboard(bool deleteAfterSending);
+
+public: // Default style & Input style
+  /**
+   * @brief Set the default font family.
+   *
+   * @param[in] defaultFontFamily The default font family.
+   */
+  void SetDefaultFontFamily(const std::string& defaultFontFamily);
+
+  /**
+   * @brief Retrieve the default font family.
+   *
+   * @return The default font family.
+   */
+  const std::string& GetDefaultFontFamily() const;
+
+  /**
+   * @brief Sets the placeholder text font family.
+   * @param[in] placeholderTextFontFamily The placeholder text font family.
+   */
+  void SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily);
+
+  /**
+   * @brief Retrieves the placeholder text font family.
+   *
+   * @return The placeholder text font family
+   */
+  const std::string& GetPlaceholderFontFamily() const;
+
+  /**
+   * @brief Sets the default font weight.
+   *
+   * @param[in] weight The font weight.
+   */
+  void SetDefaultFontWeight(FontWeight weight);
+
+  /**
+   * @brief Whether the font's weight has been defined.
+   */
+  bool IsDefaultFontWeightDefined() const;
+
+  /**
+   * @brief Retrieves the default font weight.
+   *
+   * @return The default font weight.
+   */
+  FontWeight GetDefaultFontWeight() const;
+
+  /**
+   * @brief Sets the placeholder text font weight.
+   *
+   * @param[in] weight The font weight
+   */
+  void SetPlaceholderTextFontWeight(FontWeight weight);
+
+  /**
+   * @brief Whether the font's weight has been defined.
+   *
+   * @return True if the placeholder text font weight is defined
+   */
+  bool IsPlaceholderTextFontWeightDefined() const;
+
+  /**
+   * @brief Retrieves the placeholder text font weight.
+   *
+   * @return The placeholder text font weight
+   */
+  FontWeight GetPlaceholderTextFontWeight() const;
+
+  /**
+   * @brief Sets the default font width.
+   *
+   * @param[in] width The font width.
+   */
+  void SetDefaultFontWidth(FontWidth width);
+
+  /**
+   * @brief Whether the font's width has been defined.
+   */
+  bool IsDefaultFontWidthDefined() const;
+
+  /**
+   * @brief Retrieves the default font width.
+   *
+   * @return The default font width.
+   */
+  FontWidth GetDefaultFontWidth() const;
+
+  /**
+   * @brief Sets the placeholder text font width.
+   *
+   * @param[in] width The font width
+   */
+  void SetPlaceholderTextFontWidth(FontWidth width);
+
+  /**
+   * @brief Whether the font's width has been defined.
+   *
+   * @return True if the placeholder text font width is defined
+   */
+  bool IsPlaceholderTextFontWidthDefined() const;
+
+  /**
+   * @brief Retrieves the placeholder text font width.
+   *
+   * @return The placeholder text font width
+   */
+  FontWidth GetPlaceholderTextFontWidth() const;
+
+  /**
+   * @brief Sets the default font slant.
+   *
+   * @param[in] slant The font slant.
+   */
+  void SetDefaultFontSlant(FontSlant slant);
+
+  /**
+   * @brief Whether the font's slant has been defined.
+   */
+  bool IsDefaultFontSlantDefined() const;
+
+  /**
+   * @brief Retrieves the default font slant.
+   *
+   * @return The default font slant.
+   */
+  FontSlant GetDefaultFontSlant() const;
+
+  /**
+   * @brief Sets the placeholder text font slant.
+   *
+   * @param[in] slant The font slant
+   */
+  void SetPlaceholderTextFontSlant(FontSlant slant);
+
+  /**
+   * @brief Whether the font's slant has been defined.
+   *
+   * @return True if the placeholder text font slant is defined
+   */
+  bool IsPlaceholderTextFontSlantDefined() const;
+
+  /**
+   * @brief Retrieves the placeholder text font slant.
+   *
+   * @return The placeholder text font slant
+   */
+  FontSlant GetPlaceholderTextFontSlant() const;
+
+  /**
+   * @brief Set the default font size.
+   *
+   * @param[in] fontSize The default font size
+   * @param[in] type The font size type is point size or pixel size
+   */
+  void SetDefaultFontSize(float fontSize, FontSizeType type);
+
+  /**
+   * @brief Retrieve the default point size.
+   *
+   * @param[in] type The font size type
+   * @return The default point size.
+   */
+  float GetDefaultFontSize(FontSizeType type) const;
+
+  /**
+   * @brief Set the font size scale.
+   *
+   * @param[in] scale The font size scale
+   */
+  void SetFontSizeScale(float scale);
+
+  /**
+   * @brief Get the font size scale.
+   *
+   * @return The font size scale.
+   */
+  float GetFontSizeScale() const;
+
+  /**
+   * @brief Set the font size scale enabled flag.
+   *
+   * @param[in] enabled whether to enable the font size scale.
+   */
+  void SetFontSizeScaleEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether the font size scale is enabled or not.
+   *
+   * @return @e true if the font size scale is enabled, otherwise returns @e false.
+   */
+  bool IsFontSizeScaleEnabled() const;
+
+  /**
+   * @brief Sets the Placeholder text font size.
+   * @param[in] fontSize The placeholder text font size
+   * @param[in] type The font size type is point size or pixel size
+   */
+  void SetPlaceholderTextFontSize(float fontSize, FontSizeType type);
+
+  /**
+   * @brief Retrieves the Placeholder text font size.
+   * @param[in] type The font size type
+   * @return The placeholder font size
+   */
+  float GetPlaceholderTextFontSize(FontSizeType type) const;
+
+  /**
+   * @brief Sets the text's default color.
+   *
+   * @param color The default color.
+   */
+  void SetDefaultColor(const Vector4& color);
+
+  /**
+   * @brief Retrieves the text's default color.
+   *
+   * @return The default color.
+   */
+  const Vector4& GetDefaultColor() const;
+
+  /**
+   * @brief Sets the user interaction enabled.
+   *
+   * @param enabled whether to enable the user interaction.
+   */
+  void SetUserInteractionEnabled(bool enabled);
+
+  /**
+   * @brief Whether the user interaction is enabled.
+   *
+   * @return true if the user interaction is enabled, false otherwise.
+   */
+  bool IsUserInteractionEnabled() const;
+
+  /**
+   * @brief Set the text color
+   *
+   * @param textColor The text color
+   */
+  void SetPlaceholderTextColor(const Vector4& textColor);
+
+  /**
+   * @brief Retrieve the text color
+   *
+   * @return The text color
+   */
+  const Vector4& GetPlaceholderTextColor() const;
+
+  /**
+   * @brief Set the shadow offset.
+   *
+   * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow.
+   */
+  void SetShadowOffset(const Vector2& shadowOffset);
+
+  /**
+   * @brief Retrieve the shadow offset.
+   *
+   * @return The shadow offset.
+   */
+  const Vector2& GetShadowOffset() const;
+
+  /**
+   * @brief Set the shadow color.
+   *
+   * @param[in] shadowColor The shadow color.
+   */
+  void SetShadowColor(const Vector4& shadowColor);
+
+  /**
+   * @brief Retrieve the shadow color.
+   *
+   * @return The shadow color.
+   */
+  const Vector4& GetShadowColor() const;
+
+  /**
+   * @brief Set the shadow blur radius.
+   *
+   * @param[in] shadowBlurRadius The shadow blur radius, 0,0 indicates no blur.
+   */
+  void SetShadowBlurRadius(const float& shadowBlurRadius);
+
+  /**
+   * @brief Retrieve the shadow blur radius.
+   *
+   * @return The shadow blur radius.
+   */
+  const float& GetShadowBlurRadius() const;
+
+  /**
+   * @brief Set the underline color.
+   *
+   * @param[in] color color of underline.
+   */
+  void SetUnderlineColor(const Vector4& color);
+
+  /**
+   * @brief Retrieve the underline color.
+   *
+   * @return The underline color.
+   */
+  const Vector4& GetUnderlineColor() const;
+
+  /**
+   * @brief Set the underline enabled flag.
+   *
+   * @param[in] enabled The underline enabled flag.
+   */
+  void SetUnderlineEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether the text is underlined or not.
+   *
+   * @return The underline state.
+   */
+  bool IsUnderlineEnabled() const;
+
+  /**
+   * @brief Set the override used for underline height, 0 indicates height will be supplied by font metrics
+   *
+   * @param[in] height The height in pixels of the underline
+   */
+  void SetUnderlineHeight(float height);
+
+  /**
+   * @brief Retrieves the override height of an underline, 0 indicates height is supplied by font metrics
+   *
+   * @return The height of the underline, or 0 if height is not overrided.
+   */
+  float GetUnderlineHeight() const;
+
+  /**
+   * @brief Sets the underline type.
+   * @param[in] type The underline type.
+   */
+  void SetUnderlineType(Text::Underline::Type type);
+
+  /**
+   * @brief Retrieve underline type.
+   * @return The underline type.
+   */
+  Text::Underline::Type GetUnderlineType() const;
+
+  /**
+   * @brief Set the width of the dashes of the dashed underline.
+   *
+   * @param[in] width The width in pixels of the dashes of the dashed underline.
+   */
+  void SetDashedUnderlineWidth(float width);
+
+  /**
+   * @brief Retrieves the width of the dashes of the dashed underline.
+   *
+   * @return The width of the dashes of the dashed underline.
+   */
+  float GetDashedUnderlineWidth() const;
+
+  /**
+   * @brief Set the gap between the dashes of the dashed underline.
+   *
+   * @param[in] gap The gap between the dashes of the dashed underline.
+   */
+  void SetDashedUnderlineGap(float gap);
+
+  /**
+   * @brief Retrieves the gap between the dashes of the dashed underline.
+   *
+   * @return The The gap between the dashes of the dashed underline.
+   */
+  float GetDashedUnderlineGap() const;
+
+  /**
+   * @brief Set the outline color.
+   *
+   * @param[in] color color of outline.
+   */
+  void SetOutlineColor(const Vector4& color);
+
+  /**
+   * @brief Retrieve the outline color.
+   *
+   * @return The outline color.
+   */
+  const Vector4& GetOutlineColor() const;
+
+  /**
+   * @brief Set the outline width
+   *
+   * @param[in] width The width in pixels of the outline, 0 indicates no outline
+   */
+  void SetOutlineWidth(uint16_t width);
+
+  /**
+   * @brief Retrieves the width of an outline
+   *
+   * @return The width of the outline.
+   */
+  uint16_t GetOutlineWidth() const;
+
+  /**
+   * @brief Set the background color.
+   *
+   * @param[in] color color of background.
+   */
+  void SetBackgroundColor(const Vector4& color);
+
+  /**
+   * @brief Retrieve the background color.
+   *
+   * @return The background color.
+   */
+  const Vector4& GetBackgroundColor() const;
+
+  /**
+   * @brief Set the background enabled flag.
+   *
+   * @param[in] enabled The background enabled flag.
+   */
+  void SetBackgroundEnabled(bool enabled);
+
+  /**
+   * @brief Returns whether to enable text background or not.
+   *
+   * @return Whether text background is enabled.
+   */
+  bool IsBackgroundEnabled() const;
+
+  /**
+   * @brief Sets the emboss's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] embossProperties The emboss's properties string.
+   */
+  void SetDefaultEmbossProperties(const std::string& embossProperties);
+
+  /**
+   * @brief Retrieves the emboss's properties string.
+   *
+   * @return The emboss's properties string.
+   */
+  const std::string& GetDefaultEmbossProperties() const;
+
+  /**
+   * @brief Sets the outline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] outlineProperties The outline's properties string.
+   */
+  void SetDefaultOutlineProperties(const std::string& outlineProperties);
+
+  /**
+   * @brief Retrieves the outline's properties string.
+   *
+   * @return The outline's properties string.
+   */
+  const std::string& GetDefaultOutlineProperties() const;
+
+  /**
+   * @brief Sets the default line spacing.
+   *
+   * @param[in] lineSpacing The line spacing.
+   *
+   * @return True if lineSpacing has been updated, false otherwise
+   */
+  bool SetDefaultLineSpacing(float lineSpacing);
+
+  /**
+   * @brief Retrieves the default line spacing.
+   *
+   * @return The line spacing.
+   */
+  float GetDefaultLineSpacing() const;
+
+  /**
+   * @brief Sets the default line size.
+   *
+   * @param[in] lineSize The line size.
+   *
+   * @return True if lineSize has been updated, false otherwise
+   */
+  bool SetDefaultLineSize(float lineSize);
+
+  /**
+   * @brief Retrieves the default line size.
+   *
+   * @return The line size.
+   */
+  float GetDefaultLineSize() const;
+
+  /**
+   * @brief Sets the relative line size to the original line size.
+   *
+   * @param[in] relativeLineSize The relativeline size.
+   *
+   * @return True if relativeLineSize has been updated, false otherwise
+   */
+  bool SetRelativeLineSize(float lineSize);
+
+  /**
+   * @brief Retrieves the relative line size.
+   *
+   * @return The relative line size.
+   */
+  float GetRelativeLineSize() const;
+
+  /**
+   * @brief Sets the input text's color.
+   *
+   * @param[in] color The input text's color.
+   */
+  void SetInputColor(const Vector4& color);
+
+  /**
+   * @brief Retrieves the input text's color.
+   *
+   * @return The input text's color.
+   */
+  const Vector4& GetInputColor() const;
+
+  /**
+   * @brief Sets the input text's font family name.
+   *
+   * @param[in] fontFamily The text's font family name.
+   */
+  void SetInputFontFamily(const std::string& fontFamily);
+
+  /**
+   * @brief Retrieves the input text's font family name.
+   *
+   * @return The input text's font family name.
+   */
+  const std::string& GetInputFontFamily() const;
+
+  /**
+   * @brief Sets the input font's weight.
+   *
+   * @param[in] weight The input font's weight.
+   */
+  void SetInputFontWeight(FontWeight weight);
+
+  /**
+   * @return Whether the font's weight has been defined.
+   */
+  bool IsInputFontWeightDefined() const;
+
+  /**
+   * @brief Retrieves the input font's weight.
+   *
+   * @return The input font's weight.
+   */
+  FontWeight GetInputFontWeight() const;
+
+  /**
+   * @brief Sets the input font's width.
+   *
+   * @param[in] width The input font's width.
+   */
+  void SetInputFontWidth(FontWidth width);
+
+  /**
+   * @return Whether the font's width has been defined.
+   */
+  bool IsInputFontWidthDefined() const;
+
+  /**
+   * @brief Retrieves the input font's width.
+   *
+   * @return The input font's width.
+   */
+  FontWidth GetInputFontWidth() const;
+
+  /**
+   * @brief Sets the input font's slant.
+   *
+   * @param[in] slant The input font's slant.
+   */
+  void SetInputFontSlant(FontSlant slant);
+
+  /**
+   * @return Whether the font's slant has been defined.
+   */
+  bool IsInputFontSlantDefined() const;
+
+  /**
+   * @brief Retrieves the input font's slant.
+   *
+   * @return The input font's slant.
+   */
+  FontSlant GetInputFontSlant() const;
+
+  /**
+   * @brief Sets the input font's point size.
+   *
+   * @param[in] size The input font's point size.
+   */
+  void SetInputFontPointSize(float size);
+
+  /**
+   * @brief Retrieves the input font's point size.
+   *
+   * @return The input font's point size.
+   */
+  float GetInputFontPointSize() const;
+
+  /**
+   * @brief Sets the input line spacing.
+   *
+   * @param[in] lineSpacing The line spacing.
+   */
+  void SetInputLineSpacing(float lineSpacing);
+
+  /**
+   * @brief Retrieves the input line spacing.
+   *
+   * @return The line spacing.
+   */
+  float GetInputLineSpacing() const;
+
+  /**
+   * @brief Sets the input shadow's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] shadowProperties The shadow's properties string.
+   */
+  void SetInputShadowProperties(const std::string& shadowProperties);
+
+  /**
+   * @brief Retrieves the input shadow's properties string.
+   *
+   * @return The shadow's properties string.
+   */
+  const std::string& GetInputShadowProperties() const;
+
+  /**
+   * @brief Sets the input underline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] underlineProperties The underline's properties string.
+   */
+  void SetInputUnderlineProperties(const std::string& underlineProperties);
+
+  /**
+   * @brief Retrieves the input underline's properties string.
+   *
+   * @return The underline's properties string.
+   */
+  const std::string& GetInputUnderlineProperties() const;
+
+  /**
+   * @brief Sets the input emboss's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] embossProperties The emboss's properties string.
+   */
+  void SetInputEmbossProperties(const std::string& embossProperties);
+
+  /**
+   * @brief Retrieves the input emboss's properties string.
+   *
+   * @return The emboss's properties string.
+   */
+  const std::string& GetInputEmbossProperties() const;
+
+  /**
+   * @brief Sets input the outline's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] outlineProperties The outline's properties string.
+   */
+  void SetInputOutlineProperties(const std::string& outlineProperties);
+
+  /**
+   * @brief Retrieves the input outline's properties string.
+   *
+   * @return The outline's properties string.
+   */
+  const std::string& GetInputOutlineProperties() const;
+
+  /**
+   * @brief Sets the input strikethrough's properties string.
+   *
+   * @note The string is stored to be recovered.
+   *
+   * @param[in] strikethroughProperties The strikethrough's properties string.
+   */
+  void SetInputStrikethroughProperties(const std::string& strikethroughProperties);
+
+  /**
+   * @brief Retrieves the input strikethrough's properties string.
+   *
+   * @return The strikethrough's properties string.
+   */
+  const std::string& GetInputStrikethroughProperties() const;
+
+  /**
+   * @brief Set the control's interface.
+   *
+   * @param[in] controlInterface The control's interface.
+   */
+  void SetControlInterface(ControlInterface* controlInterface);
+
+  /**
+   * @brief Set the anchor control's interface.
+   *
+   * @param[in] anchorControlInterface The control's interface.
+   */
+  void SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface);
+
+  /**
+   * @brief Sets the character spacing.
+   *
+   * @note A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
+   *
+   * @param[in] characterSpacing The character spacing.
+   */
+  void SetCharacterSpacing(float characterSpacing);
+
+  /**
+   * @brief Retrieves the character spacing.
+   *
+   * @note A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
+   *
+   * @return The character spacing.
+   */
+  const float GetCharacterSpacing() const;
+
+public: // Queries & retrieves.
+  /**
+   * @brief Return the layout engine.
+   *
+   * @return A reference to the layout engine.
+   */
+  Layout::Engine& GetLayoutEngine();
+
+  /**
+   * @brief Return a view of the text.
+   *
+   * @return A reference to the view.
+   */
+  View& GetView();
+
+  /**
+   * @copydoc Control::GetNaturalSize()
+   */
+  Vector3 GetNaturalSize();
+
+  /**
+   * @copydoc Control::GetHeightForWidth()
+   */
+  float GetHeightForWidth(float width);
+
+  /**
+   * @brief Calculates the point size for text for given layout()
+   */
+  void FitPointSizeforLayout(Size layoutSize);
+
+  /**
+   * @brief Checks if the point size fits within the layout size.
+   *
+   * @return Whether the point size fits within the layout size.
+   */
+  bool CheckForTextFit(float pointSize, Size& layoutSize);
+
+  /**
+   * @brief Retrieves the text's number of lines for a given width.
+   * @param[in] width The width of the text's area.
+   * @ return The number of lines.
+   */
+  int GetLineCount(float width);
+
+  /**
+   * @brief Retrieves the text's model.
+   *
+   * @return A pointer to the text's model.
+   */
+  const ModelInterface* const GetTextModel() const;
+
+  /**
+   * @brief Used to get scrolled distance by user input
+   *
+   * @return Distance from last scroll offset to new scroll offset
+   */
+  float GetScrollAmountByUserInput();
+
+  /**
+   * @brief Get latest scroll amount, control size and layout size
+   *
+   * This method is used to get information of control's scroll
+   * @param[out] scrollPosition The current scrolled position
+   * @param[out] controlHeight The size of a UI control
+   * @param[out] layoutHeight The size of a bounding box to layout text within.
+   *
+   * @return Whether the text scroll position is changed or not after last update.
+   */
+  bool GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight);
+
+  /**
+   * @brief Used to set the hidden input option
+   */
+  void SetHiddenInputOption(const Property::Map& options);
+
+  /**
+   * @brief Used to get the hidden input option
+   */
+  void GetHiddenInputOption(Property::Map& options);
+
+  /**
+   * @brief Used to set the input filter option
+   */
+  void SetInputFilterOption(const Property::Map& options);
+
+  /**
+   * @brief Used to get the input filter option
+   */
+  void GetInputFilterOption(Property::Map& options);
+
+  /**
+   * @brief Sets the Placeholder Properties.
+   *
+   * @param[in] map The placeholder property map
+   */
+  void SetPlaceholderProperty(const Property::Map& map);
+
+  /**
+   * @brief Retrieves the Placeholder Property map.
+   *
+   * @param[out] map The property map
+   */
+  void GetPlaceholderProperty(Property::Map& map);
+
+  /**
+   * @brief Checks text direction.
+   * @return The text direction.
+   */
+  Toolkit::DevelText::TextDirection::Type GetTextDirection();
+
+  /**
+   * @brief Retrieves vertical line alignment
+   * @return The vertical line alignment
+   */
+  Toolkit::DevelText::VerticalLineAlignment::Type GetVerticalLineAlignment() const;
+
+  /**
+   * @brief Sets vertical line alignment
+   * @param[in] alignment The vertical line alignment for the text
+   */
+  void SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment);
+
+  /**
+   * @brief Retrieves ellipsis position
+   * @return The ellipsis position
+   */
+  Toolkit::DevelText::EllipsisPosition::Type GetEllipsisPosition() const;
+
+  /**
+   * @brief Sets ellipsis position
+   * @param[in] ellipsisPosition The ellipsis position for the text
+   */
+  void SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition);
+
+  /**
+   * @brief Retrieves ignoreSpaceAfterText value from model
+   * @return The value of ignoreSpaceAfterText
+   */
+  bool IsIgnoreSpacesAfterText() const;
+
+  /**
+   * @brief Sets ignoreSpaceAfterText value to model
+   * @param[in] ignore The value of ignoreSpacesAfterText for the text
+   */
+  void SetIgnoreSpacesAfterText(bool ignore);
+
+  /**
+   * @brief Sets SetMatchLayoutDirection value to model
+   * @param[in] match The value of matchLayoutDirection for the text
+   */
+  void SetMatchLayoutDirection(DevelText::MatchLayoutDirection type);
+
+  /**
+   * @brief Retrieves matchLayoutDirection value from model
+   * @return The value of matchLayoutDirection
+   */
+  DevelText::MatchLayoutDirection GetMatchLayoutDirection() const;
+
+  /**
+   * @brief Sets layoutDirection type value.
+   * @param[in] layoutDirection The value of the layout direction type.
+   */
+  void SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection);
+
+  /**
+   * @brief Gets layoutDirection type value.
+   * @param[in] actor The actor which will get the layout direction type.
+   * @return The value of the layout direction type.
+   */
+  Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
+
+  /**
+   * @brief Get the rendered size of a specific text range.
+   * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
+   * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
+   *
+   * @param[in] startIndex start index of the text requested to calculate size for.
+   * @param[in] endIndex end index(included) of the text requested to calculate size for.
+   * @return list of sizes of the reuested text.
+   */
+  Vector<Vector2> GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex);
+
+  /**
+   * @brief Get the top/left rendered position of a specific text range.
+   * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
+   * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
+   *
+   * @param[in] startIndex start index of the text requested to get position to.
+   * @param[in] endIndex end index(included) of the text requested to get position to.
+   * @return list of positions of the requested text.
+   */
+  Vector<Vector2> GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex);
+
+  /**
+   * @brief Gets the bounding box of a specific text range.
+   *
+   * @param[in] startIndex start index of the text requested to get bounding box to.
+   * @param[in] endIndex end index(included) of the text requested to get bounding box to.
+   * @return bounding box of the requested text.
+   */
+  Rect<> GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex);
+
+  /**
+   * @brief Sets the layout direction changed.
+   */
+  void ChangedLayoutDirection();
+
+  /**
+   * @brief Retrieves if showing real text or not.
+   * @return The value of showing real text.
+   */
+  bool IsShowingRealText() const;
+
+public: // Relayout.
+  /**
+   * @brief Triggers a relayout which updates View (if necessary).
+   *
+   * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation.
+   * @param[in] size A the size of a bounding box to layout text within.
+   * @param[in] layoutDirection The direction of the system language.
+   *
+   * @return Whether the text model or decorations were updated.
+   */
+  UpdateTextType Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection = Dali::LayoutDirection::LEFT_TO_RIGHT);
+
+  /**
+   * @brief Request a relayout using the ControlInterface.
+   */
+  void RequestRelayout();
+
+public: // Input style change signals.
+  /**
+   * @return Whether the queue of input style changed signals is empty.
+   */
+  bool IsInputStyleChangedSignalsQueueEmpty();
+
+  /**
+   * @brief Process all pending input style changed signals.
+   *
+   * Calls the Text::ControlInterface::InputStyleChanged() method which is overriden by the
+   * text controls. Text controls may send signals to state the input style has changed.
+   */
+  void ProcessInputStyleChangedSignals();
+
+public: // Text-input Event Queuing.
+  /**
+   * @brief Called by editable UI controls when keyboard focus is gained.
+   */
+  void KeyboardFocusGainEvent();
+
+  /**
+   * @brief Called by editable UI controls when focus is lost.
+   */
+  void KeyboardFocusLostEvent();
+
+  /**
+   * @brief Called by editable UI controls when key events are received.
+   *
+   * @param[in] event The key event.
+   * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
+   */
+  bool KeyEvent(const Dali::KeyEvent& event);
+
+  /**
+   * @brief Called by anchor when a tap gesture occurs.
+   * @param[in] x The x position relative to the top-left of the parent control.
+   * @param[in] y The y position relative to the top-left of the parent control.
+   */
+  void AnchorEvent(float x, float y);
+
+  /**
+   * @brief Called by editable UI controls when a tap gesture occurs.
+   * @param[in] tapCount The number of taps.
+   * @param[in] x The x position relative to the top-left of the parent control.
+   * @param[in] y The y position relative to the top-left of the parent control.
+   */
+  void TapEvent(unsigned int tapCount, float x, float y);
+
+  /**
+   * @brief Called by editable UI controls when a pan gesture occurs.
+   *
+   * @param[in] state The state of the gesture.
+   * @param[in] displacement This distance panned since the last pan gesture.
+   */
+  void PanEvent(GestureState state, const Vector2& displacement);
+
+  /**
+   * @brief Called by editable UI controls when a long press gesture occurs.
+   *
+   * @param[in] state The state of the gesture.
+   * @param[in] x The x position relative to the top-left of the parent control.
+   * @param[in] y The y position relative to the top-left of the parent control.
+   */
+  void LongPressEvent(GestureState state, float x, float y);
+
+  /**
+   * @brief Used to get the Primary cursor position.
+   *
+   * @return Primary cursor position.
+   */
+  CharacterIndex GetPrimaryCursorPosition() const;
+
+  /**
+   * @brief Used to set the Primary cursor position.
+   *
+   * @param[in] index for the Primary cursor position.
+   * @param[in] focused true if UI control has gained focus to receive key event, false otherwise.
+   * @return[in] true if cursor position changed, false otherwise.
+   */
+  bool SetPrimaryCursorPosition(CharacterIndex index, bool focused);
+
+  /**
+   * @brief Creates a selection event.
+   *
+   * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed.
+   *
+   * @param[in] x The x position relative to the top-left of the parent control.
+   * @param[in] y The y position relative to the top-left of the parent control.
+   * @param[in] selection type like the whole text is selected or unselected.
+   */
+  void SelectEvent(float x, float y, SelectionType selection);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
+   */
+  void SetTextSelectionRange(const uint32_t* start, const uint32_t* end);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
+   */
+  Uint32Pair GetTextSelectionRange() const;
+
+  /**
+   * @copydoc Text::SelectableControlInterface::SelectWholeText()
+   */
+  void SelectWholeText();
+
+  /**
+   * @copydoc Text::EditableControlInterface::CopyText()
+   */
+  string CopyText();
+
+  /**
+   * @copydoc Text::EditableControlInterface::CutText()
+   */
+  string CutText();
+
+  /**
+   * @copydoc Text::EditableControlInterface::PasteText()
+   */
+  void PasteText();
+
+  /**
+   * @copydoc Text::SelectableControlInterface::SelectNone()
+   */
+  void SelectNone();
+
+  /**
+   * @copydoc Text::SelectableControlInterface::SelectText()
+   */
+  void SelectText(const uint32_t start, const uint32_t end);
+
+  /**
+   * @copydoc Text::SelectableControlInterface::GetSelectedText()
+   */
+  string GetSelectedText() const;
+
+  /**
+   * @copydoc Text::EditableControlInterface::IsEditable()
+   */
+  virtual bool IsEditable() const;
+
+  /**
+   * @copydoc Text::EditableControlInterface::SetEditable()
+   */
+  virtual void SetEditable(bool editable);
+
+  /**
+   * @copydoc Dali::Toolkit::Internal::TextEditor::ScrollBy()
+   */
+  virtual void ScrollBy(Vector2 scroll);
+
+  /**
+   * @brief Whether the text is scrollable.
+   * @return Returns true if the text is scrollable.
+   */
+  bool IsScrollable(const Vector2& displacement);
+
+  /**
+   * @copydoc Dali::Toolkit::Internal::TextEditor::GetHorizontalScrollPosition()
+   */
+  float GetHorizontalScrollPosition();
+
+  /**
+   * @copydoc Dali::Toolkit::Internal::TextEditor::GetVerticalScrollPosition()
+   */
+  float GetVerticalScrollPosition();
+
+  /**
+   * @brief Event received from input method context
+   *
+   * @param[in] inputMethodContext The input method context.
+   * @param[in] inputMethodContextEvent The event received.
+   * @return A data struture indicating if update is needed, cursor position and current text.
+   */
+  InputMethodContext::CallbackData OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent);
+
+  /**
+   * @brief Event from Clipboard notifying an Item has been selected for pasting
+   */
+  void PasteClipboardItemEvent();
+
+  /**
+   * @brief Return true when text control should clear key input focus when escape key is pressed.
+   *
+   * @return Whether text control should clear key input focus or not when escape key is pressed.
+   */
+  bool ShouldClearFocusOnEscape() const;
+
+  /**
+   * @brief Create an actor that renders the text background color
+   *
+   * @return the created actor or an empty handle if no background color needs to be rendered.
+   */
+  Actor CreateBackgroundActor();
+
+  /**
+   * @brief Used to reset the cursor position after setting a new text.
+   *
+   * @param[in] cursorIndex Where to place the cursor.
+   */
+  void ResetCursorPosition(CharacterIndex cursorIndex);
+
+  /**
+   * @brief The method acquires current position of cursor
+   * @return unsigned value with cursor position
+   */
+  CharacterIndex GetCursorPosition();
+
+  /**
+   * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
+   *
+   * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
+   */
+  void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
+
+  /**
+   * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
+   *
+   * @param[in] characterOffset A position in text coords.
+   *
+   * @return the index in anchor vector (-1 if an anchor not found)
+   */
+  int GetAnchorIndex(size_t characterOffset);
+
+protected: // Inherit from Text::Decorator::ControllerInterface.
+  /**
+   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::GetTargetSize()
+   */
+  void GetTargetSize(Vector2& targetSize) override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
+   */
+  void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) override;
+
+  /**
+   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
+   */
+  void DecorationEvent(HandleType handle, HandleState state, float x, float y) override;
+
+protected: // Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
+  /**
+   * @copydoc Dali::Toolkit::TextSelectionPopup::TextPopupButtonCallbackInterface::TextPopupButtonTouched()
+   */
+  void TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button) override;
+
+protected: // Inherit from HiddenText.
+  /**
+   * @brief Invoked from HiddenText when showing time of the last character was expired
+   */
+  void DisplayTimeExpired() override;
+
+private: // Private contructors & copy operator.
+  /**
+   * @brief Private constructor.
+   */
+  Controller()
+  : Controller(nullptr, nullptr, nullptr, nullptr)
+  {
+  }
+
+  /**
+   * @brief Private constructor.
+   */
+  Controller(ControlInterface* controlInterface)
+  : Controller(controlInterface, nullptr, nullptr, nullptr)
+  {
+  }
+
+  /**
+   * @brief Private constructor.
+   */
+  Controller(ControlInterface*           controlInterface,
+             EditableControlInterface*   editableControlInterface,
+             SelectableControlInterface* selectableControlInterface,
+             AnchorControlInterface*     anchorControlInterface);
+
+  Controller(const Controller& handle) = delete;
+  Controller& operator=(const Controller& handle) = delete;
+
+protected: // Destructor.
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference().
+   */
+  virtual ~Controller();
+
+public:
+  struct Impl; ///< Made public for testing purposes
+
+private:
+  struct EventHandler;
+  struct InputFontHandler;
+  struct InputProperties;
+  struct PlaceholderHandler;
+  struct Relayouter;
+  struct TextUpdater;
+
+  Impl* mImpl;
+};
+
+} // namespace Dali::Toolkit::Text
+
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
diff --git a/dali-toolkit/internal/text/markup-processor-anchor.cpp b/dali-toolkit/internal/text/markup-processor-anchor.cpp
deleted file mode 100644 (file)
index 771ff4e..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-anchor.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/anchor.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessAnchor(const Tag& tag, Anchor& anchor)
-{
-  anchor.href = nullptr;
-
-  for(auto&& attribute : tag.attributes)
-  {
-    if(TokenComparison(MARKUP::ANCHOR_ATTRIBUTES::HREF, attribute.nameBuffer, attribute.nameLength))
-    {
-      Length hrefLength = attribute.valueLength + 1;
-      anchor.href       = new char[hrefLength];
-      memcpy(anchor.href, attribute.valueBuffer, hrefLength);
-      anchor.href[hrefLength - 1] = '\0';
-      // The memory is freed when the font run is removed from the logical model.
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor-anchor.h b/dali-toolkit/internal/text/markup-processor-anchor.h
deleted file mode 100644 (file)
index 7c1d181..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Text
-{
-
-struct Tag;
-struct Anchor;
-
-/**
- * @brief Retrieves the @e anchor from the @p tag.
- *
- * @param[in] tag The anchor tag and its attributes.
- * @param[in,out] anchor The anchor.
- */
-void ProcessAnchor( const Tag& tag, Anchor& anchor );
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor-attribute-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor-attribute-helper-functions.cpp
deleted file mode 100644 (file)
index da00996..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-
-// EXTERNAL INCLUDES
-#include <memory.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void CopyAttributeValueFromBuffer(const Attribute& attribute, const Length maxLengthAttributeValue, char* value)
-{
-  const Length length = attribute.valueLength > maxLengthAttributeValue ? maxLengthAttributeValue : attribute.valueLength;
-  memcpy(value, attribute.valueBuffer, length);
-  value[length] = 0;
-}
-
-float ProcessFloatAttribute(const Attribute& attribute)
-{
-  return StringToFloat(attribute.valueBuffer);
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h b/dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h
deleted file mode 100644 (file)
index 52771b5..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
-
-// EXTERNAL INCLUDES
-#include <functional>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Attribute;
-
-/**
- * @brief Copy the value from attribute buffer to value.
- *
- * @param[in] attribute the value of attribute.
- * @param[in] maxLengthAttributeValue the maximum length of any of the possible value for attribute
- * @param[out] value the value container.
- *
- */
-void CopyAttributeValueFromBuffer(const Attribute& attribute, const Length maxLengthAttributeValue, char* value);
-
-/**
- * @brief Process the float attribute value from buffer.
- *
- * @param[in] attribute the float attribute.
- *
- * @return The float value.
- */
-float ProcessFloatAttribute(const Attribute& attribute);
-
-/**
- * @brief Process the Enumeration attribute value from buffer.
- *
- * @param[in] attribute the Enumeration attribute.
- * @param[in] maxLengthAttributeValue the maximum length of any of the possible value for attribute
- * @param[in] funcStringToEnum the function converts string value to enum value
- * @param[out] enumValue the enum value
- *
- * @return      True if the enum value was processed successfully
- *
- */
-template<typename T>
-bool ProcessEnumerationAttribute(const Attribute&                    attribute,
-                                 const Length                        maxLengthAttributeValue,
-                                 std::function<T(const char* const)> funcStringToEnum,
-                                 T&                                  enumValue)
-{
-  char* value = new char[maxLengthAttributeValue + 1u];
-
-  CopyAttributeValueFromBuffer(attribute, maxLengthAttributeValue, value);
-
-  enumValue = funcStringToEnum(value); // @TODO: the functions that process Enum value should be refactored to return bool from Scripting::GetEnumeration
-
-  delete[] value;
-
-  return true;
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
diff --git a/dali-toolkit/internal/text/markup-processor-background.cpp b/dali-toolkit/internal/text/markup-processor-background.cpp
deleted file mode 100644 (file)
index 7f0e8ae..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-background.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/color-run.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessBackground(const Tag& tag, ColorRun& colorRun)
-{
-  for(auto&& attribute : tag.attributes)
-  {
-    if(TokenComparison(MARKUP::BACKGROUND_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor-background.h b/dali-toolkit/internal/text/markup-processor-background.h
deleted file mode 100644 (file)
index 331d2c8..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct ColorRun;
-
-/**
- * @brief Retrieves the @e background from the @p tag.
- *
- * @param[in] tag The background tag and its attributes.
- * @param[in,out] colorRun The color run to be filled.
- */
-void ProcessBackground(const Tag& tag, ColorRun& colorRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.cpp b/dali-toolkit/internal/text/markup-processor-character-spacing.cpp
deleted file mode 100644 (file)
index cce30dd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-spacing-character-run.h>
-#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
-{
-  characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute);
-}
-
-void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-
-    if(TokenComparison(MARKUP::CHARACTER_SPACING_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-character-spacing.h b/dali-toolkit/internal/text/markup-processor-character-spacing.h
deleted file mode 100644 (file)
index b8b9beb..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-struct CharacterSpacingCharacterRun;
-
-/**
- * @brief Fill the character-spacing character run with the value (space or advance) attribute.
- *
- * @param[in] attribute the value attribute.
- * @param[out] characterSpacingCharacterRun The underlined character run
- */
-void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
-
-/**
- * @brief Retrieves the character-spacing run info from the tag and sets it to the character-spacing run.
- *
- * @param[in] tag The character-spacing tag and its attributes.
- * @param[in,out] characterSpacingCharacterRun The character-spacing character run
- */
-void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
diff --git a/dali-toolkit/internal/text/markup-processor-color.cpp b/dali-toolkit/internal/text/markup-processor-color.cpp
deleted file mode 100644 (file)
index 4fb95ef..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-color.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/color-run.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessColor(const Attribute& attribute, ColorRun& colorRun)
-{
-  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
-}
-
-void ProcessColorTag(const Tag& tag, ColorRun& colorRun)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-    if(TokenComparison(MARKUP::COLOR_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessColor(attribute, colorRun);
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-color.h b/dali-toolkit/internal/text/markup-processor-color.h
deleted file mode 100644 (file)
index 02210fb..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-struct ColorRun;
-
-/**
- * @brief Retrieves the color value from the tag and sets it to the color run.
- *
- * @param[in] attribute the color attribute.
- * @param[in,out] colorRun The color run.
- */
-void ProcessColor(const Attribute& attribute, ColorRun& colorRun);
-
-/**
- * @brief Retrieves the color value from the tag and sets it to the color run.
- *
- * @param[in] tag The color tag and its attributes.
- * @param[in,out] colorRun The color run.
- */
-void ProcessColorTag(const Tag& tag, ColorRun& colorRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
diff --git a/dali-toolkit/internal/text/markup-processor-embedded-item.cpp b/dali-toolkit/internal/text/markup-processor-embedded-item.cpp
deleted file mode 100644 (file)
index 94d6fd4..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/embedded-item.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-const std::string NONE("none");
-const std::string MULTIPLY("multiply");
-} // namespace
-
-void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem)
-{
-  embeddedItem.url               = nullptr;
-  embeddedItem.urlLength         = 0u;
-  embeddedItem.width             = 0u;
-  embeddedItem.height            = 0u;
-  embeddedItem.colorBlendingMode = ColorBlendingMode::NONE;
-
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-    if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::URL, attribute.nameBuffer, attribute.nameLength))
-    {
-      embeddedItem.urlLength = attribute.valueLength;
-      embeddedItem.url       = new char[embeddedItem.urlLength];
-      memcpy(embeddedItem.url, attribute.valueBuffer, embeddedItem.urlLength);
-      // The memory is freed when the font run is removed from the logical model.
-    }
-    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
-    {
-      embeddedItem.width = StringToUint(attribute.valueBuffer);
-    }
-    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      embeddedItem.height = StringToUint(attribute.valueBuffer);
-    }
-    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::COLOR_BLENDING, attribute.nameBuffer, attribute.nameLength))
-    {
-      if(TokenComparison(MULTIPLY, attribute.valueBuffer, attribute.valueLength))
-      {
-        embeddedItem.colorBlendingMode = ColorBlendingMode::MULTIPLY;
-      }
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-embedded-item.h b/dali-toolkit/internal/text/markup-processor-embedded-item.h
deleted file mode 100644 (file)
index 1677244..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct EmbeddedItem;
-
-/**
- * @brief Retrieves the @e embedded @e item from the @p tag.
- *
- * @param[in] tag The embedded item tag and its attributes.
- * @param[in,out] embeddedItem The embedded item.
- */
-void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
diff --git a/dali-toolkit/internal/text/markup-processor-font.cpp b/dali-toolkit/internal/text/markup-processor-font.cpp
deleted file mode 100644 (file)
index 802f9e9..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-font.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/font-description-run.h>
-#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-#include <dali-toolkit/internal/text/text-font-style.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-const std::string  FONT_PREFIX("font-");
-const unsigned int FONT_PREFIX_LENGTH      = 5u;
-const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u;   ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values.
-const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u;  ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values.
-const float        PIXEL_FORMAT_64_FACTOR  = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
-} // namespace
-
-void processFontAttributeValue(char value[], const Attribute& attribute)
-{
-  // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
-  const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
-  memcpy(value, attribute.valueBuffer, length);
-  value[length] = 0;
-}
-
-void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun)
-{
-  fontRun.familyDefined = true;
-  fontRun.familyLength  = attribute.valueLength;
-  fontRun.familyName    = new char[fontRun.familyLength];
-  memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength);
-  // The memory is freed when the font run is removed from the logical model.
-}
-
-void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun)
-{
-  // 64.f is used to convert from point size to 26.6 pixel format.
-  fontRun.size        = static_cast<PointSize26Dot6>(ProcessFloatAttribute(attribute) * PIXEL_FORMAT_64_FACTOR);
-  fontRun.sizeDefined = true;
-}
-
-void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun)
-{
-  fontRun.weightDefined = ProcessEnumerationAttribute<FontWeight>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToWeight, fontRun.weight);
-}
-
-void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun)
-{
-  fontRun.widthDefined = ProcessEnumerationAttribute<FontWidth>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToWidth, fontRun.width);
-}
-
-void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun)
-{
-  fontRun.slantDefined = ProcessEnumerationAttribute<FontSlant>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToSlant, fontRun.slant);
-}
-
-void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-
-    if(TokenComparison(MARKUP::FONT_ATTRIBUTES::FAMILY, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessFontFamily(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SIZE, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessFontSize(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessFontWeight(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessFontWidth(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SLANT, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessFontSlant(attribute, fontRun);
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-font.h b/dali-toolkit/internal/text/markup-processor-font.h
deleted file mode 100644 (file)
index 6461451..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-struct FontDescriptionRun;
-
-/**
- * @brief Retrieves the font attributes from the tag and sets it to the font run.
- *
- * @param[in] tag The font tag and its attributes.
- * @param[in,out] fontRun The font description run.
- */
-void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun);
-
-/**
- * @brief Fill the font run with the font slant attribute value.
- *
- * @param[in] attribute the font slant attribute.
- * @param[out] fontRun The font description run.
- */
-void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun);
-
-/**
- * @brief Fill the font run with the font width attribute value.
- *
- * @param[in] attribute the font width attribute.
- * @param[out] fontRun The font description run.
- */
-void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun);
-
-/**
- * @brief Fill the font run with the font weight attribute value.
- *
- * @param[in] attribute the font weight attribute.
- * @param[out] fontRun The font description run.
- */
-void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun);
-
-/**
- * @brief Fill the font run with the font size attribute value.
- *
- * @param[in] attribute the font size attribute.
- * @param[out] fontRun The font description run.
- */
-void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun);
-
-/**
- * @brief Fill the font run with the font family attribute value.
- *
- * @param[in] attribute the font family attribute.
- * @param[out] fontRun The font description run.
- */
-void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp
deleted file mode 100644 (file)
index 9f4c34d..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/constants.h>
-#include <dali/public-api/math/vector2.h>
-#include <stdlib.h>
-#include <iomanip>
-#include <sstream>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-const char WHITE_SPACE      = 0x20; // ASCII value of the white space.
-const char FIRST_UPPER_CASE = 0x41; // ASCII value of the one after the first upper case character (A).
-const char LAST_UPPER_CASE  = 0x5b; // ASCII value of the one after the last upper case character (Z).
-const char TO_LOWER_CASE    = 32;   // Value to add to a upper case character to transform it into a lower case.
-
-const unsigned int MAX_FLOAT_ATTRIBUTE_SIZE = 17u; ///< The maximum length of any of the possible float values.  +99999.999999999f  (sign, five digits, dot, nine digits, f)
-
-const char        WEB_COLOR_TOKEN('#');
-const char* const HEX_COLOR_TOKEN("0x");
-const char* const ALPHA_ONE("FF");
-
-const std::string BLACK_COLOR("black");
-const std::string WHITE_COLOR("white");
-const std::string RED_COLOR("red");
-const std::string GREEN_COLOR("green");
-const std::string BLUE_COLOR("blue");
-const std::string YELLOW_COLOR("yellow");
-const std::string MAGENTA_COLOR("magenta");
-const std::string CYAN_COLOR("cyan");
-const std::string TRANSPARENT_COLOR("transparent");
-
-const std::string SOLID_UNDERLINE("solid");
-const std::string DASHED_UNDERLINE("dashed");
-const std::string DOUBLE_UNDERLINE("double");
-
-const std::string BEGIN_HORIZONTAL_ALIGNMENT("begin");
-const std::string CENTER_HORIZONTAL_ALIGNMENT("center");
-const std::string END_HORIZONTAL_ALIGNMENT("end");
-
-} // namespace
-
-bool TokenComparison(const std::string& string1, const char* const stringBuffer2, Length length)
-{
-  const Length stringSize = string1.size();
-  if(stringSize != length)
-  {
-    // Early return. Strings have different sizes.
-    return false;
-  }
-
-  const char* const stringBuffer1 = string1.c_str();
-
-  for(std::size_t index = 0; index < stringSize; ++index)
-  {
-    const char character = *(stringBuffer2 + index);
-    const bool toLower   = (character < LAST_UPPER_CASE) && (character >= FIRST_UPPER_CASE);
-    if(*(stringBuffer1 + index) != (toLower ? character + TO_LOWER_CASE : character))
-    {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void SkipWhiteSpace(const char*&      stringBuffer,
-                    const char* const stringEndBuffer)
-{
-  for(; (WHITE_SPACE >= *stringBuffer) && (stringBuffer < stringEndBuffer); ++stringBuffer)
-    ;
-}
-
-void JumpToWhiteSpace(const char*&      stringBuffer,
-                      const char* const stringEndBuffer)
-{
-  for(; (WHITE_SPACE != *stringBuffer) && (stringBuffer < stringEndBuffer); ++stringBuffer)
-    ;
-}
-
-unsigned int StringToUint(const char* const uintStr)
-{
-  return static_cast<unsigned int>(strtoul(uintStr, NULL, 10));
-}
-
-unsigned int StringToHex(const char* const uintStr)
-{
-  return static_cast<unsigned int>(strtoul(uintStr, NULL, 16));
-}
-
-float StringToFloat(const char* const floatStr)
-{
-  return static_cast<float>(strtod(floatStr, NULL));
-}
-
-void FloatToString(float value, std::string& floatStr)
-{
-  std::stringstream ss;
-  ss << value;
-  floatStr = ss.str();
-}
-
-void UintToString(unsigned int value, std::string& uIntStr)
-{
-  std::stringstream ss;
-  ss << value;
-  uIntStr = ss.str();
-}
-
-void UintColorToVector4(unsigned int color, Vector4& retColor)
-{
-  retColor.a = static_cast<float>((color & 0xFF000000) >> 24u) / 255.f;
-  retColor.r = static_cast<float>((color & 0x00FF0000) >> 16u) / 255.f;
-  retColor.g = static_cast<float>((color & 0x0000FF00) >> 8u) / 255.f;
-  retColor.b = static_cast<float>(color & 0x000000FF) / 255.f;
-}
-
-void ColorStringToVector4(const char* const colorStr, Length length, Vector4& retColor)
-{
-  if(WEB_COLOR_TOKEN == *colorStr)
-  {
-    std::string webColor(colorStr + 1u, length - 1u);
-    if(4u == length) // 3 component web color #F00 (red)
-    {
-      webColor.insert(2u, &(webColor[2]), 1u);
-      webColor.insert(1u, &(webColor[1]), 1u);
-      webColor.insert(0u, &(webColor[0]), 1u);
-      webColor.insert(0u, ALPHA_ONE);
-    }
-    else if(7u == length) // 6 component web color #FF0000 (red)
-    {
-      webColor.insert(0u, ALPHA_ONE);
-    }
-
-    UintColorToVector4(StringToHex(webColor.c_str()), retColor);
-  }
-  else if(TokenComparison(HEX_COLOR_TOKEN, colorStr, 2u))
-  {
-    UintColorToVector4(StringToHex(colorStr + 2u), retColor);
-  }
-  else if(TokenComparison(BLACK_COLOR, colorStr, length))
-  {
-    retColor = Color::BLACK;
-  }
-  else if(TokenComparison(WHITE_COLOR, colorStr, length))
-  {
-    retColor = Color::WHITE;
-  }
-  else if(TokenComparison(RED_COLOR, colorStr, length))
-  {
-    retColor = Color::RED;
-  }
-  else if(TokenComparison(GREEN_COLOR, colorStr, length))
-  {
-    retColor = Color::GREEN;
-  }
-  else if(TokenComparison(BLUE_COLOR, colorStr, length))
-  {
-    retColor = Color::BLUE;
-  }
-  else if(TokenComparison(YELLOW_COLOR, colorStr, length))
-  {
-    retColor = Color::YELLOW;
-  }
-  else if(TokenComparison(MAGENTA_COLOR, colorStr, length))
-  {
-    retColor = Color::MAGENTA;
-  }
-  else if(TokenComparison(CYAN_COLOR, colorStr, length))
-  {
-    retColor = Color::CYAN;
-  }
-  else if(TokenComparison(TRANSPARENT_COLOR, colorStr, length))
-  {
-    retColor = Color::TRANSPARENT;
-  }
-}
-
-void Vector4ToColorString(const Vector4& value, std::string& vector2Str)
-{
-  if(Color::BLACK == value)
-  {
-    vector2Str = BLACK_COLOR;
-    return;
-  }
-
-  if(Color::WHITE == value)
-  {
-    vector2Str = WHITE_COLOR;
-    return;
-  }
-
-  if(Color::RED == value)
-  {
-    vector2Str = RED_COLOR;
-    return;
-  }
-
-  if(Color::GREEN == value)
-  {
-    vector2Str = GREEN_COLOR;
-    return;
-  }
-
-  if(Color::BLUE == value)
-  {
-    vector2Str = BLUE_COLOR;
-    return;
-  }
-
-  if(Color::YELLOW == value)
-  {
-    vector2Str = YELLOW_COLOR;
-    return;
-  }
-
-  if(Color::MAGENTA == value)
-  {
-    vector2Str = MAGENTA_COLOR;
-    return;
-  }
-
-  if(Color::CYAN == value)
-  {
-    vector2Str = CYAN_COLOR;
-    return;
-  }
-
-  if(Color::TRANSPARENT == value)
-  {
-    vector2Str = TRANSPARENT_COLOR;
-    return;
-  }
-
-  const unsigned int alpha = static_cast<unsigned int>(255.f * value.a);
-  const unsigned int red   = static_cast<unsigned int>(255.f * value.r);
-  const unsigned int green = static_cast<unsigned int>(255.f * value.g);
-  const unsigned int blue  = static_cast<unsigned int>(255.f * value.b);
-
-  std::stringstream  ss;
-  const unsigned int size = 2u * sizeof(unsigned char);
-
-  ss << "0x"
-     << std::setfill('0') << std::setw(size)
-     << std::hex << alpha
-     << std::setfill('0') << std::setw(size)
-     << std::hex << red
-     << std::setfill('0') << std::setw(size)
-     << std::hex << green
-     << std::setfill('0') << std::setw(size)
-     << std::hex << blue;
-  vector2Str = ss.str();
-}
-
-void StringToVector2(const char* const vectorStr, Length length, Vector2& vector2)
-{
-  // Points to the first character of the string.
-  const char* strBuffer = vectorStr;
-
-  // Points to the first character of the 'x' value.
-  const char* const xBuffer = strBuffer;
-
-  // Jumps to the next white space.
-  JumpToWhiteSpace(strBuffer, strBuffer + length);
-
-  // Points to the first character of the 'y' value.
-  const char* const yBuffer = strBuffer;
-
-  // Converts the shadow's offset to float.
-  vector2.x = StringToFloat(xBuffer);
-  vector2.y = StringToFloat(yBuffer);
-}
-
-void Vector2ToString(const Vector2& value, std::string& vector2Str)
-{
-  FloatToString(value.x, vector2Str);
-  vector2Str += " ";
-
-  std::string yStr;
-  FloatToString(value.y, yStr);
-
-  vector2Str += yStr;
-}
-
-void UnderlineTypeStringToTypeValue(const char* const typeStr, Length length, Text::Underline::Type& retType)
-{
-  if(TokenComparison(SOLID_UNDERLINE, typeStr, length))
-  {
-    retType = Text::Underline::SOLID;
-  }
-  else if(TokenComparison(DASHED_UNDERLINE, typeStr, length))
-  {
-    retType = Text::Underline::DASHED;
-  }
-  else if(TokenComparison(DOUBLE_UNDERLINE, typeStr, length))
-  {
-    retType = Text::Underline::DOUBLE;
-  }
-}
-
-bool HorizontalAlignmentTypeStringToTypeValue(const char* const typeStr, Length length, Text::HorizontalAlignment::Type& retType)
-{
-  // The string is valid value for HorizontalAlignment
-  bool valid = false;
-  if(TokenComparison(BEGIN_HORIZONTAL_ALIGNMENT, typeStr, length))
-  {
-    retType = Text::HorizontalAlignment::BEGIN;
-    valid   = true;
-  }
-  else if(TokenComparison(CENTER_HORIZONTAL_ALIGNMENT, typeStr, length))
-  {
-    retType = Text::HorizontalAlignment::CENTER;
-    valid   = true;
-  }
-  else if(TokenComparison(END_HORIZONTAL_ALIGNMENT, typeStr, length))
-  {
-    retType = Text::HorizontalAlignment::END;
-    valid   = true;
-  }
-
-  return valid;
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.h b/dali-toolkit/internal/text/markup-processor-helper-functions.h
deleted file mode 100644 (file)
index d763318..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-definitions.h>
-#include <dali-toolkit/public-api/text/text-enumerations.h>
-
-namespace Dali
-{
-struct Vector2;
-struct Vector4;
-
-namespace Toolkit
-{
-namespace Text
-{
-/**
- * @brief Stores an attribute pair: name, value.
- */
-struct Attribute
-{
-  const char* nameBuffer;
-  const char* valueBuffer;
-  Length      nameLength;
-  Length      valueLength;
-};
-
-/**
- * @brief Stores a tag and its attributes.
- */
-struct Tag
-{
-  Vector<Attribute> attributes;
-  const char*       buffer;
-  Length            length;
-  bool              isEndTag;
-};
-
-/**
- * @brief Compare if two tokens are equal.
- *
- * @pre @p string1 must be lower case. (The html-ish constant tokens)
- * The @p stringBuffer2 parameter is transformed to lower case.
- * This function is used in the mark-up parser.
- * It has no sense to transform the constants html-ish tokens to lower case when
- * it's known they already are.
- *
- * @param[in] string1 The html-ish constant token.
- * @param[in] stringBuffer2 Pointer to the html-ish token buffer.
- * @param[in] length The length of the html-ish token.
- *
- * @return @e true if both strings are equal.
- */
-bool TokenComparison(const std::string& string1, const char* const stringBuffer2, Length length);
-
-/**
- * @brief Skips any unnecessary white space.
- *
- * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character.
- * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer.
- */
-void SkipWhiteSpace(const char*&      stringBuffer,
-                    const char* const stringEndBuffer);
-
-/**
- * @Brief Jumps to the next white space.
- *
- * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character.
- * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer.
- */
-void JumpToWhiteSpace(const char*&      stringBuffer,
-                      const char* const stringEndBuffer);
-
-/**
-* @brief Converts a string into an unsigned int.
-*
-* @param[in] uintStr An unsigned int packed inside a string.
-*
-* @return The unsigned int value.
-*/
-unsigned int StringToUint(const char* const uintStr);
-
-/**
- * @brief Converts a string into an hexadecimal unsigned int.
- *
- * @param[in] uintStr An hexadecimal unsigned int packed inside a string.
- *
- * @return The hexadecimal value.
- */
-unsigned int StringToHex(const char* const uintStr);
-
-/**
- * @brief Converts a string into a float value.
- *
- * @param[in] floatStr A float packed inside a string.
- *
- * @return The float value.
- */
-float StringToFloat(const char* const floatStr);
-
-/**
- * @brief Converts a float into a string.
- *
- * @param[in] value The float value.
- * @param[out] floatStr The string.
- */
-void FloatToString(float value, std::string& floatStr);
-
-/**
- * @brief Converts an unsigned int into a string.
- *
- * @param[in] value The unsigned int value.
- * @param[out] uIntStr The string.
- */
-void UintToString(unsigned int value, std::string& uIntStr);
-
-/**
- * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali.
- *
- * @param[in] color An ARGB color packed in an unsigned int.
- * @param[out] retColor A Vector4 with the converted color.
- */
-void UintColorToVector4(unsigned int color, Vector4& retColor);
-
-/**
- * @brief Converts a color packed inside a string into an ARGB Vector4 color.
- *
- * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values:
- * black, white, red, green, blue, yellow, magenta, cyan or transparent.
- *
- * @param[in] colorStr A color packed inside a string.
- * @param[in] length The length of the color string.
- * @param[out] retColor A color packed inside a Vector4.
- */
-void ColorStringToVector4(const char* const colorStr, Length length, Vector4& retColor);
-
-/**
- * @brief Converts a color packed in a Vector4 into a string.
- *
- * Constant colors will be converted to the strings black, white, red, green, blue, yellow, magenta, cyan or transparent.
- *
- * If is not a constant color it will be converted to a string with hexadecimal ARGB content.
- *
- * @param[in] value The color value.
- * @param[out] colorStr The string.
- */
-void Vector4ToColorString(const Vector4& value, std::string& vector2Str);
-
-/**
- * @brief Converts a two dimension vector packed inside a string into a Vector2.
- *
- * @param[in] vectorStr The two dimension vector packed inside a string.
- * @param[in] length The length of the string.
- * @param[out] vector2 The Vector2.
- */
-void StringToVector2(const char* const vectorStr, Length length, Vector2& vector2);
-
-/**
- * @brief Converts a Vector2 into a string.
- *
- * @param[in] value The vector2 value.
- * @param[out] vector2Str The string.
- */
-void Vector2ToString(const Vector2& value, std::string& vector2Str);
-
-/**
- * @brief Converts a string into its value in the enum Text::Underline::Type.
- *
- * @param[in] typeStr The underline type value packed inside a string.
- * @param[in] length The length of the string.
- * @param[out] retType The Underline type.
- */
-void UnderlineTypeStringToTypeValue(const char* const typeStr, Length length, Text::Underline::Type& retType);
-
-/**
- * @brief Converts a string into a float value.
- *
- * @param[in] floatStr A float packed inside a string.
- *
- * @return The float value.
- */
-float StringToFloat(const char* const floatStr);
-
-/**
- * @brief Converts a string into its value in the enum Text::HorizontalAlignment::Type.
- *
- * @param[in] typeStr The horizontal-alignment type value packed inside a string.
- * @param[in] length The length of the string.
- * @param[out] retType The HorizontalAlignment type.
- *
- * @return Whether the value parsed or not.
- */
-bool HorizontalAlignmentTypeStringToTypeValue(const char* const typeStr, Length length, Text::HorizontalAlignment::Type& retType);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
diff --git a/dali-toolkit/internal/text/markup-processor-paragraph.cpp b/dali-toolkit/internal/text/markup-processor-paragraph.cpp
deleted file mode 100644 (file)
index e470bec..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-paragraph.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
-{
-  boundedParagraphRun.horizontalAlignmentDefined = HorizontalAlignmentTypeStringToTypeValue(attribute.valueBuffer,
-                                                                                            attribute.valueLength,
-                                                                                            boundedParagraphRun.horizontalAlignment);
-}
-
-void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
-{
-  boundedParagraphRun.relativeLineSize        = StringToFloat(attribute.valueBuffer);
-  boundedParagraphRun.relativeLineSizeDefined = true;
-}
-
-void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun)
-{
-  // By default the align attribute is not defined until it's parsed.
-  boundedParagraphRun.horizontalAlignmentDefined = false;
-
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-    if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::ALIGN, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessHorizontalAlignment(attribute, boundedParagraphRun);
-    }
-    else if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::RELATIVE_LINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessRelativeLineHeight(attribute, boundedParagraphRun);
-    }
-  }
-}
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-paragraph.h b/dali-toolkit/internal/text/markup-processor-paragraph.h
deleted file mode 100644 (file)
index 2859794..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-struct BoundedParagraphRun;
-
-/**
- * @brief Retrieves the horizontal alignment value from the tag and sets it to the bounded paragraph run.
- *
- * @param[in] attribute the horizontal alignment attribute.
- * @param[in,out] boundedParagraphRun The bounded paragraph run.
- */
-void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
-
-/**
- * @brief Retrieves the paragraph value from the tag and sets it to the bounded paragraph run.
- *
- * @param[in] tag The paragraph tag and its attributes.
- * @param[in,out] boundedParagraphRun The bounded paragraph run.
- */
-void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun);
-
-/**
- * @brief Retrieves the relative line height value from the paragraph tag and sets it to the bounded paragraph run.
- *
- * @param[in] attribute the relative line height attribute.
- * @param[in,out] boundedParagraphRun The bounded paragraph run.
- */
-void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
diff --git a/dali-toolkit/internal/text/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor-span.cpp
deleted file mode 100644 (file)
index 3e20c6f..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-color.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/color-run.h>
-#include <dali-toolkit/internal/text/font-description-run.h>
-#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
-#include <dali-toolkit/internal/text/markup-processor-font.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
-#include <dali-toolkit/internal/text/markup-processor-underline.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessSpanTag(const Tag&                    tag,
-                    ColorRun&                     colorRun,
-                    FontDescriptionRun&           fontRun,
-                    UnderlinedCharacterRun&       underlinedCharacterRun,
-                    ColorRun&                     backgroundColorRun,
-                    StrikethroughCharacterRun&    strikethroughRun,
-                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
-                    bool&                         isColorDefined,
-                    bool&                         isFontDefined,
-                    bool&                         isUnderlinedCharacterDefined,
-                    bool&                         isBackgroundColorDefined,
-                    bool&                         isStrikethroughDefined,
-                    bool&                         isCharacterSpacingDefined)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-
-    if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::TEXT_COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      isColorDefined = true;
-      ProcessColor(attribute, colorRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::BACKGROUND_COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      isBackgroundColorDefined = true;
-      ProcessColor(attribute, backgroundColorRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_FAMILY, attribute.nameBuffer, attribute.nameLength))
-    {
-      isFontDefined = true;
-      ProcessFontFamily(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SIZE, attribute.nameBuffer, attribute.nameLength))
-    {
-      isFontDefined = true;
-      ProcessFontSize(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      isFontDefined = true;
-      ProcessFontWeight(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WIDTH, attribute.nameBuffer, attribute.nameLength))
-    {
-      isFontDefined = true;
-      ProcessFontWidth(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SLANT, attribute.nameBuffer, attribute.nameLength))
-    {
-      isFontDefined = true;
-      ProcessFontSlant(attribute, fontRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      isUnderlinedCharacterDefined = true;
-      ProcessColorAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      isUnderlinedCharacterDefined = true;
-      ProcessHeightAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_TYPE, attribute.nameBuffer, attribute.nameLength))
-    {
-      isUnderlinedCharacterDefined = true;
-      ProcessTypeAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_GAP, attribute.nameBuffer, attribute.nameLength))
-    {
-      isUnderlinedCharacterDefined = true;
-      ProcessDashGapAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
-    {
-      isUnderlinedCharacterDefined = true;
-      ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      isStrikethroughDefined = true;
-      ProcessColorAttribute(attribute, strikethroughRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      isStrikethroughDefined = true;
-      ProcessHeightAttribute(attribute, strikethroughRun);
-    }
-    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::CHARACTER_SPACING_VALUE, attribute.nameBuffer, attribute.nameLength))
-    {
-      isCharacterSpacingDefined = true;
-      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor-span.h
deleted file mode 100644 (file)
index 5630fd3..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct MarkupProcessData;
-
-/**
- * @brief process the span from the tag and process all styles in it.
- *
- * @param[in] tag The span tag and its attributes.
- * @param[out] colorRun the color run to be filled.
- * @param[out] fontRun the font run to be filled.
- * @param[out] underlinedCharacterRun the underlined character run to be filled.
- * @param[out] backgroundColorRun the background color run to be filled.
- * @param[out] strikethroughRun the strikethrough run to be filled.
- * @param[out] characterSpacingCharacterRun the character-spacing run to be filled.
- * @param[out] isColorDefined if the span has color defined.
- * @param[out] isFontDefined if the span has font defined.
- * @param[out] isUnderlinedCharacterDefined if the span has underlined-character defined.
- * @param[out] isBackgroundColorDefined if the span has background color defined.
- * @param[out] isStrikethroughDefined if the span has strikethrough defined.
- * @param[out] isCharacterSpacingDefined if the span has character-spacing defined.
- */
-void ProcessSpanTag(const Tag&                    tag,
-                    ColorRun&                     colorRun,
-                    FontDescriptionRun&           fontRun,
-                    UnderlinedCharacterRun&       underlinedCharacterRun,
-                    ColorRun&                     backgroundColorRun,
-                    StrikethroughCharacterRun&    strikethroughRun,
-                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
-                    bool&                         isColorDefined,
-                    bool&                         isFontDefined,
-                    bool&                         isUnderlinedCharacterDefined,
-                    bool&                         isBackgroundColorDefined,
-                    bool&                         isStrikethroughDefined,
-                    bool&                         isCharacterSpacingDefined);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
diff --git a/dali-toolkit/internal/text/markup-processor-strikethrough.cpp b/dali-toolkit/internal/text/markup-processor-strikethrough.cpp
deleted file mode 100644 (file)
index 10e104c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-#include <dali-toolkit/internal/text/strikethrough-character-run.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void ProcessColorAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun)
-
-{
-  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, strikethroughRun.properties.color);
-  strikethroughRun.properties.colorDefined = true;
-}
-
-void ProcessHeightAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun)
-{
-  strikethroughRun.properties.height        = ProcessFloatAttribute(attribute);
-  strikethroughRun.properties.heightDefined = true;
-}
-
-void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& strikethroughRun)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-
-    if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessColorAttribute(attribute, strikethroughRun);
-    }
-    else if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessHeightAttribute(attribute, strikethroughRun);
-    }
-  }
-}
-
-void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns)
-{
-  // Handle nested tags
-  // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
-  // Example:
-  // <s height='5.0f' color='blue'> outer tag before  <s color='green'> inner tag </s> outer tag after </s>
-  // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
-  // "inner tag" has height = 5.0f and color = 'green'
-
-  if(strikethroughCharacterRuns.Count() > 0u)
-  {
-    Vector<StrikethroughCharacterRun>::ConstIterator preIt = strikethroughCharacterRuns.Begin();
-
-    Vector<StrikethroughCharacterRun>::Iterator      it    = strikethroughCharacterRuns.Begin() + 1;
-    Vector<StrikethroughCharacterRun>::ConstIterator endIt = strikethroughCharacterRuns.End();
-
-    while(it != endIt)
-    {
-      const StrikethroughCharacterRun& run                = *it;
-      const CharacterIndex&            characterIndex     = run.characterRun.characterIndex;
-      const Length&                    numberOfCharacters = run.characterRun.numberOfCharacters;
-
-      const StrikethroughCharacterRun& preRun                = *preIt;
-      const CharacterIndex&            preCharacterIndex     = preRun.characterRun.characterIndex;
-      const Length&                    preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
-
-      if((preCharacterIndex <= characterIndex) &&
-         ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
-      {
-        it->properties.CopyIfNotDefined(preIt->properties);
-      }
-
-      it++;
-      preIt++;
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-strikethrough.h b/dali-toolkit/internal/text/markup-processor-strikethrough.h
deleted file mode 100644 (file)
index fca6d34..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/strikethrough-character-run.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-struct StrikethroughCharacterRun;
-
-/**
- * @brief Fill the strikethrough character run with the color attribute value.
- *
- * @param[in] attribute the color attribute.
- * @param[out] strikethroughCharacterRun The strikethrough character run
- */
-void ProcessColorAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughCharacterRun);
-
-/**
- * @brief Fill the strikethrough character run with the height attribute value.
- *
- * @param[in] attribute the height attribute.
- * @param[out] strikethroughRun The strikethrough character run
- */
-void ProcessHeightAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun);
-
-/**
- * @brief Retrieves the strikethrough run info from the tag and sets it to the strikethrough run.
- *
- * @param[in] tag The strikethrough tag and its attributes.
- * @param[in,out] strikethroughRun The strikethrough run.
- */
-void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& strikethroughRun);
-
-/**
- * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
- *
- * @param[in,out] strikethroughCharacterRun The list of strikethrough character run
- */
-void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRun);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
diff --git a/dali-toolkit/internal/text/markup-processor-underline.cpp b/dali-toolkit/internal/text/markup-processor-underline.cpp
deleted file mode 100644 (file)
index 08b9f1e..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor-underline.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-#include <dali-toolkit/internal/text/text-effects-style.h>
-#include <dali-toolkit/internal/text/underlined-character-run.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-const unsigned int MAX_TYPE_ATTRIBUTE_SIZE = 7u; ///< The maximum length of any of the possible 'type' values.
-
-} // namespace
-
-void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  underlinedCharacterRun.properties.typeDefined = ProcessEnumerationAttribute<Text::Underline::Type>(attribute,
-                                                                                                     MAX_TYPE_ATTRIBUTE_SIZE,
-                                                                                                     &StringToUnderlineType,
-                                                                                                     underlinedCharacterRun.properties.type);
-}
-
-void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  underlinedCharacterRun.properties.dashGap        = ProcessFloatAttribute(attribute);
-  underlinedCharacterRun.properties.dashGapDefined = true;
-}
-
-void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  underlinedCharacterRun.properties.dashWidth        = ProcessFloatAttribute(attribute);
-  underlinedCharacterRun.properties.dashWidthDefined = true;
-}
-void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  underlinedCharacterRun.properties.height        = ProcessFloatAttribute(attribute);
-  underlinedCharacterRun.properties.heightDefined = true;
-}
-
-void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, underlinedCharacterRun.properties.color);
-  underlinedCharacterRun.properties.colorDefined = true;
-}
-
-void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
-                                       endIt = tag.attributes.End();
-      it != endIt;
-      ++it)
-  {
-    const Attribute& attribute(*it);
-
-    if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessColorAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessHeightAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::TYPE, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessTypeAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_GAP, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessDashGapAttribute(attribute, underlinedCharacterRun);
-    }
-    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
-    {
-      ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
-    }
-  }
-}
-
-void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
-{
-  // Handle nested tags
-  // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
-  // Example:
-  // <u height='5.0f' color='blue'> outer tag before  <u color='green'> inner tag </u> outer tag after </u>
-  // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
-  // "inner tag" has height = 5.0f and color = 'green'
-
-  if(underlinedCharacterRuns.Count() > 0u)
-  {
-    Vector<UnderlinedCharacterRun>::ConstIterator preIt = underlinedCharacterRuns.Begin();
-
-    Vector<UnderlinedCharacterRun>::Iterator      it    = underlinedCharacterRuns.Begin() + 1;
-    Vector<UnderlinedCharacterRun>::ConstIterator endIt = underlinedCharacterRuns.End();
-
-    while(it != endIt)
-    {
-      const UnderlinedCharacterRun& run                = *it;
-      const CharacterIndex&         characterIndex     = run.characterRun.characterIndex;
-      const Length&                 numberOfCharacters = run.characterRun.numberOfCharacters;
-
-      const UnderlinedCharacterRun& preRun                = *preIt;
-      const CharacterIndex&         preCharacterIndex     = preRun.characterRun.characterIndex;
-      const Length&                 preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
-
-      if((preCharacterIndex <= characterIndex) &&
-         ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
-      {
-        it->properties.CopyIfNotDefined(preIt->properties);
-      }
-
-      it++;
-      preIt++;
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-underline.h b/dali-toolkit/internal/text/markup-processor-underline.h
deleted file mode 100644 (file)
index cde347c..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/underlined-character-run.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Tag;
-struct Attribute;
-
-/**
- * @brief Fill the underlined character run with the type attribute value.
- *
- * @param[in] attribute the type attribute.
- * @param[out] underlinedCharacterRun The underlined character run
- */
-void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Fill the underlined character run with the dash-gap attribute value.
- *
- * @param[in] attribute the dash-gap attribute.
- * @param[out] underlinedCharacterRun The underlined character run
- */
-void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Fill the underlined character run with the dash-width attribute value.
- *
- * @param[in] attribute the dash-width attribute.
- * @param[out] underlinedCharacterRun The underlined character run
- */
-void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Fill the underlined character run with the height attribute value.
- *
- * @param[in] attribute the height attribute.
- * @param[out] underlinedCharacterRun The underlined character run
- */
-void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Fill the underlined character run with the color attribute value.
- *
- * @param[in] attribute the color attribute.
- * @param[out] underlinedCharacterRun The underlined character run
- */
-void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Retrieves the underline run info from the tag and sets it to the underline run.
- *
- * @param[in] tag The underline tag and its attributes.
- * @param[in,out] underlinedCharacterRun The underlined character run
- */
-void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun);
-
-/**
- * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
- *
- * @param[in,out] underlinedCharacterRuns The list of underlined character run
- */
-void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp
deleted file mode 100644 (file)
index 344cde1..0000000
+++ /dev/null
@@ -1,1232 +0,0 @@
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// FILE HEADER
-#include <dali-toolkit/internal/text/markup-processor.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-#include <climits> // for ULONG_MAX
-#include <functional>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/markup-processor-anchor.h>
-#include <dali-toolkit/internal/text/markup-processor-background.h>
-#include <dali-toolkit/internal/text/markup-processor-character-spacing.h>
-#include <dali-toolkit/internal/text/markup-processor-color.h>
-#include <dali-toolkit/internal/text/markup-processor-embedded-item.h>
-#include <dali-toolkit/internal/text/markup-processor-font.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
-#include <dali-toolkit/internal/text/markup-processor-paragraph.h>
-#include <dali-toolkit/internal/text/markup-processor-span.h>
-#include <dali-toolkit/internal/text/markup-processor-strikethrough.h>
-#include <dali-toolkit/internal/text/markup-processor-underline.h>
-#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
-#include <dali-toolkit/internal/text/xhtml-entities.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-const char LESS_THAN      = '<';
-const char GREATER_THAN   = '>';
-const char EQUAL          = '=';
-const char QUOTATION_MARK = '\'';
-const char SLASH          = '/';
-const char BACK_SLASH     = '\\';
-const char AMPERSAND      = '&';
-const char HASH           = '#';
-const char SEMI_COLON     = ';';
-const char CHAR_ARRAY_END = '\0';
-const char HEX_CODE       = 'x';
-
-const char WHITE_SPACE = 0x20; // ASCII value of the white space.
-const char NEW_LINE    = 0x0A; // ASCII value of the newline.
-
-// Range 1 0x0u < XHTML_DECIMAL_ENTITY_RANGE <= 0xD7FFu
-// Range 2 0xE000u < XHTML_DECIMAL_ENTITY_RANGE <= 0xFFFDu
-// Range 3 0x10000u < XHTML_DECIMAL_ENTITY_RANGE <= 0x10FFFFu
-const unsigned long XHTML_DECIMAL_ENTITY_RANGE[] = {0x0u, 0xD7FFu, 0xE000u, 0xFFFDu, 0x10000u, 0x10FFFFu};
-
-// The MAX_NUM_OF_ATTRIBUTES is the number of attributes in span tag "markup-processor-span.cpp". Because it contains the maximum number of attributes in  all tags.
-const unsigned int MAX_NUM_OF_ATTRIBUTES = 14u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color', 's-height' and 'char-space-value' attrubutes.
-const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
-
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MARKUP_PROCESSOR");
-#endif
-
-typedef VectorBase::SizeType RunIndex;
-
-/**
- * @brief Struct used to retrieve the style runs from the mark-up string.
- */
-template<typename StyleStackType>
-struct StyleStack
-{
-  Vector<StyleStackType> stack;    ///< Use a vector as a style stack.
-  unsigned int           topIndex; ///< Points the top of the stack.
-
-  StyleStack()
-  : stack(),
-    topIndex(0u)
-  {
-    stack.Resize(DEFAULT_VECTOR_SIZE);
-  }
-
-  void Push(StyleStackType item)
-  {
-    // Check if there is space inside the style stack.
-    const VectorBase::SizeType size = stack.Count();
-    if(topIndex >= size)
-    {
-      // Resize the style stack.
-      stack.Resize(2u * size);
-    }
-
-    // Set the item in the top of the stack.
-    *(stack.Begin() + topIndex) = item;
-
-    // Reposition the pointer to the top of the stack.
-    ++topIndex;
-  }
-
-  StyleStackType Pop()
-  {
-    // Pop the top of the stack.
-    --topIndex;
-    return *(stack.Begin() + topIndex);
-  }
-};
-
-/**
- * @brief Struct used to retrieve spans from the mark-up string.
- */
-struct Span
-{
-  RunIndex colorRunIndex;
-  RunIndex fontRunIndex;
-  RunIndex underlinedCharacterRunIndex;
-  RunIndex backgroundColorRunIndex;
-  RunIndex strikethroughCharacterRunIndex;
-  RunIndex characterSpacingCharacterRunIndex;
-
-  bool isColorDefined;
-  bool isFontDefined;
-  bool isUnderlinedCharacterDefined;
-  bool isBackgroundColorDefined;
-  bool isStrikethroughDefined;
-  bool isCharacterSpacingDefined;
-};
-
-/**
- * @brief Initializes a font run description to its defaults.
- *
- * @param[in,out] fontRun The font description run to initialize.
- */
-void Initialize(FontDescriptionRun& fontRun)
-{
-  fontRun.characterRun.characterIndex     = 0u;
-  fontRun.characterRun.numberOfCharacters = 0u;
-  fontRun.familyName                      = NULL;
-  fontRun.familyLength                    = 0u;
-  fontRun.weight                          = TextAbstraction::FontWeight::NORMAL;
-  fontRun.width                           = TextAbstraction::FontWidth::NORMAL;
-  fontRun.slant                           = TextAbstraction::FontSlant::NORMAL;
-  fontRun.size                            = 0u;
-  fontRun.familyDefined                   = false;
-  fontRun.weightDefined                   = false;
-  fontRun.widthDefined                    = false;
-  fontRun.slantDefined                    = false;
-  fontRun.sizeDefined                     = false;
-}
-
-/**
- * @brief Initializes a color run description to its defaults.
- *
- * @param[in,out] colorRun The font description run to initialize.
- */
-void Initialize(ColorRun& colorRun)
-{
-  colorRun.characterRun.characterIndex     = 0u;
-  colorRun.characterRun.numberOfCharacters = 0u;
-}
-
-/**
- * @brief Initializes a underlined character run to its defaults.
- *
- * @param[in,out] underlinedCharacterRun The underelined character run to initialize.
- */
-void Initialize(UnderlinedCharacterRun& underlinedCharacterRun)
-{
-  underlinedCharacterRun.characterRun.characterIndex     = 0u;
-  underlinedCharacterRun.characterRun.numberOfCharacters = 0u;
-}
-
-/**
- * @brief Initializes a span to its defaults.
- *
- * @param[in,out] span The span to be initialized.
- */
-void Initialize(Span& span)
-{
-  span.colorRunIndex  = 0u;
-  span.isColorDefined = false;
-
-  span.fontRunIndex  = 0u;
-  span.isFontDefined = false;
-
-  span.underlinedCharacterRunIndex  = 0u;
-  span.isUnderlinedCharacterDefined = false;
-  span.backgroundColorRunIndex      = 0u;
-  span.isBackgroundColorDefined     = false;
-
-  //strikethrough
-  span.strikethroughCharacterRunIndex = 0u;
-  span.isStrikethroughDefined         = false;
-
-  //characterSpacing
-  span.characterSpacingCharacterRunIndex = 0u;
-  span.isCharacterSpacingDefined         = false;
-}
-
-/**
- * @brief Initializes a strikethrough character run to its defaults.
- *
- * @param[in,out] strikethroughCharacterRun The strikethrough character run to initialize.
- */
-void Initialize(StrikethroughCharacterRun& strikethroughCharacterRun)
-{
-  strikethroughCharacterRun.characterRun.characterIndex     = 0u;
-  strikethroughCharacterRun.characterRun.numberOfCharacters = 0u;
-  strikethroughCharacterRun.properties.colorDefined         = false;
-}
-
-/**
- * @brief Initializes a  bounded-paragraph character run to its defaults.
- *
- * @param[in,out] boundedParagraphRun The bounded paragraphRun run to initialize.
- */
-void Initialize(BoundedParagraphRun& boundedParagraphRun)
-{
-  boundedParagraphRun.characterRun.characterIndex     = 0u;
-  boundedParagraphRun.characterRun.numberOfCharacters = 0u;
-}
-
-/**
- * @brief Initializes a character-spacing run to its defaults.
- *
- * @param[in,out] characterSpacingCharacterRun The character-spacing run to initialize.
- */
-void Initialize(CharacterSpacingCharacterRun& characterSpacingCharacterRun)
-{
-  characterSpacingCharacterRun.characterRun.characterIndex     = 0u;
-  characterSpacingCharacterRun.characterRun.numberOfCharacters = 0u;
-  characterSpacingCharacterRun.value                           = 0.0f;
-}
-
-/**
- * @brief Splits the tag string into the tag name and its attributes.
- *
- * The attributes are stored in a vector in the tag.
- *
- * @param[in,out] tag The tag.
- */
-void ParseAttributes(Tag& tag)
-{
-  if(tag.buffer == NULL)
-  {
-    return;
-  }
-
-  tag.attributes.Resize(MAX_NUM_OF_ATTRIBUTES);
-
-  // Find first the tag name.
-  bool isQuotationOpen = false;
-
-  const char*       tagBuffer    = tag.buffer;
-  const char* const tagEndBuffer = tagBuffer + tag.length;
-  tag.length                     = 0u;
-  for(; tagBuffer < tagEndBuffer; ++tagBuffer)
-  {
-    const char character = *tagBuffer;
-    if(WHITE_SPACE < character)
-    {
-      ++tag.length;
-    }
-    else
-    {
-      // Stops counting the length of the tag when a white space is found.
-      // @note a white space is the WHITE_SPACE character and anything below as 'tab', 'return' or 'control characters'.
-      break;
-    }
-  }
-  SkipWhiteSpace(tagBuffer, tagEndBuffer);
-
-  // Find the attributes.
-  unsigned int attributeIndex = 0u;
-  const char*  nameBuffer     = NULL;
-  const char*  valueBuffer    = NULL;
-  Length       nameLength     = 0u;
-  Length       valueLength    = 0u;
-
-  bool   addToNameValue     = true;
-  Length numberOfWhiteSpace = 0u;
-  for(; tagBuffer < tagEndBuffer; ++tagBuffer)
-  {
-    const char character = *tagBuffer;
-    if((WHITE_SPACE >= character) && !isQuotationOpen)
-    {
-      if(NULL != valueBuffer)
-      {
-        // Remove white spaces at the end of the value.
-        valueLength -= numberOfWhiteSpace;
-      }
-
-      if((NULL != nameBuffer) && (NULL != valueBuffer))
-      {
-        // Every time a white space is found, a new attribute is created and stored in the attributes vector.
-        Attribute& attribute = *(tag.attributes.Begin() + attributeIndex);
-        ++attributeIndex;
-
-        attribute.nameBuffer  = nameBuffer;
-        attribute.valueBuffer = valueBuffer;
-        attribute.nameLength  = nameLength;
-        attribute.valueLength = valueLength;
-
-        nameBuffer  = NULL;
-        valueBuffer = NULL;
-        nameLength  = 0u;
-        valueLength = 0u;
-
-        addToNameValue = true; // next read characters will be added to the name.
-      }
-    }
-    else if(EQUAL == character) // '='
-    {
-      addToNameValue = false; // next read characters will be added to the value.
-      SkipWhiteSpace(tagBuffer, tagEndBuffer);
-    }
-    else if(QUOTATION_MARK == character) // '\''
-    {
-      // Do not add quotation marks to neither name nor value.
-      isQuotationOpen = !isQuotationOpen;
-
-      if(isQuotationOpen)
-      {
-        ++tagBuffer;
-        SkipWhiteSpace(tagBuffer, tagEndBuffer);
-        --tagBuffer;
-      }
-    }
-    else
-    {
-      // Adds characters to the name or the value.
-      if(addToNameValue)
-      {
-        if(NULL == nameBuffer)
-        {
-          nameBuffer = tagBuffer;
-        }
-        ++nameLength;
-      }
-      else
-      {
-        if(isQuotationOpen)
-        {
-          if(WHITE_SPACE >= character)
-          {
-            ++numberOfWhiteSpace;
-          }
-          else
-          {
-            numberOfWhiteSpace = 0u;
-          }
-        }
-        if(NULL == valueBuffer)
-        {
-          valueBuffer = tagBuffer;
-        }
-        ++valueLength;
-      }
-    }
-  }
-
-  if(NULL != valueBuffer)
-  {
-    // Remove white spaces at the end of the value.
-    valueLength -= numberOfWhiteSpace;
-  }
-
-  if((NULL != nameBuffer) && (NULL != valueBuffer))
-  {
-    // Checks if the last attribute needs to be added.
-    Attribute& attribute = *(tag.attributes.Begin() + attributeIndex);
-    ++attributeIndex;
-
-    attribute.nameBuffer  = nameBuffer;
-    attribute.valueBuffer = valueBuffer;
-    attribute.nameLength  = nameLength;
-    attribute.valueLength = valueLength;
-  }
-
-  // Resize the vector of attributes.
-  tag.attributes.Resize(attributeIndex);
-}
-
-/**
- * @brief It parses a tag and its attributes if the given iterator @e it is pointing at a tag beginning.
- *
- * @param[in,out] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
- * @param[in] markupStringEndBuffer Pointer to one character after the end of the mark-up string buffer.
- * @param[out] tag The tag with its attributes.
- *
- * @return @e true if the iterator @e it is pointing a mark-up tag. Otherwise @e false.
- */
-bool IsTag(const char*&      markupStringBuffer,
-           const char* const markupStringEndBuffer,
-           Tag&              tag)
-{
-  bool isTag              = false;
-  bool isQuotationOpen    = false;
-  bool attributesFound    = false;
-  tag.isEndTag            = false;
-  bool isPreviousLessThan = false;
-  bool isPreviousSlash    = false;
-
-  const char character = *markupStringBuffer;
-  if(LESS_THAN == character) // '<'
-  {
-    tag.buffer         = NULL;
-    tag.length         = 0u;
-    isPreviousLessThan = true;
-
-    // if the iterator is pointing to a '<' character, then check if it's a mark-up tag is needed.
-    ++markupStringBuffer;
-    if(markupStringBuffer < markupStringEndBuffer)
-    {
-      SkipWhiteSpace(markupStringBuffer, markupStringEndBuffer);
-
-      for(; (!isTag) && (markupStringBuffer < markupStringEndBuffer); ++markupStringBuffer)
-      {
-        const char character = *markupStringBuffer;
-
-        if(!isQuotationOpen && (SLASH == character)) // '/'
-        {
-          if(isPreviousLessThan)
-          {
-            tag.isEndTag = true;
-          }
-          else
-          {
-            // if the tag has a '/' it may be an end tag.
-            isPreviousSlash = true;
-          }
-
-          isPreviousLessThan = false;
-          if((markupStringBuffer + 1u < markupStringEndBuffer) && (WHITE_SPACE >= *(markupStringBuffer + 1u)))
-          {
-            ++markupStringBuffer;
-            SkipWhiteSpace(markupStringBuffer, markupStringEndBuffer);
-            --markupStringBuffer;
-          }
-        }
-        else if(GREATER_THAN == character) // '>'
-        {
-          isTag = true;
-          if(isPreviousSlash)
-          {
-            tag.isEndTag = true;
-          }
-
-          isPreviousSlash    = false;
-          isPreviousLessThan = false;
-        }
-        else if(QUOTATION_MARK == character)
-        {
-          isQuotationOpen = !isQuotationOpen;
-          ++tag.length;
-
-          isPreviousSlash    = false;
-          isPreviousLessThan = false;
-        }
-        else if(WHITE_SPACE >= character) // ' '
-        {
-          // If the tag contains white spaces then it may have attributes.
-          if(!isQuotationOpen)
-          {
-            attributesFound = true;
-          }
-          ++tag.length;
-        }
-        else
-        {
-          if(NULL == tag.buffer)
-          {
-            tag.buffer = markupStringBuffer;
-          }
-
-          // If it's not any of the 'special' characters then just add it to the tag string.
-          ++tag.length;
-
-          isPreviousSlash    = false;
-          isPreviousLessThan = false;
-        }
-      }
-    }
-
-    // If the tag string has white spaces, then parse the attributes is needed.
-    if(attributesFound)
-    {
-      ParseAttributes(tag);
-    }
-  }
-
-  return isTag;
-}
-
-/**
- * @brief Returns length of XHTML entity by parsing the text. It also determines if it is XHTML entity or not.
- *
- * @param[in] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
- * @param[in] markupStringEndBuffer Pointing to end of mark-up string buffer.
- *
- * @return Length of markupText in case of XHTML entity otherwise return 0.
- */
-unsigned int GetXHTMLEntityLength(const char*&      markupStringBuffer,
-                                  const char* const markupStringEndBuffer)
-{
-  char character = *markupStringBuffer;
-  if(AMPERSAND == character) // '&'
-  {
-    // if the iterator is pointing to a '&' character, then check for ';' to find end to XHTML entity.
-    ++markupStringBuffer;
-    if(markupStringBuffer < markupStringEndBuffer)
-    {
-      unsigned int len = 1u;
-      for(; markupStringBuffer < markupStringEndBuffer; ++markupStringBuffer)
-      {
-        character = *markupStringBuffer;
-        ++len;
-        if(SEMI_COLON == character) // ';'
-        {
-          // found end of XHTML entity
-          ++markupStringBuffer;
-          return len;
-        }
-        else if((AMPERSAND == character) || (BACK_SLASH == character) || (LESS_THAN == character))
-        {
-          return 0;
-        }
-      }
-    }
-  }
-  return 0;
-}
-
-/**
- * @brief It parses a XHTML string which has hex/decimal entity and fill its corresponging utf-8 string.
- *
- * @param[in] markupText The mark-up text buffer.
- * @param[out] utf-8 text Corresponding to markup Text
- *
- * @return true if string is successfully parsed otherwise false
- */
-bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8)
-{
-  bool result = false;
-
-  if(NULL != markupText)
-  {
-    bool isHex = false;
-
-    // check if hex or decimal entity
-    if((CHAR_ARRAY_END != *markupText) && (HEX_CODE == *markupText))
-    {
-      isHex = true;
-      ++markupText;
-    }
-
-    char*         end = NULL;
-    unsigned long l   = strtoul(markupText, &end, (isHex ? 16 : 10)); // l contains UTF-32 code in case of correct XHTML entity
-
-    // check for valid XHTML numeric entities (between '#' or "#x" and ';')
-    if((l > 0) && (l < ULONG_MAX) && (*end == SEMI_COLON)) // in case wrong XHTML entity is set eg. "&#23abcdefs;" in that case *end will be 'a'
-    {
-      /* characters XML 1.1 permits */
-      if(((XHTML_DECIMAL_ENTITY_RANGE[0] < l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[1])) ||
-         ((XHTML_DECIMAL_ENTITY_RANGE[2] <= l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[3])) ||
-         ((XHTML_DECIMAL_ENTITY_RANGE[4] <= l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[5])))
-      {
-        // Convert UTF32 code to UTF8
-        Utf32ToUtf8(reinterpret_cast<const uint32_t* const>(&l), 1, reinterpret_cast<uint8_t*>(utf8));
-        result = true;
-      }
-    }
-  }
-  return result;
-}
-
-/**
- * @brief Processes a particular tag for the required run (color-run, font-run or underlined-character-run).
- *
- * @tparam RunType Whether ColorRun , FontDescriptionRun or UnderlinedCharacterRun
- *
- * @param[in/out] runsContainer The container containing all the runs
- * @param[in/out] styleStack The style stack
- * @param[in] tag The tag we are currently processing
- * @param[in] characterIndex The current character index
- * @param[in/out] runIndex The run index
- * @param[in/out] tagReference The tagReference we should increment/decrement
- * @param[in] parameterSettingFunction This function will be called to set run specific parameters
- */
-template<typename RunType>
-void ProcessTagForRun(
-  Vector<RunType>&                          runsContainer,
-  StyleStack<RunIndex>&                     styleStack,
-  const Tag&                                tag,
-  const CharacterIndex                      characterIndex,
-  RunIndex&                                 runIndex,
-  int&                                      tagReference,
-  std::function<void(const Tag&, RunType&)> parameterSettingFunction)
-{
-  if(!tag.isEndTag)
-  {
-    // Create a new run.
-    RunType run;
-    Initialize(run);
-
-    // Fill the run with the parameters.
-    run.characterRun.characterIndex = characterIndex;
-    parameterSettingFunction(tag, run);
-
-    // Push the run in the logical model.
-    runsContainer.PushBack(run);
-
-    // Push the index of the run into the stack.
-    styleStack.Push(runIndex);
-
-    // Point the next free run.
-    ++runIndex;
-
-    // Increase reference
-    ++tagReference;
-  }
-  else
-  {
-    if(tagReference > 0)
-    {
-      // Pop the top of the stack and set the number of characters of the run.
-      RunType& run                        = *(runsContainer.Begin() + styleStack.Pop());
-      run.characterRun.numberOfCharacters = characterIndex - run.characterRun.characterIndex;
-      --tagReference;
-    }
-  }
-}
-
-/**
- * @brief Processes the item tag
- *
- * @param[in/out] markupProcessData The markup process data
- * @param[in] tag The current tag
- * @param[in/out] characterIndex The current character index
- */
-void ProcessItemTag(
-  MarkupProcessData& markupProcessData,
-  const Tag          tag,
-  CharacterIndex&    characterIndex)
-{
-  if(tag.isEndTag)
-  {
-    // Create an embedded item instance.
-    EmbeddedItem item;
-    item.characterIndex = characterIndex;
-    ProcessEmbeddedItem(tag, item);
-
-    markupProcessData.items.PushBack(item);
-
-    // Insert white space character that will be replaced by the item.
-    markupProcessData.markupProcessedText.append(1u, WHITE_SPACE);
-    ++characterIndex;
-  }
-}
-
-/**
- * @brief Processes the paragraph-tag
- *
- * @param[in/out] markupProcessData The markup process data
- * @param[in] tag The current tag
- * @param[in] isEndBuffer Whether the end of buffer
- * @param[in/out] characterIndex The current character index
- */
-void ProcessParagraphTag(
-  MarkupProcessData& markupProcessData,
-  const Tag          tag,
-  bool               isEndBuffer,
-  CharacterIndex&    characterIndex)
-{
-  if((characterIndex > 0 &&
-      markupProcessData.markupProcessedText[characterIndex - 1u] != NEW_LINE) &&
-     (!(tag.isEndTag && isEndBuffer)))
-  {
-    // Insert new-line character at the start and end of paragraph.
-    markupProcessData.markupProcessedText.append(1u, NEW_LINE);
-    ++characterIndex;
-  }
-}
-
-/**
- * @brief Processes the anchor tag
- *
- * @param[in/out] markupProcessData The markup process data
- * @param[in] tag The current tag
- * @param[in/out] characterIndex The current character index
- */
-void ProcessAnchorTag(
-  MarkupProcessData& markupProcessData,
-  const Tag          tag,
-  CharacterIndex&    characterIndex)
-{
-  if(!tag.isEndTag)
-  {
-    // Create an anchor instance.
-    Anchor anchor;
-    anchor.startIndex = characterIndex;
-    anchor.endIndex   = 0u;
-    ProcessAnchor(tag, anchor);
-    markupProcessData.anchors.PushBack(anchor);
-  }
-  else
-  {
-    // Update end index.
-    unsigned int count = markupProcessData.anchors.Count();
-    if(count > 0)
-    {
-      markupProcessData.anchors[count - 1].endIndex = characterIndex;
-    }
-  }
-}
-
-/**
- * @brief Processes span tag for the color-run & font-run.
- *
- * @param[in] spanTag The tag we are currently processing
- * @param[inout] spanStack The spans stack
- * @param[inout] colorRuns The container containing all the color runs
- * @param[inout] fontRuns The container containing all the font description runs
- * @param[inout] underlinedCharacterRuns The container containing all the underlined character runs
- * @param[inout] strikethroughCharacterRuns The container containing all the strikethroughed character runs
- * @param[inout] colorRunIndex The color run index
- * @param[inout] fontRunIndex The font run index
- * @param[inout] underlinedCharacterRunIndex The underlined character run index
- * @param[inout] strikethroughCharacterRunIndex The strikethroughed character run index
- * @param[in] characterIndex The current character index
- * @param[in] tagReference The tagReference we should increment/decrement
- */
-void ProcessSpanForRun(
-  const Tag&                            spanTag,
-  StyleStack<Span>&                     spanStack,
-  Vector<ColorRun>&                     colorRuns,
-  Vector<FontDescriptionRun>&           fontRuns,
-  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
-  Vector<ColorRun>&                     backgroundColorRuns,
-  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
-  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns,
-  RunIndex&                             colorRunIndex,
-  RunIndex&                             fontRunIndex,
-  RunIndex&                             underlinedCharacterRunIndex,
-  RunIndex&                             backgroundColorRunIndex,
-  RunIndex&                             strikethroughCharacterRunIndex,
-  RunIndex&                             characterSpacingCharacterRunIndex,
-  const CharacterIndex                  characterIndex,
-  int&                                  tagReference)
-{
-  if(!spanTag.isEndTag)
-  {
-    // Create a new run.
-    ColorRun colorRun;
-    Initialize(colorRun);
-
-    FontDescriptionRun fontRun;
-    Initialize(fontRun);
-
-    UnderlinedCharacterRun underlinedCharacterRun;
-    Initialize(underlinedCharacterRun);
-
-    ColorRun backgroundColorRun;
-    Initialize(backgroundColorRun);
-
-    StrikethroughCharacterRun strikethroughCharacterRun;
-    Initialize(strikethroughCharacterRun);
-
-    CharacterSpacingCharacterRun characterSpacingCharacterRun;
-    Initialize(characterSpacingCharacterRun);
-
-    Span span;
-    Initialize(span);
-
-    // Fill the run with the parameters.
-    colorRun.characterRun.characterIndex                     = characterIndex;
-    fontRun.characterRun.characterIndex                      = characterIndex;
-    underlinedCharacterRun.characterRun.characterIndex       = characterIndex;
-    backgroundColorRun.characterRun.characterIndex           = characterIndex;
-    strikethroughCharacterRun.characterRun.characterIndex    = characterIndex;
-    characterSpacingCharacterRun.characterRun.characterIndex = characterIndex;
-
-    span.colorRunIndex                     = colorRunIndex;
-    span.fontRunIndex                      = fontRunIndex;
-    span.underlinedCharacterRunIndex       = underlinedCharacterRunIndex;
-    span.backgroundColorRunIndex           = backgroundColorRunIndex;
-    span.strikethroughCharacterRunIndex    = strikethroughCharacterRunIndex;
-    span.characterSpacingCharacterRunIndex = characterSpacingCharacterRunIndex;
-
-    ProcessSpanTag(spanTag,
-                   colorRun,
-                   fontRun,
-                   underlinedCharacterRun,
-                   backgroundColorRun,
-                   strikethroughCharacterRun,
-                   characterSpacingCharacterRun,
-                   span.isColorDefined,
-                   span.isFontDefined,
-                   span.isUnderlinedCharacterDefined,
-                   span.isBackgroundColorDefined,
-                   span.isStrikethroughDefined,
-                   span.isCharacterSpacingDefined);
-
-    // Push the span into the stack.
-    spanStack.Push(span);
-
-    // Point the next free run.
-    if(span.isColorDefined)
-    {
-      // Push the run in the logical model.
-      colorRuns.PushBack(colorRun);
-      ++colorRunIndex;
-    }
-
-    if(span.isFontDefined)
-    {
-      // Push the run in the logical model.
-      fontRuns.PushBack(fontRun);
-      ++fontRunIndex;
-    }
-
-    if(span.isUnderlinedCharacterDefined)
-    {
-      // Push the run in the logical model.
-      underlinedCharacterRuns.PushBack(underlinedCharacterRun);
-      ++underlinedCharacterRunIndex;
-    }
-
-    if(span.isBackgroundColorDefined)
-    {
-      // Push the run in the logical model.
-      backgroundColorRuns.PushBack(backgroundColorRun);
-      ++backgroundColorRunIndex;
-    }
-
-    if(span.isStrikethroughDefined)
-    {
-      // Push the run in the logical model.
-      strikethroughCharacterRuns.PushBack(strikethroughCharacterRun);
-      ++strikethroughCharacterRunIndex;
-    }
-
-    if(span.isCharacterSpacingDefined)
-    {
-      // Push the run in the logical model.
-      characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun);
-      ++characterSpacingCharacterRunIndex;
-    }
-
-    // Increase reference
-    ++tagReference;
-  }
-  else
-  {
-    if(tagReference > 0)
-    {
-      // Pop the top of the stack and set the number of characters of the run.
-      Span span = spanStack.Pop();
-
-      if(span.isColorDefined)
-      {
-        ColorRun& colorRun                       = *(colorRuns.Begin() + span.colorRunIndex);
-        colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex;
-      }
-
-      if(span.isFontDefined)
-      {
-        FontDescriptionRun& fontRun             = *(fontRuns.Begin() + span.fontRunIndex);
-        fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
-      }
-
-      if(span.isUnderlinedCharacterDefined)
-      {
-        UnderlinedCharacterRun& underlinedCharacterRun         = *(underlinedCharacterRuns.Begin() + span.underlinedCharacterRunIndex);
-        underlinedCharacterRun.characterRun.numberOfCharacters = characterIndex - underlinedCharacterRun.characterRun.characterIndex;
-      }
-
-      if(span.isBackgroundColorDefined)
-      {
-        ColorRun& backgroundColorRun                       = *(backgroundColorRuns.Begin() + span.backgroundColorRunIndex);
-        backgroundColorRun.characterRun.numberOfCharacters = characterIndex - backgroundColorRun.characterRun.characterIndex;
-      }
-
-      if(span.isStrikethroughDefined)
-      {
-        StrikethroughCharacterRun& strikethroughCharacterRun      = *(strikethroughCharacterRuns.Begin() + span.strikethroughCharacterRunIndex);
-        strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex;
-      }
-
-      if(span.isCharacterSpacingDefined)
-      {
-        CharacterSpacingCharacterRun& characterSpacingCharacterRun   = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex);
-        characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex;
-      }
-
-      --tagReference;
-    }
-  }
-}
-
-/**
- * @brief Resizes the model's vectors
- *
- * @param[inout] markupProcessData The markup process data
- * @param[in] fontRunIndex The font run index
- * @param[in] colorRunIndex The color run index
- * @param[in] underlinedCharacterRunIndex The underlined character run index
- * @param[in] strikethroughCharacterRunIndex The strikethroughed character run index
- * @param[in] backgroundRunIndex The background run index
- * @param[in] boundedParagraphRunIndex The bounded paragraph run index
- * @param[in] characterSpacingCharacterRunIndex The character-spacing character run index
- *
- */
-void ResizeModelVectors(MarkupProcessData& markupProcessData,
-                        const RunIndex     fontRunIndex,
-                        const RunIndex     colorRunIndex,
-                        const RunIndex     underlinedCharacterRunIndex,
-                        const RunIndex     strikethroughCharacterRunIndex,
-                        const RunIndex     backgroundRunIndex,
-                        const RunIndex     boundedParagraphRunIndex,
-                        const RunIndex     characterSpacingCharacterRunIndex)
-{
-  markupProcessData.fontRuns.Resize(fontRunIndex);
-  markupProcessData.colorRuns.Resize(colorRunIndex);
-  markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
-  markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex);
-  markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
-  markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex);
-  markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex);
-
-#ifdef DEBUG_ENABLED
-  if(gLogFilter->IsEnabledFor(Debug::Verbose))
-  {
-    for(uint32_t i = 0; i < colorRunIndex; ++i)
-    {
-      ColorRun& run = markupProcessData.colorRuns[i];
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a);
-    }
-  }
-#endif
-}
-
-/**
- * @brief Processes the markup string buffer
- *
- * @param[in/out] markupProcessData The markup process data
- * @param[in/out] markupStringBuffer The markup string buffer pointer
- * @param[in] markupStringEndBuffer The markup string end buffer pointer
- * @param[in/out] characterIndex The current character index
- */
-void ProcessMarkupStringBuffer(
-  MarkupProcessData& markupProcessData,
-  const char*&       markupStringBuffer,
-  const char* const  markupStringEndBuffer,
-  CharacterIndex&    characterIndex)
-{
-  unsigned char character    = *markupStringBuffer;
-  const char*   markupBuffer = markupStringBuffer;
-  unsigned char count        = GetUtf8Length(character);
-  char          utf8[8];
-
-  if((BACK_SLASH == character) && (markupStringBuffer + 1u < markupStringEndBuffer))
-  {
-    // Adding < , >  or & special character.
-    const unsigned char nextCharacter = *(markupStringBuffer + 1u);
-    if((LESS_THAN == nextCharacter) || (GREATER_THAN == nextCharacter) || (AMPERSAND == nextCharacter))
-    {
-      character = nextCharacter;
-      ++markupStringBuffer;
-
-      count        = GetUtf8Length(character);
-      markupBuffer = markupStringBuffer;
-    }
-  }
-  else // checking if contains XHTML entity or not
-  {
-    const unsigned int len = GetXHTMLEntityLength(markupStringBuffer, markupStringEndBuffer);
-
-    // Parse markupStringTxt if it contains XHTML Entity between '&' and ';'
-    if(len > 0)
-    {
-      char* entityCode = NULL;
-      bool  result     = false;
-      count            = 0;
-
-      // Checking if XHTML Numeric Entity
-      if(HASH == *(markupBuffer + 1u))
-      {
-        entityCode = &utf8[0];
-        // markupBuffer is currently pointing to '&'. By adding 2u to markupBuffer it will point to numeric string by skipping "&#'
-        result = XHTMLNumericEntityToUtf8((markupBuffer + 2u), entityCode);
-      }
-      else // Checking if XHTML Named Entity
-      {
-        entityCode = const_cast<char*>(NamedEntityToUtf8(markupBuffer, len));
-        result     = (entityCode != NULL);
-      }
-      if(result)
-      {
-        markupBuffer = entityCode; //utf8 text assigned to markupBuffer
-        character    = markupBuffer[0];
-      }
-      else
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Not valid XHTML entity : (%.*s) \n", len, markupBuffer);
-        markupBuffer = NULL;
-      }
-    }
-    else // in case string conatins Start of XHTML Entity('&') but not its end character(';')
-    {
-      if(character == AMPERSAND)
-      {
-        markupBuffer = NULL;
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Not Well formed XHTML content \n");
-      }
-    }
-  }
-
-  if(markupBuffer != NULL)
-  {
-    const unsigned char numberOfBytes = GetUtf8Length(character);
-    markupProcessData.markupProcessedText.push_back(character);
-
-    for(unsigned char i = 1u; i < numberOfBytes; ++i)
-    {
-      ++markupBuffer;
-      markupProcessData.markupProcessedText.push_back(*markupBuffer);
-    }
-
-    ++characterIndex;
-    markupStringBuffer += count;
-  }
-}
-
-} // namespace
-
-void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "markupString: %s\n", markupString.c_str());
-
-  // Reserve space for the plain text.
-  const Length markupStringSize = markupString.size();
-  markupProcessData.markupProcessedText.reserve(markupStringSize);
-
-  // Stores a struct with the index to the first character of the run, the type of run and its parameters.
-  StyleStack<RunIndex> styleStack;
-
-  // Stores a struct with the index to the first character of the color run & color font for the span.
-  StyleStack<Span> spanStack;
-
-  // Points the next free position in the vector of runs.
-  RunIndex colorRunIndex                     = 0u;
-  RunIndex fontRunIndex                      = 0u;
-  RunIndex underlinedCharacterRunIndex       = 0u;
-  RunIndex backgroundRunIndex                = 0u;
-  RunIndex strikethroughCharacterRunIndex    = 0u;
-  RunIndex boundedParagraphRunIndex          = 0u;
-  RunIndex characterSpacingCharacterRunIndex = 0u;
-
-  // check tag reference
-  int colorTagReference            = 0u;
-  int fontTagReference             = 0u;
-  int iTagReference                = 0u;
-  int bTagReference                = 0u;
-  int uTagReference                = 0u;
-  int backgroundTagReference       = 0u;
-  int spanTagReference             = 0u;
-  int sTagReference                = 0u;
-  int pTagReference                = 0u;
-  int characterSpacingTagReference = 0u;
-
-  // Give an initial default value to the model's vectors.
-  markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
-  markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
-  markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
-  markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
-  markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
-  markupProcessData.characterSpacingCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
-
-  // Get the mark-up string buffer.
-  const char*       markupStringBuffer    = markupString.c_str();
-  const char* const markupStringEndBuffer = markupStringBuffer + markupStringSize;
-
-  Tag            tag;
-  CharacterIndex characterIndex = 0u;
-  for(; markupStringBuffer < markupStringEndBuffer;)
-  {
-    tag.attributes.Clear();
-    if(IsTag(markupStringBuffer,
-             markupStringEndBuffer,
-             tag))
-    {
-      if(TokenComparison(MARKUP::TAG::COLOR, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<ColorRun>(
-          markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) { ProcessColorTag(tag, run); });
-      } // <color></color>
-      else if(TokenComparison(MARKUP::TAG::ITALIC, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<FontDescriptionRun>(
-          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, iTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
-            fontRun.slant        = TextAbstraction::FontSlant::ITALIC;
-            fontRun.slantDefined = true;
-          });
-      } // <i></i>
-      else if(TokenComparison(MARKUP::TAG::UNDERLINE, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<UnderlinedCharacterRun>(
-          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { ProcessUnderlineTag(tag, run); });
-      } // <u></u>
-      else if(TokenComparison(MARKUP::TAG::BOLD, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<FontDescriptionRun>(
-          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, bTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
-            fontRun.weight        = TextAbstraction::FontWeight::BOLD;
-            fontRun.weightDefined = true;
-          });
-      } // <b></b>
-      else if(TokenComparison(MARKUP::TAG::FONT, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<FontDescriptionRun>(
-          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, fontTagReference, [](const Tag& tag, FontDescriptionRun& fontRun) { ProcessFontTag(tag, fontRun); });
-      } // <font></font>
-      else if(TokenComparison(MARKUP::TAG::ANCHOR, tag.buffer, tag.length))
-      {
-        /* Anchor */
-        ProcessAnchorTag(markupProcessData, tag, characterIndex);
-        /* Color */
-        ProcessTagForRun<ColorRun>(
-          markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) {
-            run.color = Color::BLUE;
-            ProcessColorTag(tag, run);
-          });
-        /* Underline */
-        ProcessTagForRun<UnderlinedCharacterRun>(
-          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {
-            run.properties.color        = Color::BLUE;
-            run.properties.colorDefined = true;
-            ProcessUnderlineTag(tag, run);
-          });
-      } // <a href=https://www.tizen.org>tizen</a>
-      else if(TokenComparison(MARKUP::TAG::SHADOW, tag.buffer, tag.length))
-      {
-        // TODO: If !tag.isEndTag, then create a new shadow run.
-        //       else Pop the top of the stack and set the number of characters of the run.
-      } // <shadow></shadow>
-      else if(TokenComparison(MARKUP::TAG::GLOW, tag.buffer, tag.length))
-      {
-        // TODO: If !tag.isEndTag, then create a new glow run.
-        //       else Pop the top of the stack and set the number of characters of the run.
-      } // <glow></glow>
-      else if(TokenComparison(MARKUP::TAG::OUTLINE, tag.buffer, tag.length))
-      {
-        // TODO: If !tag.isEndTag, then create a new outline run.
-        //       else Pop the top of the stack and set the number of characters of the run.
-      } // <outline></outline>
-      else if(TokenComparison(MARKUP::TAG::EMBEDDED_ITEM, tag.buffer, tag.length))
-      {
-        ProcessItemTag(markupProcessData, tag, characterIndex);
-      }
-      else if(TokenComparison(MARKUP::TAG::BACKGROUND, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<ColorRun>(
-          markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
-      }
-      else if(TokenComparison(MARKUP::TAG::SPAN, tag.buffer, tag.length))
-      {
-        ProcessSpanForRun(tag,
-                          spanStack,
-                          markupProcessData.colorRuns,
-                          markupProcessData.fontRuns,
-                          markupProcessData.underlinedCharacterRuns,
-                          markupProcessData.backgroundColorRuns,
-                          markupProcessData.strikethroughCharacterRuns,
-                          markupProcessData.characterSpacingCharacterRuns,
-                          colorRunIndex,
-                          fontRunIndex,
-                          underlinedCharacterRunIndex,
-                          backgroundRunIndex,
-                          strikethroughCharacterRunIndex,
-                          characterSpacingCharacterRunIndex,
-                          characterIndex,
-                          spanTagReference);
-      }
-      else if(TokenComparison(MARKUP::TAG::STRIKETHROUGH, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<StrikethroughCharacterRun>(
-          markupProcessData.strikethroughCharacterRuns, styleStack, tag, characterIndex, strikethroughCharacterRunIndex, sTagReference, [](const Tag& tag, StrikethroughCharacterRun& run) { ProcessStrikethroughTag(tag, run); });
-      } // <s></s>
-      else if(TokenComparison(MARKUP::TAG::PARAGRAPH, tag.buffer, tag.length))
-      {
-        ProcessParagraphTag(markupProcessData, tag, (markupStringBuffer == markupStringEndBuffer), characterIndex);
-        ProcessTagForRun<BoundedParagraphRun>(
-          markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); });
-      } // <p></p>
-      else if(TokenComparison(MARKUP::TAG::CHARACTER_SPACING, tag.buffer, tag.length))
-      {
-        ProcessTagForRun<CharacterSpacingCharacterRun>(
-          markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); });
-      } // <char-spacing></char-spacing>
-    }   // end if( IsTag() )
-    else if(markupStringBuffer < markupStringEndBuffer)
-    {
-      ProcessMarkupStringBuffer(markupProcessData, markupStringBuffer, markupStringEndBuffer, characterIndex);
-    }
-  }
-
-  // Resize the model's vectors.
-  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex, characterSpacingCharacterRunIndex);
-
-  // Handle the nested tags
-  OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns);
-  OverrideNestedStrikethroughCharacterRuns(markupProcessData.strikethroughCharacterRuns);
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h
deleted file mode 100644 (file)
index f751843..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
-#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/common/dali-vector.h>
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/anchor.h>
-#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
-#include <dali-toolkit/internal/text/character-spacing-character-run.h>
-#include <dali-toolkit/internal/text/color-run.h>
-#include <dali-toolkit/internal/text/embedded-item.h>
-#include <dali-toolkit/internal/text/font-description-run.h>
-#include <dali-toolkit/internal/text/strikethrough-character-run.h>
-#include <dali-toolkit/internal/text/underlined-character-run.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-/**
- * @brief Keeps the plain text and references to vectors from the model which stores runs with text styles.
- */
-struct MarkupProcessData
-{
-  MarkupProcessData(Vector<ColorRun>&                     colorRuns,
-                    Vector<FontDescriptionRun>&           fontRuns,
-                    Vector<EmbeddedItem>&                 items,
-                    Vector<Anchor>&                       anchors,
-                    Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
-                    Vector<ColorRun>&                     backgroundColorRuns,
-                    Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
-                    Vector<BoundedParagraphRun>&          boundedParagraphRuns,
-                    Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns)
-  : colorRuns(colorRuns),
-    fontRuns(fontRuns),
-    items(items),
-    anchors(anchors),
-    underlinedCharacterRuns(underlinedCharacterRuns),
-    backgroundColorRuns(backgroundColorRuns),
-    strikethroughCharacterRuns(strikethroughCharacterRuns),
-    boundedParagraphRuns(boundedParagraphRuns),
-    characterSpacingCharacterRuns(characterSpacingCharacterRuns),
-    markupProcessedText()
-  {
-  }
-
-  Vector<ColorRun>&                     colorRuns;                     ///< The color runs.
-  Vector<FontDescriptionRun>&           fontRuns;                      ///< The font description runs.
-  Vector<EmbeddedItem>&                 items;                         ///< The embedded items.
-  Vector<Anchor>&                       anchors;                       ///< The anchors.
-  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns;       ///< The underlined character runs.
-  Vector<ColorRun>&                     backgroundColorRuns;           ///< The background color runs.
-  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns;    ///< The strikethrough character runs.
-  Vector<BoundedParagraphRun>&          boundedParagraphRuns;          ///< The bounded paragraph runs
-  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns; ///< The character-spacing runs
-
-  std::string markupProcessedText; ///< The mark-up string.
-};
-
-/**
- * @brief Process the mark-up string.
- *
- * @param[in] markupString The mark-up string.
- * @param[out] markupProcessData The plain text and the style.
- */
-void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData);
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-anchor.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-anchor.cpp
new file mode 100644 (file)
index 0000000..87789e3
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-anchor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/anchor.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessAnchor(const Tag& tag, Anchor& anchor)
+{
+  anchor.href = nullptr;
+
+  for(auto&& attribute : tag.attributes)
+  {
+    if(TokenComparison(MARKUP::ANCHOR_ATTRIBUTES::HREF, attribute.nameBuffer, attribute.nameLength))
+    {
+      Length hrefLength = attribute.valueLength + 1;
+      anchor.href       = new char[hrefLength];
+      memcpy(anchor.href, attribute.valueBuffer, hrefLength);
+      anchor.href[hrefLength - 1] = '\0';
+      // The memory is freed when the font run is removed from the logical model.
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-anchor.h b/dali-toolkit/internal/text/markup-processor/markup-processor-anchor.h
new file mode 100644 (file)
index 0000000..5559e0a
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+struct Tag;
+struct Anchor;
+
+/**
+ * @brief Retrieves the @e anchor from the @p tag.
+ *
+ * @param[in] tag The anchor tag and its attributes.
+ * @param[in,out] anchor The anchor.
+ */
+void ProcessAnchor( const Tag& tag, Anchor& anchor );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ANCHOR_H
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.cpp
new file mode 100644 (file)
index 0000000..5554c22
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+
+// EXTERNAL INCLUDES
+#include <memory.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void CopyAttributeValueFromBuffer(const Attribute& attribute, const Length maxLengthAttributeValue, char* value)
+{
+  const Length length = attribute.valueLength > maxLengthAttributeValue ? maxLengthAttributeValue : attribute.valueLength;
+  memcpy(value, attribute.valueBuffer, length);
+  value[length] = 0;
+}
+
+float ProcessFloatAttribute(const Attribute& attribute)
+{
+  return StringToFloat(attribute.valueBuffer);
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h b/dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h
new file mode 100644 (file)
index 0000000..ab7e07e
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+// EXTERNAL INCLUDES
+#include <functional>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Attribute;
+
+/**
+ * @brief Copy the value from attribute buffer to value.
+ *
+ * @param[in] attribute the value of attribute.
+ * @param[in] maxLengthAttributeValue the maximum length of any of the possible value for attribute
+ * @param[out] value the value container.
+ *
+ */
+void CopyAttributeValueFromBuffer(const Attribute& attribute, const Length maxLengthAttributeValue, char* value);
+
+/**
+ * @brief Process the float attribute value from buffer.
+ *
+ * @param[in] attribute the float attribute.
+ *
+ * @return The float value.
+ */
+float ProcessFloatAttribute(const Attribute& attribute);
+
+/**
+ * @brief Process the Enumeration attribute value from buffer.
+ *
+ * @param[in] attribute the Enumeration attribute.
+ * @param[in] maxLengthAttributeValue the maximum length of any of the possible value for attribute
+ * @param[in] funcStringToEnum the function converts string value to enum value
+ * @param[out] enumValue the enum value
+ *
+ * @return      True if the enum value was processed successfully
+ *
+ */
+template<typename T>
+bool ProcessEnumerationAttribute(const Attribute&                    attribute,
+                                 const Length                        maxLengthAttributeValue,
+                                 std::function<T(const char* const)> funcStringToEnum,
+                                 T&                                  enumValue)
+{
+  char* value = new char[maxLengthAttributeValue + 1u];
+
+  CopyAttributeValueFromBuffer(attribute, maxLengthAttributeValue, value);
+
+  enumValue = funcStringToEnum(value); // @TODO: the functions that process Enum value should be refactored to return bool from Scripting::GetEnumeration
+
+  delete[] value;
+
+  return true;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_ATTRIBUTE_HELPER_FUNCTIONS_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-background.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-background.cpp
new file mode 100644 (file)
index 0000000..303fff7
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-background.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessBackground(const Tag& tag, ColorRun& colorRun)
+{
+  for(auto&& attribute : tag.attributes)
+  {
+    if(TokenComparison(MARKUP::BACKGROUND_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-background.h b/dali-toolkit/internal/text/markup-processor/markup-processor-background.h
new file mode 100644 (file)
index 0000000..9420dac
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct ColorRun;
+
+/**
+ * @brief Retrieves the @e background from the @p tag.
+ *
+ * @param[in] tag The background tag and its attributes.
+ * @param[in,out] colorRun The color run to be filled.
+ */
+void ProcessBackground(const Tag& tag, ColorRun& colorRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_BACKGROUND_H
\ No newline at end of file
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.cpp
new file mode 100644 (file)
index 0000000..f18efe3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  characterSpacingCharacterRun.value = ProcessFloatAttribute(attribute);
+}
+
+void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(MARKUP::CHARACTER_SPACING_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h b/dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h
new file mode 100644 (file)
index 0000000..b8b9beb
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct CharacterSpacingCharacterRun;
+
+/**
+ * @brief Fill the character-spacing character run with the value (space or advance) attribute.
+ *
+ * @param[in] attribute the value attribute.
+ * @param[out] characterSpacingCharacterRun The underlined character run
+ */
+void ProcessValueAttribute(const Attribute& attribute, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
+
+/**
+ * @brief Retrieves the character-spacing run info from the tag and sets it to the character-spacing run.
+ *
+ * @param[in] tag The character-spacing tag and its attributes.
+ * @param[in,out] characterSpacingCharacterRun The character-spacing character run
+ */
+void ProcessCharacterSpacingTag(const Tag& tag, CharacterSpacingCharacterRun& characterSpacingCharacterRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_CHARACTER_SPACING_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-color.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-color.cpp
new file mode 100644 (file)
index 0000000..1a5ce73
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-color.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessColor(const Attribute& attribute, ColorRun& colorRun)
+{
+  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, colorRun.color);
+}
+
+void ProcessColorTag(const Tag& tag, ColorRun& colorRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+    if(TokenComparison(MARKUP::COLOR_ATTRIBUTES::VALUE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessColor(attribute, colorRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-color.h b/dali-toolkit/internal/text/markup-processor/markup-processor-color.h
new file mode 100644 (file)
index 0000000..2d8be1e
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct ColorRun;
+
+/**
+ * @brief Retrieves the color value from the tag and sets it to the color run.
+ *
+ * @param[in] attribute the color attribute.
+ * @param[in,out] colorRun The color run.
+ */
+void ProcessColor(const Attribute& attribute, ColorRun& colorRun);
+
+/**
+ * @brief Retrieves the color value from the tag and sets it to the color run.
+ *
+ * @param[in] tag The color tag and its attributes.
+ * @param[in,out] colorRun The color run.
+ */
+void ProcessColorTag(const Tag& tag, ColorRun& colorRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.cpp
new file mode 100644 (file)
index 0000000..8e9ec06
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/embedded-item.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string NONE("none");
+const std::string MULTIPLY("multiply");
+} // namespace
+
+void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem)
+{
+  embeddedItem.url               = nullptr;
+  embeddedItem.urlLength         = 0u;
+  embeddedItem.width             = 0u;
+  embeddedItem.height            = 0u;
+  embeddedItem.colorBlendingMode = ColorBlendingMode::NONE;
+
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+    if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::URL, attribute.nameBuffer, attribute.nameLength))
+    {
+      embeddedItem.urlLength = attribute.valueLength;
+      embeddedItem.url       = new char[embeddedItem.urlLength];
+      memcpy(embeddedItem.url, attribute.valueBuffer, embeddedItem.urlLength);
+      // The memory is freed when the font run is removed from the logical model.
+    }
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
+    {
+      embeddedItem.width = StringToUint(attribute.valueBuffer);
+    }
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      embeddedItem.height = StringToUint(attribute.valueBuffer);
+    }
+    else if(TokenComparison(MARKUP::EMBEDDED_ITEM_ATTRIBUTES::COLOR_BLENDING, attribute.nameBuffer, attribute.nameLength))
+    {
+      if(TokenComparison(MULTIPLY, attribute.valueBuffer, attribute.valueLength))
+      {
+        embeddedItem.colorBlendingMode = ColorBlendingMode::MULTIPLY;
+      }
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.h b/dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.h
new file mode 100644 (file)
index 0000000..ed6a371
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct EmbeddedItem;
+
+/**
+ * @brief Retrieves the @e embedded @e item from the @p tag.
+ *
+ * @param[in] tag The embedded item tag and its attributes.
+ * @param[in,out] embeddedItem The embedded item.
+ */
+void ProcessEmbeddedItem(const Tag& tag, EmbeddedItem& embeddedItem);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_EMBEDDED_ITEM_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-font.cpp
new file mode 100644 (file)
index 0000000..133d7fa
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-font.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+#include <dali-toolkit/internal/text/text-font-style.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const std::string  FONT_PREFIX("font-");
+const unsigned int FONT_PREFIX_LENGTH      = 5u;
+const unsigned int MIN_FONT_ATTRIBUTE_SIZE = 4u;   ///< The minimum length of any of the possible 'weight', 'width' , 'slant' or 'size' values.
+const unsigned int MAX_FONT_ATTRIBUTE_SIZE = 15u;  ///< The maximum length of any of the possible 'weight', 'width' or 'slant' values.
+const float        PIXEL_FORMAT_64_FACTOR  = 64.f; ///< 64.f is used to convert from point size to 26.6 pixel format.
+} // namespace
+
+void processFontAttributeValue(char value[], const Attribute& attribute)
+{
+  // The StringToWeight() uses the Scripting::GetEnumeration() function which requires the input string to end with a '\0' char.
+  const Length length = attribute.valueLength > MAX_FONT_ATTRIBUTE_SIZE ? MAX_FONT_ATTRIBUTE_SIZE : attribute.valueLength;
+  memcpy(value, attribute.valueBuffer, length);
+  value[length] = 0;
+}
+
+void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  fontRun.familyDefined = true;
+  fontRun.familyLength  = attribute.valueLength;
+  fontRun.familyName    = new char[fontRun.familyLength];
+  memcpy(fontRun.familyName, attribute.valueBuffer, fontRun.familyLength);
+  // The memory is freed when the font run is removed from the logical model.
+}
+
+void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  // 64.f is used to convert from point size to 26.6 pixel format.
+  fontRun.size        = static_cast<PointSize26Dot6>(ProcessFloatAttribute(attribute) * PIXEL_FORMAT_64_FACTOR);
+  fontRun.sizeDefined = true;
+}
+
+void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  fontRun.weightDefined = ProcessEnumerationAttribute<FontWeight>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToWeight, fontRun.weight);
+}
+
+void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  fontRun.widthDefined = ProcessEnumerationAttribute<FontWidth>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToWidth, fontRun.width);
+}
+
+void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun)
+{
+  fontRun.slantDefined = ProcessEnumerationAttribute<FontSlant>(attribute, MAX_FONT_ATTRIBUTE_SIZE, &StringToSlant, fontRun.slant);
+}
+
+void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(MARKUP::FONT_ATTRIBUTES::FAMILY, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessFontFamily(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SIZE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessFontSize(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessFontWeight(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::WIDTH, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessFontWidth(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::FONT_ATTRIBUTES::SLANT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessFontSlant(attribute, fontRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-font.h b/dali-toolkit/internal/text/markup-processor/markup-processor-font.h
new file mode 100644 (file)
index 0000000..cc2b561
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct FontDescriptionRun;
+
+/**
+ * @brief Retrieves the font attributes from the tag and sets it to the font run.
+ *
+ * @param[in] tag The font tag and its attributes.
+ * @param[in,out] fontRun The font description run.
+ */
+void ProcessFontTag(const Tag& tag, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font slant attribute value.
+ *
+ * @param[in] attribute the font slant attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontSlant(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font width attribute value.
+ *
+ * @param[in] attribute the font width attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontWidth(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font weight attribute value.
+ *
+ * @param[in] attribute the font weight attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontWeight(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font size attribute value.
+ *
+ * @param[in] attribute the font size attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontSize(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+/**
+ * @brief Fill the font run with the font family attribute value.
+ *
+ * @param[in] attribute the font family attribute.
+ * @param[out] fontRun The font description run.
+ */
+void ProcessFontFamily(const Attribute& attribute, FontDescriptionRun& fontRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_FONT_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.cpp
new file mode 100644 (file)
index 0000000..b0ac16b
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector2.h>
+#include <stdlib.h>
+#include <iomanip>
+#include <sstream>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const char WHITE_SPACE      = 0x20; // ASCII value of the white space.
+const char FIRST_UPPER_CASE = 0x41; // ASCII value of the one after the first upper case character (A).
+const char LAST_UPPER_CASE  = 0x5b; // ASCII value of the one after the last upper case character (Z).
+const char TO_LOWER_CASE    = 32;   // Value to add to a upper case character to transform it into a lower case.
+
+const unsigned int MAX_FLOAT_ATTRIBUTE_SIZE = 17u; ///< The maximum length of any of the possible float values.  +99999.999999999f  (sign, five digits, dot, nine digits, f)
+
+const char        WEB_COLOR_TOKEN('#');
+const char* const HEX_COLOR_TOKEN("0x");
+const char* const ALPHA_ONE("FF");
+
+const std::string BLACK_COLOR("black");
+const std::string WHITE_COLOR("white");
+const std::string RED_COLOR("red");
+const std::string GREEN_COLOR("green");
+const std::string BLUE_COLOR("blue");
+const std::string YELLOW_COLOR("yellow");
+const std::string MAGENTA_COLOR("magenta");
+const std::string CYAN_COLOR("cyan");
+const std::string TRANSPARENT_COLOR("transparent");
+
+const std::string SOLID_UNDERLINE("solid");
+const std::string DASHED_UNDERLINE("dashed");
+const std::string DOUBLE_UNDERLINE("double");
+
+const std::string BEGIN_HORIZONTAL_ALIGNMENT("begin");
+const std::string CENTER_HORIZONTAL_ALIGNMENT("center");
+const std::string END_HORIZONTAL_ALIGNMENT("end");
+
+} // namespace
+
+bool TokenComparison(const std::string& string1, const char* const stringBuffer2, Length length)
+{
+  const Length stringSize = string1.size();
+  if(stringSize != length)
+  {
+    // Early return. Strings have different sizes.
+    return false;
+  }
+
+  const char* const stringBuffer1 = string1.c_str();
+
+  for(std::size_t index = 0; index < stringSize; ++index)
+  {
+    const char character = *(stringBuffer2 + index);
+    const bool toLower   = (character < LAST_UPPER_CASE) && (character >= FIRST_UPPER_CASE);
+    if(*(stringBuffer1 + index) != (toLower ? character + TO_LOWER_CASE : character))
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SkipWhiteSpace(const char*&      stringBuffer,
+                    const char* const stringEndBuffer)
+{
+  for(; (WHITE_SPACE >= *stringBuffer) && (stringBuffer < stringEndBuffer); ++stringBuffer)
+    ;
+}
+
+void JumpToWhiteSpace(const char*&      stringBuffer,
+                      const char* const stringEndBuffer)
+{
+  for(; (WHITE_SPACE != *stringBuffer) && (stringBuffer < stringEndBuffer); ++stringBuffer)
+    ;
+}
+
+unsigned int StringToUint(const char* const uintStr)
+{
+  return static_cast<unsigned int>(strtoul(uintStr, NULL, 10));
+}
+
+unsigned int StringToHex(const char* const uintStr)
+{
+  return static_cast<unsigned int>(strtoul(uintStr, NULL, 16));
+}
+
+float StringToFloat(const char* const floatStr)
+{
+  return static_cast<float>(strtod(floatStr, NULL));
+}
+
+void FloatToString(float value, std::string& floatStr)
+{
+  std::stringstream ss;
+  ss << value;
+  floatStr = ss.str();
+}
+
+void UintToString(unsigned int value, std::string& uIntStr)
+{
+  std::stringstream ss;
+  ss << value;
+  uIntStr = ss.str();
+}
+
+void UintColorToVector4(unsigned int color, Vector4& retColor)
+{
+  retColor.a = static_cast<float>((color & 0xFF000000) >> 24u) / 255.f;
+  retColor.r = static_cast<float>((color & 0x00FF0000) >> 16u) / 255.f;
+  retColor.g = static_cast<float>((color & 0x0000FF00) >> 8u) / 255.f;
+  retColor.b = static_cast<float>(color & 0x000000FF) / 255.f;
+}
+
+void ColorStringToVector4(const char* const colorStr, Length length, Vector4& retColor)
+{
+  if(WEB_COLOR_TOKEN == *colorStr)
+  {
+    std::string webColor(colorStr + 1u, length - 1u);
+    if(4u == length) // 3 component web color #F00 (red)
+    {
+      webColor.insert(2u, &(webColor[2]), 1u);
+      webColor.insert(1u, &(webColor[1]), 1u);
+      webColor.insert(0u, &(webColor[0]), 1u);
+      webColor.insert(0u, ALPHA_ONE);
+    }
+    else if(7u == length) // 6 component web color #FF0000 (red)
+    {
+      webColor.insert(0u, ALPHA_ONE);
+    }
+
+    UintColorToVector4(StringToHex(webColor.c_str()), retColor);
+  }
+  else if(TokenComparison(HEX_COLOR_TOKEN, colorStr, 2u))
+  {
+    UintColorToVector4(StringToHex(colorStr + 2u), retColor);
+  }
+  else if(TokenComparison(BLACK_COLOR, colorStr, length))
+  {
+    retColor = Color::BLACK;
+  }
+  else if(TokenComparison(WHITE_COLOR, colorStr, length))
+  {
+    retColor = Color::WHITE;
+  }
+  else if(TokenComparison(RED_COLOR, colorStr, length))
+  {
+    retColor = Color::RED;
+  }
+  else if(TokenComparison(GREEN_COLOR, colorStr, length))
+  {
+    retColor = Color::GREEN;
+  }
+  else if(TokenComparison(BLUE_COLOR, colorStr, length))
+  {
+    retColor = Color::BLUE;
+  }
+  else if(TokenComparison(YELLOW_COLOR, colorStr, length))
+  {
+    retColor = Color::YELLOW;
+  }
+  else if(TokenComparison(MAGENTA_COLOR, colorStr, length))
+  {
+    retColor = Color::MAGENTA;
+  }
+  else if(TokenComparison(CYAN_COLOR, colorStr, length))
+  {
+    retColor = Color::CYAN;
+  }
+  else if(TokenComparison(TRANSPARENT_COLOR, colorStr, length))
+  {
+    retColor = Color::TRANSPARENT;
+  }
+}
+
+void Vector4ToColorString(const Vector4& value, std::string& vector2Str)
+{
+  if(Color::BLACK == value)
+  {
+    vector2Str = BLACK_COLOR;
+    return;
+  }
+
+  if(Color::WHITE == value)
+  {
+    vector2Str = WHITE_COLOR;
+    return;
+  }
+
+  if(Color::RED == value)
+  {
+    vector2Str = RED_COLOR;
+    return;
+  }
+
+  if(Color::GREEN == value)
+  {
+    vector2Str = GREEN_COLOR;
+    return;
+  }
+
+  if(Color::BLUE == value)
+  {
+    vector2Str = BLUE_COLOR;
+    return;
+  }
+
+  if(Color::YELLOW == value)
+  {
+    vector2Str = YELLOW_COLOR;
+    return;
+  }
+
+  if(Color::MAGENTA == value)
+  {
+    vector2Str = MAGENTA_COLOR;
+    return;
+  }
+
+  if(Color::CYAN == value)
+  {
+    vector2Str = CYAN_COLOR;
+    return;
+  }
+
+  if(Color::TRANSPARENT == value)
+  {
+    vector2Str = TRANSPARENT_COLOR;
+    return;
+  }
+
+  const unsigned int alpha = static_cast<unsigned int>(255.f * value.a);
+  const unsigned int red   = static_cast<unsigned int>(255.f * value.r);
+  const unsigned int green = static_cast<unsigned int>(255.f * value.g);
+  const unsigned int blue  = static_cast<unsigned int>(255.f * value.b);
+
+  std::stringstream  ss;
+  const unsigned int size = 2u * sizeof(unsigned char);
+
+  ss << "0x"
+     << std::setfill('0') << std::setw(size)
+     << std::hex << alpha
+     << std::setfill('0') << std::setw(size)
+     << std::hex << red
+     << std::setfill('0') << std::setw(size)
+     << std::hex << green
+     << std::setfill('0') << std::setw(size)
+     << std::hex << blue;
+  vector2Str = ss.str();
+}
+
+void StringToVector2(const char* const vectorStr, Length length, Vector2& vector2)
+{
+  // Points to the first character of the string.
+  const char* strBuffer = vectorStr;
+
+  // Points to the first character of the 'x' value.
+  const char* const xBuffer = strBuffer;
+
+  // Jumps to the next white space.
+  JumpToWhiteSpace(strBuffer, strBuffer + length);
+
+  // Points to the first character of the 'y' value.
+  const char* const yBuffer = strBuffer;
+
+  // Converts the shadow's offset to float.
+  vector2.x = StringToFloat(xBuffer);
+  vector2.y = StringToFloat(yBuffer);
+}
+
+void Vector2ToString(const Vector2& value, std::string& vector2Str)
+{
+  FloatToString(value.x, vector2Str);
+  vector2Str += " ";
+
+  std::string yStr;
+  FloatToString(value.y, yStr);
+
+  vector2Str += yStr;
+}
+
+void UnderlineTypeStringToTypeValue(const char* const typeStr, Length length, Text::Underline::Type& retType)
+{
+  if(TokenComparison(SOLID_UNDERLINE, typeStr, length))
+  {
+    retType = Text::Underline::SOLID;
+  }
+  else if(TokenComparison(DASHED_UNDERLINE, typeStr, length))
+  {
+    retType = Text::Underline::DASHED;
+  }
+  else if(TokenComparison(DOUBLE_UNDERLINE, typeStr, length))
+  {
+    retType = Text::Underline::DOUBLE;
+  }
+}
+
+bool HorizontalAlignmentTypeStringToTypeValue(const char* const typeStr, Length length, Text::HorizontalAlignment::Type& retType)
+{
+  // The string is valid value for HorizontalAlignment
+  bool valid = false;
+  if(TokenComparison(BEGIN_HORIZONTAL_ALIGNMENT, typeStr, length))
+  {
+    retType = Text::HorizontalAlignment::BEGIN;
+    valid   = true;
+  }
+  else if(TokenComparison(CENTER_HORIZONTAL_ALIGNMENT, typeStr, length))
+  {
+    retType = Text::HorizontalAlignment::CENTER;
+    valid   = true;
+  }
+  else if(TokenComparison(END_HORIZONTAL_ALIGNMENT, typeStr, length))
+  {
+    retType = Text::HorizontalAlignment::END;
+    valid   = true;
+  }
+
+  return valid;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h b/dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h
new file mode 100644 (file)
index 0000000..d763318
--- /dev/null
@@ -0,0 +1,222 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/public-api/text/text-enumerations.h>
+
+namespace Dali
+{
+struct Vector2;
+struct Vector4;
+
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Stores an attribute pair: name, value.
+ */
+struct Attribute
+{
+  const char* nameBuffer;
+  const char* valueBuffer;
+  Length      nameLength;
+  Length      valueLength;
+};
+
+/**
+ * @brief Stores a tag and its attributes.
+ */
+struct Tag
+{
+  Vector<Attribute> attributes;
+  const char*       buffer;
+  Length            length;
+  bool              isEndTag;
+};
+
+/**
+ * @brief Compare if two tokens are equal.
+ *
+ * @pre @p string1 must be lower case. (The html-ish constant tokens)
+ * The @p stringBuffer2 parameter is transformed to lower case.
+ * This function is used in the mark-up parser.
+ * It has no sense to transform the constants html-ish tokens to lower case when
+ * it's known they already are.
+ *
+ * @param[in] string1 The html-ish constant token.
+ * @param[in] stringBuffer2 Pointer to the html-ish token buffer.
+ * @param[in] length The length of the html-ish token.
+ *
+ * @return @e true if both strings are equal.
+ */
+bool TokenComparison(const std::string& string1, const char* const stringBuffer2, Length length);
+
+/**
+ * @brief Skips any unnecessary white space.
+ *
+ * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character.
+ * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer.
+ */
+void SkipWhiteSpace(const char*&      stringBuffer,
+                    const char* const stringEndBuffer);
+
+/**
+ * @Brief Jumps to the next white space.
+ *
+ * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character.
+ * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer.
+ */
+void JumpToWhiteSpace(const char*&      stringBuffer,
+                      const char* const stringEndBuffer);
+
+/**
+* @brief Converts a string into an unsigned int.
+*
+* @param[in] uintStr An unsigned int packed inside a string.
+*
+* @return The unsigned int value.
+*/
+unsigned int StringToUint(const char* const uintStr);
+
+/**
+ * @brief Converts a string into an hexadecimal unsigned int.
+ *
+ * @param[in] uintStr An hexadecimal unsigned int packed inside a string.
+ *
+ * @return The hexadecimal value.
+ */
+unsigned int StringToHex(const char* const uintStr);
+
+/**
+ * @brief Converts a string into a float value.
+ *
+ * @param[in] floatStr A float packed inside a string.
+ *
+ * @return The float value.
+ */
+float StringToFloat(const char* const floatStr);
+
+/**
+ * @brief Converts a float into a string.
+ *
+ * @param[in] value The float value.
+ * @param[out] floatStr The string.
+ */
+void FloatToString(float value, std::string& floatStr);
+
+/**
+ * @brief Converts an unsigned int into a string.
+ *
+ * @param[in] value The unsigned int value.
+ * @param[out] uIntStr The string.
+ */
+void UintToString(unsigned int value, std::string& uIntStr);
+
+/**
+ * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali.
+ *
+ * @param[in] color An ARGB color packed in an unsigned int.
+ * @param[out] retColor A Vector4 with the converted color.
+ */
+void UintColorToVector4(unsigned int color, Vector4& retColor);
+
+/**
+ * @brief Converts a color packed inside a string into an ARGB Vector4 color.
+ *
+ * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values:
+ * black, white, red, green, blue, yellow, magenta, cyan or transparent.
+ *
+ * @param[in] colorStr A color packed inside a string.
+ * @param[in] length The length of the color string.
+ * @param[out] retColor A color packed inside a Vector4.
+ */
+void ColorStringToVector4(const char* const colorStr, Length length, Vector4& retColor);
+
+/**
+ * @brief Converts a color packed in a Vector4 into a string.
+ *
+ * Constant colors will be converted to the strings black, white, red, green, blue, yellow, magenta, cyan or transparent.
+ *
+ * If is not a constant color it will be converted to a string with hexadecimal ARGB content.
+ *
+ * @param[in] value The color value.
+ * @param[out] colorStr The string.
+ */
+void Vector4ToColorString(const Vector4& value, std::string& vector2Str);
+
+/**
+ * @brief Converts a two dimension vector packed inside a string into a Vector2.
+ *
+ * @param[in] vectorStr The two dimension vector packed inside a string.
+ * @param[in] length The length of the string.
+ * @param[out] vector2 The Vector2.
+ */
+void StringToVector2(const char* const vectorStr, Length length, Vector2& vector2);
+
+/**
+ * @brief Converts a Vector2 into a string.
+ *
+ * @param[in] value The vector2 value.
+ * @param[out] vector2Str The string.
+ */
+void Vector2ToString(const Vector2& value, std::string& vector2Str);
+
+/**
+ * @brief Converts a string into its value in the enum Text::Underline::Type.
+ *
+ * @param[in] typeStr The underline type value packed inside a string.
+ * @param[in] length The length of the string.
+ * @param[out] retType The Underline type.
+ */
+void UnderlineTypeStringToTypeValue(const char* const typeStr, Length length, Text::Underline::Type& retType);
+
+/**
+ * @brief Converts a string into a float value.
+ *
+ * @param[in] floatStr A float packed inside a string.
+ *
+ * @return The float value.
+ */
+float StringToFloat(const char* const floatStr);
+
+/**
+ * @brief Converts a string into its value in the enum Text::HorizontalAlignment::Type.
+ *
+ * @param[in] typeStr The horizontal-alignment type value packed inside a string.
+ * @param[in] length The length of the string.
+ * @param[out] retType The HorizontalAlignment type.
+ *
+ * @return Whether the value parsed or not.
+ */
+bool HorizontalAlignmentTypeStringToTypeValue(const char* const typeStr, Length length, Text::HorizontalAlignment::Type& retType);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.cpp
new file mode 100644 (file)
index 0000000..8676198
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
+{
+  boundedParagraphRun.horizontalAlignmentDefined = HorizontalAlignmentTypeStringToTypeValue(attribute.valueBuffer,
+                                                                                            attribute.valueLength,
+                                                                                            boundedParagraphRun.horizontalAlignment);
+}
+
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun)
+{
+  boundedParagraphRun.relativeLineSize        = StringToFloat(attribute.valueBuffer);
+  boundedParagraphRun.relativeLineSizeDefined = true;
+}
+
+void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun)
+{
+  // By default the align attribute is not defined until it's parsed.
+  boundedParagraphRun.horizontalAlignmentDefined = false;
+
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+    if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::ALIGN, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessHorizontalAlignment(attribute, boundedParagraphRun);
+    }
+    else if(TokenComparison(MARKUP::PARAGRAPH_ATTRIBUTES::RELATIVE_LINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessRelativeLineHeight(attribute, boundedParagraphRun);
+    }
+  }
+}
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.h b/dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.h
new file mode 100644 (file)
index 0000000..2859794
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct BoundedParagraphRun;
+
+/**
+ * @brief Retrieves the horizontal alignment value from the tag and sets it to the bounded paragraph run.
+ *
+ * @param[in] attribute the horizontal alignment attribute.
+ * @param[in,out] boundedParagraphRun The bounded paragraph run.
+ */
+void ProcessHorizontalAlignment(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
+
+/**
+ * @brief Retrieves the paragraph value from the tag and sets it to the bounded paragraph run.
+ *
+ * @param[in] tag The paragraph tag and its attributes.
+ * @param[in,out] boundedParagraphRun The bounded paragraph run.
+ */
+void ProcessAttributesOfParagraphTag(const Tag& tag, BoundedParagraphRun& boundedParagraphRun);
+
+/**
+ * @brief Retrieves the relative line height value from the paragraph tag and sets it to the bounded paragraph run.
+ *
+ * @param[in] attribute the relative line height attribute.
+ * @param[in,out] boundedParagraphRun The bounded paragraph run.
+ */
+void ProcessRelativeLineHeight(const Attribute& attribute, BoundedParagraphRun& boundedParagraphRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_PARAGRAPH_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-span.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-span.cpp
new file mode 100644 (file)
index 0000000..5f8dfa2
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-color.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-font.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-underline.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessSpanTag(const Tag&                    tag,
+                    ColorRun&                     colorRun,
+                    FontDescriptionRun&           fontRun,
+                    UnderlinedCharacterRun&       underlinedCharacterRun,
+                    ColorRun&                     backgroundColorRun,
+                    StrikethroughCharacterRun&    strikethroughRun,
+                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
+                    bool&                         isColorDefined,
+                    bool&                         isFontDefined,
+                    bool&                         isUnderlinedCharacterDefined,
+                    bool&                         isBackgroundColorDefined,
+                    bool&                         isStrikethroughDefined,
+                    bool&                         isCharacterSpacingDefined)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::TEXT_COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      isColorDefined = true;
+      ProcessColor(attribute, colorRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::BACKGROUND_COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      isBackgroundColorDefined = true;
+      ProcessColor(attribute, backgroundColorRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_FAMILY, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontFamily(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SIZE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontSize(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontWeight(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_WIDTH, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontWidth(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::FONT_SLANT, attribute.nameBuffer, attribute.nameLength))
+    {
+      isFontDefined = true;
+      ProcessFontSlant(attribute, fontRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessColorAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessHeightAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_TYPE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessTypeAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_GAP, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessDashGapAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::UNDERLINE_DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
+    {
+      isUnderlinedCharacterDefined = true;
+      ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      isStrikethroughDefined = true;
+      ProcessColorAttribute(attribute, strikethroughRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::STRIKETHROUGH_HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      isStrikethroughDefined = true;
+      ProcessHeightAttribute(attribute, strikethroughRun);
+    }
+    else if(TokenComparison(MARKUP::SPAN_ATTRIBUTES::CHARACTER_SPACING_VALUE, attribute.nameBuffer, attribute.nameLength))
+    {
+      isCharacterSpacingDefined = true;
+      ProcessValueAttribute(attribute, characterSpacingCharacterRun);
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-span.h b/dali-toolkit/internal/text/markup-processor/markup-processor-span.h
new file mode 100644 (file)
index 0000000..5630fd3
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct MarkupProcessData;
+
+/**
+ * @brief process the span from the tag and process all styles in it.
+ *
+ * @param[in] tag The span tag and its attributes.
+ * @param[out] colorRun the color run to be filled.
+ * @param[out] fontRun the font run to be filled.
+ * @param[out] underlinedCharacterRun the underlined character run to be filled.
+ * @param[out] backgroundColorRun the background color run to be filled.
+ * @param[out] strikethroughRun the strikethrough run to be filled.
+ * @param[out] characterSpacingCharacterRun the character-spacing run to be filled.
+ * @param[out] isColorDefined if the span has color defined.
+ * @param[out] isFontDefined if the span has font defined.
+ * @param[out] isUnderlinedCharacterDefined if the span has underlined-character defined.
+ * @param[out] isBackgroundColorDefined if the span has background color defined.
+ * @param[out] isStrikethroughDefined if the span has strikethrough defined.
+ * @param[out] isCharacterSpacingDefined if the span has character-spacing defined.
+ */
+void ProcessSpanTag(const Tag&                    tag,
+                    ColorRun&                     colorRun,
+                    FontDescriptionRun&           fontRun,
+                    UnderlinedCharacterRun&       underlinedCharacterRun,
+                    ColorRun&                     backgroundColorRun,
+                    StrikethroughCharacterRun&    strikethroughRun,
+                    CharacterSpacingCharacterRun& characterSpacingCharacterRun,
+                    bool&                         isColorDefined,
+                    bool&                         isFontDefined,
+                    bool&                         isUnderlinedCharacterDefined,
+                    bool&                         isBackgroundColorDefined,
+                    bool&                         isStrikethroughDefined,
+                    bool&                         isCharacterSpacingDefined);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_SPAN_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.cpp
new file mode 100644 (file)
index 0000000..5d08c93
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+#include <dali-toolkit/internal/text/strikethrough-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+void ProcessColorAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun)
+
+{
+  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, strikethroughRun.properties.color);
+  strikethroughRun.properties.colorDefined = true;
+}
+
+void ProcessHeightAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun)
+{
+  strikethroughRun.properties.height        = ProcessFloatAttribute(attribute);
+  strikethroughRun.properties.heightDefined = true;
+}
+
+void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& strikethroughRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessColorAttribute(attribute, strikethroughRun);
+    }
+    else if(TokenComparison(MARKUP::STRIKETHROUGH_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessHeightAttribute(attribute, strikethroughRun);
+    }
+  }
+}
+
+void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns)
+{
+  // Handle nested tags
+  // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
+  // Example:
+  // <s height='5.0f' color='blue'> outer tag before  <s color='green'> inner tag </s> outer tag after </s>
+  // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
+  // "inner tag" has height = 5.0f and color = 'green'
+
+  if(strikethroughCharacterRuns.Count() > 0u)
+  {
+    Vector<StrikethroughCharacterRun>::ConstIterator preIt = strikethroughCharacterRuns.Begin();
+
+    Vector<StrikethroughCharacterRun>::Iterator      it    = strikethroughCharacterRuns.Begin() + 1;
+    Vector<StrikethroughCharacterRun>::ConstIterator endIt = strikethroughCharacterRuns.End();
+
+    while(it != endIt)
+    {
+      const StrikethroughCharacterRun& run                = *it;
+      const CharacterIndex&            characterIndex     = run.characterRun.characterIndex;
+      const Length&                    numberOfCharacters = run.characterRun.numberOfCharacters;
+
+      const StrikethroughCharacterRun& preRun                = *preIt;
+      const CharacterIndex&            preCharacterIndex     = preRun.characterRun.characterIndex;
+      const Length&                    preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
+
+      if((preCharacterIndex <= characterIndex) &&
+         ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
+      {
+        it->properties.CopyIfNotDefined(preIt->properties);
+      }
+
+      it++;
+      preIt++;
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h b/dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h
new file mode 100644 (file)
index 0000000..fca6d34
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/strikethrough-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+struct StrikethroughCharacterRun;
+
+/**
+ * @brief Fill the strikethrough character run with the color attribute value.
+ *
+ * @param[in] attribute the color attribute.
+ * @param[out] strikethroughCharacterRun The strikethrough character run
+ */
+void ProcessColorAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughCharacterRun);
+
+/**
+ * @brief Fill the strikethrough character run with the height attribute value.
+ *
+ * @param[in] attribute the height attribute.
+ * @param[out] strikethroughRun The strikethrough character run
+ */
+void ProcessHeightAttribute(const Attribute& attribute, StrikethroughCharacterRun& strikethroughRun);
+
+/**
+ * @brief Retrieves the strikethrough run info from the tag and sets it to the strikethrough run.
+ *
+ * @param[in] tag The strikethrough tag and its attributes.
+ * @param[in,out] strikethroughRun The strikethrough run.
+ */
+void ProcessStrikethroughTag(const Tag& tag, StrikethroughCharacterRun& strikethroughRun);
+
+/**
+ * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
+ *
+ * @param[in,out] strikethroughCharacterRun The list of strikethrough character run
+ */
+void OverrideNestedStrikethroughCharacterRuns(Vector<StrikethroughCharacterRun>& strikethroughCharacterRun);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_STRIKETHROUGH_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-underline.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor-underline.cpp
new file mode 100644 (file)
index 0000000..ac1b0ae
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-underline.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-attribute-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
+#include <dali-toolkit/internal/text/underlined-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const unsigned int MAX_TYPE_ATTRIBUTE_SIZE = 7u; ///< The maximum length of any of the possible 'type' values.
+
+} // namespace
+
+void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.properties.typeDefined = ProcessEnumerationAttribute<Text::Underline::Type>(attribute,
+                                                                                                     MAX_TYPE_ATTRIBUTE_SIZE,
+                                                                                                     &StringToUnderlineType,
+                                                                                                     underlinedCharacterRun.properties.type);
+}
+
+void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.properties.dashGap        = ProcessFloatAttribute(attribute);
+  underlinedCharacterRun.properties.dashGapDefined = true;
+}
+
+void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.properties.dashWidth        = ProcessFloatAttribute(attribute);
+  underlinedCharacterRun.properties.dashWidthDefined = true;
+}
+void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.properties.height        = ProcessFloatAttribute(attribute);
+  underlinedCharacterRun.properties.heightDefined = true;
+}
+
+void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, underlinedCharacterRun.properties.color);
+  underlinedCharacterRun.properties.colorDefined = true;
+}
+
+void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
+                                       endIt = tag.attributes.End();
+      it != endIt;
+      ++it)
+  {
+    const Attribute& attribute(*it);
+
+    if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessColorAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessHeightAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::TYPE, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessTypeAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_GAP, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessDashGapAttribute(attribute, underlinedCharacterRun);
+    }
+    else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
+    {
+      ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
+    }
+  }
+}
+
+void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
+{
+  // Handle nested tags
+  // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
+  // Example:
+  // <u height='5.0f' color='blue'> outer tag before  <u color='green'> inner tag </u> outer tag after </u>
+  // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
+  // "inner tag" has height = 5.0f and color = 'green'
+
+  if(underlinedCharacterRuns.Count() > 0u)
+  {
+    Vector<UnderlinedCharacterRun>::ConstIterator preIt = underlinedCharacterRuns.Begin();
+
+    Vector<UnderlinedCharacterRun>::Iterator      it    = underlinedCharacterRuns.Begin() + 1;
+    Vector<UnderlinedCharacterRun>::ConstIterator endIt = underlinedCharacterRuns.End();
+
+    while(it != endIt)
+    {
+      const UnderlinedCharacterRun& run                = *it;
+      const CharacterIndex&         characterIndex     = run.characterRun.characterIndex;
+      const Length&                 numberOfCharacters = run.characterRun.numberOfCharacters;
+
+      const UnderlinedCharacterRun& preRun                = *preIt;
+      const CharacterIndex&         preCharacterIndex     = preRun.characterRun.characterIndex;
+      const Length&                 preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
+
+      if((preCharacterIndex <= characterIndex) &&
+         ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
+      {
+        it->properties.CopyIfNotDefined(preIt->properties);
+      }
+
+      it++;
+      preIt++;
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor-underline.h b/dali-toolkit/internal/text/markup-processor/markup-processor-underline.h
new file mode 100644 (file)
index 0000000..cde347c
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/underlined-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+struct Tag;
+struct Attribute;
+
+/**
+ * @brief Fill the underlined character run with the type attribute value.
+ *
+ * @param[in] attribute the type attribute.
+ * @param[out] underlinedCharacterRun The underlined character run
+ */
+void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Fill the underlined character run with the dash-gap attribute value.
+ *
+ * @param[in] attribute the dash-gap attribute.
+ * @param[out] underlinedCharacterRun The underlined character run
+ */
+void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Fill the underlined character run with the dash-width attribute value.
+ *
+ * @param[in] attribute the dash-width attribute.
+ * @param[out] underlinedCharacterRun The underlined character run
+ */
+void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Fill the underlined character run with the height attribute value.
+ *
+ * @param[in] attribute the height attribute.
+ * @param[out] underlinedCharacterRun The underlined character run
+ */
+void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Fill the underlined character run with the color attribute value.
+ *
+ * @param[in] attribute the color attribute.
+ * @param[out] underlinedCharacterRun The underlined character run
+ */
+void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Retrieves the underline run info from the tag and sets it to the underline run.
+ *
+ * @param[in] tag The underline tag and its attributes.
+ * @param[in,out] underlinedCharacterRun The underlined character run
+ */
+void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun);
+
+/**
+ * @brief Override the run's attributes which contained in the previous run. This is to handle the nested tags.
+ *
+ * @param[in,out] underlinedCharacterRuns The list of underlined character run
+ */
+void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_UNDERLINE_H
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor/markup-processor.cpp
new file mode 100644 (file)
index 0000000..b19cdb1
--- /dev/null
@@ -0,0 +1,1232 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor/markup-processor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <climits> // for ULONG_MAX
+#include <functional>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-anchor.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-background.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-character-spacing.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-color.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-embedded-item.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-font.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-paragraph.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-span.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-strikethrough.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-underline.h>
+#include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
+#include <dali-toolkit/internal/text/xhtml-entities.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+namespace
+{
+const char LESS_THAN      = '<';
+const char GREATER_THAN   = '>';
+const char EQUAL          = '=';
+const char QUOTATION_MARK = '\'';
+const char SLASH          = '/';
+const char BACK_SLASH     = '\\';
+const char AMPERSAND      = '&';
+const char HASH           = '#';
+const char SEMI_COLON     = ';';
+const char CHAR_ARRAY_END = '\0';
+const char HEX_CODE       = 'x';
+
+const char WHITE_SPACE = 0x20; // ASCII value of the white space.
+const char NEW_LINE    = 0x0A; // ASCII value of the newline.
+
+// Range 1 0x0u < XHTML_DECIMAL_ENTITY_RANGE <= 0xD7FFu
+// Range 2 0xE000u < XHTML_DECIMAL_ENTITY_RANGE <= 0xFFFDu
+// Range 3 0x10000u < XHTML_DECIMAL_ENTITY_RANGE <= 0x10FFFFu
+const unsigned long XHTML_DECIMAL_ENTITY_RANGE[] = {0x0u, 0xD7FFu, 0xE000u, 0xFFFDu, 0x10000u, 0x10FFFFu};
+
+// The MAX_NUM_OF_ATTRIBUTES is the number of attributes in span tag "markup-processor-span.cpp". Because it contains the maximum number of attributes in  all tags.
+const unsigned int MAX_NUM_OF_ATTRIBUTES = 14u; ///< The span tag has the 'font-family', 'font-size' 'font-weight', 'font-width', 'font-slant','text-color', 'u-color', 'u-height','u-type','u-dash-gap', 'u-dash-width', 's-color', 's-height' and 'char-space-value' attrubutes.
+const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MARKUP_PROCESSOR");
+#endif
+
+typedef VectorBase::SizeType RunIndex;
+
+/**
+ * @brief Struct used to retrieve the style runs from the mark-up string.
+ */
+template<typename StyleStackType>
+struct StyleStack
+{
+  Vector<StyleStackType> stack;    ///< Use a vector as a style stack.
+  unsigned int           topIndex; ///< Points the top of the stack.
+
+  StyleStack()
+  : stack(),
+    topIndex(0u)
+  {
+    stack.Resize(DEFAULT_VECTOR_SIZE);
+  }
+
+  void Push(StyleStackType item)
+  {
+    // Check if there is space inside the style stack.
+    const VectorBase::SizeType size = stack.Count();
+    if(topIndex >= size)
+    {
+      // Resize the style stack.
+      stack.Resize(2u * size);
+    }
+
+    // Set the item in the top of the stack.
+    *(stack.Begin() + topIndex) = item;
+
+    // Reposition the pointer to the top of the stack.
+    ++topIndex;
+  }
+
+  StyleStackType Pop()
+  {
+    // Pop the top of the stack.
+    --topIndex;
+    return *(stack.Begin() + topIndex);
+  }
+};
+
+/**
+ * @brief Struct used to retrieve spans from the mark-up string.
+ */
+struct Span
+{
+  RunIndex colorRunIndex;
+  RunIndex fontRunIndex;
+  RunIndex underlinedCharacterRunIndex;
+  RunIndex backgroundColorRunIndex;
+  RunIndex strikethroughCharacterRunIndex;
+  RunIndex characterSpacingCharacterRunIndex;
+
+  bool isColorDefined;
+  bool isFontDefined;
+  bool isUnderlinedCharacterDefined;
+  bool isBackgroundColorDefined;
+  bool isStrikethroughDefined;
+  bool isCharacterSpacingDefined;
+};
+
+/**
+ * @brief Initializes a font run description to its defaults.
+ *
+ * @param[in,out] fontRun The font description run to initialize.
+ */
+void Initialize(FontDescriptionRun& fontRun)
+{
+  fontRun.characterRun.characterIndex     = 0u;
+  fontRun.characterRun.numberOfCharacters = 0u;
+  fontRun.familyName                      = NULL;
+  fontRun.familyLength                    = 0u;
+  fontRun.weight                          = TextAbstraction::FontWeight::NORMAL;
+  fontRun.width                           = TextAbstraction::FontWidth::NORMAL;
+  fontRun.slant                           = TextAbstraction::FontSlant::NORMAL;
+  fontRun.size                            = 0u;
+  fontRun.familyDefined                   = false;
+  fontRun.weightDefined                   = false;
+  fontRun.widthDefined                    = false;
+  fontRun.slantDefined                    = false;
+  fontRun.sizeDefined                     = false;
+}
+
+/**
+ * @brief Initializes a color run description to its defaults.
+ *
+ * @param[in,out] colorRun The font description run to initialize.
+ */
+void Initialize(ColorRun& colorRun)
+{
+  colorRun.characterRun.characterIndex     = 0u;
+  colorRun.characterRun.numberOfCharacters = 0u;
+}
+
+/**
+ * @brief Initializes a underlined character run to its defaults.
+ *
+ * @param[in,out] underlinedCharacterRun The underelined character run to initialize.
+ */
+void Initialize(UnderlinedCharacterRun& underlinedCharacterRun)
+{
+  underlinedCharacterRun.characterRun.characterIndex     = 0u;
+  underlinedCharacterRun.characterRun.numberOfCharacters = 0u;
+}
+
+/**
+ * @brief Initializes a span to its defaults.
+ *
+ * @param[in,out] span The span to be initialized.
+ */
+void Initialize(Span& span)
+{
+  span.colorRunIndex  = 0u;
+  span.isColorDefined = false;
+
+  span.fontRunIndex  = 0u;
+  span.isFontDefined = false;
+
+  span.underlinedCharacterRunIndex  = 0u;
+  span.isUnderlinedCharacterDefined = false;
+  span.backgroundColorRunIndex      = 0u;
+  span.isBackgroundColorDefined     = false;
+
+  //strikethrough
+  span.strikethroughCharacterRunIndex = 0u;
+  span.isStrikethroughDefined         = false;
+
+  //characterSpacing
+  span.characterSpacingCharacterRunIndex = 0u;
+  span.isCharacterSpacingDefined         = false;
+}
+
+/**
+ * @brief Initializes a strikethrough character run to its defaults.
+ *
+ * @param[in,out] strikethroughCharacterRun The strikethrough character run to initialize.
+ */
+void Initialize(StrikethroughCharacterRun& strikethroughCharacterRun)
+{
+  strikethroughCharacterRun.characterRun.characterIndex     = 0u;
+  strikethroughCharacterRun.characterRun.numberOfCharacters = 0u;
+  strikethroughCharacterRun.properties.colorDefined         = false;
+}
+
+/**
+ * @brief Initializes a  bounded-paragraph character run to its defaults.
+ *
+ * @param[in,out] boundedParagraphRun The bounded paragraphRun run to initialize.
+ */
+void Initialize(BoundedParagraphRun& boundedParagraphRun)
+{
+  boundedParagraphRun.characterRun.characterIndex     = 0u;
+  boundedParagraphRun.characterRun.numberOfCharacters = 0u;
+}
+
+/**
+ * @brief Initializes a character-spacing run to its defaults.
+ *
+ * @param[in,out] characterSpacingCharacterRun The character-spacing run to initialize.
+ */
+void Initialize(CharacterSpacingCharacterRun& characterSpacingCharacterRun)
+{
+  characterSpacingCharacterRun.characterRun.characterIndex     = 0u;
+  characterSpacingCharacterRun.characterRun.numberOfCharacters = 0u;
+  characterSpacingCharacterRun.value                           = 0.0f;
+}
+
+/**
+ * @brief Splits the tag string into the tag name and its attributes.
+ *
+ * The attributes are stored in a vector in the tag.
+ *
+ * @param[in,out] tag The tag.
+ */
+void ParseAttributes(Tag& tag)
+{
+  if(tag.buffer == NULL)
+  {
+    return;
+  }
+
+  tag.attributes.Resize(MAX_NUM_OF_ATTRIBUTES);
+
+  // Find first the tag name.
+  bool isQuotationOpen = false;
+
+  const char*       tagBuffer    = tag.buffer;
+  const char* const tagEndBuffer = tagBuffer + tag.length;
+  tag.length                     = 0u;
+  for(; tagBuffer < tagEndBuffer; ++tagBuffer)
+  {
+    const char character = *tagBuffer;
+    if(WHITE_SPACE < character)
+    {
+      ++tag.length;
+    }
+    else
+    {
+      // Stops counting the length of the tag when a white space is found.
+      // @note a white space is the WHITE_SPACE character and anything below as 'tab', 'return' or 'control characters'.
+      break;
+    }
+  }
+  SkipWhiteSpace(tagBuffer, tagEndBuffer);
+
+  // Find the attributes.
+  unsigned int attributeIndex = 0u;
+  const char*  nameBuffer     = NULL;
+  const char*  valueBuffer    = NULL;
+  Length       nameLength     = 0u;
+  Length       valueLength    = 0u;
+
+  bool   addToNameValue     = true;
+  Length numberOfWhiteSpace = 0u;
+  for(; tagBuffer < tagEndBuffer; ++tagBuffer)
+  {
+    const char character = *tagBuffer;
+    if((WHITE_SPACE >= character) && !isQuotationOpen)
+    {
+      if(NULL != valueBuffer)
+      {
+        // Remove white spaces at the end of the value.
+        valueLength -= numberOfWhiteSpace;
+      }
+
+      if((NULL != nameBuffer) && (NULL != valueBuffer))
+      {
+        // Every time a white space is found, a new attribute is created and stored in the attributes vector.
+        Attribute& attribute = *(tag.attributes.Begin() + attributeIndex);
+        ++attributeIndex;
+
+        attribute.nameBuffer  = nameBuffer;
+        attribute.valueBuffer = valueBuffer;
+        attribute.nameLength  = nameLength;
+        attribute.valueLength = valueLength;
+
+        nameBuffer  = NULL;
+        valueBuffer = NULL;
+        nameLength  = 0u;
+        valueLength = 0u;
+
+        addToNameValue = true; // next read characters will be added to the name.
+      }
+    }
+    else if(EQUAL == character) // '='
+    {
+      addToNameValue = false; // next read characters will be added to the value.
+      SkipWhiteSpace(tagBuffer, tagEndBuffer);
+    }
+    else if(QUOTATION_MARK == character) // '\''
+    {
+      // Do not add quotation marks to neither name nor value.
+      isQuotationOpen = !isQuotationOpen;
+
+      if(isQuotationOpen)
+      {
+        ++tagBuffer;
+        SkipWhiteSpace(tagBuffer, tagEndBuffer);
+        --tagBuffer;
+      }
+    }
+    else
+    {
+      // Adds characters to the name or the value.
+      if(addToNameValue)
+      {
+        if(NULL == nameBuffer)
+        {
+          nameBuffer = tagBuffer;
+        }
+        ++nameLength;
+      }
+      else
+      {
+        if(isQuotationOpen)
+        {
+          if(WHITE_SPACE >= character)
+          {
+            ++numberOfWhiteSpace;
+          }
+          else
+          {
+            numberOfWhiteSpace = 0u;
+          }
+        }
+        if(NULL == valueBuffer)
+        {
+          valueBuffer = tagBuffer;
+        }
+        ++valueLength;
+      }
+    }
+  }
+
+  if(NULL != valueBuffer)
+  {
+    // Remove white spaces at the end of the value.
+    valueLength -= numberOfWhiteSpace;
+  }
+
+  if((NULL != nameBuffer) && (NULL != valueBuffer))
+  {
+    // Checks if the last attribute needs to be added.
+    Attribute& attribute = *(tag.attributes.Begin() + attributeIndex);
+    ++attributeIndex;
+
+    attribute.nameBuffer  = nameBuffer;
+    attribute.valueBuffer = valueBuffer;
+    attribute.nameLength  = nameLength;
+    attribute.valueLength = valueLength;
+  }
+
+  // Resize the vector of attributes.
+  tag.attributes.Resize(attributeIndex);
+}
+
+/**
+ * @brief It parses a tag and its attributes if the given iterator @e it is pointing at a tag beginning.
+ *
+ * @param[in,out] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
+ * @param[in] markupStringEndBuffer Pointer to one character after the end of the mark-up string buffer.
+ * @param[out] tag The tag with its attributes.
+ *
+ * @return @e true if the iterator @e it is pointing a mark-up tag. Otherwise @e false.
+ */
+bool IsTag(const char*&      markupStringBuffer,
+           const char* const markupStringEndBuffer,
+           Tag&              tag)
+{
+  bool isTag              = false;
+  bool isQuotationOpen    = false;
+  bool attributesFound    = false;
+  tag.isEndTag            = false;
+  bool isPreviousLessThan = false;
+  bool isPreviousSlash    = false;
+
+  const char character = *markupStringBuffer;
+  if(LESS_THAN == character) // '<'
+  {
+    tag.buffer         = NULL;
+    tag.length         = 0u;
+    isPreviousLessThan = true;
+
+    // if the iterator is pointing to a '<' character, then check if it's a mark-up tag is needed.
+    ++markupStringBuffer;
+    if(markupStringBuffer < markupStringEndBuffer)
+    {
+      SkipWhiteSpace(markupStringBuffer, markupStringEndBuffer);
+
+      for(; (!isTag) && (markupStringBuffer < markupStringEndBuffer); ++markupStringBuffer)
+      {
+        const char character = *markupStringBuffer;
+
+        if(!isQuotationOpen && (SLASH == character)) // '/'
+        {
+          if(isPreviousLessThan)
+          {
+            tag.isEndTag = true;
+          }
+          else
+          {
+            // if the tag has a '/' it may be an end tag.
+            isPreviousSlash = true;
+          }
+
+          isPreviousLessThan = false;
+          if((markupStringBuffer + 1u < markupStringEndBuffer) && (WHITE_SPACE >= *(markupStringBuffer + 1u)))
+          {
+            ++markupStringBuffer;
+            SkipWhiteSpace(markupStringBuffer, markupStringEndBuffer);
+            --markupStringBuffer;
+          }
+        }
+        else if(GREATER_THAN == character) // '>'
+        {
+          isTag = true;
+          if(isPreviousSlash)
+          {
+            tag.isEndTag = true;
+          }
+
+          isPreviousSlash    = false;
+          isPreviousLessThan = false;
+        }
+        else if(QUOTATION_MARK == character)
+        {
+          isQuotationOpen = !isQuotationOpen;
+          ++tag.length;
+
+          isPreviousSlash    = false;
+          isPreviousLessThan = false;
+        }
+        else if(WHITE_SPACE >= character) // ' '
+        {
+          // If the tag contains white spaces then it may have attributes.
+          if(!isQuotationOpen)
+          {
+            attributesFound = true;
+          }
+          ++tag.length;
+        }
+        else
+        {
+          if(NULL == tag.buffer)
+          {
+            tag.buffer = markupStringBuffer;
+          }
+
+          // If it's not any of the 'special' characters then just add it to the tag string.
+          ++tag.length;
+
+          isPreviousSlash    = false;
+          isPreviousLessThan = false;
+        }
+      }
+    }
+
+    // If the tag string has white spaces, then parse the attributes is needed.
+    if(attributesFound)
+    {
+      ParseAttributes(tag);
+    }
+  }
+
+  return isTag;
+}
+
+/**
+ * @brief Returns length of XHTML entity by parsing the text. It also determines if it is XHTML entity or not.
+ *
+ * @param[in] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
+ * @param[in] markupStringEndBuffer Pointing to end of mark-up string buffer.
+ *
+ * @return Length of markupText in case of XHTML entity otherwise return 0.
+ */
+unsigned int GetXHTMLEntityLength(const char*&      markupStringBuffer,
+                                  const char* const markupStringEndBuffer)
+{
+  char character = *markupStringBuffer;
+  if(AMPERSAND == character) // '&'
+  {
+    // if the iterator is pointing to a '&' character, then check for ';' to find end to XHTML entity.
+    ++markupStringBuffer;
+    if(markupStringBuffer < markupStringEndBuffer)
+    {
+      unsigned int len = 1u;
+      for(; markupStringBuffer < markupStringEndBuffer; ++markupStringBuffer)
+      {
+        character = *markupStringBuffer;
+        ++len;
+        if(SEMI_COLON == character) // ';'
+        {
+          // found end of XHTML entity
+          ++markupStringBuffer;
+          return len;
+        }
+        else if((AMPERSAND == character) || (BACK_SLASH == character) || (LESS_THAN == character))
+        {
+          return 0;
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+/**
+ * @brief It parses a XHTML string which has hex/decimal entity and fill its corresponging utf-8 string.
+ *
+ * @param[in] markupText The mark-up text buffer.
+ * @param[out] utf-8 text Corresponding to markup Text
+ *
+ * @return true if string is successfully parsed otherwise false
+ */
+bool XHTMLNumericEntityToUtf8(const char* markupText, char* utf8)
+{
+  bool result = false;
+
+  if(NULL != markupText)
+  {
+    bool isHex = false;
+
+    // check if hex or decimal entity
+    if((CHAR_ARRAY_END != *markupText) && (HEX_CODE == *markupText))
+    {
+      isHex = true;
+      ++markupText;
+    }
+
+    char*         end = NULL;
+    unsigned long l   = strtoul(markupText, &end, (isHex ? 16 : 10)); // l contains UTF-32 code in case of correct XHTML entity
+
+    // check for valid XHTML numeric entities (between '#' or "#x" and ';')
+    if((l > 0) && (l < ULONG_MAX) && (*end == SEMI_COLON)) // in case wrong XHTML entity is set eg. "&#23abcdefs;" in that case *end will be 'a'
+    {
+      /* characters XML 1.1 permits */
+      if(((XHTML_DECIMAL_ENTITY_RANGE[0] < l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[1])) ||
+         ((XHTML_DECIMAL_ENTITY_RANGE[2] <= l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[3])) ||
+         ((XHTML_DECIMAL_ENTITY_RANGE[4] <= l) && (l <= XHTML_DECIMAL_ENTITY_RANGE[5])))
+      {
+        // Convert UTF32 code to UTF8
+        Utf32ToUtf8(reinterpret_cast<const uint32_t* const>(&l), 1, reinterpret_cast<uint8_t*>(utf8));
+        result = true;
+      }
+    }
+  }
+  return result;
+}
+
+/**
+ * @brief Processes a particular tag for the required run (color-run, font-run or underlined-character-run).
+ *
+ * @tparam RunType Whether ColorRun , FontDescriptionRun or UnderlinedCharacterRun
+ *
+ * @param[in/out] runsContainer The container containing all the runs
+ * @param[in/out] styleStack The style stack
+ * @param[in] tag The tag we are currently processing
+ * @param[in] characterIndex The current character index
+ * @param[in/out] runIndex The run index
+ * @param[in/out] tagReference The tagReference we should increment/decrement
+ * @param[in] parameterSettingFunction This function will be called to set run specific parameters
+ */
+template<typename RunType>
+void ProcessTagForRun(
+  Vector<RunType>&                          runsContainer,
+  StyleStack<RunIndex>&                     styleStack,
+  const Tag&                                tag,
+  const CharacterIndex                      characterIndex,
+  RunIndex&                                 runIndex,
+  int&                                      tagReference,
+  std::function<void(const Tag&, RunType&)> parameterSettingFunction)
+{
+  if(!tag.isEndTag)
+  {
+    // Create a new run.
+    RunType run;
+    Initialize(run);
+
+    // Fill the run with the parameters.
+    run.characterRun.characterIndex = characterIndex;
+    parameterSettingFunction(tag, run);
+
+    // Push the run in the logical model.
+    runsContainer.PushBack(run);
+
+    // Push the index of the run into the stack.
+    styleStack.Push(runIndex);
+
+    // Point the next free run.
+    ++runIndex;
+
+    // Increase reference
+    ++tagReference;
+  }
+  else
+  {
+    if(tagReference > 0)
+    {
+      // Pop the top of the stack and set the number of characters of the run.
+      RunType& run                        = *(runsContainer.Begin() + styleStack.Pop());
+      run.characterRun.numberOfCharacters = characterIndex - run.characterRun.characterIndex;
+      --tagReference;
+    }
+  }
+}
+
+/**
+ * @brief Processes the item tag
+ *
+ * @param[in/out] markupProcessData The markup process data
+ * @param[in] tag The current tag
+ * @param[in/out] characterIndex The current character index
+ */
+void ProcessItemTag(
+  MarkupProcessData& markupProcessData,
+  const Tag          tag,
+  CharacterIndex&    characterIndex)
+{
+  if(tag.isEndTag)
+  {
+    // Create an embedded item instance.
+    EmbeddedItem item;
+    item.characterIndex = characterIndex;
+    ProcessEmbeddedItem(tag, item);
+
+    markupProcessData.items.PushBack(item);
+
+    // Insert white space character that will be replaced by the item.
+    markupProcessData.markupProcessedText.append(1u, WHITE_SPACE);
+    ++characterIndex;
+  }
+}
+
+/**
+ * @brief Processes the paragraph-tag
+ *
+ * @param[in/out] markupProcessData The markup process data
+ * @param[in] tag The current tag
+ * @param[in] isEndBuffer Whether the end of buffer
+ * @param[in/out] characterIndex The current character index
+ */
+void ProcessParagraphTag(
+  MarkupProcessData& markupProcessData,
+  const Tag          tag,
+  bool               isEndBuffer,
+  CharacterIndex&    characterIndex)
+{
+  if((characterIndex > 0 &&
+      markupProcessData.markupProcessedText[characterIndex - 1u] != NEW_LINE) &&
+     (!(tag.isEndTag && isEndBuffer)))
+  {
+    // Insert new-line character at the start and end of paragraph.
+    markupProcessData.markupProcessedText.append(1u, NEW_LINE);
+    ++characterIndex;
+  }
+}
+
+/**
+ * @brief Processes the anchor tag
+ *
+ * @param[in/out] markupProcessData The markup process data
+ * @param[in] tag The current tag
+ * @param[in/out] characterIndex The current character index
+ */
+void ProcessAnchorTag(
+  MarkupProcessData& markupProcessData,
+  const Tag          tag,
+  CharacterIndex&    characterIndex)
+{
+  if(!tag.isEndTag)
+  {
+    // Create an anchor instance.
+    Anchor anchor;
+    anchor.startIndex = characterIndex;
+    anchor.endIndex   = 0u;
+    ProcessAnchor(tag, anchor);
+    markupProcessData.anchors.PushBack(anchor);
+  }
+  else
+  {
+    // Update end index.
+    unsigned int count = markupProcessData.anchors.Count();
+    if(count > 0)
+    {
+      markupProcessData.anchors[count - 1].endIndex = characterIndex;
+    }
+  }
+}
+
+/**
+ * @brief Processes span tag for the color-run & font-run.
+ *
+ * @param[in] spanTag The tag we are currently processing
+ * @param[inout] spanStack The spans stack
+ * @param[inout] colorRuns The container containing all the color runs
+ * @param[inout] fontRuns The container containing all the font description runs
+ * @param[inout] underlinedCharacterRuns The container containing all the underlined character runs
+ * @param[inout] strikethroughCharacterRuns The container containing all the strikethroughed character runs
+ * @param[inout] colorRunIndex The color run index
+ * @param[inout] fontRunIndex The font run index
+ * @param[inout] underlinedCharacterRunIndex The underlined character run index
+ * @param[inout] strikethroughCharacterRunIndex The strikethroughed character run index
+ * @param[in] characterIndex The current character index
+ * @param[in] tagReference The tagReference we should increment/decrement
+ */
+void ProcessSpanForRun(
+  const Tag&                            spanTag,
+  StyleStack<Span>&                     spanStack,
+  Vector<ColorRun>&                     colorRuns,
+  Vector<FontDescriptionRun>&           fontRuns,
+  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
+  Vector<ColorRun>&                     backgroundColorRuns,
+  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
+  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns,
+  RunIndex&                             colorRunIndex,
+  RunIndex&                             fontRunIndex,
+  RunIndex&                             underlinedCharacterRunIndex,
+  RunIndex&                             backgroundColorRunIndex,
+  RunIndex&                             strikethroughCharacterRunIndex,
+  RunIndex&                             characterSpacingCharacterRunIndex,
+  const CharacterIndex                  characterIndex,
+  int&                                  tagReference)
+{
+  if(!spanTag.isEndTag)
+  {
+    // Create a new run.
+    ColorRun colorRun;
+    Initialize(colorRun);
+
+    FontDescriptionRun fontRun;
+    Initialize(fontRun);
+
+    UnderlinedCharacterRun underlinedCharacterRun;
+    Initialize(underlinedCharacterRun);
+
+    ColorRun backgroundColorRun;
+    Initialize(backgroundColorRun);
+
+    StrikethroughCharacterRun strikethroughCharacterRun;
+    Initialize(strikethroughCharacterRun);
+
+    CharacterSpacingCharacterRun characterSpacingCharacterRun;
+    Initialize(characterSpacingCharacterRun);
+
+    Span span;
+    Initialize(span);
+
+    // Fill the run with the parameters.
+    colorRun.characterRun.characterIndex                     = characterIndex;
+    fontRun.characterRun.characterIndex                      = characterIndex;
+    underlinedCharacterRun.characterRun.characterIndex       = characterIndex;
+    backgroundColorRun.characterRun.characterIndex           = characterIndex;
+    strikethroughCharacterRun.characterRun.characterIndex    = characterIndex;
+    characterSpacingCharacterRun.characterRun.characterIndex = characterIndex;
+
+    span.colorRunIndex                     = colorRunIndex;
+    span.fontRunIndex                      = fontRunIndex;
+    span.underlinedCharacterRunIndex       = underlinedCharacterRunIndex;
+    span.backgroundColorRunIndex           = backgroundColorRunIndex;
+    span.strikethroughCharacterRunIndex    = strikethroughCharacterRunIndex;
+    span.characterSpacingCharacterRunIndex = characterSpacingCharacterRunIndex;
+
+    ProcessSpanTag(spanTag,
+                   colorRun,
+                   fontRun,
+                   underlinedCharacterRun,
+                   backgroundColorRun,
+                   strikethroughCharacterRun,
+                   characterSpacingCharacterRun,
+                   span.isColorDefined,
+                   span.isFontDefined,
+                   span.isUnderlinedCharacterDefined,
+                   span.isBackgroundColorDefined,
+                   span.isStrikethroughDefined,
+                   span.isCharacterSpacingDefined);
+
+    // Push the span into the stack.
+    spanStack.Push(span);
+
+    // Point the next free run.
+    if(span.isColorDefined)
+    {
+      // Push the run in the logical model.
+      colorRuns.PushBack(colorRun);
+      ++colorRunIndex;
+    }
+
+    if(span.isFontDefined)
+    {
+      // Push the run in the logical model.
+      fontRuns.PushBack(fontRun);
+      ++fontRunIndex;
+    }
+
+    if(span.isUnderlinedCharacterDefined)
+    {
+      // Push the run in the logical model.
+      underlinedCharacterRuns.PushBack(underlinedCharacterRun);
+      ++underlinedCharacterRunIndex;
+    }
+
+    if(span.isBackgroundColorDefined)
+    {
+      // Push the run in the logical model.
+      backgroundColorRuns.PushBack(backgroundColorRun);
+      ++backgroundColorRunIndex;
+    }
+
+    if(span.isStrikethroughDefined)
+    {
+      // Push the run in the logical model.
+      strikethroughCharacterRuns.PushBack(strikethroughCharacterRun);
+      ++strikethroughCharacterRunIndex;
+    }
+
+    if(span.isCharacterSpacingDefined)
+    {
+      // Push the run in the logical model.
+      characterSpacingCharacterRuns.PushBack(characterSpacingCharacterRun);
+      ++characterSpacingCharacterRunIndex;
+    }
+
+    // Increase reference
+    ++tagReference;
+  }
+  else
+  {
+    if(tagReference > 0)
+    {
+      // Pop the top of the stack and set the number of characters of the run.
+      Span span = spanStack.Pop();
+
+      if(span.isColorDefined)
+      {
+        ColorRun& colorRun                       = *(colorRuns.Begin() + span.colorRunIndex);
+        colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex;
+      }
+
+      if(span.isFontDefined)
+      {
+        FontDescriptionRun& fontRun             = *(fontRuns.Begin() + span.fontRunIndex);
+        fontRun.characterRun.numberOfCharacters = characterIndex - fontRun.characterRun.characterIndex;
+      }
+
+      if(span.isUnderlinedCharacterDefined)
+      {
+        UnderlinedCharacterRun& underlinedCharacterRun         = *(underlinedCharacterRuns.Begin() + span.underlinedCharacterRunIndex);
+        underlinedCharacterRun.characterRun.numberOfCharacters = characterIndex - underlinedCharacterRun.characterRun.characterIndex;
+      }
+
+      if(span.isBackgroundColorDefined)
+      {
+        ColorRun& backgroundColorRun                       = *(backgroundColorRuns.Begin() + span.backgroundColorRunIndex);
+        backgroundColorRun.characterRun.numberOfCharacters = characterIndex - backgroundColorRun.characterRun.characterIndex;
+      }
+
+      if(span.isStrikethroughDefined)
+      {
+        StrikethroughCharacterRun& strikethroughCharacterRun      = *(strikethroughCharacterRuns.Begin() + span.strikethroughCharacterRunIndex);
+        strikethroughCharacterRun.characterRun.numberOfCharacters = characterIndex - strikethroughCharacterRun.characterRun.characterIndex;
+      }
+
+      if(span.isCharacterSpacingDefined)
+      {
+        CharacterSpacingCharacterRun& characterSpacingCharacterRun   = *(characterSpacingCharacterRuns.Begin() + span.characterSpacingCharacterRunIndex);
+        characterSpacingCharacterRun.characterRun.numberOfCharacters = characterIndex - characterSpacingCharacterRun.characterRun.characterIndex;
+      }
+
+      --tagReference;
+    }
+  }
+}
+
+/**
+ * @brief Resizes the model's vectors
+ *
+ * @param[inout] markupProcessData The markup process data
+ * @param[in] fontRunIndex The font run index
+ * @param[in] colorRunIndex The color run index
+ * @param[in] underlinedCharacterRunIndex The underlined character run index
+ * @param[in] strikethroughCharacterRunIndex The strikethroughed character run index
+ * @param[in] backgroundRunIndex The background run index
+ * @param[in] boundedParagraphRunIndex The bounded paragraph run index
+ * @param[in] characterSpacingCharacterRunIndex The character-spacing character run index
+ *
+ */
+void ResizeModelVectors(MarkupProcessData& markupProcessData,
+                        const RunIndex     fontRunIndex,
+                        const RunIndex     colorRunIndex,
+                        const RunIndex     underlinedCharacterRunIndex,
+                        const RunIndex     strikethroughCharacterRunIndex,
+                        const RunIndex     backgroundRunIndex,
+                        const RunIndex     boundedParagraphRunIndex,
+                        const RunIndex     characterSpacingCharacterRunIndex)
+{
+  markupProcessData.fontRuns.Resize(fontRunIndex);
+  markupProcessData.colorRuns.Resize(colorRunIndex);
+  markupProcessData.underlinedCharacterRuns.Resize(underlinedCharacterRunIndex);
+  markupProcessData.strikethroughCharacterRuns.Resize(strikethroughCharacterRunIndex);
+  markupProcessData.backgroundColorRuns.Resize(backgroundRunIndex);
+  markupProcessData.boundedParagraphRuns.Resize(boundedParagraphRunIndex);
+  markupProcessData.characterSpacingCharacterRuns.Resize(characterSpacingCharacterRunIndex);
+
+#ifdef DEBUG_ENABLED
+  if(gLogFilter->IsEnabledFor(Debug::Verbose))
+  {
+    for(uint32_t i = 0; i < colorRunIndex; ++i)
+    {
+      ColorRun& run = markupProcessData.colorRuns[i];
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "run[%d] index: %d, length: %d, color %f,%f,%f,%f\n", i, run.characterRun.characterIndex, run.characterRun.numberOfCharacters, run.color.r, run.color.g, run.color.b, run.color.a);
+    }
+  }
+#endif
+}
+
+/**
+ * @brief Processes the markup string buffer
+ *
+ * @param[in/out] markupProcessData The markup process data
+ * @param[in/out] markupStringBuffer The markup string buffer pointer
+ * @param[in] markupStringEndBuffer The markup string end buffer pointer
+ * @param[in/out] characterIndex The current character index
+ */
+void ProcessMarkupStringBuffer(
+  MarkupProcessData& markupProcessData,
+  const char*&       markupStringBuffer,
+  const char* const  markupStringEndBuffer,
+  CharacterIndex&    characterIndex)
+{
+  unsigned char character    = *markupStringBuffer;
+  const char*   markupBuffer = markupStringBuffer;
+  unsigned char count        = GetUtf8Length(character);
+  char          utf8[8];
+
+  if((BACK_SLASH == character) && (markupStringBuffer + 1u < markupStringEndBuffer))
+  {
+    // Adding < , >  or & special character.
+    const unsigned char nextCharacter = *(markupStringBuffer + 1u);
+    if((LESS_THAN == nextCharacter) || (GREATER_THAN == nextCharacter) || (AMPERSAND == nextCharacter))
+    {
+      character = nextCharacter;
+      ++markupStringBuffer;
+
+      count        = GetUtf8Length(character);
+      markupBuffer = markupStringBuffer;
+    }
+  }
+  else // checking if contains XHTML entity or not
+  {
+    const unsigned int len = GetXHTMLEntityLength(markupStringBuffer, markupStringEndBuffer);
+
+    // Parse markupStringTxt if it contains XHTML Entity between '&' and ';'
+    if(len > 0)
+    {
+      char* entityCode = NULL;
+      bool  result     = false;
+      count            = 0;
+
+      // Checking if XHTML Numeric Entity
+      if(HASH == *(markupBuffer + 1u))
+      {
+        entityCode = &utf8[0];
+        // markupBuffer is currently pointing to '&'. By adding 2u to markupBuffer it will point to numeric string by skipping "&#'
+        result = XHTMLNumericEntityToUtf8((markupBuffer + 2u), entityCode);
+      }
+      else // Checking if XHTML Named Entity
+      {
+        entityCode = const_cast<char*>(NamedEntityToUtf8(markupBuffer, len));
+        result     = (entityCode != NULL);
+      }
+      if(result)
+      {
+        markupBuffer = entityCode; //utf8 text assigned to markupBuffer
+        character    = markupBuffer[0];
+      }
+      else
+      {
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Not valid XHTML entity : (%.*s) \n", len, markupBuffer);
+        markupBuffer = NULL;
+      }
+    }
+    else // in case string conatins Start of XHTML Entity('&') but not its end character(';')
+    {
+      if(character == AMPERSAND)
+      {
+        markupBuffer = NULL;
+        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Not Well formed XHTML content \n");
+      }
+    }
+  }
+
+  if(markupBuffer != NULL)
+  {
+    const unsigned char numberOfBytes = GetUtf8Length(character);
+    markupProcessData.markupProcessedText.push_back(character);
+
+    for(unsigned char i = 1u; i < numberOfBytes; ++i)
+    {
+      ++markupBuffer;
+      markupProcessData.markupProcessedText.push_back(*markupBuffer);
+    }
+
+    ++characterIndex;
+    markupStringBuffer += count;
+  }
+}
+
+} // namespace
+
+void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData)
+{
+  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "markupString: %s\n", markupString.c_str());
+
+  // Reserve space for the plain text.
+  const Length markupStringSize = markupString.size();
+  markupProcessData.markupProcessedText.reserve(markupStringSize);
+
+  // Stores a struct with the index to the first character of the run, the type of run and its parameters.
+  StyleStack<RunIndex> styleStack;
+
+  // Stores a struct with the index to the first character of the color run & color font for the span.
+  StyleStack<Span> spanStack;
+
+  // Points the next free position in the vector of runs.
+  RunIndex colorRunIndex                     = 0u;
+  RunIndex fontRunIndex                      = 0u;
+  RunIndex underlinedCharacterRunIndex       = 0u;
+  RunIndex backgroundRunIndex                = 0u;
+  RunIndex strikethroughCharacterRunIndex    = 0u;
+  RunIndex boundedParagraphRunIndex          = 0u;
+  RunIndex characterSpacingCharacterRunIndex = 0u;
+
+  // check tag reference
+  int colorTagReference            = 0u;
+  int fontTagReference             = 0u;
+  int iTagReference                = 0u;
+  int bTagReference                = 0u;
+  int uTagReference                = 0u;
+  int backgroundTagReference       = 0u;
+  int spanTagReference             = 0u;
+  int sTagReference                = 0u;
+  int pTagReference                = 0u;
+  int characterSpacingTagReference = 0u;
+
+  // Give an initial default value to the model's vectors.
+  markupProcessData.colorRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.fontRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.underlinedCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.backgroundColorRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.strikethroughCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+  markupProcessData.characterSpacingCharacterRuns.Reserve(DEFAULT_VECTOR_SIZE);
+
+  // Get the mark-up string buffer.
+  const char*       markupStringBuffer    = markupString.c_str();
+  const char* const markupStringEndBuffer = markupStringBuffer + markupStringSize;
+
+  Tag            tag;
+  CharacterIndex characterIndex = 0u;
+  for(; markupStringBuffer < markupStringEndBuffer;)
+  {
+    tag.attributes.Clear();
+    if(IsTag(markupStringBuffer,
+             markupStringEndBuffer,
+             tag))
+    {
+      if(TokenComparison(MARKUP::TAG::COLOR, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<ColorRun>(
+          markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) { ProcessColorTag(tag, run); });
+      } // <color></color>
+      else if(TokenComparison(MARKUP::TAG::ITALIC, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<FontDescriptionRun>(
+          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, iTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
+            fontRun.slant        = TextAbstraction::FontSlant::ITALIC;
+            fontRun.slantDefined = true;
+          });
+      } // <i></i>
+      else if(TokenComparison(MARKUP::TAG::UNDERLINE, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<UnderlinedCharacterRun>(
+          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) { ProcessUnderlineTag(tag, run); });
+      } // <u></u>
+      else if(TokenComparison(MARKUP::TAG::BOLD, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<FontDescriptionRun>(
+          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, bTagReference, [](const Tag&, FontDescriptionRun& fontRun) {
+            fontRun.weight        = TextAbstraction::FontWeight::BOLD;
+            fontRun.weightDefined = true;
+          });
+      } // <b></b>
+      else if(TokenComparison(MARKUP::TAG::FONT, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<FontDescriptionRun>(
+          markupProcessData.fontRuns, styleStack, tag, characterIndex, fontRunIndex, fontTagReference, [](const Tag& tag, FontDescriptionRun& fontRun) { ProcessFontTag(tag, fontRun); });
+      } // <font></font>
+      else if(TokenComparison(MARKUP::TAG::ANCHOR, tag.buffer, tag.length))
+      {
+        /* Anchor */
+        ProcessAnchorTag(markupProcessData, tag, characterIndex);
+        /* Color */
+        ProcessTagForRun<ColorRun>(
+          markupProcessData.colorRuns, styleStack, tag, characterIndex, colorRunIndex, colorTagReference, [](const Tag& tag, ColorRun& run) {
+            run.color = Color::BLUE;
+            ProcessColorTag(tag, run);
+          });
+        /* Underline */
+        ProcessTagForRun<UnderlinedCharacterRun>(
+          markupProcessData.underlinedCharacterRuns, styleStack, tag, characterIndex, underlinedCharacterRunIndex, uTagReference, [](const Tag& tag, UnderlinedCharacterRun& run) {
+            run.properties.color        = Color::BLUE;
+            run.properties.colorDefined = true;
+            ProcessUnderlineTag(tag, run);
+          });
+      } // <a href=https://www.tizen.org>tizen</a>
+      else if(TokenComparison(MARKUP::TAG::SHADOW, tag.buffer, tag.length))
+      {
+        // TODO: If !tag.isEndTag, then create a new shadow run.
+        //       else Pop the top of the stack and set the number of characters of the run.
+      } // <shadow></shadow>
+      else if(TokenComparison(MARKUP::TAG::GLOW, tag.buffer, tag.length))
+      {
+        // TODO: If !tag.isEndTag, then create a new glow run.
+        //       else Pop the top of the stack and set the number of characters of the run.
+      } // <glow></glow>
+      else if(TokenComparison(MARKUP::TAG::OUTLINE, tag.buffer, tag.length))
+      {
+        // TODO: If !tag.isEndTag, then create a new outline run.
+        //       else Pop the top of the stack and set the number of characters of the run.
+      } // <outline></outline>
+      else if(TokenComparison(MARKUP::TAG::EMBEDDED_ITEM, tag.buffer, tag.length))
+      {
+        ProcessItemTag(markupProcessData, tag, characterIndex);
+      }
+      else if(TokenComparison(MARKUP::TAG::BACKGROUND, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<ColorRun>(
+          markupProcessData.backgroundColorRuns, styleStack, tag, characterIndex, backgroundRunIndex, backgroundTagReference, [](const Tag& tag, ColorRun& run) { ProcessBackground(tag, run); });
+      }
+      else if(TokenComparison(MARKUP::TAG::SPAN, tag.buffer, tag.length))
+      {
+        ProcessSpanForRun(tag,
+                          spanStack,
+                          markupProcessData.colorRuns,
+                          markupProcessData.fontRuns,
+                          markupProcessData.underlinedCharacterRuns,
+                          markupProcessData.backgroundColorRuns,
+                          markupProcessData.strikethroughCharacterRuns,
+                          markupProcessData.characterSpacingCharacterRuns,
+                          colorRunIndex,
+                          fontRunIndex,
+                          underlinedCharacterRunIndex,
+                          backgroundRunIndex,
+                          strikethroughCharacterRunIndex,
+                          characterSpacingCharacterRunIndex,
+                          characterIndex,
+                          spanTagReference);
+      }
+      else if(TokenComparison(MARKUP::TAG::STRIKETHROUGH, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<StrikethroughCharacterRun>(
+          markupProcessData.strikethroughCharacterRuns, styleStack, tag, characterIndex, strikethroughCharacterRunIndex, sTagReference, [](const Tag& tag, StrikethroughCharacterRun& run) { ProcessStrikethroughTag(tag, run); });
+      } // <s></s>
+      else if(TokenComparison(MARKUP::TAG::PARAGRAPH, tag.buffer, tag.length))
+      {
+        ProcessParagraphTag(markupProcessData, tag, (markupStringBuffer == markupStringEndBuffer), characterIndex);
+        ProcessTagForRun<BoundedParagraphRun>(
+          markupProcessData.boundedParagraphRuns, styleStack, tag, characterIndex, boundedParagraphRunIndex, pTagReference, [](const Tag& tag, BoundedParagraphRun& run) { ProcessAttributesOfParagraphTag(tag, run); });
+      } // <p></p>
+      else if(TokenComparison(MARKUP::TAG::CHARACTER_SPACING, tag.buffer, tag.length))
+      {
+        ProcessTagForRun<CharacterSpacingCharacterRun>(
+          markupProcessData.characterSpacingCharacterRuns, styleStack, tag, characterIndex, characterSpacingCharacterRunIndex, characterSpacingTagReference, [](const Tag& tag, CharacterSpacingCharacterRun& run) { ProcessCharacterSpacingTag(tag, run); });
+      } // <char-spacing></char-spacing>
+    }   // end if( IsTag() )
+    else if(markupStringBuffer < markupStringEndBuffer)
+    {
+      ProcessMarkupStringBuffer(markupProcessData, markupStringBuffer, markupStringEndBuffer, characterIndex);
+    }
+  }
+
+  // Resize the model's vectors.
+  ResizeModelVectors(markupProcessData, fontRunIndex, colorRunIndex, underlinedCharacterRunIndex, strikethroughCharacterRunIndex, backgroundRunIndex, boundedParagraphRunIndex, characterSpacingCharacterRunIndex);
+
+  // Handle the nested tags
+  OverrideNestedUnderlinedCharacterRuns(markupProcessData.underlinedCharacterRuns);
+  OverrideNestedStrikethroughCharacterRuns(markupProcessData.strikethroughCharacterRuns);
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor/markup-processor.h b/dali-toolkit/internal/text/markup-processor/markup-processor.h
new file mode 100644 (file)
index 0000000..f751843
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
+#define DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/anchor.h>
+#include <dali-toolkit/internal/text/bounded-paragraph-run.h>
+#include <dali-toolkit/internal/text/character-spacing-character-run.h>
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/embedded-item.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/strikethrough-character-run.h>
+#include <dali-toolkit/internal/text/underlined-character-run.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Text
+{
+/**
+ * @brief Keeps the plain text and references to vectors from the model which stores runs with text styles.
+ */
+struct MarkupProcessData
+{
+  MarkupProcessData(Vector<ColorRun>&                     colorRuns,
+                    Vector<FontDescriptionRun>&           fontRuns,
+                    Vector<EmbeddedItem>&                 items,
+                    Vector<Anchor>&                       anchors,
+                    Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns,
+                    Vector<ColorRun>&                     backgroundColorRuns,
+                    Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns,
+                    Vector<BoundedParagraphRun>&          boundedParagraphRuns,
+                    Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns)
+  : colorRuns(colorRuns),
+    fontRuns(fontRuns),
+    items(items),
+    anchors(anchors),
+    underlinedCharacterRuns(underlinedCharacterRuns),
+    backgroundColorRuns(backgroundColorRuns),
+    strikethroughCharacterRuns(strikethroughCharacterRuns),
+    boundedParagraphRuns(boundedParagraphRuns),
+    characterSpacingCharacterRuns(characterSpacingCharacterRuns),
+    markupProcessedText()
+  {
+  }
+
+  Vector<ColorRun>&                     colorRuns;                     ///< The color runs.
+  Vector<FontDescriptionRun>&           fontRuns;                      ///< The font description runs.
+  Vector<EmbeddedItem>&                 items;                         ///< The embedded items.
+  Vector<Anchor>&                       anchors;                       ///< The anchors.
+  Vector<UnderlinedCharacterRun>&       underlinedCharacterRuns;       ///< The underlined character runs.
+  Vector<ColorRun>&                     backgroundColorRuns;           ///< The background color runs.
+  Vector<StrikethroughCharacterRun>&    strikethroughCharacterRuns;    ///< The strikethrough character runs.
+  Vector<BoundedParagraphRun>&          boundedParagraphRuns;          ///< The bounded paragraph runs
+  Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns; ///< The character-spacing runs
+
+  std::string markupProcessedText; ///< The mark-up string.
+};
+
+/**
+ * @brief Process the mark-up string.
+ *
+ * @param[in] markupString The mark-up string.
+ * @param[out] markupProcessData The plain text and the style.
+ */
+void ProcessMarkupString(const std::string& markupString, MarkupProcessData& markupProcessData);
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H
index ec0fc946fb8c3174a5c2e63f1ecdabe5cff78bc1..9265472e5026385ba6efaaded6d650c2e9365d1e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/builder/json-parser.h>
 #include <dali-toolkit/devel-api/builder/tree-node.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
 
 namespace Dali
 {
diff --git a/dali-toolkit/internal/text/text-controller-background-actor.cpp b/dali-toolkit/internal/text/text-controller-background-actor.cpp
deleted file mode 100644 (file)
index bc7c79b..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// HEADER
-#include <dali-toolkit/internal/text/text-controller-background-actor.h>
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/rendering/renderer.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
-#include <dali-toolkit/internal/text/text-view.h>
-
-namespace Dali::Toolkit::Text
-{
-namespace
-{
-struct BackgroundVertex
-{
-  Vector2 mPosition; ///< Vertex posiiton
-  Vector4 mColor;    ///< Vertex color
-};
-
-struct BackgroundMesh
-{
-  Vector<BackgroundVertex> mVertices; ///< container of vertices
-  Vector<unsigned short>   mIndices;  ///< container of indices
-};
-} // unnamed namespace
-
-Length CalculateBackgroundLineHeight(LineRun lineRun)
-{
-  Length height = lineRun.ascender + -(lineRun.descender);
-
-  if(lineRun.lineSpacing > 0)
-  {
-    height += lineRun.lineSpacing;
-  }
-
-  return height;
-}
-
-Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, const LogicalModelPtr& textLogicalModel, Shader& textShaderBackground)
-{
-  // NOTE: Currently we only support background color for left-to-right text.
-
-  Actor actor;
-
-  Length numberOfGlyphs = textView.GetNumberOfGlyphs();
-  if(numberOfGlyphs > 0u)
-  {
-    Vector<GlyphInfo> glyphs;
-    glyphs.Resize(numberOfGlyphs);
-
-    Vector<Vector2> positions;
-    positions.Resize(numberOfGlyphs);
-
-    // Get the line where the glyphs are laid-out.
-    const LineRun* lineRun         = textVisualModel->mLines.Begin();
-    float          alignmentOffset = lineRun->alignmentOffset;
-    numberOfGlyphs                 = textView.GetGlyphs(glyphs.Begin(),
-                                        positions.Begin(),
-                                        alignmentOffset,
-                                        0u,
-                                        numberOfGlyphs);
-
-    glyphs.Resize(numberOfGlyphs);
-    positions.Resize(numberOfGlyphs);
-
-    const GlyphInfo* const glyphsBuffer    = glyphs.Begin();
-    const Vector2* const   positionsBuffer = positions.Begin();
-
-    BackgroundMesh mesh;
-    mesh.mVertices.Reserve(4u * glyphs.Size());
-    mesh.mIndices.Reserve(6u * glyphs.Size());
-
-    const Vector2 textSize = textView.GetLayoutSize();
-
-    const float offsetX = alignmentOffset + textSize.width * 0.5f;
-    const float offsetY = textSize.height * 0.5f;
-
-    const Vector4* const    backgroundColorsBuffer       = textView.GetBackgroundColors();
-    const ColorIndex* const backgroundColorIndicesBuffer = textView.GetBackgroundColorIndices();
-    const Vector4&          defaultBackgroundColor       = textVisualModel->IsBackgroundEnabled() ? textVisualModel->GetBackgroundColor() : Color::TRANSPARENT;
-    const float             modelCharacterSpacing        = textVisualModel->GetCharacterSpacing();
-    Vector<CharacterIndex>& glyphToCharacterMap          = textVisualModel->mGlyphsToCharacters;
-    const CharacterIndex*   glyphToCharacterMapBuffer    = glyphToCharacterMap.Begin();
-    float                   calculatedAdvance            = 0.f;
-
-    // Get the character-spacing runs.
-    const Vector<CharacterSpacingGlyphRun>& characterSpacingGlyphRuns = textVisualModel->GetCharacterSpacingGlyphRuns();
-
-    Vector4   quad;
-    uint32_t  numberOfQuads = 0u;
-    Length    yLineOffset   = 0;
-    Length    prevLineIndex = 0;
-    LineIndex lineIndex;
-
-    for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i)
-    {
-      const GlyphInfo& glyph = *(glyphsBuffer + i);
-
-      // Get the background color of the character.
-      // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT)
-      const bool       isMarkupBackground       = textView.IsMarkupBackgroundColorSet();
-      const ColorIndex backgroundColorIndex     = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u;
-      const bool       isDefaultBackgroundColor = (0u == backgroundColorIndex);
-      const Vector4&   backgroundColor          = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u);
-
-      lineIndex         = textVisualModel->GetLineOfGlyph(i);
-      Length lineHeight = CalculateBackgroundLineHeight(lineRun[lineIndex]);
-
-      if(lineIndex != prevLineIndex)
-      {
-        yLineOffset += CalculateBackgroundLineHeight(lineRun[prevLineIndex]);
-
-        if(lineRun[prevLineIndex].lineSpacing < 0)
-        {
-          yLineOffset += lineRun[prevLineIndex].lineSpacing;
-        }
-      }
-
-      // Only create quads for glyphs with a background color
-      if(backgroundColor != Color::TRANSPARENT)
-      {
-        const float characterSpacing = GetGlyphCharacterSpacing(i, characterSpacingGlyphRuns, modelCharacterSpacing);
-
-        const Vector2 position = *(positionsBuffer + i);
-        calculatedAdvance      = GetCalculatedAdvance(*(textLogicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + i))), characterSpacing, glyph.advance);
-
-        if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text
-        {
-          quad.x = position.x;
-          quad.y = yLineOffset;
-          quad.z = quad.x + std::max(calculatedAdvance, glyph.xBearing + glyph.width);
-          quad.w = lineHeight;
-        }
-        else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line
-        {
-          quad.x = position.x;
-          quad.y = yLineOffset;
-          quad.z = quad.x - glyph.xBearing + calculatedAdvance;
-          quad.w = quad.y + lineHeight;
-        }
-        else if(i == glyphSize - 1u) // The last glyph in the whole text
-        {
-          quad.x = position.x - glyph.xBearing;
-          quad.y = yLineOffset;
-          quad.z = quad.x + std::max(calculatedAdvance, glyph.xBearing + glyph.width);
-          quad.w = quad.y + lineHeight;
-        }
-        else // The glyph in the middle of the text
-        {
-          quad.x = position.x - glyph.xBearing;
-          quad.y = yLineOffset;
-          quad.z = quad.x + calculatedAdvance;
-          quad.w = quad.y + lineHeight;
-        }
-
-        BackgroundVertex vertex;
-
-        // Top left
-        vertex.mPosition.x = quad.x - offsetX;
-        vertex.mPosition.y = quad.y - offsetY;
-        vertex.mColor      = backgroundColor;
-        mesh.mVertices.PushBack(vertex);
-
-        // Top right
-        vertex.mPosition.x = quad.z - offsetX;
-        vertex.mPosition.y = quad.y - offsetY;
-        vertex.mColor      = backgroundColor;
-        mesh.mVertices.PushBack(vertex);
-
-        // Bottom left
-        vertex.mPosition.x = quad.x - offsetX;
-        vertex.mPosition.y = quad.w - offsetY;
-        vertex.mColor      = backgroundColor;
-        mesh.mVertices.PushBack(vertex);
-
-        // Bottom right
-        vertex.mPosition.x = quad.z - offsetX;
-        vertex.mPosition.y = quad.w - offsetY;
-        vertex.mColor      = backgroundColor;
-        mesh.mVertices.PushBack(vertex);
-
-        // Six indices in counter clockwise winding
-        mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
-        mesh.mIndices.PushBack(0u + 4 * numberOfQuads);
-        mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
-        mesh.mIndices.PushBack(2u + 4 * numberOfQuads);
-        mesh.mIndices.PushBack(3u + 4 * numberOfQuads);
-        mesh.mIndices.PushBack(1u + 4 * numberOfQuads);
-
-        numberOfQuads++;
-      }
-
-      if(lineIndex != prevLineIndex)
-      {
-        prevLineIndex = lineIndex;
-      }
-    }
-
-    // Only create the background actor if there are glyphs with background color
-    if(mesh.mVertices.Count() > 0u)
-    {
-      Property::Map quadVertexFormat;
-      quadVertexFormat["aPosition"] = Property::VECTOR2;
-      quadVertexFormat["aColor"]    = Property::VECTOR4;
-
-      VertexBuffer quadVertices = VertexBuffer::New(quadVertexFormat);
-      quadVertices.SetData(&mesh.mVertices[0], mesh.mVertices.Size());
-
-      Geometry quadGeometry = Geometry::New();
-      quadGeometry.AddVertexBuffer(quadVertices);
-      quadGeometry.SetIndexBuffer(&mesh.mIndices[0], mesh.mIndices.Size());
-
-      if(!textShaderBackground)
-      {
-        textShaderBackground = Shader::New(SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_VERT, SHADER_TEXT_CONTROLLER_BACKGROUND_SHADER_FRAG);
-      }
-
-      Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, textShaderBackground);
-      renderer.SetProperty(Dali::Renderer::Property::BLEND_MODE, BlendMode::ON);
-      renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT);
-
-      actor = Actor::New();
-      actor.SetProperty(Dali::Actor::Property::NAME, "TextBackgroundColorActor");
-      actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
-      actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
-      actor.SetProperty(Actor::Property::SIZE, textSize);
-      actor.SetProperty(Actor::Property::COLOR_MODE, USE_OWN_MULTIPLY_PARENT_COLOR);
-      actor.AddRenderer(renderer);
-    }
-  }
-
-  return actor;
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller-background-actor.h b/dali-toolkit/internal/text/text-controller-background-actor.h
deleted file mode 100644 (file)
index 41b549c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/actors/actor.h>
-#include <dali/public-api/rendering/shader.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/logical-model-impl.h>
-#include <dali-toolkit/internal/text/visual-model-impl.h>
-
-namespace Dali::Toolkit::Text
-{
-class View;
-
-/**
- * @brief Create an actor that renders the text background color
- *
- * @param[in] textView The text view.
- * @param[in] textVisualModel The text visual model.
- * @param[in] textLogicalModel The text logical model.
- * @param[in] textShaderBackground The text shader for background.
- *
- * @return the created actor or an empty handle if no background color needs to be rendered.
- */
-Actor CreateControllerBackgroundActor(const View& textView, const VisualModelPtr& textVisualModel, const LogicalModelPtr& textLogicalModel, Shader& textShaderBackground);
-
-} // namespace Dali::Toolkit::Text
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_BACKGROUND_ACTOR_H
diff --git a/dali-toolkit/internal/text/text-controller-event-handler.cpp b/dali-toolkit/internal/text/text-controller-event-handler.cpp
deleted file mode 100644 (file)
index 59f0b8d..0000000
+++ /dev/null
@@ -1,1026 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-event-handler.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
-#include <dali/devel-api/adaptor-framework/key-devel.h>
-#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-controller-text-updater.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-const std::string KEY_C_NAME      = "c";
-const std::string KEY_V_NAME      = "v";
-const std::string KEY_X_NAME      = "x";
-const std::string KEY_A_NAME      = "a";
-const std::string KEY_INSERT_NAME = "Insert";
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void Controller::EventHandler::KeyboardFocusGainEvent(Controller& controller)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyboardFocusGainEvent");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if((EventData::INACTIVE == controller.mImpl->mEventData->mState) ||
-       (EventData::INTERRUPTED == controller.mImpl->mEventData->mState))
-    {
-      controller.mImpl->ChangeState(EventData::EDITING);
-      controller.mImpl->mEventData->mUpdateCursorPosition      = true; //If editing started without tap event, cursor update must be triggered.
-      controller.mImpl->mEventData->mUpdateInputStyle          = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition = true;
-    }
-    controller.mImpl->NotifyInputMethodContextMultiLineStatus();
-    if(controller.mImpl->IsShowingPlaceholderText())
-    {
-      // Show alternative placeholder-text when editing
-      PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
-    }
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-void Controller::EventHandler::KeyboardFocusLostEvent(Controller& controller)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyboardFocusLostEvent");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(EventData::INTERRUPTED != controller.mImpl->mEventData->mState)
-    {
-      // Init selection position
-      if(controller.mImpl->mEventData->mState == EventData::SELECTING)
-      {
-        uint32_t oldStart, oldEnd;
-        oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
-        oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
-
-        controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
-        controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
-
-        if(controller.mImpl->mSelectableControlInterface != nullptr)
-        {
-          controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mPrimaryCursorPosition, controller.mImpl->mEventData->mPrimaryCursorPosition);
-        }
-      }
-
-      controller.mImpl->ChangeState(EventData::INACTIVE);
-
-      if(!controller.mImpl->IsShowingRealText())
-      {
-        // Revert to regular placeholder-text when not editing
-        PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
-      }
-    }
-  }
-  controller.mImpl->RequestRelayout();
-}
-
-bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected KeyEvent");
-
-  bool textChanged    = false;
-  bool relayoutNeeded = false;
-  bool isEditable     = controller.IsEditable() && controller.IsUserInteractionEnabled();
-
-  if((NULL != controller.mImpl->mEventData) &&
-     (keyEvent.GetState() == KeyEvent::DOWN))
-  {
-    int                keyCode   = keyEvent.GetKeyCode();
-    const std::string& keyString = keyEvent.GetKeyString();
-    const std::string  keyName   = keyEvent.GetKeyName();
-    // Key will produce same logical-key value when ctrl
-    // is down, regardless of language layout
-    const std::string logicalKey = keyEvent.GetLogicalKey();
-
-    const bool isNullKey = (0 == keyCode) && (keyString.empty());
-
-    // Pre-process to separate modifying events from non-modifying input events.
-    if(isNullKey)
-    {
-      // In some platforms arrive key events with no key code.
-      // Do nothing.
-      return false;
-    }
-    else if(Dali::DALI_KEY_ESCAPE == keyCode || Dali::DALI_KEY_BACK == keyCode || Dali::DALI_KEY_SEARCH == keyCode)
-    {
-      // Do nothing
-      return false;
-    }
-    else if((Dali::DALI_KEY_CURSOR_LEFT == keyCode) ||
-            (Dali::DALI_KEY_CURSOR_RIGHT == keyCode) ||
-            (Dali::DALI_KEY_CURSOR_UP == keyCode) ||
-            (Dali::DALI_KEY_CURSOR_DOWN == keyCode))
-    {
-      // If don't have any text, do nothing.
-      if(!controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters || !isEditable)
-      {
-        return false;
-      }
-
-      uint32_t cursorPosition     = controller.mImpl->mEventData->mPrimaryCursorPosition;
-      uint32_t numberOfCharacters = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-      uint32_t cursorLine         = controller.mImpl->mModel->mVisualModel->GetLineOfCharacter(cursorPosition);
-      uint32_t numberOfLines      = controller.mImpl->mModel->GetNumberOfLines();
-
-      // Logic to determine whether this text control will lose focus or not.
-      if((Dali::DALI_KEY_CURSOR_LEFT == keyCode && 0 == cursorPosition && !keyEvent.IsShiftModifier()) ||
-         (Dali::DALI_KEY_CURSOR_RIGHT == keyCode && numberOfCharacters == cursorPosition && !keyEvent.IsShiftModifier()) ||
-         (Dali::DALI_KEY_CURSOR_DOWN == keyCode && cursorLine == numberOfLines - 1) ||
-         (Dali::DALI_KEY_CURSOR_DOWN == keyCode && numberOfCharacters == cursorPosition && cursorLine - 1 == numberOfLines - 1) ||
-         (Dali::DALI_KEY_CURSOR_UP == keyCode && cursorLine == 0) ||
-         (Dali::DALI_KEY_CURSOR_UP == keyCode && numberOfCharacters == cursorPosition && cursorLine == 1))
-      {
-        // Release the active highlight.
-        if(controller.mImpl->mEventData->mState == EventData::SELECTING)
-        {
-          uint32_t oldStart, oldEnd;
-          oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
-          oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
-
-          controller.mImpl->ChangeState(EventData::EDITING);
-
-          // Update selection position.
-          controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
-          controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
-          controller.mImpl->mEventData->mUpdateCursorPosition   = true;
-
-          if(controller.mImpl->mSelectableControlInterface != nullptr)
-          {
-            controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
-          }
-
-          controller.mImpl->RequestRelayout();
-        }
-        return false;
-      }
-
-      controller.mImpl->mEventData->mCheckScrollAmount = true;
-      Event event(Event::CURSOR_KEY_EVENT);
-      event.p1.mInt  = keyCode;
-      event.p2.mBool = keyEvent.IsShiftModifier();
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-
-      // Will request for relayout.
-      relayoutNeeded = true;
-    }
-    else if(Dali::DevelKey::DALI_KEY_CONTROL_LEFT == keyCode || Dali::DevelKey::DALI_KEY_CONTROL_RIGHT == keyCode)
-    {
-      // Left or Right Control key event is received before Ctrl-C/V/X key event is received
-      // If not handle it here, any selected text will be deleted
-
-      // Do nothing
-      return false;
-    }
-    else if(keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier() && isEditable)
-    {
-      bool consumed = false;
-      if(keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME)
-      {
-        // Ctrl-C or Ctrl+Insert to copy the selected text
-        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::COPY);
-        consumed = true;
-      }
-      else if(keyName == KEY_V_NAME || logicalKey == KEY_V_NAME)
-      {
-        // Ctrl-V to paste the copied text
-        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::PASTE);
-        consumed = true;
-      }
-      else if(keyName == KEY_X_NAME || logicalKey == KEY_X_NAME)
-      {
-        // Ctrl-X to cut the selected text
-        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::CUT);
-        consumed = true;
-      }
-      else if(keyName == KEY_A_NAME || logicalKey == KEY_A_NAME)
-      {
-        // Ctrl-A to select All the text
-        controller.TextPopupButtonTouched(Toolkit::TextSelectionPopup::SELECT_ALL);
-        consumed = true;
-      }
-      return consumed;
-    }
-    else if((Dali::DALI_KEY_BACKSPACE == keyCode) ||
-            (Dali::DevelKey::DALI_KEY_DELETE == keyCode))
-    {
-      textChanged = DeleteEvent(controller, keyCode);
-
-      // Will request for relayout.
-      relayoutNeeded = true;
-    }
-    else if(IsKey(keyEvent, Dali::DALI_KEY_POWER) ||
-            IsKey(keyEvent, Dali::DALI_KEY_MENU) ||
-            IsKey(keyEvent, Dali::DALI_KEY_HOME))
-    {
-      // Power key/Menu/Home key behaviour does not allow edit mode to resume.
-      controller.mImpl->ChangeState(EventData::INACTIVE);
-
-      // Will request for relayout.
-      relayoutNeeded = true;
-
-      // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
-    }
-    else if((Dali::DALI_KEY_SHIFT_LEFT == keyCode) || (Dali::DALI_KEY_SHIFT_RIGHT == keyCode))
-    {
-      // DALI_KEY_SHIFT_LEFT or DALI_KEY_SHIFT_RIGHT is the key code for Shift. It's sent (by the InputMethodContext?) when the predictive text is enabled
-      // and a character is typed after the type of a upper case latin character.
-
-      // Do nothing.
-      return false;
-    }
-    else if((Dali::DALI_KEY_VOLUME_UP == keyCode) || (Dali::DALI_KEY_VOLUME_DOWN == keyCode))
-    {
-      // This branch avoids calling the InsertText() method of the 'else' branch which can delete selected text.
-      // Do nothing.
-      return false;
-    }
-    else
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p keyString %s\n", &controller, keyString.c_str());
-      if(!isEditable) return false;
-
-      std::string refinedKey = keyString;
-      if(controller.mImpl->mInputFilter != NULL && !refinedKey.empty())
-      {
-        bool accepted = false;
-        bool rejected = false;
-        accepted      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::ACCEPTED, keyString);
-        rejected      = controller.mImpl->mInputFilter->Contains(Toolkit::InputFilter::Property::REJECTED, keyString);
-
-        if(!accepted)
-        {
-          // The filtered key is set to empty.
-          refinedKey = "";
-          // Signal emits when the character to be inserted is filtered by the accepted filter.
-          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::ACCEPTED);
-        }
-        if(rejected)
-        {
-          // The filtered key is set to empty.
-          refinedKey = "";
-          // Signal emits when the character to be inserted is filtered by the rejected filter.
-          controller.mImpl->mEditableControlInterface->InputFiltered(Toolkit::InputFilter::Property::REJECTED);
-        }
-      }
-
-      if(!refinedKey.empty())
-      {
-        // InputMethodContext is no longer handling key-events
-        controller.mImpl->ClearPreEditFlag();
-
-        TextUpdater::InsertText(controller, refinedKey, COMMIT);
-
-        textChanged = true;
-
-        // Will request for relayout.
-        relayoutNeeded = true;
-      }
-    }
-
-    if((controller.mImpl->mEventData->mState != EventData::INTERRUPTED) &&
-       (controller.mImpl->mEventData->mState != EventData::INACTIVE) &&
-       (!isNullKey) &&
-       (Dali::DALI_KEY_SHIFT_LEFT != keyCode) &&
-       (Dali::DALI_KEY_SHIFT_RIGHT != keyCode) &&
-       (Dali::DALI_KEY_VOLUME_UP != keyCode) &&
-       (Dali::DALI_KEY_VOLUME_DOWN != keyCode))
-    {
-      // Should not change the state if the key is the shift send by the InputMethodContext.
-      // Otherwise, when the state is SELECTING the text controller can't send the right
-      // surrounding info to the InputMethodContext.
-      controller.mImpl->ChangeState(EventData::EDITING);
-
-      // Will request for relayout.
-      relayoutNeeded = true;
-    }
-
-    if(relayoutNeeded)
-    {
-      controller.mImpl->RequestRelayout();
-    }
-  }
-  else if((NULL != controller.mImpl->mEventData) && (keyEvent.GetState() == KeyEvent::UP))
-  {
-    // Handles specific keys that require event propagation.
-    if(Dali::DALI_KEY_BACK == keyEvent.GetKeyCode())
-    {
-      // Do nothing
-      return false;
-    }
-  }
-
-  if(textChanged &&
-     (NULL != controller.mImpl->mEditableControlInterface))
-  {
-    // Do this last since it provides callbacks into application code
-    controller.mImpl->mEditableControlInterface->TextChanged(false);
-  }
-
-  return true;
-}
-
-void Controller::EventHandler::AnchorEvent(Controller& controller, float x, float y)
-{
-  if(!controller.mImpl->mMarkupProcessorEnabled ||
-     !controller.mImpl->mModel->mLogicalModel->mAnchors.Count() ||
-     !controller.mImpl->IsShowingRealText())
-  {
-    return;
-  }
-
-  CharacterIndex cursorPosition = 0u;
-
-  // Convert from control's coords to text's coords.
-  const float xPosition = x - controller.mImpl->mModel->mScrollPosition.x;
-  const float yPosition = y - controller.mImpl->mModel->mScrollPosition.y;
-
-  // Whether to touch point hits on a glyph.
-  bool matchedCharacter = false;
-  cursorPosition        = Text::GetClosestCursorIndex(controller.mImpl->mModel->mVisualModel,
-                                               controller.mImpl->mModel->mLogicalModel,
-                                               controller.mImpl->mMetrics,
-                                               xPosition,
-                                               yPosition,
-                                               CharacterHitTest::TAP,
-                                               matchedCharacter);
-
-  for(const auto& anchor : controller.mImpl->mModel->mLogicalModel->mAnchors)
-  {
-    // Anchor clicked if the calculated cursor position is within the range of anchor.
-    if(cursorPosition >= anchor.startIndex && cursorPosition < anchor.endIndex)
-    {
-      if(controller.mImpl->mAnchorControlInterface && anchor.href)
-      {
-        std::string href(anchor.href);
-        controller.mImpl->mAnchorControlInterface->AnchorClicked(href);
-        break;
-      }
-    }
-  }
-}
-
-void Controller::EventHandler::TapEvent(Controller& controller, unsigned int tapCount, float x, float y)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected TapEvent");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Concise, "TapEvent state:%d \n", controller.mImpl->mEventData->mState);
-    EventData::State state(controller.mImpl->mEventData->mState);
-    bool             relayoutNeeded(false); // to avoid unnecessary relayouts when tapping an empty text-field
-
-    if(controller.mImpl->IsClipboardVisible())
-    {
-      if(EventData::INACTIVE == state || EventData::EDITING == state)
-      {
-        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE);
-      }
-      relayoutNeeded = true;
-    }
-    else if(1u == tapCount)
-    {
-      if(EventData::EDITING_WITH_POPUP == state || EventData::EDITING_WITH_PASTE_POPUP == state)
-      {
-        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE); // If Popup shown hide it here so can be shown again if required.
-      }
-
-      if(controller.mImpl->IsShowingRealText() && (EventData::INACTIVE != state))
-      {
-        controller.mImpl->ChangeState(EventData::EDITING_WITH_GRAB_HANDLE);
-        relayoutNeeded = true;
-      }
-      else
-      {
-        if(controller.mImpl->IsShowingPlaceholderText() && !controller.mImpl->IsFocusedPlaceholderAvailable())
-        {
-          // Hide placeholder text
-          TextUpdater::ResetText(controller);
-        }
-
-        if(EventData::INACTIVE == state)
-        {
-          controller.mImpl->ChangeState(EventData::EDITING);
-        }
-        else if(!controller.mImpl->IsClipboardEmpty())
-        {
-          controller.mImpl->ChangeState(EventData::EDITING_WITH_POPUP);
-        }
-        relayoutNeeded = true;
-      }
-    }
-    else if(2u == tapCount)
-    {
-      if(controller.mImpl->mEventData->mSelectionEnabled &&
-         controller.mImpl->IsShowingRealText())
-      {
-        relayoutNeeded                                       = true;
-        controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
-        controller.mImpl->mEventData->mIsRightHandleSelected = true;
-      }
-    }
-
-    // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
-    if(relayoutNeeded)
-    {
-      Event event(Event::TAP_EVENT);
-      event.p1.mUint  = tapCount;
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-
-      controller.mImpl->RequestRelayout();
-    }
-  }
-
-  // Reset keyboard as tap event has occurred.
-  controller.mImpl->ResetInputMethodContext();
-}
-
-void Controller::EventHandler::PanEvent(Controller& controller, GestureState state, const Vector2& displacement)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected PanEvent");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    Event event(Event::PAN_EVENT);
-    event.p1.mInt   = static_cast<int>(state);
-    event.p2.mFloat = displacement.x;
-    event.p3.mFloat = displacement.y;
-    controller.mImpl->mEventData->mEventQueue.push_back(event);
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-void Controller::EventHandler::LongPressEvent(Controller& controller, GestureState state, float x, float y)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected LongPressEvent");
-
-  if((state == GestureState::STARTED) &&
-     (NULL != controller.mImpl->mEventData))
-  {
-    // The 1st long-press on inactive text-field is treated as tap
-    if(EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      controller.mImpl->ChangeState(EventData::EDITING);
-
-      Event event(Event::TAP_EVENT);
-      event.p1.mUint  = 1;
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-
-      controller.mImpl->RequestRelayout();
-    }
-    else if(!controller.mImpl->IsShowingRealText())
-    {
-      Event event(Event::LONG_PRESS_EVENT);
-      event.p1.mInt   = static_cast<int>(state);
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-      controller.mImpl->RequestRelayout();
-    }
-    else if(!controller.mImpl->IsClipboardVisible())
-    {
-      // Reset the InputMethodContext to commit the pre-edit before selecting the text.
-      controller.mImpl->ResetInputMethodContext();
-
-      Event event(Event::LONG_PRESS_EVENT);
-      event.p1.mInt   = static_cast<int>(state);
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-      controller.mImpl->RequestRelayout();
-
-      controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
-      controller.mImpl->mEventData->mIsRightHandleSelected = true;
-    }
-  }
-}
-
-void Controller::EventHandler::SelectEvent(Controller& controller, float x, float y, SelectionType selectType)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(selectType == SelectionType::ALL)
-    {
-      Event event(Event::SELECT_ALL);
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-    }
-    else if(selectType == SelectionType::NONE)
-    {
-      Event event(Event::SELECT_NONE);
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-    }
-    else
-    {
-      Event event(Event::SELECT);
-      event.p2.mFloat = x;
-      event.p3.mFloat = y;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-    }
-
-    controller.mImpl->mEventData->mCheckScrollAmount     = true;
-    controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
-    controller.mImpl->mEventData->mIsRightHandleSelected = true;
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-void Controller::EventHandler::SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SelectEvent\n");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(selectType == SelectionType::RANGE)
-    {
-      Event event(Event::SELECT_RANGE);
-      event.p2.mUint = start;
-      event.p3.mUint = end;
-      controller.mImpl->mEventData->mEventQueue.push_back(event);
-    }
-
-    controller.mImpl->mEventData->mCheckScrollAmount     = true;
-    controller.mImpl->mEventData->mIsLeftHandleSelected  = true;
-    controller.mImpl->mEventData->mIsRightHandleSelected = true;
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-void Controller::EventHandler::ProcessModifyEvents(Controller& controller)
-{
-  Vector<ModifyEvent>& events = controller.mImpl->mModifyEvents;
-
-  if(0u == events.Count())
-  {
-    // Nothing to do.
-    return;
-  }
-
-  for(Vector<ModifyEvent>::ConstIterator it    = events.Begin(),
-                                         endIt = events.End();
-      it != endIt;
-      ++it)
-  {
-    const ModifyEvent& event = *it;
-
-    if(ModifyEvent::TEXT_REPLACED == event.type)
-    {
-      // A (single) replace event should come first, otherwise we wasted time processing NOOP events
-      DALI_ASSERT_DEBUG(it == events.Begin() && "Unexpected TEXT_REPLACED event");
-
-      TextReplacedEvent(controller);
-    }
-    else if(ModifyEvent::TEXT_INSERTED == event.type)
-    {
-      TextInsertedEvent(controller);
-    }
-    else if(ModifyEvent::TEXT_DELETED == event.type)
-    {
-      // Placeholder-text cannot be deleted
-      if(!controller.mImpl->IsShowingPlaceholderText())
-      {
-        TextDeletedEvent(controller);
-      }
-    }
-  }
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    uint32_t oldStart, oldEnd;
-    oldStart = controller.mImpl->mEventData->mLeftSelectionPosition;
-    oldEnd   = controller.mImpl->mEventData->mRightSelectionPosition;
-
-    // When the text is being modified, delay cursor blinking
-    controller.mImpl->mEventData->mDecorator->DelayCursorBlink();
-
-    // Update selection position after modifying the text
-    controller.mImpl->mEventData->mLeftSelectionPosition  = controller.mImpl->mEventData->mPrimaryCursorPosition;
-    controller.mImpl->mEventData->mRightSelectionPosition = controller.mImpl->mEventData->mPrimaryCursorPosition;
-
-    if(controller.mImpl->mSelectableControlInterface != nullptr && controller.mImpl->mEventData->mState == EventData::SELECTING)
-    {
-      controller.mImpl->mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, controller.mImpl->mEventData->mLeftSelectionPosition, controller.mImpl->mEventData->mRightSelectionPosition);
-    }
-  }
-
-  // DISCARD temporary text
-  events.Clear();
-}
-
-void Controller::EventHandler::TextReplacedEvent(Controller& controller)
-{
-  // The natural size needs to be re-calculated.
-  controller.mImpl->mRecalculateNaturalSize = true;
-
-  // The text direction needs to be updated.
-  controller.mImpl->mUpdateTextDirection = true;
-
-  // Apply modifications to the model
-  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-}
-
-void Controller::EventHandler::TextInsertedEvent(Controller& controller)
-{
-  DALI_ASSERT_DEBUG(NULL != controller.mImpl->mEventData && "Unexpected TextInsertedEvent");
-
-  if(NULL == controller.mImpl->mEventData)
-  {
-    return;
-  }
-
-  controller.mImpl->mEventData->mCheckScrollAmount = true;
-
-  // The natural size needs to be re-calculated.
-  controller.mImpl->mRecalculateNaturalSize = true;
-
-  // The text direction needs to be updated.
-  controller.mImpl->mUpdateTextDirection = true;
-
-  // Apply modifications to the model; TODO - Optimize this
-  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-}
-
-void Controller::EventHandler::TextDeletedEvent(Controller& controller)
-{
-  DALI_ASSERT_DEBUG(NULL != controller.mImpl->mEventData && "Unexpected TextDeletedEvent");
-
-  if(NULL == controller.mImpl->mEventData)
-  {
-    return;
-  }
-
-  if(!controller.IsEditable()) return;
-
-  controller.mImpl->mEventData->mCheckScrollAmount = true;
-
-  // The natural size needs to be re-calculated.
-  controller.mImpl->mRecalculateNaturalSize = true;
-
-  // The text direction needs to be updated.
-  controller.mImpl->mUpdateTextDirection = true;
-
-  // Apply modifications to the model; TODO - Optimize this
-  controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-}
-
-bool Controller::EventHandler::DeleteEvent(Controller& controller, int keyCode)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::KeyEvent %p KeyCode : %d \n", &controller, keyCode);
-
-  bool removed = false;
-
-  if(NULL == controller.mImpl->mEventData)
-  {
-    return removed;
-  }
-
-  if(!controller.IsEditable()) return false;
-
-  // InputMethodContext is no longer handling key-events
-  controller.mImpl->ClearPreEditFlag();
-
-  if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-  {
-    removed = TextUpdater::RemoveSelectedText(controller);
-  }
-  else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE))
-  {
-    // Remove the character before the current cursor position
-    removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE);
-  }
-  else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) &&
-          (keyCode == Dali::DevelKey::DALI_KEY_DELETE))
-  {
-    // Remove the character after the current cursor position
-    removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE);
-  }
-
-  if(removed)
-  {
-    if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
-       !controller.mImpl->IsPlaceholderAvailable())
-    {
-      controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
-    }
-    else
-    {
-      PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
-    }
-    controller.mImpl->mEventData->mUpdateCursorPosition = true;
-    controller.mImpl->mEventData->mScrollAfterDelete    = true;
-  }
-
-  return removed;
-}
-
-InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextEvent(Controller& controller, InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
-{
-  // Whether the text needs to be relaid-out.
-  bool requestRelayout = false;
-
-  // Whether to retrieve the text and cursor position to be sent to the InputMethodContext.
-  bool retrieveText   = false;
-  bool retrieveCursor = false;
-
-  switch(inputMethodContextEvent.eventName)
-  {
-    case InputMethodContext::COMMIT:
-    {
-      TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::COMMIT);
-      requestRelayout = true;
-      retrieveCursor  = true;
-      break;
-    }
-    case InputMethodContext::PRE_EDIT:
-    {
-      TextUpdater::InsertText(controller, inputMethodContextEvent.predictiveString, Text::Controller::PRE_EDIT);
-      requestRelayout = true;
-      retrieveCursor  = true;
-      break;
-    }
-    case InputMethodContext::DELETE_SURROUNDING:
-    {
-      const bool textDeleted = TextUpdater::RemoveText(controller,
-                                                       inputMethodContextEvent.cursorOffset,
-                                                       inputMethodContextEvent.numberOfChars,
-                                                       DONT_UPDATE_INPUT_STYLE);
-
-      if(textDeleted)
-      {
-        if((0u != controller.mImpl->mModel->mLogicalModel->mText.Count()) ||
-           !controller.mImpl->IsPlaceholderAvailable())
-        {
-          controller.mImpl->QueueModifyEvent(ModifyEvent::TEXT_DELETED);
-        }
-        else
-        {
-          PlaceholderHandler::ShowPlaceholderText(*controller.mImpl);
-        }
-        controller.mImpl->mEventData->mUpdateCursorPosition = true;
-        controller.mImpl->mEventData->mScrollAfterDelete    = true;
-
-        requestRelayout = true;
-      }
-      break;
-    }
-    case InputMethodContext::GET_SURROUNDING:
-    {
-      retrieveText   = true;
-      retrieveCursor = true;
-      break;
-    }
-    case InputMethodContext::PRIVATE_COMMAND:
-    {
-      // PRIVATECOMMAND event is just for getting the private command message
-      retrieveText   = true;
-      retrieveCursor = true;
-      break;
-    }
-    case InputMethodContext::SELECTION_SET:
-    {
-      uint32_t start = static_cast<uint32_t>(inputMethodContextEvent.startIndex);
-      uint32_t end = static_cast<uint32_t>(inputMethodContextEvent.endIndex);
-      if(start == end)
-      {
-        controller.SetPrimaryCursorPosition(start, true);
-      }
-      else
-      {
-        controller.SelectText(start, end);
-      }
-
-      break;
-    }
-    case InputMethodContext::VOID:
-    {
-      // do nothing
-      break;
-    }
-  } // end switch
-
-  if(requestRelayout)
-  {
-    controller.mImpl->mOperationsPending = ALL_OPERATIONS;
-    controller.mImpl->RequestRelayout();
-  }
-
-  std::string    text;
-  CharacterIndex cursorPosition      = 0u;
-  Length         numberOfWhiteSpaces = 0u;
-
-  if(retrieveCursor)
-  {
-    numberOfWhiteSpaces = controller.mImpl->GetNumberOfWhiteSpaces(0u);
-
-    cursorPosition = controller.mImpl->GetLogicalCursorPosition();
-
-    if(cursorPosition < numberOfWhiteSpaces)
-    {
-      cursorPosition = 0u;
-    }
-    else
-    {
-      cursorPosition -= numberOfWhiteSpaces;
-    }
-  }
-
-  if(retrieveText)
-  {
-    if(!controller.mImpl->IsShowingPlaceholderText())
-    {
-      // Retrieves the normal text string.
-      controller.mImpl->GetText(numberOfWhiteSpaces, text);
-    }
-    else
-    {
-      // When the current text is Placeholder Text, the surrounding text should be empty string.
-      // It means DALi should send empty string ("") to IME.
-      text = "";
-    }
-  }
-
-  InputMethodContext::CallbackData callbackData((retrieveText || retrieveCursor), cursorPosition, text, false);
-
-  if(requestRelayout &&
-     (NULL != controller.mImpl->mEditableControlInterface))
-  {
-    // Do this last since it provides callbacks into application code
-    controller.mImpl->mEditableControlInterface->TextChanged(false);
-  }
-
-  return callbackData;
-}
-
-void Controller::EventHandler::PasteClipboardItemEvent(Controller& controller)
-{
-  // Retrieve the clipboard contents first
-  ClipboardEventNotifier notifier(ClipboardEventNotifier::Get());
-  std::string            stringToPaste(notifier.GetContent());
-
-  // Commit the current pre-edit text; the contents of the clipboard should be appended
-  controller.mImpl->ResetInputMethodContext();
-
-  // Temporary disable hiding clipboard
-  controller.mImpl->SetClipboardHideEnable(false);
-
-  // Paste
-  TextUpdater::PasteText(controller, stringToPaste);
-
-  controller.mImpl->SetClipboardHideEnable(true);
-}
-
-void Controller::EventHandler::DecorationEvent(Controller& controller, HandleType handleType, HandleState state, float x, float y)
-{
-  DALI_ASSERT_DEBUG(controller.mImpl->mEventData && "Unexpected DecorationEvent");
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    switch(handleType)
-    {
-      case GRAB_HANDLE:
-      {
-        Event event(Event::GRAB_HANDLE_EVENT);
-        event.p1.mUint  = state;
-        event.p2.mFloat = x;
-        event.p3.mFloat = y;
-
-        controller.mImpl->mEventData->mEventQueue.push_back(event);
-        break;
-      }
-      case LEFT_SELECTION_HANDLE:
-      {
-        Event event(Event::LEFT_SELECTION_HANDLE_EVENT);
-        event.p1.mUint  = state;
-        event.p2.mFloat = x;
-        event.p3.mFloat = y;
-
-        controller.mImpl->mEventData->mEventQueue.push_back(event);
-        break;
-      }
-      case RIGHT_SELECTION_HANDLE:
-      {
-        Event event(Event::RIGHT_SELECTION_HANDLE_EVENT);
-        event.p1.mUint  = state;
-        event.p2.mFloat = x;
-        event.p3.mFloat = y;
-
-        controller.mImpl->mEventData->mEventQueue.push_back(event);
-        break;
-      }
-      case LEFT_SELECTION_HANDLE_MARKER:
-      case RIGHT_SELECTION_HANDLE_MARKER:
-      {
-        // Markers do not move the handles.
-        break;
-      }
-      case HANDLE_TYPE_COUNT:
-      {
-        DALI_ASSERT_DEBUG(!"Controller::HandleEvent. Unexpected handle type");
-      }
-    }
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-void Controller::EventHandler::TextPopupButtonTouched(Controller& controller, Dali::Toolkit::TextSelectionPopup::Buttons button)
-{
-  if(NULL == controller.mImpl->mEventData)
-  {
-    return;
-  }
-
-  switch(button)
-  {
-    case Toolkit::TextSelectionPopup::CUT:
-    {
-      controller.CutText();
-      break;
-    }
-    case Toolkit::TextSelectionPopup::COPY:
-    {
-      controller.CopyText();
-      break;
-    }
-    case Toolkit::TextSelectionPopup::PASTE:
-    {
-      controller.PasteText();
-      break;
-    }
-    case Toolkit::TextSelectionPopup::SELECT:
-    {
-      const Vector2& currentCursorPosition = controller.mImpl->mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
-
-      if(controller.mImpl->mEventData->mSelectionEnabled)
-      {
-        // Creates a SELECT event.
-        SelectEvent(controller, currentCursorPosition.x, currentCursorPosition.y, SelectionType::INTERACTIVE);
-      }
-      break;
-    }
-    case Toolkit::TextSelectionPopup::SELECT_ALL:
-    {
-      // Creates a SELECT_ALL event
-      SelectEvent(controller, 0.f, 0.f, SelectionType::ALL);
-      break;
-    }
-    case Toolkit::TextSelectionPopup::CLIPBOARD:
-    {
-      controller.mImpl->ShowClipboard();
-      break;
-    }
-    case Toolkit::TextSelectionPopup::NONE:
-    {
-      // Nothing to do.
-      break;
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-event-handler.h b/dali-toolkit/internal/text/text-controller-event-handler.h
deleted file mode 100644 (file)
index 0028890..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/input-method-context.h>
-#include <dali/public-api/events/gesture-enumerations.h>
-#include <dali/public-api/events/key-event.h>
-#include <dali/public-api/math/vector2.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
-#include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/text-controller.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Controller::EventHandler
-{
-  /// @copydoc Text::Controller::KeyboardFocusGainEvent
-  /// @param[in] controller A reference to the controller class
-  static void KeyboardFocusGainEvent(Controller& controller);
-
-  /// @copydoc Text::Controller::KeyboardFocusLostEvent
-  /// @param[in] controller A reference to the controller class
-  static void KeyboardFocusLostEvent(Controller& controller);
-
-  /// @copydoc Text::Controller::KeyEvent
-  /// @param[in] controller A reference to the controller class
-  static bool KeyEvent(Controller& controller, const Dali::KeyEvent& keyEvent);
-
-  /// @copydoc Text::Controller::AnchorEvent
-  /// @param[in] controller A reference to the controller class
-  static void AnchorEvent(Controller& controller, float x, float y);
-
-  /// @copydoc Text::Controller::TapEvent
-  /// @param[in] controller A reference to the controller class
-  static void TapEvent(Controller& controller, unsigned int tapCount, float x, float y);
-
-  /// @copydoc Text::Controller::PanEvent
-  /// @param[in] controller A reference to the controller class
-  static void PanEvent(Controller& controller, GestureState state, const Vector2& displacement);
-
-  /// @copydoc Text::Controller::LongPressEvent
-  /// @param[in] controller A reference to the controller class
-  static void LongPressEvent(Controller& controller, GestureState state, float x, float y);
-
-  /// @copydoc Text::Controller::SelectEvent
-  /// @param[in] controller A reference to the controller class
-  static void SelectEvent(Controller& controller, float x, float y, SelectionType selectType);
-
-  /**
-   * @brief Creates a selection event with a selection index.
-   *
-   * It could be called from the SelectText().
-   * The start and end parameters are passed through the event.
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] start The start selection position.
-   * @param[in] end The end selection position.
-   * @param[in] selection type like the range.
-   */
-  static void SelectEvent(Controller& controller, const uint32_t start, const uint32_t end, SelectionType selectType);
-
-  /**
-   * @brief Process queued events which modify the model.
-   * @param[in] controller A reference to the controller class
-   */
-  static void ProcessModifyEvents(Controller& controller);
-
-  /**
-   * @brief Used to process an event queued from SetText()
-   * @param[in] controller A reference to the controller class
-   */
-  static void TextReplacedEvent(Controller& controller);
-
-  /**
-   * @brief Used to process an event queued from key events etc.
-   * @param[in] controller A reference to the controller class
-   */
-  static void TextInsertedEvent(Controller& controller);
-
-  /**
-   * @brief Used to process an event queued from backspace key etc.
-   * @param[in] controller A reference to the controller class
-   */
-  static void TextDeletedEvent(Controller& controller);
-
-  /**
-   * @brief Helper to KeyEvent() to handle the backspace or delete key case.
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] keyCode The keycode for the key pressed
-   * @return True if a character was deleted.
-   */
-  static bool DeleteEvent(Controller& controller, int keyCode);
-
-  static InputMethodContext::CallbackData OnInputMethodContextEvent(Controller&                          controller,
-                                                                    InputMethodContext&                  inputMethodContext,
-                                                                    const InputMethodContext::EventData& inputMethodContextEvent);
-
-  static void PasteClipboardItemEvent(Controller& controller);
-  static void DecorationEvent(Controller& controller, HandleType handleType, HandleState state, float x, float y);
-  static void TextPopupButtonTouched(Controller& controller, Dali::Toolkit::TextSelectionPopup::Buttons button);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_EVENT_HANDLER_H
diff --git a/dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp b/dali-toolkit/internal/text/text-controller-impl-data-clearer.cpp
deleted file mode 100644 (file)
index 87099da..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-run-container.h>
-
-namespace Dali::Toolkit::Text
-{
-
-void ControllerImplDataClearer::ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations)
-{
-  ModelPtr& model = impl.mModel;
-
-  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
-  {
-    model->mLogicalModel->mLineBreakInfo.Clear();
-    model->mLogicalModel->mParagraphInfo.Clear();
-  }
-
-  if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
-  {
-    model->mLogicalModel->mScriptRuns.Clear();
-  }
-
-  if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
-  {
-    model->mLogicalModel->mFontRuns.Clear();
-  }
-
-  if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
-  {
-    if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
-    {
-      model->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-      model->mLogicalModel->mCharacterDirections.Clear();
-    }
-
-    if(Controller::NO_OPERATION != (Controller::REORDER & operations))
-    {
-      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
-      for(Vector<BidirectionalLineInfoRun>::Iterator it    = model->mLogicalModel->mBidirectionalLineInfo.Begin(),
-                                                     endIt = model->mLogicalModel->mBidirectionalLineInfo.End();
-          it != endIt;
-          ++it)
-      {
-        BidirectionalLineInfoRun& bidiLineInfo = *it;
-
-        free(bidiLineInfo.visualToLogicalMap);
-        bidiLineInfo.visualToLogicalMap = NULL;
-      }
-      model->mLogicalModel->mBidirectionalLineInfo.Clear();
-    }
-  }
-
-  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
-  {
-    model->mVisualModel->mGlyphs.Clear();
-    model->mVisualModel->mGlyphsToCharacters.Clear();
-    model->mVisualModel->mCharactersToGlyph.Clear();
-    model->mVisualModel->mCharactersPerGlyph.Clear();
-    model->mVisualModel->mGlyphsPerCharacter.Clear();
-    model->mVisualModel->mGlyphPositions.Clear();
-  }
-
-  if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
-  {
-    model->mVisualModel->mLines.Clear();
-  }
-
-  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
-  {
-    model->mVisualModel->mColorIndices.Clear();
-    model->mVisualModel->mBackgroundColorIndices.Clear();
-  }
-}
-
-void ControllerImplDataClearer::ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
-{
-  const CharacterIndex endIndexPlusOne = endIndex + 1u;
-  ModelPtr& model = impl.mModel;
-
-  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
-  {
-    // Clear the line break info.
-    LineBreakInfo* lineBreakInfoBuffer = model->mLogicalModel->mLineBreakInfo.Begin();
-
-    model->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
-                                                     lineBreakInfoBuffer + endIndexPlusOne);
-
-    // Clear the paragraphs.
-    ClearCharacterRuns(startIndex,
-                       endIndex,
-                       model->mLogicalModel->mParagraphInfo);
-  }
-
-  if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
-  {
-    // Clear the scripts.
-    ClearCharacterRuns(startIndex,
-                       endIndex,
-                       model->mLogicalModel->mScriptRuns);
-  }
-
-  if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
-  {
-    // Clear the fonts.
-    ClearCharacterRuns(startIndex,
-                       endIndex,
-                       model->mLogicalModel->mFontRuns);
-  }
-
-  if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
-  {
-    if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
-    {
-      // Clear the bidirectional paragraph info.
-      ClearCharacterRuns(startIndex,
-                         endIndex,
-                         model->mLogicalModel->mBidirectionalParagraphInfo);
-
-      // Clear the character's directions.
-      CharacterDirection* characterDirectionsBuffer = model->mLogicalModel->mCharacterDirections.Begin();
-
-      model->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
-                                                       characterDirectionsBuffer + endIndexPlusOne);
-    }
-
-    if(Controller::NO_OPERATION != (Controller::REORDER & operations))
-    {
-      uint32_t startRemoveIndex = model->mLogicalModel->mBidirectionalLineInfo.Count();
-      uint32_t endRemoveIndex   = startRemoveIndex;
-      ClearCharacterRuns(startIndex,
-                         endIndex,
-                         model->mLogicalModel->mBidirectionalLineInfo,
-                         startRemoveIndex,
-                         endRemoveIndex);
-
-      BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = model->mLogicalModel->mBidirectionalLineInfo.Begin();
-
-      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
-      for(Vector<BidirectionalLineInfoRun>::Iterator it    = bidirectionalLineInfoBuffer + startRemoveIndex,
-                                                     endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
-          it != endIt;
-          ++it)
-      {
-        BidirectionalLineInfoRun& bidiLineInfo = *it;
-
-        free(bidiLineInfo.visualToLogicalMap);
-        bidiLineInfo.visualToLogicalMap = NULL;
-      }
-
-      model->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
-                                                         bidirectionalLineInfoBuffer + endRemoveIndex);
-    }
-  }
-}
-
-void ControllerImplDataClearer::ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
-{
-  const CharacterIndex endIndexPlusOne           = endIndex + 1u;
-  const Length         numberOfCharactersRemoved = endIndexPlusOne - startIndex;
-  ModelPtr&            model                     = impl.mModel;
-  TextUpdateInfo&      textUpdateInfo            = impl.mTextUpdateInfo;
-
-
-  // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
-  GlyphIndex* charactersToGlyphBuffer  = model->mVisualModel->mCharactersToGlyph.Begin();
-  Length*     glyphsPerCharacterBuffer = model->mVisualModel->mGlyphsPerCharacter.Begin();
-
-  const GlyphIndex endGlyphIndexPlusOne  = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
-  const Length     numberOfGlyphsRemoved = endGlyphIndexPlusOne - textUpdateInfo.mStartGlyphIndex;
-
-  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
-  {
-    // Update the character to glyph indices.
-    for(Vector<GlyphIndex>::Iterator it    = charactersToGlyphBuffer + endIndexPlusOne,
-                                     endIt = charactersToGlyphBuffer + model->mVisualModel->mCharactersToGlyph.Count();
-        it != endIt;
-        ++it)
-    {
-      CharacterIndex& index = *it;
-      index -= numberOfGlyphsRemoved;
-    }
-
-    // Clear the character to glyph conversion table.
-    model->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
-                                                  charactersToGlyphBuffer + endIndexPlusOne);
-
-    // Clear the glyphs per character table.
-    model->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
-                                                   glyphsPerCharacterBuffer + endIndexPlusOne);
-
-    // Clear the glyphs buffer.
-    GlyphInfo* glyphsBuffer = model->mVisualModel->mGlyphs.Begin();
-    model->mVisualModel->mGlyphs.Erase(glyphsBuffer + textUpdateInfo.mStartGlyphIndex,
-                                       glyphsBuffer + endGlyphIndexPlusOne);
-
-    CharacterIndex* glyphsToCharactersBuffer = model->mVisualModel->mGlyphsToCharacters.Begin();
-
-    // Update the glyph to character indices.
-    for(Vector<CharacterIndex>::Iterator it    = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
-                                         endIt = glyphsToCharactersBuffer + model->mVisualModel->mGlyphsToCharacters.Count();
-        it != endIt;
-        ++it)
-    {
-      CharacterIndex& index = *it;
-      index -= numberOfCharactersRemoved;
-    }
-
-    // Clear the glyphs to characters buffer.
-    model->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + textUpdateInfo.mStartGlyphIndex,
-                                                   glyphsToCharactersBuffer + endGlyphIndexPlusOne);
-
-    // Clear the characters per glyph buffer.
-    Length* charactersPerGlyphBuffer = model->mVisualModel->mCharactersPerGlyph.Begin();
-    model->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + textUpdateInfo.mStartGlyphIndex,
-                                                   charactersPerGlyphBuffer + endGlyphIndexPlusOne);
-
-    // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
-    if(0u != model->mVisualModel->mGlyphPositions.Count())
-    {
-      // Clear the positions buffer.
-      Vector2* positionsBuffer = model->mVisualModel->mGlyphPositions.Begin();
-      model->mVisualModel->mGlyphPositions.Erase(positionsBuffer + textUpdateInfo.mStartGlyphIndex,
-                                                 positionsBuffer + endGlyphIndexPlusOne);
-    }
-  }
-
-  if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
-  {
-    // Clear the lines.
-    uint32_t startRemoveIndex = model->mVisualModel->mLines.Count();
-    uint32_t endRemoveIndex   = startRemoveIndex;
-    ClearCharacterRuns(startIndex,
-                       endIndex,
-                       model->mVisualModel->mLines,
-                       startRemoveIndex,
-                       endRemoveIndex);
-
-    // Will update the glyph runs.
-    startRemoveIndex = model->mVisualModel->mLines.Count();
-    endRemoveIndex   = startRemoveIndex;
-    ClearGlyphRuns(textUpdateInfo.mStartGlyphIndex,
-                   endGlyphIndexPlusOne - 1u,
-                   model->mVisualModel->mLines,
-                   startRemoveIndex,
-                   endRemoveIndex);
-
-    // Set the line index from where to insert the new laid-out lines.
-    textUpdateInfo.mStartLineIndex = startRemoveIndex;
-
-    LineRun* linesBuffer = model->mVisualModel->mLines.Begin();
-    model->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
-                                      linesBuffer + endRemoveIndex);
-  }
-
-  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
-  {
-    if(0u != model->mVisualModel->mColorIndices.Count())
-    {
-      ColorIndex* colorIndexBuffer = model->mVisualModel->mColorIndices.Begin();
-      model->mVisualModel->mColorIndices.Erase(colorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
-                                                colorIndexBuffer + endGlyphIndexPlusOne);
-    }
-
-    if(0u != model->mVisualModel->mBackgroundColorIndices.Count())
-    {
-      ColorIndex* backgroundColorIndexBuffer = model->mVisualModel->mBackgroundColorIndices.Begin();
-      model->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
-                                                         backgroundColorIndexBuffer + endGlyphIndexPlusOne);
-    }
-  }
-}
-
-void ControllerImplDataClearer::ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
-{
-  TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
-
-  if(textUpdateInfo.mClearAll ||
-     ((0u == startIndex) &&
-      (textUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
-  {
-    ClearFullModelData(impl, operations);
-  }
-  else
-  {
-    // Clear the model data related with characters.
-    ClearCharacterModelData(impl, startIndex, endIndex, operations);
-
-    // Clear the model data related with glyphs.
-    ClearGlyphModelData(impl, startIndex, endIndex, operations);
-  }
-
-  ModelPtr& model = impl.mModel;
-
-  // The estimated number of lines. Used to avoid reallocations when layouting.
-  textUpdateInfo.mEstimatedNumberOfLines = std::max(model->mVisualModel->mLines.Count(), model->mLogicalModel->mParagraphInfo.Count());
-
-  model->mVisualModel->ClearCaches();
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller-impl-data-clearer.h b/dali-toolkit/internal/text/text-controller-impl-data-clearer.h
deleted file mode 100644 (file)
index 87d6e24..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-
-namespace Dali::Toolkit::Text
-{
-
-/// Provides methods to clear some of the model data in the Text::Controller::Impl
-struct ControllerImplDataClearer
-{
-
-  /**
-   * @brief Helper to clear completely the parts of the model specified by the given @p operations.
-   *
-   * @note It never clears the text stored in utf32.
-   *
-   * @param[in] impl The text controller impl.
-   * @param[in] operations The operations required.
-   */
-  static void ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations);
-
-  /**
-   * @brief Helper to clear completely the parts of the model related with the characters specified by the given @p operations.
-   *
-   * @note It never clears the text stored in utf32.
-   *
-   * @param[in] impl The text controller impl.
-   * @param[in] startIndex Index to the first character to be cleared.
-   * @param[in] endIndex Index to the last character to be cleared.
-   * @param[in] operations The operations required.
-   */
-  static void ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
-
-  /**
-   * @brief Helper to clear completely the parts of the model related with the glyphs specified by the given @p operations.
-   *
-   * @note It never clears the text stored in utf32.
-   * @note Character indices are transformed to glyph indices.
-   *
-   * @param[in] impl The text controller impl.
-   * @param[in] startIndex Index to the first character to be cleared.
-   * @param[in] endIndex Index to the last character to be cleared.
-   * @param[in] operations The operations required.
-   */
-  static void ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
-
-  /**
-   * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
-   *
-   * @note It never clears the text stored in utf32.
-   *
-   * @param[in] impl The text controller impl.
-   * @param[in] startIndex Index to the first character to be cleared.
-   * @param[in] endIndex Index to the last character to be cleared.
-   * @param[in] operations The operations required.
-   */
-  static void ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations);
-};
-
-} // namespace Dali::Toolkit::Text
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_DATA_CLEARER_H
diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp b/dali-toolkit/internal/text/text-controller-impl-event-handler.cpp
deleted file mode 100644 (file)
index 1ed8c7f..0000000
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/adaptor-framework/key.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-
-using namespace Dali;
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-bool ControllerImplEventHandler::ProcessInputEvents(Controller::Impl& impl)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::ProcessInputEvents\n");
-
-  EventData*& eventData = impl.mEventData;
-  if(NULL == eventData)
-  {
-    // Nothing to do if there is no text input.
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents no event data\n");
-    return false;
-  }
-
-  unsigned int oldPos = eventData->mPrimaryCursorPosition;
-
-  if(eventData->mDecorator)
-  {
-    for(std::vector<Event>::iterator iter = eventData->mEventQueue.begin();
-        iter != eventData->mEventQueue.end();
-        ++iter)
-    {
-      switch(iter->type)
-      {
-        case Event::CURSOR_KEY_EVENT:
-        {
-          OnCursorKeyEvent(impl, *iter);
-          break;
-        }
-        case Event::TAP_EVENT:
-        {
-          OnTapEvent(impl, *iter);
-          break;
-        }
-        case Event::LONG_PRESS_EVENT:
-        {
-          OnLongPressEvent(impl, *iter);
-          break;
-        }
-        case Event::PAN_EVENT:
-        {
-          OnPanEvent(impl, *iter);
-          break;
-        }
-        case Event::GRAB_HANDLE_EVENT:
-        case Event::LEFT_SELECTION_HANDLE_EVENT:
-        case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through
-        {
-          OnHandleEvent(impl, *iter);
-          break;
-        }
-        case Event::SELECT:
-        {
-          OnSelectEvent(impl, *iter);
-          break;
-        }
-        case Event::SELECT_ALL:
-        {
-          OnSelectAllEvent(impl);
-          break;
-        }
-        case Event::SELECT_NONE:
-        {
-          OnSelectNoneEvent(impl);
-          break;
-        }
-        case Event::SELECT_RANGE:
-        {
-          OnSelectRangeEvent(impl, *iter);
-          break;
-        }
-      }
-    }
-  }
-
-  if(eventData->mUpdateCursorPosition ||
-     eventData->mUpdateHighlightBox)
-  {
-    impl.NotifyInputMethodContext();
-  }
-
-  // The cursor must also be repositioned after inserts into the model
-  if(eventData->mUpdateCursorPosition)
-  {
-    // Updates the cursor position and scrolls the text to make it visible.
-    CursorInfo cursorInfo;
-
-    // Calculate the cursor position from the new cursor index.
-    impl.GetCursorPosition(eventData->mPrimaryCursorPosition, cursorInfo);
-
-    //only emit the event if the cursor is moved in current function.
-    if(nullptr != impl.mEditableControlInterface && eventData->mEventQueue.size() > 0)
-    {
-      impl.mEditableControlInterface->CursorPositionChanged(oldPos, eventData->mPrimaryCursorPosition);
-    }
-
-    if(eventData->mUpdateCursorHookPosition)
-    {
-      // Update the cursor hook position. Used to move the cursor with the keys 'up' and 'down'.
-      eventData->mCursorHookPositionX      = cursorInfo.primaryPosition.x;
-      eventData->mUpdateCursorHookPosition = false;
-    }
-
-    // Scroll first the text after delete ...
-    if(eventData->mScrollAfterDelete)
-    {
-      impl.ScrollTextToMatchCursor(cursorInfo);
-    }
-
-    // ... then, text can be scrolled to make the cursor visible.
-    if(eventData->mScrollAfterUpdatePosition)
-    {
-      const Vector2 currentCursorPosition(cursorInfo.primaryPosition.x, cursorInfo.lineOffset);
-      impl.ScrollToMakePositionVisible(currentCursorPosition, cursorInfo.lineHeight);
-    }
-    eventData->mScrollAfterUpdatePosition = false;
-    eventData->mScrollAfterDelete         = false;
-
-    impl.UpdateCursorPosition(cursorInfo);
-
-    eventData->mDecoratorUpdated         = true;
-    eventData->mUpdateCursorPosition     = false;
-    eventData->mUpdateGrabHandlePosition = false;
-  }
-
-  if(eventData->mUpdateHighlightBox ||
-     eventData->mUpdateLeftSelectionPosition ||
-     eventData->mUpdateRightSelectionPosition)
-  {
-    CursorInfo leftHandleInfo;
-    CursorInfo rightHandleInfo;
-
-    if(eventData->mUpdateHighlightBox)
-    {
-      impl.GetCursorPosition(eventData->mLeftSelectionPosition, leftHandleInfo);
-
-      impl.GetCursorPosition(eventData->mRightSelectionPosition, rightHandleInfo);
-
-      if(eventData->mScrollAfterUpdatePosition && (eventData->mIsLeftHandleSelected ? eventData->mUpdateLeftSelectionPosition : eventData->mUpdateRightSelectionPosition))
-      {
-        if(eventData->mIsLeftHandleSelected && eventData->mIsRightHandleSelected)
-        {
-          CursorInfo& infoLeft = leftHandleInfo;
-
-          const Vector2 currentCursorPositionLeft(infoLeft.primaryPosition.x, infoLeft.lineOffset);
-          impl.ScrollToMakePositionVisible(currentCursorPositionLeft, infoLeft.lineHeight);
-
-          CursorInfo& infoRight = rightHandleInfo;
-
-          const Vector2 currentCursorPositionRight(infoRight.primaryPosition.x, infoRight.lineOffset);
-          impl.ScrollToMakePositionVisible(currentCursorPositionRight, infoRight.lineHeight);
-        }
-        else
-        {
-          CursorInfo& info = eventData->mIsLeftHandleSelected ? leftHandleInfo : rightHandleInfo;
-
-          const Vector2 currentCursorPosition(info.primaryPosition.x, info.lineOffset);
-          impl.ScrollToMakePositionVisible(currentCursorPosition, info.lineHeight);
-        }
-      }
-    }
-
-    if(eventData->mUpdateLeftSelectionPosition)
-    {
-      impl.UpdateSelectionHandle(LEFT_SELECTION_HANDLE, leftHandleInfo);
-
-      impl.SetPopupButtons();
-      eventData->mDecoratorUpdated            = true;
-      eventData->mUpdateLeftSelectionPosition = false;
-    }
-
-    if(eventData->mUpdateRightSelectionPosition)
-    {
-      impl.UpdateSelectionHandle(RIGHT_SELECTION_HANDLE, rightHandleInfo);
-
-      impl.SetPopupButtons();
-      eventData->mDecoratorUpdated             = true;
-      eventData->mUpdateRightSelectionPosition = false;
-    }
-
-    if(eventData->mUpdateHighlightBox)
-    {
-      impl.RepositionSelectionHandles();
-
-      eventData->mUpdateLeftSelectionPosition  = false;
-      eventData->mUpdateRightSelectionPosition = false;
-      eventData->mUpdateHighlightBox           = false;
-      eventData->mIsLeftHandleSelected         = false;
-      eventData->mIsRightHandleSelected        = false;
-    }
-
-    eventData->mScrollAfterUpdatePosition = false;
-  }
-
-  if(eventData->mUpdateInputStyle)
-  {
-    // Keep a copy of the current input style.
-    InputStyle currentInputStyle;
-    currentInputStyle.Copy(eventData->mInputStyle);
-
-    // Set the default style first.
-    impl.RetrieveDefaultInputStyle(eventData->mInputStyle);
-
-    // Get the character index from the cursor index.
-    const CharacterIndex styleIndex = (eventData->mPrimaryCursorPosition > 0u) ? eventData->mPrimaryCursorPosition - 1u : 0u;
-
-    // Retrieve the style from the style runs stored in the logical model.
-    impl.mModel->mLogicalModel->RetrieveStyle(styleIndex, eventData->mInputStyle);
-
-    // Compare if the input style has changed.
-    const bool hasInputStyleChanged = !currentInputStyle.Equal(eventData->mInputStyle);
-
-    if(hasInputStyleChanged)
-    {
-      const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(eventData->mInputStyle);
-      // Queue the input style changed signal.
-      eventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
-    }
-
-    eventData->mUpdateInputStyle = false;
-  }
-
-  eventData->mEventQueue.clear();
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n");
-
-  const bool decoratorUpdated  = eventData->mDecoratorUpdated;
-  eventData->mDecoratorUpdated = false;
-
-  return decoratorUpdated;
-}
-
-void ControllerImplEventHandler::OnCursorKeyEvent(Controller::Impl& impl, const Event& event)
-{
-  if(NULL == impl.mEventData || !impl.IsShowingRealText())
-  {
-    // Nothing to do if there is no text input.
-    return;
-  }
-
-  int              keyCode         = event.p1.mInt;
-  bool             isShiftModifier = event.p2.mBool;
-  EventData&       eventData       = *impl.mEventData;
-  ModelPtr&        model           = impl.mModel;
-  LogicalModelPtr& logicalModel    = model->mLogicalModel;
-  VisualModelPtr&  visualModel     = model->mVisualModel;
-  uint32_t         oldSelStart     = eventData.mLeftSelectionPosition;
-  uint32_t         oldSelEnd       = eventData.mRightSelectionPosition;
-
-  CharacterIndex& primaryCursorPosition         = eventData.mPrimaryCursorPosition;
-  CharacterIndex  previousPrimaryCursorPosition = primaryCursorPosition;
-
-  if(Dali::DALI_KEY_CURSOR_LEFT == keyCode)
-  {
-    if(primaryCursorPosition > 0u)
-    {
-      if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible())
-      {
-        primaryCursorPosition = std::min(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-      }
-      else
-      {
-        primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition - 1u);
-      }
-    }
-  }
-  else if(Dali::DALI_KEY_CURSOR_RIGHT == keyCode)
-  {
-    if(logicalModel->mText.Count() > primaryCursorPosition)
-    {
-      if(!isShiftModifier && eventData.mDecorator->IsHighlightVisible())
-      {
-        primaryCursorPosition = std::max(eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-      }
-      else
-      {
-        primaryCursorPosition = impl.CalculateNewCursorIndex(primaryCursorPosition);
-      }
-    }
-  }
-  else if(Dali::DALI_KEY_CURSOR_UP == keyCode && !isShiftModifier)
-  {
-    // Ignore Shift-Up for text selection for now.
-
-    // Get first the line index of the current cursor position index.
-    CharacterIndex characterIndex = 0u;
-
-    if(primaryCursorPosition > 0u)
-    {
-      characterIndex = primaryCursorPosition - 1u;
-    }
-
-    const LineIndex lineIndex         = visualModel->GetLineOfCharacter(characterIndex);
-    const LineIndex previousLineIndex = (lineIndex > 0 ? lineIndex - 1u : lineIndex);
-    const LineIndex lastLineIndex     = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
-    const bool      isLastLine        = (previousLineIndex == lastLineIndex);
-
-    // Retrieve the cursor position info.
-    CursorInfo cursorInfo;
-    impl.GetCursorPosition(primaryCursorPosition,
-                           cursorInfo);
-
-    // Get the line above.
-    const LineRun& line = *(visualModel->mLines.Begin() + previousLineIndex);
-
-    // Get the next hit 'y' point.
-    const float hitPointY = cursorInfo.lineOffset - 0.5f * GetLineHeight(line, isLastLine);
-
-    // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
-    bool matchedCharacter = false;
-    primaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
-                                                        logicalModel,
-                                                        impl.mMetrics,
-                                                        eventData.mCursorHookPositionX,
-                                                        hitPointY,
-                                                        CharacterHitTest::TAP,
-                                                        matchedCharacter);
-  }
-  else if(Dali::DALI_KEY_CURSOR_DOWN == keyCode && !isShiftModifier)
-  {
-    // Ignore Shift-Down for text selection for now.
-
-    // Get first the line index of the current cursor position index.
-    CharacterIndex characterIndex = 0u;
-
-    if(primaryCursorPosition > 0u)
-    {
-      characterIndex = primaryCursorPosition - 1u;
-    }
-
-    const LineIndex lineIndex = visualModel->GetLineOfCharacter(characterIndex);
-
-    if(lineIndex + 1u < visualModel->mLines.Count())
-    {
-      // Retrieve the cursor position info.
-      CursorInfo cursorInfo;
-      impl.GetCursorPosition(primaryCursorPosition, cursorInfo);
-
-      // Get the line below.
-      const LineRun& nextline = *(visualModel->mLines.Begin() + lineIndex + 1u);
-      const LineRun& currline = *(visualModel->mLines.Begin() + lineIndex);
-
-      // Get last line index
-      const LineIndex lastLineIndex = (visualModel->mLines.Size() > 0 ? visualModel->mLines.Size() - 1u : 0);
-      const bool      isLastLine    = (lineIndex + 1u == lastLineIndex);
-
-      // Get the next hit 'y' point.
-      const float hitPointY = cursorInfo.lineOffset + GetLineHeight(currline, false) + 0.5f * GetLineHeight(nextline, isLastLine);
-
-      // Use the cursor hook position 'x' and the next hit 'y' position to calculate the new cursor index.
-      bool matchedCharacter = false;
-      primaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
-                                                          logicalModel,
-                                                          impl.mMetrics,
-                                                          eventData.mCursorHookPositionX,
-                                                          hitPointY,
-                                                          CharacterHitTest::TAP,
-                                                          matchedCharacter);
-    }
-  }
-
-  if(!isShiftModifier && eventData.mState != EventData::SELECTING)
-  {
-    // Update selection position after moving the cursor
-    eventData.mLeftSelectionPosition  = primaryCursorPosition;
-    eventData.mRightSelectionPosition = primaryCursorPosition;
-
-    if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
-    {
-      impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-    }
-  }
-
-  if(isShiftModifier && impl.IsShowingRealText() && eventData.mShiftSelectionFlag)
-  {
-    // Handle text selection
-    bool selecting = false;
-
-    if(Dali::DALI_KEY_CURSOR_LEFT == keyCode || Dali::DALI_KEY_CURSOR_RIGHT == keyCode)
-    {
-      // Shift-Left/Right to select the text
-      int cursorPositionDelta = primaryCursorPosition - previousPrimaryCursorPosition;
-      if(cursorPositionDelta > 0 || eventData.mRightSelectionPosition > 0u) // Check the boundary
-      {
-        eventData.mRightSelectionPosition += cursorPositionDelta;
-        eventData.mPrimaryCursorPosition = eventData.mRightSelectionPosition;
-
-        if(impl.mSelectableControlInterface != nullptr)
-        {
-          impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-        }
-      }
-
-      if(impl.mSelectableControlInterface != nullptr && eventData.mLeftSelectionPosition == eventData.mRightSelectionPosition)
-      {
-        // If left selection position and right selection position are the same, the selection is canceled.
-        selecting = false;
-      }
-      else
-      {
-        selecting = true;
-      }
-    }
-    else if(eventData.mLeftSelectionPosition != eventData.mRightSelectionPosition)
-    {
-      // Show no grab handles and text highlight if Shift-Up/Down pressed but no selected text
-      selecting = true;
-    }
-
-    if(selecting)
-    {
-      // Notify the cursor position to the InputMethodContext.
-      if(eventData.mInputMethodContext)
-      {
-        eventData.mInputMethodContext.SetCursorPosition(primaryCursorPosition);
-        eventData.mInputMethodContext.NotifyCursorPosition();
-      }
-
-      impl.ChangeState(EventData::SELECTING);
-
-      eventData.mUpdateLeftSelectionPosition  = true;
-      eventData.mUpdateRightSelectionPosition = true;
-      eventData.mUpdateGrabHandlePosition     = true;
-      eventData.mUpdateHighlightBox           = true;
-
-      // Hide the text selection popup if select the text using keyboard instead of moving grab handles
-      if(eventData.mGrabHandlePopupEnabled)
-      {
-        eventData.mDecorator->SetPopupActive(false);
-      }
-    }
-    else
-    {
-      // If no selection, set a normal cursor.
-      impl.ChangeState(EventData::EDITING);
-      eventData.mUpdateCursorPosition = true;
-    }
-  }
-  else
-  {
-    // Handle normal cursor move
-    impl.ChangeState(EventData::EDITING);
-    eventData.mUpdateCursorPosition = true;
-  }
-
-  eventData.mUpdateInputStyle          = true;
-  eventData.mScrollAfterUpdatePosition = true;
-}
-
-void ControllerImplEventHandler::OnTapEvent(Controller::Impl& impl, const Event& event)
-{
-  if(impl.mEventData)
-  {
-    const unsigned int tapCount     = event.p1.mUint;
-    EventData&         eventData    = *impl.mEventData;
-    ModelPtr&          model        = impl.mModel;
-    LogicalModelPtr&   logicalModel = model->mLogicalModel;
-    VisualModelPtr&    visualModel  = model->mVisualModel;
-
-    if(1u == tapCount)
-    {
-      if(impl.IsShowingRealText())
-      {
-        // Convert from control's coords to text's coords.
-        const float xPosition   = event.p2.mFloat - model->mScrollPosition.x;
-        const float yPosition   = event.p3.mFloat - model->mScrollPosition.y;
-        uint32_t    oldSelStart = eventData.mLeftSelectionPosition;
-        uint32_t    oldSelEnd   = eventData.mRightSelectionPosition;
-
-        // Keep the tap 'x' position. Used to move the cursor.
-        eventData.mCursorHookPositionX = xPosition;
-
-        // Whether to touch point hits on a glyph.
-        bool matchedCharacter            = false;
-        eventData.mPrimaryCursorPosition = Text::GetClosestCursorIndex(visualModel,
-                                                                       logicalModel,
-                                                                       impl.mMetrics,
-                                                                       xPosition,
-                                                                       yPosition,
-                                                                       CharacterHitTest::TAP,
-                                                                       matchedCharacter);
-
-        if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
-        {
-          impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mPrimaryCursorPosition, eventData.mPrimaryCursorPosition);
-        }
-
-        // When the cursor position is changing, delay cursor blinking
-        eventData.mDecorator->DelayCursorBlink();
-      }
-      else
-      {
-        eventData.mPrimaryCursorPosition = 0u;
-      }
-
-      // Update selection position after tapping
-      eventData.mLeftSelectionPosition  = eventData.mPrimaryCursorPosition;
-      eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition;
-
-      eventData.mUpdateCursorPosition      = true;
-      eventData.mUpdateGrabHandlePosition  = true;
-      eventData.mScrollAfterUpdatePosition = true;
-      eventData.mUpdateInputStyle          = true;
-
-      // Notify the cursor position to the InputMethodContext.
-      if(eventData.mInputMethodContext)
-      {
-        eventData.mInputMethodContext.SetCursorPosition(eventData.mPrimaryCursorPosition);
-        eventData.mInputMethodContext.NotifyCursorPosition();
-      }
-    }
-    else if(2u == tapCount)
-    {
-      if(eventData.mSelectionEnabled)
-      {
-        // Convert from control's coords to text's coords.
-        const float xPosition = event.p2.mFloat - model->mScrollPosition.x;
-        const float yPosition = event.p3.mFloat - model->mScrollPosition.y;
-
-        // Calculates the logical position from the x,y coords.
-        impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mDoubleTapAction);
-      }
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnPanEvent(Controller::Impl& impl, const Event& event)
-{
-  if(impl.mEventData)
-  {
-    EventData&    eventData = *impl.mEventData;
-    DecoratorPtr& decorator = eventData.mDecorator;
-
-    const bool isHorizontalScrollEnabled = decorator->IsHorizontalScrollEnabled();
-    const bool isVerticalScrollEnabled   = decorator->IsVerticalScrollEnabled();
-
-    if(!isHorizontalScrollEnabled && !isVerticalScrollEnabled)
-    {
-      // Nothing to do if scrolling is not enabled.
-      return;
-    }
-
-    const GestureState state = static_cast<GestureState>(event.p1.mInt);
-    switch(state)
-    {
-      case GestureState::STARTED:
-      {
-        // Will remove the cursor, handles or text's popup, ...
-        impl.ChangeState(EventData::TEXT_PANNING);
-        break;
-      }
-      case GestureState::CONTINUING:
-      {
-        ModelPtr& model = impl.mModel;
-
-        const Vector2& layoutSize     = model->mVisualModel->GetLayoutSize();
-        Vector2&       scrollPosition = model->mScrollPosition;
-        const Vector2  currentScroll  = scrollPosition;
-
-        if(isHorizontalScrollEnabled)
-        {
-          const float displacementX = event.p2.mFloat;
-          scrollPosition.x += displacementX;
-
-          impl.ClampHorizontalScroll(layoutSize);
-        }
-
-        if(isVerticalScrollEnabled)
-        {
-          const float displacementY = event.p3.mFloat;
-          scrollPosition.y += displacementY;
-
-          impl.ClampVerticalScroll(layoutSize);
-        }
-
-        decorator->UpdatePositions(scrollPosition - currentScroll);
-        break;
-      }
-      case GestureState::FINISHED:
-      case GestureState::CANCELLED: // FALLTHROUGH
-      {
-        // Will go back to the previous state to show the cursor, handles, the text's popup, ...
-        impl.ChangeState(eventData.mPreviousState);
-        break;
-      }
-      default:
-        break;
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnLongPressEvent(Controller::Impl& impl, const Event& event)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::OnLongPressEvent\n");
-
-  if(impl.mEventData)
-  {
-    EventData& eventData = *impl.mEventData;
-
-    if(!impl.IsShowingRealText() && (EventData::EDITING == eventData.mState))
-    {
-      impl.ChangeState(EventData::EDITING_WITH_POPUP);
-      eventData.mDecoratorUpdated = true;
-      eventData.mUpdateInputStyle = true;
-    }
-    else
-    {
-      if(eventData.mSelectionEnabled)
-      {
-        ModelPtr& model = impl.mModel;
-
-        // Convert from control's coords to text's coords.
-        const float xPosition = event.p2.mFloat - model->mScrollPosition.x;
-        const float yPosition = event.p3.mFloat - model->mScrollPosition.y;
-
-        // Calculates the logical position from the x,y coords.
-        impl.RepositionSelectionHandles(xPosition, yPosition, eventData.mLongPressAction);
-      }
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnHandleEvent(Controller::Impl& impl, const Event& event)
-{
-  if(impl.mEventData)
-  {
-    const unsigned int state                    = event.p1.mUint;
-    const bool         handleStopScrolling      = (HANDLE_STOP_SCROLLING == state);
-    const bool         isSmoothHandlePanEnabled = impl.mEventData->mDecorator->IsSmoothHandlePanEnabled();
-
-    if(HANDLE_PRESSED == state)
-    {
-      OnHandlePressed(impl, event, isSmoothHandlePanEnabled);
-    } // end ( HANDLE_PRESSED == state )
-    else if((HANDLE_RELEASED == state) ||
-            handleStopScrolling)
-    {
-      OnHandleReleased(impl, event, isSmoothHandlePanEnabled, handleStopScrolling);
-    } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) )
-    else if(HANDLE_SCROLLING == state)
-    {
-      OnHandleScrolling(impl, event, isSmoothHandlePanEnabled);
-    } // end ( HANDLE_SCROLLING == state )
-  }
-}
-
-void ControllerImplEventHandler::OnSelectEvent(Controller::Impl& impl, const Event& event)
-{
-  if(impl.mEventData && impl.mEventData->mSelectionEnabled)
-  {
-    ModelPtr&      model          = impl.mModel;
-    const Vector2& scrollPosition = model->mScrollPosition;
-
-    // Convert from control's coords to text's coords.
-    const float xPosition = event.p2.mFloat - scrollPosition.x;
-    const float yPosition = event.p3.mFloat - scrollPosition.y;
-
-    // Calculates the logical position from the x,y coords.
-    impl.RepositionSelectionHandles(xPosition, yPosition, Controller::NoTextTap::HIGHLIGHT);
-  }
-}
-
-void ControllerImplEventHandler::OnSelectAllEvent(Controller::Impl& impl)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectAllEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false");
-
-  if(impl.mEventData)
-  {
-    EventData& eventData = *impl.mEventData;
-    if(eventData.mSelectionEnabled && eventData.mState != EventData::INACTIVE)
-    {
-      ModelPtr&      model          = impl.mModel;
-      const Vector2& scrollPosition = model->mScrollPosition;
-
-      // Calculates the logical position from the start.
-      impl.RepositionSelectionHandles(0.f - scrollPosition.x,
-                                      0.f - scrollPosition.y,
-                                      Controller::NoTextTap::HIGHLIGHT);
-
-      uint32_t oldStart = eventData.mLeftSelectionPosition;
-      uint32_t oldEnd   = eventData.mRightSelectionPosition;
-
-      eventData.mLeftSelectionPosition  = 0u;
-      eventData.mRightSelectionPosition = model->mLogicalModel->mText.Count();
-      eventData.mPrimaryCursorPosition  = eventData.mRightSelectionPosition;
-
-      if(impl.mSelectableControlInterface != nullptr)
-      {
-        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-      }
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnSelectNoneEvent(Controller::Impl& impl)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "OnSelectNoneEvent mEventData->mSelectionEnabled%s \n", impl.mEventData->mSelectionEnabled ? "true" : "false");
-
-  if(impl.mEventData)
-  {
-    EventData& eventData = *impl.mEventData;
-    if(eventData.mSelectionEnabled && eventData.mState == EventData::SELECTING)
-    {
-      uint32_t oldStart = eventData.mLeftSelectionPosition;
-      uint32_t oldEnd   = eventData.mRightSelectionPosition;
-
-      eventData.mLeftSelectionPosition = eventData.mRightSelectionPosition = eventData.mPrimaryCursorPosition;
-      impl.ChangeState(EventData::EDITING);
-      eventData.mUpdateCursorPosition      = true;
-      eventData.mUpdateInputStyle          = true;
-      eventData.mScrollAfterUpdatePosition = true;
-
-      if(impl.mSelectableControlInterface != nullptr)
-      {
-        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-      }
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnSelectRangeEvent(Controller::Impl& impl, const Event& event)
-{
-  if(impl.mEventData && impl.mEventData->mSelectionEnabled && impl.mEventData->mState != EventData::INACTIVE)
-  {
-    ModelPtr&      model          = impl.mModel;
-    const Vector2& scrollPosition = model->mScrollPosition;
-
-    // Calculate the selection index.
-    const uint32_t length = static_cast<uint32_t>(model->mLogicalModel->mText.Count());
-    const uint32_t start  = std::min(event.p2.mUint, length);
-    const uint32_t end    = std::min(event.p3.mUint, length);
-
-    if(start != end)
-    {
-      uint32_t oldStart = impl.mEventData->mLeftSelectionPosition;
-      uint32_t oldEnd   = impl.mEventData->mRightSelectionPosition;
-
-      // Calculates the logical position from the x,y coords.
-      impl.RepositionSelectionHandles(0.f - scrollPosition.x, 0.f - scrollPosition.y, Controller::NoTextTap::HIGHLIGHT);
-
-      impl.mEventData->mLeftSelectionPosition  = start;
-      impl.mEventData->mRightSelectionPosition = end;
-      impl.mEventData->mPrimaryCursorPosition  = end;
-
-      if(impl.mSelectableControlInterface != nullptr)
-      {
-        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
-      }
-    }
-  }
-}
-
-void ControllerImplEventHandler::OnHandlePressed(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled)
-{
-  ModelPtr&      model          = impl.mModel;
-  const Vector2& scrollPosition = model->mScrollPosition;
-
-  // Convert from decorator's coords to text's coords.
-  const float xPosition = event.p2.mFloat - scrollPosition.x;
-  const float yPosition = event.p3.mFloat - scrollPosition.y;
-
-  // Need to calculate the handle's new position.
-  bool                 matchedCharacter  = false;
-  const CharacterIndex handleNewPosition = Text::GetClosestCursorIndex(model->mVisualModel,
-                                                                       model->mLogicalModel,
-                                                                       impl.mMetrics,
-                                                                       xPosition,
-                                                                       yPosition,
-                                                                       CharacterHitTest::SCROLL,
-                                                                       matchedCharacter);
-
-  EventData& eventData = *impl.mEventData;
-  uint32_t   oldStart  = eventData.mLeftSelectionPosition;
-  uint32_t   oldEnd    = eventData.mRightSelectionPosition;
-
-  if(Event::GRAB_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::GRAB_HANDLE_PANNING);
-
-    if(handleNewPosition != eventData.mPrimaryCursorPosition)
-    {
-      // Updates the cursor position if the handle's new position is different than the current one.
-      eventData.mUpdateCursorPosition = true;
-      // Does not update the grab handle position if the smooth panning is enabled. (The decorator does it smooth).
-      eventData.mUpdateGrabHandlePosition = !isSmoothHandlePanEnabled;
-      eventData.mPrimaryCursorPosition    = handleNewPosition;
-    }
-
-    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
-  }
-  else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
-
-    if((handleNewPosition != eventData.mLeftSelectionPosition) &&
-       (handleNewPosition != eventData.mRightSelectionPosition))
-    {
-      // Updates the highlight box if the handle's new position is different than the current one.
-      eventData.mUpdateHighlightBox = true;
-      // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
-      eventData.mUpdateLeftSelectionPosition = !isSmoothHandlePanEnabled;
-      eventData.mLeftSelectionPosition       = handleNewPosition;
-    }
-
-    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
-
-    // Will define the order to scroll the text to match the handle position.
-    eventData.mIsLeftHandleSelected  = true;
-    eventData.mIsRightHandleSelected = false;
-  }
-  else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
-
-    if((handleNewPosition != eventData.mRightSelectionPosition) &&
-       (handleNewPosition != eventData.mLeftSelectionPosition))
-    {
-      // Updates the highlight box if the handle's new position is different than the current one.
-      eventData.mUpdateHighlightBox = true;
-      // Does not update the selection handle position if the smooth panning is enabled. (The decorator does it smooth).
-      eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
-      eventData.mRightSelectionPosition       = handleNewPosition;
-    }
-
-    // Updates the decorator if the soft handle panning is enabled. It triggers a relayout in the decorator and the new position of the handle is set.
-    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
-
-    // Will define the order to scroll the text to match the handle position.
-    eventData.mIsLeftHandleSelected  = false;
-    eventData.mIsRightHandleSelected = true;
-  }
-
-  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
-  {
-    impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-  }
-}
-
-void ControllerImplEventHandler::OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling)
-{
-  CharacterIndex handlePosition = 0u;
-  if(handleStopScrolling || isSmoothHandlePanEnabled)
-  {
-    ModelPtr&      model          = impl.mModel;
-    const Vector2& scrollPosition = model->mScrollPosition;
-
-    // Convert from decorator's coords to text's coords.
-    const float xPosition = event.p2.mFloat - scrollPosition.x;
-    const float yPosition = event.p3.mFloat - scrollPosition.y;
-
-    bool matchedCharacter = false;
-    handlePosition        = Text::GetClosestCursorIndex(model->mVisualModel,
-                                                 model->mLogicalModel,
-                                                 impl.mMetrics,
-                                                 xPosition,
-                                                 yPosition,
-                                                 CharacterHitTest::SCROLL,
-                                                 matchedCharacter);
-  }
-
-  EventData& eventData = *impl.mEventData;
-  uint32_t   oldStart  = eventData.mLeftSelectionPosition;
-  uint32_t   oldEnd    = eventData.mRightSelectionPosition;
-
-  if(Event::GRAB_HANDLE_EVENT == event.type)
-  {
-    eventData.mUpdateCursorPosition     = true;
-    eventData.mUpdateGrabHandlePosition = true;
-    eventData.mUpdateInputStyle         = true;
-
-    if(!impl.IsClipboardEmpty())
-    {
-      impl.ChangeState(EventData::EDITING_WITH_PASTE_POPUP); // Moving grabhandle will show Paste Popup
-    }
-
-    if(handleStopScrolling || isSmoothHandlePanEnabled)
-    {
-      eventData.mScrollAfterUpdatePosition = true;
-      eventData.mPrimaryCursorPosition     = handlePosition;
-    }
-  }
-  else if(Event::LEFT_SELECTION_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::SELECTING);
-
-    eventData.mUpdateHighlightBox           = true;
-    eventData.mUpdateLeftSelectionPosition  = true;
-    eventData.mUpdateRightSelectionPosition = true;
-
-    if(handleStopScrolling || isSmoothHandlePanEnabled)
-    {
-      eventData.mScrollAfterUpdatePosition = true;
-
-      if((handlePosition != eventData.mRightSelectionPosition) &&
-         (handlePosition != eventData.mLeftSelectionPosition))
-      {
-        eventData.mLeftSelectionPosition = handlePosition;
-      }
-    }
-  }
-  else if(Event::RIGHT_SELECTION_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::SELECTING);
-
-    eventData.mUpdateHighlightBox           = true;
-    eventData.mUpdateRightSelectionPosition = true;
-    eventData.mUpdateLeftSelectionPosition  = true;
-
-    if(handleStopScrolling || isSmoothHandlePanEnabled)
-    {
-      eventData.mScrollAfterUpdatePosition = true;
-      if((handlePosition != eventData.mRightSelectionPosition) &&
-         (handlePosition != eventData.mLeftSelectionPosition))
-      {
-        eventData.mRightSelectionPosition = handlePosition;
-      }
-    }
-  }
-
-  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
-  {
-    impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-  }
-
-  eventData.mDecoratorUpdated = true;
-}
-
-void ControllerImplEventHandler::OnHandleScrolling(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled)
-{
-  ModelPtr&       model          = impl.mModel;
-  Vector2&        scrollPosition = model->mScrollPosition;
-  VisualModelPtr& visualModel    = model->mVisualModel;
-
-  const float    xSpeed                = event.p2.mFloat;
-  const float    ySpeed                = event.p3.mFloat;
-  const Vector2& layoutSize            = visualModel->GetLayoutSize();
-  const Vector2  currentScrollPosition = scrollPosition;
-
-  scrollPosition.x += xSpeed;
-  scrollPosition.y += ySpeed;
-
-  impl.ClampHorizontalScroll(layoutSize);
-  impl.ClampVerticalScroll(layoutSize);
-
-  EventData&    eventData = *impl.mEventData;
-  DecoratorPtr& decorator = eventData.mDecorator;
-
-  bool endOfScroll = false;
-  if(Vector2::ZERO == (currentScrollPosition - scrollPosition))
-  {
-    // Notify the decorator there is no more text to scroll.
-    // The decorator won't send more scroll events.
-    decorator->NotifyEndOfScroll();
-    // Still need to set the position of the handle.
-    endOfScroll = true;
-  }
-
-  // Set the position of the handle.
-  const bool scrollRightDirection      = xSpeed > 0.f;
-  const bool scrollBottomDirection     = ySpeed > 0.f;
-  const bool leftSelectionHandleEvent  = Event::LEFT_SELECTION_HANDLE_EVENT == event.type;
-  const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type;
-
-  if(Event::GRAB_HANDLE_EVENT == event.type)
-  {
-    impl.ChangeState(EventData::GRAB_HANDLE_PANNING);
-
-    // Get the grab handle position in decorator coords.
-    Vector2 position = decorator->GetPosition(GRAB_HANDLE);
-
-    if(decorator->IsHorizontalScrollEnabled())
-    {
-      // Position the grag handle close to either the left or right edge.
-      position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width;
-    }
-
-    if(decorator->IsVerticalScrollEnabled())
-    {
-      position.x = eventData.mCursorHookPositionX;
-
-      // Position the grag handle close to either the top or bottom edge.
-      position.y = scrollBottomDirection ? 0.f : visualModel->mControlSize.height;
-    }
-
-    // Get the new handle position.
-    // The grab handle's position is in decorator's coords. Need to transforms to text's coords.
-    bool                 matchedCharacter = false;
-    const CharacterIndex handlePosition   = Text::GetClosestCursorIndex(visualModel,
-                                                                      impl.mModel->mLogicalModel,
-                                                                      impl.mMetrics,
-                                                                      position.x - scrollPosition.x,
-                                                                      position.y - scrollPosition.y,
-                                                                      CharacterHitTest::SCROLL,
-                                                                      matchedCharacter);
-
-    if(eventData.mPrimaryCursorPosition != handlePosition)
-    {
-      eventData.mUpdateCursorPosition      = true;
-      eventData.mUpdateGrabHandlePosition  = !isSmoothHandlePanEnabled;
-      eventData.mScrollAfterUpdatePosition = true;
-      eventData.mPrimaryCursorPosition     = handlePosition;
-    }
-    eventData.mUpdateInputStyle = eventData.mUpdateCursorPosition;
-
-    // Updates the decorator if the soft handle panning is enabled.
-    eventData.mDecoratorUpdated = isSmoothHandlePanEnabled;
-  }
-  else if(leftSelectionHandleEvent || rightSelectionHandleEvent)
-  {
-    impl.ChangeState(EventData::SELECTION_HANDLE_PANNING);
-
-    // Get the selection handle position in decorator coords.
-    Vector2 position = decorator->GetPosition(leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE);
-
-    if(decorator->IsHorizontalScrollEnabled())
-    {
-      // Position the selection handle close to either the left or right edge.
-      position.x = scrollRightDirection ? 0.f : visualModel->mControlSize.width;
-    }
-
-    if(decorator->IsVerticalScrollEnabled())
-    {
-      position.x = eventData.mCursorHookPositionX;
-
-      // Position the grag handle close to either the top or bottom edge.
-      position.y = scrollBottomDirection ? 0.f : visualModel->mControlSize.height;
-    }
-
-    // Get the new handle position.
-    // The selection handle's position is in decorator's coords. Need to transform to text's coords.
-    bool                 matchedCharacter = false;
-    const CharacterIndex handlePosition   = Text::GetClosestCursorIndex(visualModel,
-                                                                      impl.mModel->mLogicalModel,
-                                                                      impl.mMetrics,
-                                                                      position.x - scrollPosition.x,
-                                                                      position.y - scrollPosition.y,
-                                                                      CharacterHitTest::SCROLL,
-                                                                      matchedCharacter);
-    uint32_t             oldStart         = eventData.mLeftSelectionPosition;
-    uint32_t             oldEnd           = eventData.mRightSelectionPosition;
-
-    if(leftSelectionHandleEvent)
-    {
-      const bool differentHandles = (eventData.mLeftSelectionPosition != handlePosition) && (eventData.mRightSelectionPosition != handlePosition);
-
-      if(differentHandles || endOfScroll)
-      {
-        eventData.mUpdateHighlightBox           = true;
-        eventData.mUpdateLeftSelectionPosition  = !isSmoothHandlePanEnabled;
-        eventData.mUpdateRightSelectionPosition = isSmoothHandlePanEnabled;
-        eventData.mLeftSelectionPosition        = handlePosition;
-      }
-    }
-    else
-    {
-      const bool differentHandles = (eventData.mRightSelectionPosition != handlePosition) && (eventData.mLeftSelectionPosition != handlePosition);
-      if(differentHandles || endOfScroll)
-      {
-        eventData.mUpdateHighlightBox           = true;
-        eventData.mUpdateRightSelectionPosition = !isSmoothHandlePanEnabled;
-        eventData.mUpdateLeftSelectionPosition  = isSmoothHandlePanEnabled;
-        eventData.mRightSelectionPosition       = handlePosition;
-      }
-    }
-
-    if(eventData.mUpdateLeftSelectionPosition || eventData.mUpdateRightSelectionPosition)
-    {
-      impl.RepositionSelectionHandles();
-
-      eventData.mScrollAfterUpdatePosition = !isSmoothHandlePanEnabled;
-
-      if(impl.mSelectableControlInterface != nullptr)
-      {
-        impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
-      }
-    }
-  }
-  eventData.mDecoratorUpdated = true;
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-impl-event-handler.h b/dali-toolkit/internal/text/text-controller-impl-event-handler.h
deleted file mode 100644 (file)
index 82e5c78..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-/**
- * Contains all the event handling methods for Text::Controller::Impl
- */
-struct ControllerImplEventHandler
-{
-  /**
-   * @brief Processes input events
-   *
-   * @param[in] impl A reference to Controller::Impl
-   * @return True if the decorator has been updated
-   */
-  static bool ProcessInputEvents(Controller::Impl& impl);
-
-  /**
-   * @brief Called by Controller::Impl when a cursor key event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnCursorKeyEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a tap event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnTapEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a pan event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnPanEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a long press event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnLongPressEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a handle event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnHandleEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a select event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnSelectEvent(Controller::Impl& controllerImpl, const Event& event);
-
-  /**
-   * @brief Called by Controller::Impl when a select all event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnSelectAllEvent(Controller::Impl& controllerImpl);
-
-  /**
-   * @brief Called by Controller::Impl when a select none event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnSelectNoneEvent(Controller::Impl& controllerImpl);
-
-  /**
-   * @brief Called by Controller::Impl when a select range event is received.
-   *
-   * @param controllerImpl A reference to Controller::Impl
-   * @param event The event
-   */
-  static void OnSelectRangeEvent(Controller::Impl& controllerImpl, const Event& event);
-
-private:
-  /**
-   * @brief Called by OnHandleEvent when we are in the Pressed state.
-   *
-   * @param impl A reference to Controller::Impl
-   * @param event The event
-   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
-   */
-  static void OnHandlePressed(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled);
-
-  /**
-   * @brief Called by OnHandleEvent when we are in the Released state.
-   *
-   * @param impl A reference to Controller::Impl
-   * @param event The event
-   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
-   * @param handleStopScrolling Whether we should handle stop scrolling or not
-   */
-  static void OnHandleReleased(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled, const bool handleStopScrolling);
-
-  /**
-   * @brief Called by OnHandleEvent when we are in the Scrolling state.
-   *
-   * @param impl A reference to Controller::Impl
-   * @param event The event
-   * @param isSmoothHandlePanEnabled Whether smooth handle pan is enabled
-   */
-  static void OnHandleScrolling(Controller::Impl& impl, const Event& event, const bool isSmoothHandlePanEnabled);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_EVENT_HANDLER_H
diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp b/dali-toolkit/internal/text/text-controller-impl-model-updater.cpp
deleted file mode 100644 (file)
index de18e85..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/bidirectional-support.h>
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/color-segmentation.h>
-#include <dali-toolkit/internal/text/hyphenator.h>
-#include <dali-toolkit/internal/text/multi-language-support.h>
-#include <dali-toolkit/internal/text/segmentation.h>
-#include <dali-toolkit/internal/text/shaper.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-
-namespace Dali::Toolkit::Text
-{
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B)
-// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
-constexpr float         BRIGHTNESS_THRESHOLD = 0.179f;
-constexpr float         CONSTANT_R           = 0.2126f;
-constexpr float         CONSTANT_G           = 0.7152f;
-constexpr float         CONSTANT_B           = 0.0722f;
-constexpr Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f);
-constexpr Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f);
-constexpr Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f);
-constexpr Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f);
-constexpr Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f);
-constexpr Dali::Vector4 BACKGROUND_SUB6(1.f, 0.5f, 0.5f, 1.f);
-constexpr Dali::Vector4 BACKGROUND_SUB7(1.f, 0.8f, 0.8f, 1.f);
-} // namespace
-
-bool ControllerImplModelUpdater::Update(Controller::Impl& impl, OperationsMask operationsRequired)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel\n");
-
-  // Calculate the operations to be done.
-  const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
-
-  if(Controller::NO_OPERATION == operations)
-  {
-    // Nothing to do if no operations are pending and required.
-    return false;
-  }
-
-  Vector<Character>& srcCharacters = impl.mModel->mLogicalModel->mText;
-  Vector<Character>  displayCharacters;
-  bool               useHiddenText = false;
-  if(impl.mHiddenInput && impl.mEventData != nullptr && !impl.mEventData->mIsShowingPlaceholderText)
-  {
-    impl.mHiddenInput->Substitute(srcCharacters, displayCharacters);
-    useHiddenText = true;
-  }
-
-  Vector<Character>& utf32Characters    = useHiddenText ? displayCharacters : srcCharacters;
-  const Length       numberOfCharacters = utf32Characters.Count();
-
-  // Index to the first character of the first paragraph to be updated.
-  CharacterIndex startIndex = 0u;
-  // Number of characters of the paragraphs to be removed.
-  Length paragraphCharacters = 0u;
-
-  impl.CalculateTextUpdateIndices(paragraphCharacters);
-
-  // Check whether the indices for updating the text is valid
-  if(numberOfCharacters > 0u &&
-     (impl.mTextUpdateInfo.mParagraphCharacterIndex > numberOfCharacters ||
-      impl.mTextUpdateInfo.mRequestedNumberOfCharacters > numberOfCharacters))
-  {
-    std::string currentText;
-    Utf32ToUtf8(impl.mModel->mLogicalModel->mText.Begin(), numberOfCharacters, currentText);
-
-    DALI_LOG_ERROR("Controller::Impl::UpdateModel: mTextUpdateInfo has invalid indices\n");
-    DALI_LOG_ERROR("Number of characters: %d, current text is: %s\n", numberOfCharacters, currentText.c_str());
-
-    // Dump mTextUpdateInfo
-    DALI_LOG_ERROR("Dump mTextUpdateInfo:\n");
-    DALI_LOG_ERROR("     mTextUpdateInfo.mCharacterIndex = %u\n", impl.mTextUpdateInfo.mCharacterIndex);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToRemove = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToRemove);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mNumberOfCharactersToAdd = %u\n", impl.mTextUpdateInfo.mNumberOfCharactersToAdd);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mPreviousNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mPreviousNumberOfCharacters);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mParagraphCharacterIndex = %u\n", impl.mTextUpdateInfo.mParagraphCharacterIndex);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mRequestedNumberOfCharacters = %u\n", impl.mTextUpdateInfo.mRequestedNumberOfCharacters);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mStartGlyphIndex = %u\n", impl.mTextUpdateInfo.mStartGlyphIndex);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mStartLineIndex = %u\n", impl.mTextUpdateInfo.mStartLineIndex);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mEstimatedNumberOfLines = %u\n", impl.mTextUpdateInfo.mEstimatedNumberOfLines);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mClearAll = %d\n", impl.mTextUpdateInfo.mClearAll);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mFullRelayoutNeeded = %d\n", impl.mTextUpdateInfo.mFullRelayoutNeeded);
-    DALI_LOG_ERROR("     mTextUpdateInfo.mIsLastCharacterNewParagraph = %d\n", impl.mTextUpdateInfo.mIsLastCharacterNewParagraph);
-
-    return false;
-  }
-
-  startIndex = impl.mTextUpdateInfo.mParagraphCharacterIndex;
-
-  if(impl.mTextUpdateInfo.mClearAll ||
-     (0u != paragraphCharacters))
-  {
-    impl.ClearModelData(startIndex, startIndex + ((paragraphCharacters > 0u) ? paragraphCharacters - 1u : 0u), operations);
-  }
-
-  impl.mTextUpdateInfo.mClearAll = false;
-
-  // Whether the model is updated.
-  bool updated = false;
-
-  Vector<LineBreakInfo>& lineBreakInfo               = impl.mModel->mLogicalModel->mLineBreakInfo;
-  const Length           requestedNumberOfCharacters = impl.mTextUpdateInfo.mRequestedNumberOfCharacters;
-
-  if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
-  {
-    // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
-    // calculate the bidirectional info for each 'paragraph'.
-    // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines
-    // is not shaped together).
-    lineBreakInfo.Resize(numberOfCharacters, TextAbstraction::LINE_NO_BREAK);
-
-    SetLineBreakInfo(utf32Characters,
-                     startIndex,
-                     requestedNumberOfCharacters,
-                     lineBreakInfo);
-
-    if(impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
-       impl.mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED))
-    {
-      CharacterIndex end                 = startIndex + requestedNumberOfCharacters;
-      LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
-
-      for(CharacterIndex index = startIndex; index < end; index++)
-      {
-        CharacterIndex wordEnd = index;
-        while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK))
-        {
-          wordEnd++;
-        }
-
-        if((wordEnd + 1) == end) // add last char
-        {
-          wordEnd++;
-        }
-
-        Vector<bool> hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr);
-
-        for(CharacterIndex i = 0; i < (wordEnd - index); i++)
-        {
-          if(hyphens[i])
-          {
-            *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK;
-          }
-        }
-
-        index = wordEnd;
-      }
-    }
-
-    // Create the paragraph info.
-    impl.mModel->mLogicalModel->CreateParagraphInfo(startIndex,
-                                                    requestedNumberOfCharacters);
-    updated = true;
-  }
-
-  const bool getScripts    = Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations);
-  const bool validateFonts = Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations);
-
-  Vector<ScriptRun>& scripts    = impl.mModel->mLogicalModel->mScriptRuns;
-  Vector<FontRun>&   validFonts = impl.mModel->mLogicalModel->mFontRuns;
-
-  if(getScripts || validateFonts)
-  {
-    // Validates the fonts assigned by the application or assigns default ones.
-    // It makes sure all the characters are going to be rendered by the correct font.
-    MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
-
-    if(getScripts)
-    {
-      // Retrieves the scripts used in the text.
-      multilanguageSupport.SetScripts(utf32Characters,
-                                      startIndex,
-                                      requestedNumberOfCharacters,
-                                      scripts);
-    }
-
-    if(validateFonts)
-    {
-      // Validate the fonts set through the mark-up string.
-      Vector<FontDescriptionRun>& fontDescriptionRuns = impl.mModel->mLogicalModel->mFontDescriptionRuns;
-
-      // Get the default font's description.
-      TextAbstraction::FontDescription defaultFontDescription;
-      TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * impl.GetFontSizeScale();
-
-      //Get the number of points per one unit of point-size
-      uint32_t numberOfPointsPerOneUnitOfPointSize = impl.mFontClient.GetNumberOfPointsPerOneUnitOfPointSize();
-
-      if(impl.IsShowingPlaceholderText() && impl.mEventData && (nullptr != impl.mEventData->mPlaceholderFont))
-      {
-        // If the placeholder font is set specifically, only placeholder font is changed.
-        defaultFontDescription = impl.mEventData->mPlaceholderFont->mFontDescription;
-        if(impl.mEventData->mPlaceholderFont->sizeDefined)
-        {
-          defaultPointSize = impl.mEventData->mPlaceholderFont->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
-        }
-      }
-      else if(nullptr != impl.mFontDefaults)
-      {
-        // Set the normal font and the placeholder font.
-        defaultFontDescription = impl.mFontDefaults->mFontDescription;
-
-        if(impl.mTextFitEnabled)
-        {
-          defaultPointSize = impl.mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize;
-        }
-        else
-        {
-          defaultPointSize = impl.mFontDefaults->mDefaultPointSize * impl.GetFontSizeScale() * numberOfPointsPerOneUnitOfPointSize;
-        }
-      }
-
-      // Validates the fonts. If there is a character with no assigned font it sets a default one.
-      // After this call, fonts are validated.
-      multilanguageSupport.ValidateFonts(utf32Characters,
-                                         scripts,
-                                         fontDescriptionRuns,
-                                         defaultFontDescription,
-                                         defaultPointSize,
-                                         startIndex,
-                                         requestedNumberOfCharacters,
-                                         validFonts);
-    }
-    updated = true;
-  }
-
-  Vector<Character> mirroredUtf32Characters;
-  bool              textMirrored       = false;
-  const Length      numberOfParagraphs = impl.mModel->mLogicalModel->mParagraphInfo.Count();
-  if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
-  {
-    Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = impl.mModel->mLogicalModel->mBidirectionalParagraphInfo;
-    bidirectionalInfo.Reserve(numberOfParagraphs);
-
-    // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts.
-    SetBidirectionalInfo(utf32Characters,
-                         scripts,
-                         lineBreakInfo,
-                         startIndex,
-                         requestedNumberOfCharacters,
-                         bidirectionalInfo,
-                         (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS),
-                         impl.mLayoutDirection);
-
-    if(0u != bidirectionalInfo.Count())
-    {
-      // Only set the character directions if there is right to left characters.
-      Vector<CharacterDirection>& directions = impl.mModel->mLogicalModel->mCharacterDirections;
-      GetCharactersDirection(bidirectionalInfo,
-                             numberOfCharacters,
-                             startIndex,
-                             requestedNumberOfCharacters,
-                             directions);
-
-      // This paragraph has right to left text. Some characters may need to be mirrored.
-      // TODO: consider if the mirrored string can be stored as well.
-
-      textMirrored = GetMirroredText(utf32Characters,
-                                     directions,
-                                     bidirectionalInfo,
-                                     startIndex,
-                                     requestedNumberOfCharacters,
-                                     mirroredUtf32Characters);
-    }
-    else
-    {
-      // There is no right to left characters. Clear the directions vector.
-      impl.mModel->mLogicalModel->mCharacterDirections.Clear();
-    }
-    updated = true;
-  }
-
-  Vector<GlyphInfo>&      glyphs                = impl.mModel->mVisualModel->mGlyphs;
-  Vector<CharacterIndex>& glyphsToCharactersMap = impl.mModel->mVisualModel->mGlyphsToCharacters;
-  Vector<Length>&         charactersPerGlyph    = impl.mModel->mVisualModel->mCharactersPerGlyph;
-  Vector<GlyphIndex>      newParagraphGlyphs;
-  newParagraphGlyphs.Reserve(numberOfParagraphs);
-
-  const Length currentNumberOfGlyphs = glyphs.Count();
-  if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
-  {
-    const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
-    // Shapes the text.
-    ShapeText(textToShape,
-              lineBreakInfo,
-              scripts,
-              validFonts,
-              startIndex,
-              impl.mTextUpdateInfo.mStartGlyphIndex,
-              requestedNumberOfCharacters,
-              glyphs,
-              glyphsToCharactersMap,
-              charactersPerGlyph,
-              newParagraphGlyphs);
-
-    // Create the 'number of glyphs' per character and the glyph to character conversion tables.
-    impl.mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
-    impl.mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, impl.mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters);
-
-    updated = true;
-  }
-
-  const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
-
-  if(Controller::NO_OPERATION != (Controller::GET_GLYPH_METRICS & operations))
-  {
-    GlyphInfo* glyphsBuffer = glyphs.Begin();
-    impl.mMetrics->GetGlyphMetrics(glyphsBuffer + impl.mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs);
-
-    // Update the width and advance of all new paragraph characters.
-    for(Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it)
-    {
-      const GlyphIndex index = *it;
-      GlyphInfo&       glyph = *(glyphsBuffer + index);
-
-      glyph.xBearing = 0.f;
-      glyph.width    = 0.f;
-      glyph.advance  = 0.f;
-    }
-    updated = true;
-  }
-
-  if((nullptr != impl.mEventData) &&
-     impl.mEventData->mPreEditFlag &&
-     (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count()))
-  {
-    Dali::InputMethodContext::PreEditAttributeDataContainer attrs;
-    impl.mEventData->mInputMethodContext.GetPreeditStyle(attrs);
-    Dali::InputMethodContext::PreeditStyle type = Dali::InputMethodContext::PreeditStyle::NONE;
-
-    // Check the type of preedit and run it.
-    for(Dali::InputMethodContext::PreEditAttributeDataContainer::Iterator it = attrs.Begin(), endIt = attrs.End(); it != endIt; it++)
-    {
-      Dali::InputMethodContext::PreeditAttributeData attrData = *it;
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::UpdateModel PreeditStyle type : %d  start %d end %d \n", attrData.preeditType, attrData.startIndex, attrData.endIndex);
-      type = attrData.preeditType;
-
-      // Check the number of commit characters for the start position.
-      unsigned int numberOfCommit  = impl.mEventData->mPrimaryCursorPosition - impl.mEventData->mPreEditLength;
-      Length       numberOfIndices = attrData.endIndex - attrData.startIndex;
-
-      switch(type)
-      {
-        case Dali::InputMethodContext::PreeditStyle::UNDERLINE:
-        {
-          // Add the underline for the pre-edit text.
-          UnderlinedGlyphRun underlineRun;
-          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
-          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
-          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::REVERSE:
-        {
-          Vector4  textColor = impl.mModel->mVisualModel->GetTextColor();
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = textColor;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          Vector4 backgroundColor = impl.mModel->mVisualModel->GetBackgroundColor();
-          if(backgroundColor.a == 0) // There is no text background color.
-          {
-            // Try use the control's background color.
-            if(nullptr != impl.mEditableControlInterface)
-            {
-              impl.mEditableControlInterface->GetControlBackgroundColor(backgroundColor);
-              if(backgroundColor.a == 0) // There is no control background color.
-              {
-                // Determines black or white color according to text color.
-                // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/)
-                float L         = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b;
-                backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE;
-              }
-            }
-          }
-
-          Vector<ColorRun> colorRuns;
-          colorRuns.Resize(1u);
-          ColorRun& colorRun                       = *(colorRuns.Begin());
-          colorRun.color                           = backgroundColor;
-          colorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          colorRun.characterRun.numberOfCharacters = numberOfIndices;
-          impl.mModel->mLogicalModel->mColorRuns.PushBack(colorRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT:
-        {
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = LIGHT_BLUE;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1:
-        {
-          // CUSTOM_PLATFORM_STYLE_1 should be drawn with background and underline together.
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = BACKGROUND_SUB4;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          UnderlinedGlyphRun underlineRun;
-          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
-          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
-          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2:
-        {
-          // CUSTOM_PLATFORM_STYLE_2 should be drawn with background and underline together.
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = BACKGROUND_SUB5;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          UnderlinedGlyphRun underlineRun;
-          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
-          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
-          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3:
-        {
-          // CUSTOM_PLATFORM_STYLE_3 should be drawn with background and underline together.
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = BACKGROUND_SUB6;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          UnderlinedGlyphRun underlineRun;
-          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
-          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
-          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4:
-        {
-          // CUSTOM_PLATFORM_STYLE_4 should be drawn with background and underline together.
-          ColorRun backgroundColorRun;
-          backgroundColorRun.characterRun.characterIndex     = attrData.startIndex + numberOfCommit;
-          backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices;
-          backgroundColorRun.color                           = BACKGROUND_SUB7;
-          impl.mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun);
-
-          UnderlinedGlyphRun underlineRun;
-          underlineRun.glyphRun.glyphIndex     = attrData.startIndex + numberOfCommit;
-          underlineRun.glyphRun.numberOfGlyphs = numberOfIndices;
-          impl.mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun);
-
-          //Mark-up processor case
-          if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-          {
-            impl.CopyUnderlinedFromLogicalToVisualModels(false);
-          }
-          break;
-        }
-        case Dali::InputMethodContext::PreeditStyle::NONE:
-        default:
-        {
-          break;
-        }
-      }
-    }
-    attrs.Clear();
-    updated = true;
-  }
-
-  if(Controller::NO_OPERATION != (Controller::COLOR & operations))
-  {
-    // Set the color runs in glyphs.
-    SetColorSegmentationInfo(impl.mModel->mLogicalModel->mColorRuns,
-                             impl.mModel->mVisualModel->mCharactersToGlyph,
-                             impl.mModel->mVisualModel->mGlyphsPerCharacter,
-                             startIndex,
-                             impl.mTextUpdateInfo.mStartGlyphIndex,
-                             requestedNumberOfCharacters,
-                             impl.mModel->mVisualModel->mColors,
-                             impl.mModel->mVisualModel->mColorIndices);
-
-    // Set the background color runs in glyphs.
-    SetColorSegmentationInfo(impl.mModel->mLogicalModel->mBackgroundColorRuns,
-                             impl.mModel->mVisualModel->mCharactersToGlyph,
-                             impl.mModel->mVisualModel->mGlyphsPerCharacter,
-                             startIndex,
-                             impl.mTextUpdateInfo.mStartGlyphIndex,
-                             requestedNumberOfCharacters,
-                             impl.mModel->mVisualModel->mBackgroundColors,
-                             impl.mModel->mVisualModel->mBackgroundColorIndices);
-
-    updated = true;
-  }
-
-  if((Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations)) &&
-     !((nullptr != impl.mEventData) &&
-       impl.mEventData->mPreEditFlag &&
-       (0u != impl.mModel->mVisualModel->mCharactersToGlyph.Count())))
-  {
-    //Mark-up processor case
-    if(impl.mModel->mVisualModel->IsMarkupProcessorEnabled())
-    {
-      impl.CopyUnderlinedFromLogicalToVisualModels(true);
-      impl.CopyStrikethroughFromLogicalToVisualModels();
-      impl.CopyCharacterSpacingFromLogicalToVisualModels();
-    }
-
-    updated = true;
-  }
-
-  // The estimated number of lines. Used to avoid reallocations when layouting.
-  impl.mTextUpdateInfo.mEstimatedNumberOfLines = std::max(impl.mModel->mVisualModel->mLines.Count(), impl.mModel->mLogicalModel->mParagraphInfo.Count());
-
-  // Set the previous number of characters for the next time the text is updated.
-  impl.mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
-
-  return updated;
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller-impl-model-updater.h b/dali-toolkit/internal/text/text-controller-impl-model-updater.h
deleted file mode 100644 (file)
index 2c5dd8c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-namespace Dali::Toolkit::Text
-{
-
-/**
- * Contains methods for updating the models in the TextController
- */
-struct ControllerImplModelUpdater
-{
-  using OperationsMask = Controller::OperationsMask;
-
-  /**
-   * @brief Updates the logical and visual models. Updates the style runs in the visual model when the text's styles changes.
-   *
-   * @param[in] impl A reference to the Controller::Impl class
-   * @param[in] operationsRequired The operations required
-   * @return true if mode has been modified.
-   */
-  static bool Update(Controller::Impl& impl, OperationsMask operationsRequired);
-};
-
-} // namespace Dali::Toolkit::Text
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_MODEL_UPDATER_H
diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp
deleted file mode 100644 (file)
index 7fac661..0000000
+++ /dev/null
@@ -1,1981 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/window-devel.h>
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/actors/layer.h>
-#include <dali/public-api/rendering/renderer.h>
-#include <cmath>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/cursor-helper-functions.h>
-#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
-#include <dali-toolkit/internal/text/text-control-interface.h>
-#include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
-#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
-#include <dali-toolkit/internal/text/text-controller-impl-model-updater.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-controller-relayouter.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-#include <dali-toolkit/internal/text/text-enumerations-impl.h>
-#include <dali-toolkit/internal/text/text-run-container.h>
-#include <dali-toolkit/internal/text/text-selection-handle-controller.h>
-#include <dali-toolkit/internal/text/underlined-glyph-run.h>
-
-using namespace Dali;
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-
-const std::string EMPTY_STRING("");
-
-} // namespace
-
-namespace Dali::Toolkit::Text
-{
-namespace
-{
-void SetDefaultInputStyle(InputStyle& inputStyle, const FontDefaults* const fontDefaults, const Vector4& textColor)
-{
-  // Sets the default text's color.
-  inputStyle.textColor      = textColor;
-  inputStyle.isDefaultColor = true;
-
-  inputStyle.familyName.clear();
-  inputStyle.weight = TextAbstraction::FontWeight::NORMAL;
-  inputStyle.width  = TextAbstraction::FontWidth::NORMAL;
-  inputStyle.slant  = TextAbstraction::FontSlant::NORMAL;
-  inputStyle.size   = 0.f;
-
-  inputStyle.lineSpacing = 0.f;
-
-  inputStyle.underlineProperties.clear();
-  inputStyle.shadowProperties.clear();
-  inputStyle.embossProperties.clear();
-  inputStyle.outlineProperties.clear();
-
-  inputStyle.isFamilyDefined = false;
-  inputStyle.isWeightDefined = false;
-  inputStyle.isWidthDefined  = false;
-  inputStyle.isSlantDefined  = false;
-  inputStyle.isSizeDefined   = false;
-
-  inputStyle.isLineSpacingDefined = false;
-
-  inputStyle.isUnderlineDefined = false;
-  inputStyle.isShadowDefined    = false;
-  inputStyle.isEmbossDefined    = false;
-  inputStyle.isOutlineDefined   = false;
-
-  // Sets the default font's family name, weight, width, slant and size.
-  if(fontDefaults)
-  {
-    if(fontDefaults->familyDefined)
-    {
-      inputStyle.familyName      = fontDefaults->mFontDescription.family;
-      inputStyle.isFamilyDefined = true;
-    }
-
-    if(fontDefaults->weightDefined)
-    {
-      inputStyle.weight          = fontDefaults->mFontDescription.weight;
-      inputStyle.isWeightDefined = true;
-    }
-
-    if(fontDefaults->widthDefined)
-    {
-      inputStyle.width          = fontDefaults->mFontDescription.width;
-      inputStyle.isWidthDefined = true;
-    }
-
-    if(fontDefaults->slantDefined)
-    {
-      inputStyle.slant          = fontDefaults->mFontDescription.slant;
-      inputStyle.isSlantDefined = true;
-    }
-
-    if(fontDefaults->sizeDefined)
-    {
-      inputStyle.size          = fontDefaults->mDefaultPointSize;
-      inputStyle.isSizeDefined = true;
-    }
-  }
-}
-
-void ChangeTextControllerState(Controller::Impl& impl, EventData::State newState)
-{
-  EventData* eventData = impl.mEventData;
-
-  if(nullptr == eventData)
-  {
-    // Nothing to do if there is no text input.
-    return;
-  }
-
-  DecoratorPtr& decorator = eventData->mDecorator;
-  if(!decorator)
-  {
-    // Nothing to do if there is no decorator.
-    return;
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "ChangeState state:%d  newstate:%d\n", eventData->mState, newState);
-
-  if(eventData->mState != newState)
-  {
-    eventData->mPreviousState = eventData->mState;
-    eventData->mState         = newState;
-
-    switch(eventData->mState)
-    {
-      case EventData::INACTIVE:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        decorator->SetPopupActive(false);
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::INTERRUPTED:
-      {
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        decorator->SetPopupActive(false);
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::SELECTING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
-        }
-        decorator->SetHighlightActive(true);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::EDITING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        // Grab handle is not shown until a tap is received whilst EDITING
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-      case EventData::EDITING_WITH_POPUP:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_POPUP \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        if(eventData->mSelectionEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-          decorator->SetHighlightActive(false);
-        }
-        else if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-      case EventData::EDITING_WITH_GRAB_HANDLE:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_GRAB_HANDLE \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        // Grab handle is not shown until a tap is received whilst EDITING
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::SELECTION_HANDLE_PANNING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, true);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, true);
-        }
-        decorator->SetHighlightActive(true);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::GRAB_HANDLE_PANNING:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "GRAB_HANDLE_PANNING \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::EDITING_WITH_PASTE_POPUP:
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "EDITING_WITH_PASTE_POPUP \n", newState);
-
-        decorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-        if(eventData->mCursorBlinkEnabled)
-        {
-          decorator->StartCursorBlink();
-        }
-
-        if(eventData->mGrabHandleEnabled)
-        {
-          decorator->SetHandleActive(GRAB_HANDLE, true);
-        }
-        decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-        decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-        decorator->SetHighlightActive(false);
-
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          impl.SetPopupButtons();
-          decorator->SetPopupActive(true);
-        }
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-
-      case EventData::TEXT_PANNING:
-      {
-        decorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-        decorator->StopCursorBlink();
-        decorator->SetHandleActive(GRAB_HANDLE, false);
-        if(eventData->mDecorator->IsHandleActive(LEFT_SELECTION_HANDLE) ||
-           decorator->IsHandleActive(RIGHT_SELECTION_HANDLE))
-        {
-          decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-          decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-          decorator->SetHighlightActive(true);
-        }
-
-        if(eventData->mGrabHandlePopupEnabled)
-        {
-          decorator->SetPopupActive(false);
-        }
-
-        eventData->mDecoratorUpdated = true;
-        break;
-      }
-    }
-  }
-}
-
-void UpdateCursorPositionForAlignment(Controller::Impl& impl, bool needFullAlignment)
-{
-  EventData* eventData = impl.mEventData;
-
-  // Set the flag to redo the alignment operation
-  impl.mOperationsPending = static_cast<Controller::OperationsMask>(impl.mOperationsPending | Controller::OperationsMask::ALIGN);
-
-  if(eventData)
-  {
-    // Note: mUpdateAlignment is currently only needed for horizontal alignment
-    eventData->mUpdateAlignment = needFullAlignment;
-
-    // Update the cursor if it's in editing mode
-    if(EventData::IsEditingState(eventData->mState))
-    {
-      impl.ChangeState(EventData::EDITING);
-      eventData->mUpdateCursorPosition = true;
-    }
-  }
-}
-
-} // unnamed Namespace
-
-EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
-: mDecorator(decorator),
-  mInputMethodContext(inputMethodContext),
-  mPlaceholderFont(nullptr),
-  mPlaceholderTextActive(),
-  mPlaceholderTextInactive(),
-  mPlaceholderTextColor(0.8f, 0.8f, 0.8f, 0.8f), // This color has been published in the Public API (placeholder-properties.h).
-  mEventQueue(),
-  mInputStyleChangedQueue(),
-  mPreviousState(INACTIVE),
-  mState(INACTIVE),
-  mPrimaryCursorPosition(0u),
-  mLeftSelectionPosition(0u),
-  mRightSelectionPosition(0u),
-  mPreEditStartPosition(0u),
-  mPreEditLength(0u),
-  mCursorHookPositionX(0.f),
-  mDoubleTapAction(Controller::NoTextTap::NO_ACTION),
-  mLongPressAction(Controller::NoTextTap::SHOW_SELECTION_POPUP),
-  mIsShowingPlaceholderText(false),
-  mPreEditFlag(false),
-  mDecoratorUpdated(false),
-  mCursorBlinkEnabled(true),
-  mGrabHandleEnabled(true),
-  mGrabHandlePopupEnabled(true),
-  mSelectionEnabled(true),
-  mUpdateCursorHookPosition(false),
-  mUpdateCursorPosition(false),
-  mUpdateGrabHandlePosition(false),
-  mUpdateLeftSelectionPosition(false),
-  mUpdateRightSelectionPosition(false),
-  mIsLeftHandleSelected(false),
-  mIsRightHandleSelected(false),
-  mUpdateHighlightBox(false),
-  mScrollAfterUpdatePosition(false),
-  mScrollAfterDelete(false),
-  mAllTextSelected(false),
-  mUpdateInputStyle(false),
-  mPasswordInput(false),
-  mCheckScrollAmount(false),
-  mIsPlaceholderPixelSize(false),
-  mIsPlaceholderElideEnabled(false),
-  mPlaceholderEllipsisFlag(false),
-  mShiftSelectionFlag(true),
-  mUpdateAlignment(false),
-  mEditingEnabled(true)
-{
-}
-
-bool Controller::Impl::ProcessInputEvents()
-{
-  return ControllerImplEventHandler::ProcessInputEvents(*this);
-}
-
-void Controller::Impl::NotifyInputMethodContext()
-{
-  if(mEventData && mEventData->mInputMethodContext)
-  {
-    CharacterIndex cursorPosition = GetLogicalCursorPosition();
-
-    const Length numberOfWhiteSpaces = GetNumberOfWhiteSpaces(0u);
-
-    // Update the cursor position by removing the initial white spaces.
-    if(cursorPosition < numberOfWhiteSpaces)
-    {
-      cursorPosition = 0u;
-    }
-    else
-    {
-      cursorPosition -= numberOfWhiteSpaces;
-    }
-
-    mEventData->mInputMethodContext.SetCursorPosition(cursorPosition);
-    mEventData->mInputMethodContext.NotifyCursorPosition();
-  }
-}
-
-void Controller::Impl::NotifyInputMethodContextMultiLineStatus()
-{
-  if(mEventData && mEventData->mInputMethodContext)
-  {
-    Text::Layout::Engine::Type layout = mLayoutEngine.GetLayout();
-    mEventData->mInputMethodContext.NotifyTextInputMultiLine(layout == Text::Layout::Engine::MULTI_LINE_BOX);
-  }
-}
-
-CharacterIndex Controller::Impl::GetLogicalCursorPosition() const
-{
-  CharacterIndex cursorPosition = 0u;
-
-  if(mEventData)
-  {
-    if((EventData::SELECTING == mEventData->mState) ||
-       (EventData::SELECTION_HANDLE_PANNING == mEventData->mState))
-    {
-      cursorPosition = std::min(mEventData->mRightSelectionPosition, mEventData->mLeftSelectionPosition);
-    }
-    else
-    {
-      cursorPosition = mEventData->mPrimaryCursorPosition;
-    }
-  }
-
-  return cursorPosition;
-}
-
-Length Controller::Impl::GetNumberOfWhiteSpaces(CharacterIndex index) const
-{
-  Length numberOfWhiteSpaces = 0u;
-
-  // Get the buffer to the text.
-  Character* utf32CharacterBuffer = mModel->mLogicalModel->mText.Begin();
-
-  const Length totalNumberOfCharacters = mModel->mLogicalModel->mText.Count();
-  for(; index < totalNumberOfCharacters; ++index, ++numberOfWhiteSpaces)
-  {
-    if(!TextAbstraction::IsWhiteSpace(*(utf32CharacterBuffer + index)))
-    {
-      break;
-    }
-  }
-
-  return numberOfWhiteSpaces;
-}
-
-void Controller::Impl::GetText(std::string& text) const
-{
-  if(!IsShowingPlaceholderText())
-  {
-    // Retrieves the text string.
-    GetText(0u, text);
-  }
-  else
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::GetText %p empty (but showing placeholder)\n", this);
-  }
-}
-
-void Controller::Impl::GetText(CharacterIndex index, std::string& text) const
-{
-  // Get the total number of characters.
-  Length numberOfCharacters = mModel->mLogicalModel->mText.Count();
-
-  // Retrieve the text.
-  if(0u != numberOfCharacters)
-  {
-    Utf32ToUtf8(mModel->mLogicalModel->mText.Begin() + index, numberOfCharacters - index, text);
-  }
-}
-
-Dali::LayoutDirection::Type Controller::Impl::GetLayoutDirection(Dali::Actor& actor) const
-{
-  if(mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::LOCALE ||
-     (mModel->mMatchLayoutDirection == DevelText::MatchLayoutDirection::INHERIT && !mIsLayoutDirectionChanged))
-  {
-    Window window = DevelWindow::Get(actor);
-    return static_cast<Dali::LayoutDirection::Type>(window ? window.GetRootLayer().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>() : LayoutDirection::LEFT_TO_RIGHT);
-  }
-  else
-  {
-    return static_cast<Dali::LayoutDirection::Type>(actor.GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
-  }
-}
-
-Toolkit::DevelText::TextDirection::Type Controller::Impl::GetTextDirection()
-{
-  if(mUpdateTextDirection)
-  {
-    // Operations that can be done only once until the text changes.
-    const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
-                                                                          GET_SCRIPTS |
-                                                                          VALIDATE_FONTS |
-                                                                          GET_LINE_BREAKS |
-                                                                          BIDI_INFO |
-                                                                          SHAPE_TEXT |
-                                                                          GET_GLYPH_METRICS);
-
-    // Set the update info to relayout the whole text.
-    mTextUpdateInfo.mParagraphCharacterIndex     = 0u;
-    mTextUpdateInfo.mRequestedNumberOfCharacters = mModel->mLogicalModel->mText.Count();
-
-    // Make sure the model is up-to-date before layouting
-    UpdateModel(onlyOnceOperations);
-
-    Vector3 naturalSize;
-    Relayouter::DoRelayout(*this,
-                           Size(MAX_FLOAT, MAX_FLOAT),
-                           static_cast<OperationsMask>(onlyOnceOperations |
-                                                       LAYOUT | REORDER | UPDATE_DIRECTION),
-                           naturalSize.GetVectorXY());
-
-    // Do not do again the only once operations.
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending & ~onlyOnceOperations);
-
-    // Clear the update info. This info will be set the next time the text is updated.
-    mTextUpdateInfo.Clear();
-
-    // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
-    mTextUpdateInfo.mFullRelayoutNeeded = true;
-
-    mUpdateTextDirection = false;
-  }
-
-  return mIsTextDirectionRTL ? Toolkit::DevelText::TextDirection::RIGHT_TO_LEFT : Toolkit::DevelText::TextDirection::LEFT_TO_RIGHT;
-}
-
-void Controller::Impl::CalculateTextUpdateIndices(Length& numberOfCharacters)
-{
-  mTextUpdateInfo.mParagraphCharacterIndex = 0u;
-  mTextUpdateInfo.mStartGlyphIndex         = 0u;
-  mTextUpdateInfo.mStartLineIndex          = 0u;
-  numberOfCharacters                       = 0u;
-
-  const Length numberOfParagraphs = mModel->mLogicalModel->mParagraphInfo.Count();
-  if(0u == numberOfParagraphs)
-  {
-    mTextUpdateInfo.mParagraphCharacterIndex = 0u;
-    numberOfCharacters                       = 0u;
-
-    mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-
-    // Nothing else to do if there are no paragraphs.
-    return;
-  }
-
-  // Find the paragraphs to be updated.
-  Vector<ParagraphRunIndex> paragraphsToBeUpdated;
-  if(mTextUpdateInfo.mCharacterIndex >= mTextUpdateInfo.mPreviousNumberOfCharacters)
-  {
-    // Text is being added at the end of the current text.
-    if(mTextUpdateInfo.mIsLastCharacterNewParagraph)
-    {
-      // Text is being added in a new paragraph after the last character of the text.
-      mTextUpdateInfo.mParagraphCharacterIndex     = mTextUpdateInfo.mPreviousNumberOfCharacters;
-      numberOfCharacters                           = 0u;
-      mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-
-      mTextUpdateInfo.mStartGlyphIndex = mModel->mVisualModel->mGlyphs.Count();
-      mTextUpdateInfo.mStartLineIndex  = mModel->mVisualModel->mLines.Count() - 1u;
-
-      // Nothing else to do;
-      return;
-    }
-
-    paragraphsToBeUpdated.PushBack(numberOfParagraphs - 1u);
-  }
-  else
-  {
-    Length numberOfCharactersToUpdate = 0u;
-    if(mTextUpdateInfo.mFullRelayoutNeeded)
-    {
-      numberOfCharactersToUpdate = mTextUpdateInfo.mPreviousNumberOfCharacters;
-    }
-    else
-    {
-      numberOfCharactersToUpdate = (mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) ? mTextUpdateInfo.mNumberOfCharactersToRemove : 1u;
-    }
-    mModel->mLogicalModel->FindParagraphs(mTextUpdateInfo.mCharacterIndex,
-                                          numberOfCharactersToUpdate,
-                                          paragraphsToBeUpdated);
-  }
-
-  if(0u != paragraphsToBeUpdated.Count())
-  {
-    const ParagraphRunIndex firstParagraphIndex = *(paragraphsToBeUpdated.Begin());
-    const ParagraphRun&     firstParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + firstParagraphIndex);
-    mTextUpdateInfo.mParagraphCharacterIndex    = firstParagraph.characterRun.characterIndex;
-
-    ParagraphRunIndex   lastParagraphIndex = *(paragraphsToBeUpdated.End() - 1u);
-    const ParagraphRun& lastParagraph      = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex);
-
-    if((mTextUpdateInfo.mNumberOfCharactersToRemove > 0u) &&                                           // Some character are removed.
-       (lastParagraphIndex < numberOfParagraphs - 1u) &&                                               // There is a next paragraph.
-       ((lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters) == // The last removed character is the new paragraph character.
-        (mTextUpdateInfo.mCharacterIndex + mTextUpdateInfo.mNumberOfCharactersToRemove)))
-    {
-      // The new paragraph character of the last updated paragraph has been removed so is going to be merged with the next one.
-      const ParagraphRun& lastParagraph = *(mModel->mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex + 1u);
-
-      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
-    }
-    else
-    {
-      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
-    }
-  }
-
-  mTextUpdateInfo.mRequestedNumberOfCharacters = numberOfCharacters + mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
-  mTextUpdateInfo.mStartGlyphIndex             = *(mModel->mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex);
-}
-
-void Controller::Impl::ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations)
-{
-  ControllerImplDataClearer::ClearModelData(*this, startIndex, endIndex, operations);
-}
-
-bool Controller::Impl::UpdateModel(OperationsMask operationsRequired)
-{
-  return ControllerImplModelUpdater::Update(*this, operationsRequired);
-}
-
-void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle)
-{
-  SetDefaultInputStyle(inputStyle, mFontDefaults, mTextColor);
-}
-
-float Controller::Impl::GetDefaultFontLineHeight()
-{
-  FontId defaultFontId = 0u;
-  if(nullptr == mFontDefaults)
-  {
-    TextAbstraction::FontDescription fontDescription;
-    defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * GetFontSizeScale());
-  }
-  else
-  {
-    defaultFontId = mFontDefaults->GetFontId(mFontClient, mFontDefaults->mDefaultPointSize * GetFontSizeScale());
-  }
-
-  Text::FontMetrics fontMetrics;
-  mMetrics->GetFontMetrics(defaultFontId, fontMetrics);
-
-  return (fontMetrics.ascender - fontMetrics.descender);
-}
-
-bool Controller::Impl::SetDefaultLineSpacing(float lineSpacing)
-{
-  if(std::fabs(lineSpacing - mLayoutEngine.GetDefaultLineSpacing()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetDefaultLineSpacing(lineSpacing);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-bool Controller::Impl::SetDefaultLineSize(float lineSize)
-{
-  if(std::fabs(lineSize - mLayoutEngine.GetDefaultLineSize()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetDefaultLineSize(lineSize);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-bool Controller::Impl::SetRelativeLineSize(float relativeLineSize)
-{
-  if(std::fabs(relativeLineSize - GetRelativeLineSize()) > Math::MACHINE_EPSILON_1000)
-  {
-    mLayoutEngine.SetRelativeLineSize(relativeLineSize);
-
-    RelayoutAllCharacters();
-    return true;
-  }
-  return false;
-}
-
-float Controller::Impl::GetRelativeLineSize()
-{
-  return mLayoutEngine.GetRelativeLineSize();
-}
-
-string Controller::Impl::GetSelectedText()
-{
-  string text;
-  if(EventData::SELECTING == mEventData->mState)
-  {
-    RetrieveSelection(text, false);
-  }
-  return text;
-}
-
-string Controller::Impl::CopyText()
-{
-  string text;
-  RetrieveSelection(text, false);
-  SendSelectionToClipboard(false); // Text not modified
-
-  mEventData->mUpdateCursorPosition = true;
-
-  RequestRelayout(); // Cursor, Handles, Selection Highlight, Popup
-
-  return text;
-}
-
-string Controller::Impl::CutText()
-{
-  string text;
-  RetrieveSelection(text, false);
-
-  if(!IsEditable())
-  {
-    return EMPTY_STRING;
-  }
-
-  SendSelectionToClipboard(true); // Synchronous call to modify text
-  mOperationsPending = ALL_OPERATIONS;
-
-  if((0u != mModel->mLogicalModel->mText.Count()) ||
-     !IsPlaceholderAvailable())
-  {
-    QueueModifyEvent(ModifyEvent::TEXT_DELETED);
-  }
-  else
-  {
-    PlaceholderHandler::ShowPlaceholderText(*this);
-  }
-
-  mEventData->mUpdateCursorPosition = true;
-  mEventData->mScrollAfterDelete    = true;
-
-  RequestRelayout();
-
-  if(nullptr != mEditableControlInterface)
-  {
-    mEditableControlInterface->TextChanged(true);
-  }
-  return text;
-}
-
-void Controller::Impl::SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEnd)
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text.
-    return;
-  }
-
-  if(mEventData->mSelectionEnabled && (pStart || pEnd))
-  {
-    uint32_t length   = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
-    uint32_t oldStart = mEventData->mLeftSelectionPosition;
-    uint32_t oldEnd   = mEventData->mRightSelectionPosition;
-
-    if(pStart)
-    {
-      mEventData->mLeftSelectionPosition = std::min(*pStart, length);
-    }
-    if(pEnd)
-    {
-      mEventData->mRightSelectionPosition = std::min(*pEnd, length);
-    }
-
-    if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
-    {
-      ChangeState(EventData::EDITING);
-      mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition;
-      mEventData->mUpdateCursorPosition                                       = true;
-    }
-    else
-    {
-      ChangeState(EventData::SELECTING);
-      mEventData->mUpdateHighlightBox           = true;
-      mEventData->mUpdateLeftSelectionPosition  = true;
-      mEventData->mUpdateRightSelectionPosition = true;
-    }
-
-    if(mSelectableControlInterface != nullptr)
-    {
-      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
-    }
-  }
-}
-
-CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const
-{
-  if(nullptr == mEventData)
-  {
-    return 0;
-  }
-  return mEventData->mPrimaryCursorPosition;
-}
-
-bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text.
-    return false;
-  }
-
-  if(mEventData->mPrimaryCursorPosition == index && mEventData->mState != EventData::SELECTING)
-  {
-    // Nothing for same cursor position.
-    return false;
-  }
-
-  uint32_t length                    = static_cast<uint32_t>(mModel->mLogicalModel->mText.Count());
-  uint32_t oldCursorPos              = mEventData->mPrimaryCursorPosition;
-  mEventData->mPrimaryCursorPosition = std::min(index, length);
-  // If there is no focus, only the value is updated.
-  if(focused)
-  {
-    bool     wasInSelectingState = mEventData->mState == EventData::SELECTING;
-    uint32_t oldStart            = mEventData->mLeftSelectionPosition;
-    uint32_t oldEnd              = mEventData->mRightSelectionPosition;
-    ChangeState(EventData::EDITING);
-    mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition;
-    mEventData->mUpdateCursorPosition                                        = true;
-
-    if(mSelectableControlInterface != nullptr && wasInSelectingState)
-    {
-      mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition);
-    }
-
-    ScrollTextToMatchCursor();
-  }
-
-  if(nullptr != mEditableControlInterface)
-  {
-    mEditableControlInterface->CursorPositionChanged(oldCursorPos, mEventData->mPrimaryCursorPosition);
-  }
-
-  return true;
-}
-
-Uint32Pair Controller::Impl::GetTextSelectionRange() const
-{
-  Uint32Pair range;
-
-  if(mEventData)
-  {
-    range.first  = mEventData->mLeftSelectionPosition;
-    range.second = mEventData->mRightSelectionPosition;
-  }
-
-  return range;
-}
-
-bool Controller::Impl::IsEditable() const
-{
-  return mEventData && mEventData->mEditingEnabled;
-}
-
-void Controller::Impl::SetEditable(bool editable)
-{
-  if(mEventData)
-  {
-    mEventData->mEditingEnabled = editable;
-
-    if(mEventData->mDecorator)
-    {
-      bool decoratorEditable = editable && mIsUserInteractionEnabled;
-      mEventData->mDecorator->SetEditable(decoratorEditable);
-    }
-  }
-}
-
-void Controller::Impl::UpdateAfterFontChange(const std::string& newDefaultFont)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::UpdateAfterFontChange\n");
-
-  if(!mFontDefaults->familyDefined) // If user defined font then should not update when system font changes
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str());
-    mFontDefaults->mFontDescription.family = newDefaultFont;
-
-    ClearFontData();
-
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval)
-{
-  if(mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition)
-  {
-    // Nothing to select if handles are in the same place.
-    selectedText.clear();
-    return;
-  }
-
-  const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
-
-  //Get start and end position of selection
-  const CharacterIndex startOfSelectedText  = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
-  const Length         lengthOfSelectedText = (handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition) - startOfSelectedText;
-
-  Vector<Character>& utf32Characters    = mModel->mLogicalModel->mText;
-  const Length       numberOfCharacters = utf32Characters.Count();
-
-  // Validate the start and end selection points
-  if((startOfSelectedText + lengthOfSelectedText) <= numberOfCharacters)
-  {
-    //Get text as a UTF8 string
-    Utf32ToUtf8(&utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText);
-
-    if(deleteAfterRetrieval) // Only delete text if copied successfully
-    {
-      // Keep a copy of the current input style.
-      InputStyle currentInputStyle;
-      currentInputStyle.Copy(mEventData->mInputStyle);
-
-      // Set as input style the style of the first deleted character.
-      mModel->mLogicalModel->RetrieveStyle(startOfSelectedText, mEventData->mInputStyle);
-
-      // Compare if the input style has changed.
-      const bool hasInputStyleChanged = !currentInputStyle.Equal(mEventData->mInputStyle);
-
-      if(hasInputStyleChanged)
-      {
-        const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(mEventData->mInputStyle);
-        // Queue the input style changed signal.
-        mEventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
-      }
-
-      mModel->mLogicalModel->UpdateTextStyleRuns(startOfSelectedText, -static_cast<int>(lengthOfSelectedText));
-
-      // Mark the paragraphs to be updated.
-      if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
-      {
-        mTextUpdateInfo.mCharacterIndex             = 0;
-        mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-        mTextUpdateInfo.mNumberOfCharactersToAdd    = mTextUpdateInfo.mPreviousNumberOfCharacters - lengthOfSelectedText;
-        mTextUpdateInfo.mClearAll                   = true;
-      }
-      else
-      {
-        mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-      }
-
-      // Delete text between handles
-      Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
-      Vector<Character>::Iterator last  = first + lengthOfSelectedText;
-      utf32Characters.Erase(first, last);
-
-      // Will show the cursor at the first character of the selection.
-      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
-    }
-    else
-    {
-      // Will show the cursor at the last character of the selection.
-      mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
-    }
-
-    mEventData->mDecoratorUpdated = true;
-  }
-}
-
-void Controller::Impl::SetSelection(int start, int end)
-{
-  uint32_t oldStart = mEventData->mLeftSelectionPosition;
-  uint32_t oldEnd   = mEventData->mRightSelectionPosition;
-
-  mEventData->mLeftSelectionPosition  = start;
-  mEventData->mRightSelectionPosition = end;
-  mEventData->mUpdateCursorPosition   = true;
-
-  if(mSelectableControlInterface != nullptr)
-  {
-    mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, start, end);
-  }
-}
-
-std::pair<int, int> Controller::Impl::GetSelectionIndexes() const
-{
-  return {mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition};
-}
-
-void Controller::Impl::ShowClipboard()
-{
-  if(mClipboard)
-  {
-    mClipboard.ShowClipboard();
-  }
-}
-
-void Controller::Impl::HideClipboard()
-{
-  if(mClipboard && mClipboardHideEnabled)
-  {
-    mClipboard.HideClipboard();
-  }
-}
-
-void Controller::Impl::SetClipboardHideEnable(bool enable)
-{
-  mClipboardHideEnabled = enable;
-}
-
-bool Controller::Impl::CopyStringToClipboard(const std::string& source)
-{
-  //Send string to clipboard
-  return (mClipboard && mClipboard.SetItem(source));
-}
-
-void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
-{
-  std::string selectedText;
-  RetrieveSelection(selectedText, deleteAfterSending);
-  CopyStringToClipboard(selectedText);
-  ChangeState(EventData::EDITING);
-}
-
-void Controller::Impl::RequestGetTextFromClipboard()
-{
-  if(mClipboard)
-  {
-    mClipboard.RequestItem();
-  }
-}
-
-void Controller::Impl::RepositionSelectionHandles()
-{
-  SelectionHandleController::Reposition(*this);
-}
-void Controller::Impl::RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action)
-{
-  SelectionHandleController::Reposition(*this, visualX, visualY, action);
-}
-
-void Controller::Impl::SetPopupButtons()
-{
-  /**
-   *  Sets the Popup buttons to be shown depending on State.
-   *
-   *  If SELECTING :  CUT & COPY + ( PASTE & CLIPBOARD if content available to paste )
-   *
-   *  If EDITING_WITH_POPUP : SELECT & SELECT_ALL
-   */
-
-  bool                        isEditable    = IsEditable();
-  TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::NONE;
-
-  if(EventData::SELECTING == mEventData->mState)
-  {
-    buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::COPY);
-    if(isEditable)
-    {
-      buttonsToShow = TextSelectionPopup::Buttons(buttonsToShow | TextSelectionPopup::CUT);
-    }
-
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-
-    if(!mEventData->mAllTextSelected)
-    {
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::SELECT_ALL));
-    }
-  }
-  else if(EventData::EDITING_WITH_POPUP == mEventData->mState)
-  {
-    if(mModel->mLogicalModel->mText.Count() && !IsShowingPlaceholderText())
-    {
-      buttonsToShow = TextSelectionPopup::Buttons(TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL);
-    }
-
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-  }
-  else if(EventData::EDITING_WITH_PASTE_POPUP == mEventData->mState)
-  {
-    if(!IsClipboardEmpty())
-    {
-      if(isEditable)
-      {
-        buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::PASTE));
-      }
-      buttonsToShow = TextSelectionPopup::Buttons((buttonsToShow | TextSelectionPopup::CLIPBOARD));
-    }
-  }
-
-  mEventData->mDecorator->SetEnabledPopupButtons(buttonsToShow);
-}
-
-void Controller::Impl::ChangeState(EventData::State newState)
-{
-  ChangeTextControllerState(*this, newState);
-}
-
-void Controller::Impl::GetCursorPosition(CharacterIndex logical,
-                                         CursorInfo&    cursorInfo)
-{
-  if(!IsShowingRealText())
-  {
-    // Do not want to use the place-holder text to set the cursor position.
-
-    // Use the line's height of the font's family set to set the cursor's size.
-    // If there is no font's family set, use the default font.
-    // Use the current alignment to place the cursor at the beginning, center or end of the box.
-
-    cursorInfo.lineOffset          = 0.f;
-    cursorInfo.lineHeight          = GetDefaultFontLineHeight();
-    cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
-
-    bool isRTL = false;
-    if(mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS)
-    {
-      isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT;
-    }
-
-    switch(mModel->mHorizontalAlignment)
-    {
-      case Text::HorizontalAlignment::BEGIN:
-      {
-        if(isRTL)
-        {
-          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
-        }
-        else
-        {
-          cursorInfo.primaryPosition.x = 0.f;
-        }
-        break;
-      }
-      case Text::HorizontalAlignment::CENTER:
-      {
-        cursorInfo.primaryPosition.x = floorf(0.5f * mModel->mVisualModel->mControlSize.width);
-        break;
-      }
-      case Text::HorizontalAlignment::END:
-      {
-        if(isRTL)
-        {
-          cursorInfo.primaryPosition.x = 0.f;
-        }
-        else
-        {
-          cursorInfo.primaryPosition.x = mModel->mVisualModel->mControlSize.width - mEventData->mDecorator->GetCursorWidth();
-        }
-        break;
-      }
-    }
-
-    // Nothing else to do.
-    return;
-  }
-
-  const bool                  isMultiLine = (Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout());
-  GetCursorPositionParameters parameters;
-  parameters.visualModel  = mModel->mVisualModel;
-  parameters.logicalModel = mModel->mLogicalModel;
-  parameters.metrics      = mMetrics;
-  parameters.logical      = logical;
-  parameters.isMultiline  = isMultiLine;
-
-  float defaultFontLineHeight = GetDefaultFontLineHeight();
-
-  Text::GetCursorPosition(parameters,
-                          defaultFontLineHeight,
-                          cursorInfo);
-
-  // Adds Outline offset.
-  const float outlineWidth = static_cast<float>(mModel->GetOutlineWidth());
-  cursorInfo.primaryPosition.x += outlineWidth;
-  cursorInfo.primaryPosition.y += outlineWidth;
-  cursorInfo.secondaryPosition.x += outlineWidth;
-  cursorInfo.secondaryPosition.y += outlineWidth;
-
-  if(isMultiLine)
-  {
-    // 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 = mModel->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
-{
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text input.
-    return 0u;
-  }
-
-  CharacterIndex cursorIndex = mEventData->mPrimaryCursorPosition;
-
-  const GlyphIndex* const charactersToGlyphBuffer  = mModel->mVisualModel->mCharactersToGlyph.Begin();
-  const Length* const     charactersPerGlyphBuffer = mModel->mVisualModel->mCharactersPerGlyph.Begin();
-
-  GlyphIndex glyphIndex         = *(charactersToGlyphBuffer + index);
-  Length     numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
-
-  if(numberOfCharacters > 1u)
-  {
-    const Script script = mModel->mLogicalModel->GetScript(index);
-    if(HasLigatureMustBreak(script))
-    {
-      // Prevents to jump the whole Latin ligatures like fi, ff, or Arabic ï»», ...
-      numberOfCharacters = 1u;
-    }
-  }
-  else
-  {
-    while(0u == numberOfCharacters)
-    {
-      ++glyphIndex;
-      numberOfCharacters = *(charactersPerGlyphBuffer + glyphIndex);
-    }
-  }
-
-  if(index < mEventData->mPrimaryCursorPosition)
-  {
-    cursorIndex -= numberOfCharacters;
-  }
-  else
-  {
-    cursorIndex += numberOfCharacters;
-  }
-
-  // Will update the cursor hook position.
-  mEventData->mUpdateCursorHookPosition = true;
-
-  return cursorIndex;
-}
-
-void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this);
-  if(nullptr == mEventData)
-  {
-    // Nothing to do if there is no text input.
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n");
-    return;
-  }
-
-  const Vector2 cursorPosition = cursorInfo.primaryPosition + mModel->mScrollPosition;
-
-  mEventData->mDecorator->SetGlyphOffset(PRIMARY_CURSOR, cursorInfo.glyphOffset);
-
-  // Sets the cursor position.
-  mEventData->mDecorator->SetPosition(PRIMARY_CURSOR,
-                                      cursorPosition.x,
-                                      cursorPosition.y,
-                                      cursorInfo.primaryCursorHeight,
-                                      cursorInfo.lineHeight);
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Primary cursor position: %f,%f\n", cursorPosition.x, cursorPosition.y);
-
-  if(mEventData->mUpdateGrabHandlePosition)
-  {
-    // Sets the grab handle position.
-    mEventData->mDecorator->SetPosition(GRAB_HANDLE,
-                                        cursorPosition.x,
-                                        cursorInfo.lineOffset + mModel->mScrollPosition.y,
-                                        cursorInfo.lineHeight);
-  }
-
-  if(cursorInfo.isSecondaryCursor)
-  {
-    mEventData->mDecorator->SetPosition(SECONDARY_CURSOR,
-                                        cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x,
-                                        cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y,
-                                        cursorInfo.secondaryCursorHeight,
-                                        cursorInfo.lineHeight);
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + mModel->mScrollPosition.x, cursorInfo.secondaryPosition.y + mModel->mScrollPosition.y);
-  }
-
-  // Set which cursors are active according the state.
-  if(EventData::IsEditingState(mEventData->mState) || (EventData::GRAB_HANDLE_PANNING == mEventData->mState))
-  {
-    if(cursorInfo.isSecondaryCursor)
-    {
-      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_BOTH);
-    }
-    else
-    {
-      mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_PRIMARY);
-    }
-  }
-  else
-  {
-    mEventData->mDecorator->SetActiveCursor(ACTIVE_CURSOR_NONE);
-  }
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition\n");
-}
-
-void Controller::Impl::UpdateSelectionHandle(HandleType        handleType,
-                                             const CursorInfo& cursorInfo)
-{
-  SelectionHandleController::Update(*this, handleType, cursorInfo);
-}
-
-void Controller::Impl::ClampHorizontalScroll(const Vector2& layoutSize)
-{
-  // Clamp between -space & -alignment offset.
-
-  if(layoutSize.width > mModel->mVisualModel->mControlSize.width)
-  {
-    const float space         = (layoutSize.width - mModel->mVisualModel->mControlSize.width) + mModel->mAlignmentOffset;
-    mModel->mScrollPosition.x = (mModel->mScrollPosition.x < -space) ? -space : mModel->mScrollPosition.x;
-    mModel->mScrollPosition.x = (mModel->mScrollPosition.x > -mModel->mAlignmentOffset) ? -mModel->mAlignmentOffset : mModel->mScrollPosition.x;
-
-    mEventData->mDecoratorUpdated = true;
-  }
-  else
-  {
-    mModel->mScrollPosition.x = 0.f;
-  }
-}
-
-void Controller::Impl::ClampVerticalScroll(const Vector2& layoutSize)
-{
-  if(Layout::Engine::SINGLE_LINE_BOX == mLayoutEngine.GetLayout())
-  {
-    // Nothing to do if the text is single line.
-    return;
-  }
-
-  // Clamp between -space & 0.
-  if(layoutSize.height > mModel->mVisualModel->mControlSize.height)
-  {
-    const float space         = (layoutSize.height - mModel->mVisualModel->mControlSize.height);
-    mModel->mScrollPosition.y = (mModel->mScrollPosition.y < -space) ? -space : mModel->mScrollPosition.y;
-    mModel->mScrollPosition.y = (mModel->mScrollPosition.y > 0.f) ? 0.f : mModel->mScrollPosition.y;
-
-    mEventData->mDecoratorUpdated = true;
-  }
-  else
-  {
-    mModel->mScrollPosition.y = 0.f;
-  }
-}
-
-void Controller::Impl::ScrollToMakePositionVisible(const Vector2& position, float lineHeight)
-{
-  const float cursorWidth = mEventData->mDecorator ? static_cast<float>(mEventData->mDecorator->GetCursorWidth()) : 0.f;
-
-  // position is in actor's coords.
-  const float positionEndX = position.x + cursorWidth;
-  const float positionEndY = position.y + lineHeight;
-
-  // Transform the position to decorator coords.
-  const float decoratorPositionBeginX = position.x + mModel->mScrollPosition.x;
-  const float decoratorPositionEndX   = positionEndX + mModel->mScrollPosition.x;
-
-  const float decoratorPositionBeginY = position.y + mModel->mScrollPosition.y;
-  const float decoratorPositionEndY   = positionEndY + mModel->mScrollPosition.y;
-
-  if(decoratorPositionBeginX < 0.f)
-  {
-    mModel->mScrollPosition.x = -position.x;
-  }
-  else if(decoratorPositionEndX > mModel->mVisualModel->mControlSize.width)
-  {
-    mModel->mScrollPosition.x = mModel->mVisualModel->mControlSize.width - positionEndX;
-  }
-
-  if(Layout::Engine::MULTI_LINE_BOX == mLayoutEngine.GetLayout())
-  {
-    if(decoratorPositionBeginY < 0.f)
-    {
-      mModel->mScrollPosition.y = -position.y;
-    }
-    else if(decoratorPositionEndY > mModel->mVisualModel->mControlSize.height)
-    {
-      mModel->mScrollPosition.y = mModel->mVisualModel->mControlSize.height - positionEndY;
-    }
-    else if(mModel->mLogicalModel->mText.Count() == 0u)
-    {
-      Relayouter::CalculateVerticalOffset(*this, mModel->mVisualModel->mControlSize);
-    }
-  }
-}
-
-void Controller::Impl::ScrollTextToMatchCursor(const CursorInfo& cursorInfo)
-{
-  // Get the current cursor position in decorator coords.
-  const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition(PRIMARY_CURSOR);
-
-  const LineIndex lineIndex = mModel->mVisualModel->GetLineOfCharacter(mEventData->mPrimaryCursorPosition);
-
-  // Calculate the offset to match the cursor position before the character was deleted.
-  mModel->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x;
-
-  //If text control has more than two lines and current line index is not last, calculate scrollpositionY
-  if(mModel->mVisualModel->mLines.Count() > 1u && lineIndex != mModel->mVisualModel->mLines.Count() - 1u)
-  {
-    const float currentCursorGlyphOffset = mEventData->mDecorator->GetGlyphOffset(PRIMARY_CURSOR);
-    mModel->mScrollPosition.y            = currentCursorPosition.y - cursorInfo.lineOffset - currentCursorGlyphOffset;
-  }
-
-  ClampHorizontalScroll(mModel->mVisualModel->GetLayoutSize());
-  ClampVerticalScroll(mModel->mVisualModel->GetLayoutSize());
-
-  // Makes the new cursor position visible if needed.
-  ScrollToMakePositionVisible(cursorInfo.primaryPosition, cursorInfo.lineHeight);
-}
-
-void Controller::Impl::ScrollTextToMatchCursor()
-{
-  CursorInfo cursorInfo;
-  GetCursorPosition(mEventData->mPrimaryCursorPosition, cursorInfo);
-  ScrollTextToMatchCursor(cursorInfo);
-}
-
-void Controller::Impl::RequestRelayout()
-{
-  if(nullptr != mControlInterface)
-  {
-    mControlInterface->RequestTextRelayout();
-  }
-}
-
-void Controller::Impl::RelayoutAllCharacters()
-{
-  // relayout all characters
-  mTextUpdateInfo.mCharacterIndex             = 0;
-  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-  mOperationsPending                          = static_cast<OperationsMask>(mOperationsPending | LAYOUT);
-
-  mTextUpdateInfo.mFullRelayoutNeeded = true;
-
-  // Need to recalculate natural size
-  mRecalculateNaturalSize = true;
-
-  //remove selection
-  if((mEventData != nullptr) && (mEventData->mState == EventData::SELECTING))
-  {
-    ChangeState(EventData::EDITING);
-  }
-
-  RequestRelayout();
-}
-
-bool Controller::Impl::IsInputStyleChangedSignalsQueueEmpty()
-{
-  return (NULL == mEventData) || (0u == mEventData->mInputStyleChangedQueue.Count());
-}
-
-void Controller::Impl::ProcessInputStyleChangedSignals()
-{
-  if(mEventData)
-  {
-    if(mEditableControlInterface)
-    {
-      // Emit the input style changed signal for each mask
-      std::for_each(mEventData->mInputStyleChangedQueue.begin(),
-                    mEventData->mInputStyleChangedQueue.end(),
-                    [&](const auto mask) { mEditableControlInterface->InputStyleChanged(mask); });
-    }
-
-    mEventData->mInputStyleChangedQueue.Clear();
-  }
-}
-
-void Controller::Impl::ScrollBy(Vector2 scroll)
-{
-  if(mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0))
-  {
-    const Vector2& layoutSize    = mModel->mVisualModel->GetLayoutSize();
-    const Vector2  currentScroll = mModel->mScrollPosition;
-
-    scroll.x = -scroll.x;
-    scroll.y = -scroll.y;
-
-    if(fabs(scroll.x) > Math::MACHINE_EPSILON_0)
-    {
-      mModel->mScrollPosition.x += scroll.x;
-      ClampHorizontalScroll(layoutSize);
-    }
-
-    if(fabs(scroll.y) > Math::MACHINE_EPSILON_0)
-    {
-      mModel->mScrollPosition.y += scroll.y;
-      ClampVerticalScroll(layoutSize);
-    }
-
-    if(mModel->mScrollPosition != currentScroll)
-    {
-      mEventData->mDecorator->UpdatePositions(mModel->mScrollPosition - currentScroll);
-      RequestRelayout();
-    }
-  }
-}
-
-bool Controller::Impl::IsScrollable(const Vector2& displacement)
-{
-  bool isScrollable = false;
-  if(mEventData)
-  {
-    const bool isHorizontalScrollEnabled = mEventData->mDecorator->IsHorizontalScrollEnabled();
-    const bool isVerticalScrollEnabled   = mEventData->mDecorator->IsVerticalScrollEnabled();
-    if(isHorizontalScrollEnabled ||isVerticalScrollEnabled)
-    {
-      const Vector2& targetSize = mModel->mVisualModel->mControlSize;
-      const Vector2& layoutSize = mModel->mVisualModel->GetLayoutSize();
-      const Vector2& scrollPosition = mModel->mScrollPosition;
-
-      if(isHorizontalScrollEnabled)
-      {
-        const float displacementX = displacement.x;
-        const float positionX = scrollPosition.x + displacementX;
-        if(layoutSize.width > targetSize.width && -positionX > 0.f && -positionX < layoutSize.width - targetSize.width)
-        {
-          isScrollable = true;
-        }
-      }
-
-      if(isVerticalScrollEnabled)
-      {
-        const float displacementY = displacement.y;
-        const float positionY = scrollPosition.y + displacementY;
-        if(layoutSize.height > targetSize.height && -positionY > 0 && -positionY < layoutSize.height - targetSize.height)
-        {
-          isScrollable = true;
-        }
-      }
-    }
-  }
-  return isScrollable;
-}
-
-float Controller::Impl::GetHorizontalScrollPosition()
-{
-  // Scroll values are negative internally so we convert them to positive numbers
-  return mEventData ? -mModel->mScrollPosition.x : 0.0f;
-}
-
-float Controller::Impl::GetVerticalScrollPosition()
-{
-  // Scroll values are negative internally so we convert them to positive numbers
-  return mEventData ? -mModel->mScrollPosition.y : 0.0f;
-}
-
-Vector3 Controller::Impl::GetAnchorPosition(Anchor anchor) const
-{
-  //TODO
-  return Vector3(10.f, 10.f, 10.f);
-}
-
-Vector2 Controller::Impl::GetAnchorSize(Anchor anchor) const
-{
-  //TODO
-  return Vector2(10.f, 10.f);
-}
-
-Toolkit::TextAnchor Controller::Impl::CreateAnchorActor(Anchor anchor)
-{
-  auto actor = Toolkit::TextAnchor::New();
-  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
-  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
-  const Vector3 anchorPosition = GetAnchorPosition(anchor);
-  actor.SetProperty(Actor::Property::POSITION, anchorPosition);
-  const Vector2 anchorSize = GetAnchorSize(anchor);
-  actor.SetProperty(Actor::Property::SIZE, anchorSize);
-  std::string anchorText(mModel->mLogicalModel->mText.Begin() + anchor.startIndex, mModel->mLogicalModel->mText.Begin() + anchor.endIndex);
-  actor.SetProperty(Actor::Property::NAME, anchorText);
-  actor.SetProperty(Toolkit::TextAnchor::Property::URI, std::string(anchor.href));
-  actor.SetProperty(Toolkit::TextAnchor::Property::START_CHARACTER_INDEX, static_cast<int>(anchor.startIndex));
-  actor.SetProperty(Toolkit::TextAnchor::Property::END_CHARACTER_INDEX, static_cast<int>(anchor.endIndex));
-  return actor;
-}
-
-void Controller::Impl::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
-{
-  /* TODO: Now actors are created/destroyed in every "RenderText" function call. Even when we add just 1 character,
-           we need to create and destroy potentially many actors. Some optimization can be considered here.
-           Maybe a "dirty" flag in mLogicalModel? */
-  anchorActors.clear();
-  for(auto& anchor : mModel->mLogicalModel->mAnchors)
-  {
-    auto actor = CreateAnchorActor(anchor);
-    anchorActors.push_back(actor);
-  }
-}
-
-int32_t Controller::Impl::GetAnchorIndex(size_t characterOffset) const
-{
-  Vector<Anchor>::Iterator it = mModel->mLogicalModel->mAnchors.Begin();
-
-  while(it != mModel->mLogicalModel->mAnchors.End() && (it->startIndex > characterOffset || it->endIndex <= characterOffset))
-  {
-    it++;
-  }
-
-  return it == mModel->mLogicalModel->mAnchors.End() ? -1 : it - mModel->mLogicalModel->mAnchors.Begin();
-}
-
-void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns)
-{
-  //Underlined character runs for markup-processor
-  const Vector<UnderlinedCharacterRun>& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns;
-  const Vector<GlyphIndex>&             charactersToGlyph       = mModel->mVisualModel->mCharactersToGlyph;
-  const Vector<Length>&                 glyphsPerCharacter      = mModel->mVisualModel->mGlyphsPerCharacter;
-
-  if(shouldClearPreUnderlineRuns)
-  {
-    mModel->mVisualModel->mUnderlineRuns.Clear();
-  }
-
-  for(Vector<UnderlinedCharacterRun>::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it)
-  {
-    CharacterIndex characterIndex     = it->characterRun.characterIndex;
-    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
-
-    if(numberOfCharacters == 0)
-    {
-      continue;
-    }
-
-    // Create one run for all glyphs of all run's characters that has same properties
-    // This enhance performance and reduce the needed memory to store glyphs-runs
-    UnderlinedGlyphRun underlineGlyphRun;
-    underlineGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
-    underlineGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
-    //Copy properties (attributes)
-    underlineGlyphRun.properties = it->properties;
-
-    for(Length index = 1u; index < numberOfCharacters; index++)
-    {
-      underlineGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
-    }
-
-    mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun);
-  }
-}
-
-void Controller::Impl::CopyStrikethroughFromLogicalToVisualModels()
-{
-  //Strikethrough character runs from markup-processor
-  const Vector<StrikethroughCharacterRun>& strikethroughCharacterRuns = mModel->mLogicalModel->mStrikethroughCharacterRuns;
-  const Vector<GlyphIndex>&                charactersToGlyph          = mModel->mVisualModel->mCharactersToGlyph;
-  const Vector<Length>&                    glyphsPerCharacter         = mModel->mVisualModel->mGlyphsPerCharacter;
-
-  mModel->mVisualModel->mStrikethroughRuns.Clear();
-
-  for(Vector<StrikethroughCharacterRun>::ConstIterator it = strikethroughCharacterRuns.Begin(), endIt = strikethroughCharacterRuns.End(); it != endIt; ++it)
-  {
-    CharacterIndex characterIndex     = it->characterRun.characterIndex;
-    Length         numberOfCharacters = it->characterRun.numberOfCharacters;
-
-    if(numberOfCharacters == 0)
-    {
-      continue;
-    }
-
-    StrikethroughGlyphRun strikethroughGlyphRun;
-    strikethroughGlyphRun.properties              = it->properties;
-    strikethroughGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
-    strikethroughGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
-
-    for(Length index = 1u; index < numberOfCharacters; index++)
-    {
-      strikethroughGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
-    }
-
-    mModel->mVisualModel->mStrikethroughRuns.PushBack(strikethroughGlyphRun);
-  }
-}
-
-void Controller::Impl::CopyCharacterSpacingFromLogicalToVisualModels()
-{
-  //CharacterSpacing character runs from markup-processor
-  const Vector<CharacterSpacingCharacterRun>& characterSpacingCharacterRuns = mModel->mLogicalModel->mCharacterSpacingCharacterRuns;
-  const Vector<GlyphIndex>&                   charactersToGlyph             = mModel->mVisualModel->mCharactersToGlyph;
-  const Vector<Length>&                       glyphsPerCharacter            = mModel->mVisualModel->mGlyphsPerCharacter;
-
-  mModel->mVisualModel->mCharacterSpacingRuns.Clear();
-
-  for(Vector<CharacterSpacingCharacterRun>::ConstIterator it = characterSpacingCharacterRuns.Begin(), endIt = characterSpacingCharacterRuns.End(); it != endIt; ++it)
-  {
-    const CharacterIndex& characterIndex     = it->characterRun.characterIndex;
-    const Length&         numberOfCharacters = it->characterRun.numberOfCharacters;
-
-    if(numberOfCharacters == 0)
-    {
-      continue;
-    }
-
-    CharacterSpacingGlyphRun characterSpacingGlyphRun;
-    characterSpacingGlyphRun.value                   = it->value;
-    characterSpacingGlyphRun.glyphRun.glyphIndex     = charactersToGlyph[characterIndex];
-    characterSpacingGlyphRun.glyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex];
-
-    for(Length index = 1u; index < numberOfCharacters; index++)
-    {
-      characterSpacingGlyphRun.glyphRun.numberOfGlyphs += glyphsPerCharacter[characterIndex + index];
-    }
-
-    mModel->mVisualModel->mCharacterSpacingRuns.PushBack(characterSpacingGlyphRun);
-  }
-}
-
-void Controller::Impl::SetAutoScrollEnabled(bool enable)
-{
-  if(mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
-  {
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                     LAYOUT |
-                                                     ALIGN |
-                                                     UPDATE_LAYOUT_SIZE |
-                                                     REORDER);
-
-    if(enable)
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
-      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | UPDATE_DIRECTION);
-    }
-    else
-    {
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
-    }
-
-    mIsAutoScrollEnabled = enable;
-    RequestRelayout();
-  }
-  else
-  {
-    DALI_LOG_WARNING("Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n");
-    mIsAutoScrollEnabled = false;
-  }
-}
-
-void Controller::Impl::SetEnableCursorBlink(bool enable)
-{
-  DALI_ASSERT_DEBUG(NULL != mEventData && "TextInput disabled");
-
-  if(mEventData)
-  {
-    mEventData->mCursorBlinkEnabled = enable;
-
-    if(!enable && mEventData->mDecorator)
-    {
-      mEventData->mDecorator->StopCursorBlink();
-    }
-  }
-}
-
-void Controller::Impl::SetMultiLineEnabled(bool enable)
-{
-  const Layout::Engine::Type layout = enable ? Layout::Engine::MULTI_LINE_BOX : Layout::Engine::SINGLE_LINE_BOX;
-
-  if(layout != mLayoutEngine.GetLayout())
-  {
-    // Set the layout type.
-    mLayoutEngine.SetLayout(layout);
-
-    // Set the flags to redo the layout operations
-    const OperationsMask layoutOperations = static_cast<OperationsMask>(LAYOUT |
-                                                                        UPDATE_LAYOUT_SIZE |
-                                                                        ALIGN |
-                                                                        REORDER);
-
-    mTextUpdateInfo.mFullRelayoutNeeded = true;
-    mOperationsPending                  = static_cast<OperationsMask>(mOperationsPending | layoutOperations);
-
-    // Need to recalculate natural size
-    mRecalculateNaturalSize = true;
-
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
-{
-  if(alignment != mModel->mHorizontalAlignment)
-  {
-    // Set the alignment.
-    mModel->mHorizontalAlignment = alignment;
-    UpdateCursorPositionForAlignment(*this, true);
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetVerticalAlignment(VerticalAlignment::Type alignment)
-{
-  if(alignment != mModel->mVerticalAlignment)
-  {
-    // Set the alignment.
-    mModel->mVerticalAlignment = alignment;
-    UpdateCursorPositionForAlignment(*this, false);
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
-{
-  if(lineWrapMode != mModel->mLineWrapMode)
-  {
-    // Update Text layout for applying wrap mode
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                     ALIGN |
-                                                     LAYOUT |
-                                                     UPDATE_LAYOUT_SIZE |
-                                                     REORDER);
-
-    if((mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) ||
-       (mModel->mLineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED) || (lineWrapMode == (Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) // hyphen is treated as line break
-    {
-      mOperationsPending = static_cast<OperationsMask>(mOperationsPending | GET_LINE_BREAKS);
-    }
-
-    // Set the text wrap mode.
-    mModel->mLineWrapMode = lineWrapMode;
-
-    mTextUpdateInfo.mCharacterIndex             = 0u;
-    mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-    mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-
-    // Request relayout
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetDefaultColor(const Vector4& color)
-{
-  mTextColor = color;
-
-  if(!IsShowingPlaceholderText())
-  {
-    mModel->mVisualModel->SetTextColor(color);
-    mModel->mLogicalModel->mColorRuns.Clear();
-    mOperationsPending = static_cast<OperationsMask>(mOperationsPending | COLOR);
-    RequestRelayout();
-  }
-}
-
-void Controller::Impl::SetUserInteractionEnabled(bool enabled)
-{
-  mIsUserInteractionEnabled = enabled;
-
-  if(mEventData && mEventData->mDecorator)
-  {
-    bool editable = mEventData->mEditingEnabled && enabled;
-    mEventData->mDecorator->SetEditable(editable);
-  }
-}
-
-void Controller::Impl::ClearFontData()
-{
-  if(mFontDefaults)
-  {
-    mFontDefaults->mFontId = 0u; // Remove old font ID
-  }
-
-  // Set flags to update the model.
-  mTextUpdateInfo.mCharacterIndex             = 0u;
-  mTextUpdateInfo.mNumberOfCharactersToRemove = mTextUpdateInfo.mPreviousNumberOfCharacters;
-  mTextUpdateInfo.mNumberOfCharactersToAdd    = mModel->mLogicalModel->mText.Count();
-
-  mTextUpdateInfo.mClearAll           = true;
-  mTextUpdateInfo.mFullRelayoutNeeded = true;
-  mRecalculateNaturalSize             = true;
-
-  mOperationsPending = static_cast<OperationsMask>(mOperationsPending |
-                                                   VALIDATE_FONTS |
-                                                   SHAPE_TEXT |
-                                                   BIDI_INFO |
-                                                   GET_GLYPH_METRICS |
-                                                   LAYOUT |
-                                                   UPDATE_LAYOUT_SIZE |
-                                                   REORDER |
-                                                   ALIGN);
-}
-
-void Controller::Impl::ClearStyleData()
-{
-  mModel->mLogicalModel->mColorRuns.Clear();
-  mModel->mLogicalModel->ClearFontDescriptionRuns();
-  mModel->mLogicalModel->ClearStrikethroughRuns();
-}
-
-void Controller::Impl::ResetScrollPosition()
-{
-  if(mEventData)
-  {
-    // Reset the scroll position.
-    mModel->mScrollPosition                = Vector2::ZERO;
-    mEventData->mScrollAfterUpdatePosition = true;
-  }
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h
deleted file mode 100644 (file)
index 23b020c..0000000
+++ /dev/null
@@ -1,1050 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/clipboard.h>
-#include <dali/devel-api/text-abstraction/font-client.h>
-#include <dali/public-api/rendering/shader.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
-#include <dali-toolkit/internal/text/input-style.h>
-#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-model.h>
-#include <dali-toolkit/internal/text/text-view.h>
-#include <dali-toolkit/public-api/styling/style-manager.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-const float DEFAULT_TEXTFIT_MIN            = 10.f;
-const float DEFAULT_TEXTFIT_MAX            = 100.f;
-const float DEFAULT_TEXTFIT_STEP           = 1.f;
-const float DEFAULT_FONT_SIZE_SCALE        = 1.f;
-const float DEFAULT_DISABLED_COLOR_OPACITY = 0.3f;
-
-//Forward declarations
-struct CursorInfo;
-struct FontDefaults;
-struct ControllerImplEventHandler;
-struct ControllerImplModelUpdater;
-struct SelectionHandleController;
-
-class SelectableControlInterface;
-class AnchorControlInterface;
-
-struct Event
-{
-  // Used to queue input events until DoRelayout()
-  enum Type
-  {
-    CURSOR_KEY_EVENT,
-    TAP_EVENT,
-    PAN_EVENT,
-    LONG_PRESS_EVENT,
-    GRAB_HANDLE_EVENT,
-    LEFT_SELECTION_HANDLE_EVENT,
-    RIGHT_SELECTION_HANDLE_EVENT,
-    SELECT,
-    SELECT_ALL,
-    SELECT_NONE,
-    SELECT_RANGE,
-  };
-
-  union Param
-  {
-    int          mInt;
-    unsigned int mUint;
-    float        mFloat;
-    bool         mBool;
-  };
-
-  Event(Type eventType)
-  : type(eventType)
-  {
-    p1.mInt = 0;
-    p2.mInt = 0;
-    p3.mInt = 0;
-  }
-
-  Type  type;
-  Param p1;
-  Param p2;
-  Param p3;
-};
-
-struct EventData
-{
-  enum State
-  {
-    INACTIVE,
-    INTERRUPTED,
-    SELECTING,
-    EDITING,
-    EDITING_WITH_POPUP,
-    EDITING_WITH_GRAB_HANDLE,
-    EDITING_WITH_PASTE_POPUP,
-    GRAB_HANDLE_PANNING,
-    SELECTION_HANDLE_PANNING,
-    TEXT_PANNING
-  };
-
-  EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext);
-
-  ~EventData() = default;
-
-  static bool IsEditingState(State stateToCheck)
-  {
-    return (stateToCheck == EDITING || stateToCheck == EDITING_WITH_POPUP || stateToCheck == EDITING_WITH_GRAB_HANDLE || stateToCheck == EDITING_WITH_PASTE_POPUP);
-  }
-
-  DecoratorPtr                  mDecorator;               ///< Pointer to the decorator.
-  InputMethodContext            mInputMethodContext;      ///< The Input Method Framework Manager.
-  std::unique_ptr<FontDefaults> mPlaceholderFont;         ///< The placeholder default font.
-  std::string                   mPlaceholderTextActive;   ///< The text to display when the TextField is empty with key-input focus.
-  std::string                   mPlaceholderTextInactive; ///< The text to display when the TextField is empty and inactive.
-  Vector4                       mPlaceholderTextColor;    ///< The in/active placeholder text color.
-
-  /**
-   * This is used to delay handling events until after the model has been updated.
-   * The number of updates to the model is minimized to improve performance.
-   */
-  std::vector<Event> mEventQueue; ///< The queue of touch events etc.
-
-  Vector<InputStyle::Mask> mInputStyleChangedQueue; ///< Queue of changes in the input style. Used to emit the signal in the iddle callback.
-
-  InputStyle mInputStyle; ///< The style to be set to the new inputed text.
-
-  State mPreviousState; ///< Stores the current state before it's updated with the new one.
-  State mState;         ///< Selection mode, edit mode etc.
-
-  CharacterIndex mPrimaryCursorPosition;  ///< Index into logical model for primary cursor.
-  CharacterIndex mLeftSelectionPosition;  ///< Index into logical model for left selection handle.
-  CharacterIndex mRightSelectionPosition; ///< Index into logical model for right selection handle.
-
-  CharacterIndex mPreEditStartPosition; ///< Used to remove the pre-edit text if necessary.
-  Length         mPreEditLength;        ///< Used to remove the pre-edit text if necessary.
-
-  float mCursorHookPositionX; ///< Used to move the cursor with the keys or when scrolling the text vertically with the handles.
-
-  Controller::NoTextTap::Action mDoubleTapAction; ///< Action to be done when there is a double tap on top of 'no text'
-  Controller::NoTextTap::Action mLongPressAction; ///< Action to be done when there is a long press on top of 'no text'
-
-  bool mIsShowingPlaceholderText : 1;     ///< True if the place-holder text is being displayed.
-  bool mPreEditFlag : 1;                  ///< True if the model contains text in pre-edit state.
-  bool mDecoratorUpdated : 1;             ///< True if the decorator was updated during event processing.
-  bool mCursorBlinkEnabled : 1;           ///< True if cursor should blink when active.
-  bool mGrabHandleEnabled : 1;            ///< True if grab handle is enabled.
-  bool mGrabHandlePopupEnabled : 1;       ///< True if the grab handle popu-up should be shown.
-  bool mSelectionEnabled : 1;             ///< True if selection handles, highlight etc. are enabled.
-  bool mUpdateCursorHookPosition : 1;     ///< True if the cursor hook position must be updated. Used to move the cursor with the keys 'up' and 'down'.
-  bool mUpdateCursorPosition : 1;         ///< True if the visual position of the cursor must be recalculated.
-  bool mUpdateGrabHandlePosition : 1;     ///< True if the visual position of the grab handle must be recalculated.
-  bool mUpdateLeftSelectionPosition : 1;  ///< True if the visual position of the left selection handle must be recalculated.
-  bool mUpdateRightSelectionPosition : 1; ///< True if the visual position of the right selection handle must be recalculated.
-  bool mIsLeftHandleSelected : 1;         ///< Whether is the left handle the one which is selected.
-  bool mIsRightHandleSelected : 1;        ///< Whether is the right handle the one which is selected.
-  bool mUpdateHighlightBox : 1;           ///< True if the text selection high light box must be updated.
-  bool mScrollAfterUpdatePosition : 1;    ///< Whether to scroll after the cursor position is updated.
-  bool mScrollAfterDelete : 1;            ///< Whether to scroll after delete characters.
-  bool mAllTextSelected : 1;              ///< True if the selection handles are selecting all the text.
-  bool mUpdateInputStyle : 1;             ///< Whether to update the input style after moving the cursor.
-  bool mPasswordInput : 1;                ///< True if password input is enabled.
-  bool mCheckScrollAmount : 1;            ///< Whether to check scrolled amount after updating the position
-  bool mIsPlaceholderPixelSize : 1;       ///< True if the placeholder font size is set as pixel size.
-  bool mIsPlaceholderElideEnabled : 1;    ///< True if the placeholder text's elide is enabled.
-  bool mPlaceholderEllipsisFlag : 1;      ///< True if the text controller sets the placeholder ellipsis.
-  bool mShiftSelectionFlag : 1;           ///< True if the text selection using Shift key is enabled.
-  bool mUpdateAlignment : 1;              ///< True if the whole text needs to be full aligned..
-  bool mEditingEnabled : 1;               ///< True if the editing is enabled, false otherwise.
-};
-
-struct ModifyEvent
-{
-  enum Type
-  {
-    TEXT_REPLACED, ///< The entire text was replaced
-    TEXT_INSERTED, ///< Insert characters at the current cursor position
-    TEXT_DELETED   ///< Characters were deleted
-  };
-
-  Type type;
-};
-
-struct FontDefaults
-{
-  FontDefaults()
-  : mFontDescription(),
-    mDefaultPointSize(0.f),
-    mFitPointSize(0.f),
-    mFontId(0u),
-    familyDefined(false),
-    weightDefined(false),
-    widthDefined(false),
-    slantDefined(false),
-    sizeDefined(false)
-  {
-    // Initially use the default platform font
-    TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
-    fontClient.GetDefaultPlatformFontDescription(mFontDescription);
-  }
-
-  FontId GetFontId(TextAbstraction::FontClient& fontClient, float fontPointSize)
-  {
-    if(!mFontId)
-    {
-      const PointSize26Dot6 pointSize = static_cast<PointSize26Dot6>(fontPointSize * 64.f);
-      mFontId                         = fontClient.GetFontId(mFontDescription, pointSize);
-    }
-
-    return mFontId;
-  }
-
-  TextAbstraction::FontDescription mFontDescription;  ///< The default font's description.
-  float                            mDefaultPointSize; ///< The default font's point size.
-  float                            mFitPointSize;     ///< The fit font's point size.
-  FontId                           mFontId;           ///< The font's id of the default font.
-  bool                             familyDefined : 1; ///< Whether the default font's family name is defined.
-  bool                             weightDefined : 1; ///< Whether the default font's weight is defined.
-  bool                             widthDefined : 1;  ///< Whether the default font's width is defined.
-  bool                             slantDefined : 1;  ///< Whether the default font's slant is defined.
-  bool                             sizeDefined : 1;   ///< Whether the default font's point size is defined.
-};
-
-/**
- * @brief Stores indices used to update the text.
- * Stores the character index where the text is updated and the number of characters removed and added.
- * Stores as well indices to the first and the last paragraphs to be updated.
- */
-struct TextUpdateInfo
-{
-  TextUpdateInfo()
-  : mCharacterIndex(0u),
-    mNumberOfCharactersToRemove(0u),
-    mNumberOfCharactersToAdd(0u),
-    mPreviousNumberOfCharacters(0u),
-    mParagraphCharacterIndex(0u),
-    mRequestedNumberOfCharacters(0u),
-    mStartGlyphIndex(0u),
-    mStartLineIndex(0u),
-    mEstimatedNumberOfLines(0u),
-    mClearAll(true),
-    mFullRelayoutNeeded(true),
-    mIsLastCharacterNewParagraph(false)
-  {
-  }
-
-  ~TextUpdateInfo()
-  {
-  }
-
-  CharacterIndex mCharacterIndex;             ///< Index to the first character to be updated.
-  Length         mNumberOfCharactersToRemove; ///< The number of characters to be removed.
-  Length         mNumberOfCharactersToAdd;    ///< The number of characters to be added.
-  Length         mPreviousNumberOfCharacters; ///< The number of characters before the text update.
-
-  CharacterIndex mParagraphCharacterIndex;     ///< Index of the first character of the first paragraph to be updated.
-  Length         mRequestedNumberOfCharacters; ///< The requested number of characters.
-  GlyphIndex     mStartGlyphIndex;
-  LineIndex      mStartLineIndex;
-  Length         mEstimatedNumberOfLines; ///< The estimated number of lines. Used to avoid reallocations when layouting.
-
-  bool mClearAll : 1;                    ///< Whether the whole text is cleared. i.e. when the text is reset.
-  bool mFullRelayoutNeeded : 1;          ///< Whether a full re-layout is needed. i.e. when a new size is set to the text control.
-  bool mIsLastCharacterNewParagraph : 1; ///< Whether the last character is a new paragraph character.
-
-  void Clear()
-  {
-    // Clear all info except the mPreviousNumberOfCharacters member.
-    mCharacterIndex              = static_cast<CharacterIndex>(-1);
-    mNumberOfCharactersToRemove  = 0u;
-    mNumberOfCharactersToAdd     = 0u;
-    mParagraphCharacterIndex     = 0u;
-    mRequestedNumberOfCharacters = 0u;
-    mStartGlyphIndex             = 0u;
-    mStartLineIndex              = 0u;
-    mEstimatedNumberOfLines      = 0u;
-    mClearAll                    = false;
-    mFullRelayoutNeeded          = false;
-    mIsLastCharacterNewParagraph = false;
-  }
-};
-
-struct UnderlineDefaults
-{
-  std::string properties;
-  // TODO: complete with underline parameters.
-};
-
-struct ShadowDefaults
-{
-  std::string properties;
-  // TODO: complete with shadow parameters.
-};
-
-struct EmbossDefaults
-{
-  std::string properties;
-  // TODO: complete with emboss parameters.
-};
-
-struct OutlineDefaults
-{
-  std::string properties;
-  // TODO: complete with outline parameters.
-};
-
-struct Controller::Impl
-{
-  Impl(ControlInterface*           controlInterface,
-       EditableControlInterface*   editableControlInterface,
-       SelectableControlInterface* selectableControlInterface,
-       AnchorControlInterface*     anchorControlInterface)
-  : mControlInterface(controlInterface),
-    mEditableControlInterface(editableControlInterface),
-    mSelectableControlInterface(selectableControlInterface),
-    mAnchorControlInterface(anchorControlInterface),
-    mModel(),
-    mFontDefaults(NULL),
-    mUnderlineDefaults(NULL),
-    mShadowDefaults(NULL),
-    mEmbossDefaults(NULL),
-    mOutlineDefaults(NULL),
-    mEventData(NULL),
-    mFontClient(),
-    mClipboard(),
-    mView(),
-    mMetrics(),
-    mModifyEvents(),
-    mTextColor(Color::BLACK),
-    mTextUpdateInfo(),
-    mOperationsPending(NO_OPERATION),
-    mMaximumNumberOfCharacters(50u),
-    mHiddenInput(NULL),
-    mInputFilter(nullptr),
-    mRecalculateNaturalSize(true),
-    mMarkupProcessorEnabled(false),
-    mClipboardHideEnabled(true),
-    mIsAutoScrollEnabled(false),
-    mIsAutoScrollMaxTextureExceeded(false),
-    mUpdateTextDirection(true),
-    mIsTextDirectionRTL(false),
-    mUnderlineSetByString(false),
-    mShadowSetByString(false),
-    mOutlineSetByString(false),
-    mFontStyleSetByString(false),
-    mStrikethroughSetByString(false),
-    mShouldClearFocusOnEscape(true),
-    mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
-    mTextFitMinSize(DEFAULT_TEXTFIT_MIN),
-    mTextFitMaxSize(DEFAULT_TEXTFIT_MAX),
-    mTextFitStepSize(DEFAULT_TEXTFIT_STEP),
-    mFontSizeScale(DEFAULT_FONT_SIZE_SCALE),
-    mDisabledColorOpacity(DEFAULT_DISABLED_COLOR_OPACITY),
-    mFontSizeScaleEnabled(true),
-    mTextFitEnabled(false),
-    mTextFitChanged(false),
-    mIsLayoutDirectionChanged(false),
-    mIsUserInteractionEnabled(true)
-  {
-    mModel = Model::New();
-
-    mFontClient = TextAbstraction::FontClient::Get();
-    mClipboard  = Clipboard::Get();
-
-    mView.SetVisualModel(mModel->mVisualModel);
-    mView.SetLogicalModel(mModel->mLogicalModel);
-
-    // Use this to access FontClient i.e. to get down-scaled Emoji metrics.
-    mMetrics = Metrics::New(mFontClient);
-    mLayoutEngine.SetMetrics(mMetrics);
-
-    // Set the text properties to default
-    mModel->mVisualModel->SetUnderlineEnabled(false);
-    mModel->mVisualModel->SetUnderlineHeight(0.0f);
-
-    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
-    if(styleManager)
-    {
-      const Property::Map& config                  = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
-      const auto           clearFocusOnEscapeValue = config.Find("clearFocusOnEscape", Property::Type::BOOLEAN);
-
-      // Default is true. If config don't have "clearFocusOnEscape" property, make it true.
-      mShouldClearFocusOnEscape = (!clearFocusOnEscapeValue || clearFocusOnEscapeValue->Get<bool>());
-    }
-  }
-
-  ~Impl()
-  {
-    delete mHiddenInput;
-    delete mFontDefaults;
-    delete mUnderlineDefaults;
-    delete mShadowDefaults;
-    delete mEmbossDefaults;
-    delete mOutlineDefaults;
-    delete mEventData;
-  }
-
-  // Text Controller Implementation.
-
-  /**
-   * @copydoc Text::Controller::RequestRelayout()
-   */
-  void RequestRelayout();
-
-  /**
-   * @brief Request a relayout using the ControlInterface.
-   */
-  void QueueModifyEvent(ModifyEvent::Type type)
-  {
-    if(ModifyEvent::TEXT_REPLACED == type)
-    {
-      // Cancel previously queued inserts etc.
-      mModifyEvents.Clear();
-    }
-
-    ModifyEvent event;
-    event.type = type;
-    mModifyEvents.PushBack(event);
-
-    // The event will be processed during relayout
-    RequestRelayout();
-  }
-
-  /**
-   * @brief Helper to move the cursor, grab handle etc.
-   */
-  bool ProcessInputEvents();
-
-  /**
-   * @brief Helper to check whether any place-holder text is available.
-   */
-  bool IsPlaceholderAvailable() const
-  {
-    return (mEventData &&
-            (!mEventData->mPlaceholderTextInactive.empty() ||
-             !mEventData->mPlaceholderTextActive.empty()));
-  }
-
-  bool IsShowingPlaceholderText() const
-  {
-    return (mEventData && mEventData->mIsShowingPlaceholderText);
-  }
-
-  /**
-   * @brief Helper to check whether active place-holder text is available.
-   */
-  bool IsFocusedPlaceholderAvailable() const
-  {
-    return (mEventData && !mEventData->mPlaceholderTextActive.empty());
-  }
-
-  bool IsShowingRealText() const
-  {
-    return (!IsShowingPlaceholderText() &&
-            0u != mModel->mLogicalModel->mText.Count());
-  }
-
-  /**
-   * @brief Called when placeholder-text is hidden
-   */
-  void PlaceholderCleared()
-  {
-    if(mEventData)
-    {
-      mEventData->mIsShowingPlaceholderText = false;
-
-      // Remove mPlaceholderTextColor
-      mModel->mVisualModel->SetTextColor(mTextColor);
-    }
-  }
-
-  void ClearPreEditFlag()
-  {
-    if(mEventData)
-    {
-      mEventData->mPreEditFlag          = false;
-      mEventData->mPreEditStartPosition = 0;
-      mEventData->mPreEditLength        = 0;
-    }
-  }
-
-  void ResetInputMethodContext()
-  {
-    if(mEventData)
-    {
-      // Reset incase we are in a pre-edit state.
-      if(mEventData->mInputMethodContext)
-      {
-        mEventData->mInputMethodContext.Reset(); // Will trigger a message ( commit, get surrounding )
-      }
-
-      ClearPreEditFlag();
-    }
-  }
-
-  float GetFontSizeScale()
-  {
-    return mFontSizeScaleEnabled ? mFontSizeScale : 1.0f;
-  }
-
-  /**
-   * @brief Helper to notify InputMethodContext with surrounding text & cursor changes.
-   */
-  void NotifyInputMethodContext();
-
-  /**
-   * @brief Helper to notify InputMethodContext with multi line status.
-   */
-  void NotifyInputMethodContextMultiLineStatus();
-
-  /**
-   * @brief Retrieve the current cursor position.
-   *
-   * @return The cursor position.
-   */
-  CharacterIndex GetLogicalCursorPosition() const;
-
-  /**
-   * @brief Retrieves the number of consecutive white spaces starting from the given @p index.
-   *
-   * @param[in] index The character index from where to count the number of consecutive white spaces.
-   *
-   * @return The number of consecutive white spaces.
-   */
-  Length GetNumberOfWhiteSpaces(CharacterIndex index) const;
-
-  /**
-   * @brief Retrieve any text previously set.
-   *
-   * @param[out] text A string of UTF-8 characters.
-   */
-  void GetText(std::string& text) const;
-
-  /**
-   * @brief Retrieve any text previously set starting from the given @p index.
-   *
-   * @param[in] index The character index from where to retrieve the text.
-   * @param[out] text A string of UTF-8 characters.
-   *
-   * @see Dali::Toolkit::Text::Controller::GetText()
-   */
-  void GetText(CharacterIndex index, std::string& text) const;
-
-  bool IsClipboardEmpty()
-  {
-    bool result(mClipboard && mClipboard.NumberOfItems());
-    return !result; // If NumberOfItems greater than 0, return false
-  }
-
-  bool IsClipboardVisible()
-  {
-    bool result(mClipboard && mClipboard.IsVisible());
-    return result;
-  }
-
-  /**
-   * @copydoc Controller::GetLayoutDirection()
-   */
-  Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
-
-  /**
-   * @brief Checks text direction.
-   * @return The text direction.
-   */
-  Toolkit::DevelText::TextDirection::Type GetTextDirection();
-
-  /**
-   * @brief Calculates the start character index of the first paragraph to be updated and
-   * the end character index of the last paragraph to be updated.
-   *
-   * @param[out] numberOfCharacters The number of characters to be updated.
-   */
-  void CalculateTextUpdateIndices(Length& numberOfCharacters);
-
-  /**
-   * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
-   *
-   * @note It never clears the text stored in utf32.
-   *
-   * @param[in] startIndex Index to the first character to be cleared.
-   * @param[in] endIndex Index to the last character to be cleared.
-   * @param[in] operations The operations required.
-   */
-  void ClearModelData(CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations);
-
-  /**
-   * @brief Updates the logical and visual models. Updates the style runs in the visual model when the text's styles changes.
-   *
-   * When text or style changes the model is set with some operations pending.
-   * When i.e. the text's size or a relayout is required this method is called
-   * with a given @p operationsRequired parameter. The operations required are
-   * matched with the operations pending to perform the minimum number of operations.
-   *
-   * @param[in] operationsRequired The operations required.
-   *
-   * @return @e true if the model has been modified.
-   */
-  bool UpdateModel(OperationsMask operationsRequired);
-
-  /**
-   * @brief Retreieves the default style.
-   *
-   * @param[out] inputStyle The default style.
-   */
-  void RetrieveDefaultInputStyle(InputStyle& inputStyle);
-
-  /**
-   * @brief Retrieve the line height of the default font.
-   */
-  float GetDefaultFontLineHeight();
-
-  /**
-   * @copydoc Controller::SetDefaultLineSpacing
-   */
-  bool SetDefaultLineSpacing(float lineSpacing);
-
-  /**
-   * @copydoc Controller::SetDefaultLineSize
-   */
-  bool SetDefaultLineSize(float lineSize);
-
-  /**
-   * @copydoc Controller::SetRelativeLineSize
-   */
-  bool SetRelativeLineSize(float relativeLineSize);
-
-  /**
-   * @copydoc Controller::GetRelativeLineSize
-   */
-  float GetRelativeLineSize();
-
-  /**
-   * @copydoc Text::Controller::GetPrimaryCursorPosition()
-   */
-  CharacterIndex GetPrimaryCursorPosition() const;
-
-  /**
-   * @copydoc Text::Controller::SetPrimaryCursorPosition()
-   */
-  bool SetPrimaryCursorPosition(CharacterIndex index, bool focused);
-
-  /**
-   * @copydoc Text::SelectableControlInterface::GetSelectedText()
-   */
-  string GetSelectedText();
-
-  /**
-   * @copydoc Text::EditableControlInterface::CopyText()
-   */
-  string CopyText();
-
-  /**
-   * @copydoc Text::EditableControlInterface::CutText()
-   */
-  string CutText();
-
-  /**
-   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
-   */
-  void SetTextSelectionRange(const uint32_t* pStart, const uint32_t* pEndf);
-
-  /**
-   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
-   */
-  Uint32Pair GetTextSelectionRange() const;
-
-  /**
-   * @copydoc Text::EditableControlInterface::IsEditable()
-   */
-  bool IsEditable() const;
-
-  /**
-   * @copydoc Text::EditableControlInterface::SetEditable()
-   */
-  void SetEditable(bool editable);
-
-  /**
-   * @copydoc Controller::UpdateAfterFontChange
-   */
-  void UpdateAfterFontChange(const std::string& newDefaultFont);
-
-  /**
-   * @brief Retrieves the selected text. It removes the text if the @p deleteAfterRetrieval parameter is @e true.
-   *
-   * @param[out] selectedText The selected text encoded in utf8.
-   * @param[in] deleteAfterRetrieval Whether the text should be deleted after retrieval.
-   */
-  void RetrieveSelection(std::string& selectedText, bool deleteAfterRetrieval);
-
-  void SetSelection(int start, int end);
-
-  std::pair<int, int> GetSelectionIndexes() const;
-
-  void ShowClipboard();
-
-  void HideClipboard();
-
-  void SetClipboardHideEnable(bool enable);
-
-  bool CopyStringToClipboard(const std::string& source);
-
-  void SendSelectionToClipboard(bool deleteAfterSending);
-
-  void RequestGetTextFromClipboard();
-
-  void RepositionSelectionHandles();
-  void RepositionSelectionHandles(float visualX, float visualY, Controller::NoTextTap::Action action);
-
-  void SetPopupButtons();
-
-  void ChangeState(EventData::State newState);
-
-  /**
-   * @brief Calculates the cursor's position for a given character index in the logical order.
-   *
-   * It retrieves as well the line's height and the cursor's height and
-   * if there is a valid alternative cursor, its position and height.
-   *
-   * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character.
-   * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor.
-   */
-  void GetCursorPosition(CharacterIndex logical,
-                         CursorInfo&    cursorInfo);
-
-  /**
-   * @brief Calculates the new cursor index.
-   *
-   * It takes into account that in some scripts multiple characters can form a glyph and all of them
-   * need to be jumped with one key event.
-   *
-   * @param[in] index The initial new index.
-   *
-   * @return The new cursor index.
-   */
-  CharacterIndex CalculateNewCursorIndex(CharacterIndex index) const;
-
-  /**
-   * @brief Updates the cursor position.
-   *
-   * Sets the cursor's position into the decorator. It transforms the cursor's position into decorator's coords.
-   * It sets the position of the secondary cursor if it's a valid one.
-   * Sets which cursors are active.
-   *
-   * @param[in] cursorInfo Contains the selection handle position in Actor's coords.
-   *
-   */
-  void UpdateCursorPosition(const CursorInfo& cursorInfo);
-
-  /**
-   * @brief Updates the position of the given selection handle. It transforms the handle's position into decorator's coords.
-   *
-   * @param[in] handleType One of the selection handles.
-   * @param[in] cursorInfo Contains the selection handle position in Actor's coords.
-   */
-  void UpdateSelectionHandle(HandleType        handleType,
-                             const CursorInfo& cursorInfo);
-
-  /**
-   * @biref Clamps the horizontal scrolling to get the control always filled with text.
-   *
-   * @param[in] layoutSize The size of the laid out text.
-   */
-  void ClampHorizontalScroll(const Vector2& layoutSize);
-
-  /**
-   * @biref Clamps the vertical scrolling to get the control always filled with text.
-   *
-   * @param[in] layoutSize The size of the laid out text.
-   */
-  void ClampVerticalScroll(const Vector2& layoutSize);
-
-  /**
-   * @brief Scrolls the text to make a position visible.
-   *
-   * @pre mEventData must not be NULL. (there is a text-input or selection capabilities).
-   *
-   * @param[in] position A position in text coords.
-   * @param[in] lineHeight The line height for the given position.
-   *
-   * This method is called after inserting text, moving the cursor with the grab handle or the keypad,
-   * or moving the selection handles.
-   */
-  void ScrollToMakePositionVisible(const Vector2& position, float lineHeight);
-
-  /**
-   * @brief Scrolls the text to make the cursor visible.
-   *
-   * This method is called after deleting text.
-   */
-  void ScrollTextToMatchCursor(const CursorInfo& cursorInfo);
-
-  /**
-   * @brief Scrolls the text to make primary cursor visible.
-   */
-  void ScrollTextToMatchCursor();
-
-  /**
-   * @brief Create an actor that renders the text background color
-   *
-   * @return the created actor or an empty handle if no background color needs to be rendered.
-   */
-  Actor CreateBackgroundActor();
-
-  /**
-   * @brief fill needed relayout parameters whenever a property is changed and a re-layout is needed for the entire text.
-   */
-  void RelayoutAllCharacters();
-
-  /**
-   * @copydoc Controller::IsInputStyleChangedSignalsQueueEmpty
-   */
-  bool IsInputStyleChangedSignalsQueueEmpty();
-
-  /**
-   * @copydoc Controller::ProcessInputStyleChangedSignals
-   */
-  void ProcessInputStyleChangedSignals();
-
-  /**
-   * @copydoc Controller::ScrollBy()
-   */
-  void ScrollBy(Vector2 scroll);
-
-  /**
-   * @copydoc Controller::IsScrollable()
-   */
-  bool IsScrollable(const Vector2& displacement);
-
-  /**
-   * @copydoc Controller::GetHorizontalScrollPosition()
-   */
-  float GetHorizontalScrollPosition();
-
-  /**
-   * @copydoc Controller::GetVerticalScrollPosition()
-   */
-  float GetVerticalScrollPosition();
-
-  /**
-   * @copydoc Controller::SetAutoScrollEnabled()
-   */
-  void SetAutoScrollEnabled(bool enable);
-
-  /**
-   * @copydoc Controller::SetEnableCursorBlink()
-   */
-  void SetEnableCursorBlink(bool enable);
-
-  /**
-   * @copydoc Controller::SetMultiLineEnabled()
-   */
-  void SetMultiLineEnabled(bool enable);
-
-  /**
-   * @copydoc Controller::SetHorizontalAlignment()
-   */
-  void SetHorizontalAlignment(HorizontalAlignment::Type alignment);
-
-  /**
-   * @copydoc Controller::SetVerticalAlignment()
-   */
-  void SetVerticalAlignment(VerticalAlignment::Type alignment);
-
-  /**
-   * @copydoc Controller::SetLineWrapMode()
-   */
-  void SetLineWrapMode(Text::LineWrap::Mode textWarpMode);
-
-  /**
-   * @copydoc Controller::SetDefaultColor()
-   */
-  void SetDefaultColor(const Vector4& color);
-
-  /**
-   * @copydoc Controller::SetUserInteractionEnabled()
-   */
-  void SetUserInteractionEnabled(bool enabled);
-
-  /**
-   * @brief Helper to clear font-specific data (only).
-   */
-  void ClearFontData();
-
-  /**
-   * @brief Helper to clear text's style data.
-   */
-  void ClearStyleData();
-
-  /**
-   * @brief Used to reset the scroll position after setting a new text.
-   */
-  void ResetScrollPosition();
-
-  /**
-   * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
-   *
-   * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
-   */
-  void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
-
-  /**
-   * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
-   *
-   * @param[in] characterOffset A position in text coords.
-   *
-   * @return the 0-based index in anchor vector (-1 if an anchor not found)
-   */
-  int32_t GetAnchorIndex(size_t characterOffset) const;
-
-  /**
-   * @brief Return the geometrical position of an anchor relative to the parent origin point.
-   *
-   * @param[in] anchor An anchor.
-   *
-   * @return The x, y, z coordinates of an anchor.
-   */
-  Vector3 GetAnchorPosition(Anchor anchor) const;
-
-  /**
-   * @brief Return the size of an anchor expresed as a vector containing anchor's width and height.
-   *
-   * @param[in] anchor An anchor.
-   *
-   * @return The width and height of an anchor.
-   */
-  Vector2 GetAnchorSize(Anchor anchor) const;
-
-  /**
-   * @brief Return the actor representing an anchor.
-   *
-   * @param[in] anchor An anchor.
-   *
-   * @return The actor representing an anchor.
-   */
-  Toolkit::TextAnchor CreateAnchorActor(Anchor anchor);
-
-public:
-  /**
-   * @brief Gets implementation from the controller handle.
-   * @param controller The text controller
-   * @return The implementation of the Controller
-   */
-  static Impl& GetImplementation(Text::Controller& controller)
-  {
-    return *controller.mImpl;
-  }
-
-private:
-  // Declared private and left undefined to avoid copies.
-  Impl(const Impl&);
-  // Declared private and left undefined to avoid copies.
-  Impl& operator=(const Impl&);
-
-  /**
-   * @brief Copy Underlined-Character-Runs from Logical-Model to Underlined-Glyph-Runs in Visual-Model
-   *
-   * @param shouldClearPreUnderlineRuns Whether should clear the existing Underlined-Glyph-Runs in Visual-Model
-   */
-  void CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns);
-
-  /**
-   * @brief Copy strikethrough-Character-Runs from Logical-Model to strikethrough-Glyph-Runs in Visual-Model
-   *
-   */
-  void CopyStrikethroughFromLogicalToVisualModels();
-
-  /**
-   * @brief Copy CharacterSpacing-Character-Runs from Logical-Model to CharacterSpacing-Glyph-Runs in Visual-Model
-   *
-   */
-  void CopyCharacterSpacingFromLogicalToVisualModels();
-
-public:
-  ControlInterface*            mControlInterface;           ///< Reference to the text controller.
-  EditableControlInterface*    mEditableControlInterface;   ///< Reference to the editable text controller.
-  SelectableControlInterface*  mSelectableControlInterface; ///< Reference to the selectable text controller.
-  AnchorControlInterface*      mAnchorControlInterface;     ///< Reference to the anchor controller.
-  ModelPtr                     mModel;                      ///< Pointer to the text's model.
-  FontDefaults*                mFontDefaults;               ///< Avoid allocating this when the user does not specify a font.
-  UnderlineDefaults*           mUnderlineDefaults;          ///< Avoid allocating this when the user does not specify underline parameters.
-  ShadowDefaults*              mShadowDefaults;             ///< Avoid allocating this when the user does not specify shadow parameters.
-  EmbossDefaults*              mEmbossDefaults;             ///< Avoid allocating this when the user does not specify emboss parameters.
-  OutlineDefaults*             mOutlineDefaults;            ///< Avoid allocating this when the user does not specify outline parameters.
-  EventData*                   mEventData;                  ///< Avoid allocating everything for text input until EnableTextInput().
-  TextAbstraction::FontClient  mFontClient;                 ///< Handle to the font client.
-  Clipboard                    mClipboard;                  ///< Handle to the system clipboard
-  View                         mView;                       ///< The view interface to the rendering back-end.
-  MetricsPtr                   mMetrics;                    ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
-  Layout::Engine               mLayoutEngine;               ///< The layout engine.
-  Vector<ModifyEvent>          mModifyEvents;               ///< Temporary stores the text set until the next relayout.
-  Vector4                      mTextColor;                  ///< The regular text color
-  TextUpdateInfo               mTextUpdateInfo;             ///< Info of the characters updated.
-  OperationsMask               mOperationsPending;          ///< Operations pending to be done to layout the text.
-  Length                       mMaximumNumberOfCharacters;  ///< Maximum number of characters that can be inserted.
-  HiddenText*                  mHiddenInput;                ///< Avoid allocating this when the user does not specify hidden input mode.
-  std::unique_ptr<InputFilter> mInputFilter;                ///< Avoid allocating this when the user does not specify input filter mode.
-  Vector2                      mTextFitContentSize;         ///< Size of Text fit content
-
-  bool               mRecalculateNaturalSize : 1;         ///< Whether the natural size needs to be recalculated.
-  bool               mMarkupProcessorEnabled : 1;         ///< Whether the mark-up procesor is enabled.
-  bool               mClipboardHideEnabled : 1;           ///< Whether the ClipboardHide function work or not
-  bool               mIsAutoScrollEnabled : 1;            ///< Whether auto text scrolling is enabled.
-  bool               mIsAutoScrollMaxTextureExceeded : 1; ///< Whether auto text scrolling is exceed max texture size.
-  bool               mUpdateTextDirection : 1;            ///< Whether the text direction needs to be updated.
-  CharacterDirection mIsTextDirectionRTL : 1;             ///< Whether the text direction is right to left or not
-
-  bool                  mUnderlineSetByString : 1;     ///< Set when underline is set by string (legacy) instead of map
-  bool                  mShadowSetByString : 1;        ///< Set when shadow is set by string (legacy) instead of map
-  bool                  mOutlineSetByString : 1;       ///< Set when outline is set by string (legacy) instead of map
-  bool                  mFontStyleSetByString : 1;     ///< Set when font style is set by string (legacy) instead of map
-  bool                  mStrikethroughSetByString : 1; ///< Set when strikethrough is set by string (legacy) instead of map
-  bool                  mShouldClearFocusOnEscape : 1; ///< Whether text control should clear key input focus
-  LayoutDirection::Type mLayoutDirection;              ///< Current system language direction
-
-  Shader mShaderBackground; ///< The shader for text background.
-
-  float mTextFitMinSize;               ///< Minimum Font Size for text fit. Default 10
-  float mTextFitMaxSize;               ///< Maximum Font Size for text fit. Default 100
-  float mTextFitStepSize;              ///< Step Size for font intervalse. Default 1
-  float mFontSizeScale;                ///< Scale value for Font Size. Default 1.0
-  float mDisabledColorOpacity;         ///< Color opacity when disabled.
-  bool  mFontSizeScaleEnabled : 1;     ///< Whether the font size scale is enabled.
-  bool  mTextFitEnabled : 1;           ///< Whether the text's fit is enabled.
-  bool  mTextFitChanged : 1;           ///< Whether the text fit property has changed.
-  bool  mIsLayoutDirectionChanged : 1; ///< Whether the layout has changed.
-  bool  mIsUserInteractionEnabled : 1; ///< Whether the user interaction is enabled.
-
-private:
-  friend ControllerImplEventHandler;
-  friend ControllerImplModelUpdater;
-  friend SelectionHandleController;
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
diff --git a/dali-toolkit/internal/text/text-controller-input-font-handler.cpp b/dali-toolkit/internal/text/text-controller-input-font-handler.cpp
deleted file mode 100644 (file)
index 988ddd1..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
-
-// EXTERNAL INCLUDES
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-namespace
-{
-/**
- * @brief Adds a new font description run for the selected text.
- *
- * The new font parameters are added after the call to this method.
- *
- * @param[in] eventData The event data pointer.
- * @param[in] logicalModel The logical model where to add the new font description run.
- * @param[out] startOfSelectedText Index to the first selected character.
- * @param[out] lengthOfSelectedText Number of selected characters.
- */
-FontDescriptionRun& UpdateSelectionFontStyleRun(EventData*      eventData,
-                                                LogicalModelPtr logicalModel,
-                                                CharacterIndex& startOfSelectedText,
-                                                Length&         lengthOfSelectedText)
-{
-  const bool handlesCrossed = eventData->mLeftSelectionPosition > eventData->mRightSelectionPosition;
-
-  // Get start and end position of selection
-  startOfSelectedText  = handlesCrossed ? eventData->mRightSelectionPosition : eventData->mLeftSelectionPosition;
-  lengthOfSelectedText = (handlesCrossed ? eventData->mLeftSelectionPosition : eventData->mRightSelectionPosition) - startOfSelectedText;
-
-  // Add the font run.
-  const VectorBase::SizeType numberOfRuns = logicalModel->mFontDescriptionRuns.Count();
-  logicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
-
-  FontDescriptionRun& fontDescriptionRun = *(logicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
-
-  fontDescriptionRun.characterRun.characterIndex     = startOfSelectedText;
-  fontDescriptionRun.characterRun.numberOfCharacters = lengthOfSelectedText;
-
-  // Recalculate the selection highlight as the metrics may have changed.
-  eventData->mUpdateLeftSelectionPosition  = true;
-  eventData->mUpdateRightSelectionPosition = true;
-  eventData->mUpdateHighlightBox           = true;
-
-  return fontDescriptionRun;
-}
-
-} // unnamed namespace
-
-void Controller::InputFontHandler::SetInputFontFamily(Controller& controller, const std::string& fontFamily)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.familyName      = fontFamily;
-    controller.mImpl->mEventData->mInputStyle.isFamilyDefined = true;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      CharacterIndex startOfSelectedText  = 0u;
-      Length         lengthOfSelectedText = 0u;
-
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        // Update a font description run for the selecting state.
-        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
-                                                                             controller.mImpl->mModel->mLogicalModel,
-                                                                             startOfSelectedText,
-                                                                             lengthOfSelectedText);
-
-        fontDescriptionRun.familyLength = fontFamily.size();
-        fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
-        memcpy(fontDescriptionRun.familyName, fontFamily.c_str(), fontDescriptionRun.familyLength);
-        fontDescriptionRun.familyDefined = true;
-
-        // The memory allocated for the font family name is freed when the font description is removed from the logical model.
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
-                                                                         VALIDATE_FONTS |
-                                                                         SHAPE_TEXT |
-                                                                         GET_GLYPH_METRICS |
-                                                                         LAYOUT |
-                                                                         UPDATE_LAYOUT_SIZE |
-                                                                         REORDER |
-                                                                         ALIGN);
-      controller.mImpl->mRecalculateNaturalSize = true;
-      controller.mImpl->RequestRelayout();
-
-      // As the font changes, recalculate the handle positions is needed.
-      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
-      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
-      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
-    }
-  }
-}
-
-const std::string& Controller::InputFontHandler::GetInputFontFamily(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mInputStyle.familyName;
-  }
-
-  // Return the default font's family if there is no EventData.
-  return controller.GetDefaultFontFamily();
-}
-
-void Controller::InputFontHandler::SetInputFontWeight(const Controller& controller, FontWeight weight)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.weight          = weight;
-    controller.mImpl->mEventData->mInputStyle.isWeightDefined = true;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      CharacterIndex startOfSelectedText  = 0u;
-      Length         lengthOfSelectedText = 0u;
-
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        // Update a font description run for the selecting state.
-        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
-                                                                             controller.mImpl->mModel->mLogicalModel,
-                                                                             startOfSelectedText,
-                                                                             lengthOfSelectedText);
-
-        fontDescriptionRun.weight        = weight;
-        fontDescriptionRun.weightDefined = true;
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
-                                                                         VALIDATE_FONTS |
-                                                                         SHAPE_TEXT |
-                                                                         GET_GLYPH_METRICS |
-                                                                         LAYOUT |
-                                                                         UPDATE_LAYOUT_SIZE |
-                                                                         REORDER |
-                                                                         ALIGN);
-      controller.mImpl->mRecalculateNaturalSize = true;
-      controller.mImpl->RequestRelayout();
-
-      // As the font might change, recalculate the handle positions is needed.
-      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
-      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
-      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
-    }
-  }
-}
-
-bool Controller::InputFontHandler::IsInputFontWeightDefined(const Controller& controller)
-{
-  bool defined = false;
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    defined = controller.mImpl->mEventData->mInputStyle.isWeightDefined;
-  }
-
-  return defined;
-}
-
-FontWeight Controller::InputFontHandler::GetInputFontWeight(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mInputStyle.weight;
-  }
-
-  return controller.GetDefaultFontWeight();
-}
-
-void Controller::InputFontHandler::SetInputFontWidth(Controller& controller, FontWidth width)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.width          = width;
-    controller.mImpl->mEventData->mInputStyle.isWidthDefined = true;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      CharacterIndex startOfSelectedText  = 0u;
-      Length         lengthOfSelectedText = 0u;
-
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        // Update a font description run for the selecting state.
-        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
-                                                                             controller.mImpl->mModel->mLogicalModel,
-                                                                             startOfSelectedText,
-                                                                             lengthOfSelectedText);
-
-        fontDescriptionRun.width        = width;
-        fontDescriptionRun.widthDefined = true;
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
-                                                                         VALIDATE_FONTS |
-                                                                         SHAPE_TEXT |
-                                                                         GET_GLYPH_METRICS |
-                                                                         LAYOUT |
-                                                                         UPDATE_LAYOUT_SIZE |
-                                                                         REORDER |
-                                                                         ALIGN);
-      controller.mImpl->mRecalculateNaturalSize = true;
-      controller.mImpl->RequestRelayout();
-
-      // As the font might change, recalculate the handle positions is needed.
-      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
-      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
-      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
-    }
-  }
-}
-
-bool Controller::InputFontHandler::IsInputFontWidthDefined(const Controller& controller)
-{
-  bool defined = false;
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    defined = controller.mImpl->mEventData->mInputStyle.isWidthDefined;
-  }
-
-  return defined;
-}
-
-FontWidth Controller::InputFontHandler::GetInputFontWidth(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mInputStyle.width;
-  }
-
-  return controller.GetDefaultFontWidth();
-}
-
-void Controller::InputFontHandler::SetInputFontSlant(Controller& controller, FontSlant slant)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.slant          = slant;
-    controller.mImpl->mEventData->mInputStyle.isSlantDefined = true;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      CharacterIndex startOfSelectedText  = 0u;
-      Length         lengthOfSelectedText = 0u;
-
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        // Update a font description run for the selecting state.
-        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
-                                                                             controller.mImpl->mModel->mLogicalModel,
-                                                                             startOfSelectedText,
-                                                                             lengthOfSelectedText);
-
-        fontDescriptionRun.slant        = slant;
-        fontDescriptionRun.slantDefined = true;
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
-                                                                         VALIDATE_FONTS |
-                                                                         SHAPE_TEXT |
-                                                                         GET_GLYPH_METRICS |
-                                                                         LAYOUT |
-                                                                         UPDATE_LAYOUT_SIZE |
-                                                                         REORDER |
-                                                                         ALIGN);
-      controller.mImpl->mRecalculateNaturalSize = true;
-      controller.mImpl->RequestRelayout();
-
-      // As the font might change, recalculate the handle positions is needed.
-      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
-      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
-      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
-    }
-  }
-}
-
-bool Controller::InputFontHandler::IsInputFontSlantDefined(const Controller& controller)
-{
-  bool defined = false;
-
-  if(NULL != controller.mImpl->mEventData)
-  {
-    defined = controller.mImpl->mEventData->mInputStyle.isSlantDefined;
-  }
-
-  return defined;
-}
-
-FontSlant Controller::InputFontHandler::GetInputFontSlant(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mInputStyle.slant;
-  }
-
-  return controller.GetDefaultFontSlant();
-}
-
-void Controller::InputFontHandler::SetInputFontPointSize(Controller& controller, float size)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.size          = size;
-    controller.mImpl->mEventData->mInputStyle.isSizeDefined = true;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      CharacterIndex startOfSelectedText  = 0u;
-      Length         lengthOfSelectedText = 0u;
-
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        // Update a font description run for the selecting state.
-        FontDescriptionRun& fontDescriptionRun = UpdateSelectionFontStyleRun(controller.mImpl->mEventData,
-                                                                             controller.mImpl->mModel->mLogicalModel,
-                                                                             startOfSelectedText,
-                                                                             lengthOfSelectedText);
-
-        fontDescriptionRun.size        = static_cast<PointSize26Dot6>(size * controller.mImpl->GetFontSizeScale() * 64.f);
-        fontDescriptionRun.sizeDefined = true;
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending      = static_cast<OperationsMask>(controller.mImpl->mOperationsPending |
-                                                                         VALIDATE_FONTS |
-                                                                         SHAPE_TEXT |
-                                                                         GET_GLYPH_METRICS |
-                                                                         LAYOUT |
-                                                                         UPDATE_LAYOUT_SIZE |
-                                                                         REORDER |
-                                                                         ALIGN);
-      controller.mImpl->mRecalculateNaturalSize = true;
-      controller.mImpl->RequestRelayout();
-
-      // As the font might change, recalculate the handle positions is needed.
-      controller.mImpl->mEventData->mUpdateLeftSelectionPosition  = true;
-      controller.mImpl->mEventData->mUpdateRightSelectionPosition = true;
-      controller.mImpl->mEventData->mUpdateHighlightBox           = true;
-      controller.mImpl->mEventData->mScrollAfterUpdatePosition    = true;
-    }
-  }
-}
-
-float Controller::InputFontHandler::GetInputFontPointSize(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mInputStyle.size;
-  }
-
-  // Return the default font's point size if there is no EventData.
-  return controller.GetDefaultFontSize(Text::Controller::POINT_SIZE);
-}
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-input-font-handler.h b/dali-toolkit/internal/text/text-controller-input-font-handler.h
deleted file mode 100644 (file)
index f76bc41..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-definitions.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Controller::InputFontHandler
-{
-  static void               SetInputFontFamily(Controller& controller, const std::string& fontFamily);
-  static const std::string& GetInputFontFamily(const Controller& controller);
-  static void               SetInputFontWeight(const Controller& controller, FontWeight weight);
-  static bool               IsInputFontWeightDefined(const Controller& controller);
-  static FontWeight         GetInputFontWeight(const Controller& controller);
-  static void               SetInputFontWidth(Controller& controller, FontWidth width);
-  static bool               IsInputFontWidthDefined(const Controller& controller);
-  static FontWidth          GetInputFontWidth(const Controller& controller);
-  static void               SetInputFontSlant(Controller& controller, FontSlant slant);
-  static bool               IsInputFontSlantDefined(const Controller& controller);
-  static FontSlant          GetInputFontSlant(const Controller& controller);
-  static void               SetInputFontPointSize(Controller& controller, float size);
-  static float              GetInputFontPointSize(const Controller& controller);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_FONT_HANDLER_H
diff --git a/dali-toolkit/internal/text/text-controller-input-properties.cpp b/dali-toolkit/internal/text/text-controller-input-properties.cpp
deleted file mode 100644 (file)
index 99ef15a..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-input-properties.h>
-
-// EXTERNAL INCLUDES
-//#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-//#include <dali/devel-api/adaptor-framework/window-devel.h>
-//#include <dali/integration-api/debug.h>
-#include <memory.h>
-#include <cmath>
-#include <limits>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
-#include <dali-toolkit/internal/text/text-controller-event-handler.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-controller-relayouter.h>
-#include <dali-toolkit/internal/text/text-controller-text-updater.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-
-namespace
-{
-const std::string EMPTY_STRING("");
-}
-
-namespace Dali::Toolkit::Text
-{
-
-void Controller::InputProperties::SetInputColor(Controller& controller, const Vector4& color)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.textColor      = color;
-    controller.mImpl->mEventData->mInputStyle.isDefaultColor = false;
-
-    if(EventData::SELECTING == controller.mImpl->mEventData->mState || EventData::EDITING == controller.mImpl->mEventData->mState || EventData::INACTIVE == controller.mImpl->mEventData->mState)
-    {
-      if(EventData::SELECTING == controller.mImpl->mEventData->mState)
-      {
-        const bool handlesCrossed = controller.mImpl->mEventData->mLeftSelectionPosition > controller.mImpl->mEventData->mRightSelectionPosition;
-
-        // Get start and end position of selection
-        const CharacterIndex startOfSelectedText  = handlesCrossed ? controller.mImpl->mEventData->mRightSelectionPosition : controller.mImpl->mEventData->mLeftSelectionPosition;
-        const Length         lengthOfSelectedText = (handlesCrossed ? controller.mImpl->mEventData->mLeftSelectionPosition : controller.mImpl->mEventData->mRightSelectionPosition) - startOfSelectedText;
-
-        // Add the color run.
-        const VectorBase::SizeType numberOfRuns = controller.mImpl->mModel->mLogicalModel->mColorRuns.Count();
-        controller.mImpl->mModel->mLogicalModel->mColorRuns.Resize(numberOfRuns + 1u);
-
-        ColorRun& colorRun                       = *(controller.mImpl->mModel->mLogicalModel->mColorRuns.Begin() + numberOfRuns);
-        colorRun.color                           = color;
-        colorRun.characterRun.characterIndex     = startOfSelectedText;
-        colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
-
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = startOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = lengthOfSelectedText;
-      }
-      else
-      {
-        controller.mImpl->mTextUpdateInfo.mCharacterIndex             = 0;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = controller.mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
-        controller.mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd    = controller.mImpl->mModel->mLogicalModel->mText.Count();
-      }
-
-      // Request to relayout.
-      controller.mImpl->mOperationsPending = static_cast<OperationsMask>(controller.mImpl->mOperationsPending | COLOR);
-      controller.mImpl->RequestRelayout();
-    }
-  }
-}
-
-const Vector4& Controller::InputProperties::GetInputColor(const Controller& controller)
-{
-  // Return event text input color if we have it, otherwise just return the default text's color
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.textColor : controller.mImpl->mTextColor;
-}
-
-void Controller::InputProperties::SetInputLineSpacing(Controller& controller, float lineSpacing)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.lineSpacing          = lineSpacing;
-    controller.mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
-  }
-}
-
-float Controller::InputProperties::GetInputLineSpacing(const Controller& controller)
-{
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.lineSpacing : 0.0f;
-}
-
-void Controller::InputProperties::SetInputShadowProperties(Controller& controller, const std::string& shadowProperties)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
-  }
-}
-
-const std::string& Controller::InputProperties::GetInputShadowProperties(const Controller& controller)
-{
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING;
-}
-
-void Controller::InputProperties::SetInputUnderlineProperties(Controller& controller, const std::string& underlineProperties)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
-  }
-}
-
-const std::string& Controller::InputProperties::GetInputUnderlineProperties(const Controller& controller)
-{
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING;
-}
-
-void Controller::InputProperties::SetInputEmbossProperties(Controller& controller, const std::string& embossProperties)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
-  }
-}
-
-const std::string& Controller::InputProperties::GetInputEmbossProperties(const Controller& controller)
-{
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.embossProperties : controller.GetDefaultEmbossProperties();
-}
-
-void Controller::InputProperties::SetInputOutlineProperties(Controller& controller, const std::string& outlineProperties)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
-  }
-}
-
-const std::string& Controller::InputProperties::GetInputOutlineProperties(const Controller& controller)
-{
-  return controller.mImpl->mEventData ? controller.mImpl->mEventData->mInputStyle.outlineProperties : controller.GetDefaultOutlineProperties();
-}
-
-void Controller::InputProperties::SetInputModePassword(Controller& controller, bool passwordInput)
-{
-  if(controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mPasswordInput = passwordInput;
-  }
-}
-
-bool Controller::InputProperties::IsInputModePassword(Controller& controller)
-{
-  return controller.mImpl->mEventData && controller.mImpl->mEventData->mPasswordInput;
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller-input-properties.h b/dali-toolkit/internal/text/text-controller-input-properties.h
deleted file mode 100644 (file)
index d453b5f..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/input-method-context.h>
-#include <dali/public-api/events/gesture.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-//#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
-//#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
-//#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
-//#include <dali-toolkit/internal/text/decorator/text-decorator.h>
-//#include <dali-toolkit/internal/text/hidden-text.h>
-//#include <dali-toolkit/internal/text/input-filter.h>
-//#include <dali-toolkit/internal/text/layouts/layout-engine.h>
-//#include <dali-toolkit/internal/text/text-anchor-control-interface.h>
-//#include <dali-toolkit/internal/text/text-model-interface.h>
-//#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
-//#include <dali-toolkit/public-api/text/text-enumerations.h>
-
-namespace Dali::Toolkit::Text
-{
-struct Controller::InputProperties
-{
-  static void SetInputColor(Controller& controller, const Vector4& color);
-
-  static const Vector4& GetInputColor(const Controller& controller);
-
-  static void SetInputLineSpacing(Controller& controller, float lineSpacing);
-
-  static float GetInputLineSpacing(const Controller& controller);
-
-  static void SetInputShadowProperties(Controller& controller, const std::string& shadowProperties);
-
-  static const std::string& GetInputShadowProperties(const Controller& controller);
-
-  static void SetInputUnderlineProperties(Controller& controller, const std::string& underlineProperties);
-
-  static const std::string& GetInputUnderlineProperties(const Controller& controller);
-
-  static void SetInputEmbossProperties(Controller& controller, const std::string& embossProperties);
-
-  static const std::string& GetInputEmbossProperties(const Controller& controller);
-
-  static void SetInputOutlineProperties(Controller& controller, const std::string& outlineProperties);
-
-  static const std::string& GetInputOutlineProperties(const Controller& controller);
-
-  static void SetInputModePassword(Controller& controller, bool passwordInput);
-
-  static bool IsInputModePassword(Controller& controller);
-};
-
-
-} // namespace Dali::Toolkit::Text
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_INPUT_PROPERTIES_H
diff --git a/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp b/dali-toolkit/internal/text/text-controller-placeholder-handler.cpp
deleted file mode 100644 (file)
index 312ecb5..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-font-style.h>
-#include <dali-toolkit/public-api/controls/text-controls/placeholder-properties.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-const std::string EMPTY_STRING("");
-
-const char* const PLACEHOLDER_TEXT         = "text";
-const char* const PLACEHOLDER_TEXT_FOCUSED = "textFocused";
-const char* const PLACEHOLDER_COLOR        = "color";
-const char* const PLACEHOLDER_FONT_FAMILY  = "fontFamily";
-const char* const PLACEHOLDER_FONT_STYLE   = "fontStyle";
-const char* const PLACEHOLDER_POINT_SIZE   = "pointSize";
-const char* const PLACEHOLDER_PIXEL_SIZE   = "pixelSize";
-const char* const PLACEHOLDER_ELLIPSIS     = "ellipsis";
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void Controller::PlaceholderHandler::SetPlaceholderTextElideEnabled(Controller& controller, bool enabled)
-{
-  controller.mImpl->mEventData->mIsPlaceholderElideEnabled = enabled;
-  controller.mImpl->mEventData->mPlaceholderEllipsisFlag   = true;
-
-  // Update placeholder if there is no text
-  if(controller.mImpl->IsShowingPlaceholderText() ||
-     (0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
-  {
-    ShowPlaceholderText(*controller.mImpl);
-  }
-}
-
-bool Controller::PlaceholderHandler::IsPlaceholderTextElideEnabled(const Controller& controller)
-{
-  return controller.mImpl->mEventData->mIsPlaceholderElideEnabled;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderText(Controller& controller, PlaceholderType type, const std::string& text)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(PLACEHOLDER_TYPE_INACTIVE == type)
-    {
-      controller.mImpl->mEventData->mPlaceholderTextInactive = text;
-    }
-    else
-    {
-      controller.mImpl->mEventData->mPlaceholderTextActive = text;
-    }
-
-    // Update placeholder if there is no text
-    if(controller.mImpl->IsShowingPlaceholderText() ||
-       (0u == controller.mImpl->mModel->mLogicalModel->mText.Count()))
-    {
-      ShowPlaceholderText(*controller.mImpl);
-    }
-  }
-}
-
-void Controller::PlaceholderHandler::GetPlaceholderText(const Controller& controller, PlaceholderType type, std::string& text)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(PLACEHOLDER_TYPE_INACTIVE == type)
-    {
-      text = controller.mImpl->mEventData->mPlaceholderTextInactive;
-    }
-    else
-    {
-      text = controller.mImpl->mEventData->mPlaceholderTextActive;
-    }
-  }
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderFontFamily(Controller& controller, const std::string& placeholderTextFontFamily)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    // if mPlaceholderFont is null, create an instance.
-    CreatePlaceholderFont(controller);
-
-    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.family = placeholderTextFontFamily;
-    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetPlaceholderFontFamily %s\n", placeholderTextFontFamily.c_str());
-    controller.mImpl->mEventData->mPlaceholderFont->familyDefined = !placeholderTextFontFamily.empty();
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-const std::string& Controller::PlaceholderHandler::GetPlaceholderFontFamily(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.family;
-  }
-
-  return EMPTY_STRING;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderTextFontWeight(Controller& controller, FontWeight weight)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    // if mPlaceholderFont is null, create an instance.
-    CreatePlaceholderFont(controller);
-
-    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.weight = weight;
-    controller.mImpl->mEventData->mPlaceholderFont->weightDefined           = true;
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-bool Controller::PlaceholderHandler::IsPlaceholderTextFontWeightDefined(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->weightDefined;
-  }
-  return false;
-}
-
-FontWeight Controller::PlaceholderHandler::GetPlaceholderTextFontWeight(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.weight;
-  }
-
-  return TextAbstraction::FontWeight::NORMAL;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderTextFontWidth(Controller& controller, FontWidth width)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    // if mPlaceholderFont is null, create an instance.
-    CreatePlaceholderFont(controller);
-
-    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.width = width;
-    controller.mImpl->mEventData->mPlaceholderFont->widthDefined           = true;
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-bool Controller::PlaceholderHandler::IsPlaceholderTextFontWidthDefined(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->widthDefined;
-  }
-  return false;
-}
-
-FontWidth Controller::PlaceholderHandler::GetPlaceholderTextFontWidth(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.width;
-  }
-
-  return TextAbstraction::FontWidth::NORMAL;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderTextFontSlant(Controller& controller, FontSlant slant)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    // if mPlaceholderFont is null, create an instance.
-    CreatePlaceholderFont(controller);
-
-    controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.slant = slant;
-    controller.mImpl->mEventData->mPlaceholderFont->slantDefined           = true;
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-bool Controller::PlaceholderHandler::IsPlaceholderTextFontSlantDefined(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->slantDefined;
-  }
-  return false;
-}
-
-FontSlant Controller::PlaceholderHandler::GetPlaceholderTextFontSlant(const Controller& controller)
-{
-  if((NULL != controller.mImpl->mEventData) && (NULL != controller.mImpl->mEventData->mPlaceholderFont))
-  {
-    return controller.mImpl->mEventData->mPlaceholderFont->mFontDescription.slant;
-  }
-
-  return TextAbstraction::FontSlant::NORMAL;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderTextFontSize(Controller& controller, float fontSize, FontSizeType type)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    // if mPlaceholderFont is null, create an instance.
-    CreatePlaceholderFont(controller);
-
-    switch(type)
-    {
-      case POINT_SIZE:
-      {
-        controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize = fontSize;
-        controller.mImpl->mEventData->mPlaceholderFont->sizeDefined       = true;
-        controller.mImpl->mEventData->mIsPlaceholderPixelSize             = false; // Font size flag
-        break;
-      }
-      case PIXEL_SIZE:
-      {
-        // Point size = Pixel size * 72.f / DPI
-        unsigned int                horizontalDpi = 0u;
-        unsigned int                verticalDpi   = 0u;
-        TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
-        fontClient.GetDpi(horizontalDpi, verticalDpi);
-
-        controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
-        controller.mImpl->mEventData->mPlaceholderFont->sizeDefined       = true;
-        controller.mImpl->mEventData->mIsPlaceholderPixelSize             = true; // Font size flag
-        break;
-      }
-    }
-
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-float Controller::PlaceholderHandler::GetPlaceholderTextFontSize(const Controller& controller, FontSizeType type)
-{
-  float value = 0.0f;
-  if(NULL != controller.mImpl->mEventData)
-  {
-    switch(type)
-    {
-      case POINT_SIZE:
-      {
-        if(NULL != controller.mImpl->mEventData->mPlaceholderFont)
-        {
-          value = controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize;
-        }
-        else
-        {
-          // If the placeholder text font size is not set, then return the default font size.
-          value = controller.GetDefaultFontSize(POINT_SIZE);
-        }
-        break;
-      }
-      case PIXEL_SIZE:
-      {
-        if(NULL != controller.mImpl->mEventData->mPlaceholderFont)
-        {
-          // Pixel size = Point size * DPI / 72.f
-          unsigned int                horizontalDpi = 0u;
-          unsigned int                verticalDpi   = 0u;
-          TextAbstraction::FontClient fontClient    = TextAbstraction::FontClient::Get();
-          fontClient.GetDpi(horizontalDpi, verticalDpi);
-
-          value = controller.mImpl->mEventData->mPlaceholderFont->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
-        }
-        else
-        {
-          // If the placeholder text font size is not set, then return the default font size.
-          value = controller.GetDefaultFontSize(PIXEL_SIZE);
-        }
-        break;
-      }
-    }
-    return value;
-  }
-
-  return value;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderTextColor(Controller& controller, const Vector4& textColor)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    controller.mImpl->mEventData->mPlaceholderTextColor = textColor;
-  }
-
-  if(controller.mImpl->IsShowingPlaceholderText())
-  {
-    controller.mImpl->mModel->mVisualModel->SetTextColor(textColor);
-    controller.mImpl->mModel->mLogicalModel->mColorRuns.Clear();
-    controller.mImpl->mOperationsPending = static_cast<OperationsMask>(controller.mImpl->mOperationsPending | COLOR);
-    controller.mImpl->RequestRelayout();
-  }
-}
-
-const Vector4& Controller::PlaceholderHandler::GetPlaceholderTextColor(const Controller& controller)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    return controller.mImpl->mEventData->mPlaceholderTextColor;
-  }
-
-  return Color::BLACK;
-}
-
-void Controller::PlaceholderHandler::SetPlaceholderProperty(Controller& controller, const Property::Map& map)
-{
-  const Property::Map::SizeType count = map.Count();
-
-  for(Property::Map::SizeType position = 0; position < count; ++position)
-  {
-    KeyValuePair     keyValue = map.GetKeyValue(position);
-    Property::Key&   key      = keyValue.first;
-    Property::Value& value    = keyValue.second;
-
-    if(key == Toolkit::Text::PlaceHolder::Property::TEXT || key == PLACEHOLDER_TEXT)
-    {
-      std::string text = "";
-      value.Get(text);
-      SetPlaceholderText(controller, Controller::PLACEHOLDER_TYPE_INACTIVE, text);
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::TEXT_FOCUSED || key == PLACEHOLDER_TEXT_FOCUSED)
-    {
-      std::string text = "";
-      value.Get(text);
-      SetPlaceholderText(controller, Controller::PLACEHOLDER_TYPE_ACTIVE, text);
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::COLOR || key == PLACEHOLDER_COLOR)
-    {
-      Vector4 textColor;
-      value.Get(textColor);
-      if(GetPlaceholderTextColor(controller) != textColor)
-      {
-        SetPlaceholderTextColor(controller, textColor);
-      }
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::FONT_FAMILY || key == PLACEHOLDER_FONT_FAMILY)
-    {
-      std::string fontFamily = "";
-      value.Get(fontFamily);
-      SetPlaceholderFontFamily(controller, fontFamily);
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::FONT_STYLE || key == PLACEHOLDER_FONT_STYLE)
-    {
-      SetFontStyleProperty(&controller, value, Text::FontStyle::PLACEHOLDER);
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::POINT_SIZE || key == PLACEHOLDER_POINT_SIZE)
-    {
-      float pointSize;
-      value.Get(pointSize);
-      if(!Equals(GetPlaceholderTextFontSize(controller, Text::Controller::POINT_SIZE), pointSize))
-      {
-        SetPlaceholderTextFontSize(controller, pointSize, Text::Controller::POINT_SIZE);
-      }
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::PIXEL_SIZE || key == PLACEHOLDER_PIXEL_SIZE)
-    {
-      float pixelSize;
-      value.Get(pixelSize);
-      if(!Equals(GetPlaceholderTextFontSize(controller, Text::Controller::PIXEL_SIZE), pixelSize))
-      {
-        SetPlaceholderTextFontSize(controller, pixelSize, Text::Controller::PIXEL_SIZE);
-      }
-    }
-    else if(key == Toolkit::Text::PlaceHolder::Property::ELLIPSIS || key == PLACEHOLDER_ELLIPSIS)
-    {
-      bool ellipsis;
-      value.Get(ellipsis);
-      SetPlaceholderTextElideEnabled(controller, ellipsis);
-    }
-  }
-}
-
-void Controller::PlaceholderHandler::GetPlaceholderProperty(Controller& controller, Property::Map& map)
-{
-  if(NULL != controller.mImpl->mEventData)
-  {
-    if(!controller.mImpl->mEventData->mPlaceholderTextActive.empty())
-    {
-      map[Text::PlaceHolder::Property::TEXT_FOCUSED] = controller.mImpl->mEventData->mPlaceholderTextActive;
-    }
-    if(!controller.mImpl->mEventData->mPlaceholderTextInactive.empty())
-    {
-      map[Text::PlaceHolder::Property::TEXT] = controller.mImpl->mEventData->mPlaceholderTextInactive;
-    }
-
-    map[Text::PlaceHolder::Property::COLOR]       = controller.mImpl->mEventData->mPlaceholderTextColor;
-    map[Text::PlaceHolder::Property::FONT_FAMILY] = GetPlaceholderFontFamily(controller);
-
-    Property::Value fontStyleMapGet;
-    GetFontStyleProperty(&controller, fontStyleMapGet, Text::FontStyle::PLACEHOLDER);
-    map[Text::PlaceHolder::Property::FONT_STYLE] = fontStyleMapGet;
-
-    // Choose font size : POINT_SIZE or PIXEL_SIZE
-    if(!controller.mImpl->mEventData->mIsPlaceholderPixelSize)
-    {
-      map[Text::PlaceHolder::Property::POINT_SIZE] = GetPlaceholderTextFontSize(controller, Text::Controller::POINT_SIZE);
-    }
-    else
-    {
-      map[Text::PlaceHolder::Property::PIXEL_SIZE] = GetPlaceholderTextFontSize(controller, Text::Controller::PIXEL_SIZE);
-    }
-
-    if(controller.mImpl->mEventData->mPlaceholderEllipsisFlag)
-    {
-      map[Text::PlaceHolder::Property::ELLIPSIS] = IsPlaceholderTextElideEnabled(controller);
-    }
-  }
-}
-
-void Controller::PlaceholderHandler::ShowPlaceholderText(Controller::Impl& impl)
-{
-  if(impl.IsPlaceholderAvailable())
-  {
-    EventData*& eventData = impl.mEventData;
-    DALI_ASSERT_DEBUG(eventData && "No placeholder text available");
-
-    if(NULL == eventData)
-    {
-      return;
-    }
-
-    eventData->mIsShowingPlaceholderText = true;
-
-    // Disable handles when showing place-holder text
-    DecoratorPtr& decorator = eventData->mDecorator;
-    decorator->SetHandleActive(GRAB_HANDLE, false);
-    decorator->SetHandleActive(LEFT_SELECTION_HANDLE, false);
-    decorator->SetHandleActive(RIGHT_SELECTION_HANDLE, false);
-
-    const char* text(NULL);
-    size_t      size(0);
-
-    // TODO - Switch Placeholder text when changing state
-    std::string& placeholderTextActive = eventData->mPlaceholderTextActive;
-    if((EventData::INACTIVE != eventData->mState) &&
-       (0u != placeholderTextActive.c_str()))
-    {
-      text = placeholderTextActive.c_str();
-      size = placeholderTextActive.size();
-    }
-    else
-    {
-      std::string& placeholderTextInactive = eventData->mPlaceholderTextInactive;
-      text                                 = placeholderTextInactive.c_str();
-      size                                 = placeholderTextInactive.size();
-    }
-
-    TextUpdateInfo& textUpdateInfo             = impl.mTextUpdateInfo;
-    textUpdateInfo.mCharacterIndex             = 0u;
-    textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
-
-    // Reset model for showing placeholder.
-    ModelPtr&        model        = impl.mModel;
-    LogicalModelPtr& logicalModel = model->mLogicalModel;
-    logicalModel->mText.Clear();
-    model->mVisualModel->SetTextColor(eventData->mPlaceholderTextColor);
-
-    // Convert text into UTF-32
-    Vector<Character>& utf32Characters = logicalModel->mText;
-    utf32Characters.Resize(size);
-
-    // This is a bit horrible but std::string returns a (signed) char*
-    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text);
-
-    // Transform a text array encoded in utf8 into an array encoded in utf32.
-    // It returns the actual number of characters.
-    const Length characterCount = Utf8ToUtf32(utf8, size, utf32Characters.Begin());
-    utf32Characters.Resize(characterCount);
-
-    // The characters to be added.
-    textUpdateInfo.mNumberOfCharactersToAdd = characterCount;
-
-    // Reset the cursor position
-    eventData->mPrimaryCursorPosition = 0;
-
-    // The natural size needs to be re-calculated.
-    impl.mRecalculateNaturalSize = true;
-
-    // The text direction needs to be updated.
-    impl.mUpdateTextDirection = true;
-
-    // Apply modifications to the model
-    impl.mOperationsPending = ALL_OPERATIONS;
-
-    // Update the rest of the model during size negotiation
-    impl.QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
-  }
-}
-
-void Controller::PlaceholderHandler::CreatePlaceholderFont(Controller& controller)
-{
-  if(nullptr == controller.mImpl->mEventData->mPlaceholderFont)
-  {
-    controller.mImpl->mEventData->mPlaceholderFont = std::unique_ptr<FontDefaults>(new FontDefaults());
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-placeholder-handler.h b/dali-toolkit/internal/text/text-controller-placeholder-handler.h
deleted file mode 100644 (file)
index 9c81eb1..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/math/vector4.h>
-#include <dali/public-api/object/property-map.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-definitions.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-struct Controller::PlaceholderHandler
-{
-  static void               SetPlaceholderTextElideEnabled(Controller& controller, bool enabled);
-  static bool               IsPlaceholderTextElideEnabled(const Controller& controller);
-  static void               SetPlaceholderText(Controller& controller, PlaceholderType type, const std::string& text);
-  static void               GetPlaceholderText(const Controller& controller, PlaceholderType type, std::string& text);
-  static void               SetPlaceholderFontFamily(Controller& controller, const std::string& placeholderTextFontFamily);
-  static const std::string& GetPlaceholderFontFamily(const Controller& controller);
-  static void               SetPlaceholderTextFontWeight(Controller& controller, FontWeight weight);
-  static bool               IsPlaceholderTextFontWeightDefined(const Controller& controller);
-  static FontWeight         GetPlaceholderTextFontWeight(const Controller& controller);
-  static void               SetPlaceholderTextFontWidth(Controller& controller, FontWidth width);
-  static bool               IsPlaceholderTextFontWidthDefined(const Controller& controller);
-  static FontWidth          GetPlaceholderTextFontWidth(const Controller& controller);
-  static void               SetPlaceholderTextFontSlant(Controller& controller, FontSlant slant);
-  static bool               IsPlaceholderTextFontSlantDefined(const Controller& controller);
-  static FontSlant          GetPlaceholderTextFontSlant(const Controller& controller);
-  static void               SetPlaceholderTextFontSize(Controller& controller, float fontSize, FontSizeType type);
-  static float              GetPlaceholderTextFontSize(const Controller& controller, FontSizeType type);
-  static void               SetPlaceholderTextColor(Controller& controller, const Vector4& textColor);
-  static const Vector4&     GetPlaceholderTextColor(const Controller& controller);
-  static void               SetPlaceholderProperty(Controller& controller, const Property::Map& map);
-  static void               GetPlaceholderProperty(Controller& controller, Property::Map& map);
-  static void               ShowPlaceholderText(Controller::Impl& impl);
-  static void               CreatePlaceholderFont(Controller& controller);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_PLACEHOLDER_HANDLER_H
diff --git a/dali-toolkit/internal/text/text-controller-relayouter.cpp b/dali-toolkit/internal/text/text-controller-relayouter.cpp
deleted file mode 100644 (file)
index 527bb99..0000000
+++ /dev/null
@@ -1,869 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-relayouter.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-#include <limits>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
-#include <dali-toolkit/internal/text/text-controller-event-handler.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-constexpr float MAX_FLOAT = std::numeric_limits<float>::max();
-
-float ConvertToEven(float value)
-{
-  int intValue(static_cast<int>(value));
-  return static_cast<float>(intValue + (intValue & 1));
-}
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-Size Controller::Relayouter::CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->CalculateLayoutSizeOnRequiredControllerSize\n");
-  Size calculatedLayoutSize;
-
-  Controller::Impl& impl        = *controller.mImpl;
-  ModelPtr&         model       = impl.mModel;
-  VisualModelPtr&   visualModel = model->mVisualModel;
-
-  // Operations that can be done only once until the text changes.
-  const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
-                                                                        GET_SCRIPTS |
-                                                                        VALIDATE_FONTS |
-                                                                        GET_LINE_BREAKS |
-                                                                        BIDI_INFO |
-                                                                        SHAPE_TEXT |
-                                                                        GET_GLYPH_METRICS);
-
-  const OperationsMask sizeOperations = static_cast<OperationsMask>(LAYOUT | ALIGN | REORDER);
-
-  // Set the update info to relayout the whole text.
-  TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
-  if((0 == textUpdateInfo.mNumberOfCharactersToAdd) &&
-     (0 == textUpdateInfo.mPreviousNumberOfCharacters) &&
-     ((visualModel->mControlSize.width < Math::MACHINE_EPSILON_1000) || (visualModel->mControlSize.height < Math::MACHINE_EPSILON_1000)))
-  {
-    textUpdateInfo.mNumberOfCharactersToAdd = model->mLogicalModel->mText.Count();
-  }
-  textUpdateInfo.mParagraphCharacterIndex     = 0u;
-  textUpdateInfo.mRequestedNumberOfCharacters = model->mLogicalModel->mText.Count();
-
-  // Get a reference to the pending operations member
-  OperationsMask& operationsPending = impl.mOperationsPending;
-
-  // Store the actual control's size to restore later.
-  const Size actualControlSize = visualModel->mControlSize;
-
-  // Whether the text control is editable
-  const bool isEditable = NULL != impl.mEventData;
-
-  if(!isEditable)
-  {
-    impl.UpdateModel(onlyOnceOperations);
-
-    // Layout the text for the new width.
-    operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask);
-
-    DoRelayout(impl,
-               requestedControllerSize,
-               static_cast<OperationsMask>(onlyOnceOperations | requestedOperationsMask),
-               calculatedLayoutSize);
-
-    textUpdateInfo.Clear();
-    textUpdateInfo.mClearAll = true;
-
-    // Do not do again the only once operations.
-    operationsPending = static_cast<OperationsMask>(operationsPending & ~onlyOnceOperations);
-  }
-  else
-  {
-    // This is to keep Index to the first character to be updated.
-    // Then restore it after calling Clear method.
-    auto updateInfoCharIndexBackup = textUpdateInfo.mCharacterIndex;
-
-    // Layout the text for the new width.
-    // Apply the pending operations, requested operations and the only once operations.
-    // Then remove onlyOnceOperations
-    operationsPending = static_cast<OperationsMask>(operationsPending | requestedOperationsMask | onlyOnceOperations);
-
-    // Make sure the model is up-to-date before layouting
-    impl.UpdateModel(static_cast<OperationsMask>(operationsPending & ~UPDATE_LAYOUT_SIZE));
-
-    DoRelayout(impl,
-               requestedControllerSize,
-               static_cast<OperationsMask>(operationsPending & ~UPDATE_LAYOUT_SIZE),
-               calculatedLayoutSize);
-
-    // Clear the update info. This info will be set the next time the text is updated.
-    textUpdateInfo.Clear();
-
-    //TODO: Refactor "DoRelayout" and extract common code of size calculation without modifying attributes of mVisualModel,
-    //TODO: then calculate GlyphPositions. Lines, Size, Layout for Natural-Size
-    //TODO: and utilize the values in OperationsPending and TextUpdateInfo without changing the original one.
-    //TODO: Also it will improve performance because there is no need todo FullRelyout on the next need for layouting.
-
-    // FullRelayoutNeeded should be true because DoRelayout is MAX_FLOAT, MAX_FLOAT.
-    // By this no need to take backup and restore it.
-    textUpdateInfo.mFullRelayoutNeeded = true;
-
-    // Restore mCharacterIndex. Because "Clear" set it to the maximum integer.
-    // The "CalculateTextUpdateIndices" does not work proprely because the mCharacterIndex will be greater than mPreviousNumberOfCharacters.
-    // Which apply an assumption to update only the last  paragraph. That could cause many of out of index crashes.
-    textUpdateInfo.mCharacterIndex = updateInfoCharIndexBackup;
-  }
-
-  // Do the size related operations again.
-  operationsPending = static_cast<OperationsMask>(operationsPending | sizeOperations);
-
-  // Restore the actual control's size.
-  visualModel->mControlSize = actualControlSize;
-
-  return calculatedLayoutSize;
-}
-
-Vector3 Controller::Relayouter::GetNaturalSize(Controller& controller)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetNaturalSize\n");
-  Vector3 naturalSizeVec3;
-
-  // Make sure the model is up-to-date before layouting
-  EventHandler::ProcessModifyEvents(controller);
-
-  Controller::Impl& impl        = *controller.mImpl;
-  ModelPtr&         model       = impl.mModel;
-  VisualModelPtr&   visualModel = model->mVisualModel;
-
-  if(impl.mRecalculateNaturalSize)
-  {
-    Size naturalSize;
-
-    // Layout the text for the new width.
-    OperationsMask requestedOperationsMask  = static_cast<OperationsMask>(LAYOUT | REORDER);
-    Size           sizeMaxWidthAndMaxHeight = Size(MAX_FLOAT, MAX_FLOAT);
-
-    naturalSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeMaxWidthAndMaxHeight, requestedOperationsMask);
-
-    // Stores the natural size to avoid recalculate it again
-    // unless the text/style changes.
-    visualModel->SetNaturalSize(naturalSize);
-    naturalSizeVec3 = naturalSize;
-
-    impl.mRecalculateNaturalSize = false;
-
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
-  }
-  else
-  {
-    naturalSizeVec3 = visualModel->GetNaturalSize();
-
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSizeVec3.x, naturalSizeVec3.y, naturalSizeVec3.z);
-  }
-
-  naturalSizeVec3.x = ConvertToEven(naturalSizeVec3.x);
-  naturalSizeVec3.y = ConvertToEven(naturalSizeVec3.y);
-
-  return naturalSizeVec3;
-}
-
-bool Controller::Relayouter::CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize)
-{
-  Size              textSize;
-  Controller::Impl& impl            = *controller.mImpl;
-  TextUpdateInfo&   textUpdateInfo  = impl.mTextUpdateInfo;
-  impl.mFontDefaults->mFitPointSize = pointSize;
-  impl.mFontDefaults->sizeDefined   = true;
-  impl.ClearFontData();
-
-  // Operations that can be done only once until the text changes.
-  const OperationsMask onlyOnceOperations = static_cast<OperationsMask>(CONVERT_TO_UTF32 |
-                                                                        GET_SCRIPTS |
-                                                                        VALIDATE_FONTS |
-                                                                        GET_LINE_BREAKS |
-                                                                        BIDI_INFO |
-                                                                        SHAPE_TEXT |
-                                                                        GET_GLYPH_METRICS);
-
-  textUpdateInfo.mParagraphCharacterIndex     = 0u;
-  textUpdateInfo.mRequestedNumberOfCharacters = impl.mModel->mLogicalModel->mText.Count();
-
-  // Make sure the model is up-to-date before layouting
-  impl.UpdateModel(onlyOnceOperations);
-
-  DoRelayout(impl,
-             Size(layoutSize.width, MAX_FLOAT),
-             static_cast<OperationsMask>(onlyOnceOperations | LAYOUT),
-             textSize);
-
-  // Clear the update info. This info will be set the next time the text is updated.
-  textUpdateInfo.Clear();
-  textUpdateInfo.mClearAll = true;
-
-  if(textSize.width > layoutSize.width || textSize.height > layoutSize.height)
-  {
-    return false;
-  }
-  return true;
-}
-
-void Controller::Relayouter::FitPointSizeforLayout(Controller& controller, const Size& layoutSize)
-{
-  Controller::Impl& impl = *controller.mImpl;
-
-  const OperationsMask operations = impl.mOperationsPending;
-  if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations) || impl.mTextFitContentSize != layoutSize)
-  {
-    ModelPtr& model = impl.mModel;
-
-    bool  actualellipsis      = model->mElideEnabled;
-    float minPointSize        = impl.mTextFitMinSize;
-    float maxPointSize        = impl.mTextFitMaxSize;
-    float pointInterval       = impl.mTextFitStepSize;
-    float currentFitPointSize = impl.mFontDefaults->mFitPointSize;
-
-    model->mElideEnabled = false;
-    Vector<float> pointSizeArray;
-
-    // check zero value
-    if(pointInterval < 1.f)
-    {
-      impl.mTextFitStepSize = pointInterval = 1.0f;
-    }
-
-    pointSizeArray.Reserve(static_cast<unsigned int>(ceil((maxPointSize - minPointSize) / pointInterval)));
-
-    for(float i = minPointSize; i < maxPointSize; i += pointInterval)
-    {
-      pointSizeArray.PushBack(i);
-    }
-
-    pointSizeArray.PushBack(maxPointSize);
-
-    int bestSizeIndex = 0;
-    int min           = bestSizeIndex + 1;
-    int max           = pointSizeArray.Size() - 1;
-    while(min <= max)
-    {
-      int destI = (min + max) / 2;
-
-      if(CheckForTextFit(controller, pointSizeArray[destI], layoutSize))
-      {
-        bestSizeIndex = min;
-        min           = destI + 1;
-      }
-      else
-      {
-        max           = destI - 1;
-        bestSizeIndex = max;
-      }
-    }
-
-    model->mElideEnabled = actualellipsis;
-    if(currentFitPointSize != pointSizeArray[bestSizeIndex])
-    {
-      impl.mTextFitChanged = true;
-    }
-    impl.mFontDefaults->mFitPointSize = pointSizeArray[bestSizeIndex];
-    impl.mFontDefaults->sizeDefined   = true;
-    impl.ClearFontData();
-  }
-}
-
-float Controller::Relayouter::GetHeightForWidth(Controller& controller, float width)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::GetHeightForWidth %p width %f\n", &controller, width);
-
-  // Make sure the model is up-to-date before layouting
-  EventHandler::ProcessModifyEvents(controller);
-
-  Controller::Impl& impl           = *controller.mImpl;
-  ModelPtr&         model          = impl.mModel;
-  VisualModelPtr&   visualModel    = model->mVisualModel;
-  TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
-
-  Size layoutSize;
-
-  if(fabsf(width - visualModel->mControlSize.width) > Math::MACHINE_EPSILON_1000 ||
-     textUpdateInfo.mFullRelayoutNeeded ||
-     textUpdateInfo.mClearAll)
-  {
-    // Layout the text for the new width.
-    OperationsMask requestedOperationsMask        = static_cast<OperationsMask>(LAYOUT);
-    Size           sizeRequestedWidthAndMaxHeight = Size(width, MAX_FLOAT);
-
-    layoutSize = CalculateLayoutSizeOnRequiredControllerSize(controller, sizeRequestedWidthAndMaxHeight, requestedOperationsMask);
-
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height);
-  }
-  else
-  {
-    layoutSize = visualModel->GetLayoutSize();
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth cached %f\n", layoutSize.height);
-  }
-
-  return layoutSize.height;
-}
-
-Controller::UpdateTextType Controller::Relayouter::Relayout(Controller& controller, const Size& size, Dali::LayoutDirection::Type layoutDirection)
-{
-  Controller::Impl& impl           = *controller.mImpl;
-  ModelPtr&         model          = impl.mModel;
-  VisualModelPtr&   visualModel    = model->mVisualModel;
-  TextUpdateInfo&   textUpdateInfo = impl.mTextUpdateInfo;
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", &controller, size.width, size.height, impl.mIsAutoScrollEnabled ? "true" : "false");
-
-  UpdateTextType updateTextType = NONE_UPDATED;
-
-  if((size.width < Math::MACHINE_EPSILON_1000) || (size.height < Math::MACHINE_EPSILON_1000))
-  {
-    if(0u != visualModel->mGlyphPositions.Count())
-    {
-      visualModel->mGlyphPositions.Clear();
-      updateTextType = MODEL_UPDATED;
-    }
-
-    // Clear the update info. This info will be set the next time the text is updated.
-    textUpdateInfo.Clear();
-
-    // Not worth to relayout if width or height is equal to zero.
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n");
-
-    return updateTextType;
-  }
-
-  // Whether a new size has been set.
-  const bool newSize = (size != visualModel->mControlSize);
-
-  // Get a reference to the pending operations member
-  OperationsMask& operationsPending = impl.mOperationsPending;
-
-  if(newSize)
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", visualModel->mControlSize.width, visualModel->mControlSize.height);
-
-    if((0 == textUpdateInfo.mNumberOfCharactersToAdd) &&
-       (0 == textUpdateInfo.mPreviousNumberOfCharacters) &&
-       ((visualModel->mControlSize.width < Math::MACHINE_EPSILON_1000) || (visualModel->mControlSize.height < Math::MACHINE_EPSILON_1000)))
-    {
-      textUpdateInfo.mNumberOfCharactersToAdd = model->mLogicalModel->mText.Count();
-    }
-
-    // Layout operations that need to be done if the size changes.
-    operationsPending = static_cast<OperationsMask>(operationsPending |
-                                                    LAYOUT |
-                                                    ALIGN |
-                                                    UPDATE_LAYOUT_SIZE |
-                                                    REORDER);
-    // Set the update info to relayout the whole text.
-    textUpdateInfo.mFullRelayoutNeeded = true;
-    textUpdateInfo.mCharacterIndex     = 0u;
-
-    // Store the size used to layout the text.
-    visualModel->mControlSize = size;
-  }
-
-  // Whether there are modify events.
-  if(0u != impl.mModifyEvents.Count())
-  {
-    // Style operations that need to be done if the text is modified.
-    operationsPending = static_cast<OperationsMask>(operationsPending | COLOR);
-  }
-
-  // Set the update info to elide the text.
-  if(model->mElideEnabled ||
-     ((NULL != impl.mEventData) && impl.mEventData->mIsPlaceholderElideEnabled))
-  {
-    // Update Text layout for applying elided
-    operationsPending                  = static_cast<OperationsMask>(operationsPending |
-                                                    ALIGN |
-                                                    LAYOUT |
-                                                    UPDATE_LAYOUT_SIZE |
-                                                    REORDER);
-    textUpdateInfo.mFullRelayoutNeeded = true;
-    textUpdateInfo.mCharacterIndex     = 0u;
-  }
-
-  bool layoutDirectionChanged = false;
-  if(impl.mLayoutDirection != layoutDirection)
-  {
-    // Flag to indicate that the layout direction has changed.
-    layoutDirectionChanged = true;
-    // Clear the update info. This info will be set the next time the text is updated.
-    textUpdateInfo.mClearAll = true;
-    // Apply modifications to the model
-    // Shape the text again is needed because characters like '()[]{}' have to be mirrored and the glyphs generated again.
-    operationsPending     = static_cast<OperationsMask>(operationsPending |
-                                                    GET_GLYPH_METRICS |
-                                                    SHAPE_TEXT |
-                                                    UPDATE_DIRECTION |
-                                                    ALIGN |
-                                                    LAYOUT |
-                                                    BIDI_INFO |
-                                                    REORDER);
-    impl.mLayoutDirection = layoutDirection;
-  }
-
-  // Make sure the model is up-to-date before layouting.
-  EventHandler::ProcessModifyEvents(controller);
-  bool updated = impl.UpdateModel(operationsPending);
-
-  // Layout the text.
-  Size layoutSize;
-  updated = DoRelayout(impl, size, operationsPending, layoutSize) || updated;
-
-  if(updated)
-  {
-    updateTextType = MODEL_UPDATED;
-  }
-
-  // Do not re-do any operation until something changes.
-  operationsPending          = NO_OPERATION;
-  model->mScrollPositionLast = model->mScrollPosition;
-
-  // Whether the text control is editable
-  const bool isEditable = NULL != impl.mEventData;
-
-  // Keep the current offset as it will be used to update the decorator's positions (if the size changes).
-  Vector2 offset;
-  if(newSize && isEditable)
-  {
-    offset = model->mScrollPosition;
-  }
-
-  if(!isEditable || !controller.IsMultiLineEnabled())
-  {
-    // After doing the text layout, the vertical offset to place the actor in the desired position can be calculated.
-    CalculateVerticalOffset(impl, size);
-  }
-  else // TextEditor
-  {
-    // If layoutSize is bigger than size, vertical align has no meaning.
-    if(layoutSize.y < size.y)
-    {
-      CalculateVerticalOffset(impl, size);
-      if(impl.mEventData)
-      {
-        impl.mEventData->mScrollAfterDelete = false;
-      }
-    }
-  }
-
-  if(isEditable)
-  {
-    if(newSize || layoutDirectionChanged)
-    {
-      // If there is a new size or layout direction is changed, the scroll position needs to be clamped.
-      impl.ClampHorizontalScroll(layoutSize);
-
-      // Update the decorator's positions is needed if there is a new size.
-      impl.mEventData->mDecorator->UpdatePositions(model->mScrollPosition - offset);
-
-      // All decorator elements need to be updated.
-      if(EventData::IsEditingState(impl.mEventData->mState))
-      {
-        impl.mEventData->mScrollAfterUpdatePosition = true;
-        impl.mEventData->mUpdateCursorPosition      = true;
-        impl.mEventData->mUpdateGrabHandlePosition  = true;
-      }
-      else if(impl.mEventData->mState == EventData::SELECTING)
-      {
-        impl.mEventData->mUpdateHighlightBox = true;
-      }
-    }
-
-    // Move the cursor, grab handle etc.
-    if(impl.ProcessInputEvents())
-    {
-      updateTextType = static_cast<UpdateTextType>(updateTextType | DECORATOR_UPDATED);
-    }
-  }
-
-  // Clear the update info. This info will be set the next time the text is updated.
-  textUpdateInfo.Clear();
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayout\n");
-
-  return updateTextType;
-}
-
-bool Controller::Relayouter::DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::Relayouter::DoRelayout %p size %f,%f\n", &impl, size.width, size.height);
-  bool viewUpdated(false);
-
-  // Calculate the operations to be done.
-  const OperationsMask operations = static_cast<OperationsMask>(impl.mOperationsPending & operationsRequired);
-
-  TextUpdateInfo&      textUpdateInfo              = impl.mTextUpdateInfo;
-  const CharacterIndex startIndex                  = textUpdateInfo.mParagraphCharacterIndex;
-  const Length         requestedNumberOfCharacters = textUpdateInfo.mRequestedNumberOfCharacters;
-
-  // Get the current layout size.
-  VisualModelPtr& visualModel = impl.mModel->mVisualModel;
-  layoutSize                  = visualModel->GetLayoutSize();
-
-  if(NO_OPERATION != (LAYOUT & operations))
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::DoRelayout LAYOUT & operations\n");
-
-    // Some vectors with data needed to layout and reorder may be void
-    // after the first time the text has been laid out.
-    // Fill the vectors again.
-
-    // Calculate the number of glyphs to layout.
-    const Vector<GlyphIndex>& charactersToGlyph        = visualModel->mCharactersToGlyph;
-    const Vector<Length>&     glyphsPerCharacter       = visualModel->mGlyphsPerCharacter;
-    const GlyphIndex* const   charactersToGlyphBuffer  = charactersToGlyph.Begin();
-    const Length* const       glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
-
-    const CharacterIndex lastIndex       = startIndex + ((requestedNumberOfCharacters > 0u) ? requestedNumberOfCharacters - 1u : 0u);
-    const GlyphIndex     startGlyphIndex = textUpdateInfo.mStartGlyphIndex;
-
-    // Make sure the index is not out of bound
-    if(charactersToGlyph.Count() != glyphsPerCharacter.Count() ||
-       requestedNumberOfCharacters > charactersToGlyph.Count() ||
-       (lastIndex > charactersToGlyph.Count() && charactersToGlyph.Count() > 0u))
-    {
-      std::string currentText;
-      impl.GetText(currentText);
-
-      DALI_LOG_ERROR("Controller::DoRelayout: Attempting to access invalid buffer\n");
-      DALI_LOG_ERROR("Current text is: %s\n", currentText.c_str());
-      DALI_LOG_ERROR("startIndex: %u, lastIndex: %u, requestedNumberOfCharacters: %u, charactersToGlyph.Count = %lu, glyphsPerCharacter.Count = %lu\n", startIndex, lastIndex, requestedNumberOfCharacters, charactersToGlyph.Count(), glyphsPerCharacter.Count());
-
-      return false;
-    }
-
-    const Length numberOfGlyphs      = (requestedNumberOfCharacters > 0u) ? *(charactersToGlyphBuffer + lastIndex) + *(glyphsPerCharacterBuffer + lastIndex) - startGlyphIndex : 0u;
-    const Length totalNumberOfGlyphs = visualModel->mGlyphs.Count();
-
-    if(0u == totalNumberOfGlyphs)
-    {
-      if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
-      {
-        visualModel->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;
-    }
-
-    // Set the layout parameters.
-    Layout::Parameters layoutParameters(size, impl.mModel);
-
-    // Resize the vector of positions to have the same size than the vector of glyphs.
-    Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
-    glyphPositions.Resize(totalNumberOfGlyphs);
-
-    // Whether the last character is a new paragraph character.
-    const Character* const textBuffer           = impl.mModel->mLogicalModel->mText.Begin();
-    textUpdateInfo.mIsLastCharacterNewParagraph = TextAbstraction::IsNewParagraph(*(textBuffer + (impl.mModel->mLogicalModel->mText.Count() - 1u)));
-    layoutParameters.isLastNewParagraph         = textUpdateInfo.mIsLastCharacterNewParagraph;
-
-    // The initial glyph and the number of glyphs to layout.
-    layoutParameters.startGlyphIndex        = startGlyphIndex;
-    layoutParameters.numberOfGlyphs         = numberOfGlyphs;
-    layoutParameters.startLineIndex         = textUpdateInfo.mStartLineIndex;
-    layoutParameters.estimatedNumberOfLines = textUpdateInfo.mEstimatedNumberOfLines;
-
-    // Update the ellipsis
-    bool elideTextEnabled = impl.mModel->mElideEnabled;
-    auto ellipsisPosition = impl.mModel->mEllipsisPosition;
-
-    if(NULL != impl.mEventData)
-    {
-      if(impl.mEventData->mPlaceholderEllipsisFlag && impl.IsShowingPlaceholderText())
-      {
-        elideTextEnabled = impl.mEventData->mIsPlaceholderElideEnabled;
-      }
-      else if(EventData::INACTIVE != impl.mEventData->mState)
-      {
-        // Disable ellipsis when editing
-        elideTextEnabled = false;
-      }
-
-      // Reset the scroll position in inactive state
-      if(elideTextEnabled && (impl.mEventData->mState == EventData::INACTIVE))
-      {
-        impl.ResetScrollPosition();
-      }
-    }
-
-    // Update the visual model.
-    bool isAutoScrollEnabled            = impl.mIsAutoScrollEnabled;
-    bool isAutoScrollMaxTextureExceeded = impl.mIsAutoScrollMaxTextureExceeded;
-
-    Size newLayoutSize;
-    viewUpdated               = impl.mLayoutEngine.LayoutText(layoutParameters,
-                                                newLayoutSize,
-                                                elideTextEnabled,
-                                                isAutoScrollEnabled,
-                                                isAutoScrollMaxTextureExceeded,
-                                                ellipsisPosition);
-    impl.mIsAutoScrollEnabled = isAutoScrollEnabled;
-
-    viewUpdated = viewUpdated || (newLayoutSize != layoutSize);
-
-    if(viewUpdated)
-    {
-      layoutSize = newLayoutSize;
-
-      if(NO_OPERATION != (UPDATE_DIRECTION & operations))
-      {
-        impl.mIsTextDirectionRTL = false;
-      }
-
-      if((NO_OPERATION != (UPDATE_DIRECTION & operations)) && !visualModel->mLines.Empty())
-      {
-        impl.mIsTextDirectionRTL = visualModel->mLines[0u].direction;
-      }
-
-      // Sets the layout size.
-      if(NO_OPERATION != (UPDATE_LAYOUT_SIZE & operations))
-      {
-        visualModel->SetLayoutSize(layoutSize);
-      }
-    } // view updated
-  }
-
-  if(NO_OPERATION != (ALIGN & operations))
-  {
-    DoRelayoutHorizontalAlignment(impl, size, startIndex, requestedNumberOfCharacters);
-    viewUpdated = true;
-  }
-#if defined(DEBUG_ENABLED)
-  std::string currentText;
-  impl.GetText(currentText);
-  DALI_LOG_INFO(gLogFilter, Debug::Concise, "Controller::Relayouter::DoRelayout [%p] mImpl->mIsTextDirectionRTL[%s] [%s]\n", &impl, (impl.mIsTextDirectionRTL) ? "true" : "false", currentText.c_str());
-#endif
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::Relayouter::DoRelayout, view updated %s\n", (viewUpdated ? "true" : "false"));
-  return viewUpdated;
-}
-
-void Controller::Relayouter::DoRelayoutHorizontalAlignment(Controller::Impl&    impl,
-                                                           const Size&          size,
-                                                           const CharacterIndex startIndex,
-                                                           const Length         requestedNumberOfCharacters)
-{
-  // The visualModel
-  VisualModelPtr& visualModel = impl.mModel->mVisualModel;
-
-  // The laid-out lines.
-  Vector<LineRun>& lines = visualModel->mLines;
-
-  CharacterIndex alignStartIndex                  = startIndex;
-  Length         alignRequestedNumberOfCharacters = requestedNumberOfCharacters;
-
-  // the whole text needs to be full aligned.
-  // If you do not do a full aligned, only the last line of the multiline input is aligned.
-  if(impl.mEventData && impl.mEventData->mUpdateAlignment)
-  {
-    alignStartIndex                   = 0u;
-    alignRequestedNumberOfCharacters  = impl.mModel->mLogicalModel->mText.Count();
-    impl.mEventData->mUpdateAlignment = false;
-  }
-
-  // If there is no BoundedParagraphRuns then apply the alignment of controller.
-  // Check whether the layout is single line. It's needed to apply one alignment for single-line.
-  // In single-line layout case we need to check whether to follow the alignment of controller or the first BoundedParagraph.
-  // Apply BoundedParagraph's alignment if and only if there is one BoundedParagraph contains all characters. Otherwise follow controller's alignment.
-  const bool isFollowControllerAlignment = ((impl.mModel->GetNumberOfBoundedParagraphRuns() == 0u) ||
-                                            ((Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout()) &&
-                                             (impl.mModel->GetBoundedParagraphRuns()[0].characterRun.numberOfCharacters != impl.mModel->mLogicalModel->mText.Count())));
-
-  if(isFollowControllerAlignment)
-  {
-    // Need to align with the control's size as the text may contain lines
-    // starting either with left to right text or right to left.
-    impl.mLayoutEngine.Align(size,
-                             alignStartIndex,
-                             alignRequestedNumberOfCharacters,
-                             impl.mModel->mHorizontalAlignment,
-                             lines,
-                             impl.mModel->mAlignmentOffset,
-                             impl.mLayoutDirection,
-                             (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
-  }
-  else
-  {
-    //Override the controller horizontal-alignment by horizontal-alignment of bounded paragraph.
-    const Length&                      numberOfBoundedParagraphRuns = impl.mModel->GetNumberOfBoundedParagraphRuns();
-    const Vector<BoundedParagraphRun>& boundedParagraphRuns         = impl.mModel->GetBoundedParagraphRuns();
-    const CharacterIndex               alignEndIndex                = alignStartIndex + alignRequestedNumberOfCharacters - 1u;
-
-    Length alignIndex               = alignStartIndex;
-    Length boundedParagraphRunIndex = 0u;
-
-    while(alignIndex <= alignEndIndex && boundedParagraphRunIndex < numberOfBoundedParagraphRuns)
-    {
-      //BP: BoundedParagraph
-      const BoundedParagraphRun& boundedParagraphRun   = boundedParagraphRuns[boundedParagraphRunIndex];
-      const CharacterIndex&      characterStartIndexBP = boundedParagraphRun.characterRun.characterIndex;
-      const Length&              numberOfCharactersBP  = boundedParagraphRun.characterRun.numberOfCharacters;
-      const CharacterIndex       characterEndIndexBP   = characterStartIndexBP + numberOfCharactersBP - 1u;
-
-      CharacterIndex                  decidedAlignStartIndex         = alignIndex;
-      Length                          decidedAlignNumberOfCharacters = alignEndIndex - alignIndex + 1u;
-      Text::HorizontalAlignment::Type decidedHorizontalAlignment     = impl.mModel->mHorizontalAlignment;
-
-      /*
-         * Shortcuts to explain indexes cases:
-         *
-         * AS: Alignment Start Index
-         * AE: Alignment End Index
-         * PS: Paragraph Start Index
-         * PE: Paragraph End Index
-         * B: BoundedParagraph Alignment
-         * M: Model Alignment
-         *
-         */
-
-      if(alignIndex < characterStartIndexBP && characterStartIndexBP <= alignEndIndex) /// AS.MMMMMM.PS--------AE
-      {
-        // Alignment from "Alignment Start Index" to index before "Paragraph Start Index" according to "Model Alignment"
-        decidedAlignStartIndex         = alignIndex;
-        decidedAlignNumberOfCharacters = characterStartIndexBP - alignIndex;
-        decidedHorizontalAlignment     = impl.mModel->mHorizontalAlignment;
-
-        // Need to re-heck the case of current bounded paragraph
-        alignIndex = characterStartIndexBP; // Shift AS to be PS
-      }
-      else if((characterStartIndexBP <= alignIndex && alignIndex <= characterEndIndexBP) ||     /// ---PS.BBBBBBB.AS.BBBBBBB.PE---
-              (characterStartIndexBP <= alignEndIndex && alignEndIndex <= characterEndIndexBP)) /// ---PS.BBBBBB.AE.BBBBBBB.PE---
-      {
-        // Alignment from "Paragraph Start Index" to "Paragraph End Index" according to "BoundedParagraph Alignment"
-        decidedAlignStartIndex         = characterStartIndexBP;
-        decidedAlignNumberOfCharacters = numberOfCharactersBP;
-        decidedHorizontalAlignment     = boundedParagraphRun.horizontalAlignmentDefined ? boundedParagraphRun.horizontalAlignment : impl.mModel->mHorizontalAlignment;
-
-        alignIndex = characterEndIndexBP + 1u; // Shift AS to be after PE direct
-        boundedParagraphRunIndex++;            // Align then check the case of next bounded paragraph
-      }
-      else
-      {
-        boundedParagraphRunIndex++; // Check the case of next bounded paragraph
-        continue;
-      }
-
-      impl.mLayoutEngine.Align(size,
-                               decidedAlignStartIndex,
-                               decidedAlignNumberOfCharacters,
-                               decidedHorizontalAlignment,
-                               lines,
-                               impl.mModel->mAlignmentOffset,
-                               impl.mLayoutDirection,
-                               (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
-    }
-
-    //Align the remaining that is not aligned
-    if(alignIndex <= alignEndIndex)
-    {
-      impl.mLayoutEngine.Align(size,
-                               alignIndex,
-                               (alignEndIndex - alignIndex + 1u),
-                               impl.mModel->mHorizontalAlignment,
-                               lines,
-                               impl.mModel->mAlignmentOffset,
-                               impl.mLayoutDirection,
-                               (impl.mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS));
-    }
-  }
-}
-
-void Controller::Relayouter::CalculateVerticalOffset(Controller::Impl& impl, const Size& controlSize)
-{
-  ModelPtr&       model                 = impl.mModel;
-  VisualModelPtr& visualModel           = model->mVisualModel;
-  Size            layoutSize            = model->mVisualModel->GetLayoutSize();
-  Size            oldLayoutSize         = layoutSize;
-  float           offsetY               = 0.f;
-  bool            needRecalc            = false;
-  float           defaultFontLineHeight = impl.GetDefaultFontLineHeight();
-
-  if(fabsf(layoutSize.height) < Math::MACHINE_EPSILON_1000)
-  {
-    // Get the line height of the default font.
-    layoutSize.height = defaultFontLineHeight;
-  }
-
-  // Whether the text control is editable
-  const bool isEditable = NULL != impl.mEventData;
-  if(isEditable && layoutSize.height != defaultFontLineHeight && impl.IsShowingPlaceholderText())
-  {
-    // This code prevents the wrong positioning of cursor when the layout size is bigger/smaller than defaultFontLineHeight.
-    // This situation occurs when the size of placeholder text is different from the default text.
-    layoutSize.height = defaultFontLineHeight;
-    needRecalc        = true;
-  }
-
-  switch(model->mVerticalAlignment)
-  {
-    case VerticalAlignment::TOP:
-    {
-      model->mScrollPosition.y = 0.f;
-      offsetY                  = 0.f;
-      break;
-    }
-    case VerticalAlignment::CENTER:
-    {
-      model->mScrollPosition.y = floorf(0.5f * (controlSize.height - layoutSize.height)); // try to avoid pixel alignment.
-      if(needRecalc) offsetY = floorf(0.5f * (layoutSize.height - oldLayoutSize.height));
-      break;
-    }
-    case VerticalAlignment::BOTTOM:
-    {
-      model->mScrollPosition.y = controlSize.height - layoutSize.height;
-      if(needRecalc) offsetY = layoutSize.height - oldLayoutSize.height;
-      break;
-    }
-  }
-
-  if(needRecalc)
-  {
-    // Update glyphPositions according to recalculation.
-    const Length     positionCount  = visualModel->mGlyphPositions.Count();
-    Vector<Vector2>& glyphPositions = visualModel->mGlyphPositions;
-    for(Length index = 0u; index < positionCount; index++)
-    {
-      glyphPositions[index].y += offsetY;
-    }
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-relayouter.h b/dali-toolkit/internal/text/text-controller-relayouter.h
deleted file mode 100644 (file)
index a98ed53..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/actors/actor-enumerations.h>
-#include <dali/public-api/math/vector2.h>
-#include <dali/public-api/math/vector3.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-/**
- * Contains all the relayouting related methods for Text::Controller
- */
-struct Controller::Relayouter
-{
-  /**
-   * @brief Called by the Controller to retrieve the natural size.
-   *
-   * @param[in] controller A reference to the controller class
-   * @return
-   */
-  static Vector3 GetNaturalSize(Controller& controller);
-
-  /**
-   * @brief Called by the Controller to check if the text fits.
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] pointSize The point size
-   * @param[in] layoutSize The layout size
-   * @return
-   */
-  static bool CheckForTextFit(Controller& controller, float pointSize, const Size& layoutSize);
-
-  /**
-   * @brief Calculates the point size for text for given layout()
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] layoutSize The layout size
-   */
-  static void FitPointSizeforLayout(Controller& controller, const Size& layoutSize);
-
-  /**
-   * @brief Called by the Controller to get the height for a particular width.
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] width The width we want the height for
-   * @return
-   */
-  static float GetHeightForWidth(Controller& controller, float width);
-
-  /**
-   * @brief Called by the Controller to do the relayout itself.
-   *
-   * @param[in] controller A reference to the controller class
-   * @param[in] size The size to set
-   * @param[in] layoutDirection The layout direction
-   * @return
-   */
-  static Controller::UpdateTextType Relayout(Controller& controller, const Size& size, Dali::LayoutDirection::Type layoutDirection);
-
-  /**
-   * @brief Called by the Controller to do certain operations when relayouting.
-   *
-   * @param[in] impl A reference to the controller impl class
-   * @param[in] size The size to set
-   * @param[in] operationsRequired The operations we need to do
-   * @param[in/out] layoutSize The Layout size which can be updated depending on the result of the performed operations
-   * @return
-   */
-
-  static bool DoRelayout(Controller::Impl& impl, const Size& size, OperationsMask operationsRequired, Size& layoutSize);
-
-  /**
-   * @brief Called by the Controller to calculate the veritcal offset give the control size.
-   *
-   * @param[in] impl A reference to the controller impl class
-   * @param[in] controlSize The control size
-   */
-  static void CalculateVerticalOffset(Controller::Impl& impl, const Size& controlSize);
-
-  /**
-  * @brief Calculates the layout size of control according to @p requestedControllerSize and @p requestedOperationsMask
-  *
-  * GetNaturalSize() and GetHeightForWidth() calls this method.
-  *
-  * @param[in] controller The controller to calcualte size on it.
-  * @param[in] requestedControllerSize The requested size of controller to calcualte layout size on it.
-  * @param[in] requestedOperationsMask The requested operations-mask to calcualte layout size according to it.
-  *
-  * @return The calculated layout-size.
-  */
-  static Size CalculateLayoutSizeOnRequiredControllerSize(Controller& controller, const Size& requestedControllerSize, const OperationsMask& requestedOperationsMask);
-
-private:
-  /**
-   * @brief Called by the DoRelayout to do HorizontalAlignment operation when relayouting.
-   *
-   * @param[in] impl A reference to the controller impl class
-   * @param[in] size The size to set
-   * @param[in] startIndex The start index for relayouting
-   * @param[in] requestedNumberOfCharacters The number Of characters for relayouting
-   */
-
-  static void DoRelayoutHorizontalAlignment(Controller::Impl& impl, const Size& size, const CharacterIndex startIndex, const Length requestedNumberOfCharacters);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_RELAYOUTER_H
diff --git a/dali-toolkit/internal/text/text-controller-text-updater.cpp b/dali-toolkit/internal/text/text-controller-text-updater.cpp
deleted file mode 100644 (file)
index 4d0ba8f..0000000
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller-text-updater.h>
-
-// EXTERNAL INCLUDES
-#include <dali/integration-api/debug.h>
-#include <memory.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/character-set-conversion.h>
-#include <dali-toolkit/internal/text/characters-helper-functions.h>
-#include <dali-toolkit/internal/text/emoji-helper.h>
-#include <dali-toolkit/internal/text/markup-processor.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-void Controller::TextUpdater::SetText(Controller& controller, const std::string& text)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText\n");
-
-  Controller::Impl& impl = *controller.mImpl;
-
-  // Reset keyboard as text changed
-  impl.ResetInputMethodContext();
-
-  // Remove the previously set text and style.
-  ResetText(controller);
-
-  // Remove the style.
-  impl.ClearStyleData();
-
-  CharacterIndex lastCursorIndex = 0u;
-
-  EventData*& eventData = impl.mEventData;
-
-  if(nullptr != eventData)
-  {
-    // If popup shown then hide it by switching to Editing state
-    if((EventData::SELECTING == eventData->mState) ||
-       (EventData::EDITING_WITH_POPUP == eventData->mState) ||
-       (EventData::EDITING_WITH_GRAB_HANDLE == eventData->mState) ||
-       (EventData::EDITING_WITH_PASTE_POPUP == eventData->mState))
-    {
-      if((impl.mSelectableControlInterface != nullptr) && (EventData::SELECTING == eventData->mState))
-      {
-        impl.mSelectableControlInterface->SelectionChanged(eventData->mLeftSelectionPosition, eventData->mRightSelectionPosition, eventData->mPrimaryCursorPosition, eventData->mPrimaryCursorPosition);
-      }
-
-      impl.ChangeState(EventData::EDITING);
-    }
-  }
-
-  if(!text.empty())
-  {
-    ModelPtr&        model        = impl.mModel;
-    LogicalModelPtr& logicalModel = model->mLogicalModel;
-    model->mVisualModel->SetTextColor(impl.mTextColor);
-
-    MarkupProcessData markupProcessData(logicalModel->mColorRuns,
-                                        logicalModel->mFontDescriptionRuns,
-                                        logicalModel->mEmbeddedItems,
-                                        logicalModel->mAnchors,
-                                        logicalModel->mUnderlinedCharacterRuns,
-                                        logicalModel->mBackgroundColorRuns,
-                                        logicalModel->mStrikethroughCharacterRuns,
-                                        logicalModel->mBoundedParagraphRuns,
-                                        logicalModel->mCharacterSpacingCharacterRuns);
-
-    Length         textSize = 0u;
-    const uint8_t* utf8     = NULL;
-    if(impl.mMarkupProcessorEnabled)
-    {
-      ProcessMarkupString(text, markupProcessData);
-      textSize = markupProcessData.markupProcessedText.size();
-
-      // This is a bit horrible but std::string returns a (signed) char*
-      utf8 = reinterpret_cast<const uint8_t*>(markupProcessData.markupProcessedText.c_str());
-    }
-    else
-    {
-      textSize = text.size();
-
-      // This is a bit horrible but std::string returns a (signed) char*
-      utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
-    }
-
-    //  Convert text into UTF-32
-    Vector<Character>& utf32Characters = logicalModel->mText;
-    utf32Characters.Resize(textSize);
-
-    // Transform a text array encoded in utf8 into an array encoded in utf32.
-    // It returns the actual number of characters.
-    Length characterCount = Utf8ToUtf32(utf8, textSize, utf32Characters.Begin());
-    utf32Characters.Resize(characterCount);
-
-    DALI_ASSERT_DEBUG(textSize >= characterCount && "Invalid UTF32 conversion length");
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", &controller, textSize, logicalModel->mText.Count());
-
-    // The characters to be added.
-    impl.mTextUpdateInfo.mNumberOfCharactersToAdd = logicalModel->mText.Count();
-
-    // To reset the cursor position
-    lastCursorIndex = characterCount;
-
-    // Update the rest of the model during size negotiation
-    impl.QueueModifyEvent(ModifyEvent::TEXT_REPLACED);
-
-    // The natural size needs to be re-calculated.
-    impl.mRecalculateNaturalSize = true;
-
-    // The text direction needs to be updated.
-    impl.mUpdateTextDirection = true;
-
-    // Apply modifications to the model
-    impl.mOperationsPending = ALL_OPERATIONS;
-  }
-  else
-  {
-    PlaceholderHandler::ShowPlaceholderText(impl);
-  }
-
-  unsigned int oldCursorPos = (nullptr != eventData ? eventData->mPrimaryCursorPosition : 0);
-
-  // Resets the cursor position.
-  controller.ResetCursorPosition(lastCursorIndex);
-
-  // Scrolls the text to make the cursor visible.
-  impl.ResetScrollPosition();
-
-  impl.RequestRelayout();
-
-  if(nullptr != eventData)
-  {
-    // Cancel previously queued events
-    eventData->mEventQueue.clear();
-  }
-
-  // Do this last since it provides callbacks into application code.
-  if(NULL != impl.mEditableControlInterface)
-  {
-    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, lastCursorIndex);
-    impl.mEditableControlInterface->TextChanged(true);
-  }
-}
-
-void Controller::TextUpdater::InsertText(Controller& controller, const std::string& text, Controller::InsertType type)
-{
-  Controller::Impl& impl      = *controller.mImpl;
-  EventData*&       eventData = impl.mEventData;
-
-  DALI_ASSERT_DEBUG(nullptr != eventData && "Unexpected InsertText")
-
-  if(NULL == eventData)
-  {
-    return;
-  }
-
-  bool         removedPrevious  = false;
-  bool         removedSelected  = false;
-  bool         maxLengthReached = false;
-  unsigned int oldCursorPos     = eventData->mPrimaryCursorPosition;
-
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::InsertText %p %s (%s) mPrimaryCursorPosition %d mPreEditFlag %d mPreEditStartPosition %d mPreEditLength %d\n", &controller, text.c_str(), (COMMIT == type ? "COMMIT" : "PRE_EDIT"), eventData->mPrimaryCursorPosition, eventData->mPreEditFlag, eventData->mPreEditStartPosition, eventData->mPreEditLength);
-
-  ModelPtr&        model        = impl.mModel;
-  LogicalModelPtr& logicalModel = model->mLogicalModel;
-
-  // TODO: At the moment the underline runs are only for pre-edit.
-  model->mVisualModel->mUnderlineRuns.Clear();
-
-  // Remove the previous InputMethodContext pre-edit.
-  if(eventData->mPreEditFlag && (0u != eventData->mPreEditLength))
-  {
-    removedPrevious = RemoveText(controller,
-                                 -static_cast<int>(eventData->mPrimaryCursorPosition - eventData->mPreEditStartPosition),
-                                 eventData->mPreEditLength,
-                                 DONT_UPDATE_INPUT_STYLE);
-
-    eventData->mPrimaryCursorPosition = eventData->mPreEditStartPosition;
-    eventData->mPreEditLength         = 0u;
-  }
-  else
-  {
-    // Remove the previous Selection.
-    removedSelected = RemoveSelectedText(controller);
-  }
-
-  Vector<Character> utf32Characters;
-  Length            characterCount = 0u;
-
-  if(!text.empty())
-  {
-    //  Convert text into UTF-32
-    utf32Characters.Resize(text.size());
-
-    // This is a bit horrible but std::string returns a (signed) char*
-    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(text.c_str());
-
-    // Transform a text array encoded in utf8 into an array encoded in utf32.
-    // It returns the actual number of characters.
-    characterCount = Utf8ToUtf32(utf8, text.size(), utf32Characters.Begin());
-    utf32Characters.Resize(characterCount);
-
-    DALI_ASSERT_DEBUG(text.size() >= utf32Characters.Count() && "Invalid UTF32 conversion length");
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count());
-  }
-
-  if(0u != utf32Characters.Count()) // Check if Utf8ToUtf32 conversion succeeded
-  {
-    // The placeholder text is no longer needed
-    if(impl.IsShowingPlaceholderText())
-    {
-      ResetText(controller);
-    }
-
-    impl.ChangeState(EventData::EDITING);
-
-    // Handle the InputMethodContext (predicitive text) state changes
-    if(COMMIT == type)
-    {
-      // InputMethodContext is no longer handling key-events
-      impl.ClearPreEditFlag();
-    }
-    else // PRE_EDIT
-    {
-      if(!eventData->mPreEditFlag)
-      {
-        DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Entered PreEdit state\n");
-
-        // Record the start of the pre-edit text
-        eventData->mPreEditStartPosition = eventData->mPrimaryCursorPosition;
-      }
-
-      eventData->mPreEditLength = utf32Characters.Count();
-      eventData->mPreEditFlag   = true;
-
-      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "mPreEditStartPosition %d mPreEditLength %d\n", eventData->mPreEditStartPosition, eventData->mPreEditLength);
-    }
-
-    const Length numberOfCharactersInModel = logicalModel->mText.Count();
-
-    // Restrict new text to fit within Maximum characters setting.
-    Length temp_length      = (impl.mMaximumNumberOfCharacters > numberOfCharactersInModel ? impl.mMaximumNumberOfCharacters - numberOfCharactersInModel : 0);
-    Length maxSizeOfNewText = std::min(temp_length, characterCount);
-    maxLengthReached        = (characterCount > maxSizeOfNewText);
-
-    // The cursor position.
-    CharacterIndex& cursorIndex = eventData->mPrimaryCursorPosition;
-
-    // Update the text's style.
-
-    // Updates the text style runs by adding characters.
-    logicalModel->UpdateTextStyleRuns(cursorIndex, maxSizeOfNewText);
-
-    // Get the character index from the cursor index.
-    const CharacterIndex styleIndex = (cursorIndex > 0u) ? cursorIndex - 1u : 0u;
-
-    // Retrieve the text's style for the given index.
-    InputStyle style;
-    impl.RetrieveDefaultInputStyle(style);
-    logicalModel->RetrieveStyle(styleIndex, style);
-
-    InputStyle& inputStyle = eventData->mInputStyle;
-
-    // Whether to add a new text color run.
-    const bool addColorRun = (style.textColor != inputStyle.textColor) && !inputStyle.isDefaultColor;
-
-    // Whether to add a new font run.
-    const bool addFontNameRun   = (style.familyName != inputStyle.familyName) && inputStyle.isFamilyDefined;
-    const bool addFontWeightRun = (style.weight != inputStyle.weight) && inputStyle.isWeightDefined;
-    const bool addFontWidthRun  = (style.width != inputStyle.width) && inputStyle.isWidthDefined;
-    const bool addFontSlantRun  = (style.slant != inputStyle.slant) && inputStyle.isSlantDefined;
-    const bool addFontSizeRun   = (style.size != inputStyle.size) && inputStyle.isSizeDefined;
-
-    // Add style runs.
-    if(addColorRun)
-    {
-      const VectorBase::SizeType numberOfRuns = logicalModel->mColorRuns.Count();
-      logicalModel->mColorRuns.Resize(numberOfRuns + 1u);
-
-      ColorRun& colorRun                       = *(logicalModel->mColorRuns.Begin() + numberOfRuns);
-      colorRun.color                           = inputStyle.textColor;
-      colorRun.characterRun.characterIndex     = cursorIndex;
-      colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
-    }
-
-    if(addFontNameRun ||
-       addFontWeightRun ||
-       addFontWidthRun ||
-       addFontSlantRun ||
-       addFontSizeRun)
-    {
-      const VectorBase::SizeType numberOfRuns = logicalModel->mFontDescriptionRuns.Count();
-      logicalModel->mFontDescriptionRuns.Resize(numberOfRuns + 1u);
-
-      FontDescriptionRun& fontDescriptionRun = *(logicalModel->mFontDescriptionRuns.Begin() + numberOfRuns);
-
-      if(addFontNameRun)
-      {
-        fontDescriptionRun.familyLength = inputStyle.familyName.size();
-        fontDescriptionRun.familyName   = new char[fontDescriptionRun.familyLength];
-        memcpy(fontDescriptionRun.familyName, inputStyle.familyName.c_str(), fontDescriptionRun.familyLength);
-        fontDescriptionRun.familyDefined = true;
-
-        // The memory allocated for the font family name is freed when the font description is removed from the logical model.
-      }
-
-      if(addFontWeightRun)
-      {
-        fontDescriptionRun.weight        = inputStyle.weight;
-        fontDescriptionRun.weightDefined = true;
-      }
-
-      if(addFontWidthRun)
-      {
-        fontDescriptionRun.width        = inputStyle.width;
-        fontDescriptionRun.widthDefined = true;
-      }
-
-      if(addFontSlantRun)
-      {
-        fontDescriptionRun.slant        = inputStyle.slant;
-        fontDescriptionRun.slantDefined = true;
-      }
-
-      if(addFontSizeRun)
-      {
-        fontDescriptionRun.size        = static_cast<PointSize26Dot6>(inputStyle.size * impl.GetFontSizeScale() * 64.f);
-        fontDescriptionRun.sizeDefined = true;
-      }
-
-      fontDescriptionRun.characterRun.characterIndex     = cursorIndex;
-      fontDescriptionRun.characterRun.numberOfCharacters = maxSizeOfNewText;
-    }
-
-    // Insert at current cursor position.
-    Vector<Character>& modifyText = logicalModel->mText;
-
-    auto pos = modifyText.End();
-    if(cursorIndex < numberOfCharactersInModel)
-    {
-      pos = modifyText.Begin() + cursorIndex;
-    }
-    unsigned int realPos = pos - modifyText.Begin();
-    modifyText.Insert(pos, utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText);
-
-    if(NULL != impl.mEditableControlInterface)
-    {
-      impl.mEditableControlInterface->TextInserted(realPos, maxSizeOfNewText, text);
-    }
-
-    TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
-
-    // Mark the first paragraph to be updated.
-    if(Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout())
-    {
-      textUpdateInfo.mCharacterIndex             = 0;
-      textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
-      textUpdateInfo.mNumberOfCharactersToAdd    = numberOfCharactersInModel + maxSizeOfNewText;
-      textUpdateInfo.mClearAll                   = true;
-    }
-    else
-    {
-      textUpdateInfo.mCharacterIndex = std::min(cursorIndex, textUpdateInfo.mCharacterIndex);
-      textUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
-    }
-
-    if(impl.mMarkupProcessorEnabled)
-    {
-      InsertTextAnchor(controller, maxSizeOfNewText, cursorIndex);
-    }
-
-    // Update the cursor index.
-    cursorIndex += maxSizeOfNewText;
-
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition);
-  }
-
-  if((0u == logicalModel->mText.Count()) &&
-     impl.IsPlaceholderAvailable())
-  {
-    // Show place-holder if empty after removing the pre-edit text
-    PlaceholderHandler::ShowPlaceholderText(impl);
-    eventData->mUpdateCursorPosition = true;
-    impl.ClearPreEditFlag();
-  }
-  else if(removedPrevious ||
-          removedSelected ||
-          (0 != utf32Characters.Count()))
-  {
-    // Queue an inserted event
-    impl.QueueModifyEvent(ModifyEvent::TEXT_INSERTED);
-
-    eventData->mUpdateCursorPosition = true;
-    if(removedSelected)
-    {
-      eventData->mScrollAfterDelete = true;
-    }
-    else
-    {
-      eventData->mScrollAfterUpdatePosition = true;
-    }
-  }
-
-  if(nullptr != impl.mEditableControlInterface)
-  {
-    impl.mEditableControlInterface->CursorPositionChanged(oldCursorPos, eventData->mPrimaryCursorPosition);
-  }
-
-  if(maxLengthReached)
-  {
-    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", logicalModel->mText.Count());
-
-    impl.ResetInputMethodContext();
-
-    if(NULL != impl.mEditableControlInterface)
-    {
-      // Do this last since it provides callbacks into application code
-      impl.mEditableControlInterface->MaxLengthReached();
-    }
-  }
-}
-
-void Controller::TextUpdater::PasteText(Controller& controller, const std::string& stringToPaste)
-{
-  InsertText(controller, stringToPaste, Text::Controller::COMMIT);
-  Controller::Impl& impl = *controller.mImpl;
-  impl.ChangeState(EventData::EDITING);
-  impl.RequestRelayout();
-
-  if(NULL != impl.mEditableControlInterface)
-  {
-    // Do this last since it provides callbacks into application code
-    impl.mEditableControlInterface->TextChanged(true);
-  }
-}
-
-bool Controller::TextUpdater::RemoveText(
-  Controller&          controller,
-  int                  cursorOffset,
-  int                  numberOfCharacters,
-  UpdateInputStyleType type)
-{
-  bool removed = false;
-  bool removeAll = false;
-
-  Controller::Impl& impl      = *controller.mImpl;
-  EventData*&       eventData = impl.mEventData;
-
-  if(nullptr == eventData)
-  {
-    return removed;
-  }
-
-  ModelPtr&        model        = impl.mModel;
-  LogicalModelPtr& logicalModel = model->mLogicalModel;
-  VisualModelPtr&  visualModel  = model->mVisualModel;
-
-  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n", &controller, logicalModel->mText.Count(), eventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters);
-
-  if(!impl.IsShowingPlaceholderText())
-  {
-    // Delete at current cursor position
-    Vector<Character>& currentText         = logicalModel->mText;
-    CharacterIndex&    previousCursorIndex = eventData->mPrimaryCursorPosition;
-
-    CharacterIndex cursorIndex = 0;
-
-    // Validate the cursor position & number of characters
-    if((static_cast<int>(eventData->mPrimaryCursorPosition) + cursorOffset) >= 0)
-    {
-      cursorIndex = eventData->mPrimaryCursorPosition + cursorOffset;
-    }
-
-    //Handle Emoji clustering for cursor handling
-    // Deletion case: this is handling the deletion cases when the cursor is before or after Emoji
-    //  - Before: when use delete key and cursor is before Emoji (cursorOffset = -1)
-    //  - After: when use backspace key and cursor is after Emoji (cursorOffset = 0)
-
-    const Script script = logicalModel->GetScript(cursorIndex);
-    if((numberOfCharacters == 1u) &&
-       (IsOneOfEmojiScripts(script)))
-    {
-      //TODO: Use this clustering for Emoji cases only. This needs more testing to generalize to all scripts.
-      CharacterRun emojiClusteredCharacters = RetrieveClusteredCharactersOfCharacterIndex(visualModel, logicalModel, cursorIndex);
-      Length       actualNumberOfCharacters = emojiClusteredCharacters.numberOfCharacters;
-
-      //Set cursorIndex at the first characterIndex of clustred Emoji
-      cursorIndex = emojiClusteredCharacters.characterIndex;
-
-      numberOfCharacters = actualNumberOfCharacters;
-    }
-
-    if((cursorIndex + numberOfCharacters) > currentText.Count())
-    {
-      numberOfCharacters = currentText.Count() - cursorIndex;
-    }
-
-    if((cursorIndex == 0) && (currentText.Count() - numberOfCharacters == 0))
-    {
-      removeAll = true;
-    }
-
-    TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
-
-    if(eventData->mPreEditFlag || removeAll || // If the preedit flag is enabled, it means two (or more) of them came together i.e. when two keys have been pressed at the same time.
-       ((cursorIndex + numberOfCharacters) <= textUpdateInfo.mPreviousNumberOfCharacters))
-    {
-      // Mark the paragraphs to be updated.
-      if(Layout::Engine::SINGLE_LINE_BOX == impl.mLayoutEngine.GetLayout())
-      {
-        textUpdateInfo.mCharacterIndex             = 0;
-        textUpdateInfo.mNumberOfCharactersToRemove = textUpdateInfo.mPreviousNumberOfCharacters;
-        textUpdateInfo.mNumberOfCharactersToAdd    = textUpdateInfo.mPreviousNumberOfCharacters - numberOfCharacters;
-        textUpdateInfo.mClearAll                   = true;
-      }
-      else
-      {
-        textUpdateInfo.mCharacterIndex = std::min(cursorIndex, textUpdateInfo.mCharacterIndex);
-        textUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
-      }
-
-      // Update the input style and remove the text's style before removing the text.
-
-      if(UPDATE_INPUT_STYLE == type)
-      {
-        InputStyle& eventDataInputStyle = eventData->mInputStyle;
-
-        // Keep a copy of the current input style.
-        InputStyle currentInputStyle;
-        currentInputStyle.Copy(eventDataInputStyle);
-
-        // Set first the default input style.
-        impl.RetrieveDefaultInputStyle(eventDataInputStyle);
-
-        // Update the input style.
-        logicalModel->RetrieveStyle(cursorIndex, eventDataInputStyle);
-
-        // Compare if the input style has changed.
-        const bool hasInputStyleChanged = !currentInputStyle.Equal(eventDataInputStyle);
-
-        if(hasInputStyleChanged)
-        {
-          const InputStyle::Mask styleChangedMask = currentInputStyle.GetInputStyleChangeMask(eventDataInputStyle);
-          // Queue the input style changed signal.
-          eventData->mInputStyleChangedQueue.PushBack(styleChangedMask);
-        }
-      }
-
-      // If the number of current text and the number of characters to be deleted are same,
-      // it means all texts should be removed and all Preedit variables should be initialized.
-      if(removeAll)
-      {
-        impl.ClearPreEditFlag();
-        textUpdateInfo.mNumberOfCharactersToAdd = 0;
-      }
-
-      // Updates the text style runs by removing characters. Runs with no characters are removed.
-      logicalModel->UpdateTextStyleRuns(cursorIndex, -numberOfCharacters);
-
-      // Remove the characters.
-      Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
-      Vector<Character>::Iterator last  = first + numberOfCharacters;
-
-      if(NULL != impl.mEditableControlInterface)
-      {
-        std::string utf8;
-        Utf32ToUtf8(first, numberOfCharacters, utf8);
-        impl.mEditableControlInterface->TextDeleted(cursorIndex, numberOfCharacters, utf8);
-      }
-
-      currentText.Erase(first, last);
-
-      if(impl.mMarkupProcessorEnabled)
-      {
-        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
-      }
-
-      if(nullptr != impl.mEditableControlInterface)
-      {
-        impl.mEditableControlInterface->CursorPositionChanged(previousCursorIndex, cursorIndex);
-      }
-
-      // Cursor position retreat
-      previousCursorIndex = cursorIndex;
-
-      eventData->mScrollAfterDelete = true;
-
-      if(EventData::INACTIVE == eventData->mState)
-      {
-        impl.ChangeState(EventData::EDITING);
-      }
-
-      DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", &controller, numberOfCharacters);
-      removeAll = false;
-      removed = true;
-    }
-  }
-
-  return removed;
-}
-
-bool Controller::TextUpdater::RemoveSelectedText(Controller& controller)
-{
-  bool textRemoved(false);
-
-  Controller::Impl& impl = *controller.mImpl;
-
-  if(EventData::SELECTING == impl.mEventData->mState)
-  {
-    std::string removedString;
-    uint32_t    oldSelStart = impl.mEventData->mLeftSelectionPosition;
-    uint32_t    oldSelEnd   = impl.mEventData->mRightSelectionPosition;
-
-    impl.RetrieveSelection(removedString, true);
-
-    if(!removedString.empty())
-    {
-      textRemoved = true;
-      impl.ChangeState(EventData::EDITING);
-
-      if(impl.mMarkupProcessorEnabled)
-      {
-        int             cursorOffset        = -1;
-        int             numberOfCharacters  = removedString.length();
-        CharacterIndex& cursorIndex         = impl.mEventData->mPrimaryCursorPosition;
-        CharacterIndex  previousCursorIndex = cursorIndex + numberOfCharacters;
-
-        RemoveTextAnchor(controller, cursorOffset, numberOfCharacters, previousCursorIndex);
-      }
-
-      if(impl.mSelectableControlInterface != nullptr)
-      {
-        impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, impl.mEventData->mPrimaryCursorPosition, impl.mEventData->mPrimaryCursorPosition);
-      }
-    }
-  }
-
-  return textRemoved;
-}
-
-void Controller::TextUpdater::ResetText(Controller& controller)
-{
-  Controller::Impl& impl         = *controller.mImpl;
-  LogicalModelPtr&  logicalModel = impl.mModel->mLogicalModel;
-
-  // Reset buffers.
-  logicalModel->mText.Clear();
-
-  // Reset the embedded images buffer.
-  logicalModel->ClearEmbeddedImages();
-
-  // Reset the anchors buffer.
-  logicalModel->ClearAnchors();
-
-  // We have cleared everything including the placeholder-text
-  impl.PlaceholderCleared();
-
-  impl.mTextUpdateInfo.mCharacterIndex             = 0u;
-  impl.mTextUpdateInfo.mNumberOfCharactersToRemove = impl.mTextUpdateInfo.mPreviousNumberOfCharacters;
-  impl.mTextUpdateInfo.mNumberOfCharactersToAdd    = 0u;
-
-  // Clear any previous text.
-  impl.mTextUpdateInfo.mClearAll = true;
-
-  // The natural size needs to be re-calculated.
-  impl.mRecalculateNaturalSize = true;
-
-  // The text direction needs to be updated.
-  impl.mUpdateTextDirection = true;
-
-  // Apply modifications to the model
-  impl.mOperationsPending = ALL_OPERATIONS;
-}
-
-void Controller::TextUpdater::InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex)
-{
-  Controller::Impl& impl         = *controller.mImpl;
-  ModelPtr&         model        = impl.mModel;
-  LogicalModelPtr&  logicalModel = model->mLogicalModel;
-
-  for(auto& anchor : logicalModel->mAnchors)
-  {
-    if(anchor.endIndex < previousCursorIndex) //      [anchor]  CUR
-    {
-      continue;
-    }
-    if(anchor.startIndex < previousCursorIndex) //      [anCURr]
-    {
-      anchor.endIndex += numberOfCharacters;
-    }
-    else // CUR  [anchor]
-    {
-      anchor.startIndex += numberOfCharacters;
-      anchor.endIndex += numberOfCharacters;
-    }
-    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::InsertTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
-  }
-}
-
-void Controller::TextUpdater::RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
-{
-  Controller::Impl&        impl         = *controller.mImpl;
-  ModelPtr&                model        = impl.mModel;
-  LogicalModelPtr&         logicalModel = model->mLogicalModel;
-  Vector<Anchor>::Iterator it           = logicalModel->mAnchors.Begin();
-
-  while(it != logicalModel->mAnchors.End())
-  {
-    Anchor& anchor = *it;
-
-    if(anchor.endIndex <= previousCursorIndex && cursorOffset == 0) // [anchor]    CUR >>
-    {
-      // Nothing happens.
-    }
-    else if(anchor.endIndex <= previousCursorIndex && cursorOffset == -1) // [anchor] << CUR
-    {
-      int endIndex = anchor.endIndex;
-      int offset   = previousCursorIndex - endIndex;
-      int index    = endIndex - (numberOfCharacters - offset);
-
-      if(index < endIndex)
-      {
-        endIndex = index;
-      }
-
-      if((int)anchor.startIndex >= endIndex)
-      {
-        if(anchor.href)
-        {
-          delete[] anchor.href;
-        }
-        it = logicalModel->mAnchors.Erase(it);
-        continue;
-      }
-      else
-      {
-        anchor.endIndex = endIndex;
-      }
-    }
-    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == -1) // << CUR    [anchor]
-    {
-      anchor.startIndex -= numberOfCharacters;
-      anchor.endIndex -= numberOfCharacters;
-    }
-    else if(anchor.startIndex >= previousCursorIndex && cursorOffset == 0) //    CUR >> [anchor]
-    {
-      int startIndex = anchor.startIndex;
-      int endIndex   = anchor.endIndex;
-      int index      = previousCursorIndex + numberOfCharacters - 1;
-
-      if(startIndex > index)
-      {
-        anchor.startIndex -= numberOfCharacters;
-        anchor.endIndex -= numberOfCharacters;
-      }
-      else if(endIndex > index + 1)
-      {
-        anchor.endIndex -= numberOfCharacters;
-      }
-      else
-      {
-        if(anchor.href)
-        {
-          delete[] anchor.href;
-        }
-        it = logicalModel->mAnchors.Erase(it);
-        continue;
-      }
-    }
-    else if(cursorOffset == -1) // [<< CUR]
-    {
-      int startIndex = anchor.startIndex;
-      int index      = previousCursorIndex - numberOfCharacters;
-
-      if(startIndex >= index)
-      {
-        anchor.startIndex = index;
-      }
-      anchor.endIndex -= numberOfCharacters;
-    }
-    else if(cursorOffset == 0) // [CUR >>]
-    {
-      anchor.endIndex -= numberOfCharacters;
-    }
-    else
-    {
-      // When this condition is reached, someting is wrong.
-      DALI_LOG_ERROR("Controller::RemoveTextAnchor[%p] Invaild state cursorOffset[%d]\n", &controller, cursorOffset);
-    }
-
-    DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::RemoveTextAnchor[%p] Anchor[%s] start[%d] end[%d]\n", &controller, anchor.href, anchor.startIndex, anchor.endIndex);
-
-    it++;
-  }
-}
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/text/text-controller-text-updater.h b/dali-toolkit/internal/text/text-controller-text-updater.h
deleted file mode 100644 (file)
index 1070966..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_UPDATER_H
-#define DALI_TOOLKIT_TEXT_UPDATER_H
-
-/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
-{
-/**
- * @brief Methods that update the text
- */
-struct Controller::TextUpdater
-{
-  /// @copydoc Text::Contoller::SetText
-  /// @param[in] controller The controller
-  static void SetText(Controller& controller, const std::string& text);
-
-  /**
-   * @brief Called by editable UI controls when key events are received.
-   *
-   * @param[in] controller The controller
-   * @param[in] text The text to insert.
-   * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
-   */
-  static void InsertText(Controller& controller, const std::string& text, Controller::InsertType type);
-
-  /// @copydoc Text::EditableControlInterface::PasteText()
-  /// @param[in] controller The controller
-  static void PasteText(Controller& controller, const std::string& stringToPaste);
-
-  /**
-   * @brief Remove a given number of characters
-   *
-   * When predictve text is used the pre-edit text is removed and inserted again with the new characters.
-   * The UpdateInputStyleType @type parameter if set to DONT_UPDATE_INPUT_STYLE avoids to update the input
-   * style when pre-edit text is removed.
-   *
-   * @param[in] controller The controller
-   * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
-   * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
-   * @param[in] type Whether to update the input style.
-   * @return True if the remove was successful.
-   */
-  static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type);
-
-  /**
-   * @brief Checks if text is selected and if so removes it.
-   * @param[in] controller The controller
-   * @return true if text was removed
-   */
-  static bool RemoveSelectedText(Controller& controller);
-
-  /**
-   * @brief Used to remove the text included the placeholder text.
-   * @param[in] controller The controller
-   */
-  static void ResetText(Controller& controller);
-
-  /**
-   * @brief Update anchor position from given number of inserted characters.
-   *
-   * @param[in] controller The controller
-   * @param[in] numberOfCharacters The number of inserted characters.
-   * @param[in] previousCursorIndex A cursor position before event occurs.
-   */
-  static void InsertTextAnchor(Controller& controller, int numberOfCharacters, CharacterIndex previousCursorIndex);
-
-  /**
-   * @brief Update anchor position from given number of removed characters.
-   *
-   * @param[in] controller The controller
-   * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
-   * @param[in] numberOfCharacters The number of removed characters.
-   * @param[in] previousCursorIndex A cursor position before event occurs.
-   */
-  static void RemoveTextAnchor(Controller& controller, int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex);
-};
-
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXT_UPDATER_H
diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp
deleted file mode 100644 (file)
index 1a07af5..0000000
+++ /dev/null
@@ -1,1707 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-controller.h>
-
-// EXTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
-#include <dali/integration-api/debug.h>
-#include <memory.h>
-#include <cmath>
-#include <limits>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
-#include <dali-toolkit/internal/text/text-controller-background-actor.h>
-#include <dali-toolkit/internal/text/text-controller-event-handler.h>
-#include <dali-toolkit/internal/text/text-controller-impl.h>
-#include <dali-toolkit/internal/text/text-controller-input-font-handler.h>
-#include <dali-toolkit/internal/text/text-controller-input-properties.h>
-#include <dali-toolkit/internal/text/text-controller-placeholder-handler.h>
-#include <dali-toolkit/internal/text/text-controller-relayouter.h>
-#include <dali-toolkit/internal/text/text-controller-text-updater.h>
-#include <dali-toolkit/internal/text/text-editable-control-interface.h>
-#include <dali-toolkit/internal/text/text-geometry.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
-#endif
-
-const std::string EMPTY_STRING("");
-
-template<typename Type>
-void EnsureCreated(Type*& object)
-{
-  if(!object)
-  {
-    object = new Type();
-  }
-}
-
-template<typename Type>
-void EnsureCreated(std::unique_ptr<Type>& object)
-{
-  if(!object)
-  {
-    object = std::unique_ptr<Type>(new Type());
-  }
-}
-
-template<typename Type, typename Arg1>
-void EnsureCreated(Type*& object, Arg1 arg1)
-{
-  if(!object)
-  {
-    object = new Type(arg1);
-  }
-}
-
-template<typename Type, typename Arg1, typename Arg2>
-void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
-{
-  if(!object)
-  {
-    object = new Type(arg1, arg2);
-  }
-}
-
-float GetDpi()
-{
-  unsigned int                      horizontalDpi = 0u;
-  unsigned int                      verticalDpi   = 0u;
-  Dali::TextAbstraction::FontClient fontClient    = Dali::TextAbstraction::FontClient::Get();
-  fontClient.GetDpi(horizontalDpi, verticalDpi);
-  return static_cast<float>(horizontalDpi);
-}
-
-float ConvertPixelToPoint(float pixel)
-{
-  return pixel * 72.0f / GetDpi();
-}
-
-float ConvertPointToPixel(float point)
-{
-  // Pixel size = Point size * DPI / 72.f
-  return point * GetDpi() / 72.0f;
-}
-
-void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
-{
-  if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
-  {
-    // Update the cursor position if it's in editing mode
-    eventData->mDecoratorUpdated     = true;
-    eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
-  }
-}
-
-} // namespace
-
-namespace Dali::Toolkit::Text
-{
-void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
-{
-  if(!decorator)
-  {
-    delete mImpl->mEventData;
-    mImpl->mEventData = NULL;
-
-    // Nothing else to do.
-    return;
-  }
-
-  EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
-}
-
-void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
-{
-  // Metrics for bitmap & vector based glyphs are different
-  mImpl->mMetrics->SetGlyphType(glyphType);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-void Controller::SetMarkupProcessorEnabled(bool enable)
-{
-  if(enable != mImpl->mMarkupProcessorEnabled)
-  {
-    //If Text was already set, call the SetText again for enabling or disabling markup
-    mImpl->mMarkupProcessorEnabled = enable;
-    std::string text;
-    GetText(text);
-    SetText(text);
-  }
-
-  mImpl->mModel->mVisualModel->SetMarkupProcessorEnabled(enable);
-}
-
-bool Controller::IsMarkupProcessorEnabled() const
-{
-  return mImpl->mMarkupProcessorEnabled;
-}
-
-bool Controller::HasAnchors() const
-{
-  return (mImpl->mMarkupProcessorEnabled && mImpl->mModel->mLogicalModel->mAnchors.Count() && mImpl->IsShowingRealText());
-}
-
-void Controller::SetAutoScrollEnabled(bool enable)
-{
-  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable) ? "true" : "false", (mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX) ? "true" : "false", this);
-  mImpl->SetAutoScrollEnabled(enable);
-}
-
-void Controller::SetAutoScrollMaxTextureExceeded(bool exceed)
-{
-  mImpl->mIsAutoScrollMaxTextureExceeded = exceed;
-}
-
-bool Controller::IsAutoScrollEnabled() const
-{
-  DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled ? "true" : "false");
-  return mImpl->mIsAutoScrollEnabled;
-}
-
-CharacterDirection Controller::GetAutoScrollDirection() const
-{
-  return mImpl->mIsTextDirectionRTL;
-}
-
-float Controller::GetAutoScrollLineAlignment() const
-{
-  float offset = 0.f;
-  if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
-  {
-    offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
-  }
-  return offset;
-}
-
-void Controller::SetHorizontalScrollEnabled(bool enable)
-{
-  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
-  {
-    mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
-  }
-}
-
-bool Controller::IsHorizontalScrollEnabled() const
-{
-  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
-}
-
-void Controller::SetVerticalScrollEnabled(bool enable)
-{
-  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
-  {
-    mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
-  }
-}
-
-bool Controller::IsVerticalScrollEnabled() const
-{
-  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
-}
-
-void Controller::SetSmoothHandlePanEnabled(bool enable)
-{
-  if(mImpl->mEventData && mImpl->mEventData->mDecorator)
-  {
-    mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
-  }
-}
-
-bool Controller::IsSmoothHandlePanEnabled() const
-{
-  return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
-}
-
-void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
-{
-  mImpl->mMaximumNumberOfCharacters = maxCharacters;
-}
-
-int Controller::GetMaximumNumberOfCharacters()
-{
-  return mImpl->mMaximumNumberOfCharacters;
-}
-
-void Controller::SetEnableCursorBlink(bool enable)
-{
-  mImpl->SetEnableCursorBlink(enable);
-}
-
-bool Controller::GetEnableCursorBlink() const
-{
-  return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
-}
-
-void Controller::SetMultiLineEnabled(bool enable)
-{
-  mImpl->SetMultiLineEnabled(enable);
-}
-
-bool Controller::IsMultiLineEnabled() const
-{
-  return Layout::Engine::MULTI_LINE_BOX == mImpl->mLayoutEngine.GetLayout();
-}
-
-void Controller::SetHorizontalAlignment(Text::HorizontalAlignment::Type alignment)
-{
-  mImpl->SetHorizontalAlignment(alignment);
-}
-
-Text::HorizontalAlignment::Type Controller::GetHorizontalAlignment() const
-{
-  return mImpl->mModel->mHorizontalAlignment;
-}
-
-void Controller::SetVerticalAlignment(VerticalAlignment::Type alignment)
-{
-  mImpl->SetVerticalAlignment(alignment);
-}
-
-VerticalAlignment::Type Controller::GetVerticalAlignment() const
-{
-  return mImpl->mModel->mVerticalAlignment;
-}
-
-bool Controller::IsIgnoreSpacesAfterText() const
-{
-  return mImpl->mModel->mIgnoreSpacesAfterText;
-}
-
-void Controller::SetIgnoreSpacesAfterText(bool ignore)
-{
-  mImpl->mModel->mIgnoreSpacesAfterText = ignore;
-}
-
-void Controller::ChangedLayoutDirection()
-{
-  mImpl->mIsLayoutDirectionChanged = true;
-}
-
-void Controller::SetMatchLayoutDirection(DevelText::MatchLayoutDirection type)
-{
-  mImpl->mModel->mMatchLayoutDirection = type;
-}
-
-DevelText::MatchLayoutDirection Controller::GetMatchLayoutDirection() const
-{
-  return mImpl->mModel->mMatchLayoutDirection;
-}
-
-void Controller::SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection)
-{
-  mImpl->mLayoutDirection = layoutDirection;
-}
-
-Dali::LayoutDirection::Type Controller::GetLayoutDirection(Dali::Actor& actor) const
-{
-  return mImpl->GetLayoutDirection(actor);
-}
-
-bool Controller::IsShowingRealText() const
-{
-  return mImpl->IsShowingRealText();
-}
-
-void Controller::SetLineWrapMode(Text::LineWrap::Mode lineWrapMode)
-{
-  mImpl->SetLineWrapMode(lineWrapMode);
-}
-
-Text::LineWrap::Mode Controller::GetLineWrapMode() const
-{
-  return mImpl->mModel->mLineWrapMode;
-}
-
-void Controller::SetTextElideEnabled(bool enabled)
-{
-  mImpl->mModel->mElideEnabled = enabled;
-  mImpl->mModel->mVisualModel->SetTextElideEnabled(enabled);
-}
-
-bool Controller::IsTextElideEnabled() const
-{
-  return mImpl->mModel->mElideEnabled;
-}
-
-void Controller::SetTextFitEnabled(bool enabled)
-{
-  mImpl->mTextFitEnabled = enabled;
-}
-
-bool Controller::IsTextFitEnabled() const
-{
-  return mImpl->mTextFitEnabled;
-}
-
-void Controller::SetTextFitChanged(bool changed)
-{
-  mImpl->mTextFitChanged = changed;
-}
-
-bool Controller::IsTextFitChanged() const
-{
-  return mImpl->mTextFitChanged;
-}
-
-void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
-{
-  mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
-}
-
-float Controller::GetTextFitMinSize() const
-{
-  return mImpl->mTextFitMinSize;
-}
-
-void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
-{
-  mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
-}
-
-float Controller::GetTextFitMaxSize() const
-{
-  return mImpl->mTextFitMaxSize;
-}
-
-void Controller::SetTextFitStepSize(float step, FontSizeType type)
-{
-  mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
-}
-
-float Controller::GetTextFitStepSize() const
-{
-  return mImpl->mTextFitStepSize;
-}
-
-void Controller::SetTextFitContentSize(Vector2 size)
-{
-  mImpl->mTextFitContentSize = size;
-}
-
-Vector2 Controller::GetTextFitContentSize() const
-{
-  return mImpl->mTextFitContentSize;
-}
-
-float Controller::GetTextFitPointSize() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFitPointSize : 0.0f;
-}
-
-void Controller::SetPlaceholderTextElideEnabled(bool enabled)
-{
-  PlaceholderHandler::SetPlaceholderTextElideEnabled(*this, enabled);
-}
-
-bool Controller::IsPlaceholderTextElideEnabled() const
-{
-  return PlaceholderHandler::IsPlaceholderTextElideEnabled(*this);
-}
-
-void Controller::SetSelectionEnabled(bool enabled)
-{
-  mImpl->mEventData->mSelectionEnabled = enabled;
-}
-
-bool Controller::IsSelectionEnabled() const
-{
-  return mImpl->mEventData->mSelectionEnabled;
-}
-
-void Controller::SetShiftSelectionEnabled(bool enabled)
-{
-  mImpl->mEventData->mShiftSelectionFlag = enabled;
-}
-
-bool Controller::IsShiftSelectionEnabled() const
-{
-  return mImpl->mEventData->mShiftSelectionFlag;
-}
-
-void Controller::SetGrabHandleEnabled(bool enabled)
-{
-  mImpl->mEventData->mGrabHandleEnabled = enabled;
-}
-
-bool Controller::IsGrabHandleEnabled() const
-{
-  return mImpl->mEventData->mGrabHandleEnabled;
-}
-
-void Controller::SetGrabHandlePopupEnabled(bool enabled)
-{
-  mImpl->mEventData->mGrabHandlePopupEnabled = enabled;
-}
-
-bool Controller::IsGrabHandlePopupEnabled() const
-{
-  return mImpl->mEventData->mGrabHandlePopupEnabled;
-}
-
-void Controller::SetText(const std::string& text)
-{
-  TextUpdater::SetText(*this, text);
-}
-
-void Controller::GetText(std::string& text) const
-{
-  mImpl->GetText(text);
-}
-
-void Controller::SetPlaceholderText(PlaceholderType type, const std::string& text)
-{
-  PlaceholderHandler::SetPlaceholderText(*this, type, text);
-}
-
-void Controller::GetPlaceholderText(PlaceholderType type, std::string& text) const
-{
-  PlaceholderHandler::GetPlaceholderText(*this, type, text);
-}
-
-void Controller::UpdateAfterFontChange(const std::string& newDefaultFont)
-{
-  mImpl->UpdateAfterFontChange(newDefaultFont);
-}
-
-void Controller::RetrieveSelection(std::string& selectedText) const
-{
-  mImpl->RetrieveSelection(selectedText, false);
-}
-
-void Controller::SetSelection(int start, int end)
-{
-  mImpl->SetSelection(start, end);
-}
-
-std::pair<int, int> Controller::GetSelectionIndexes() const
-{
-  return mImpl->GetSelectionIndexes();
-}
-
-void Controller::CopyStringToClipboard(const std::string& source)
-{
-  mImpl->CopyStringToClipboard(source);
-}
-
-void Controller::SendSelectionToClipboard(bool deleteAfterSending)
-{
-  mImpl->SendSelectionToClipboard(deleteAfterSending);
-}
-
-void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
-{
-  EnsureCreated(mImpl->mFontDefaults);
-
-  mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
-  DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
-  mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-const std::string& Controller::GetDefaultFontFamily() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
-}
-
-void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
-{
-  PlaceholderHandler::SetPlaceholderFontFamily(*this, placeholderTextFontFamily);
-}
-
-const std::string& Controller::GetPlaceholderFontFamily() const
-{
-  return PlaceholderHandler::GetPlaceholderFontFamily(*this);
-}
-
-void Controller::SetDefaultFontWeight(FontWeight weight)
-{
-  EnsureCreated(mImpl->mFontDefaults);
-
-  mImpl->mFontDefaults->mFontDescription.weight = weight;
-  mImpl->mFontDefaults->weightDefined           = true;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsDefaultFontWeightDefined() const
-{
-  return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
-}
-
-FontWeight Controller::GetDefaultFontWeight() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
-}
-
-void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
-{
-  PlaceholderHandler::SetPlaceholderTextFontWeight(*this, weight);
-}
-
-bool Controller::IsPlaceholderTextFontWeightDefined() const
-{
-  return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
-}
-
-FontWeight Controller::GetPlaceholderTextFontWeight() const
-{
-  return PlaceholderHandler::GetPlaceholderTextFontWeight(*this);
-}
-
-void Controller::SetDefaultFontWidth(FontWidth width)
-{
-  EnsureCreated(mImpl->mFontDefaults);
-
-  mImpl->mFontDefaults->mFontDescription.width = width;
-  mImpl->mFontDefaults->widthDefined           = true;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsDefaultFontWidthDefined() const
-{
-  return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
-}
-
-FontWidth Controller::GetDefaultFontWidth() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
-}
-
-void Controller::SetPlaceholderTextFontWidth(FontWidth width)
-{
-  PlaceholderHandler::SetPlaceholderTextFontWidth(*this, width);
-}
-
-bool Controller::IsPlaceholderTextFontWidthDefined() const
-{
-  return PlaceholderHandler::IsPlaceholderTextFontWidthDefined(*this);
-}
-
-FontWidth Controller::GetPlaceholderTextFontWidth() const
-{
-  return PlaceholderHandler::GetPlaceholderTextFontWidth(*this);
-}
-
-void Controller::SetDefaultFontSlant(FontSlant slant)
-{
-  EnsureCreated(mImpl->mFontDefaults);
-
-  mImpl->mFontDefaults->mFontDescription.slant = slant;
-  mImpl->mFontDefaults->slantDefined           = true;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsDefaultFontSlantDefined() const
-{
-  return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
-}
-
-FontSlant Controller::GetDefaultFontSlant() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
-}
-
-void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
-{
-  PlaceholderHandler::SetPlaceholderTextFontSlant(*this, slant);
-}
-
-bool Controller::IsPlaceholderTextFontSlantDefined() const
-{
-  return PlaceholderHandler::IsPlaceholderTextFontSlantDefined(*this);
-}
-
-FontSlant Controller::GetPlaceholderTextFontSlant() const
-{
-  return PlaceholderHandler::GetPlaceholderTextFontSlant(*this);
-}
-
-void Controller::SetFontSizeScale(float scale)
-{
-  mImpl->mFontSizeScale = scale;
-
-  // No relayout is required
-  if(!mImpl->mFontSizeScaleEnabled) return;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetFontSizeScale() const
-{
-  return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
-}
-
-void Controller::SetFontSizeScaleEnabled(bool enabled)
-{
-  mImpl->mFontSizeScaleEnabled = enabled;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsFontSizeScaleEnabled() const
-{
-  return mImpl->mFontSizeScaleEnabled;
-}
-
-void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
-{
-  EnsureCreated(mImpl->mFontDefaults);
-
-  mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
-  mImpl->mFontDefaults->sizeDefined       = true;
-
-  // Update the cursor position if it's in editing mode
-  UpdateCursorPosition(mImpl->mEventData);
-
-  // Clear the font-specific data
-  mImpl->ClearFontData();
-
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetDefaultFontSize(FontSizeType type) const
-{
-  if(mImpl->mFontDefaults)
-  {
-    return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
-  }
-  return 0.0f;
-}
-
-void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
-{
-  PlaceholderHandler::SetPlaceholderTextFontSize(*this, fontSize, type);
-}
-
-float Controller::GetPlaceholderTextFontSize(FontSizeType type) const
-{
-  return PlaceholderHandler::GetPlaceholderTextFontSize(*this, type);
-}
-
-void Controller::SetDefaultColor(const Vector4& color)
-{
-  mImpl->SetDefaultColor(color);
-}
-
-const Vector4& Controller::GetDefaultColor() const
-{
-  return mImpl->mTextColor;
-}
-
-void Controller::SetDisabledColorOpacity(float opacity)
-{
-  mImpl->mDisabledColorOpacity = opacity;
-}
-
-float Controller::GetDisabledColorOpacity() const
-{
-  return mImpl->mDisabledColorOpacity;
-}
-
-void Controller::SetUserInteractionEnabled(bool enabled)
-{
-  mImpl->SetUserInteractionEnabled(enabled);
-}
-
-bool Controller::IsUserInteractionEnabled() const
-{
-  return mImpl->mIsUserInteractionEnabled;
-}
-
-void Controller::SetPlaceholderTextColor(const Vector4& textColor)
-{
-  PlaceholderHandler::SetPlaceholderTextColor(*this, textColor);
-}
-
-const Vector4& Controller::GetPlaceholderTextColor() const
-{
-  return PlaceholderHandler::GetPlaceholderTextColor(*this);
-}
-
-void Controller::SetShadowOffset(const Vector2& shadowOffset)
-{
-  mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
-  mImpl->RequestRelayout();
-}
-
-const Vector2& Controller::GetShadowOffset() const
-{
-  return mImpl->mModel->mVisualModel->GetShadowOffset();
-}
-
-void Controller::SetShadowColor(const Vector4& shadowColor)
-{
-  mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
-  mImpl->RequestRelayout();
-}
-
-const Vector4& Controller::GetShadowColor() const
-{
-  return mImpl->mModel->mVisualModel->GetShadowColor();
-}
-
-void Controller::SetShadowBlurRadius(const float& shadowBlurRadius)
-{
-  if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
-  {
-    mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
-    mImpl->RequestRelayout();
-  }
-}
-
-const float& Controller::GetShadowBlurRadius() const
-{
-  return mImpl->mModel->mVisualModel->GetShadowBlurRadius();
-}
-
-void Controller::SetUnderlineColor(const Vector4& color)
-{
-  mImpl->mModel->mVisualModel->SetUnderlineColor(color);
-  mImpl->RequestRelayout();
-}
-
-const Vector4& Controller::GetUnderlineColor() const
-{
-  return mImpl->mModel->mVisualModel->GetUnderlineColor();
-}
-
-void Controller::SetUnderlineEnabled(bool enabled)
-{
-  mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsUnderlineEnabled() const
-{
-  return mImpl->mModel->mVisualModel->IsUnderlineEnabled();
-}
-
-void Controller::SetUnderlineHeight(float height)
-{
-  mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetUnderlineHeight() const
-{
-  return mImpl->mModel->mVisualModel->GetUnderlineHeight();
-}
-
-void Controller::SetUnderlineType(Text::Underline::Type type)
-{
-  mImpl->mModel->mVisualModel->SetUnderlineType(type);
-
-  mImpl->RequestRelayout();
-}
-
-Text::Underline::Type Controller::GetUnderlineType() const
-{
-  return mImpl->mModel->mVisualModel->GetUnderlineType();
-}
-
-void Controller::SetDashedUnderlineWidth(float width)
-{
-  mImpl->mModel->mVisualModel->SetDashedUnderlineWidth(width);
-
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetDashedUnderlineWidth() const
-{
-  return mImpl->mModel->mVisualModel->GetDashedUnderlineWidth();
-}
-
-void Controller::SetDashedUnderlineGap(float gap)
-{
-  mImpl->mModel->mVisualModel->SetDashedUnderlineGap(gap);
-
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetDashedUnderlineGap() const
-{
-  return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
-}
-
-void Controller::SetOutlineColor(const Vector4& color)
-{
-  mImpl->mModel->mVisualModel->SetOutlineColor(color);
-  mImpl->RequestRelayout();
-}
-
-const Vector4& Controller::GetOutlineColor() const
-{
-  return mImpl->mModel->mVisualModel->GetOutlineColor();
-}
-
-void Controller::SetOutlineWidth(uint16_t width)
-{
-  mImpl->mModel->mVisualModel->SetOutlineWidth(width);
-  mImpl->RequestRelayout();
-}
-
-uint16_t Controller::GetOutlineWidth() const
-{
-  return mImpl->mModel->mVisualModel->GetOutlineWidth();
-}
-
-void Controller::SetBackgroundColor(const Vector4& color)
-{
-  mImpl->mModel->mVisualModel->SetBackgroundColor(color);
-  mImpl->RequestRelayout();
-}
-
-const Vector4& Controller::GetBackgroundColor() const
-{
-  return mImpl->mModel->mVisualModel->GetBackgroundColor();
-}
-
-void Controller::SetBackgroundEnabled(bool enabled)
-{
-  mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsBackgroundEnabled() const
-{
-  return mImpl->mModel->mVisualModel->IsBackgroundEnabled();
-}
-
-void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
-{
-  EnsureCreated(mImpl->mEmbossDefaults);
-  mImpl->mEmbossDefaults->properties = embossProperties;
-}
-
-const std::string& Controller::GetDefaultEmbossProperties() const
-{
-  return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
-}
-
-void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
-{
-  EnsureCreated(mImpl->mOutlineDefaults);
-  mImpl->mOutlineDefaults->properties = outlineProperties;
-}
-
-const std::string& Controller::GetDefaultOutlineProperties() const
-{
-  return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
-}
-
-bool Controller::SetDefaultLineSpacing(float lineSpacing)
-{
-  return mImpl->SetDefaultLineSpacing(lineSpacing);
-}
-
-float Controller::GetDefaultLineSpacing() const
-{
-  return mImpl->mLayoutEngine.GetDefaultLineSpacing();
-}
-
-bool Controller::SetDefaultLineSize(float lineSize)
-{
-  return mImpl->SetDefaultLineSize(lineSize);
-}
-
-float Controller::GetDefaultLineSize() const
-{
-  return mImpl->mLayoutEngine.GetDefaultLineSize();
-}
-
-bool Controller::SetRelativeLineSize(float relativeLineSize)
-{
-  return mImpl->SetRelativeLineSize(relativeLineSize);
-}
-
-float Controller::GetRelativeLineSize() const
-{
-  return mImpl->GetRelativeLineSize();
-}
-
-void Controller::SetInputColor(const Vector4& color)
-{
-  InputProperties::SetInputColor(*this, color);
-}
-
-const Vector4& Controller::GetInputColor() const
-{
-  return InputProperties::GetInputColor(*this);
-}
-
-void Controller::SetInputFontFamily(const std::string& fontFamily)
-{
-  InputFontHandler::SetInputFontFamily(*this, fontFamily);
-}
-
-const std::string& Controller::GetInputFontFamily() const
-{
-  return InputFontHandler::GetInputFontFamily(*this);
-}
-
-void Controller::SetInputFontWeight(FontWeight weight)
-{
-  InputFontHandler::SetInputFontWeight(*this, weight);
-}
-
-bool Controller::IsInputFontWeightDefined() const
-{
-  return InputFontHandler::IsInputFontWeightDefined(*this);
-}
-
-FontWeight Controller::GetInputFontWeight() const
-{
-  return InputFontHandler::GetInputFontWeight(*this);
-}
-
-void Controller::SetInputFontWidth(FontWidth width)
-{
-  InputFontHandler::SetInputFontWidth(*this, width);
-}
-
-bool Controller::IsInputFontWidthDefined() const
-{
-  return InputFontHandler::IsInputFontWidthDefined(*this);
-}
-
-FontWidth Controller::GetInputFontWidth() const
-{
-  return InputFontHandler::GetInputFontWidth(*this);
-}
-
-void Controller::SetInputFontSlant(FontSlant slant)
-{
-  InputFontHandler::SetInputFontSlant(*this, slant);
-}
-
-bool Controller::IsInputFontSlantDefined() const
-{
-  return InputFontHandler::IsInputFontSlantDefined(*this);
-}
-
-FontSlant Controller::GetInputFontSlant() const
-{
-  return InputFontHandler::GetInputFontSlant(*this);
-}
-
-void Controller::SetInputFontPointSize(float size)
-{
-  InputFontHandler::SetInputFontPointSize(*this, size);
-}
-
-float Controller::GetInputFontPointSize() const
-{
-  return InputFontHandler::GetInputFontPointSize(*this);
-}
-
-void Controller::SetInputLineSpacing(float lineSpacing)
-{
-  InputProperties::SetInputLineSpacing(*this, lineSpacing);
-}
-
-float Controller::GetInputLineSpacing() const
-{
-  return InputProperties::GetInputLineSpacing(*this);
-}
-
-void Controller::SetInputShadowProperties(const std::string& shadowProperties)
-{
-  InputProperties::SetInputShadowProperties(*this, shadowProperties);
-}
-
-const std::string& Controller::GetInputShadowProperties() const
-{
-  return InputProperties::GetInputShadowProperties(*this);
-}
-
-void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
-{
-  InputProperties::SetInputUnderlineProperties(*this, underlineProperties);
-}
-
-const std::string& Controller::GetInputUnderlineProperties() const
-{
-  return InputProperties::GetInputUnderlineProperties(*this);
-}
-
-void Controller::SetInputEmbossProperties(const std::string& embossProperties)
-{
-  InputProperties::SetInputEmbossProperties(*this, embossProperties);
-}
-
-const std::string& Controller::GetInputEmbossProperties() const
-{
-  return InputProperties::GetInputEmbossProperties(*this);
-}
-
-void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
-{
-  InputProperties::SetInputOutlineProperties(*this, outlineProperties);
-}
-
-const std::string& Controller::GetInputOutlineProperties() const
-{
-  return InputProperties::GetInputOutlineProperties(*this);
-}
-
-void Controller::SetInputModePassword(bool passwordInput)
-{
-  InputProperties::SetInputModePassword(*this, passwordInput);
-}
-
-bool Controller::IsInputModePassword()
-{
-  return InputProperties::IsInputModePassword(*this);
-}
-
-void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
-{
-  if(mImpl->mEventData)
-  {
-    mImpl->mEventData->mDoubleTapAction = action;
-  }
-}
-
-Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
-{
-  return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
-}
-
-void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
-{
-  if(mImpl->mEventData)
-  {
-    mImpl->mEventData->mLongPressAction = action;
-  }
-}
-
-Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
-{
-  return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
-}
-
-bool Controller::IsUnderlineSetByString()
-{
-  return mImpl->mUnderlineSetByString;
-}
-
-void Controller::UnderlineSetByString(bool setByString)
-{
-  mImpl->mUnderlineSetByString = setByString;
-}
-
-bool Controller::IsShadowSetByString()
-{
-  return mImpl->mShadowSetByString;
-}
-
-void Controller::ShadowSetByString(bool setByString)
-{
-  mImpl->mShadowSetByString = setByString;
-}
-
-bool Controller::IsOutlineSetByString()
-{
-  return mImpl->mOutlineSetByString;
-}
-
-void Controller::OutlineSetByString(bool setByString)
-{
-  mImpl->mOutlineSetByString = setByString;
-}
-
-bool Controller::IsFontStyleSetByString()
-{
-  return mImpl->mFontStyleSetByString;
-}
-
-void Controller::FontStyleSetByString(bool setByString)
-{
-  mImpl->mFontStyleSetByString = setByString;
-}
-
-void Controller::SetStrikethroughHeight(float height)
-{
-  mImpl->mModel->mVisualModel->SetStrikethroughHeight(height);
-
-  mImpl->RequestRelayout();
-}
-
-float Controller::GetStrikethroughHeight() const
-{
-  return mImpl->mModel->mVisualModel->GetStrikethroughHeight();
-}
-
-void Controller::SetStrikethroughColor(const Vector4& color)
-{
-  mImpl->mModel->mVisualModel->SetStrikethroughColor(color);
-
-  mImpl->RequestRelayout();
-}
-
-const Vector4& Controller::GetStrikethroughColor() const
-{
-  return mImpl->mModel->mVisualModel->GetStrikethroughColor();
-}
-
-void Controller::SetStrikethroughEnabled(bool enabled)
-{
-  mImpl->mModel->mVisualModel->SetStrikethroughEnabled(enabled);
-
-  mImpl->RequestRelayout();
-}
-
-bool Controller::IsStrikethroughEnabled() const
-{
-  return mImpl->mModel->mVisualModel->IsStrikethroughEnabled();
-}
-
-void Controller::SetInputStrikethroughProperties(const std::string& strikethroughProperties)
-{
-  if(NULL != mImpl->mEventData)
-  {
-    mImpl->mEventData->mInputStyle.strikethroughProperties = strikethroughProperties;
-  }
-}
-
-const std::string& Controller::GetInputStrikethroughProperties() const
-{
-  return (NULL != mImpl->mEventData) ? mImpl->mEventData->mInputStyle.strikethroughProperties : EMPTY_STRING;
-}
-
-bool Controller::IsStrikethroughSetByString()
-{
-  return mImpl->mStrikethroughSetByString;
-}
-
-void Controller::StrikethroughSetByString(bool setByString)
-{
-  mImpl->mStrikethroughSetByString = setByString;
-}
-
-Layout::Engine& Controller::GetLayoutEngine()
-{
-  return mImpl->mLayoutEngine;
-}
-
-View& Controller::GetView()
-{
-  return mImpl->mView;
-}
-
-Vector3 Controller::GetNaturalSize()
-{
-  return Relayouter::GetNaturalSize(*this);
-}
-
-bool Controller::CheckForTextFit(float pointSize, Size& layoutSize)
-{
-  return Relayouter::CheckForTextFit(*this, pointSize, layoutSize);
-}
-
-void Controller::FitPointSizeforLayout(Size layoutSize)
-{
-  Relayouter::FitPointSizeforLayout(*this, layoutSize);
-}
-
-float Controller::GetHeightForWidth(float width)
-{
-  return Relayouter::GetHeightForWidth(*this, width);
-}
-
-int Controller::GetLineCount(float width)
-{
-  GetHeightForWidth(width);
-  return mImpl->mModel->GetNumberOfLines();
-}
-
-const ModelInterface* const Controller::GetTextModel() const
-{
-  return mImpl->mModel.Get();
-}
-
-float Controller::GetScrollAmountByUserInput()
-{
-  float scrollAmount = 0.0f;
-
-  if(NULL != mImpl->mEventData && mImpl->mEventData->mCheckScrollAmount)
-  {
-    scrollAmount                          = mImpl->mModel->mScrollPosition.y - mImpl->mModel->mScrollPositionLast.y;
-    mImpl->mEventData->mCheckScrollAmount = false;
-  }
-  return scrollAmount;
-}
-
-bool Controller::GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight)
-{
-  const Vector2& layout = mImpl->mModel->mVisualModel->GetLayoutSize();
-  bool           isScrolled;
-
-  controlHeight  = mImpl->mModel->mVisualModel->mControlSize.height;
-  layoutHeight   = layout.height;
-  scrollPosition = mImpl->mModel->mScrollPosition.y;
-  isScrolled     = !Equals(mImpl->mModel->mScrollPosition.y, mImpl->mModel->mScrollPositionLast.y, Math::MACHINE_EPSILON_1);
-  return isScrolled;
-}
-
-void Controller::SetHiddenInputOption(const Property::Map& options)
-{
-  EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
-  mImpl->mHiddenInput->SetProperties(options);
-}
-
-void Controller::GetHiddenInputOption(Property::Map& options)
-{
-  if(mImpl->mHiddenInput)
-  {
-    mImpl->mHiddenInput->GetProperties(options);
-  }
-}
-
-void Controller::SetInputFilterOption(const Property::Map& options)
-{
-  EnsureCreated(mImpl->mInputFilter);
-  mImpl->mInputFilter->SetProperties(options);
-}
-
-void Controller::GetInputFilterOption(Property::Map& options)
-{
-  if(mImpl->mInputFilter)
-  {
-    mImpl->mInputFilter->GetProperties(options);
-  }
-}
-
-void Controller::SetPlaceholderProperty(const Property::Map& map)
-{
-  PlaceholderHandler::SetPlaceholderProperty(*this, map);
-}
-
-void Controller::GetPlaceholderProperty(Property::Map& map)
-{
-  PlaceholderHandler::GetPlaceholderProperty(*this, map);
-}
-
-Toolkit::DevelText::TextDirection::Type Controller::GetTextDirection()
-{
-  // Make sure the model is up-to-date before layouting
-  EventHandler::ProcessModifyEvents(*this);
-
-  return mImpl->GetTextDirection();
-}
-
-Toolkit::DevelText::VerticalLineAlignment::Type Controller::GetVerticalLineAlignment() const
-{
-  return mImpl->mModel->GetVerticalLineAlignment();
-}
-
-void Controller::SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment)
-{
-  mImpl->mModel->mVerticalLineAlignment = alignment;
-}
-
-Toolkit::DevelText::EllipsisPosition::Type Controller::GetEllipsisPosition() const
-{
-  return mImpl->mModel->GetEllipsisPosition();
-}
-
-void Controller::SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition)
-{
-  mImpl->mModel->mEllipsisPosition = ellipsisPosition;
-  mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
-}
-
-void Controller::SetCharacterSpacing(float characterSpacing)
-{
-  mImpl->mModel->mVisualModel->SetCharacterSpacing(characterSpacing);
-
-  mImpl->RelayoutAllCharacters();
-  mImpl->RequestRelayout();
-}
-
-const float Controller::GetCharacterSpacing() const
-{
-  return mImpl->mModel->mVisualModel->GetCharacterSpacing();
-}
-
-Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
-{
-  return Relayouter::Relayout(*this, size, layoutDirection);
-}
-
-void Controller::RequestRelayout()
-{
-  mImpl->RequestRelayout();
-}
-
-Vector<Vector2> Controller::GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex)
-{
-  Vector<Vector2> sizesList;
-  Vector<Vector2> positionsList;
-
-  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
-  return sizesList;
-}
-
-Vector<Vector2> Controller::GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex)
-{
-  Vector<Vector2> sizesList;
-  Vector<Vector2> positionsList;
-
-  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizesList, positionsList);
-  return positionsList;
-}
-
-Rect<> Controller::GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex)
-{
-  Vector<Vector2> sizeList;
-  Vector<Vector2> positionList;
-
-  GetTextGeometry(mImpl->mModel, startIndex, endIndex, sizeList, positionList);
-
-  if(sizeList.Empty() || sizeList.Size() != positionList.Size())
-  {
-    return {0, 0, 0, 0};
-  }
-
-  auto minX      = positionList[0].x;
-  auto minY      = positionList[0].y;
-  auto maxRight  = positionList[0].x + sizeList[0].x;
-  auto maxBottom = positionList[0].y + sizeList[0].y;
-
-  for(unsigned int i = 1; i < sizeList.Size(); i++)
-  {
-    minX      = std::min(minX, positionList[i].x);
-    minY      = std::min(minY, positionList[i].y);
-    maxRight  = std::max(maxRight, positionList[i].x + sizeList[i].x);
-    maxBottom = std::max(maxBottom, positionList[i].y + sizeList[i].y);
-  }
-
-  return {minX, minY, maxRight - minX, maxBottom - minY};
-}
-
-bool Controller::IsInputStyleChangedSignalsQueueEmpty()
-{
-  return mImpl->IsInputStyleChangedSignalsQueueEmpty();
-}
-
-void Controller::ProcessInputStyleChangedSignals()
-{
-  mImpl->ProcessInputStyleChangedSignals();
-}
-
-void Controller::KeyboardFocusGainEvent()
-{
-  EventHandler::KeyboardFocusGainEvent(*this);
-}
-
-void Controller::KeyboardFocusLostEvent()
-{
-  EventHandler::KeyboardFocusLostEvent(*this);
-}
-
-bool Controller::KeyEvent(const Dali::KeyEvent& keyEvent)
-{
-  return EventHandler::KeyEvent(*this, keyEvent);
-}
-
-void Controller::AnchorEvent(float x, float y)
-{
-  EventHandler::AnchorEvent(*this, x, y);
-}
-
-void Controller::TapEvent(unsigned int tapCount, float x, float y)
-{
-  EventHandler::TapEvent(*this, tapCount, x, y);
-}
-
-void Controller::PanEvent(GestureState state, const Vector2& displacement)
-{
-  EventHandler::PanEvent(*this, state, displacement);
-}
-
-void Controller::LongPressEvent(GestureState state, float x, float y)
-{
-  EventHandler::LongPressEvent(*this, state, x, y);
-}
-
-void Controller::SelectEvent(float x, float y, SelectionType selectType)
-{
-  EventHandler::SelectEvent(*this, x, y, selectType);
-}
-
-void Controller::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
-{
-  if(mImpl->mEventData)
-  {
-    mImpl->mEventData->mCheckScrollAmount     = true;
-    mImpl->mEventData->mIsLeftHandleSelected  = true;
-    mImpl->mEventData->mIsRightHandleSelected = true;
-    mImpl->SetTextSelectionRange(start, end);
-    mImpl->RequestRelayout();
-    EventHandler::KeyboardFocusGainEvent(*this);
-  }
-}
-
-Uint32Pair Controller::GetTextSelectionRange() const
-{
-  return mImpl->GetTextSelectionRange();
-}
-
-CharacterIndex Controller::GetPrimaryCursorPosition() const
-{
-  return mImpl->GetPrimaryCursorPosition();
-}
-
-bool Controller::SetPrimaryCursorPosition(CharacterIndex index, bool focused)
-{
-  if(mImpl->mEventData)
-  {
-    mImpl->mEventData->mCheckScrollAmount     = true;
-    mImpl->mEventData->mIsLeftHandleSelected  = true;
-    mImpl->mEventData->mIsRightHandleSelected = true;
-    mImpl->mEventData->mCheckScrollAmount     = true;
-    if(mImpl->SetPrimaryCursorPosition(index, focused) && focused)
-    {
-      EventHandler::KeyboardFocusGainEvent(*this);
-      return true;
-    }
-  }
-  return false;
-}
-
-void Controller::SelectWholeText()
-{
-  EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::ALL);
-}
-
-void Controller::SelectNone()
-{
-  EventHandler::SelectEvent(*this, 0.f, 0.f, SelectionType::NONE);
-}
-
-void Controller::SelectText(const uint32_t start, const uint32_t end)
-{
-  EventHandler::SelectEvent(*this, start, end, SelectionType::RANGE);
-}
-
-string Controller::GetSelectedText() const
-{
-  return mImpl->GetSelectedText();
-}
-
-string Controller::CopyText()
-{
-  return mImpl->CopyText();
-}
-
-string Controller::CutText()
-{
-  return mImpl->CutText();
-}
-
-void Controller::PasteText()
-{
-  mImpl->RequestGetTextFromClipboard(); // Request clipboard service to retrieve an item
-}
-
-InputMethodContext::CallbackData Controller::OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
-{
-  return EventHandler::OnInputMethodContextEvent(*this, inputMethodContext, inputMethodContextEvent);
-}
-
-void Controller::PasteClipboardItemEvent()
-{
-  EventHandler::PasteClipboardItemEvent(*this);
-}
-
-void Controller::GetTargetSize(Vector2& targetSize)
-{
-  targetSize = mImpl->mModel->mVisualModel->mControlSize;
-}
-
-void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
-{
-  if(mImpl->mEditableControlInterface)
-  {
-    mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
-  }
-}
-
-bool Controller::IsEditable() const
-{
-  return mImpl->IsEditable();
-}
-
-void Controller::SetEditable(bool editable)
-{
-  mImpl->SetEditable(editable);
-}
-
-void Controller::ScrollBy(Vector2 scroll)
-{
-  mImpl->ScrollBy(scroll);
-}
-
-bool Controller::IsScrollable(const Vector2& displacement)
-{
-  return mImpl->IsScrollable(displacement);
-}
-
-float Controller::GetHorizontalScrollPosition()
-{
-  return mImpl->GetHorizontalScrollPosition();
-}
-
-float Controller::GetVerticalScrollPosition()
-{
-  return mImpl->GetVerticalScrollPosition();
-}
-
-void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
-{
-  EventHandler::DecorationEvent(*this, handleType, state, x, y);
-}
-
-void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
-{
-  EventHandler::TextPopupButtonTouched(*this, button);
-}
-
-void Controller::DisplayTimeExpired()
-{
-  mImpl->mEventData->mUpdateCursorPosition = true;
-  // Apply modifications to the model
-  mImpl->mOperationsPending = ALL_OPERATIONS;
-
-  mImpl->RequestRelayout();
-}
-
-void Controller::ResetCursorPosition(CharacterIndex cursorIndex)
-{
-  // Reset the cursor position
-  if(NULL != mImpl->mEventData)
-  {
-    mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
-
-    // Update the cursor if it's in editing mode.
-    if(EventData::IsEditingState(mImpl->mEventData->mState))
-    {
-      mImpl->mEventData->mUpdateCursorPosition = true;
-    }
-  }
-}
-
-CharacterIndex Controller::GetCursorPosition()
-{
-  return mImpl->mEventData ? mImpl->mEventData->mPrimaryCursorPosition : 0;
-}
-
-void Controller::SetControlInterface(ControlInterface* controlInterface)
-{
-  mImpl->mControlInterface = controlInterface;
-}
-
-void Controller::SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface)
-{
-  mImpl->mAnchorControlInterface = anchorControlInterface;
-}
-
-bool Controller::ShouldClearFocusOnEscape() const
-{
-  return mImpl->mShouldClearFocusOnEscape;
-}
-
-Actor Controller::CreateBackgroundActor()
-{
-  return CreateControllerBackgroundActor(mImpl->mView, mImpl->mModel->mVisualModel, mImpl->mModel->mLogicalModel, mImpl->mShaderBackground);
-}
-
-void Controller::GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors)
-{
-  mImpl->GetAnchorActors(anchorActors);
-}
-
-int Controller::GetAnchorIndex(size_t characterOffset)
-{
-  return mImpl->GetAnchorIndex(characterOffset);
-}
-
-Controller::Controller(ControlInterface*           controlInterface,
-                       EditableControlInterface*   editableControlInterface,
-                       SelectableControlInterface* selectableControlInterface,
-                       AnchorControlInterface*     anchorControlInterface)
-: mImpl(new Controller::Impl(controlInterface, editableControlInterface, selectableControlInterface, anchorControlInterface))
-{
-}
-
-Controller::~Controller()
-{
-  delete mImpl;
-}
-
-} // namespace Dali::Toolkit::Text
diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h
deleted file mode 100644 (file)
index 09305d2..0000000
+++ /dev/null
@@ -1,2075 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_H
-#define DALI_TOOLKIT_TEXT_CONTROLLER_H
-
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/input-method-context.h>
-#include <dali/public-api/events/gesture.h>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/text-controls/text-anchor-devel.h>
-#include <dali-toolkit/devel-api/controls/text-controls/text-label-devel.h>
-#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
-#include <dali-toolkit/devel-api/text/text-enumerations-devel.h>
-#include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/hidden-text.h>
-#include <dali-toolkit/internal/text/input-filter.h>
-#include <dali-toolkit/internal/text/layouts/layout-engine.h>
-#include <dali-toolkit/internal/text/text-anchor-control-interface.h>
-#include <dali-toolkit/internal/text/text-model-interface.h>
-#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
-#include <dali-toolkit/public-api/text/text-enumerations.h>
-
-namespace Dali::Toolkit::Text
-{
-class Controller;
-class ControlInterface;
-class EditableControlInterface;
-class View;
-class RenderingController;
-
-/**
-   * @brief Text selection operations .
-   */
-enum SelectionType
-{
-  INTERACTIVE = 0x0000, ///< Select the word where the cursor is located.
-  ALL         = 0x0001, ///< Select the whole text.
-  NONE        = 0x0002, ///< Unselect the whole text.
-  RANGE       = 0x0003  ///< Select the range text.
-};
-
-typedef IntrusivePtr<Controller> ControllerPtr;
-
-/**
- * @brief A Text Controller is used by UI Controls which display text.
- *
- * It manipulates the Logical & Visual text models on behalf of the UI Controls.
- * It provides a view of the text that can be used by rendering back-ends.
- *
- * For selectable/editable UI controls, the controller handles input events from the UI control
- * and decorations (grab handles etc) via the Decorator::ControllerInterface interface.
- *
- * The text selection popup button callbacks are as well handled via the TextSelectionPopupCallbackInterface interface.
- */
-class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface, public HiddenText::Observer
-{
-public: // Enumerated types.
-  /**
-   * @brief Text related operations to be done in the relayout process.
-   */
-  enum OperationsMask
-  {
-    NO_OPERATION       = 0x0000,
-    CONVERT_TO_UTF32   = 0x0001,
-    GET_SCRIPTS        = 0x0002,
-    VALIDATE_FONTS     = 0x0004,
-    GET_LINE_BREAKS    = 0x0008,
-    BIDI_INFO          = 0x0010,
-    SHAPE_TEXT         = 0x0020,
-    GET_GLYPH_METRICS  = 0x0040,
-    LAYOUT             = 0x0080,
-    UPDATE_LAYOUT_SIZE = 0x0100,
-    REORDER            = 0x0200,
-    ALIGN              = 0x0400,
-    COLOR              = 0x0800,
-    UPDATE_DIRECTION   = 0x1000,
-    ALL_OPERATIONS     = 0xFFFF
-  };
-
-  /**
-   * @brief Used to distinguish between regular key events and InputMethodContext events
-   */
-  enum InsertType
-  {
-    COMMIT,
-    PRE_EDIT
-  };
-
-  /**
-   * @brief Used to specify whether to update the input style.
-   */
-  enum UpdateInputStyleType
-  {
-    UPDATE_INPUT_STYLE,
-    DONT_UPDATE_INPUT_STYLE
-  };
-
-  /**
-   * @brief Used to specify what has been updated after the Relayout() method has been called.
-   */
-  enum UpdateTextType
-  {
-    NONE_UPDATED      = 0x0, ///< Nothing has been updated.
-    MODEL_UPDATED     = 0x1, ///< The text's model has been updated.
-    DECORATOR_UPDATED = 0x2  ///< The decoration has been updated.
-  };
-
-  /**
-   * @brief Different placeholder-text can be shown when the control is active/inactive.
-   */
-  enum PlaceholderType
-  {
-    PLACEHOLDER_TYPE_ACTIVE,
-    PLACEHOLDER_TYPE_INACTIVE,
-  };
-
-  /**
-   * @brief Enumeration for Font Size Type.
-   */
-  enum FontSizeType
-  {
-    POINT_SIZE, // The size of font in points.
-    PIXEL_SIZE  // The size of font in pixels.
-  };
-
-  struct NoTextTap
-  {
-    enum Action
-    {
-      NO_ACTION,           ///< Does no action if there is a tap on top of an area with no text.
-      HIGHLIGHT,           ///< Highlights the nearest text (at the beginning or end of the text) and shows the text's selection popup.
-      SHOW_SELECTION_POPUP ///< Shows the text's selection popup.
-    };
-  };
-
-  struct TextFitInfo
-  {
-    enum Property
-    {
-      TEXT_FIT_ENABLE,
-      TEXT_FIT_MIN_SIZE,
-      TEXT_FIT_MAX_SIZE,
-      TEXT_FIT_STEP_SIZE,
-      TEXT_FIT_FONT_SIZE_TYPE
-    };
-  };
-
-public: // Constructor.
-  /**
-   * @brief Create a new instance of a Controller.
-   *
-   * @return A pointer to a new Controller.
-   */
-  static ControllerPtr New()
-  {
-    return ControllerPtr(new Controller());
-  }
-
-  /**
-   * @brief Create a new instance of a Controller.
-   *
-   * @param[in] controlInterface The control's interface.
-   *
-   * @return A pointer to a new Controller.
-   */
-  static ControllerPtr New(ControlInterface* controlInterface)
-  {
-    return ControllerPtr(new Controller(controlInterface));
-  }
-
-  /**
-   * @brief Create a new instance of a Controller.
-   *
-   * @param[in] controlInterface The control's interface.
-   * @param[in] editableControlInterface The editable control's interface.
-   * @param[in] selectableControlInterface The selectable control's interface.
-   * @param[in] anchorControlInterface The anchor control's interface.
-   *
-   * @return A pointer to a new Controller.
-   */
-  static ControllerPtr New(ControlInterface*           controlInterface,
-                           EditableControlInterface*   editableControlInterface,
-                           SelectableControlInterface* selectableControlInterface,
-                           AnchorControlInterface*     anchorControlInterface)
-  {
-    return ControllerPtr(new Controller(controlInterface,
-                                        editableControlInterface,
-                                        selectableControlInterface,
-                                        anchorControlInterface));
-  }
-
-public: // Configure the text controller.
-  /**
-   * @brief Called to enable text input.
-   *
-   * @note Selectable or editable controls should call this once after Controller::New().
-   * @param[in] decorator Used to create cursor, selection handle decorations etc.
-   * @param[in] inputMethodContext Used to manager ime.
-   */
-  void EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext);
-
-  /**
-   * @brief Used to switch between bitmap & vector based glyphs
-   *
-   * @param[in] glyphType The type of glyph; note that metrics for bitmap & vector based glyphs are different.
-   */
-  void SetGlyphType(TextAbstraction::GlyphType glyphType);
-
-  /**
-   * @brief Enables/disables the mark-up processor.
-   *
-   * By default is disabled.
-   *
-   * @param[in] enable Whether to enable the mark-up processor.
-   */
-  void SetMarkupProcessorEnabled(bool enable);
-
-  /**
-   * @brief Retrieves whether the mark-up processor is enabled.
-   *
-   * By default is disabled.
-   *
-   * @return @e true if the mark-up processor is enabled, otherwise returns @e false.
-   */
-  bool IsMarkupProcessorEnabled() const;
-
-  /**
-   * @brief Retrieves whether the current text contains anchors.
-   *
-   * @return @e true if the current text contains anchors. @e false.
-   */
-  bool HasAnchors() const;
-
-  /**
-   * @brief Enables/disables the auto text scrolling
-   *
-   * By default is disabled.
-   *
-   * @param[in] enable Whether to enable the auto scrolling
-   */
-  void SetAutoScrollEnabled(bool enable);
-
-  /**
-   * @brief Whether the auto scrolling texture exceed max texture.
-   *
-   * By default is false.
-   *
-   * @param[in] exceed Whether the auto scrolling texture exceed max texture.
-   */
-  void SetAutoScrollMaxTextureExceeded(bool exceed);
-
-  /**
-   * @brief Retrieves whether auto text scrolling is enabled.
-   *
-   * By default is disabled.
-   *
-   * @return @e true if auto scrolling is enabled, otherwise returns @e false.
-   */
-  bool IsAutoScrollEnabled() const;
-
-  /**
-   * @brief Get direction of the text from the first line of text,
-   * @return bool rtl (right to left) is true
-   */
-  CharacterDirection GetAutoScrollDirection() const;
-
-  /**
-   * @brief Get the alignment offset of the first line of text.
-   *
-   * @return The alignment offset.
-   */
-  float GetAutoScrollLineAlignment() const;
-
-  /**
-   * @brief Enables the horizontal scrolling.
-   *
-   * @param[in] enable Whether to enable the horizontal scrolling.
-   */
-  void SetHorizontalScrollEnabled(bool enable);
-
-  /**
-   * @brief Retrieves whether the horizontal scrolling is enabled.
-   *
-   * @return @e true if the horizontal scrolling is enabled, otherwise it returns @e false.
-   */
-  bool IsHorizontalScrollEnabled() const;
-
-  /**
-   * @brief Enables the vertical scrolling.
-   *
-   * @param[in] enable Whether to enable the vertical scrolling.
-   */
-  void SetVerticalScrollEnabled(bool enable);
-
-  /**
-   * @brief Retrieves whether the verticall scrolling is enabled.
-   *
-   * @return @e true if the vertical scrolling is enabled, otherwise it returns @e false.
-   */
-  bool IsVerticalScrollEnabled() const;
-
-  /**
-   * @brief Enables the smooth handle panning.
-   *
-   * @param[in] enable Whether to enable the smooth handle panning.
-   */
-  void SetSmoothHandlePanEnabled(bool enable);
-
-  /**
-   * @brief Retrieves whether the smooth handle panning is enabled.
-   *
-   * @return @e true if the smooth handle panning is enabled.
-   */
-  bool IsSmoothHandlePanEnabled() const;
-
-  /**
-   * @brief Sets the maximum number of characters that can be inserted into the TextModel
-   *
-   * @param[in] maxCharacters maximum number of characters to be accepted
-   */
-  void SetMaximumNumberOfCharacters(Length maxCharacters);
-
-  /**
-   * @brief Sets the maximum number of characters that can be inserted into the TextModel
-   *
-   * @param[in] maxCharacters maximum number of characters to be accepted
-   */
-  int GetMaximumNumberOfCharacters();
-
-  /**
-   * @brief Called to enable/disable cursor blink.
-   *
-   * @note Only editable controls should calls this.
-   * @param[in] enabled Whether the cursor should blink or not.
-   */
-  void SetEnableCursorBlink(bool enable);
-
-  /**
-   * @brief Query whether cursor blink is enabled.
-   *
-   * @return Whether the cursor should blink or not.
-   */
-  bool GetEnableCursorBlink() const;
-
-  /**
-   * @brief Whether to enable the multi-line layout.
-   *
-   * @param[in] enable \e true enables the multi-line (by default)
-   */
-  void SetMultiLineEnabled(bool enable);
-
-  /**
-   * @return Whether the multi-line layout is enabled.
-   */
-  bool IsMultiLineEnabled() const;
-
-  /**
-   * @brief Sets the text's horizontal alignment.
-   *
-   * @param[in] alignment The horizontal alignment.
-   */
-  void SetHorizontalAlignment(HorizontalAlignment::Type alignment);
-
-  /**
-   * @copydoc ModelInterface::GetHorizontalAlignment()
-   */
-  HorizontalAlignment::Type GetHorizontalAlignment() const;
-
-  /**
-   * @brief Sets the text's vertical alignment.
-   *
-   * @param[in] alignment The vertical alignment.
-   */
-  void SetVerticalAlignment(VerticalAlignment::Type alignment);
-
-  /**
-   * @copydoc ModelInterface::GetVerticalAlignment()
-   */
-  VerticalAlignment::Type GetVerticalAlignment() const;
-
-  /**
-   * @brief Sets the text's wrap mode
-   * @param[in] text wrap mode The unit of wrapping
-   */
-  void SetLineWrapMode(Text::LineWrap::Mode textWarpMode);
-
-  /**
-   * @brief Retrieve text wrap mode previously set.
-   * @return text wrap mode
-   */
-  Text::LineWrap::Mode GetLineWrapMode() const;
-
-  /**
-   * @brief Enable or disable the text elide.
-   *
-   * @param[in] enabled Whether to enable the text elide.
-   */
-  void SetTextElideEnabled(bool enabled);
-
-  /**
-   * @copydoc ModelInterface::IsTextElideEnabled()
-   */
-  bool IsTextElideEnabled() const;
-
-  /**
-   * @brief Enable or disable the text fit.
-   *
-   * @param[in] enabled Whether to enable the text fit.
-   */
-  void SetTextFitEnabled(bool enabled);
-
-  /**
-   * @brief Whether the text fit is enabled or not.
-   *
-   * @return True if the text fit is enabled
-   */
-  bool IsTextFitEnabled() const;
-
-  /**
-   * @brief Sets minimum size valid for text fit.
-   *
-   * @param[in] minimum size value.
-   * @param[in] type The font size type is point size or pixel size
-   */
-  void SetTextFitMinSize(float pointSize, FontSizeType type);
-
-  /**
-   * @brief Retrieves the minimum point size valid for text fit.
-   *
-   * @return The minimum point size valid for text fit
-   */
-  float GetTextFitMinSize() const;
-
-  /**
-   * @brief Sets maximum size valid for text fit.
-   *
-   * @param[in] maximum size value.
-   * @param[in] type The font size type is point size or pixel size
-   */
-  void SetTextFitMaxSize(float pointSize, FontSizeType type);
-
-  /**
-   * @brief Retrieves the maximum point size valid for text fit.
-   *
-   * @return The maximum point size valid for text fit
-   */
-  float GetTextFitMaxSize() const;
-
-  /**
-   * @brief Sets step size for font increase valid for text fit.
-   *
-   * @param[in] step size value.
-   * @param[in] type The font size type is point size or pixel size
-   */
-  void SetTextFitStepSize(float step, FontSizeType type);
-
-  /**
-   * @brief Retrieves the step point size valid for text fit.
-   *
-   * @return The step point size valid for text fit
-   */
-  float GetTextFitStepSize() const;
-
-  /**
-   * @brief Sets content size valid for text fit.
-   *
-   * @param[in] Content size value.
-   */
-  void SetTextFitContentSize(Vector2 size);
-
-  /**
-   * @brief Retrieves the content size valid for text fit.
-   *
-   * @return The content size valid for text fit
-   */
-  Vector2 GetTextFitContentSize() const;
-
-  /**
-   * @brief Retrieve the fited point size.
-   *
-   * @return The fited point size.
-   */
-  float GetTextFitPointSize() const;
-
-  /**
-   * @brief Sets whether the text fit properties have changed.
-   *
-   * @param[in] changed Whether to changed the text fit.
-   */
-  void SetTextFitChanged(bool changed);
-
-  /**
-   * @brief Whether the text fit properties are changed or not.
-   *
-   * @return True if the text fit properties are changed
-   */
-  bool IsTextFitChanged() const;
-
-  /**
-   * @brief Sets disabled color opacity.
-   *
-   * @param[in] opacity The color opacity value in disabled state.
-   */
-  void SetDisabledColorOpacity(float opacity);
-
-  /**
-   * @brief Retrieves the disabled color opacity.
-   *
-   * @return The disabled color opacity value for disabled state.
-   */
-  float GetDisabledColorOpacity() const;
-
-  /**
-   * @brief Enable or disable the placeholder text elide.
-   * @param enabled Whether to enable the placeholder text elide.
-   */
-  void SetPlaceholderTextElideEnabled(bool enabled);
-
-  /**
-   * @brief Whether the placeholder text elide property is enabled.
-   * @return True if the placeholder text elide property is enabled, false otherwise.
-   */
-  bool IsPlaceholderTextElideEnabled() const;
-
-  /**
-   * @brief Enable or disable the text selection.
-   * @param[in] enabled Whether to enable the text selection.
-   */
-  void SetSelectionEnabled(bool enabled);
-
-  /**
-   * @brief Whether the text selection is enabled or not.
-   * @return True if the text selection is enabled
-   */
-  bool IsSelectionEnabled() const;
-
-  /**
-   * @brief Enable or disable the text selection using Shift key.
-   * @param enabled Whether to enable the text selection using Shift key
-   */
-  void SetShiftSelectionEnabled(bool enabled);
-
-  /**
-   * @brief Whether the text selection using Shift key is enabled or not.
-   * @return True if the text selection using Shift key is enabled
-   */
-  bool IsShiftSelectionEnabled() const;
-
-  /**
-   * @brief Enable or disable the grab handles for text selection.
-   *
-   * @param[in] enabled Whether to enable the grab handles
-   */
-  void SetGrabHandleEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether the grab handles are enabled.
-   *
-   * @return True if the grab handles are enabled
-   */
-  bool IsGrabHandleEnabled() const;
-
-  /**
-   * @brief Enable or disable the grab handles for text selection.
-   *
-   * @param[in] enabled Whether to enable the grab handles
-   */
-  void SetGrabHandlePopupEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether the grab handles are enabled.
-   *
-   * @return True if the grab handles are enabled
-   */
-  bool IsGrabHandlePopupEnabled() const;
-
-  /**
-   * @brief Sets input type to password
-   *
-   * @note The string is displayed hidden character
-   *
-   * @param[in] passwordInput True if password input is enabled.
-   */
-  void SetInputModePassword(bool passwordInput);
-
-  /**
-   * @brief Returns whether the input mode type is set as password.
-   *
-   * @return True if input mode type is password
-   */
-  bool IsInputModePassword();
-
-  /**
-   * @brief Sets the action when there is a double tap event on top of a text area with no text.
-   *
-   * @param[in] action The action to do.
-   */
-  void SetNoTextDoubleTapAction(NoTextTap::Action action);
-
-  /**
-   * @brief Retrieves the action when there is a double tap event on top of a text area with no text.
-   *
-   * @return The action to do.
-   */
-  NoTextTap::Action GetNoTextDoubleTapAction() const;
-
-  /**
-   * @briefSets the action when there is a long press event on top of a text area with no text.
-   *
-   * @param[in] action The action to do.
-   */
-  void SetNoTextLongPressAction(NoTextTap::Action action);
-
-  /**
-   * @brief Retrieves the action when there is a long press event on top of a text area with no text.
-   *
-   * @return The action to do.
-   */
-  NoTextTap::Action GetNoTextLongPressAction() const;
-
-  /**
-   * @brief Query if Underline settings were provided by string or map
-   * @return bool true if set by string
-   */
-  bool IsUnderlineSetByString();
-
-  /**
-   * Set method underline setting were set by
-   * @param[in] bool, true if set by string
-   */
-  void UnderlineSetByString(bool setByString);
-
-  /**
-   * @brief Query if shadow settings were provided by string or map
-   * @return bool true if set by string
-   */
-  bool IsShadowSetByString();
-
-  /**
-   * Set method shadow setting were set by
-   * @param[in] bool, true if set by string
-   */
-  void ShadowSetByString(bool setByString);
-
-  /**
-   * @brief Query if outline settings were provided by string or map
-   * @return bool true if set by string
-   */
-  bool IsOutlineSetByString();
-
-  /**
-   * Set method outline setting were set by
-   * @param[in] bool, true if set by string
-   */
-  void OutlineSetByString(bool setByString);
-
-  /**
-   * @brief Query if font style settings were provided by string or map
-   * @return bool true if set by string
-   */
-  bool IsFontStyleSetByString();
-
-  /**
-   * Set method font style setting were set by
-   * @param[in] bool, true if set by string
-   */
-  void FontStyleSetByString(bool setByString);
-
-  /**
-   * @brief Query if Strikethrough settings were provided by string or map
-   * @return bool true if set by string
-   */
-  bool IsStrikethroughSetByString();
-
-  /**
-   * Set method Strikethrough setting were set by
-   * @param[in] bool, true if set by string
-   */
-  void StrikethroughSetByString(bool setByString);
-
-  /**
-   * @brief Set the override used for strikethrough height, 0 indicates height will be supplied by font metrics
-   *
-   * @param[in] height The height in pixels of the strikethrough
-   */
-  void SetStrikethroughHeight(float height);
-
-  /**
-   * @brief Retrieves the override height of an strikethrough, 0 indicates height is supplied by font metrics
-   *
-   * @return The height of the strikethrough, or 0 if height is not overrided.
-   */
-  float GetStrikethroughHeight() const;
-
-  /**
-   * @brief Set the strikethrough color.
-   *
-   * @param[in] color color of strikethrough.
-   */
-  void SetStrikethroughColor(const Vector4& color);
-
-  /**
-   * @brief Retrieve the strikethrough color.
-   *
-   * @return The strikethrough color.
-   */
-  const Vector4& GetStrikethroughColor() const;
-
-  /**
-   * @brief Set the strikethrough enabled flag.
-   *
-   * @param[in] enabled The strikethrough enabled flag.
-   */
-  void SetStrikethroughEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether the text has a strikethrough or not.
-   *
-   * @return The strikethrough state.
-   */
-  bool IsStrikethroughEnabled() const;
-
-public: // Update.
-  /**
-   * @brief Replaces any text previously set.
-   *
-   * @note This will be converted into UTF-32 when stored in the text model.
-   * @param[in] text A string of UTF-8 characters.
-   */
-  void SetText(const std::string& text);
-
-  /**
-   * @brief Retrieve any text previously set.
-   *
-   * @param[out] text A string of UTF-8 characters.
-   */
-  void GetText(std::string& text) const;
-
-  /**
-   * @brief Replaces any placeholder text previously set.
-   *
-   * @param[in] type Different placeholder-text can be shown when the control is active/inactive.
-   * @param[in] text A string of UTF-8 characters.
-   */
-  void SetPlaceholderText(PlaceholderType type, const std::string& text);
-
-  /**
-   * @brief Retrieve any placeholder text previously set.
-   *
-   * @param[in] type Different placeholder-text can be shown when the control is active/inactive.
-   * @param[out] A string of UTF-8 characters.
-   */
-  void GetPlaceholderText(PlaceholderType type, std::string& text) const;
-
-  /**
-   * @ brief Update the text after a font change
-   * @param[in] newDefaultFont The new font to change to
-   */
-  void UpdateAfterFontChange(const std::string& newDefaultFont);
-
-  /**
-   * @brief The method acquires currently selected text
-   * @param selectedText variable to place selected text in
-   */
-  void RetrieveSelection(std::string& selectedText) const;
-
-  /**
-   * @brief The method sets selection in given range
-   * @param start index of first character
-   * @param end   index of first character after selection
-   */
-  void SetSelection(int start, int end);
-
-  /**
-   * @brief This method retrieve indexes of current selection
-   *
-   * @return a pair, where first element is left index of selection and second is the right one
-   */
-  std::pair<int, int> GetSelectionIndexes() const;
-
-  /**
-   * Place string in system clipboard
-   * @param source std::string
-   */
-  void CopyStringToClipboard(const std::string& source);
-
-  /**
-   * Place currently selected text in system clipboard
-   * @param deleteAfterSending flag pointing if text should be deleted after sending to clipboard
-   */
-  void SendSelectionToClipboard(bool deleteAfterSending);
-
-public: // Default style & Input style
-  /**
-   * @brief Set the default font family.
-   *
-   * @param[in] defaultFontFamily The default font family.
-   */
-  void SetDefaultFontFamily(const std::string& defaultFontFamily);
-
-  /**
-   * @brief Retrieve the default font family.
-   *
-   * @return The default font family.
-   */
-  const std::string& GetDefaultFontFamily() const;
-
-  /**
-   * @brief Sets the placeholder text font family.
-   * @param[in] placeholderTextFontFamily The placeholder text font family.
-   */
-  void SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily);
-
-  /**
-   * @brief Retrieves the placeholder text font family.
-   *
-   * @return The placeholder text font family
-   */
-  const std::string& GetPlaceholderFontFamily() const;
-
-  /**
-   * @brief Sets the default font weight.
-   *
-   * @param[in] weight The font weight.
-   */
-  void SetDefaultFontWeight(FontWeight weight);
-
-  /**
-   * @brief Whether the font's weight has been defined.
-   */
-  bool IsDefaultFontWeightDefined() const;
-
-  /**
-   * @brief Retrieves the default font weight.
-   *
-   * @return The default font weight.
-   */
-  FontWeight GetDefaultFontWeight() const;
-
-  /**
-   * @brief Sets the placeholder text font weight.
-   *
-   * @param[in] weight The font weight
-   */
-  void SetPlaceholderTextFontWeight(FontWeight weight);
-
-  /**
-   * @brief Whether the font's weight has been defined.
-   *
-   * @return True if the placeholder text font weight is defined
-   */
-  bool IsPlaceholderTextFontWeightDefined() const;
-
-  /**
-   * @brief Retrieves the placeholder text font weight.
-   *
-   * @return The placeholder text font weight
-   */
-  FontWeight GetPlaceholderTextFontWeight() const;
-
-  /**
-   * @brief Sets the default font width.
-   *
-   * @param[in] width The font width.
-   */
-  void SetDefaultFontWidth(FontWidth width);
-
-  /**
-   * @brief Whether the font's width has been defined.
-   */
-  bool IsDefaultFontWidthDefined() const;
-
-  /**
-   * @brief Retrieves the default font width.
-   *
-   * @return The default font width.
-   */
-  FontWidth GetDefaultFontWidth() const;
-
-  /**
-   * @brief Sets the placeholder text font width.
-   *
-   * @param[in] width The font width
-   */
-  void SetPlaceholderTextFontWidth(FontWidth width);
-
-  /**
-   * @brief Whether the font's width has been defined.
-   *
-   * @return True if the placeholder text font width is defined
-   */
-  bool IsPlaceholderTextFontWidthDefined() const;
-
-  /**
-   * @brief Retrieves the placeholder text font width.
-   *
-   * @return The placeholder text font width
-   */
-  FontWidth GetPlaceholderTextFontWidth() const;
-
-  /**
-   * @brief Sets the default font slant.
-   *
-   * @param[in] slant The font slant.
-   */
-  void SetDefaultFontSlant(FontSlant slant);
-
-  /**
-   * @brief Whether the font's slant has been defined.
-   */
-  bool IsDefaultFontSlantDefined() const;
-
-  /**
-   * @brief Retrieves the default font slant.
-   *
-   * @return The default font slant.
-   */
-  FontSlant GetDefaultFontSlant() const;
-
-  /**
-   * @brief Sets the placeholder text font slant.
-   *
-   * @param[in] slant The font slant
-   */
-  void SetPlaceholderTextFontSlant(FontSlant slant);
-
-  /**
-   * @brief Whether the font's slant has been defined.
-   *
-   * @return True if the placeholder text font slant is defined
-   */
-  bool IsPlaceholderTextFontSlantDefined() const;
-
-  /**
-   * @brief Retrieves the placeholder text font slant.
-   *
-   * @return The placeholder text font slant
-   */
-  FontSlant GetPlaceholderTextFontSlant() const;
-
-  /**
-   * @brief Set the default font size.
-   *
-   * @param[in] fontSize The default font size
-   * @param[in] type The font size type is point size or pixel size
-   */
-  void SetDefaultFontSize(float fontSize, FontSizeType type);
-
-  /**
-   * @brief Retrieve the default point size.
-   *
-   * @param[in] type The font size type
-   * @return The default point size.
-   */
-  float GetDefaultFontSize(FontSizeType type) const;
-
-  /**
-   * @brief Set the font size scale.
-   *
-   * @param[in] scale The font size scale
-   */
-  void SetFontSizeScale(float scale);
-
-  /**
-   * @brief Get the font size scale.
-   *
-   * @return The font size scale.
-   */
-  float GetFontSizeScale() const;
-
-  /**
-   * @brief Set the font size scale enabled flag.
-   *
-   * @param[in] enabled whether to enable the font size scale.
-   */
-  void SetFontSizeScaleEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether the font size scale is enabled or not.
-   *
-   * @return @e true if the font size scale is enabled, otherwise returns @e false.
-   */
-  bool IsFontSizeScaleEnabled() const;
-
-  /**
-   * @brief Sets the Placeholder text font size.
-   * @param[in] fontSize The placeholder text font size
-   * @param[in] type The font size type is point size or pixel size
-   */
-  void SetPlaceholderTextFontSize(float fontSize, FontSizeType type);
-
-  /**
-   * @brief Retrieves the Placeholder text font size.
-   * @param[in] type The font size type
-   * @return The placeholder font size
-   */
-  float GetPlaceholderTextFontSize(FontSizeType type) const;
-
-  /**
-   * @brief Sets the text's default color.
-   *
-   * @param color The default color.
-   */
-  void SetDefaultColor(const Vector4& color);
-
-  /**
-   * @brief Retrieves the text's default color.
-   *
-   * @return The default color.
-   */
-  const Vector4& GetDefaultColor() const;
-
-  /**
-   * @brief Sets the user interaction enabled.
-   *
-   * @param enabled whether to enable the user interaction.
-   */
-  void SetUserInteractionEnabled(bool enabled);
-
-  /**
-   * @brief Whether the user interaction is enabled.
-   *
-   * @return true if the user interaction is enabled, false otherwise.
-   */
-  bool IsUserInteractionEnabled() const;
-
-  /**
-   * @brief Set the text color
-   *
-   * @param textColor The text color
-   */
-  void SetPlaceholderTextColor(const Vector4& textColor);
-
-  /**
-   * @brief Retrieve the text color
-   *
-   * @return The text color
-   */
-  const Vector4& GetPlaceholderTextColor() const;
-
-  /**
-   * @brief Set the shadow offset.
-   *
-   * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow.
-   */
-  void SetShadowOffset(const Vector2& shadowOffset);
-
-  /**
-   * @brief Retrieve the shadow offset.
-   *
-   * @return The shadow offset.
-   */
-  const Vector2& GetShadowOffset() const;
-
-  /**
-   * @brief Set the shadow color.
-   *
-   * @param[in] shadowColor The shadow color.
-   */
-  void SetShadowColor(const Vector4& shadowColor);
-
-  /**
-   * @brief Retrieve the shadow color.
-   *
-   * @return The shadow color.
-   */
-  const Vector4& GetShadowColor() const;
-
-  /**
-   * @brief Set the shadow blur radius.
-   *
-   * @param[in] shadowBlurRadius The shadow blur radius, 0,0 indicates no blur.
-   */
-  void SetShadowBlurRadius(const float& shadowBlurRadius);
-
-  /**
-   * @brief Retrieve the shadow blur radius.
-   *
-   * @return The shadow blur radius.
-   */
-  const float& GetShadowBlurRadius() const;
-
-  /**
-   * @brief Set the underline color.
-   *
-   * @param[in] color color of underline.
-   */
-  void SetUnderlineColor(const Vector4& color);
-
-  /**
-   * @brief Retrieve the underline color.
-   *
-   * @return The underline color.
-   */
-  const Vector4& GetUnderlineColor() const;
-
-  /**
-   * @brief Set the underline enabled flag.
-   *
-   * @param[in] enabled The underline enabled flag.
-   */
-  void SetUnderlineEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether the text is underlined or not.
-   *
-   * @return The underline state.
-   */
-  bool IsUnderlineEnabled() const;
-
-  /**
-   * @brief Set the override used for underline height, 0 indicates height will be supplied by font metrics
-   *
-   * @param[in] height The height in pixels of the underline
-   */
-  void SetUnderlineHeight(float height);
-
-  /**
-   * @brief Retrieves the override height of an underline, 0 indicates height is supplied by font metrics
-   *
-   * @return The height of the underline, or 0 if height is not overrided.
-   */
-  float GetUnderlineHeight() const;
-
-  /**
-   * @brief Sets the underline type.
-   * @param[in] type The underline type.
-   */
-  void SetUnderlineType(Text::Underline::Type type);
-
-  /**
-   * @brief Retrieve underline type.
-   * @return The underline type.
-   */
-  Text::Underline::Type GetUnderlineType() const;
-
-  /**
-   * @brief Set the width of the dashes of the dashed underline.
-   *
-   * @param[in] width The width in pixels of the dashes of the dashed underline.
-   */
-  void SetDashedUnderlineWidth(float width);
-
-  /**
-   * @brief Retrieves the width of the dashes of the dashed underline.
-   *
-   * @return The width of the dashes of the dashed underline.
-   */
-  float GetDashedUnderlineWidth() const;
-
-  /**
-   * @brief Set the gap between the dashes of the dashed underline.
-   *
-   * @param[in] gap The gap between the dashes of the dashed underline.
-   */
-  void SetDashedUnderlineGap(float gap);
-
-  /**
-   * @brief Retrieves the gap between the dashes of the dashed underline.
-   *
-   * @return The The gap between the dashes of the dashed underline.
-   */
-  float GetDashedUnderlineGap() const;
-
-  /**
-   * @brief Set the outline color.
-   *
-   * @param[in] color color of outline.
-   */
-  void SetOutlineColor(const Vector4& color);
-
-  /**
-   * @brief Retrieve the outline color.
-   *
-   * @return The outline color.
-   */
-  const Vector4& GetOutlineColor() const;
-
-  /**
-   * @brief Set the outline width
-   *
-   * @param[in] width The width in pixels of the outline, 0 indicates no outline
-   */
-  void SetOutlineWidth(uint16_t width);
-
-  /**
-   * @brief Retrieves the width of an outline
-   *
-   * @return The width of the outline.
-   */
-  uint16_t GetOutlineWidth() const;
-
-  /**
-   * @brief Set the background color.
-   *
-   * @param[in] color color of background.
-   */
-  void SetBackgroundColor(const Vector4& color);
-
-  /**
-   * @brief Retrieve the background color.
-   *
-   * @return The background color.
-   */
-  const Vector4& GetBackgroundColor() const;
-
-  /**
-   * @brief Set the background enabled flag.
-   *
-   * @param[in] enabled The background enabled flag.
-   */
-  void SetBackgroundEnabled(bool enabled);
-
-  /**
-   * @brief Returns whether to enable text background or not.
-   *
-   * @return Whether text background is enabled.
-   */
-  bool IsBackgroundEnabled() const;
-
-  /**
-   * @brief Sets the emboss's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] embossProperties The emboss's properties string.
-   */
-  void SetDefaultEmbossProperties(const std::string& embossProperties);
-
-  /**
-   * @brief Retrieves the emboss's properties string.
-   *
-   * @return The emboss's properties string.
-   */
-  const std::string& GetDefaultEmbossProperties() const;
-
-  /**
-   * @brief Sets the outline's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] outlineProperties The outline's properties string.
-   */
-  void SetDefaultOutlineProperties(const std::string& outlineProperties);
-
-  /**
-   * @brief Retrieves the outline's properties string.
-   *
-   * @return The outline's properties string.
-   */
-  const std::string& GetDefaultOutlineProperties() const;
-
-  /**
-   * @brief Sets the default line spacing.
-   *
-   * @param[in] lineSpacing The line spacing.
-   *
-   * @return True if lineSpacing has been updated, false otherwise
-   */
-  bool SetDefaultLineSpacing(float lineSpacing);
-
-  /**
-   * @brief Retrieves the default line spacing.
-   *
-   * @return The line spacing.
-   */
-  float GetDefaultLineSpacing() const;
-
-  /**
-   * @brief Sets the default line size.
-   *
-   * @param[in] lineSize The line size.
-   *
-   * @return True if lineSize has been updated, false otherwise
-   */
-  bool SetDefaultLineSize(float lineSize);
-
-  /**
-   * @brief Retrieves the default line size.
-   *
-   * @return The line size.
-   */
-  float GetDefaultLineSize() const;
-
-  /**
-   * @brief Sets the relative line size to the original line size.
-   *
-   * @param[in] relativeLineSize The relativeline size.
-   *
-   * @return True if relativeLineSize has been updated, false otherwise
-   */
-  bool SetRelativeLineSize(float lineSize);
-
-  /**
-   * @brief Retrieves the relative line size.
-   *
-   * @return The relative line size.
-   */
-  float GetRelativeLineSize() const;
-
-  /**
-   * @brief Sets the input text's color.
-   *
-   * @param[in] color The input text's color.
-   */
-  void SetInputColor(const Vector4& color);
-
-  /**
-   * @brief Retrieves the input text's color.
-   *
-   * @return The input text's color.
-   */
-  const Vector4& GetInputColor() const;
-
-  /**
-   * @brief Sets the input text's font family name.
-   *
-   * @param[in] fontFamily The text's font family name.
-   */
-  void SetInputFontFamily(const std::string& fontFamily);
-
-  /**
-   * @brief Retrieves the input text's font family name.
-   *
-   * @return The input text's font family name.
-   */
-  const std::string& GetInputFontFamily() const;
-
-  /**
-   * @brief Sets the input font's weight.
-   *
-   * @param[in] weight The input font's weight.
-   */
-  void SetInputFontWeight(FontWeight weight);
-
-  /**
-   * @return Whether the font's weight has been defined.
-   */
-  bool IsInputFontWeightDefined() const;
-
-  /**
-   * @brief Retrieves the input font's weight.
-   *
-   * @return The input font's weight.
-   */
-  FontWeight GetInputFontWeight() const;
-
-  /**
-   * @brief Sets the input font's width.
-   *
-   * @param[in] width The input font's width.
-   */
-  void SetInputFontWidth(FontWidth width);
-
-  /**
-   * @return Whether the font's width has been defined.
-   */
-  bool IsInputFontWidthDefined() const;
-
-  /**
-   * @brief Retrieves the input font's width.
-   *
-   * @return The input font's width.
-   */
-  FontWidth GetInputFontWidth() const;
-
-  /**
-   * @brief Sets the input font's slant.
-   *
-   * @param[in] slant The input font's slant.
-   */
-  void SetInputFontSlant(FontSlant slant);
-
-  /**
-   * @return Whether the font's slant has been defined.
-   */
-  bool IsInputFontSlantDefined() const;
-
-  /**
-   * @brief Retrieves the input font's slant.
-   *
-   * @return The input font's slant.
-   */
-  FontSlant GetInputFontSlant() const;
-
-  /**
-   * @brief Sets the input font's point size.
-   *
-   * @param[in] size The input font's point size.
-   */
-  void SetInputFontPointSize(float size);
-
-  /**
-   * @brief Retrieves the input font's point size.
-   *
-   * @return The input font's point size.
-   */
-  float GetInputFontPointSize() const;
-
-  /**
-   * @brief Sets the input line spacing.
-   *
-   * @param[in] lineSpacing The line spacing.
-   */
-  void SetInputLineSpacing(float lineSpacing);
-
-  /**
-   * @brief Retrieves the input line spacing.
-   *
-   * @return The line spacing.
-   */
-  float GetInputLineSpacing() const;
-
-  /**
-   * @brief Sets the input shadow's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] shadowProperties The shadow's properties string.
-   */
-  void SetInputShadowProperties(const std::string& shadowProperties);
-
-  /**
-   * @brief Retrieves the input shadow's properties string.
-   *
-   * @return The shadow's properties string.
-   */
-  const std::string& GetInputShadowProperties() const;
-
-  /**
-   * @brief Sets the input underline's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] underlineProperties The underline's properties string.
-   */
-  void SetInputUnderlineProperties(const std::string& underlineProperties);
-
-  /**
-   * @brief Retrieves the input underline's properties string.
-   *
-   * @return The underline's properties string.
-   */
-  const std::string& GetInputUnderlineProperties() const;
-
-  /**
-   * @brief Sets the input emboss's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] embossProperties The emboss's properties string.
-   */
-  void SetInputEmbossProperties(const std::string& embossProperties);
-
-  /**
-   * @brief Retrieves the input emboss's properties string.
-   *
-   * @return The emboss's properties string.
-   */
-  const std::string& GetInputEmbossProperties() const;
-
-  /**
-   * @brief Sets input the outline's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] outlineProperties The outline's properties string.
-   */
-  void SetInputOutlineProperties(const std::string& outlineProperties);
-
-  /**
-   * @brief Retrieves the input outline's properties string.
-   *
-   * @return The outline's properties string.
-   */
-  const std::string& GetInputOutlineProperties() const;
-
-  /**
-   * @brief Sets the input strikethrough's properties string.
-   *
-   * @note The string is stored to be recovered.
-   *
-   * @param[in] strikethroughProperties The strikethrough's properties string.
-   */
-  void SetInputStrikethroughProperties(const std::string& strikethroughProperties);
-
-  /**
-   * @brief Retrieves the input strikethrough's properties string.
-   *
-   * @return The strikethrough's properties string.
-   */
-  const std::string& GetInputStrikethroughProperties() const;
-
-  /**
-   * @brief Set the control's interface.
-   *
-   * @param[in] controlInterface The control's interface.
-   */
-  void SetControlInterface(ControlInterface* controlInterface);
-
-  /**
-   * @brief Set the anchor control's interface.
-   *
-   * @param[in] anchorControlInterface The control's interface.
-   */
-  void SetAnchorControlInterface(AnchorControlInterface* anchorControlInterface);
-
-  /**
-   * @brief Sets the character spacing.
-   *
-   * @note A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
-   *
-   * @param[in] characterSpacing The character spacing.
-   */
-  void SetCharacterSpacing(float characterSpacing);
-
-  /**
-   * @brief Retrieves the character spacing.
-   *
-   * @note A positive value will make the characters far apart (expanded) and a negative value will bring them closer (condensed).
-   *
-   * @return The character spacing.
-   */
-  const float GetCharacterSpacing() const;
-
-public: // Queries & retrieves.
-  /**
-   * @brief Return the layout engine.
-   *
-   * @return A reference to the layout engine.
-   */
-  Layout::Engine& GetLayoutEngine();
-
-  /**
-   * @brief Return a view of the text.
-   *
-   * @return A reference to the view.
-   */
-  View& GetView();
-
-  /**
-   * @copydoc Control::GetNaturalSize()
-   */
-  Vector3 GetNaturalSize();
-
-  /**
-   * @copydoc Control::GetHeightForWidth()
-   */
-  float GetHeightForWidth(float width);
-
-  /**
-   * @brief Calculates the point size for text for given layout()
-   */
-  void FitPointSizeforLayout(Size layoutSize);
-
-  /**
-   * @brief Checks if the point size fits within the layout size.
-   *
-   * @return Whether the point size fits within the layout size.
-   */
-  bool CheckForTextFit(float pointSize, Size& layoutSize);
-
-  /**
-   * @brief Retrieves the text's number of lines for a given width.
-   * @param[in] width The width of the text's area.
-   * @ return The number of lines.
-   */
-  int GetLineCount(float width);
-
-  /**
-   * @brief Retrieves the text's model.
-   *
-   * @return A pointer to the text's model.
-   */
-  const ModelInterface* const GetTextModel() const;
-
-  /**
-   * @brief Used to get scrolled distance by user input
-   *
-   * @return Distance from last scroll offset to new scroll offset
-   */
-  float GetScrollAmountByUserInput();
-
-  /**
-   * @brief Get latest scroll amount, control size and layout size
-   *
-   * This method is used to get information of control's scroll
-   * @param[out] scrollPosition The current scrolled position
-   * @param[out] controlHeight The size of a UI control
-   * @param[out] layoutHeight The size of a bounding box to layout text within.
-   *
-   * @return Whether the text scroll position is changed or not after last update.
-   */
-  bool GetTextScrollInfo(float& scrollPosition, float& controlHeight, float& layoutHeight);
-
-  /**
-   * @brief Used to set the hidden input option
-   */
-  void SetHiddenInputOption(const Property::Map& options);
-
-  /**
-   * @brief Used to get the hidden input option
-   */
-  void GetHiddenInputOption(Property::Map& options);
-
-  /**
-   * @brief Used to set the input filter option
-   */
-  void SetInputFilterOption(const Property::Map& options);
-
-  /**
-   * @brief Used to get the input filter option
-   */
-  void GetInputFilterOption(Property::Map& options);
-
-  /**
-   * @brief Sets the Placeholder Properties.
-   *
-   * @param[in] map The placeholder property map
-   */
-  void SetPlaceholderProperty(const Property::Map& map);
-
-  /**
-   * @brief Retrieves the Placeholder Property map.
-   *
-   * @param[out] map The property map
-   */
-  void GetPlaceholderProperty(Property::Map& map);
-
-  /**
-   * @brief Checks text direction.
-   * @return The text direction.
-   */
-  Toolkit::DevelText::TextDirection::Type GetTextDirection();
-
-  /**
-   * @brief Retrieves vertical line alignment
-   * @return The vertical line alignment
-   */
-  Toolkit::DevelText::VerticalLineAlignment::Type GetVerticalLineAlignment() const;
-
-  /**
-   * @brief Sets vertical line alignment
-   * @param[in] alignment The vertical line alignment for the text
-   */
-  void SetVerticalLineAlignment(Toolkit::DevelText::VerticalLineAlignment::Type alignment);
-
-  /**
-   * @brief Retrieves ellipsis position
-   * @return The ellipsis position
-   */
-  Toolkit::DevelText::EllipsisPosition::Type GetEllipsisPosition() const;
-
-  /**
-   * @brief Sets ellipsis position
-   * @param[in] ellipsisPosition The ellipsis position for the text
-   */
-  void SetEllipsisPosition(Toolkit::DevelText::EllipsisPosition::Type ellipsisPosition);
-
-  /**
-   * @brief Retrieves ignoreSpaceAfterText value from model
-   * @return The value of ignoreSpaceAfterText
-   */
-  bool IsIgnoreSpacesAfterText() const;
-
-  /**
-   * @brief Sets ignoreSpaceAfterText value to model
-   * @param[in] ignore The value of ignoreSpacesAfterText for the text
-   */
-  void SetIgnoreSpacesAfterText(bool ignore);
-
-  /**
-   * @brief Sets SetMatchLayoutDirection value to model
-   * @param[in] match The value of matchLayoutDirection for the text
-   */
-  void SetMatchLayoutDirection(DevelText::MatchLayoutDirection type);
-
-  /**
-   * @brief Retrieves matchLayoutDirection value from model
-   * @return The value of matchLayoutDirection
-   */
-  DevelText::MatchLayoutDirection GetMatchLayoutDirection() const;
-
-  /**
-   * @brief Sets layoutDirection type value.
-   * @param[in] layoutDirection The value of the layout direction type.
-   */
-  void SetLayoutDirection(Dali::LayoutDirection::Type layoutDirection);
-
-  /**
-   * @brief Gets layoutDirection type value.
-   * @param[in] actor The actor which will get the layout direction type.
-   * @return The value of the layout direction type.
-   */
-  Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
-
-  /**
-   * @brief Get the rendered size of a specific text range.
-   * if the requested text is at multilines, multiple sizes will be returned for each text located in a separate line.
-   * if a line contains characters with different directions, multiple sizes will be returned for each block of contiguous characters with the same direction.
-   *
-   * @param[in] startIndex start index of the text requested to calculate size for.
-   * @param[in] endIndex end index(included) of the text requested to calculate size for.
-   * @return list of sizes of the reuested text.
-   */
-  Vector<Vector2> GetTextSize(CharacterIndex startIndex, CharacterIndex endIndex);
-
-  /**
-   * @brief Get the top/left rendered position of a specific text range.
-   * if the requested text is at multilines, multiple positions will be returned for each text located in a separate line.
-   * if a line contains characters with different directions, multiple positions will be returned for each block of contiguous characters with the same direction.
-   *
-   * @param[in] startIndex start index of the text requested to get position to.
-   * @param[in] endIndex end index(included) of the text requested to get position to.
-   * @return list of positions of the requested text.
-   */
-  Vector<Vector2> GetTextPosition(CharacterIndex startIndex, CharacterIndex endIndex);
-
-  /**
-   * @brief Gets the bounding box of a specific text range.
-   *
-   * @param[in] startIndex start index of the text requested to get bounding box to.
-   * @param[in] endIndex end index(included) of the text requested to get bounding box to.
-   * @return bounding box of the requested text.
-   */
-  Rect<> GetTextBoundingRectangle(CharacterIndex startIndex, CharacterIndex endIndex);
-
-  /**
-   * @brief Sets the layout direction changed.
-   */
-  void ChangedLayoutDirection();
-
-  /**
-   * @brief Retrieves if showing real text or not.
-   * @return The value of showing real text.
-   */
-  bool IsShowingRealText() const;
-
-public: // Relayout.
-  /**
-   * @brief Triggers a relayout which updates View (if necessary).
-   *
-   * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation.
-   * @param[in] size A the size of a bounding box to layout text within.
-   * @param[in] layoutDirection The direction of the system language.
-   *
-   * @return Whether the text model or decorations were updated.
-   */
-  UpdateTextType Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection = Dali::LayoutDirection::LEFT_TO_RIGHT);
-
-  /**
-   * @brief Request a relayout using the ControlInterface.
-   */
-  void RequestRelayout();
-
-public: // Input style change signals.
-  /**
-   * @return Whether the queue of input style changed signals is empty.
-   */
-  bool IsInputStyleChangedSignalsQueueEmpty();
-
-  /**
-   * @brief Process all pending input style changed signals.
-   *
-   * Calls the Text::ControlInterface::InputStyleChanged() method which is overriden by the
-   * text controls. Text controls may send signals to state the input style has changed.
-   */
-  void ProcessInputStyleChangedSignals();
-
-public: // Text-input Event Queuing.
-  /**
-   * @brief Called by editable UI controls when keyboard focus is gained.
-   */
-  void KeyboardFocusGainEvent();
-
-  /**
-   * @brief Called by editable UI controls when focus is lost.
-   */
-  void KeyboardFocusLostEvent();
-
-  /**
-   * @brief Called by editable UI controls when key events are received.
-   *
-   * @param[in] event The key event.
-   * @param[in] type Used to distinguish between regular key events and InputMethodContext events.
-   */
-  bool KeyEvent(const Dali::KeyEvent& event);
-
-  /**
-   * @brief Called by anchor when a tap gesture occurs.
-   * @param[in] x The x position relative to the top-left of the parent control.
-   * @param[in] y The y position relative to the top-left of the parent control.
-   */
-  void AnchorEvent(float x, float y);
-
-  /**
-   * @brief Called by editable UI controls when a tap gesture occurs.
-   * @param[in] tapCount The number of taps.
-   * @param[in] x The x position relative to the top-left of the parent control.
-   * @param[in] y The y position relative to the top-left of the parent control.
-   */
-  void TapEvent(unsigned int tapCount, float x, float y);
-
-  /**
-   * @brief Called by editable UI controls when a pan gesture occurs.
-   *
-   * @param[in] state The state of the gesture.
-   * @param[in] displacement This distance panned since the last pan gesture.
-   */
-  void PanEvent(GestureState state, const Vector2& displacement);
-
-  /**
-   * @brief Called by editable UI controls when a long press gesture occurs.
-   *
-   * @param[in] state The state of the gesture.
-   * @param[in] x The x position relative to the top-left of the parent control.
-   * @param[in] y The y position relative to the top-left of the parent control.
-   */
-  void LongPressEvent(GestureState state, float x, float y);
-
-  /**
-   * @brief Used to get the Primary cursor position.
-   *
-   * @return Primary cursor position.
-   */
-  CharacterIndex GetPrimaryCursorPosition() const;
-
-  /**
-   * @brief Used to set the Primary cursor position.
-   *
-   * @param[in] index for the Primary cursor position.
-   * @param[in] focused true if UI control has gained focus to receive key event, false otherwise.
-   * @return[in] true if cursor position changed, false otherwise.
-   */
-  bool SetPrimaryCursorPosition(CharacterIndex index, bool focused);
-
-  /**
-   * @brief Creates a selection event.
-   *
-   * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed.
-   *
-   * @param[in] x The x position relative to the top-left of the parent control.
-   * @param[in] y The y position relative to the top-left of the parent control.
-   * @param[in] selection type like the whole text is selected or unselected.
-   */
-  void SelectEvent(float x, float y, SelectionType selection);
-
-  /**
-   * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
-   */
-  void SetTextSelectionRange(const uint32_t* start, const uint32_t* end);
-
-  /**
-   * @copydoc Text::SelectableControlInterface::GetTextSelectionRange()
-   */
-  Uint32Pair GetTextSelectionRange() const;
-
-  /**
-   * @copydoc Text::SelectableControlInterface::SelectWholeText()
-   */
-  void SelectWholeText();
-
-  /**
-   * @copydoc Text::EditableControlInterface::CopyText()
-   */
-  string CopyText();
-
-  /**
-   * @copydoc Text::EditableControlInterface::CutText()
-   */
-  string CutText();
-
-  /**
-   * @copydoc Text::EditableControlInterface::PasteText()
-   */
-  void PasteText();
-
-  /**
-   * @copydoc Text::SelectableControlInterface::SelectNone()
-   */
-  void SelectNone();
-
-  /**
-   * @copydoc Text::SelectableControlInterface::SelectText()
-   */
-  void SelectText(const uint32_t start, const uint32_t end);
-
-  /**
-   * @copydoc Text::SelectableControlInterface::GetSelectedText()
-   */
-  string GetSelectedText() const;
-
-  /**
-   * @copydoc Text::EditableControlInterface::IsEditable()
-   */
-  virtual bool IsEditable() const;
-
-  /**
-   * @copydoc Text::EditableControlInterface::SetEditable()
-   */
-  virtual void SetEditable(bool editable);
-
-  /**
-   * @copydoc Dali::Toolkit::Internal::TextEditor::ScrollBy()
-   */
-  virtual void ScrollBy(Vector2 scroll);
-
-  /**
-   * @brief Whether the text is scrollable.
-   * @return Returns true if the text is scrollable.
-   */
-  bool IsScrollable(const Vector2& displacement);
-
-  /**
-   * @copydoc Dali::Toolkit::Internal::TextEditor::GetHorizontalScrollPosition()
-   */
-  float GetHorizontalScrollPosition();
-
-  /**
-   * @copydoc Dali::Toolkit::Internal::TextEditor::GetVerticalScrollPosition()
-   */
-  float GetVerticalScrollPosition();
-
-  /**
-   * @brief Event received from input method context
-   *
-   * @param[in] inputMethodContext The input method context.
-   * @param[in] inputMethodContextEvent The event received.
-   * @return A data struture indicating if update is needed, cursor position and current text.
-   */
-  InputMethodContext::CallbackData OnInputMethodContextEvent(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent);
-
-  /**
-   * @brief Event from Clipboard notifying an Item has been selected for pasting
-   */
-  void PasteClipboardItemEvent();
-
-  /**
-   * @brief Return true when text control should clear key input focus when escape key is pressed.
-   *
-   * @return Whether text control should clear key input focus or not when escape key is pressed.
-   */
-  bool ShouldClearFocusOnEscape() const;
-
-  /**
-   * @brief Create an actor that renders the text background color
-   *
-   * @return the created actor or an empty handle if no background color needs to be rendered.
-   */
-  Actor CreateBackgroundActor();
-
-  /**
-   * @brief Used to reset the cursor position after setting a new text.
-   *
-   * @param[in] cursorIndex Where to place the cursor.
-   */
-  void ResetCursorPosition(CharacterIndex cursorIndex);
-
-  /**
-   * @brief The method acquires current position of cursor
-   * @return unsigned value with cursor position
-   */
-  CharacterIndex GetCursorPosition();
-
-  /**
-   * @brief Resets a provided vector with actors that marks the position of anchors in markup enabled text
-   *
-   * @param[out] anchorActors the vector of actor (empty collection if no anchors available).
-   */
-  void GetAnchorActors(std::vector<Toolkit::TextAnchor>& anchorActors);
-
-  /**
-   * @brief Return an index of first anchor in the anchor vector whose boundaries includes given character offset
-   *
-   * @param[in] characterOffset A position in text coords.
-   *
-   * @return the index in anchor vector (-1 if an anchor not found)
-   */
-  int GetAnchorIndex(size_t characterOffset);
-
-protected: // Inherit from Text::Decorator::ControllerInterface.
-  /**
-   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::GetTargetSize()
-   */
-  void GetTargetSize(Vector2& targetSize) override;
-
-  /**
-   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
-   */
-  void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) override;
-
-  /**
-   * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
-   */
-  void DecorationEvent(HandleType handle, HandleState state, float x, float y) override;
-
-protected: // Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
-  /**
-   * @copydoc Dali::Toolkit::TextSelectionPopup::TextPopupButtonCallbackInterface::TextPopupButtonTouched()
-   */
-  void TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button) override;
-
-protected: // Inherit from HiddenText.
-  /**
-   * @brief Invoked from HiddenText when showing time of the last character was expired
-   */
-  void DisplayTimeExpired() override;
-
-private: // Private contructors & copy operator.
-  /**
-   * @brief Private constructor.
-   */
-  Controller()
-  : Controller(nullptr, nullptr, nullptr, nullptr)
-  {
-  }
-
-  /**
-   * @brief Private constructor.
-   */
-  Controller(ControlInterface* controlInterface)
-  : Controller(controlInterface, nullptr, nullptr, nullptr)
-  {
-  }
-
-  /**
-   * @brief Private constructor.
-   */
-  Controller(ControlInterface*           controlInterface,
-             EditableControlInterface*   editableControlInterface,
-             SelectableControlInterface* selectableControlInterface,
-             AnchorControlInterface*     anchorControlInterface);
-
-  Controller(const Controller& handle) = delete;
-  Controller& operator=(const Controller& handle) = delete;
-
-protected: // Destructor.
-  /**
-   * @brief A reference counted object may only be deleted by calling Unreference().
-   */
-  virtual ~Controller();
-
-public:
-  struct Impl; ///< Made public for testing purposes
-
-private:
-  struct EventHandler;
-  struct InputFontHandler;
-  struct InputProperties;
-  struct PlaceholderHandler;
-  struct Relayouter;
-  struct TextUpdater;
-
-  Impl* mImpl;
-};
-
-} // namespace Dali::Toolkit::Text
-
-#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
index 90c570ac8fde2f1c49c23829a749652722512eb5..c15a11d0d0c272d2c03d2849827c2c3e80ee7d3f 100644 (file)
@@ -20,7 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/controls/text-controls/text-style-properties-devel.h>
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
 #include <dali-toolkit/internal/text/property-string-parser.h>
 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
 
index d87e8100436583e93d01e65097a1087045c19108..0ceeab3c0ca33f494253b8b53bfd789278c31b13 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/public-api/text/text-enumerations.h>
 #include <dali/devel-api/scripting/scripting.h>
 
index 117268ac31e6d4d32efa8d036664736eda816290..ce5e8608fab6f5ccf3f8e5b8a693e30ef79ae867 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -22,7 +22,7 @@
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/markup-processor/markup-processor-helper-functions.h>
 #include <dali-toolkit/internal/text/property-string-parser.h>
 
 namespace Dali
index c85ec5856d8be42f944c6c871c6dec3c009ef58a..e2955c7d3b8ec02fac226e1396e5b0d02fc76f54 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_TEXT_FONT_STYLE_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -22,7 +22,7 @@
 #include <dali/devel-api/scripting/scripting.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 
 namespace Dali
 {
index e4bf91c5b431577c9e1f50ac4bba87a1dde8cb17..fef3baa5938baca0bb61885bcec8c8a4e510ce5e 100644 (file)
@@ -25,7 +25,7 @@
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/rendering/styles/character-spacing-helper-functions.h>
-#include <dali-toolkit/internal/text/text-controller-impl-event-handler.h>
+#include <dali-toolkit/internal/text/controller/text-controller-impl-event-handler.h>
 
 using namespace Dali;
 
index 62032fd8274ea55514bca16db9ba4452c7bd7e67..a02100954a44a7b485a5008315709c20d12bb71a 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_TEXT_SELECTION_HANDLE_CONTROLLER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -21,7 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/cursor-helper-functions.h>
 #include <dali-toolkit/internal/text/decorator/text-decorator.h>
-#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 
 namespace Dali
 {
index 05d158586cafc344c1c660cc8007b7b53eeabaf5..c81fbcee1ebef46704546831cb2dd8f3aaae032f 100644 (file)
@@ -25,8 +25,8 @@
 #include <dali/public-api/rendering/visual-renderer.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/controller/text-controller.h>
 #include <dali-toolkit/internal/text/rendering/text-typesetter.h>
-#include <dali-toolkit/internal/text/text-controller.h>
 #include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>