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