Using delete[] for pointer that created with new[]
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-run-container.h
1 #ifndef __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__
2 #define __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__
3
4 /*
5  * Copyright (c) 2016 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   T* run = runsBuffer;
51
52   const Length length = runs.Count();
53   Length index = 0u;
54   for( index = 0u; index < length; ++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     ++run;
67   }
68
69   run = ( runsBuffer + startRemoveIndex );
70   for( index = startRemoveIndex; index < length; ++index )
71   {
72     if( ( run->characterRun.characterIndex > endIndex ) ||
73         ( startIndex >= run->characterRun.characterIndex + run->characterRun.numberOfCharacters ) )
74     {
75       // Run found. Nothing else to do.
76       break;
77     }
78     ++run;
79   }
80   endRemoveIndex = index;
81
82   // The number of characters to remove.
83   const Length numberOfCharactersRemoved = 1u + endIndex - startIndex;
84
85   // Update the character index of the next runs.
86   run = runsBuffer;
87   for( Length index = 0u; index < length; ++index )
88   {
89     if( run->characterRun.characterIndex > startIndex )
90     {
91       run->characterRun.characterIndex -= numberOfCharactersRemoved;
92     }
93
94     ++run;
95   }
96 }
97
98 /**
99  * @brief Clears the runs starting from the given character index.
100  *
101  * @param[in] startIndex The starting character index used to remove runs.
102  * @param[in] endIndex The ending character index used to remove runs.
103  * @param[in,out] runs The text's runs.
104  */
105 template< typename T >
106 void ClearCharacterRuns( CharacterIndex startIndex,
107                          CharacterIndex endIndex,
108                          Vector<T>& runs )
109 {
110   uint32_t startRemoveIndex = runs.Count();
111   uint32_t endRemoveIndex = startRemoveIndex;
112   ClearCharacterRuns( startIndex,
113                       endIndex,
114                       runs,
115                       startRemoveIndex,
116                       endRemoveIndex );
117
118   // Remove all remaining runs.
119   T* runBuffer = runs.Begin();
120   runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
121 }
122
123 /**
124  * @brief Updates the number of characters and the character index of the text's style runs.
125  *
126  * If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.
127  *
128  * It deletes runs if all their characters are removed.
129  *
130  * @param[in] index Index to the first character updated.
131  * @param[in] numberOfCharacters The number of characters to be updated.
132  * @param[in] totalNumberOfCharacters Total number of characters of the text.
133  * @param[in,out] runs The text's style runs.
134  * @param[out] removedRuns The text's style removed runs.
135  */
136 template< typename T >
137 void UpdateCharacterRuns( CharacterIndex index,
138                           int numberOfCharacters,
139                           Length totalNumberOfCharacters,
140                           Vector<T>& runs,
141                           Vector<T>& removedRuns )
142 {
143   if( 0 > numberOfCharacters )
144   {
145     // Remove characters.
146     const Length numberOfRemovedCharacters = -numberOfCharacters;
147
148     if( ( 0u == index ) && ( numberOfRemovedCharacters == totalNumberOfCharacters ) )
149     {
150       // Set the removed runs.
151       removedRuns = runs;
152
153       // All characters are removed.
154       runs.Clear();
155
156       // Nothing else to do.
157       return;
158     }
159
160     const VectorBase::SizeType size = runs.Count();
161     // Temporary vector used to remove runs.
162     Vector<T> tempRuns;
163     // Reserve some space for the temporary vector.
164     tempRuns.Reserve( size );
165     removedRuns.Reserve( size );
166
167     // Whether any run has to be removed.
168     bool runsRemoved = false;
169
170     // Index to the last character added/removed.
171     const CharacterIndex lastIndex = index + numberOfRemovedCharacters - 1u;
172
173     // Update the style runs
174     for( typename Vector<T>::Iterator it = runs.Begin(),
175            endIt = runs.End();
176          it != endIt;
177          ++it )
178     {
179       T& run = *it;
180
181       const CharacterIndex lastRunIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u;
182
183       if( lastRunIndex < index )
184       {
185         // The style run is not affected by the removed text.
186         tempRuns.PushBack( run );
187         continue;
188       }
189
190       if( ( index <= run.characterRun.characterIndex ) &&
191           ( lastIndex >= lastRunIndex ) )
192       {
193         // Add the removed run into the vector.
194         removedRuns.PushBack( run );
195
196         // All the characters are removed.
197         runsRemoved = true;
198       }
199       else
200       {
201         if( lastIndex < run.characterRun.characterIndex )
202         {
203           // Just move the character index.
204           run.characterRun.characterIndex -= numberOfRemovedCharacters;
205         }
206         else
207         {
208           if( run.characterRun.characterIndex < index )
209           {
210             // Remove characters starting from a character within the run.
211             run.characterRun.numberOfCharacters -= std::min( numberOfRemovedCharacters, 1u + lastRunIndex - index );
212           }
213           else
214           {
215             // Remove characters starting from a character located before the first index of the run.
216             run.characterRun.numberOfCharacters -= 1u + lastIndex - run.characterRun.characterIndex;
217             run.characterRun.characterIndex = index;
218           }
219         }
220
221         tempRuns.PushBack( run );
222       }
223     }
224
225     // Copy the temporary vector if there are runs removed.
226     if( runsRemoved )
227     {
228       runs = tempRuns;
229     }
230   }
231   else
232   {
233     // Add characters.
234
235     // Update the style runs
236     for( typename Vector<T>::Iterator it = runs.Begin(),
237            endIt = runs.End();
238          it != endIt;
239          ++it )
240     {
241       T& run = *it;
242
243       // Update the number of characters of the style run.
244
245       if( ( 0u == index ) && ( 0u == run.characterRun.characterIndex ) )
246       {
247         run.characterRun.numberOfCharacters += numberOfCharacters;
248       }
249       else if( index <= run.characterRun.characterIndex )
250       {
251         run.characterRun.characterIndex += numberOfCharacters;
252       }
253       else if( index <= run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
254       {
255         run.characterRun.numberOfCharacters += numberOfCharacters;
256       }
257     }
258   }
259 }
260
261 /**
262  * @brief Clears the runs starting from the given glyph index.
263  *
264  * @param[in] startIndex The starting glyph index used to remove runs.
265  * @param[in] endIndex The ending glyph index used to remove runs.
266  * @param[in,out] runs The text's runs.
267  * @param[out] startRemoveIndex The index to the first run to be removed.
268  * @param[out] endRemoveIndex The index to the last run to be removed.
269  */
270 template< typename T >
271 void ClearGlyphRuns( GlyphIndex startIndex,
272                      GlyphIndex endIndex,
273                      Vector<T>& runs,
274                      uint32_t& startRemoveIndex,
275                      uint32_t& endRemoveIndex )
276 {
277   T* runsBuffer = runs.Begin();
278   T* run = runsBuffer;
279
280   const Length length = runs.Count();
281   Length index = 0u;
282   for( index = 0u; index < length; ++index )
283   {
284     if( ( run->glyphRun.glyphIndex <= endIndex ) &&
285         ( startIndex < run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) )
286     {
287       // Run found.
288
289       // Set the index to the first run to be removed.
290       startRemoveIndex = index;
291       break;
292     }
293     ++run;
294   }
295
296   run = ( runsBuffer + startRemoveIndex );
297   for( index = startRemoveIndex; index < length; ++index )
298   {
299     if( ( run->glyphRun.glyphIndex > endIndex ) ||
300         ( startIndex >= run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) )
301     {
302       // Run found. Nothing else to do.
303       break;
304     }
305
306     ++run;
307   }
308   endRemoveIndex = index;
309
310   // The number of glyphs to remove.
311   const Length numberOfGlyphsRemoved = 1u + endIndex - startIndex;
312
313   // Update the glyph index of the next runs.
314   run = runsBuffer;
315   for( Length index = 0u; index < length; ++index )
316   {
317
318     if( run->glyphRun.glyphIndex > startIndex )
319     {
320       run->glyphRun.glyphIndex -= numberOfGlyphsRemoved;
321     }
322   }
323 }
324
325 /**
326  * @brief Clears the runs starting from the given glyph index.
327  *
328  * @param[in] startIndex The starting glyph index used to remove runs.
329  * @param[in] endIndex The ending glyph index used to remove runs.
330  * @param[in,out] runs The text's runs.
331  */
332 template< typename T >
333 void ClearGlyphRuns( GlyphIndex startIndex,
334                      GlyphIndex endIndex,
335                      Vector<T>& runs )
336 {
337   uint32_t startRemoveIndex = runs.Count();
338   uint32_t endRemoveIndex = startRemoveIndex;
339   ClearGlyphRuns( startIndex,
340                   endIndex,
341                   runs,
342                   startRemoveIndex,
343                   endRemoveIndex );
344
345   // Remove all remaining runs.
346   T* runBuffer = runs.Begin();
347   runs.Erase( runBuffer + startRemoveIndex, runBuffer + endRemoveIndex );
348 }
349
350 } // namespace Text
351
352 } // namespace Toolkit
353
354 } // namespace Dali
355
356 #endif // __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__