Merge "Ability to build from different Style folders" into 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.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs > glyphIndex ) &&
153         ( lastGlyphIndex > line.glyphRun.glyphIndex ) )
154     {
155       firstLineFound = true;
156       ++numberOfLines;
157     }
158     else if( lastGlyphIndex <= line.glyphRun.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::GetUnderlineRuns( GlyphRun* underlineRuns,
220                                     UnderlineRunIndex index,
221                                     Length numberOfRuns ) const
222 {
223   memcpy( underlineRuns,
224           mUnderlineRuns.Begin() + index,
225           numberOfRuns * sizeof( GlyphRun ) );
226 }
227
228 void VisualModel::SetNaturalSize( const Vector2& size  )
229 {
230   mNaturalSize = size;
231 }
232
233 const Vector2& VisualModel::GetNaturalSize() const
234 {
235   return mNaturalSize;
236 }
237
238 void VisualModel::SetActualSize( const Vector2& size )
239 {
240   mActualSize = size;
241 }
242
243 const Vector2& VisualModel::GetActualSize() const
244 {
245   return mActualSize;
246 }
247
248 void VisualModel::SetTextColor( const Vector4& textColor )
249 {
250   mTextColor = textColor;
251
252   if ( !mUnderlineColorSet )
253   {
254     mUnderlineColor = textColor;
255   }
256 }
257
258 void VisualModel::SetShadowOffset( const Vector2& shadowOffset )
259 {
260   mShadowOffset = shadowOffset;
261 }
262
263 void VisualModel::SetShadowColor( const Vector4& shadowColor )
264 {
265   mShadowColor = shadowColor;
266 }
267
268 void VisualModel::SetUnderlineColor( const Vector4& color )
269 {
270   mUnderlineColor = color;
271   mUnderlineColorSet = true;
272 }
273
274 void VisualModel::SetUnderlineEnabled( bool enabled )
275 {
276   mUnderlineEnabled = enabled;
277 }
278
279 void VisualModel::SetUnderlineHeight( float height )
280 {
281   mUnderlineHeight = height;
282 }
283
284 const Vector4& VisualModel::GetTextColor() const
285 {
286   return mTextColor;
287 }
288
289 const Vector2& VisualModel::GetShadowOffset() const
290 {
291   return mShadowOffset;
292 }
293
294 const Vector4& VisualModel::GetShadowColor() const
295 {
296   return mShadowColor;
297 }
298
299 const Vector4& VisualModel::GetUnderlineColor() const
300 {
301   return mUnderlineColor;
302 }
303
304 bool VisualModel::IsUnderlineEnabled() const
305 {
306   return mUnderlineEnabled;
307 }
308
309 float VisualModel::GetUnderlineHeight() const
310 {
311   return mUnderlineHeight;
312 }
313
314 void VisualModel::ClearCaches()
315 {
316   mCachedLineIndex = 0u;
317 }
318
319 VisualModel::~VisualModel()
320 {
321 }
322
323 VisualModel::VisualModel()
324 : mGlyphs(),
325   mGlyphsToCharacters(),
326   mCharactersToGlyph(),
327   mCharactersPerGlyph(),
328   mGlyphsPerCharacter(),
329   mGlyphPositions(),
330   mLines(),
331   mTextColor( Color::BLACK ),
332   mShadowColor( Color::BLACK ),
333   mUnderlineColor( Color::BLACK ),
334   mShadowOffset( Vector2::ZERO ),
335   mUnderlineHeight( 0.0f ),
336   mNaturalSize(),
337   mActualSize(),
338   mCachedLineIndex( 0u ),
339   mUnderlineEnabled( false ),
340   mUnderlineColorSet( false )
341 {
342 }
343
344 } // namespace Text
345
346 } // namespace Toolkit
347
348 } // namespace Dali