Lines added to the model.
[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 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
176                                      GlyphIndex glyphIndex,
177                                      Length numberOfGlyphs ) const
178 {
179   const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
180   memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
181 }
182
183 const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
184 {
185   return *( mImpl->mGlyphPositions.Begin() + glyphIndex );
186 }
187
188 void VisualModel::SetLines( const LineRun* const lines,
189                             Length numberOfLines )
190 {
191   Vector<LineRun>& modelLines = mImpl->mLines;
192   GetLineCache& lineCache = mImpl->mGetLineCache;
193
194   modelLines.Resize( numberOfLines );
195   memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
196
197   // Clear the get line cache.
198   lineCache.glyphIndex = 0u;
199   lineCache.numberOfGlyphs = 0u;
200   lineCache.firstLine = 0u;
201   lineCache.numberOfLines = 0u;
202 }
203
204 Length VisualModel::GetNumberOfLines() const
205 {
206   return mImpl->mLines.Count();
207 }
208
209 void VisualModel::GetLines( LineRun* lines,
210                             LineIndex lineIndex,
211                             Length numberOfLines ) const
212 {
213   const Vector<LineRun>& modelLines = mImpl->mLines;
214   memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
215 }
216
217 Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
218                                       Length numberOfGlyphs ) const
219 {
220   // If is likely the user query consecutively for the number of lines with the same
221   // glyph index and number of glyphs, use the cache could be considered.
222   GetLineCache& lineCache = mImpl->mGetLineCache;
223
224   // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange().
225   lineCache.glyphIndex = glyphIndex;
226   lineCache.numberOfGlyphs = numberOfGlyphs;
227
228   // Check first if the query is for the total number of glyphs.
229   const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count();
230
231   if( ( 0u == glyphIndex ) &&
232       ( totalNumberOfGlyphs == numberOfGlyphs ) )
233   {
234     lineCache.firstLine = 0u;
235     lineCache.numberOfLines = mImpl->mLines.Count();
236
237     return lineCache.numberOfLines;
238   }
239
240   // Initialize the number of lines and the first line.
241   lineCache.numberOfLines = 0u;
242   lineCache.firstLine = 0u;
243   bool firstLineFound = false;
244
245   const Vector<LineRun>& modelLines = mImpl->mLines;
246   const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
247
248   // Traverse the lines and cound those lines within the range of glyphs.
249   for( Vector<LineRun>::ConstIterator it = modelLines.Begin(),
250          endIt = modelLines.End();
251        it != endIt;
252        ++it )
253   {
254     const LineRun& line = *it;
255
256     if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
257         ( lastGlyphIndex > line.glyphIndex ) )
258     {
259       firstLineFound = true;
260       ++lineCache.numberOfLines;
261     }
262     else if( lastGlyphIndex <= line.glyphIndex )
263     {
264       // nothing else to do.
265       break;
266     }
267
268     if( !firstLineFound )
269     {
270       ++lineCache.firstLine;
271     }
272   }
273
274   return lineCache.numberOfLines;
275 }
276
277 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
278                                         GlyphIndex glyphIndex,
279                                         Length numberOfGlyphs ) const
280 {
281   const Vector<LineRun>& modelLines = mImpl->mLines;
282   GetLineCache& lineCache = mImpl->mGetLineCache;
283
284   if( ( glyphIndex != lineCache.glyphIndex ) ||
285       ( numberOfGlyphs != lineCache.numberOfGlyphs ) )
286   {
287     GetNumberOfLines( glyphIndex,
288                       numberOfGlyphs );
289   }
290
291   memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) );
292 }
293
294 void VisualModel::SetNaturalSize( const Vector2& size  )
295 {
296   mImpl->mNaturalSize = size;
297 }
298
299 const Vector2& VisualModel::GetNaturalSize() const
300 {
301   return mImpl->mNaturalSize;
302 }
303
304 void VisualModel::SetActualSize( const Vector2& size )
305 {
306   mImpl->mActualSize = size;
307 }
308
309 const Vector2& VisualModel::GetActualSize() const
310 {
311   return mImpl->mActualSize;
312 }
313
314 VisualModel::~VisualModel()
315 {
316   delete mImpl;
317 }
318
319 VisualModel::VisualModel()
320 : mImpl( NULL )
321 {
322   mImpl = new VisualModel::Impl();
323 }
324
325 } // namespace Text
326
327 } // namespace Toolkit
328
329 } // namespace Dali