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