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