6d22f3ad35ce2c4a492b6f535c291d507e5179a1
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / text / logical-model.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/public-api/text/logical-model.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/public-api/text/bidirectional-line-info-run.h>
23 #include <dali-toolkit/public-api/text/bidirectional-paragraph-info-run.h>
24 #include <dali-toolkit/public-api/text/font-run.h>
25 #include <dali-toolkit/public-api/text/script-run.h>
26
27 // EXTERNAL INCLUDES
28 #include <memory.h>
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Text
37 {
38
39 struct LogicalModel::Impl
40 {
41   Vector<Character> mText;
42   Vector<ScriptRun> mScriptRuns;
43   Vector<FontRun>   mFontRuns;
44 };
45
46 LogicalModelPtr LogicalModel::New()
47 {
48   return LogicalModelPtr( new LogicalModel() );
49 }
50
51 void LogicalModel::SetText( const Character* const text,
52                             Length numberOfCharacters )
53 {
54   Vector<Character>& modelText = mImpl->mText;
55   modelText.Resize( numberOfCharacters );
56   memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) );
57 }
58
59 Length LogicalModel::GetNumberOfCharacters() const
60 {
61   return mImpl->mText.Count();
62 }
63
64 void LogicalModel::GetText( CharacterIndex characterIndex,
65                             Character* text,
66                             Length numberOfCharacters ) const
67 {
68   Vector<Character>& modelText = mImpl->mText;
69   memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
70 }
71
72 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
73 {
74   return mImpl->mText[characterIndex];
75 }
76
77 void LogicalModel::SetScripts( const ScriptRun* const scripts,
78                                Length numberOfRuns )
79 {
80   Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
81   scriptRuns.Resize( numberOfRuns );
82   memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
83 }
84
85 Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
86                                             Length numberOfCharacters ) const
87 {
88   if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
89   {
90     return mImpl->mScriptRuns.Count();
91   }
92
93   const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
94   Length numberOfScriptRuns = 0u;
95   bool firstIndexFound = false;
96
97   for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
98   {
99     const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
100
101     if( !firstIndexFound &&
102         ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
103     {
104       // The character index is within this script run.
105       // Starts the counter of script runs.
106       firstIndexFound = true;
107     }
108
109     if( firstIndexFound )
110     {
111       ++numberOfScriptRuns;
112       if( scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters > charcterEndIndex )
113       {
114         // This script run exceeds the given range. The number of scripts can be returned.
115         return numberOfScriptRuns;
116       }
117     }
118   }
119
120   return numberOfScriptRuns;
121 }
122
123 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
124                                   CharacterIndex characterIndex,
125                                   Length numberOfCharacters ) const
126 {
127   // A better implementation can cache the first script run and the number of then when the GetNumberOfScriptRuns() is called.
128
129   Length numberOfScriptRuns = GetNumberOfScriptRuns( characterIndex,
130                                                      numberOfCharacters );
131
132   for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
133   {
134     const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
135
136     if( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters )
137     {
138       memcpy( scriptRuns, scriptRun, sizeof( ScriptRun ) * numberOfScriptRuns );
139       return;
140     }
141   }
142 }
143
144 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
145 {
146   // If this operation is too slow, consider a binary search.
147
148   for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
149   {
150     const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
151
152     if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
153         ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
154     {
155       return scriptRun->script;
156     }
157   }
158
159   return TextAbstraction::UNKNOWN;
160 }
161
162 void LogicalModel::SetFonts( const FontRun* const fonts,
163                              Length numberOfRuns )
164 {
165   Vector<FontRun>& fontRuns = mImpl->mFontRuns;
166   fontRuns.Resize( numberOfRuns );
167   memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
168 }
169
170 Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
171                                           Length numberOfCharacters ) const
172 {
173   if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
174   {
175     return mImpl->mFontRuns.Count();
176   }
177
178   const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
179   Length numberOfFontRuns = 0u;
180   bool firstIndexFound = false;
181
182   for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
183   {
184     const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
185
186     if( !firstIndexFound &&
187         ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
188     {
189       // The character index is within this font run.
190       // Starts the counter of font runs.
191       firstIndexFound = true;
192     }
193
194     if( firstIndexFound )
195     {
196       ++numberOfFontRuns;
197       if( fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters > charcterEndIndex )
198       {
199         // This font run exceeds the given range. The number of fonts can be returned.
200         return numberOfFontRuns;
201       }
202     }
203   }
204
205   return numberOfFontRuns;
206 }
207
208 void LogicalModel::GetFontRuns( FontRun* fontRuns,
209                                 CharacterIndex characterIndex,
210                                 Length numberOfCharacters ) const
211 {
212   // A better implementation can cache the first font run and the number of then when the GetNumberOfFontRuns() is called.
213
214   Length numberOfFontRuns = GetNumberOfFontRuns( characterIndex,
215                                                  numberOfCharacters );
216
217   for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
218   {
219     const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
220
221     if( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters )
222     {
223       memcpy( fontRuns, fontRun, sizeof( FontRun ) * numberOfFontRuns );
224       return;
225     }
226   }
227 }
228
229 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
230 {
231   for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
232   {
233     const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
234
235     if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
236         ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
237     {
238       return fontRun->fontId;
239     }
240   }
241
242   return 0u;
243 }
244
245 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
246                                      Length length )
247 {
248 }
249
250 void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
251                                      CharacterIndex characterIndex,
252                                      Length numberOfItems ) const
253 {
254 }
255
256 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
257 {
258   return 0;
259 }
260
261 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
262                                      Length length )
263 {
264 }
265
266 void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
267                                      CharacterIndex characterIndex,
268                                      Length numberOfItems ) const
269 {
270 }
271
272 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
273 {
274   return 0;
275 }
276
277 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
278                                          Length numberOfRuns )
279 {
280 }
281
282 Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
283                                                        Length numberOfCharacters ) const
284 {
285   return 0u;
286 }
287
288 void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
289                                            CharacterIndex characterIndex,
290                                            Length numberOfCharacters ) const
291 {
292 }
293
294 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
295 {
296   return false;
297 }
298
299 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
300                                           Length numberOfRuns )
301 {
302 }
303
304 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
305 {
306   return 0u;
307 }
308
309 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
310 {
311   return 0u;
312 }
313
314 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
315                                           CharacterIndex characterIndex,
316                                           Length numberOfCharacters ) const
317 {
318 }
319
320 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
321                                           CharacterIndex characterIndex,
322                                           Length numberOfCharacters ) const
323 {
324 }
325
326 LogicalModel::~LogicalModel()
327 {
328   delete mImpl;
329 }
330
331 LogicalModel::LogicalModel()
332 : mImpl( NULL )
333 {
334   mImpl = new LogicalModel::Impl();
335 }
336
337 } // namespace Text
338
339 } // namespace Toolkit
340
341 } // namespace Dali