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>
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>
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<Vector2> mGlyphPositions; ///< For each glyph, the position.
57 Vector<LineRun> mLines; ///< The laid out lines.
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.
62 GetLineCache mGetLineCache; ///< Caches the GetNumberOfLines( glyphIndex, numberOfGlyphs ) operation.
65 VisualModelPtr VisualModel::New()
67 return VisualModelPtr( new VisualModel() );
70 void VisualModel::SetGlyphs( const GlyphInfo* glyphs,
71 const CharacterIndex* characterIndices,
72 const Length* charactersPerGlyph,
73 Length numberOfGlyphs )
75 Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
76 modelGlyphs.Resize( numberOfGlyphs );
77 memcpy( modelGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) );
79 Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
80 modelGlyphsToCharacters.Resize( numberOfGlyphs );
81 memcpy( modelGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) );
83 Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
84 modelCharactersPerGlyph.Resize( numberOfGlyphs );
85 memcpy( modelCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) );
87 // Build the characters to glyph conversion table.
88 Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
90 // 1) Reserve some space for the characters to avoid reallocations.
91 modelCharactersToGlyph.Reserve( static_cast<Length> ( static_cast<float>( numberOfGlyphs ) * 1.3f ) );
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();
101 const Length numberOfCharacters = *it;
103 for( Length index = 0u; index < numberOfCharacters; ++index, ++totalNumberOfCharacters )
105 modelCharactersToGlyph.PushBack( glyphIndex );
110 Length VisualModel::GetNumberOfGlyphs() const
112 return mImpl->mGlyphs.Count();
115 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
116 GlyphIndex glyphIndex,
117 Length numberOfGlyphs ) const
119 const Vector<GlyphInfo>& modelGlyphs = mImpl->mGlyphs;
120 memcpy( glyphs, modelGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
123 const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
125 return mImpl->mGlyphs[glyphIndex];
128 CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
130 return mImpl->mGlyphsToCharacters[glyphIndex];
133 Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
135 return mImpl->mCharactersPerGlyph[glyphIndex];
138 GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
140 return mImpl->mCharactersToGlyph[characterIndex];
143 void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
144 CharacterIndex characterIndex,
145 Length numberOfCharacters ) const
147 const Vector<GlyphIndex>& modelCharactersToGlyph = mImpl->mCharactersToGlyph;
148 memcpy( characterToGlyphMap, modelCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
151 void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
152 GlyphIndex glyphIndex,
153 Length numberOfGlyphs ) const
155 const Vector<Length>& modelCharactersPerGlyph = mImpl->mCharactersPerGlyph;
156 memcpy( charactersPerGlyph, modelCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
159 void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
160 GlyphIndex glyphIndex,
161 Length numberOfGlyphs ) const
163 const Vector<CharacterIndex>& modelGlyphsToCharacters = mImpl->mGlyphsToCharacters;
164 memcpy( glyphToCharacter, modelGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
167 void VisualModel::SetGlyphPositions( const Vector2* glyphPositions,
168 Length numberOfGlyphs )
170 Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
171 modelPositions.Resize( numberOfGlyphs );
172 memcpy( modelPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) );
175 Length VisualModel::GetNumberOfGlyphPositions() const
177 return mImpl->mGlyphPositions.Count();
180 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
181 GlyphIndex glyphIndex,
182 Length numberOfGlyphs ) const
184 const Vector<Vector2>& modelPositions = mImpl->mGlyphPositions;
185 memcpy( glyphPositions, modelPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
188 const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
190 return *( mImpl->mGlyphPositions.Begin() + glyphIndex );
193 void VisualModel::SetLines( const LineRun* const lines,
194 Length numberOfLines )
196 Vector<LineRun>& modelLines = mImpl->mLines;
197 GetLineCache& lineCache = mImpl->mGetLineCache;
199 modelLines.Resize( numberOfLines );
200 memcpy( modelLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
202 // Clear the get line cache.
203 lineCache.glyphIndex = 0u;
204 lineCache.numberOfGlyphs = 0u;
205 lineCache.firstLine = 0u;
206 lineCache.numberOfLines = 0u;
209 Length VisualModel::GetNumberOfLines() const
211 return mImpl->mLines.Count();
214 void VisualModel::GetLines( LineRun* lines,
216 Length numberOfLines ) const
218 const Vector<LineRun>& modelLines = mImpl->mLines;
219 memcpy( lines, modelLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
222 Length VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
223 Length numberOfGlyphs ) const
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;
229 // Cache the glyph index and number of glyphs to be used in the GetLinesOfGlyphRange().
230 lineCache.glyphIndex = glyphIndex;
231 lineCache.numberOfGlyphs = numberOfGlyphs;
233 // Check first if the query is for the total number of glyphs.
234 const Length totalNumberOfGlyphs = mImpl->mGlyphs.Count();
236 if( ( 0u == glyphIndex ) &&
237 ( totalNumberOfGlyphs == numberOfGlyphs ) )
239 lineCache.firstLine = 0u;
240 lineCache.numberOfLines = mImpl->mLines.Count();
242 return lineCache.numberOfLines;
245 // Initialize the number of lines and the first line.
246 lineCache.numberOfLines = 0u;
247 lineCache.firstLine = 0u;
248 bool firstLineFound = false;
250 const Vector<LineRun>& modelLines = mImpl->mLines;
251 const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
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();
259 const LineRun& line = *it;
261 if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
262 ( lastGlyphIndex > line.glyphIndex ) )
264 firstLineFound = true;
265 ++lineCache.numberOfLines;
267 else if( lastGlyphIndex <= line.glyphIndex )
269 // nothing else to do.
273 if( !firstLineFound )
275 ++lineCache.firstLine;
279 return lineCache.numberOfLines;
282 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
283 GlyphIndex glyphIndex,
284 Length numberOfGlyphs ) const
286 const Vector<LineRun>& modelLines = mImpl->mLines;
287 GetLineCache& lineCache = mImpl->mGetLineCache;
289 if( ( glyphIndex != lineCache.glyphIndex ) ||
290 ( numberOfGlyphs != lineCache.numberOfGlyphs ) )
292 GetNumberOfLines( glyphIndex,
296 memcpy( lines, modelLines.Begin() + lineCache.firstLine, lineCache.numberOfLines * sizeof( LineRun ) );
299 void VisualModel::SetNaturalSize( const Vector2& size )
301 mImpl->mNaturalSize = size;
304 const Vector2& VisualModel::GetNaturalSize() const
306 return mImpl->mNaturalSize;
309 void VisualModel::SetActualSize( const Vector2& size )
311 mImpl->mActualSize = size;
314 const Vector2& VisualModel::GetActualSize() const
316 return mImpl->mActualSize;
319 VisualModel::~VisualModel()
324 VisualModel::VisualModel()
327 mImpl = new VisualModel::Impl();
332 } // namespace Toolkit