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