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