Refactoring and documenting the markup tags and attributes
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / markup-processor-underline.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/markup-processor-underline.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/dali-vector.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/text/markup-processor-attribute-helper-functions.h>
26 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
27 #include <dali-toolkit/internal/text/markup-tags-and-attributes.h>
28 #include <dali-toolkit/internal/text/text-effects-style.h>
29 #include <dali-toolkit/internal/text/underlined-character-run.h>
30
31 namespace Dali
32 {
33 namespace Toolkit
34 {
35 namespace Text
36 {
37 namespace
38 {
39 const unsigned int MAX_TYPE_ATTRIBUTE_SIZE = 7u; ///< The maximum length of any of the possible 'type' values.
40
41 } // namespace
42
43 void ProcessTypeAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
44 {
45   underlinedCharacterRun.properties.typeDefined = ProcessEnumerationAttribute<Text::Underline::Type>(attribute,
46                                                                                                      MAX_TYPE_ATTRIBUTE_SIZE,
47                                                                                                      &StringToUnderlineType,
48                                                                                                      underlinedCharacterRun.properties.type);
49 }
50
51 void ProcessDashGapAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
52 {
53   underlinedCharacterRun.properties.dashGap        = ProcessFloatAttribute(attribute);
54   underlinedCharacterRun.properties.dashGapDefined = true;
55 }
56
57 void ProcessDashWidthAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
58 {
59   underlinedCharacterRun.properties.dashWidth        = ProcessFloatAttribute(attribute);
60   underlinedCharacterRun.properties.dashWidthDefined = true;
61 }
62 void ProcessHeightAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
63 {
64   underlinedCharacterRun.properties.height        = ProcessFloatAttribute(attribute);
65   underlinedCharacterRun.properties.heightDefined = true;
66 }
67
68 void ProcessColorAttribute(const Attribute& attribute, UnderlinedCharacterRun& underlinedCharacterRun)
69 {
70   ColorStringToVector4(attribute.valueBuffer, attribute.valueLength, underlinedCharacterRun.properties.color);
71   underlinedCharacterRun.properties.colorDefined = true;
72 }
73
74 void ProcessUnderlineTag(const Tag& tag, UnderlinedCharacterRun& underlinedCharacterRun)
75 {
76   for(Vector<Attribute>::ConstIterator it    = tag.attributes.Begin(),
77                                        endIt = tag.attributes.End();
78       it != endIt;
79       ++it)
80   {
81     const Attribute& attribute(*it);
82
83     if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::COLOR, attribute.nameBuffer, attribute.nameLength))
84     {
85       ProcessColorAttribute(attribute, underlinedCharacterRun);
86     }
87     else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::HEIGHT, attribute.nameBuffer, attribute.nameLength))
88     {
89       ProcessHeightAttribute(attribute, underlinedCharacterRun);
90     }
91     else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::TYPE, attribute.nameBuffer, attribute.nameLength))
92     {
93       ProcessTypeAttribute(attribute, underlinedCharacterRun);
94     }
95     else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_GAP, attribute.nameBuffer, attribute.nameLength))
96     {
97       ProcessDashGapAttribute(attribute, underlinedCharacterRun);
98     }
99     else if(TokenComparison(MARKUP::UNDERLINE_ATTRIBUTES::DASH_WIDTH, attribute.nameBuffer, attribute.nameLength))
100     {
101       ProcessDashWidthAttribute(attribute, underlinedCharacterRun);
102     }
103   }
104 }
105
106 void OverrideNestedUnderlinedCharacterRuns(Vector<UnderlinedCharacterRun>& underlinedCharacterRuns)
107 {
108   // Handle nested tags
109   // The inner tag inherit the attributes of the outer tag and override them when defined in the inner tag.
110   // Example:
111   // <u height='5.0f' color='blue'> outer tag before  <u color='green'> inner tag </u> outer tag after </u>
112   // "outer tag before" and  "outer tag after" have height = 5.0f and color = 'blue'
113   // "inner tag" has height = 5.0f and color = 'green'
114
115   if(underlinedCharacterRuns.Count() > 0u)
116   {
117     Vector<UnderlinedCharacterRun>::ConstIterator preIt = underlinedCharacterRuns.Begin();
118
119     Vector<UnderlinedCharacterRun>::Iterator      it    = underlinedCharacterRuns.Begin() + 1;
120     Vector<UnderlinedCharacterRun>::ConstIterator endIt = underlinedCharacterRuns.End();
121
122     while(it != endIt)
123     {
124       const UnderlinedCharacterRun& run                = *it;
125       const CharacterIndex&         characterIndex     = run.characterRun.characterIndex;
126       const Length&                 numberOfCharacters = run.characterRun.numberOfCharacters;
127
128       const UnderlinedCharacterRun& preRun                = *preIt;
129       const CharacterIndex&         preCharacterIndex     = preRun.characterRun.characterIndex;
130       const Length&                 preNumberOfCharacters = preRun.characterRun.numberOfCharacters;
131
132       if((preCharacterIndex <= characterIndex) &&
133          ((characterIndex + numberOfCharacters) <= (preCharacterIndex + preNumberOfCharacters)))
134       {
135         it->properties.CopyIfNotDefined(preIt->properties);
136       }
137
138       it++;
139       preIt++;
140     }
141   }
142 }
143
144 } // namespace Text
145
146 } // namespace Toolkit
147
148 } // namespace Dali