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>
30 LogicalModelPtr LogicalModel::New()
32 return LogicalModelPtr( new LogicalModel() );
35 Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
37 // If this operation is too slow, consider a binary search.
39 for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index )
41 const ScriptRun* const scriptRun = mScriptRuns.Begin() + index;
43 if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
44 ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
46 return scriptRun->script;
50 return TextAbstraction::UNKNOWN;
53 CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
55 if( characterIndex >= mCharacterDirections.Count() )
57 // The model has no right to left characters, so the vector of directions is void.
61 return *( mCharacterDirections.Begin() + characterIndex );
64 void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
67 if( 0u == numberOfRuns )
69 mVisualToLogicalMap.Clear();
70 mLogicalToVisualMap.Clear();
71 mVisualToLogicalCursorMap.Clear();
75 const Length numberOfCharacters = mText.Count();
76 mVisualToLogicalMap.Resize( numberOfCharacters );
77 mLogicalToVisualMap.Resize( numberOfCharacters );
79 const Length numberOfCharactersPlus = numberOfCharacters + 1u;
80 mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus );
82 CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
83 CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
85 CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
87 CharacterIndex lastIndex = 0u;
88 for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
90 const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
92 if( lastIndex < bidiLineInfo.characterRun.characterIndex )
94 // Fill with the identity.
95 for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
97 *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
101 // Fill the conversion table of the run.
102 for( CharacterIndex index = 0u;
103 index < bidiLineInfo.characterRun.numberOfCharacters;
104 ++index, ++lastIndex )
106 *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
110 // Complete with the identity if there are some left to right characters after the last right to left.
111 for( ; lastIndex < numberOfCharacters; ++lastIndex )
113 *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
116 // Sets the logical to visual conversion map.
117 for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
119 *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
122 // Sets the visual to logical conversion map for cursor positions.
124 const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
125 BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
126 BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
128 const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
130 Length bidirectionalParagraphIndex = 0u;
131 bool isRightToLeftParagraph = false;
132 for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index )
134 if( bidirectionalParagraph &&
135 ( bidirectionalParagraph->characterRun.characterIndex == index ) )
137 isRightToLeftParagraph = *( modelCharacterDirections + index );
142 if( isRightToLeftParagraph )
144 *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
146 else // else logical position is zero.
148 *( modelVisualToLogicalCursorMap + index ) = 0u;
151 else if( numberOfCharacters == index )
153 if( isRightToLeftParagraph )
155 *( modelVisualToLogicalCursorMap + index ) = 0u;
157 else // else logical position is the number of characters.
159 *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
164 // Get the character indexed by index - 1 and index
165 // and calculate the logical position according the directions of
166 // both characters and the direction of the paragraph.
168 const CharacterIndex previousIndex = index - 1u;
169 const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
170 const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
172 const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
173 const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
175 if( direction0 == direction1 )
177 // Both glyphs have the same direction.
180 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
184 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
189 if( isRightToLeftParagraph )
193 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
197 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
204 *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
208 *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
214 if( bidirectionalParagraph &&
215 ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
217 isRightToLeftParagraph = false;
218 ++bidirectionalParagraphIndex;
219 if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
221 bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
225 bidirectionalParagraph = NULL;
232 CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
234 if( 0u == mVisualToLogicalMap.Count() )
236 // If there is no visual to logical info is because the whole text is left to right.
237 // Return the identity.
238 return visualCharacterIndex;
241 return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
244 LogicalModel::~LogicalModel()
248 LogicalModel::LogicalModel()
254 } // namespace Toolkit