Fix key event propagation in text controller
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-controller-impl-data-clearer.cpp
1 /*
2  * Copyright (c) 2021 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 // CLASS HEADER
19 #include <dali-toolkit/internal/text/text-controller-impl-data-clearer.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/text/text-controller-impl.h>
23 #include <dali-toolkit/internal/text/text-run-container.h>
24
25 namespace Dali::Toolkit::Text
26 {
27
28 void ControllerImplDataClearer::ClearFullModelData(Controller::Impl& impl, Controller::OperationsMask operations)
29 {
30   ModelPtr& model = impl.mModel;
31
32   if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
33   {
34     model->mLogicalModel->mLineBreakInfo.Clear();
35     model->mLogicalModel->mParagraphInfo.Clear();
36   }
37
38   if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
39   {
40     model->mLogicalModel->mScriptRuns.Clear();
41   }
42
43   if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
44   {
45     model->mLogicalModel->mFontRuns.Clear();
46   }
47
48   if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
49   {
50     if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
51     {
52       model->mLogicalModel->mBidirectionalParagraphInfo.Clear();
53       model->mLogicalModel->mCharacterDirections.Clear();
54     }
55
56     if(Controller::NO_OPERATION != (Controller::REORDER & operations))
57     {
58       // Free the allocated memory used to store the conversion table in the bidirectional line info run.
59       for(Vector<BidirectionalLineInfoRun>::Iterator it    = model->mLogicalModel->mBidirectionalLineInfo.Begin(),
60                                                      endIt = model->mLogicalModel->mBidirectionalLineInfo.End();
61           it != endIt;
62           ++it)
63       {
64         BidirectionalLineInfoRun& bidiLineInfo = *it;
65
66         free(bidiLineInfo.visualToLogicalMap);
67         bidiLineInfo.visualToLogicalMap = NULL;
68       }
69       model->mLogicalModel->mBidirectionalLineInfo.Clear();
70     }
71   }
72
73   if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
74   {
75     model->mVisualModel->mGlyphs.Clear();
76     model->mVisualModel->mGlyphsToCharacters.Clear();
77     model->mVisualModel->mCharactersToGlyph.Clear();
78     model->mVisualModel->mCharactersPerGlyph.Clear();
79     model->mVisualModel->mGlyphsPerCharacter.Clear();
80     model->mVisualModel->mGlyphPositions.Clear();
81   }
82
83   if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
84   {
85     model->mVisualModel->mLines.Clear();
86   }
87
88   if(Controller::NO_OPERATION != (Controller::COLOR & operations))
89   {
90     model->mVisualModel->mColorIndices.Clear();
91     model->mVisualModel->mBackgroundColorIndices.Clear();
92   }
93 }
94
95 void ControllerImplDataClearer::ClearCharacterModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
96 {
97   const CharacterIndex endIndexPlusOne = endIndex + 1u;
98   ModelPtr& model = impl.mModel;
99
100   if(Controller::NO_OPERATION != (Controller::GET_LINE_BREAKS & operations))
101   {
102     // Clear the line break info.
103     LineBreakInfo* lineBreakInfoBuffer = model->mLogicalModel->mLineBreakInfo.Begin();
104
105     model->mLogicalModel->mLineBreakInfo.Erase(lineBreakInfoBuffer + startIndex,
106                                                      lineBreakInfoBuffer + endIndexPlusOne);
107
108     // Clear the paragraphs.
109     ClearCharacterRuns(startIndex,
110                        endIndex,
111                        model->mLogicalModel->mParagraphInfo);
112   }
113
114   if(Controller::NO_OPERATION != (Controller::GET_SCRIPTS & operations))
115   {
116     // Clear the scripts.
117     ClearCharacterRuns(startIndex,
118                        endIndex,
119                        model->mLogicalModel->mScriptRuns);
120   }
121
122   if(Controller::NO_OPERATION != (Controller::VALIDATE_FONTS & operations))
123   {
124     // Clear the fonts.
125     ClearCharacterRuns(startIndex,
126                        endIndex,
127                        model->mLogicalModel->mFontRuns);
128   }
129
130   if(0u != model->mLogicalModel->mBidirectionalParagraphInfo.Count())
131   {
132     if(Controller::NO_OPERATION != (Controller::BIDI_INFO & operations))
133     {
134       // Clear the bidirectional paragraph info.
135       ClearCharacterRuns(startIndex,
136                          endIndex,
137                          model->mLogicalModel->mBidirectionalParagraphInfo);
138
139       // Clear the character's directions.
140       CharacterDirection* characterDirectionsBuffer = model->mLogicalModel->mCharacterDirections.Begin();
141
142       model->mLogicalModel->mCharacterDirections.Erase(characterDirectionsBuffer + startIndex,
143                                                        characterDirectionsBuffer + endIndexPlusOne);
144     }
145
146     if(Controller::NO_OPERATION != (Controller::REORDER & operations))
147     {
148       uint32_t startRemoveIndex = model->mLogicalModel->mBidirectionalLineInfo.Count();
149       uint32_t endRemoveIndex   = startRemoveIndex;
150       ClearCharacterRuns(startIndex,
151                          endIndex,
152                          model->mLogicalModel->mBidirectionalLineInfo,
153                          startRemoveIndex,
154                          endRemoveIndex);
155
156       BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = model->mLogicalModel->mBidirectionalLineInfo.Begin();
157
158       // Free the allocated memory used to store the conversion table in the bidirectional line info run.
159       for(Vector<BidirectionalLineInfoRun>::Iterator it    = bidirectionalLineInfoBuffer + startRemoveIndex,
160                                                      endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
161           it != endIt;
162           ++it)
163       {
164         BidirectionalLineInfoRun& bidiLineInfo = *it;
165
166         free(bidiLineInfo.visualToLogicalMap);
167         bidiLineInfo.visualToLogicalMap = NULL;
168       }
169
170       model->mLogicalModel->mBidirectionalLineInfo.Erase(bidirectionalLineInfoBuffer + startRemoveIndex,
171                                                          bidirectionalLineInfoBuffer + endRemoveIndex);
172     }
173   }
174 }
175
176 void ControllerImplDataClearer::ClearGlyphModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
177 {
178   const CharacterIndex endIndexPlusOne           = endIndex + 1u;
179   const Length         numberOfCharactersRemoved = endIndexPlusOne - startIndex;
180   ModelPtr&            model                     = impl.mModel;
181   TextUpdateInfo&      textUpdateInfo            = impl.mTextUpdateInfo;
182
183
184   // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
185   GlyphIndex* charactersToGlyphBuffer  = model->mVisualModel->mCharactersToGlyph.Begin();
186   Length*     glyphsPerCharacterBuffer = model->mVisualModel->mGlyphsPerCharacter.Begin();
187
188   const GlyphIndex endGlyphIndexPlusOne  = *(charactersToGlyphBuffer + endIndex) + *(glyphsPerCharacterBuffer + endIndex);
189   const Length     numberOfGlyphsRemoved = endGlyphIndexPlusOne - textUpdateInfo.mStartGlyphIndex;
190
191   if(Controller::NO_OPERATION != (Controller::SHAPE_TEXT & operations))
192   {
193     // Update the character to glyph indices.
194     for(Vector<GlyphIndex>::Iterator it    = charactersToGlyphBuffer + endIndexPlusOne,
195                                      endIt = charactersToGlyphBuffer + model->mVisualModel->mCharactersToGlyph.Count();
196         it != endIt;
197         ++it)
198     {
199       CharacterIndex& index = *it;
200       index -= numberOfGlyphsRemoved;
201     }
202
203     // Clear the character to glyph conversion table.
204     model->mVisualModel->mCharactersToGlyph.Erase(charactersToGlyphBuffer + startIndex,
205                                                   charactersToGlyphBuffer + endIndexPlusOne);
206
207     // Clear the glyphs per character table.
208     model->mVisualModel->mGlyphsPerCharacter.Erase(glyphsPerCharacterBuffer + startIndex,
209                                                    glyphsPerCharacterBuffer + endIndexPlusOne);
210
211     // Clear the glyphs buffer.
212     GlyphInfo* glyphsBuffer = model->mVisualModel->mGlyphs.Begin();
213     model->mVisualModel->mGlyphs.Erase(glyphsBuffer + textUpdateInfo.mStartGlyphIndex,
214                                        glyphsBuffer + endGlyphIndexPlusOne);
215
216     CharacterIndex* glyphsToCharactersBuffer = model->mVisualModel->mGlyphsToCharacters.Begin();
217
218     // Update the glyph to character indices.
219     for(Vector<CharacterIndex>::Iterator it    = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
220                                          endIt = glyphsToCharactersBuffer + model->mVisualModel->mGlyphsToCharacters.Count();
221         it != endIt;
222         ++it)
223     {
224       CharacterIndex& index = *it;
225       index -= numberOfCharactersRemoved;
226     }
227
228     // Clear the glyphs to characters buffer.
229     model->mVisualModel->mGlyphsToCharacters.Erase(glyphsToCharactersBuffer + textUpdateInfo.mStartGlyphIndex,
230                                                    glyphsToCharactersBuffer + endGlyphIndexPlusOne);
231
232     // Clear the characters per glyph buffer.
233     Length* charactersPerGlyphBuffer = model->mVisualModel->mCharactersPerGlyph.Begin();
234     model->mVisualModel->mCharactersPerGlyph.Erase(charactersPerGlyphBuffer + textUpdateInfo.mStartGlyphIndex,
235                                                    charactersPerGlyphBuffer + endGlyphIndexPlusOne);
236
237     // Should pass if mGlyphPositions has already been cleared in Controller::Relayouter::Relayout
238     if(0u != model->mVisualModel->mGlyphPositions.Count())
239     {
240       // Clear the positions buffer.
241       Vector2* positionsBuffer = model->mVisualModel->mGlyphPositions.Begin();
242       model->mVisualModel->mGlyphPositions.Erase(positionsBuffer + textUpdateInfo.mStartGlyphIndex,
243                                                  positionsBuffer + endGlyphIndexPlusOne);
244     }
245   }
246
247   if(Controller::NO_OPERATION != (Controller::LAYOUT & operations))
248   {
249     // Clear the lines.
250     uint32_t startRemoveIndex = model->mVisualModel->mLines.Count();
251     uint32_t endRemoveIndex   = startRemoveIndex;
252     ClearCharacterRuns(startIndex,
253                        endIndex,
254                        model->mVisualModel->mLines,
255                        startRemoveIndex,
256                        endRemoveIndex);
257
258     // Will update the glyph runs.
259     startRemoveIndex = model->mVisualModel->mLines.Count();
260     endRemoveIndex   = startRemoveIndex;
261     ClearGlyphRuns(textUpdateInfo.mStartGlyphIndex,
262                    endGlyphIndexPlusOne - 1u,
263                    model->mVisualModel->mLines,
264                    startRemoveIndex,
265                    endRemoveIndex);
266
267     // Set the line index from where to insert the new laid-out lines.
268     textUpdateInfo.mStartLineIndex = startRemoveIndex;
269
270     LineRun* linesBuffer = model->mVisualModel->mLines.Begin();
271     model->mVisualModel->mLines.Erase(linesBuffer + startRemoveIndex,
272                                       linesBuffer + endRemoveIndex);
273   }
274
275   if(Controller::NO_OPERATION != (Controller::COLOR & operations))
276   {
277     if(0u != model->mVisualModel->mColorIndices.Count())
278     {
279       ColorIndex* colorIndexBuffer = model->mVisualModel->mColorIndices.Begin();
280       model->mVisualModel->mColorIndices.Erase(colorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
281                                                 colorIndexBuffer + endGlyphIndexPlusOne);
282     }
283
284     if(0u != model->mVisualModel->mBackgroundColorIndices.Count())
285     {
286       ColorIndex* backgroundColorIndexBuffer = model->mVisualModel->mBackgroundColorIndices.Begin();
287       model->mVisualModel->mBackgroundColorIndices.Erase(backgroundColorIndexBuffer + textUpdateInfo.mStartGlyphIndex,
288                                                          backgroundColorIndexBuffer + endGlyphIndexPlusOne);
289     }
290   }
291 }
292
293 void ControllerImplDataClearer::ClearModelData(Controller::Impl& impl, CharacterIndex startIndex, CharacterIndex endIndex, Controller::OperationsMask operations)
294 {
295   TextUpdateInfo& textUpdateInfo = impl.mTextUpdateInfo;
296
297   if(textUpdateInfo.mClearAll ||
298      ((0u == startIndex) &&
299       (textUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u)))
300   {
301     ClearFullModelData(impl, operations);
302   }
303   else
304   {
305     // Clear the model data related with characters.
306     ClearCharacterModelData(impl, startIndex, endIndex, operations);
307
308     // Clear the model data related with glyphs.
309     ClearGlyphModelData(impl, startIndex, endIndex, operations);
310   }
311
312   ModelPtr& model = impl.mModel;
313
314   // The estimated number of lines. Used to avoid reallocations when layouting.
315   textUpdateInfo.mEstimatedNumberOfLines = std::max(model->mVisualModel->mLines.Count(), model->mLogicalModel->mParagraphInfo.Count());
316
317   model->mVisualModel->ClearCaches();
318 }
319
320 } // namespace Dali::Toolkit::Text