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