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