Merge "SVACE Error fix TextureManager Thread bounds" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-effects-style.cpp
1 /*
2  * Copyright (c) 2016 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/internal/text/markup-processor-helper-functions.h>
23 #include <dali-toolkit/internal/text/property-string-parser.h>
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Text
32 {
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 TRUE_TOKEN( "true" );
43 const std::string FALSE_TOKEN( "false" );
44 }
45
46 bool ParseShadowProperties( const Property::Map& shadowPropertiesMap,
47                             bool& colorDefined,
48                             Vector4& color,
49                             bool& offsetDefined,
50                             Vector2& offset,
51                             bool& blurRadiusDefined,
52                             float& blurRadius )
53 {
54   const unsigned int numberOfItems = shadowPropertiesMap.Count();
55
56   // Parses and applies the style.
57   for( unsigned int index = 0u; index < numberOfItems; ++index )
58   {
59     const KeyValuePair& valueGet = shadowPropertiesMap.GetKeyValue( index );
60
61     if( COLOR_KEY == valueGet.first.stringKey )
62     {
63       /// Color key.
64       colorDefined = true;
65
66       if( valueGet.second.GetType() == Dali::Property::STRING )
67       {
68         const std::string colorStr = valueGet.second.Get<std::string>();
69         Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
70       }
71       else
72       {
73         color = valueGet.second.Get<Vector4>();
74       }
75     }
76     else if( OFFSET_KEY == valueGet.first.stringKey )
77     {
78       /// Offset key.
79       offsetDefined = true;
80
81       if( valueGet.second.GetType() == Dali::Property::STRING )
82       {
83         const std::string offsetStr = valueGet.second.Get<std::string>();
84         StringToVector2( offsetStr.c_str(), offsetStr.size(), offset );
85       }
86       else
87       {
88         offset = valueGet.second.Get<Vector2>();
89       }
90     }
91     else if( BLUR_RADIUS_KEY == valueGet.first.stringKey )
92     {
93       /// Blur radius key.
94       blurRadiusDefined = true;
95
96       if( valueGet.second.GetType() == Dali::Property::STRING )
97       {
98         const std::string blurRadiusStr = valueGet.second.Get<std::string>();
99         blurRadius = StringToFloat( blurRadiusStr.c_str() );
100       }
101       else
102       {
103         blurRadius = valueGet.second.Get<float>();
104       }
105     }
106   }
107
108   return 0u == numberOfItems;
109 }
110
111 bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap,
112                                bool& enabled,
113                                bool& colorDefined,
114                                Vector4& color,
115                                bool& heightDefined,
116                                float& height )
117 {
118   const unsigned int numberOfItems = underlinePropertiesMap.Count();
119
120   // Parses and applies the style.
121   for( unsigned int index = 0u; index < numberOfItems; ++index )
122   {
123     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index );
124
125     if( ENABLE_KEY == valueGet.first.stringKey )
126     {
127       /// Enable key.
128       if( valueGet.second.GetType() == Dali::Property::STRING )
129       {
130         const std::string enableStr = valueGet.second.Get<std::string>();
131         enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() );
132       }
133       else
134       {
135         enabled = valueGet.second.Get<bool>();
136       }
137     }
138     else if( COLOR_KEY == valueGet.first.stringKey )
139     {
140       /// Color key.
141       colorDefined = true;
142
143       if( valueGet.second.GetType() == Dali::Property::STRING )
144       {
145         const std::string colorStr = valueGet.second.Get<std::string>();
146         Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
147       }
148       else
149       {
150         color = valueGet.second.Get<Vector4>();
151       }
152     }
153     else if( HEIGHT_KEY == valueGet.first.stringKey )
154     {
155       /// Height key.
156       heightDefined = true;
157
158       if( valueGet.second.GetType() == Dali::Property::STRING )
159       {
160         const std::string heightStr = valueGet.second.Get<std::string>();
161         height = StringToFloat( heightStr.c_str() );
162       }
163       else
164       {
165         height = valueGet.second.Get<float>();
166       }
167     }
168   }
169
170   return 0u == numberOfItems;
171 }
172
173 bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
174                                bool& colorDefined,
175                                Vector4& color,
176                                bool& widthDefined,
177                                unsigned int& width )
178 {
179   const unsigned int numberOfItems = underlinePropertiesMap.Count();
180
181   // Parses and applies the style.
182   for( unsigned int index = 0u; index < numberOfItems; ++index )
183   {
184     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index );
185
186     if( COLOR_KEY == valueGet.first.stringKey )
187     {
188       /// Color key.
189       colorDefined = true;
190       color = valueGet.second.Get<Vector4>();
191     }
192     else if( WIDTH_KEY == valueGet.first.stringKey )
193     {
194       /// Width key.
195       widthDefined = true;
196       width = static_cast<unsigned int>( valueGet.second.Get<float>() );
197     }
198   }
199
200   return 0u == numberOfItems;
201 }
202
203 bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
204 {
205   bool update = false;
206
207   if( controller )
208   {
209     switch( type )
210     {
211       case EffectStyle::DEFAULT:
212       {
213         const Property::Map& propertiesMap = value.Get<Property::Map>();
214
215         bool enabled = false;
216         bool colorDefined = false;
217         Vector4 color;
218         bool heightDefined = false;
219         float height = 0.f;
220
221         bool empty = true;
222
223         if ( propertiesMap.Empty() )
224         {
225           // Map empty so check if a string provided
226           const std::string propertyString = value.Get<std::string>();
227
228           if ( !propertyString.empty() )
229           {
230             Property::Map parsedStringMap;
231             Text::ParsePropertyString( propertyString, parsedStringMap );
232
233             empty = ParseUnderlineProperties( parsedStringMap,
234                                               enabled,
235                                               colorDefined,
236                                               color,
237                                               heightDefined,
238                                               height );
239
240             controller->UnderlineSetByString( !empty );
241           }
242         }
243         else
244         {
245            empty = ParseUnderlineProperties( propertiesMap,
246                                              enabled,
247                                              colorDefined,
248                                              color,
249                                              heightDefined,
250                                              height );
251
252            controller->UnderlineSetByString( false );
253         }
254
255         if( !empty )
256         {
257           if( enabled != controller->IsUnderlineEnabled() )
258           {
259             controller->SetUnderlineEnabled( enabled );
260             update = true;
261           }
262
263           // Sets the default underline values.
264           if( colorDefined && ( controller->GetUnderlineColor() != color ) )
265           {
266             controller->SetUnderlineColor( color );
267             update = true;
268           }
269
270           if( heightDefined && ( fabsf( controller->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) )
271           {
272             controller->SetUnderlineHeight( height );
273             update = true;
274           }
275         }
276         else
277         {
278           // Disable underline.
279           if( controller->IsUnderlineEnabled() )
280           {
281             controller->SetUnderlineEnabled( false );
282             update = true;
283           }
284         }
285         break;
286       }
287       case EffectStyle::INPUT:
288       {
289         const std::string& underlineProperties = value.Get<std::string>();
290
291         controller->SetInputUnderlineProperties( underlineProperties );
292         break;
293       }
294     } // switch
295   } // if( controller )
296
297   return update;
298 }
299
300 void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
301 {
302   if( controller )
303   {
304     switch( type )
305     {
306       case EffectStyle::DEFAULT:
307       {
308         const bool enabled = controller->IsUnderlineEnabled();
309         const Vector4& color = controller->GetUnderlineColor();
310         const float height = controller->GetUnderlineHeight();
311
312         if ( controller->IsUnderlineSetByString() )
313         {
314           std::string underlineProperties = "{\"enable\":";
315           const std::string enabledStr = enabled ? "true" : "false";
316           underlineProperties += "\"" + enabledStr + "\",";
317
318           std::string colorStr;
319           Vector4ToColorString( color, colorStr );
320           underlineProperties += "\"color\":\"" + colorStr + "\",";
321
322           std::string heightStr;
323           FloatToString( height, heightStr );
324           underlineProperties += "\"height\":\"" + heightStr + "\"}";
325
326           value = underlineProperties;
327         }
328         else
329         {
330           Property::Map map;
331
332           const std::string enabledStr = enabled ? TRUE_TOKEN : FALSE_TOKEN;
333           map.Insert( ENABLE_KEY, enabledStr );
334
335           std::string colorStr;
336           Vector4ToColorString( color, colorStr );
337           map.Insert( COLOR_KEY, colorStr );
338
339           std::string heightStr;
340           FloatToString( height, heightStr );
341           map.Insert( HEIGHT_KEY, heightStr );
342
343           value = map;
344         }
345
346         break;
347       }
348       case EffectStyle::INPUT:
349       {
350         value = controller->GetInputUnderlineProperties();
351         break;
352       }
353     }
354   }
355 }
356
357 bool SetShadowProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
358 {
359   bool update = false;
360
361   if( controller )
362   {
363     switch( type )
364     {
365       case EffectStyle::DEFAULT:
366       {
367         const Property::Map& propertiesMap = value.Get<Property::Map>();
368
369         bool colorDefined = false;
370         Vector4 color;
371         bool offsetDefined = false;
372         Vector2 offset;
373         bool blurRadiusDefined = false;
374         float blurRadius;
375
376         bool empty = true;
377
378         if ( propertiesMap.Empty() )
379         {
380            // Map empty so check if a string provided
381            const std::string propertyString = value.Get<std::string>();
382
383            Property::Map parsedStringMap;
384            Text::ParsePropertyString( propertyString, parsedStringMap );
385
386            empty = ParseShadowProperties( parsedStringMap,
387                                           colorDefined,
388                                           color,
389                                           offsetDefined,
390                                           offset,
391                                           blurRadiusDefined,
392                                           blurRadius );
393
394            controller->ShadowSetByString( !empty );
395
396         }
397         else
398         {
399           empty = ParseShadowProperties( propertiesMap,
400                                          colorDefined,
401                                          color,
402                                          offsetDefined,
403                                          offset,
404                                          blurRadiusDefined,
405                                          blurRadius );
406
407           controller->ShadowSetByString( false );
408         }
409
410         if( !empty )
411         {
412           // Sets the default shadow values.
413           if( colorDefined && ( controller->GetShadowColor() != color ) )
414           {
415             controller->SetShadowColor( color );
416             update = true;
417           }
418
419           if( offsetDefined && ( controller->GetShadowOffset() != offset ) )
420           {
421             controller->SetShadowOffset( offset );
422             update = true;
423           }
424
425           if( blurRadiusDefined && ( controller->GetShadowBlurRadius() != blurRadius ) )
426           {
427             controller->SetShadowBlurRadius( blurRadius );
428             update = true;
429           }
430         }
431         else
432         {
433           // Disable shadow.
434           if( Vector2::ZERO != controller->GetShadowOffset() )
435           {
436             controller->SetShadowOffset( Vector2::ZERO );
437           }
438         }
439         break;
440       }
441       case EffectStyle::INPUT:
442       {
443         const std::string& shadowString = value.Get<std::string>();
444
445         controller->SetInputShadowProperties( shadowString );
446         break;
447       }
448     } // switch
449   } // if( controller )
450
451   return update;
452 }
453
454 void GetShadowProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
455 {
456   if( controller )
457   {
458     switch( type )
459     {
460       case EffectStyle::DEFAULT:
461       {
462         const Vector4& color = controller->GetShadowColor();
463         const Vector2& offset = controller->GetShadowOffset();
464         const float& blurRadius = controller->GetShadowBlurRadius();
465
466         if ( controller->IsShadowSetByString() )
467         {
468           std::string shadowProperties = "{";
469
470           std::string colorStr;
471           Vector4ToColorString( color, colorStr );
472           shadowProperties += "\"color\":\"" + colorStr + "\",";
473
474           std::string offsetStr;
475           Vector2ToString( offset, offsetStr );
476           shadowProperties += "\"offset\":\"" + offsetStr + "\",";
477
478           std::string blurRadiusStr;
479           FloatToString( blurRadius, blurRadiusStr );
480           shadowProperties += "\"blurRadius\":\"" + blurRadiusStr + "\"}";
481
482           value = shadowProperties;
483         }
484         else
485         {
486           Property::Map map;
487
488           map.Insert( COLOR_KEY, color );
489           map.Insert( OFFSET_KEY, offset );
490           map.Insert( BLUR_RADIUS_KEY, blurRadius );
491
492           value = map;
493         }
494         break;
495       }
496       case EffectStyle::INPUT:
497       {
498         value = controller->GetInputShadowProperties();
499         break;
500       }
501     }
502   }
503 }
504
505 bool SetEmbossProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
506 {
507   bool update = false;
508
509   if( controller )
510   {
511     const std::string properties = value.Get< std::string >();
512
513     switch( type )
514     {
515       case EffectStyle::DEFAULT:
516       {
517         // Stores the default emboss's properties string to be recovered by the GetEmbossProperties() function.
518         controller->SetDefaultEmbossProperties( properties );
519         break;
520       }
521       case EffectStyle::INPUT:
522       {
523         // Stores the input emboss's properties string to be recovered by the GetEmbossProperties() function.
524         controller->SetInputEmbossProperties( properties );
525         break;
526       }
527     }
528   }
529
530   return update;
531 }
532
533 void GetEmbossProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
534 {
535   if( controller )
536   {
537     switch( type )
538     {
539       case EffectStyle::DEFAULT:
540       {
541         value = controller->GetDefaultEmbossProperties();
542         break;
543       }
544       case EffectStyle::INPUT:
545       {
546         value = controller->GetInputEmbossProperties();
547         break;
548       }
549     }
550   }
551 }
552
553 bool SetOutlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
554 {
555   bool update = false;
556
557   if( controller )
558   {
559     switch( type )
560     {
561       case EffectStyle::DEFAULT:
562       {
563         const Property::Map& propertiesMap = value.Get<Property::Map>();
564
565         bool colorDefined = false;
566         Vector4 color;
567         bool widthDefined = false;
568         unsigned int width = 0u;
569
570         bool empty = true;
571
572         if ( propertiesMap.Empty() )
573         {
574            // Map empty so check if a string provided
575            // This is purely to maintain backward compatibility, but we don't parse the string to be a property map.
576            const std::string propertyString = value.Get<std::string>();
577
578            // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function.
579            controller->SetDefaultOutlineProperties( propertyString );
580
581            controller->OutlineSetByString( true );
582         }
583         else
584         {
585            empty = ParseOutlineProperties( propertiesMap,
586                                            colorDefined,
587                                            color,
588                                            widthDefined,
589                                            width );
590
591            controller->OutlineSetByString( false );
592         }
593
594         if( !empty )
595         {
596           // Sets the default outline values.
597           if( colorDefined && ( controller->GetOutlineColor() != color ) )
598           {
599             controller->SetOutlineColor( color );
600             update = true;
601           }
602
603           if( widthDefined && ( controller->GetOutlineWidth() != width ) )
604           {
605             controller->SetOutlineWidth( width );
606             update = true;
607           }
608         }
609         else
610         {
611           // Disable outline
612           if( 0u != controller->GetOutlineWidth() )
613           {
614             controller->SetOutlineWidth( 0u );
615             update = true;
616           }
617         }
618         break;
619       }
620       case EffectStyle::INPUT:
621       {
622         const std::string& outlineProperties = value.Get<std::string>();
623
624         controller->SetInputOutlineProperties( outlineProperties );
625         break;
626       }
627     } // switch
628   } // if( controller )
629
630   return update;
631 }
632
633 void GetOutlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
634 {
635   if( controller )
636   {
637     switch( type )
638     {
639       case EffectStyle::DEFAULT:
640       {
641         if ( controller->IsOutlineSetByString() )
642         {
643           value = controller->GetDefaultOutlineProperties();
644           break;
645         }
646         else
647         {
648           const Vector4& color = controller->GetOutlineColor();
649           const unsigned int width = controller->GetOutlineWidth();
650
651           Property::Map map;
652
653           std::string colorStr;
654           Vector4ToColorString( color, colorStr );
655           map.Insert( COLOR_KEY, colorStr );
656
657           std::string widthStr;
658           UintToString( width, widthStr );
659           map.Insert( WIDTH_KEY, widthStr );
660
661           value = map;
662
663           break;
664         }
665       }
666       case EffectStyle::INPUT:
667       {
668         value = controller->GetInputOutlineProperties();
669         break;
670       }
671     }
672   }
673 }
674
675 } // namespace Text
676
677 } // namespace Toolkit
678
679 } // namespace Dali