Merge "Lines added to the model." into new_text
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / visual-model.cpp
1 /*
2  * Copyright (c) 2015 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/visual-model.h>
20
21 // EXTERNAL INCLUDES
22 #include <memory.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-vector.h>
26 #include <dali/public-api/math/vector2.h>
27 #include <dali-toolkit/internal/text/line-run.h>
28
29 namespace Dali
30 {
31
32 namespace Toolkit
33 {
34
35 namespace Text
36 {
37
38 /**
39  * @brief caches some temporary values of the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation
40  * as they are going to be used in the GetLinesOfGlyphRange() call.
41  */
42 struct GetLineCache
43 {
44   GlyphIndex glyphIndex;     ///< The glyph index.
45   Length     numberOfGlyphs; ///< The number of glyphs.
46   Length     firstLine;      ///< Index to the first line.
47   Length     numberOfLines;  ///< The number of lines.
48 };
49
50 struct VisualModel::Impl
51 {
52   Vector<GlyphInfo>      mGlyphs;             ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics.
53   Vector<CharacterIndex> mGlyphsToCharacters; ///< For each glyph, the index of the first character.
54   Vector<GlyphIndex>     mCharactersToGlyph;  ///< For each character, the index of the first glyph.
55   Vector<Length>         mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph.
56   Vector<Vector2>        mGlyphPositions;     ///< For each glyph, the position.
57   Vector<LineRun>        mLines;              ///< The laid out lines.
58
59   Size                   mNaturalSize;        ///< Size of the text with no line wrapping.
60   Size                   mActualSize;         ///< Size of the laid-out text considering the layout properties set.
61
62   GetLineCache           mGetLineCache;       ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation.
63 };
64
65 VisualModelPtr VisualModel::New()
66 {
67   return VisualModelPtr( new VisualModel() );
68 }
69
70 void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
71                              const CharacterIndex* characterIndices,
72                              const Length* charactersPerGlyph,
73                              Length numberOfGlyphs )
74 {
75   Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
76   modelGlyphs.Resize( numberOfGlyphs );
77   memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) );
78
79   Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
80   modelGlyphsToCharacters.Resize( numberOfGlyphs );
81   memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) );
82
83   Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
84   modelCharactersPerGlyph.Resize( numberOfGlyphs );
85   memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
86
87   // Build the characters to glyph conversion table.
88   Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
89
90   // 1) Reserve some space for the characters to avoid reallocations.
91   modelCharactersToGlyph.Reserve( static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f ) );
92
93   // 2) Traverse the glyphs and set the glyph indices.
94   GlyphIndex glyphIndex = 0u;
95   Length totalNumberOfCharacters = 0u;
96   for( Vector<Length>::ConstIterator it = modelCharactersPerGlyph.Begin(),
97          endIt = modelCharactersPerGlyph.End();
98        it != endIt;
99        ++it, ++glyphIndex )
100   {
101     const Length numberOfCharacters = *it;
102
103     for( Length index = 0u; index < numberOfCharacters; ++index, ++totalNumberOfCharacters )
104     {
105       modelCharactersToGlyph.PushBack( glyphIndex );
106     }
107   }
108 }
109
110 Length VisualModel::GetNumberOfGlyphs() const
111 {
112   return mImpl->mGlyphs.Count();
113 }
114
115 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
116                              GlyphIndex glyphIndex,
117                              Length numberOfGlyphs ) const
118 {
119   const Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
120   memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
121 }
122
123 const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
124 {
125   return mImpl->mGlyphs[glyphIndex];
126 }
127
128 CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
129 {
130   return mImpl->mGlyphsToCharacters[glyphIndex];
131 }
132
133 Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
134 {
135   return mImpl->mCharactersPerGlyph[glyphIndex];
136 }
137
138 GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
139 {
140   return mImpl->mCharactersToGlyph[characterIndex];
141 }
142
143 void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
144                                           CharacterIndex characterIndex,
145                                           Length numberOfCharacters ) const
146 {
147   const Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
148   memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
149 }
150
151 void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
152                                             GlyphIndex glyphIndex,
153                                             Length numberOfGlyphs ) const
154 {
155   const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
156   memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
157 }
158
159 void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
160                                           GlyphIndex glyphIndex,
161                                           Length numberOfGlyphs ) const
162 {
163   const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
164   memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
165 }
166
167 void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
168                                      Length numberOfGlyphs )
169 {
170   Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
171   modelPositions.Resize( numberOfGlyphs );
172   memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
173 }
174
175 Length VisualModel::GetNumberOfGlyphPositions() const
176 {
177   return mImpl->mGlyphPositions.Count();
178 }
179
180 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
181                                      GlyphIndex glyphIndex,
182                                      Length numberOfGlyphs ) const
183 {
184   const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
185   memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
186 }
187
188 const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
189 {
190   return *( mImpl->mGlyphPositions.Begin() + glyphIndex );
191 }
192
193 void VisualModel::SetLines( const LineRun* const lines,
194                             Length numberOfLines )
195 {
196   Vector<LineRun>& modelLines = mImpl->mLines;
197   GetLineCache& lineCache = mImpl->mGetLineCache;
198
199   modelLines.Resize( numberOfLines );
200   memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
201
202   // Clear the get line cache.
203   lineCache.glyphIndex = 0u;
204   lineCache.numberOfGlyphs = 0u;
205   lineCache.firstLine = 0u;
206   lineCache.numberOfLines = 0u;
207 }
208
209 Length VisualModel::GetNumberOfLines() const
210 {
211   return mImpl->mLines.Count();
212 }
213
214 void VisualModel::GetLines( LineRun* lines,
215                             LineIndex lineIndex,
216                             Length numberOfLines ) const
217 {
218   const Vector<LineRun>& modelLines = mImpl->mLines;
219   memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
220 }
221
222 Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
223                                       Length numberOfGlyphs ) const
224 {
225   // If is likely the user query consecutively for the number of lines with the same
226   // glyph index and number of glyphs, use the cache could be considered.
227   GetLineCache& lineCache = mImpl->mGetLineCache;
228
229   // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange().
230   lineCache.glyphIndex = glyphIndex;
231   lineCache.numberOfGlyphs = numberOfGlyphs;
232
233   // Check first if the query is for the total number of glyphs.
234   const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count();
235
236   if( ( 0u == glyphIndex ) &&
237       ( totalNumberOfGlyphs == numberOfGlyphs ) )
238   {
239     lineCache.firstLine = 0u;
240     lineCache.numberOfLines = mImpl->mLines.Count();
241
242     return lineCache.numberOfLines;
243   }
244
245   // Initialize the number of lines and the first line.
246   lineCache.numberOfLines = 0u;
247   lineCache.firstLine = 0u;
248   bool firstLineFound = false;
249
250   const Vector<LineRun>& modelLines = mImpl->mLines;
251   const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
252
253   // Traverse the lines and cound those lines within the range of glyphs.
254   for( Vector<LineRun>::ConstIterator it = modelLines.Begin(),
255          endIt = modelLines.End();
256        it != endIt;
257        ++it )
258   {
259     const LineRun& line = *it;
260
261     if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
262         ( lastGlyphIndex > line.glyphIndex ) )
263     {
264       firstLineFound = true;
265       ++lineCache.numberOfLines;
266     }
267     else if( lastGlyphIndex <= line.glyphIndex )
268     {
269       // nothing else to do.
270       break;
271     }
272
273     if( !firstLineFound )
274     {
275       ++lineCache.firstLine;
276     }
277   }
278
279   return lineCache.numberOfLines;
280 }
281
282 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
283                                         GlyphIndex glyphIndex,
284                                         Length numberOfGlyphs ) const
285 {
286   const Vector<LineRun>& modelLines = mImpl->mLines;
287   GetLineCache& lineCache = mImpl->mGetLineCache;
288
289   if( ( glyphIndex != lineCache.glyphIndex ) ||
290       ( numberOfGlyphs != lineCache.numberOfGlyphs ) )
291   {
292     GetNumberOfLines( glyphIndex,
293                       numberOfGlyphs );
294   }
295
296   memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) );
297 }
298
299 void VisualModel::SetNaturalSize( const Vector2& size  )
300 {
301   mImpl->mNaturalSize = size;
302 }
303
304 const Vector2& VisualModel::GetNaturalSize() const
305 {
306   return mImpl->mNaturalSize;
307 }
308
309 void VisualModel::SetActualSize( const Vector2& size )
310 {
311   mImpl->mActualSize = size;
312 }
313
314 const Vector2& VisualModel::GetActualSize() const
315 {
316   return mImpl->mActualSize;
317 }
318
319 VisualModel::~VisualModel()
320 {
321   delete mImpl;
322 }
323
324 VisualModel::VisualModel()
325 : mImpl( NULL )
326 {
327   mImpl = new VisualModel::Impl();
328 }
329
330 } // namespace Text
331
332 } // namespace Toolkit
333
334 } // namespace Dali