2 * Copyright (c) 2018 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-impl.h>
33 VisualModelPtr VisualModel::New()
35 return VisualModelPtr( new VisualModel() );
38 void VisualModel::CreateCharacterToGlyphTable( CharacterIndex startIndex,
39 GlyphIndex startGlyphIndex,
40 Length numberOfCharacters )
42 if( 0u == numberOfCharacters )
48 DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u );
50 // Get the total number of characters.
51 const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
53 // Whether the current buffer is being updated or is set from scratch.
54 const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
56 Vector<GlyphIndex> newCharactersToGlyph;
57 GlyphIndex* charactersToGlyphBuffer = NULL;
59 // 1) Reserve some space for the glyph indices to avoid reallocations.
60 if( updateCurrentBuffer )
62 newCharactersToGlyph.Resize( numberOfCharacters );
63 charactersToGlyphBuffer = newCharactersToGlyph.Begin();
67 mCharactersToGlyph.Resize( numberOfCharacters );
68 charactersToGlyphBuffer = mCharactersToGlyph.Begin() + startIndex;
71 const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin();
73 // 2) Traverse the glyphs and set the glyph indices per character.
75 // Index to the glyph.
76 GlyphIndex glyphIndex = startGlyphIndex;
77 CharacterIndex characterIndex = startIndex;
78 const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
79 for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex,
80 endIt = mCharactersPerGlyph.End();
81 ( it != endIt ) && ( characterIndex < lastCharacterIndexPlusOne );
84 const Length numberOfCharactersPerGlyph = *it;
86 Length numberOfGlyphs = 0u;
87 // Set the glyph indices.
88 for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
90 *charactersToGlyphBuffer = glyphIndex;
91 numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
92 ++charactersToGlyphBuffer;
94 glyphIndex += numberOfGlyphs;
97 // If the character to glyph buffer is updated, it needs to be inserted in the model.
98 if( updateCurrentBuffer )
100 // Update the indices.
101 const Length numberOfGlyphs = glyphIndex - startGlyphIndex;
102 for( Vector<Length>::Iterator it = mCharactersToGlyph.Begin() + startIndex,
103 endIt = mCharactersToGlyph.End();
107 *it += numberOfGlyphs;
110 mCharactersToGlyph.Insert( mCharactersToGlyph.Begin() + startIndex,
111 newCharactersToGlyph.Begin(),
112 newCharactersToGlyph.End() );
117 void VisualModel::CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
118 GlyphIndex startGlyphIndex,
119 Length numberOfCharacters )
121 if( 0u == numberOfCharacters )
127 // Get the total number of characters.
128 const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
130 // Whether the current buffer is being updated or is set from scratch.
131 const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
133 Vector<Length> newGlyphsPerCharacter;
134 Length* glyphsPerCharacterBuffer = NULL;
136 // 1) Reserve some space for the glyphs per character to avoid reallocations.
137 if( updateCurrentBuffer )
139 newGlyphsPerCharacter.Resize( numberOfCharacters );
140 glyphsPerCharacterBuffer = newGlyphsPerCharacter.Begin();
144 mGlyphsPerCharacter.Resize( numberOfCharacters );
145 glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin() + startIndex;
148 // 2) Traverse the glyphs and set the number of glyphs per character.
150 Length traversedCharacters = 0;
152 // The number of 'characters per glyph' equal to zero.
153 Length zeroCharactersPerGlyph = 0u;
155 for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + startGlyphIndex,
156 endIt = mCharactersPerGlyph.End();
157 ( it != endIt ) && ( traversedCharacters < numberOfCharacters );
160 const Length numberOfCharactersPerGlyph = *it;
161 traversedCharacters += numberOfCharactersPerGlyph;
163 // Set the glyphs per character.
164 if( 0u == numberOfCharactersPerGlyph )
166 ++zeroCharactersPerGlyph;
170 const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
171 for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter; ++zeroIndex )
173 *glyphsPerCharacterBuffer = 0u;
175 // Point to the next position in the buffer.
176 ++glyphsPerCharacterBuffer;
179 *glyphsPerCharacterBuffer = zeroCharactersPerGlyph + 1u;
181 zeroCharactersPerGlyph = 0u;
183 // Point to the next position in the buffer.
184 ++glyphsPerCharacterBuffer;
188 // If the glyphs per character buffer is updated, it needs to be inserted in the model.
189 if( updateCurrentBuffer )
191 mGlyphsPerCharacter.Insert( mGlyphsPerCharacter.Begin() + startIndex,
192 newGlyphsPerCharacter.Begin(),
193 newGlyphsPerCharacter.End() );
197 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
198 GlyphIndex glyphIndex,
199 Length numberOfGlyphs ) const
201 memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
204 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
205 GlyphIndex glyphIndex,
206 Length numberOfGlyphs ) const
208 memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
211 void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
212 Length numberOfGlyphs,
213 LineIndex& firstLine,
214 Length& numberOfLines ) const
216 // Initialize the number of lines and the first line.
219 bool firstLineFound = false;
221 const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
223 // Traverse the lines and count those lines within the range of glyphs.
224 for( Vector<LineRun>::ConstIterator it = mLines.Begin(),
225 endIt = mLines.End();
229 const LineRun& line = *it;
231 if( ( line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs > glyphIndex ) &&
232 ( lastGlyphIndex > line.glyphRun.glyphIndex ) )
234 firstLineFound = true;
237 else if( lastGlyphIndex <= line.glyphRun.glyphIndex )
239 // nothing else to do.
243 if( !firstLineFound )
250 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
251 GlyphIndex glyphIndex,
252 Length numberOfGlyphs ) const
254 LineIndex firstLine = 0u;
255 Length numberOfLines = 0u;
257 GetNumberOfLines( glyphIndex,
262 memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
265 LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex )
267 // 1) Check line is empty or not.
273 // 2) Check in the cached line.
274 const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex );
275 if( ( lineRun.characterRun.characterIndex <= characterIndex ) &&
276 ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) )
278 return mCachedLineIndex;
281 // 3) Is not in the cached line. Check in the other lines.
282 LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u;
284 for( Vector<LineRun>::ConstIterator it = mLines.Begin() + index,
285 endIt = mLines.End();
289 const LineRun& lineRun = *it;
291 if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters )
293 mCachedLineIndex = index;
301 void VisualModel::GetUnderlineRuns( GlyphRun* underlineRuns,
302 UnderlineRunIndex index,
303 Length numberOfRuns ) const
305 memcpy( underlineRuns,
306 mUnderlineRuns.Begin() + index,
307 numberOfRuns * sizeof( GlyphRun ) );
310 void VisualModel::SetNaturalSize( const Vector2& size )
315 const Vector2& VisualModel::GetNaturalSize() const
320 void VisualModel::SetLayoutSize( const Vector2& size )
325 const Vector2& VisualModel::GetLayoutSize() const
330 void VisualModel::SetTextColor( const Vector4& textColor )
332 mTextColor = textColor;
334 if ( !mUnderlineColorSet )
336 mUnderlineColor = textColor;
340 void VisualModel::SetShadowOffset( const Vector2& shadowOffset )
342 mShadowOffset = shadowOffset;
345 void VisualModel::SetShadowColor( const Vector4& shadowColor )
347 mShadowColor = shadowColor;
350 void VisualModel::SetShadowBlurRadius( const float& shadowBlurRadius )
352 mShadowBlurRadius = shadowBlurRadius;
355 void VisualModel::SetUnderlineColor( const Vector4& color )
357 mUnderlineColor = color;
358 mUnderlineColorSet = true;
361 void VisualModel::SetOutlineColor( const Vector4& color )
363 mOutlineColor = color;
366 void VisualModel::SetUnderlineEnabled( bool enabled )
368 mUnderlineEnabled = enabled;
371 void VisualModel::SetUnderlineHeight( float height )
373 mUnderlineHeight = height;
376 void VisualModel::SetOutlineWidth( unsigned int width )
378 mOutlineWidth = width;
381 void VisualModel::SetBackgroundColor( const Vector4& color )
383 mBackgroundColor = color;
386 void VisualModel::SetBackgroundEnabled( bool enabled )
388 mBackgroundEnabled = enabled;
391 const Vector4& VisualModel::GetTextColor() const
396 const Vector2& VisualModel::GetShadowOffset() const
398 return mShadowOffset;
401 const Vector4& VisualModel::GetShadowColor() const
406 const float& VisualModel::GetShadowBlurRadius() const
408 return mShadowBlurRadius;
411 const Vector4& VisualModel::GetUnderlineColor() const
413 return mUnderlineColor;
416 const Vector4& VisualModel::GetOutlineColor() const
418 return mOutlineColor;
421 bool VisualModel::IsUnderlineEnabled() const
423 return mUnderlineEnabled;
426 float VisualModel::GetUnderlineHeight() const
428 return mUnderlineHeight;
431 unsigned int VisualModel::GetOutlineWidth() const
433 return mOutlineWidth;
436 const Vector4& VisualModel::GetBackgroundColor() const
438 return mBackgroundColor;
441 bool VisualModel::IsBackgroundEnabled() const
443 return mBackgroundEnabled;
446 Length VisualModel::GetNumberOfUnderlineRuns() const
448 return mUnderlineRuns.Count();
451 void VisualModel::ClearCaches()
453 mCachedLineIndex = 0u;
456 VisualModel::~VisualModel()
460 VisualModel::VisualModel()
462 mGlyphsToCharacters(),
463 mCharactersToGlyph(),
464 mCharactersPerGlyph(),
465 mGlyphsPerCharacter(),
468 mTextColor( Color::BLACK ),
469 mShadowColor( Color::BLACK ),
470 mUnderlineColor( Color::BLACK ),
471 mOutlineColor( Color::WHITE ),
472 mBackgroundColor( Color::CYAN ),
475 mUnderlineHeight( 0.0f ),
477 mShadowBlurRadius( 0.0f ),
480 mCachedLineIndex( 0u ),
481 mUnderlineEnabled( false ),
482 mUnderlineColorSet( false ),
483 mBackgroundEnabled( false )
489 } // namespace Toolkit