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/bidirectional-support.h>
22 #include <dali/public-api/text-abstraction/bidirectional-support.h>
37 * @brief Get the lines of a paragraph.
39 * @param[in] paragraphInfo The paragraph.
40 * @param[in] lines The lines.
41 * @param[in] lineIndex Index pointing the first line to be checked.
42 * @param[out] firstLine Index to the first line of the paragraph.
43 * @param[out] numberOfLines The number of lines.
45 void GetLines( const BidirectionalParagraphInfoRun& paragraphInfo,
46 const Vector<LineRun>& lines,
47 unsigned int lineIndex,
48 unsigned int& firstLine,
49 unsigned int& numberOfLines )
51 firstLine = lineIndex;
54 const CharacterIndex lastCharacterIndex = paragraphInfo.characterRun.characterIndex + paragraphInfo.characterRun.numberOfCharacters;
55 bool firstLineFound = false;
57 for( Vector<LineRun>::ConstIterator it = lines.Begin() + lineIndex,
62 const LineRun& line = *it;
64 if( ( line.characterRun.characterIndex + line.characterRun.numberOfCharacters > paragraphInfo.characterRun.characterIndex ) &&
65 ( lastCharacterIndex > line.characterRun.characterIndex ) )
67 firstLineFound = true;
70 else if( lastCharacterIndex <= line.characterRun.characterIndex )
72 // nothing else to do.
85 void SetBidirectionalInfo( const Vector<Character>& text,
86 const Vector<ScriptRun>& scripts,
87 const Vector<LineBreakInfo>& lineBreakInfo,
88 Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo )
90 // Traverse the script runs. If there is one with a right to left script, create the bidirectional info for the paragraph containing that script is needed.
91 // From the bidirectional point of view, a paragraph is the piece of text between two LINE_MUST_BREAK.
93 // Index pointing the first character of the current paragraph.
94 CharacterIndex paragraphCharacterIndex = 0u;
96 // Pointer to the text buffer.
97 const Character* textBuffer = text.Begin();
99 // Pointer to the line break info buffer.
100 const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
102 // The number of characters.
103 const Length numberOfCharacters = text.Count();
105 // Handle to the bidirectional info module in text-abstraction.
106 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
108 for( Vector<ScriptRun>::ConstIterator it = scripts.Begin(),
109 endIt = scripts.End();
113 const ScriptRun& scriptRun = *it;
114 const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters;
116 if( TextAbstraction::IsRightToLeftScript( scriptRun.script ) && // The script is right to left.
117 ( lastScriptRunIndex > paragraphCharacterIndex ) ) // It isn't part of a previous paragraph.
119 // Find the paragraphs which contains this script run.
121 // 1) Different paragraphs may contain this script run.
122 // ------||------------------- rtl sr ------------------------||-------------------
123 // --||----- p -----||------------------ p -------------||-------- p ------||------
125 // 2) The paragraph which contains this script run may contain other right to left script runs.
126 // -----||--- rtl sr ---||---- ltr sr ----||---------- rtl sr -----------||--------
127 // -----||---------------------------------- p -----------------------------------|
129 while( lastScriptRunIndex > paragraphCharacterIndex )
131 // There is a paragraph which contains the current script.
133 Length index = paragraphCharacterIndex;
134 while( ( index < numberOfCharacters ) && ( paragraphCharacterIndex < lastScriptRunIndex ) )
136 if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
138 if( index >= scriptRun.characterRun.characterIndex )
140 // The Bidirectional run must have the same number of characters than the paragraph.
141 BidirectionalParagraphInfoRun bidirectionalRun;
142 bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex;
143 bidirectionalRun.characterRun.numberOfCharacters = ( index - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah.
145 // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run.
146 bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex,
147 bidirectionalRun.characterRun.numberOfCharacters );
149 bidirectionalInfo.PushBack( bidirectionalRun );
152 // Update the character index of the next paragraph.
153 paragraphCharacterIndex = index + 1u;
158 // The last character is always a must-break, so there is no need to check if there is characters left.
164 void ReplaceBidirectionalInfo( LogicalModel& model,
165 CharacterIndex characterIndex,
166 Length numberOfCharactersToRemove,
167 Length numberOfCharactersToInsert )
171 void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
172 const Vector<LineRun>& lineRuns,
173 Vector<BidirectionalLineInfoRun>& lineInfoRuns )
175 // Handle to the bidirectional info module in text-abstraction.
176 TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get();
178 // Keep an index to the first line to be checked if it's contained inside the paragraph.
179 // Avoids check the lines from the beginning for each paragraph.
180 unsigned int lineIndex = 0u;
182 for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = bidirectionalInfo.Begin(),
183 endIt = bidirectionalInfo.End();
187 const BidirectionalParagraphInfoRun& paragraphInfo = *it;
189 // Get the lines for this paragraph.
190 unsigned int firstLine = 0u;
191 unsigned int numberOfLines = 0u;
193 // Get an index to the first line and the number of lines of the current paragraph.
194 GetLines( paragraphInfo,
200 lineIndex = firstLine + numberOfLines;
202 // Traverse the lines and reorder them
203 for( Vector<LineRun>::ConstIterator lineIt = lineRuns.Begin() + firstLine,
204 endLineIt = lineRuns.Begin() + firstLine + numberOfLines;
208 const LineRun& line = *lineIt;
210 // Creates a bidirectional info for the line run.
211 BidirectionalLineInfoRun lineInfoRun;
212 lineInfoRun.characterRun.characterIndex = line.characterRun.characterIndex;
213 lineInfoRun.characterRun.numberOfCharacters = line.characterRun.numberOfCharacters;
215 // Allocate space for the conversion maps.
216 // The memory is freed after the visual to logical to visual conversion tables are built in the logical model.
217 lineInfoRun.visualToLogicalMap = reinterpret_cast<CharacterIndex*>( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) );
219 // Reorders the line.
220 bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex,
221 line.characterRun.characterIndex,
222 line.characterRun.numberOfCharacters,
223 lineInfoRun.visualToLogicalMap );
225 // Push the run into the vector.
226 lineInfoRuns.PushBack( lineInfoRun );
231 void ReorderLines( LogicalModel& logicalModel,
232 const VisualModel& visualModel,
233 CharacterIndex characterIndex,
234 Length numberOfCharactersToRemove,
235 Length numberOfCharactersToInsert )
241 } // namespace Toolkit