2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/text/text-effects-style.h>
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>
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");
44 bool ParseShadowProperties(const Property::Map& shadowPropertiesMap,
49 bool& blurRadiusDefined,
52 const unsigned int numberOfItems = shadowPropertiesMap.Count();
54 // Parses and applies the style.
55 for(unsigned int index = 0u; index < numberOfItems; ++index)
57 const KeyValuePair& valueGet = shadowPropertiesMap.GetKeyValue(index);
59 if((DevelText::Shadow::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
64 if(valueGet.second.GetType() == Dali::Property::STRING)
66 const std::string colorStr = valueGet.second.Get<std::string>();
67 Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
71 color = valueGet.second.Get<Vector4>();
74 else if((DevelText::Shadow::Property::OFFSET == valueGet.first.indexKey) || (OFFSET_KEY == valueGet.first.stringKey))
79 if(valueGet.second.GetType() == Dali::Property::STRING)
81 const std::string offsetStr = valueGet.second.Get<std::string>();
82 StringToVector2(offsetStr.c_str(), offsetStr.size(), offset);
86 offset = valueGet.second.Get<Vector2>();
89 else if((DevelText::Shadow::Property::BLUR_RADIUS == valueGet.first.indexKey) || (BLUR_RADIUS_KEY == valueGet.first.stringKey))
92 blurRadiusDefined = true;
94 if(valueGet.second.GetType() == Dali::Property::STRING)
96 const std::string blurRadiusStr = valueGet.second.Get<std::string>();
97 blurRadius = StringToFloat(blurRadiusStr.c_str());
101 blurRadius = valueGet.second.Get<float>();
106 return 0u == numberOfItems;
109 bool ParseUnderlineProperties(const Property::Map& underlinePropertiesMap,
116 const unsigned int numberOfItems = underlinePropertiesMap.Count();
118 // Parses and applies the style.
119 for(unsigned int index = 0u; index < numberOfItems; ++index)
121 const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue(index);
123 if((DevelText::Underline::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
126 if(valueGet.second.GetType() == Dali::Property::STRING)
128 const std::string enableStr = valueGet.second.Get<std::string>();
129 enabled = Text::TokenComparison(TRUE_TOKEN, enableStr.c_str(), enableStr.size());
133 enabled = valueGet.second.Get<bool>();
136 else if((DevelText::Underline::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
141 if(valueGet.second.GetType() == Dali::Property::STRING)
143 const std::string colorStr = valueGet.second.Get<std::string>();
144 Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
148 color = valueGet.second.Get<Vector4>();
151 else if((DevelText::Underline::Property::HEIGHT == valueGet.first.indexKey) || (HEIGHT_KEY == valueGet.first.stringKey))
154 heightDefined = true;
156 if(valueGet.second.GetType() == Dali::Property::STRING)
158 const std::string heightStr = valueGet.second.Get<std::string>();
159 height = StringToFloat(heightStr.c_str());
163 height = valueGet.second.Get<float>();
168 return 0u == numberOfItems;
171 bool ParseOutlineProperties(const Property::Map& underlinePropertiesMap,
177 const unsigned int numberOfItems = underlinePropertiesMap.Count();
179 // Parses and applies the style.
180 for(unsigned int index = 0u; index < numberOfItems; ++index)
182 const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue(index);
184 if((DevelText::Outline::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
188 color = valueGet.second.Get<Vector4>();
190 else if((DevelText::Outline::Property::WIDTH == valueGet.first.indexKey) || (WIDTH_KEY == valueGet.first.stringKey))
194 width = static_cast<uint16_t>(valueGet.second.Get<float>());
198 return 0u == numberOfItems;
201 bool ParseBackgroundProperties(const Property::Map& backgroundProperties,
206 const unsigned int numberOfItems = backgroundProperties.Count();
208 // Parses and applies the style.
209 for(unsigned int index = 0u; index < numberOfItems; ++index)
211 const KeyValuePair& valueGet = backgroundProperties.GetKeyValue(index);
213 if((DevelText::Background::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
216 enabled = valueGet.second.Get<bool>();
218 else if((DevelText::Background::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
222 color = valueGet.second.Get<Vector4>();
226 return 0u == numberOfItems;
229 bool ParseStrikethroughProperties(const Property::Map& strikethroughPropertiesMap,
236 const unsigned int numberOfItems = strikethroughPropertiesMap.Count();
238 // Parses and applies the style.
239 for(unsigned int index = 0u; index < numberOfItems; ++index)
241 const KeyValuePair& valueGet = strikethroughPropertiesMap.GetKeyValue(index);
243 if((DevelText::Strikethrough::Property::ENABLE == valueGet.first.indexKey) || (ENABLE_KEY == valueGet.first.stringKey))
246 if(valueGet.second.GetType() == Dali::Property::STRING)
248 const std::string enableStr = valueGet.second.Get<std::string>();
249 enabled = Text::TokenComparison(TRUE_TOKEN, enableStr.c_str(), enableStr.size());
253 enabled = valueGet.second.Get<bool>();
256 else if((DevelText::Strikethrough::Property::COLOR == valueGet.first.indexKey) || (COLOR_KEY == valueGet.first.stringKey))
261 if(valueGet.second.GetType() == Dali::Property::STRING)
263 const std::string colorStr = valueGet.second.Get<std::string>();
264 Text::ColorStringToVector4(colorStr.c_str(), colorStr.size(), color);
268 color = valueGet.second.Get<Vector4>();
271 else if((DevelText::Strikethrough::Property::HEIGHT == valueGet.first.indexKey) || (HEIGHT_KEY == valueGet.first.stringKey))
274 heightDefined = true;
276 if(valueGet.second.GetType() == Dali::Property::STRING)
278 const std::string heightStr = valueGet.second.Get<std::string>();
279 height = StringToFloat(heightStr.c_str());
283 height = valueGet.second.Get<float>();
287 return 0u == numberOfItems;
290 bool SetUnderlineProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
298 case EffectStyle::DEFAULT:
300 const Property::Map& propertiesMap = value.Get<Property::Map>();
302 bool enabled = false;
303 bool colorDefined = false;
305 bool heightDefined = false;
310 if(propertiesMap.Empty())
312 // Map empty so check if a string provided
313 const std::string propertyString = value.Get<std::string>();
315 if(!propertyString.empty())
317 Property::Map parsedStringMap;
318 Text::ParsePropertyString(propertyString, parsedStringMap);
320 empty = ParseUnderlineProperties(parsedStringMap,
327 controller->UnderlineSetByString(!empty);
332 empty = ParseUnderlineProperties(propertiesMap,
339 controller->UnderlineSetByString(false);
344 if(enabled != controller->IsUnderlineEnabled())
346 controller->SetUnderlineEnabled(enabled);
350 // Sets the default underline values.
351 if(colorDefined && (controller->GetUnderlineColor() != color))
353 controller->SetUnderlineColor(color);
357 if(heightDefined && (fabsf(controller->GetUnderlineHeight() - height) > Math::MACHINE_EPSILON_1000))
359 controller->SetUnderlineHeight(height);
365 // Disable underline.
366 if(controller->IsUnderlineEnabled())
368 controller->SetUnderlineEnabled(false);
374 case EffectStyle::INPUT:
376 const std::string& underlineProperties = value.Get<std::string>();
378 controller->SetInputUnderlineProperties(underlineProperties);
382 } // if( controller )
387 void GetUnderlineProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
393 case EffectStyle::DEFAULT:
395 const bool enabled = controller->IsUnderlineEnabled();
396 const Vector4& color = controller->GetUnderlineColor();
397 const float height = controller->GetUnderlineHeight();
399 if(controller->IsUnderlineSetByString())
401 std::string underlineProperties = "{\"enable\":";
402 const std::string enabledStr = enabled ? "true" : "false";
403 underlineProperties += "\"" + enabledStr + "\",";
405 std::string colorStr;
406 Vector4ToColorString(color, colorStr);
407 underlineProperties += "\"color\":\"" + colorStr + "\",";
409 std::string heightStr;
410 FloatToString(height, heightStr);
411 underlineProperties += "\"height\":\"" + heightStr + "\"}";
413 value = underlineProperties;
419 map.Insert(ENABLE_KEY, enabled);
420 map.Insert(COLOR_KEY, color);
421 map.Insert(HEIGHT_KEY, height);
428 case EffectStyle::INPUT:
430 value = controller->GetInputUnderlineProperties();
437 bool SetShadowProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
445 case EffectStyle::DEFAULT:
447 const Property::Map& propertiesMap = value.Get<Property::Map>();
449 bool colorDefined = false;
451 bool offsetDefined = false;
453 bool blurRadiusDefined = false;
458 if(propertiesMap.Empty())
460 // Map empty so check if a string provided
461 const std::string propertyString = value.Get<std::string>();
463 Property::Map parsedStringMap;
464 Text::ParsePropertyString(propertyString, parsedStringMap);
466 empty = ParseShadowProperties(parsedStringMap,
474 controller->ShadowSetByString(!empty);
478 empty = ParseShadowProperties(propertiesMap,
486 controller->ShadowSetByString(false);
491 // Sets the default shadow values.
492 if(colorDefined && (controller->GetShadowColor() != color))
494 controller->SetShadowColor(color);
498 if(offsetDefined && (controller->GetShadowOffset() != offset))
500 controller->SetShadowOffset(offset);
504 if(blurRadiusDefined && (controller->GetShadowBlurRadius() != blurRadius))
506 controller->SetShadowBlurRadius(blurRadius);
513 if(Vector2::ZERO != controller->GetShadowOffset())
515 controller->SetShadowOffset(Vector2::ZERO);
520 case EffectStyle::INPUT:
522 const std::string& shadowString = value.Get<std::string>();
524 controller->SetInputShadowProperties(shadowString);
528 } // if( controller )
533 void GetShadowProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
539 case EffectStyle::DEFAULT:
541 const Vector4& color = controller->GetShadowColor();
542 const Vector2& offset = controller->GetShadowOffset();
543 const float& blurRadius = controller->GetShadowBlurRadius();
545 if(controller->IsShadowSetByString())
547 std::string shadowProperties = "{";
549 std::string colorStr;
550 Vector4ToColorString(color, colorStr);
551 shadowProperties += "\"color\":\"" + colorStr + "\",";
553 std::string offsetStr;
554 Vector2ToString(offset, offsetStr);
555 shadowProperties += "\"offset\":\"" + offsetStr + "\",";
557 std::string blurRadiusStr;
558 FloatToString(blurRadius, blurRadiusStr);
559 shadowProperties += "\"blurRadius\":\"" + blurRadiusStr + "\"}";
561 value = shadowProperties;
567 map.Insert(COLOR_KEY, color);
568 map.Insert(OFFSET_KEY, offset);
569 map.Insert(BLUR_RADIUS_KEY, blurRadius);
575 case EffectStyle::INPUT:
577 value = controller->GetInputShadowProperties();
584 bool SetEmbossProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
590 const std::string properties = value.Get<std::string>();
594 case EffectStyle::DEFAULT:
596 // Stores the default emboss's properties string to be recovered by the GetEmbossProperties() function.
597 controller->SetDefaultEmbossProperties(properties);
600 case EffectStyle::INPUT:
602 // Stores the input emboss's properties string to be recovered by the GetEmbossProperties() function.
603 controller->SetInputEmbossProperties(properties);
612 void GetEmbossProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
618 case EffectStyle::DEFAULT:
620 value = controller->GetDefaultEmbossProperties();
623 case EffectStyle::INPUT:
625 value = controller->GetInputEmbossProperties();
632 bool SetOutlineProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
640 case EffectStyle::DEFAULT:
642 const Property::Map& propertiesMap = value.Get<Property::Map>();
644 bool colorDefined = false;
646 bool widthDefined = false;
651 if(propertiesMap.Empty())
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>();
657 // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function.
658 controller->SetDefaultOutlineProperties(propertyString);
660 controller->OutlineSetByString(true);
664 empty = ParseOutlineProperties(propertiesMap,
670 controller->OutlineSetByString(false);
675 // Sets the default outline values.
676 if(colorDefined && (controller->GetOutlineColor() != color))
678 controller->SetOutlineColor(color);
682 if(widthDefined && (controller->GetOutlineWidth() != width))
684 controller->SetOutlineWidth(width);
691 if(0u != controller->GetOutlineWidth())
693 controller->SetOutlineWidth(0u);
699 case EffectStyle::INPUT:
701 const std::string& outlineProperties = value.Get<std::string>();
703 controller->SetInputOutlineProperties(outlineProperties);
707 } // if( controller )
712 void GetOutlineProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
718 case EffectStyle::DEFAULT:
720 if(controller->IsOutlineSetByString())
722 value = controller->GetDefaultOutlineProperties();
727 const Vector4& color = controller->GetOutlineColor();
728 const uint16_t width = controller->GetOutlineWidth();
731 map.Insert(COLOR_KEY, color);
732 map.Insert(WIDTH_KEY, static_cast<int>(width));
739 case EffectStyle::INPUT:
741 value = controller->GetInputOutlineProperties();
748 bool SetBackgroundProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
756 case EffectStyle::DEFAULT:
758 const Property::Map& propertiesMap = value.Get<Property::Map>();
760 bool enabled = false;
761 bool colorDefined = false;
766 if(!propertiesMap.Empty())
768 empty = ParseBackgroundProperties(propertiesMap,
776 if(enabled != controller->IsBackgroundEnabled())
778 controller->SetBackgroundEnabled(enabled);
782 if(colorDefined && (controller->GetBackgroundColor() != color))
784 controller->SetBackgroundColor(color);
790 // Disable background.
791 if(controller->IsBackgroundEnabled())
793 controller->SetBackgroundEnabled(false);
799 case EffectStyle::INPUT:
801 // Text background is not supported while inputting yet
805 } // if( controller )
810 void GetBackgroundProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
816 case EffectStyle::DEFAULT:
818 const bool enabled = controller->IsBackgroundEnabled();
819 const Vector4& color = controller->GetBackgroundColor();
822 map.Insert(ENABLE_KEY, enabled);
823 map.Insert(COLOR_KEY, color);
829 case EffectStyle::INPUT:
831 // Text background is not supported while inputting yet
838 bool SetStrikethroughProperties(ControllerPtr controller, const Property::Value& value, EffectStyle::Type type)
846 case EffectStyle::DEFAULT:
848 const Property::Map& propertiesMap = value.Get<Property::Map>();
850 bool enabled = false;
851 bool colorDefined = false;
853 bool heightDefined = false;
858 if(propertiesMap.Empty())
860 // Map empty so check if a string provided
861 const std::string propertyString = value.Get<std::string>();
863 if(!propertyString.empty())
865 Property::Map parsedStringMap;
866 Text::ParsePropertyString(propertyString, parsedStringMap);
868 empty = ParseStrikethroughProperties(parsedStringMap,
875 controller->StrikethroughSetByString(!empty);
880 empty = ParseStrikethroughProperties(propertiesMap,
887 controller->StrikethroughSetByString(false);
892 if(enabled != controller->IsStrikethroughEnabled())
894 controller->SetStrikethroughEnabled(enabled);
898 // Sets the default strikethrough values.
899 if(colorDefined && (controller->GetStrikethroughColor() != color))
901 controller->SetStrikethroughColor(color);
904 if(heightDefined && (fabsf(controller->GetStrikethroughHeight() - height) > Math::MACHINE_EPSILON_1000))
906 controller->SetStrikethroughHeight(height);
912 // Disable strikethrough.
913 if(controller->IsStrikethroughEnabled())
915 controller->SetStrikethroughEnabled(false);
921 case EffectStyle::INPUT:
923 const std::string& strikethroughProperties = value.Get<std::string>();
925 controller->SetInputStrikethroughProperties(strikethroughProperties);
930 } // if( controller )
935 void GetStrikethroughProperties(ControllerPtr controller, Property::Value& value, EffectStyle::Type type)
941 case EffectStyle::DEFAULT:
943 const bool enabled = controller->IsStrikethroughEnabled();
944 const Vector4& color = controller->GetStrikethroughColor();
945 const float height = controller->GetStrikethroughHeight();
947 if(controller->IsStrikethroughSetByString())
949 std::string strikethroughProperties = "{\"enable\":";
950 const std::string enabledStr = enabled ? "true" : "false";
951 strikethroughProperties += "\"" + enabledStr + "\",";
953 std::string colorStr;
954 Vector4ToColorString(color, colorStr);
955 strikethroughProperties += "\"color\":\"" + colorStr + "\",";
957 std::string heightStr;
958 FloatToString(height, heightStr);
959 strikethroughProperties += "\"height\":\"" + heightStr + "\"}";
961 value = strikethroughProperties;
967 map.Insert(ENABLE_KEY, enabled);
968 map.Insert(COLOR_KEY, color);
969 map.Insert(HEIGHT_KEY, height);
976 case EffectStyle::INPUT:
978 value = controller->GetInputStrikethroughProperties();
987 } // namespace Toolkit