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-impl.h>
22 #include <dali-toolkit/internal/text/input-style.h>
23 #include <dali-toolkit/internal/text/text-style-run-container.h>
34 LogicalModelPtr LogicalModel::New()
36 return LogicalModelPtr( new LogicalModel() );
39 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
41 // If this operation is too slow, consider a binary search.
43 for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index )
45 const ScriptRun* const scriptRun = mScriptRuns.Begin() + index;
47 if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
48 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
50 return scriptRun->script;
54 return TextAbstraction::UNKNOWN;
57 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
59 if( characterIndex >= mCharacterDirections.Count() )
61 // The model has no right to left characters, so the vector of directions is void.
65 return *( mCharacterDirections.Begin() + characterIndex );
68 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
71 if( 0u == numberOfRuns )
73 mVisualToLogicalMap.Clear();
74 mLogicalToVisualMap.Clear();
75 mVisualToLogicalCursorMap.Clear();
79 const Length numberOfCharacters = mText.Count();
80 mVisualToLogicalMap.Resize( numberOfCharacters );
81 mLogicalToVisualMap.Resize( numberOfCharacters );
83 const Length numberOfCharactersPlus = numberOfCharacters + 1u;
84 mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus );
86 CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
87 CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
89 CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
91 CharacterIndex lastIndex = 0u;
92 for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
94 const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
96 if( lastIndex < bidiLineInfo.characterRun.characterIndex )
98 // Fill with the identity.
99 for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
101 *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
105 // Fill the conversion table of the run.
106 for( CharacterIndex index = 0u;
107 index < bidiLineInfo.characterRun.numberOfCharacters;
108 ++index, ++lastIndex )
110 *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
114 // Complete with the identity if there are some left to right characters after the last right to left.
115 for( ; lastIndex < numberOfCharacters; ++lastIndex )
117 *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
120 // Sets the logical to visual conversion map.
121 for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
123 *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
126 // Sets the visual to logical conversion map for cursor positions.
128 const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
129 BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
130 BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
132 const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
134 Length bidirectionalParagraphIndex = 0u;
135 bool isRightToLeftParagraph = false;
136 for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index )
138 if( bidirectionalParagraph &&
139 ( bidirectionalParagraph->characterRun.characterIndex == index ) )
141 isRightToLeftParagraph = *( modelCharacterDirections + index );
146 if( isRightToLeftParagraph )
148 *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
150 else // else logical position is zero.
152 *( modelVisualToLogicalCursorMap + index ) = 0u;
155 else if( numberOfCharacters == index )
157 if( isRightToLeftParagraph )
159 *( modelVisualToLogicalCursorMap + index ) = 0u;
161 else // else logical position is the number of characters.
163 *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
168 // Get the character indexed by index - 1 and index
169 // and calculate the logical position according the directions of
170 // both characters and the direction of the paragraph.
172 const CharacterIndex previousIndex = index - 1u;
173 const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
174 const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
176 const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
177 const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
179 if( direction0 == direction1 )
181 // Both glyphs have the same direction.
184 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
188 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
193 if( isRightToLeftParagraph )
197 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
201 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
208 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
212 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
218 if( bidirectionalParagraph &&
219 ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
221 isRightToLeftParagraph = false;
222 ++bidirectionalParagraphIndex;
223 if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
225 bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
229 bidirectionalParagraph = NULL;
236 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
238 if( 0u == mVisualToLogicalMap.Count() )
240 // If there is no visual to logical info is because the whole text is left to right.
241 // Return the identity.
242 return visualCharacterIndex;
245 return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
248 void LogicalModel::UpdateTextStyleRuns( CharacterIndex index, int numberOfCharacters )
250 const Length totalNumberOfCharacters = mText.Count();
252 // Process the color runs.
253 Vector<ColorRun> removedColorRuns;
254 UpdateCharacterRuns<ColorRun>( index,
256 totalNumberOfCharacters,
261 void LogicalModel::RetrieveStyle( CharacterIndex index, InputStyle& style )
263 unsigned int runIndex = 0u;
264 unsigned int lastRunIndex = 0u;
265 bool overriden = false;
267 // Set the text color.
268 for( Vector<ColorRun>::ConstIterator it = mColorRuns.Begin(),
269 endIt = mColorRuns.End();
273 const ColorRun& colorRun = *it;
275 if( ( colorRun.characterRun.characterIndex <= index ) &&
276 ( index < colorRun.characterRun.characterIndex + colorRun.characterRun.numberOfCharacters ) )
278 lastRunIndex = runIndex;
283 // Set the text's color if it's overriden.
286 style.textColor = ( *( mColorRuns.Begin() + lastRunIndex ) ).color;
290 LogicalModel::~LogicalModel()
294 LogicalModel::LogicalModel()
300 } // namespace Toolkit