Support Markup Underline attributes
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-effects-style.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19 #include <dali-toolkit/internal/text/text-effects-style.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/devel-api/controls/text-controls/text-style-properties-devel.h>
23 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
24 #include <dali-toolkit/internal/text/property-string-parser.h>
25 #include <dali-toolkit/internal/text/text-enumerations-impl.h>
26
27 namespace Dali
28 {
29 namespace Toolkit
30 {
31 namespace Text
32 {
33 namespace
34 {
35 const std::string COLOR_KEY("color");
36 const std::string OFFSET_KEY("offset");
37 const std::string BLUR_RADIUS_KEY("blurRadius");
38 const std::string WIDTH_KEY("width");
39 const std::string HEIGHT_KEY("height");
40 const std::string ENABLE_KEY("enable");
41 const std::string TYPE_KEY("type");
42 const std::string DASH_WIDTH_KEY("dashWidth");
43 const std::string DASH_GAP_KEY("dashGap");
44 const std::string TRUE_TOKEN("true");
45 const std::string FALSE_TOKEN("false");
46 } // namespace
47
48 bool ParseShadowProperties(const Property::Map& shadowPropertiesMap,
49                            bool&                colorDefined,
50                            Vector4&             color,
51                            bool&                offsetDefined,
52                            Vector2&             offset,
53                            bool&                blurRadiusDefined,
54                            float&               blurRadius)
55 {
56   const unsigned int numberOfItems = shadowPropertiesMap.Count();
57
58   // Parses and applies the style.
59   for(unsigned int index = 0u; index < numberOfItems; ++index)
60   {
61     const KeyValuePair& valueGet = shadowPropertiesMap.GetKeyValue(index);
62
63     if((DevelText::Shadow::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
64     {
65       /// Color key.
66       colorDefined = true;
67
68       if(valueGet.second.GetType() == Dali::Property::STRING)
69       {
70         const std::string colorStr = valueGet.second.Get<std::string>();
71         Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
72       }
73       else
74       {
75         color = valueGet.second.Get<Vector4>();
76       }
77     }
78     else if((DevelText::Shadow::Property::OFFSET == valueGet.first.indexKey) || (OFFSET_KEY == valueGet.first.stringKey))
79     {
80       /// Offset key.
81       offsetDefined = true;
82
83       if(valueGet.second.GetType() == Dali::Property::STRING)
84       {
85         const std::string offsetStr = valueGet.second.Get<std::string>();
86         StringToVector2(offsetStr.c_str(), offsetStr.size(), offset);
87       }
88       else
89       {
90         offset = valueGet.second.Get<Vector2>();
91       }
92     }
93     else if((DevelText::Shadow::Property::BLUR_RADIUS == valueGet.first.indexKey) || (BLUR_RADIUS_KEY == valueGet.first.stringKey))
94     {
95       /// Blur radius key.
96       blurRadiusDefined = true;
97
98       if(valueGet.second.GetType() == Dali::Property::STRING)
99       {
100         const std::string blurRadiusStr = valueGet.second.Get<std::string>();
101         blurRadius                      = StringToFloat(blurRadiusStr.c_str());
102       }
103       else
104       {
105         blurRadius = valueGet.second.Get<float>();
106       }
107     }
108   }
109
110   return 0u == numberOfItems;
111 }
112
113 bool ParseUnderlineProperties(const Property::Map&   underlinePropertiesMap,
114                               bool&                  enabled,
115                               bool&                  colorDefined,
116                               Vector4&               color,
117                               bool&                  heightDefined,
118                               float&                 height,
119                               bool&                  typeDefined,
120                               Text::Underline::Type& type,
121                               bool&                  dashWidthDefined,
122                               float&                 dashWidth,
123                               bool&                  dashGapDefined,
124                               float&                 dashGap)
125 {
126   const unsigned int numberOfItems = underlinePropertiesMap.Count();
127
128   // Parses and applies the style.
129   for(unsigned int index = 0u; index < numberOfItems; ++index)
130   {
131     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue(index);
132
133     if((DevelText::Underline::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
134     {
135       /// Enable key.
136       if(valueGet.second.GetType() == Dali::Property::STRING)
137       {
138         const std::string enableStr = valueGet.second.Get<std::string>();
139         enabled                     = Text::TokenComparison(TRUE_TOKEN, enableStr.c_str(), enableStr.size());
140       }
141       else
142       {
143         enabled = valueGet.second.Get<bool>();
144       }
145     }
146     else if((DevelText::Underline::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
147     {
148       /// Color key.
149       colorDefined = true;
150
151       if(valueGet.second.GetType() == Dali::Property::STRING)
152       {
153         const std::string colorStr = valueGet.second.Get<std::string>();
154         Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
155       }
156       else
157       {
158         color = valueGet.second.Get<Vector4>();
159       }
160     }
161     else if((DevelText::Underline::Property::HEIGHT == valueGet.first.indexKey) || (HEIGHT_KEY == valueGet.first.stringKey))
162     {
163       /// Height key.
164       heightDefined = true;
165
166       if(valueGet.second.GetType() == Dali::Property::STRING)
167       {
168         const std::string heightStr = valueGet.second.Get<std::string>();
169         height                      = StringToFloat(heightStr.c_str());
170       }
171       else
172       {
173         height = valueGet.second.Get<float>();
174       }
175     }
176     else if((DevelText::Underline::Property::TYPE == valueGet.first.indexKey) || (TYPE_KEY == valueGet.first.stringKey))
177     {
178       /// Underline Type key.
179       typeDefined = true;
180
181       if(valueGet.second.GetType() == Dali::Property::STRING)
182       {
183         const std::string typeStr = valueGet.second.Get<std::string>();
184         Text::UnderlineTypeStringToTypeValue(typeStr.c_str(), typeStr.size(), type);
185       }
186       else
187       {
188         type = valueGet.second.Get<Text::Underline::Type>();
189       }
190     }
191     else if((DevelText::Underline::Property::DASH_WIDTH == valueGet.first.indexKey) || (DASH_WIDTH_KEY == valueGet.first.stringKey))
192     {
193       /// Dashed Underline Width key.
194       dashWidthDefined = true;
195
196       if(valueGet.second.GetType() == Dali::Property::STRING)
197       {
198         const std::string dashWidthStr = valueGet.second.Get<std::string>();
199         dashWidth                      = StringToFloat(dashWidthStr.c_str());
200       }
201       else
202       {
203         dashWidth = valueGet.second.Get<float>();
204       }
205     }
206     else if((DevelText::Underline::Property::DASH_GAP == valueGet.first.indexKey) || (DASH_GAP_KEY == valueGet.first.stringKey))
207     {
208       /// Dashed Underline Gap key.
209       dashGapDefined = true;
210
211       if(valueGet.second.GetType() == Dali::Property::STRING)
212       {
213         const std::string dashGapStr = valueGet.second.Get<std::string>();
214         dashGap                      = StringToFloat(dashGapStr.c_str());
215       }
216       else
217       {
218         dashGap = valueGet.second.Get<float>();
219       }
220     }
221   }
222
223   return 0u == numberOfItems;
224 }
225
226 bool ParseOutlineProperties(const Property::Map& underlinePropertiesMap,
227                             bool&                colorDefined,
228                             Vector4&             color,
229                             bool&                widthDefined,
230                             uint16_t&            width)
231 {
232   const unsigned int numberOfItems = underlinePropertiesMap.Count();
233
234   // Parses and applies the style.
235   for(unsigned int index = 0u; index < numberOfItems; ++index)
236   {
237     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue(index);
238
239     if((DevelText::Outline::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
240     {
241       /// Color key.
242       colorDefined = true;
243       color        = valueGet.second.Get<Vector4>();
244     }
245     else if((DevelText::Outline::Property::WIDTH == valueGet.first.indexKey) || (WIDTH_KEY == valueGet.first.stringKey))
246     {
247       /// Width key.
248       widthDefined = true;
249       width        = static_cast<uint16_t>(valueGet.second.Get<float>());
250     }
251   }
252
253   return 0u == numberOfItems;
254 }
255
256 bool ParseBackgroundProperties(const Property::Map& backgroundProperties,
257                                bool&                enabled,
258                                bool&                colorDefined,
259                                Vector4&             color)
260 {
261   const unsigned int numberOfItems = backgroundProperties.Count();
262
263   // Parses and applies the style.
264   for(unsigned int index = 0u; index < numberOfItems; ++index)
265   {
266     const KeyValuePair& valueGet = backgroundProperties.GetKeyValue(index);
267
268     if((DevelText::Background::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
269     {
270       /// Enable key.
271       enabled = valueGet.second.Get<bool>();
272     }
273     else if((DevelText::Background::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
274     {
275       /// Color key.
276       colorDefined = true;
277       color        = valueGet.second.Get<Vector4>();
278     }
279   }
280
281   return 0u == numberOfItems;
282 }
283
284 bool ParseStrikethroughProperties(const Property::Map& strikethroughPropertiesMap,
285                                   bool&                enabled,
286                                   bool&                colorDefined,
287                                   Vector4&             color,
288                                   bool&                heightDefined,
289                                   float&               height)
290 {
291   const unsigned int numberOfItems = strikethroughPropertiesMap.Count();
292
293   // Parses and applies the style.
294   for(unsigned int index = 0u; index < numberOfItems; ++index)
295   {
296     const KeyValuePair& valueGet = strikethroughPropertiesMap.GetKeyValue(index);
297
298     if((DevelText::Strikethrough::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
299     {
300       /// Enable key.
301       if(valueGet.second.GetType() == Dali::Property::STRING)
302       {
303         const std::string enableStr = valueGet.second.Get<std::string>();
304         enabled                     = Text::TokenComparison(TRUE_TOKEN, enableStr.c_str(), enableStr.size());
305       }
306       else
307       {
308         enabled = valueGet.second.Get<bool>();
309       }
310     }
311     else if((DevelText::Strikethrough::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
312     {
313       /// Color key.
314       colorDefined = true;
315
316       if(valueGet.second.GetType() == Dali::Property::STRING)
317       {
318         const std::string colorStr = valueGet.second.Get<std::string>();
319         Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
320       }
321       else
322       {
323         color = valueGet.second.Get<Vector4>();
324       }
325     }
326     else if((DevelText::Strikethrough::Property::HEIGHT == valueGet.first.indexKey) || (HEIGHT_KEY == valueGet.first.stringKey))
327     {
328       /// Height key.
329       heightDefined = true;
330
331       if(valueGet.second.GetType() == Dali::Property::STRING)
332       {
333         const std::string heightStr = valueGet.second.Get<std::string>();
334         height                      = StringToFloat(heightStr.c_str());
335       }
336       else
337       {
338         height = valueGet.second.Get<float>();
339       }
340     }
341   }
342   return 0u == numberOfItems;
343 }
344
345 bool SetUnderlineProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
346 {
347   bool update = false;
348
349   if(controller)
350   {
351     switch(type)
352     {
353       case EffectStyle::DEFAULT:
354       {
355         const Property::Map& propertiesMap = value.Get<Property::Map>();
356
357         bool                  enabled      = false;
358         bool                  colorDefined = false;
359         Vector4               color;
360         bool                  heightDefined = false;
361         float                 height        = 0.f;
362         bool                  typeDefined   = false;
363         Text::Underline::Type type;
364         bool                  dashWidthDefined = false;
365         float                 dashWidth        = 2.0f;
366         bool                  dashGapDefined   = false;
367         float                 dashGap          = 1.0f;
368
369         bool empty = true;
370
371         if(propertiesMap.Empty())
372         {
373           // Map empty so check if a string provided
374           const std::string propertyString = value.Get<std::string>();
375
376           if(!propertyString.empty())
377           {
378             Property::Map parsedStringMap;
379             Text::ParsePropertyString(propertyString, parsedStringMap);
380
381             empty = ParseUnderlineProperties(parsedStringMap,
382                                              enabled,
383                                              colorDefined,
384                                              color,
385                                              heightDefined,
386                                              height,
387                                              typeDefined,
388                                              type,
389                                              dashWidthDefined,
390                                              dashWidth,
391                                              dashGapDefined,
392                                              dashGap);
393
394             controller->UnderlineSetByString(!empty);
395           }
396         }
397         else
398         {
399           empty = ParseUnderlineProperties(propertiesMap,
400                                            enabled,
401                                            colorDefined,
402                                            color,
403                                            heightDefined,
404                                            height,
405                                            typeDefined,
406                                            type,
407                                            dashWidthDefined,
408                                            dashWidth,
409                                            dashGapDefined,
410                                            dashGap);
411
412           controller->UnderlineSetByString(false);
413         }
414
415         if(!empty)
416         {
417           if(enabled != controller->IsUnderlineEnabled())
418           {
419             controller->SetUnderlineEnabled(enabled);
420             update = true;
421           }
422
423           // Sets the default underline values.
424           if(colorDefined && (controller->GetUnderlineColor() != color))
425           {
426             controller->SetUnderlineColor(color);
427             update = true;
428           }
429
430           if(heightDefined && (fabsf(controller->GetUnderlineHeight() - height) > Math::MACHINE_EPSILON_1000))
431           {
432             controller->SetUnderlineHeight(height);
433             update = true;
434           }
435
436           if(typeDefined && (controller->GetUnderlineType() != type))
437           {
438             controller->SetUnderlineType(type);
439             update = true;
440           }
441
442           if(dashWidthDefined && (fabsf(controller->GetDashedUnderlineWidth() - dashWidth) > Math::MACHINE_EPSILON_1000))
443           {
444             controller->SetDashedUnderlineWidth(dashWidth);
445             update = true;
446           }
447
448           if(dashGapDefined && (fabsf(controller->GetDashedUnderlineGap() - dashGap) > Math::MACHINE_EPSILON_1000))
449           {
450             controller->SetDashedUnderlineGap(dashGap);
451             update = true;
452           }
453         }
454         else
455         {
456           // Disable underline.
457           if(controller->IsUnderlineEnabled())
458           {
459             controller->SetUnderlineEnabled(false);
460             update = true;
461           }
462         }
463         break;
464       }
465       case EffectStyle::INPUT:
466       {
467         const std::string& underlineProperties = value.Get<std::string>();
468
469         controller->SetInputUnderlineProperties(underlineProperties);
470         break;
471       }
472     } // switch
473   }   // if( controller )
474
475   return update;
476 }
477
478 void GetUnderlineProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
479 {
480   if(controller)
481   {
482     switch(type)
483     {
484       case EffectStyle::DEFAULT:
485       {
486         const bool                  enabled   = controller->IsUnderlineEnabled();
487         const Vector4&              color     = controller->GetUnderlineColor();
488         const float                 height    = controller->GetUnderlineHeight();
489         const Text::Underline::Type type      = controller->GetUnderlineType();
490         const float                 dashWidth = controller->GetDashedUnderlineWidth();
491         const float                 dashGap   = controller->GetDashedUnderlineGap();
492
493         if(controller->IsUnderlineSetByString())
494         {
495           std::string       underlineProperties = "{\"enable\":";
496           const std::string enabledStr          = enabled ? "true" : "false";
497           underlineProperties += "\"" + enabledStr + "\",";
498
499           std::string colorStr;
500           Vector4ToColorString(color, colorStr);
501           underlineProperties += "\"color\":\"" + colorStr + "\",";
502
503           std::string heightStr;
504           FloatToString(height, heightStr);
505           underlineProperties += "\"height\":\"" + heightStr + "\",";
506
507           std::string typeStr;
508           typeStr = GetUnderlineTypeToString(type);
509           underlineProperties += "\"type\":\"" + typeStr + "\",";
510
511           std::string dashWidthStr;
512           FloatToString(dashWidth, dashWidthStr);
513           underlineProperties += "\"dashWidth\":\"" + dashWidthStr + "\",";
514
515           std::string dashGapStr;
516           FloatToString(dashGap, dashGapStr);
517           underlineProperties += "\"dashGap\":\"" + dashGapStr + "\"}";
518
519           value = underlineProperties;
520         }
521         else
522         {
523           Property::Map map;
524
525           map.Insert(ENABLE_KEY, enabled);
526           map.Insert(COLOR_KEY, color);
527           map.Insert(HEIGHT_KEY, height);
528           map.Insert(TYPE_KEY, type);
529           map.Insert(DASH_WIDTH_KEY, dashWidth);
530           map.Insert(DASH_GAP_KEY, dashGap);
531
532           value = map;
533         }
534
535         break;
536       }
537       case EffectStyle::INPUT:
538       {
539         value = controller->GetInputUnderlineProperties();
540         break;
541       }
542     }
543   }
544 }
545
546 bool SetShadowProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
547 {
548   bool update = false;
549
550   if(controller)
551   {
552     switch(type)
553     {
554       case EffectStyle::DEFAULT:
555       {
556         const Property::Map& propertiesMap = value.Get<Property::Map>();
557
558         bool    colorDefined = false;
559         Vector4 color;
560         bool    offsetDefined = false;
561         Vector2 offset;
562         bool    blurRadiusDefined = false;
563         float   blurRadius;
564
565         bool empty = true;
566
567         if(propertiesMap.Empty())
568         {
569           // Map empty so check if a string provided
570           const std::string propertyString = value.Get<std::string>();
571
572           Property::Map parsedStringMap;
573           Text::ParsePropertyString(propertyString, parsedStringMap);
574
575           empty = ParseShadowProperties(parsedStringMap,
576                                         colorDefined,
577                                         color,
578                                         offsetDefined,
579                                         offset,
580                                         blurRadiusDefined,
581                                         blurRadius);
582
583           controller->ShadowSetByString(!empty);
584         }
585         else
586         {
587           empty = ParseShadowProperties(propertiesMap,
588                                         colorDefined,
589                                         color,
590                                         offsetDefined,
591                                         offset,
592                                         blurRadiusDefined,
593                                         blurRadius);
594
595           controller->ShadowSetByString(false);
596         }
597
598         if(!empty)
599         {
600           // Sets the default shadow values.
601           if(colorDefined && (controller->GetShadowColor() != color))
602           {
603             controller->SetShadowColor(color);
604             update = true;
605           }
606
607           if(offsetDefined && (controller->GetShadowOffset() != offset))
608           {
609             controller->SetShadowOffset(offset);
610             update = true;
611           }
612
613           if(blurRadiusDefined && (controller->GetShadowBlurRadius() != blurRadius))
614           {
615             controller->SetShadowBlurRadius(blurRadius);
616             update = true;
617           }
618         }
619         else
620         {
621           // Disable shadow.
622           if(Vector2::ZERO != controller->GetShadowOffset())
623           {
624             controller->SetShadowOffset(Vector2::ZERO);
625           }
626         }
627         break;
628       }
629       case EffectStyle::INPUT:
630       {
631         const std::string& shadowString = value.Get<std::string>();
632
633         controller->SetInputShadowProperties(shadowString);
634         break;
635       }
636     } // switch
637   }   // if( controller )
638
639   return update;
640 }
641
642 void GetShadowProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
643 {
644   if(controller)
645   {
646     switch(type)
647     {
648       case EffectStyle::DEFAULT:
649       {
650         const Vector4& color      = controller->GetShadowColor();
651         const Vector2& offset     = controller->GetShadowOffset();
652         const float&   blurRadius = controller->GetShadowBlurRadius();
653
654         if(controller->IsShadowSetByString())
655         {
656           std::string shadowProperties = "{";
657
658           std::string colorStr;
659           Vector4ToColorString(color, colorStr);
660           shadowProperties += "\"color\":\"" + colorStr + "\",";
661
662           std::string offsetStr;
663           Vector2ToString(offset, offsetStr);
664           shadowProperties += "\"offset\":\"" + offsetStr + "\",";
665
666           std::string blurRadiusStr;
667           FloatToString(blurRadius, blurRadiusStr);
668           shadowProperties += "\"blurRadius\":\"" + blurRadiusStr + "\"}";
669
670           value = shadowProperties;
671         }
672         else
673         {
674           Property::Map map;
675
676           map.Insert(COLOR_KEY, color);
677           map.Insert(OFFSET_KEY, offset);
678           map.Insert(BLUR_RADIUS_KEY, blurRadius);
679
680           value = map;
681         }
682         break;
683       }
684       case EffectStyle::INPUT:
685       {
686         value = controller->GetInputShadowProperties();
687         break;
688       }
689     }
690   }
691 }
692
693 bool SetEmbossProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
694 {
695   bool update = false;
696
697   if(controller)
698   {
699     const std::string properties = value.Get<std::string>();
700
701     switch(type)
702     {
703       case EffectStyle::DEFAULT:
704       {
705         // Stores the default emboss's properties string to be recovered by the GetEmbossProperties() function.
706         controller->SetDefaultEmbossProperties(properties);
707         break;
708       }
709       case EffectStyle::INPUT:
710       {
711         // Stores the input emboss's properties string to be recovered by the GetEmbossProperties() function.
712         controller->SetInputEmbossProperties(properties);
713         break;
714       }
715     }
716   }
717
718   return update;
719 }
720
721 void GetEmbossProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
722 {
723   if(controller)
724   {
725     switch(type)
726     {
727       case EffectStyle::DEFAULT:
728       {
729         value = controller->GetDefaultEmbossProperties();
730         break;
731       }
732       case EffectStyle::INPUT:
733       {
734         value = controller->GetInputEmbossProperties();
735         break;
736       }
737     }
738   }
739 }
740
741 bool SetOutlineProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
742 {
743   bool update = false;
744
745   if(controller)
746   {
747     switch(type)
748     {
749       case EffectStyle::DEFAULT:
750       {
751         const Property::Map& propertiesMap = value.Get<Property::Map>();
752
753         bool     colorDefined = false;
754         Vector4  color;
755         bool     widthDefined = false;
756         uint16_t width        = 0u;
757
758         bool empty = true;
759
760         if(propertiesMap.Empty())
761         {
762           // Map empty so check if a string provided
763           // This is purely to maintain backward compatibility, but we don't parse the string to be a property map.
764           const std::string propertyString = value.Get<std::string>();
765
766           // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function.
767           controller->SetDefaultOutlineProperties(propertyString);
768
769           controller->OutlineSetByString(true);
770         }
771         else
772         {
773           empty = ParseOutlineProperties(propertiesMap,
774                                          colorDefined,
775                                          color,
776                                          widthDefined,
777                                          width);
778
779           controller->OutlineSetByString(false);
780         }
781
782         if(!empty)
783         {
784           // Sets the default outline values.
785           if(colorDefined && (controller->GetOutlineColor() != color))
786           {
787             controller->SetOutlineColor(color);
788             update = true;
789           }
790
791           if(widthDefined && (controller->GetOutlineWidth() != width))
792           {
793             controller->SetOutlineWidth(width);
794             update = true;
795           }
796         }
797         else
798         {
799           // Disable outline
800           if(0u != controller->GetOutlineWidth())
801           {
802             controller->SetOutlineWidth(0u);
803             update = true;
804           }
805         }
806         break;
807       }
808       case EffectStyle::INPUT:
809       {
810         const std::string& outlineProperties = value.Get<std::string>();
811
812         controller->SetInputOutlineProperties(outlineProperties);
813         break;
814       }
815     } // switch
816   }   // if( controller )
817
818   return update;
819 }
820
821 void GetOutlineProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
822 {
823   if(controller)
824   {
825     switch(type)
826     {
827       case EffectStyle::DEFAULT:
828       {
829         if(controller->IsOutlineSetByString())
830         {
831           value = controller->GetDefaultOutlineProperties();
832           break;
833         }
834         else
835         {
836           const Vector4& color = controller->GetOutlineColor();
837           const uint16_t width = controller->GetOutlineWidth();
838
839           Property::Map map;
840           map.Insert(COLOR_KEY, color);
841           map.Insert(WIDTH_KEY, static_cast<int>(width));
842
843           value = map;
844
845           break;
846         }
847       }
848       case EffectStyle::INPUT:
849       {
850         value = controller->GetInputOutlineProperties();
851         break;
852       }
853     }
854   }
855 }
856
857 bool SetBackgroundProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
858 {
859   bool update = false;
860
861   if(controller)
862   {
863     switch(type)
864     {
865       case EffectStyle::DEFAULT:
866       {
867         const Property::Map& propertiesMap = value.Get<Property::Map>();
868
869         bool    enabled      = false;
870         bool    colorDefined = false;
871         Vector4 color;
872
873         bool empty = true;
874
875         if(!propertiesMap.Empty())
876         {
877           empty = ParseBackgroundProperties(propertiesMap,
878                                             enabled,
879                                             colorDefined,
880                                             color);
881         }
882
883         if(!empty)
884         {
885           if(enabled != controller->IsBackgroundEnabled())
886           {
887             controller->SetBackgroundEnabled(enabled);
888             update = true;
889           }
890
891           if(colorDefined && (controller->GetBackgroundColor() != color))
892           {
893             controller->SetBackgroundColor(color);
894             update = true;
895           }
896         }
897         else
898         {
899           // Disable background.
900           if(controller->IsBackgroundEnabled())
901           {
902             controller->SetBackgroundEnabled(false);
903             update = true;
904           }
905         }
906         break;
907       }
908       case EffectStyle::INPUT:
909       {
910         // Text background is not supported while inputting yet
911         break;
912       }
913     } // switch
914   }   // if( controller )
915
916   return update;
917 }
918
919 void GetBackgroundProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
920 {
921   if(controller)
922   {
923     switch(type)
924     {
925       case EffectStyle::DEFAULT:
926       {
927         const bool     enabled = controller->IsBackgroundEnabled();
928         const Vector4& color   = controller->GetBackgroundColor();
929
930         Property::Map map;
931         map.Insert(ENABLE_KEY, enabled);
932         map.Insert(COLOR_KEY, color);
933
934         value = map;
935
936         break;
937       }
938       case EffectStyle::INPUT:
939       {
940         // Text background is not supported while inputting yet
941         break;
942       }
943     }
944   }
945 }
946
947 bool SetStrikethroughProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
948 {
949   bool update = false;
950
951   if(controller)
952   {
953     switch(type)
954     {
955       case EffectStyle::DEFAULT:
956       {
957         const Property::Map& propertiesMap = value.Get<Property::Map>();
958
959         bool    enabled      = false;
960         bool    colorDefined = false;
961         Vector4 color;
962         bool    heightDefined = false;
963         float   height        = 0.f;
964
965         bool empty = true;
966
967         if(propertiesMap.Empty())
968         {
969           // Map empty so check if a string provided
970           const std::string propertyString = value.Get<std::string>();
971
972           if(!propertyString.empty())
973           {
974             Property::Map parsedStringMap;
975             Text::ParsePropertyString(propertyString, parsedStringMap);
976
977             empty = ParseStrikethroughProperties(parsedStringMap,
978                                                  enabled,
979                                                  colorDefined,
980                                                  color,
981                                                  heightDefined,
982                                                  height);
983
984             controller->StrikethroughSetByString(!empty);
985           }
986         }
987         else
988         {
989           empty = ParseStrikethroughProperties(propertiesMap,
990                                                enabled,
991                                                colorDefined,
992                                                color,
993                                                heightDefined,
994                                                height);
995
996           controller->StrikethroughSetByString(false);
997         }
998
999         if(!empty)
1000         {
1001           if(enabled != controller->IsStrikethroughEnabled())
1002           {
1003             controller->SetStrikethroughEnabled(enabled);
1004             update = true;
1005           }
1006
1007           // Sets the default strikethrough values.
1008           if(colorDefined && (controller->GetStrikethroughColor() != color))
1009           {
1010             controller->SetStrikethroughColor(color);
1011             update = true;
1012           }
1013           if(heightDefined && (fabsf(controller->GetStrikethroughHeight() - height) > Math::MACHINE_EPSILON_1000))
1014           {
1015             controller->SetStrikethroughHeight(height);
1016             update = true;
1017           }
1018         }
1019         else
1020         {
1021           // Disable strikethrough.
1022           if(controller->IsStrikethroughEnabled())
1023           {
1024             controller->SetStrikethroughEnabled(false);
1025             update = true;
1026           }
1027         }
1028         break;
1029       }
1030       case EffectStyle::INPUT:
1031       {
1032         const std::string& strikethroughProperties = value.Get<std::string>();
1033
1034         controller->SetInputStrikethroughProperties(strikethroughProperties);
1035         update = true;
1036         break;
1037       }
1038     } // switch
1039   }   // if( controller )
1040
1041   return update;
1042 }
1043
1044 void GetStrikethroughProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
1045 {
1046   if(controller)
1047   {
1048     switch(type)
1049     {
1050       case EffectStyle::DEFAULT:
1051       {
1052         const bool     enabled = controller->IsStrikethroughEnabled();
1053         const Vector4& color   = controller->GetStrikethroughColor();
1054         const float    height  = controller->GetStrikethroughHeight();
1055
1056         if(controller->IsStrikethroughSetByString())
1057         {
1058           std::string       strikethroughProperties = "{\"enable\":";
1059           const std::string enabledStr              = enabled ? "true" : "false";
1060           strikethroughProperties += "\"" + enabledStr + "\",";
1061
1062           std::string colorStr;
1063           Vector4ToColorString(color, colorStr);
1064           strikethroughProperties += "\"color\":\"" + colorStr + "\",";
1065
1066           std::string heightStr;
1067           FloatToString(height, heightStr);
1068           strikethroughProperties += "\"height\":\"" + heightStr + "\"}";
1069
1070           value = strikethroughProperties;
1071         }
1072         else
1073         {
1074           Property::Map map;
1075
1076           map.Insert(ENABLE_KEY, enabled);
1077           map.Insert(COLOR_KEY, color);
1078           map.Insert(HEIGHT_KEY, height);
1079
1080           value = map;
1081         }
1082
1083         break;
1084       }
1085       case EffectStyle::INPUT:
1086       {
1087         value = controller->GetInputStrikethroughProperties();
1088         break;
1089       }
1090     }
1091   }
1092 }
1093
1094 Underline::Type StringToUnderlineType(const char* const underlineTypeStr)
1095 {
1096   Underline::Type underlineType = Text::Underline::SOLID;
1097   Scripting::GetEnumeration<Underline::Type>(underlineTypeStr,
1098                                              UNDERLINE_TYPE_STRING_TABLE,
1099                                              UNDERLINE_TYPE_STRING_TABLE_COUNT,
1100                                              underlineType);
1101
1102   return underlineType;
1103 }
1104
1105 } // namespace Text
1106
1107 } // namespace Toolkit
1108
1109 } // namespace Dali