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;
57 modelText.Resize( numberOfCharacters );
58 memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) );
61 Length LogicalModel::GetNumberOfCharacters() const
63 return mImpl->mText.Count();
66 void LogicalModel::GetText( CharacterIndex characterIndex,
68 Length numberOfCharacters ) const
70 Vector<Character>& modelText = mImpl->mText;
71 memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
74 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
76 return mImpl->mText[characterIndex];
79 void LogicalModel::SetScripts( const ScriptRun* const scripts,
82 Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
83 scriptRuns.Resize( numberOfRuns );
84 memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
87 Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
88 Length numberOfCharacters ) const
90 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
92 return mImpl->mScriptRuns.Count();
95 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
96 Length numberOfScriptRuns = 0u;
97 bool firstIndexFound = false;
99 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
101 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
103 if( !firstIndexFound &&
104 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
106 // The character index is within this script run.
107 // Starts the counter of script runs.
108 firstIndexFound = true;
111 if( firstIndexFound )
113 ++numberOfScriptRuns;
114 if( scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters > charcterEndIndex )
116 // This script run exceeds the given range. The number of scripts can be returned.
117 return numberOfScriptRuns;
122 return numberOfScriptRuns;
125 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
126 CharacterIndex characterIndex,
127 Length numberOfCharacters ) const
129 // A better implementation can cache the first script run and the number of then when the GetNumberOfScriptRuns() is called.
131 Length numberOfScriptRuns = GetNumberOfScriptRuns( characterIndex,
132 numberOfCharacters );
134 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
136 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
138 if( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters )
140 memcpy( scriptRuns, scriptRun, sizeof( ScriptRun ) * numberOfScriptRuns );
146 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
148 // If this operation is too slow, consider a binary search.
150 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
152 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
154 if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
155 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
157 return scriptRun->script;
161 return TextAbstraction::UNKNOWN;
164 void LogicalModel::SetFonts( const FontRun* const fonts,
165 Length numberOfRuns )
167 Vector<FontRun>& fontRuns = mImpl->mFontRuns;
168 fontRuns.Resize( numberOfRuns );
169 memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
172 Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
173 Length numberOfCharacters ) const
175 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
177 return mImpl->mFontRuns.Count();
180 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
181 Length numberOfFontRuns = 0u;
182 bool firstIndexFound = false;
184 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
186 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
188 if( !firstIndexFound &&
189 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
191 // The character index is within this font run.
192 // Starts the counter of font runs.
193 firstIndexFound = true;
196 if( firstIndexFound )
199 if( fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters > charcterEndIndex )
201 // This font run exceeds the given range. The number of fonts can be returned.
202 return numberOfFontRuns;
207 return numberOfFontRuns;
210 void LogicalModel::GetFontRuns( FontRun* fontRuns,
211 CharacterIndex characterIndex,
212 Length numberOfCharacters ) const
214 // A better implementation can cache the first font run and the number of then when the GetNumberOfFontRuns() is called.
216 Length numberOfFontRuns = GetNumberOfFontRuns( characterIndex,
217 numberOfCharacters );
219 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
221 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
223 if( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters )
225 memcpy( fontRuns, fontRun, sizeof( FontRun ) * numberOfFontRuns );
231 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
233 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
235 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
237 if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
238 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
240 return fontRun->fontId;
247 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
250 Vector<LineBreakInfo>& modelLineBreakInfo = mImpl->mLineBreakInfo;
251 modelLineBreakInfo.Resize( length );
252 memcpy( modelLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) );
255 void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
256 CharacterIndex characterIndex,
257 Length numberOfItems ) const
259 memcpy( lineBreakInfo, mImpl->mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) );
262 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
264 return *( mImpl->mLineBreakInfo.Begin() + characterIndex );
267 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
270 Vector<WordBreakInfo>& modelWordBreakInfo = mImpl->mWordBreakInfo;
271 modelWordBreakInfo.Resize( length );
272 memcpy( modelWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) );
275 void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
276 CharacterIndex characterIndex,
277 Length numberOfItems ) const
279 memcpy( wordBreakInfo, mImpl->mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) );
282 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
284 return *( mImpl->mWordBreakInfo.Begin() + characterIndex );
287 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
288 Length numberOfRuns )
292 Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
293 Length numberOfCharacters ) const
298 void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
299 CharacterIndex characterIndex,
300 Length numberOfCharacters ) const
304 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
309 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
310 Length numberOfRuns )
314 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
319 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
324 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
325 CharacterIndex characterIndex,
326 Length numberOfCharacters ) const
330 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
331 CharacterIndex characterIndex,
332 Length numberOfCharacters ) const
336 LogicalModel::~LogicalModel()
341 LogicalModel::LogicalModel()
344 mImpl = new LogicalModel::Impl();
349 } // namespace Toolkit