TextModel - Create the text segmentation info for a given range of characters inside...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-run-container.h
1 #ifndef __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
2 #define __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/text/character-run.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Text
31 {
32
33 /**
34  * @brief Clears the runs starting from the given character index.
35  *
36  * @param[in] startIndex The starting character index used to remove runs.
37  * @param[in] endIndex The ending character index used to remove runs.
38  * @param[in,out] runs The text's runs.
39  * @param[out] startRemoveIndex The index to the first run to be removed.
40  * @param[out] endRemoveIndex The index to the last run to be removed.
41  */
42 template< typename T >
43 void ClearCharacterRuns( CharacterIndex startIndex,
44                          CharacterIndex endIndex,
45                          Vector<T>& runs,
46                          uint32_t& startRemoveIndex,
47                          uint32_t& endRemoveIndex )
48 {
49   T* runsBuffer = runs.Begin();
50
51   const Length length = runs.Count();
52   for( Length index = 0u; index < length; ++index )
53   {
54     T* run = ( runsBuffer + index );
55
56     if( ( run->characterRun.characterIndex <= endIndex ) &&
57         ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
58     {
59       // Run found.
60
61       // Set the index to the first run to be removed.
62       startRemoveIndex = index;
63       break;
64     }
65   }
66
67   for( Length index = startRemoveIndex; index < length; ++index )
68   {
69     T* run = ( runsBuffer + index );
70
71     if( ( run->characterRun.characterIndex <= endIndex ) &&
72         ( startIndex < run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
73     {
74       // Update the index to the last run to be removed.
75       endRemoveIndex = index + 1u;
76     }
77     else
78     {
79       // Run found. Nothing else to do.
80       break;
81     }
82   }
83
84   // The number of characters to remove.
85   const Length numberOfCharactersRemoved = 1u + endIndex - startIndex;
86
87   // Update the character index of the next runs.
88   for( Length index = 0u; index < length; ++index )
89   {
90     T* run = ( runsBuffer + index );
91
92     if( run->characterRun.characterIndex > startIndex )
93     {
94       run->characterRun.characterIndex -= numberOfCharactersRemoved;
95     }
96   }
97 }
98
99 /**
100  * @brief Clears the runs starting from the given character index.
101  *
102  * @param[in] startIndex The starting character index used to remove runs.
103  * @param[in] endIndex The ending character index used to remove runs.
104  * @param[in,out] runs The text's runs.
105  */
106 template< typename T >
107 void ClearCharacterRuns( CharacterIndex startIndex,
108                          CharacterIndex endIndex,
109                          Vector<T>& runs )
110 {
111   uint32_t startRemoveIndex = runs.Count();
112   uint32_t endRemoveIndex = startRemoveIndex;
113   ClearCharacterRuns( startIndex,
114                       endIndex,
115                       runs,
116                       startRemoveIndex,
117                       endRemoveIndex );
118
119   // Remove all remaining runs.
120   T* runBuffer = runs.Begin();
121   runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
122 }
123
124 /**
125  * @brief Updates the number of characters and the character index of the text's style runs.
126  *
127  * If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.
128  *
129  * It deletes runs if all their characters are removed.
130  *
131  * @param[in] index Index to the first character updated.
132  * @param[in] numberOfCharacters The number of characters to be updated.
133  * @param[in] totalNumberOfCharacters Total number of characters of the text.
134  * @param[in,out] runs The text's style runs.
135  * @param[out] removedRuns The text's style removed runs.
136  */
137 template< typename T >
138 void UpdateCharacterRuns( CharacterIndex index,
139                           int numberOfCharacters,
140                           Length totalNumberOfCharacters,
141                           Vector<T>& runs,
142                           Vector<T>& removedRuns )
143 {
144   if( 0 > numberOfCharacters )
145   {
146     // Remove characters.
147     const Length numberOfRemovedCharacters = -numberOfCharacters;
148
149     if( ( 0u == index ) && ( numberOfRemovedCharacters == totalNumberOfCharacters ) )
150     {
151       // Set the removed runs.
152       removedRuns = runs;
153
154       // All characters are removed.
155       runs.Clear();
156
157       // Nothing else to do.
158       return;
159     }
160
161     const VectorBase::SizeType size = runs.Count();
162     // Temporary vector used to remove runs.
163     Vector<T> tempRuns;
164     // Reserve some space for the temporary vector.
165     tempRuns.Reserve( size );
166     removedRuns.Reserve( size );
167
168     // Whether any run has to be removed.
169     bool runsRemoved = false;
170
171     // Index to the last character added/removed.
172     const CharacterIndex lastIndex = index + numberOfRemovedCharacters - 1u;
173
174     // Update the style runs
175     for( typename Vector<T>::Iterator it = runs.Begin(),
176            endIt = runs.End();
177          it != endIt;
178          ++it )
179     {
180       T& run = *it;
181
182       const CharacterIndex lastRunIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u;
183
184       if( lastRunIndex < index )
185       {
186         // The style run is not affected by the removed text.
187         tempRuns.PushBack( run );
188         continue;
189       }
190
191       if( ( index <= run.characterRun.characterIndex ) &&
192           ( lastIndex >= lastRunIndex ) )
193       {
194         // Add the removed run into the vector.
195         removedRuns.PushBack( run );
196
197         // All the characters are removed.
198         runsRemoved = true;
199       }
200       else
201       {
202         if( lastIndex < run.characterRun.characterIndex )
203         {
204           // Just move the character index.
205           run.characterRun.characterIndex -= numberOfRemovedCharacters;
206         }
207         else
208         {
209           if( run.characterRun.characterIndex < index )
210           {
211             // Remove characters starting from a character within the run.
212             run.characterRun.numberOfCharacters -= std::min( numberOfRemovedCharacters, 1u + lastRunIndex - index );
213           }
214           else
215           {
216             // Remove characters starting from a character located before the first index of the run.
217             run.characterRun.numberOfCharacters -= 1u + lastIndex - run.characterRun.characterIndex;
218             run.characterRun.characterIndex = index;
219           }
220         }
221
222         tempRuns.PushBack( run );
223       }
224     }
225
226     // Copy the temporary vector if there are runs removed.
227     if( runsRemoved )
228     {
229       runs = tempRuns;
230     }
231   }
232   else
233   {
234     // Add characters.
235
236     // Update the style runs
237     for( typename Vector<T>::Iterator it = runs.Begin(),
238            endIt = runs.End();
239          it != endIt;
240          ++it )
241     {
242       T& run = *it;
243
244       // Update the number of characters of the style run.
245
246       if( ( 0u == index ) && ( 0u == run.characterRun.characterIndex ) )
247       {
248         run.characterRun.numberOfCharacters += numberOfCharacters;
249       }
250       else if( index <= run.characterRun.characterIndex )
251       {
252         run.characterRun.characterIndex += numberOfCharacters;
253       }
254       else if( index <= run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
255       {
256         run.characterRun.numberOfCharacters += numberOfCharacters;
257       }
258     }
259   }
260 }
261
262 } // namespace Text
263
264 } // namespace Toolkit
265
266 } // namespace Dali
267
268 #endif // __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__