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