2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/text/logical-model.h>
22 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
23 #include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
24 #include <dali-toolkit/internal/text/font-run.h>
25 #include <dali-toolkit/internal/text/script-run.h>
39 struct LogicalModel::Impl
41 Vector<Character> mText;
42 Vector<ScriptRun> mScriptRuns;
43 Vector<FontRun> mFontRuns;
44 Vector<LineBreakInfo> mLineBreakInfo;
45 Vector<WordBreakInfo> mWordBreakInfo;
48 LogicalModelPtr LogicalModel::New()
50 return LogicalModelPtr( new LogicalModel() );
53 void LogicalModel::SetText( const Character* const text,
54 Length numberOfCharacters )
56 Vector<Character>& modelText = mImpl->mText;
58 if( 0u == numberOfCharacters )
64 modelText.Resize( numberOfCharacters );
65 memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) );
69 Length LogicalModel::GetNumberOfCharacters() const
71 return mImpl->mText.Count();
74 void LogicalModel::GetText( CharacterIndex characterIndex,
76 Length numberOfCharacters ) const
78 Vector<Character>& modelText = mImpl->mText;
79 memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
82 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
84 return mImpl->mText[characterIndex];
87 void LogicalModel::SetScripts( const ScriptRun* const scripts,
90 Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
92 if( 0u == numberOfRuns )
98 scriptRuns.Resize( numberOfRuns );
99 memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
103 Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
104 Length numberOfCharacters ) const
106 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
108 return mImpl->mScriptRuns.Count();
111 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
112 Length numberOfScriptRuns = 0u;
113 bool firstIndexFound = false;
115 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
117 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
119 if( !firstIndexFound &&
120 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
122 // The character index is within this script run.
123 // Starts the counter of script runs.
124 firstIndexFound = true;
127 if( firstIndexFound )
129 ++numberOfScriptRuns;
130 if( scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters > charcterEndIndex )
132 // This script run exceeds the given range. The number of scripts can be returned.
133 return numberOfScriptRuns;
138 return numberOfScriptRuns;
141 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
142 CharacterIndex characterIndex,
143 Length numberOfCharacters ) const
145 // A better implementation can cache the first script run and the number of then when the GetNumberOfScriptRuns() is called.
147 Length numberOfScriptRuns = GetNumberOfScriptRuns( characterIndex,
148 numberOfCharacters );
150 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
152 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
154 if( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters )
156 memcpy( scriptRuns, scriptRun, sizeof( ScriptRun ) * numberOfScriptRuns );
162 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
164 // If this operation is too slow, consider a binary search.
166 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
168 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
170 if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
171 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
173 return scriptRun->script;
177 return TextAbstraction::UNKNOWN;
180 void LogicalModel::SetFonts( const FontRun* const fonts,
181 Length numberOfRuns )
183 Vector<FontRun>& fontRuns = mImpl->mFontRuns;
185 if( 0u == numberOfRuns )
191 fontRuns.Resize( numberOfRuns );
192 memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
196 Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
197 Length numberOfCharacters ) const
199 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
201 return mImpl->mFontRuns.Count();
204 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
205 Length numberOfFontRuns = 0u;
206 bool firstIndexFound = false;
208 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
210 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
212 if( !firstIndexFound &&
213 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
215 // The character index is within this font run.
216 // Starts the counter of font runs.
217 firstIndexFound = true;
220 if( firstIndexFound )
223 if( fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters > charcterEndIndex )
225 // This font run exceeds the given range. The number of fonts can be returned.
226 return numberOfFontRuns;
231 return numberOfFontRuns;
234 void LogicalModel::GetFontRuns( FontRun* fontRuns,
235 CharacterIndex characterIndex,
236 Length numberOfCharacters ) const
238 // A better implementation can cache the first font run and the number of then when the GetNumberOfFontRuns() is called.
240 Length numberOfFontRuns = GetNumberOfFontRuns( characterIndex,
241 numberOfCharacters );
243 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
245 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
247 if( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters )
249 memcpy( fontRuns, fontRun, sizeof( FontRun ) * numberOfFontRuns );
255 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
257 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
259 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
261 if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
262 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
264 return fontRun->fontId;
271 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
274 Vector<LineBreakInfo>& modelLineBreakInfo = mImpl->mLineBreakInfo;
278 modelLineBreakInfo.Clear();
282 modelLineBreakInfo.Resize( length );
283 memcpy( modelLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) );
287 void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
288 CharacterIndex characterIndex,
289 Length numberOfItems ) const
291 memcpy( lineBreakInfo, mImpl->mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) );
294 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
296 return *( mImpl->mLineBreakInfo.Begin() + characterIndex );
299 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
302 Vector<WordBreakInfo>& modelWordBreakInfo = mImpl->mWordBreakInfo;
306 modelWordBreakInfo.Clear();
310 modelWordBreakInfo.Resize( length );
311 memcpy( modelWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) );
315 void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
316 CharacterIndex characterIndex,
317 Length numberOfItems ) const
319 memcpy( wordBreakInfo, mImpl->mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) );
322 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
324 return *( mImpl->mWordBreakInfo.Begin() + characterIndex );
327 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
328 Length numberOfRuns )
332 Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
333 Length numberOfCharacters ) const
338 void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
339 CharacterIndex characterIndex,
340 Length numberOfCharacters ) const
344 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
349 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
350 Length numberOfRuns )
354 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
359 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
364 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
365 CharacterIndex characterIndex,
366 Length numberOfCharacters ) const
370 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
371 CharacterIndex characterIndex,
372 Length numberOfCharacters ) const
376 LogicalModel::~LogicalModel()
381 LogicalModel::LogicalModel()
384 mImpl = new LogicalModel::Impl();
389 } // namespace Toolkit