2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/text/visual-model.h>
23 #include <dali/public-api/common/dali-vector.h>
24 #include <dali/public-api/math/vector2.h>
27 #include <dali-toolkit/internal/text/line-run.h>
39 * @brief caches some temporary values of the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation
40 * as they are going to be used in the GetLinesOfGlyphRange() call.
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.
50 struct VisualModel::Impl
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<Length> mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped.
57 Vector<Vector2> mGlyphPositions; ///< For each glyph, the position.
58 Vector<LineRun> mLines; ///< The laid out lines.
60 Size mNaturalSize; ///< Size of the text with no line wrapping.
61 Size mActualSize; ///< Size of the laid-out text considering the layout properties set.
63 GetLineCache mGetLineCache; ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation.
66 VisualModelPtr VisualModel::New()
68 return VisualModelPtr( new VisualModel() );
71 void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
72 const CharacterIndex* characterIndices,
73 const Length* charactersPerGlyph,
74 Length numberOfGlyphs )
76 Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
77 Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
78 Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
79 Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
80 Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
82 if( 0u == numberOfGlyphs )
85 modelGlyphsToCharacters.Clear();
86 modelCharactersToGlyph.Clear();
87 modelCharactersPerGlyph.Clear();
88 modelGlyphsPerCharacter.Clear();
94 modelGlyphs.Resize( numberOfGlyphs );
95 memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) );
98 if( NULL != characterIndices )
100 modelGlyphsToCharacters.Resize( numberOfGlyphs );
101 memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) );
104 if( NULL != charactersPerGlyph )
106 modelCharactersPerGlyph.Resize( numberOfGlyphs );
107 memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
109 // Build the characters to glyph conversion table.
111 // 1) Reserve some space for the characters to avoid reallocations.
112 const Length numberOfCharacters = static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f );
113 modelCharactersToGlyph.Reserve( numberOfCharacters );
114 modelGlyphsPerCharacter.Reserve( numberOfCharacters );
116 // 2) Traverse the glyphs and set the glyph indices and the glyphs per character.
118 // The number of 'characters per glyph' equal to zero.
119 Length zeroCharactersPerGlyph = 0u;
121 // Index to the glyph.
122 GlyphIndex glyphIndex = 0u;
123 for( Vector<Length>::ConstIterator it = modelCharactersPerGlyph.Begin(),
124 endIt = modelCharactersPerGlyph.End();
128 const Length numberOfCharacters = *it;
130 // Set the glyph indices.
131 for( Length index = 0u; index < numberOfCharacters; ++index )
133 modelCharactersToGlyph.PushBack( glyphIndex );
136 // Set the glyphs per character.
137 if( 0u == numberOfCharacters )
139 ++zeroCharactersPerGlyph;
143 const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharacters - 1u );
144 for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
146 modelGlyphsPerCharacter.PushBack( 0u );
149 modelGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
151 zeroCharactersPerGlyph = 0u;
158 Length VisualModel::GetNumberOfGlyphs() const
160 return mImpl->mGlyphs.Count();
163 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
164 GlyphIndex glyphIndex,
165 Length numberOfGlyphs ) const
167 const Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
168 memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
171 const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
173 return mImpl->mGlyphs[glyphIndex];
176 void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex,
177 Length numberOfGlyphsToRemove,
178 const GlyphInfo* const glyphs,
179 const Length* const numberOfCharacters,
180 Length numberOfGlyphsToInsert )
184 CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
186 return mImpl->mGlyphsToCharacters[glyphIndex];
189 Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
191 return mImpl->mCharactersPerGlyph[glyphIndex];
194 GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
196 return mImpl->mCharactersToGlyph[characterIndex];
199 void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
200 CharacterIndex characterIndex,
201 Length numberOfCharacters ) const
203 const Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
204 memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
207 void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
208 GlyphIndex glyphIndex,
209 Length numberOfGlyphs ) const
211 const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
212 memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
215 void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
216 GlyphIndex glyphIndex,
217 Length numberOfGlyphs ) const
219 const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
220 memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
223 void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
224 CharacterIndex characterIndex,
225 Length numberOfCharacters ) const
227 const Vector<Length>& modelGlyphsPerCharacter = mImpl->mGlyphsPerCharacter;
228 memcpy( glyphsPerCharacter, modelGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
231 void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
232 Length numberOfGlyphs )
234 Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
235 if( 0u == numberOfGlyphs )
237 modelPositions.Clear();
241 modelPositions.Resize( numberOfGlyphs );
242 memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
246 Length VisualModel::GetNumberOfGlyphPositions() const
248 return mImpl->mGlyphPositions.Count();
251 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
252 GlyphIndex glyphIndex,
253 Length numberOfGlyphs ) const
255 const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
256 memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
259 const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
261 return *( mImpl->mGlyphPositions.Begin() + glyphIndex );
264 void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex,
265 Length numberOfGlyphsToRemove,
266 const Vector2* const positions,
267 Length numberOfGlyphsToInsert )
271 void VisualModel::SetLines( const LineRun* const lines,
272 Length numberOfLines )
274 Vector<LineRun>& modelLines = mImpl->mLines;
275 GetLineCache& lineCache = mImpl->mGetLineCache;
277 if( 0u == numberOfLines )
283 modelLines.Resize( numberOfLines );
284 memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
287 // Clear the get line cache.
288 lineCache.glyphIndex = 0u;
289 lineCache.numberOfGlyphs = 0u;
290 lineCache.firstLine = 0u;
291 lineCache.numberOfLines = 0u;
294 Length VisualModel::GetNumberOfLines() const
296 return mImpl->mLines.Count();
299 void VisualModel::GetLines( LineRun* lines,
301 Length numberOfLines ) const
303 const Vector<LineRun>& modelLines = mImpl->mLines;
304 memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
307 Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
308 Length numberOfGlyphs ) const
310 // If is likely the user query consecutively for the number of lines with the same
311 // glyph index and number of glyphs, use the cache could be considered.
312 GetLineCache& lineCache = mImpl->mGetLineCache;
314 // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange().
315 lineCache.glyphIndex = glyphIndex;
316 lineCache.numberOfGlyphs = numberOfGlyphs;
318 // Check first if the query is for the total number of glyphs.
319 const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count();
321 if( ( 0u == glyphIndex ) &&
322 ( totalNumberOfGlyphs == numberOfGlyphs ) )
324 lineCache.firstLine = 0u;
325 lineCache.numberOfLines = mImpl->mLines.Count();
327 return lineCache.numberOfLines;
330 // Initialize the number of lines and the first line.
331 lineCache.numberOfLines = 0u;
332 lineCache.firstLine = 0u;
333 bool firstLineFound = false;
335 const Vector<LineRun>& modelLines = mImpl->mLines;
336 const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
338 // Traverse the lines and count those lines within the range of glyphs.
339 for( Vector<LineRun>::ConstIterator it = modelLines.Begin(),
340 endIt = modelLines.End();
344 const LineRun& line = *it;
346 if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
347 ( lastGlyphIndex > line.glyphIndex ) )
349 firstLineFound = true;
350 ++lineCache.numberOfLines;
352 else if( lastGlyphIndex <= line.glyphIndex )
354 // nothing else to do.
358 if( !firstLineFound )
360 ++lineCache.firstLine;
364 return lineCache.numberOfLines;
367 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
368 GlyphIndex glyphIndex,
369 Length numberOfGlyphs ) const
371 const Vector<LineRun>& modelLines = mImpl->mLines;
372 GetLineCache& lineCache = mImpl->mGetLineCache;
374 if( ( glyphIndex != lineCache.glyphIndex ) ||
375 ( numberOfGlyphs != lineCache.numberOfGlyphs ) )
377 GetNumberOfLines( glyphIndex,
381 memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) );
384 void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
385 Length numberOfGlyphsToRemove,
386 const LineRun* const lines,
387 Length numberOfGlyphsToInsert )
391 void VisualModel::SetNaturalSize( const Vector2& size )
393 mImpl->mNaturalSize = size;
396 const Vector2& VisualModel::GetNaturalSize() const
398 return mImpl->mNaturalSize;
401 void VisualModel::SetActualSize( const Vector2& size )
403 mImpl->mActualSize = size;
406 const Vector2& VisualModel::GetActualSize() const
408 return mImpl->mActualSize;
411 VisualModel::~VisualModel()
416 VisualModel::VisualModel()
419 mImpl = new VisualModel::Impl();
424 } // namespace Toolkit