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-impl.h>
23 #include <dali/public-api/math/vector2.h>
34 VisualModelPtr VisualModel::New()
36 return VisualModelPtr( new VisualModel() );
39 void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
41 // 1) Reserve some space for the characters to avoid reallocations.
42 if( 0u == numberOfCharacters )
44 // If no number of characters is given, just set something sensible to avoid reallocations.
45 numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
47 mCharactersToGlyph.Reserve( numberOfCharacters );
49 DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ||
50 ( 0u == numberOfCharacters ) );
52 const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin();
54 // 2) Traverse the glyphs and set the glyph indices per character.
56 // Index to the glyph.
57 GlyphIndex glyphIndex = 0u;
58 CharacterIndex characterIndex = 0u;
59 for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
60 endIt = mCharactersPerGlyph.End();
64 const Length numberOfCharactersPerGlyph = *it;
66 Length numberOfGlyphs = 0u;
67 // Set the glyph indices.
68 for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
70 mCharactersToGlyph.PushBack( glyphIndex );
71 numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
73 glyphIndex += numberOfGlyphs;
77 void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
79 // 1) Reserve some space for the characters to avoid reallocations.
80 if( 0u == numberOfCharacters )
82 // If no number of characters is given, just set something sensible to avoid reallocations.
83 numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
85 mGlyphsPerCharacter.Reserve( numberOfCharacters );
87 // 2) Traverse the glyphs and set the number of glyphs per character.
89 // The number of 'characters per glyph' equal to zero.
90 Length zeroCharactersPerGlyph = 0u;
92 for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
93 endIt = mCharactersPerGlyph.End();
97 const Length numberOfCharactersPerGlyph = *it;
99 // Set the glyphs per character.
100 if( 0u == numberOfCharactersPerGlyph )
102 ++zeroCharactersPerGlyph;
106 const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
107 for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
109 mGlyphsPerCharacter.PushBack( 0u );
112 mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
114 zeroCharactersPerGlyph = 0u;
119 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
120 GlyphIndex glyphIndex,
121 Length numberOfGlyphs ) const
123 memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
126 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
127 GlyphIndex glyphIndex,
128 Length numberOfGlyphs ) const
130 memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
133 void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
134 Length numberOfGlyphs,
135 LineIndex& firstLine,
136 Length& numberOfLines ) const
138 // Initialize the number of lines and the first line.
141 bool firstLineFound = false;
143 const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
145 // Traverse the lines and count those lines within the range of glyphs.
146 for( Vector<LineRun>::ConstIterator it = mLines.Begin(),
147 endIt = mLines.End();
151 const LineRun& line = *it;
153 if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
154 ( lastGlyphIndex > line.glyphIndex ) )
156 firstLineFound = true;
159 else if( lastGlyphIndex <= line.glyphIndex )
161 // nothing else to do.
165 if( !firstLineFound )
172 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
173 GlyphIndex glyphIndex,
174 Length numberOfGlyphs ) const
176 LineIndex firstLine = 0u;
177 Length numberOfLines = 0u;
179 GetNumberOfLines( glyphIndex,
184 memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
187 LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex )
189 // 1) Check first in the cached line.
191 const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex );
193 if( ( lineRun.characterRun.characterIndex <= characterIndex ) &&
194 ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) )
196 return mCachedLineIndex;
199 // 2) Is not in the cached line. Check in the other lines.
201 LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u;
203 for( Vector<LineRun>::ConstIterator it = mLines.Begin() + index,
204 endIt = mLines.End();
208 const LineRun& lineRun = *it;
210 if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters )
212 mCachedLineIndex = index;
220 void VisualModel::SetNaturalSize( const Vector2& size )
225 const Vector2& VisualModel::GetNaturalSize() const
230 void VisualModel::SetActualSize( const Vector2& size )
235 const Vector2& VisualModel::GetActualSize() const
240 void VisualModel::SetTextColor( const Vector4& textColor )
242 mTextColor = textColor;
244 if ( !mUnderlineColorSet )
246 mUnderlineColor = textColor;
250 void VisualModel::SetShadowOffset( const Vector2& shadowOffset )
252 mShadowOffset = shadowOffset;
255 void VisualModel::SetShadowColor( const Vector4& shadowColor )
257 mShadowColor = shadowColor;
260 void VisualModel::SetUnderlineColor( const Vector4& color )
262 mUnderlineColor = color;
263 mUnderlineColorSet = true;
266 void VisualModel::SetUnderlineEnabled( bool enabled )
268 mUnderlineEnabled = enabled;
271 void VisualModel::SetUnderlineHeight( float height )
273 mUnderlineHeight = height;
276 const Vector4& VisualModel::GetTextColor() const
281 const Vector2& VisualModel::GetShadowOffset() const
283 return mShadowOffset;
286 const Vector4& VisualModel::GetShadowColor() const
291 const Vector4& VisualModel::GetUnderlineColor() const
293 return mUnderlineColor;
296 bool VisualModel::IsUnderlineEnabled() const
298 return mUnderlineEnabled;
301 float VisualModel::GetUnderlineHeight() const
303 return mUnderlineHeight;
306 void VisualModel::ClearCaches()
308 mCachedLineIndex = 0u;
311 VisualModel::~VisualModel()
315 VisualModel::VisualModel()
317 mGlyphsToCharacters(),
318 mCharactersToGlyph(),
319 mCharactersPerGlyph(),
320 mGlyphsPerCharacter(),
323 mTextColor( Color::BLACK ),
324 mShadowColor( Color::BLACK ),
325 mUnderlineColor( Color::BLACK ),
326 mShadowOffset( Vector2::ZERO ),
327 mUnderlineHeight( 0.0f ),
330 mCachedLineIndex( 0u ),
331 mUnderlineEnabled( false ),
332 mUnderlineColorSet( false )
338 } // namespace Toolkit