[dali_1.0.51] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / visual-model-impl.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-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <memory.h>
23
24 namespace Dali
25 {
26
27 namespace Toolkit
28 {
29
30 namespace Text
31 {
32
33 VisualModelPtr VisualModel::New()
34 {
35   return VisualModelPtr( new VisualModel() );
36 }
37
38 void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
39 {
40   // 1) Reserve some space for the characters to avoid reallocations.
41   if( 0u == numberOfCharacters )
42   {
43     // If no number of characters is given, just set something sensible to avoid reallocations.
44     numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
45   }
46   mCharactersToGlyph.Reserve( numberOfCharacters );
47
48   DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ||
49                      ( 0u == numberOfCharacters ) );
50
51   const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin();
52
53   // 2) Traverse the glyphs and set the glyph indices per character.
54
55   // Index to the glyph.
56   GlyphIndex glyphIndex = 0u;
57   CharacterIndex characterIndex = 0u;
58   for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
59          endIt = mCharactersPerGlyph.End();
60        it != endIt;
61        ++it )
62   {
63     const Length numberOfCharactersPerGlyph = *it;
64
65     Length numberOfGlyphs = 0u;
66     // Set the glyph indices.
67     for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
68     {
69       mCharactersToGlyph.PushBack( glyphIndex );
70       numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
71     }
72     glyphIndex += numberOfGlyphs;
73   }
74 }
75
76 void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
77 {
78   // 1) Reserve some space for the characters to avoid reallocations.
79   if( 0u == numberOfCharacters )
80   {
81     // If no number of characters is given, just set something sensible to avoid reallocations.
82     numberOfCharacters = static_cast<Length> ( static_cast<float>( mGlyphs.Count() ) * 1.3f );
83   }
84   mGlyphsPerCharacter.Reserve( numberOfCharacters );
85
86   // 2) Traverse the glyphs and set the number of glyphs per character.
87
88   // The number of 'characters per glyph' equal to zero.
89   Length zeroCharactersPerGlyph = 0u;
90
91   for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin(),
92          endIt = mCharactersPerGlyph.End();
93        it != endIt;
94        ++it )
95   {
96     const Length numberOfCharactersPerGlyph = *it;
97
98     // Set the glyphs per character.
99     if( 0u == numberOfCharactersPerGlyph )
100     {
101       ++zeroCharactersPerGlyph;
102     }
103     else
104     {
105       const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
106       for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
107       {
108         mGlyphsPerCharacter.PushBack( 0u );
109       }
110
111       mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
112
113       zeroCharactersPerGlyph = 0u;
114     }
115   }
116 }
117
118 void VisualModel::GetGlyphs( GlyphInfo* glyphs,
119                              GlyphIndex glyphIndex,
120                              Length numberOfGlyphs ) const
121 {
122   memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
123 }
124
125 void VisualModel::GetGlyphPositions( Vector2* glyphPositions,
126                                      GlyphIndex glyphIndex,
127                                      Length numberOfGlyphs ) const
128 {
129   memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
130 }
131
132 void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
133                                     Length numberOfGlyphs,
134                                     LineIndex& firstLine,
135                                     Length& numberOfLines ) const
136 {
137   // Initialize the number of lines and the first line.
138   firstLine = 0u;
139   numberOfLines = 0u;
140   bool firstLineFound = false;
141
142   const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs;
143
144   // Traverse the lines and count those lines within the range of glyphs.
145   for( Vector<LineRun>::ConstIterator it = mLines.Begin(),
146          endIt = mLines.End();
147        it != endIt;
148        ++it )
149   {
150     const LineRun& line = *it;
151
152     if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) &&
153         ( lastGlyphIndex > line.glyphIndex ) )
154     {
155       firstLineFound = true;
156       ++numberOfLines;
157     }
158     else if( lastGlyphIndex <= line.glyphIndex )
159     {
160       // nothing else to do.
161       break;
162     }
163
164     if( !firstLineFound )
165     {
166       ++firstLine;
167     }
168   }
169 }
170
171 void VisualModel::GetLinesOfGlyphRange( LineRun* lines,
172                                         GlyphIndex glyphIndex,
173                                         Length numberOfGlyphs ) const
174 {
175   LineIndex firstLine = 0u;
176   Length numberOfLines = 0u;
177
178   GetNumberOfLines( glyphIndex,
179                     numberOfGlyphs,
180                     firstLine,
181                     numberOfLines );
182
183   memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
184 }
185
186 LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex )
187 {
188   // 1) Check first in the cached line.
189
190   const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex );
191
192   if( ( lineRun.characterRun.characterIndex <= characterIndex ) &&
193       ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) )
194   {
195     return mCachedLineIndex;
196   }
197
198   // 2) Is not in the cached line. Check in the other lines.
199
200   LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u;
201
202   for( Vector<LineRun>::ConstIterator it = mLines.Begin() + index,
203          endIt = mLines.End();
204        it != endIt;
205        ++it, ++index )
206   {
207     const LineRun& lineRun = *it;
208
209     if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters )
210     {
211       mCachedLineIndex = index;
212       break;
213     }
214   }
215
216   return index;
217 }
218
219 void VisualModel::SetNaturalSize( const Vector2& size  )
220 {
221   mNaturalSize = size;
222 }
223
224 const Vector2& VisualModel::GetNaturalSize() const
225 {
226   return mNaturalSize;
227 }
228
229 void VisualModel::SetActualSize( const Vector2& size )
230 {
231   mActualSize = size;
232 }
233
234 const Vector2& VisualModel::GetActualSize() const
235 {
236   return mActualSize;
237 }
238
239 void VisualModel::SetTextColor( const Vector4& textColor )
240 {
241   mTextColor = textColor;
242
243   if ( !mUnderlineColorSet )
244   {
245     mUnderlineColor = textColor;
246   }
247 }
248
249 void VisualModel::SetShadowOffset( const Vector2& shadowOffset )
250 {
251   mShadowOffset = shadowOffset;
252 }
253
254 void VisualModel::SetShadowColor( const Vector4& shadowColor )
255 {
256   mShadowColor = shadowColor;
257 }
258
259 void VisualModel::SetUnderlineColor( const Vector4& color )
260 {
261   mUnderlineColor = color;
262   mUnderlineColorSet = true;
263 }
264
265 void VisualModel::SetUnderlineEnabled( bool enabled )
266 {
267   mUnderlineEnabled = enabled;
268 }
269
270 void VisualModel::SetUnderlineHeight( float height )
271 {
272   mUnderlineHeight = height;
273 }
274
275 const Vector4& VisualModel::GetTextColor() const
276 {
277   return mTextColor;
278 }
279
280 const Vector2& VisualModel::GetShadowOffset() const
281 {
282   return mShadowOffset;
283 }
284
285 const Vector4& VisualModel::GetShadowColor() const
286 {
287   return mShadowColor;
288 }
289
290 const Vector4& VisualModel::GetUnderlineColor() const
291 {
292   return mUnderlineColor;
293 }
294
295 bool VisualModel::IsUnderlineEnabled() const
296 {
297   return mUnderlineEnabled;
298 }
299
300 float VisualModel::GetUnderlineHeight() const
301 {
302   return mUnderlineHeight;
303 }
304
305 void VisualModel::ClearCaches()
306 {
307   mCachedLineIndex = 0u;
308 }
309
310 VisualModel::~VisualModel()
311 {
312 }
313
314 VisualModel::VisualModel()
315 : mGlyphs(),
316   mGlyphsToCharacters(),
317   mCharactersToGlyph(),
318   mCharactersPerGlyph(),
319   mGlyphsPerCharacter(),
320   mGlyphPositions(),
321   mLines(),
322   mTextColor( Color::BLACK ),
323   mShadowColor( Color::BLACK ),
324   mUnderlineColor( Color::BLACK ),
325   mShadowOffset( Vector2::ZERO ),
326   mUnderlineHeight( 0.0f ),
327   mNaturalSize(),
328   mActualSize(),
329   mCachedLineIndex( 0u ),
330   mUnderlineEnabled( false ),
331   mUnderlineColorSet( false )
332 {
333 }
334
335 } // namespace Text
336
337 } // namespace Toolkit
338
339 } // namespace Dali