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/public-api/text/logical-model.h>
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>
39 struct LogicalModel::Impl
41 Vector<Character> mText;
42 Vector<ScriptRun> mScriptRuns;
43 Vector<FontRun> mFontRuns;
46 LogicalModelPtr LogicalModel::New()
48 return LogicalModelPtr( new LogicalModel() );
51 void LogicalModel::SetText( const Character* const text,
52 Length numberOfCharacters )
54 Vector<Character>& modelText = mImpl->mText;
55 modelText.Resize( numberOfCharacters );
56 memcpy( modelText.Begin(), text, numberOfCharacters * sizeof( Character ) );
59 Length LogicalModel::GetNumberOfCharacters() const
61 return mImpl->mText.Count();
64 void LogicalModel::GetText( CharacterIndex characterIndex,
66 Length numberOfCharacters ) const
68 Vector<Character>& modelText = mImpl->mText;
69 memcpy( text, modelText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
72 Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
74 return mImpl->mText[characterIndex];
77 void LogicalModel::SetScripts( const ScriptRun* const scripts,
80 Vector<ScriptRun>& scriptRuns = mImpl->mScriptRuns;
81 scriptRuns.Resize( numberOfRuns );
82 memcpy( scriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
85 Length LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
86 Length numberOfCharacters ) const
88 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
90 return mImpl->mScriptRuns.Count();
93 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
94 Length numberOfScriptRuns = 0u;
95 bool firstIndexFound = false;
97 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
99 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
101 if( !firstIndexFound &&
102 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
104 // The character index is within this script run.
105 // Starts the counter of script runs.
106 firstIndexFound = true;
109 if( firstIndexFound )
111 ++numberOfScriptRuns;
112 if( scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters > charcterEndIndex )
114 // This script run exceeds the given range. The number of scripts can be returned.
115 return numberOfScriptRuns;
120 return numberOfScriptRuns;
123 void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
124 CharacterIndex characterIndex,
125 Length numberOfCharacters ) const
127 // A better implementation can cache the first script run and the number of then when the GetNumberOfScriptRuns() is called.
129 Length numberOfScriptRuns = GetNumberOfScriptRuns( characterIndex,
130 numberOfCharacters );
132 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
134 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
136 if( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters )
138 memcpy( scriptRuns, scriptRun, sizeof( ScriptRun ) * numberOfScriptRuns );
144 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
146 // If this operation is too slow, consider a binary search.
148 for( Length index = 0u, length = mImpl->mScriptRuns.Count(); index < length; ++index )
150 const ScriptRun* const scriptRun = mImpl->mScriptRuns.Begin() + index;
152 if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
153 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
155 return scriptRun->script;
159 return TextAbstraction::UNKNOWN;
162 void LogicalModel::SetFonts( const FontRun* const fonts,
163 Length numberOfRuns )
165 Vector<FontRun>& fontRuns = mImpl->mFontRuns;
166 fontRuns.Resize( numberOfRuns );
167 memcpy( fontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
170 Length LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
171 Length numberOfCharacters ) const
173 if( ( 0u == characterIndex ) && ( mImpl->mText.Count() == numberOfCharacters ) )
175 return mImpl->mFontRuns.Count();
178 const CharacterIndex charcterEndIndex = characterIndex + numberOfCharacters;
179 Length numberOfFontRuns = 0u;
180 bool firstIndexFound = false;
182 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
184 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
186 if( !firstIndexFound &&
187 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
189 // The character index is within this font run.
190 // Starts the counter of font runs.
191 firstIndexFound = true;
194 if( firstIndexFound )
197 if( fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters > charcterEndIndex )
199 // This font run exceeds the given range. The number of fonts can be returned.
200 return numberOfFontRuns;
205 return numberOfFontRuns;
208 void LogicalModel::GetFontRuns( FontRun* fontRuns,
209 CharacterIndex characterIndex,
210 Length numberOfCharacters ) const
212 // A better implementation can cache the first font run and the number of then when the GetNumberOfFontRuns() is called.
214 Length numberOfFontRuns = GetNumberOfFontRuns( characterIndex,
215 numberOfCharacters );
217 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
219 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
221 if( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters )
223 memcpy( fontRuns, fontRun, sizeof( FontRun ) * numberOfFontRuns );
229 FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
231 for( Length index = 0u, length = mImpl->mFontRuns.Count(); index < length; ++index )
233 const FontRun* const fontRun = mImpl->mFontRuns.Begin() + index;
235 if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
236 ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
238 return fontRun->fontId;
245 void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
250 void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
251 CharacterIndex characterIndex,
252 Length numberOfItems ) const
256 LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
261 void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
266 void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
267 CharacterIndex characterIndex,
268 Length numberOfItems ) const
272 WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
277 void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
278 Length numberOfRuns )
282 Length LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
283 Length numberOfCharacters ) const
288 void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
289 CharacterIndex characterIndex,
290 Length numberOfCharacters ) const
294 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
299 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
300 Length numberOfRuns )
304 CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
309 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
314 void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
315 CharacterIndex characterIndex,
316 Length numberOfCharacters ) const
320 void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
321 CharacterIndex characterIndex,
322 Length numberOfCharacters ) const
326 LogicalModel::~LogicalModel()
331 LogicalModel::LogicalModel()
334 mImpl = new LogicalModel::Impl();
339 } // namespace Toolkit