2 * Copyright (c) 2014 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/controls/text-view/text-processor-bidirectional-info.h>
30 namespace TextProcessor
33 BidirectionalParagraphInfo::BidirectionalParagraphInfo()
34 : mDirection( FRIBIDI_TYPE_ON ),
35 mCharactersTypeBuffer(),
37 mLogicalUnicodeBuffer()
41 BidirectionalParagraphInfo::~BidirectionalParagraphInfo()
45 BidirectionalParagraphInfo::BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info )
46 : mDirection( info.mDirection ),
47 mCharactersTypeBuffer( info.mCharactersTypeBuffer ),
48 mLevelsBuffer( info.mLevelsBuffer ),
49 mLogicalUnicodeBuffer( info.mLogicalUnicodeBuffer )
53 BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const BidirectionalParagraphInfo& info )
57 mDirection = info.mDirection;
58 mCharactersTypeBuffer = info.mCharactersTypeBuffer;
59 mLevelsBuffer = info.mLevelsBuffer;
60 mLogicalUnicodeBuffer = info.mLogicalUnicodeBuffer;
66 bool BidirectionalParagraphInfo::IsRightToLeftParagraph() const
68 bool isRightToLeft = false;
72 case FRIBIDI_PAR_LTR: // Left-To-Right paragraph.
73 case FRIBIDI_PAR_ON: // DirectiOn-Neutral paragraph.
74 case FRIBIDI_PAR_WLTR: // Weak Left To Right paragraph.
76 isRightToLeft = false;
79 case FRIBIDI_PAR_RTL: // Right-To-Left paragraph.
80 case FRIBIDI_PAR_WRTL: // Weak Right To Left paragraph.
90 BidirectionalLineInfo::BidirectionalLineInfo()
91 : mCharacterParagraphIndex(),
92 mNumberOfCharacters(),
94 mVisualToLogicalMap(),
99 BidirectionalLineInfo::~BidirectionalLineInfo()
103 BidirectionalLineInfo::BidirectionalLineInfo( const BidirectionalLineInfo& info )
104 : mCharacterParagraphIndex( info.mCharacterParagraphIndex ),
105 mNumberOfCharacters( info.mNumberOfCharacters ),
107 mVisualToLogicalMap( info.mVisualToLogicalMap ),
108 mLogicalToVisualMap( info.mLogicalToVisualMap )
112 BidirectionalLineInfo& BidirectionalLineInfo::operator=( const BidirectionalLineInfo& info )
116 mCharacterParagraphIndex = info.mCharacterParagraphIndex;
117 mNumberOfCharacters = info.mNumberOfCharacters;
119 mVisualToLogicalMap = info.mVisualToLogicalMap;
120 mLogicalToVisualMap = info.mLogicalToVisualMap;
126 bool BeginsRightToLeftCharacter( const Text& text )
128 for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
130 Character::CharacterDirection direction = text[i].GetCharacterDirection();
131 if( direction != Character::Neutral )
133 return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak );
140 bool ContainsRightToLeftCharacter( const Dali::Text& text )
142 for( size_t i = 0u, length = text.GetLength(); i < length; ++i )
144 Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection();
145 if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) )
154 void ProcessBidirectionalText( Text& paragraph, BidirectionalParagraphInfo* info )
156 if( paragraph.IsEmpty() )
158 // nothing to do if the paragraph is empty.
162 const std::size_t stringSize = paragraph.GetText().size();
164 // Text buffer in logical order. Coded in unicode.
165 info->mLogicalUnicodeBuffer.resize( stringSize + 1u, 0u );
166 FriBidiChar* logicalUnicodeBufferPointer = &info->mLogicalUnicodeBuffer[0u];
168 // Converts from utf8 to unicode.
169 const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, paragraph.GetText().c_str(), stringSize, logicalUnicodeBufferPointer );
171 // Character type buffer.
172 info->mCharactersTypeBuffer.resize( length, 0u );
175 info->mLevelsBuffer.resize( length, 0u );
177 // Joining type buffer.
178 std::vector<FriBidiJoiningType> joiningTypeBuffer;
179 joiningTypeBuffer.resize( length, 0u );
181 // Pointers to the buffers.
182 FriBidiCharType* charactersTypeBufferPointer = &info->mCharactersTypeBuffer[0u];
183 FriBidiLevel* levelsBufferPointer = &info->mLevelsBuffer[0u];
184 FriBidiJoiningType* joiningTypeBufferPointer = &joiningTypeBuffer[0u];
186 // Retrieves the type of each character.
187 fribidi_get_bidi_types( logicalUnicodeBufferPointer, length, charactersTypeBufferPointer );
189 // Retrieves the paragraph direction.
190 info->mDirection = fribidi_get_par_direction( charactersTypeBufferPointer, length );
192 // Retrieve the embedding levels.
193 fribidi_get_par_embedding_levels( charactersTypeBufferPointer, length, &info->mDirection, levelsBufferPointer );
195 // Retrieve the joining types.
196 fribidi_get_joining_types( logicalUnicodeBufferPointer, length, joiningTypeBufferPointer );
198 fribidi_join_arabic( charactersTypeBufferPointer, length, levelsBufferPointer, joiningTypeBufferPointer );
200 const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
202 fribidi_shape( flags, levelsBufferPointer, length, joiningTypeBufferPointer, logicalUnicodeBufferPointer );
204 std::vector<char> bidiTextConverted;
206 bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
207 // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
209 fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, logicalUnicodeBufferPointer, length, &bidiTextConverted[0] );
211 paragraph = Text( &bidiTextConverted[0u] );
214 void ReorderLine( BidirectionalParagraphInfo* paragraphInfo,
215 BidirectionalLineInfo* lineInfo )
217 const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
219 lineInfo->mVisualToLogicalMap.Resize( lineInfo->mNumberOfCharacters, 0u );
220 lineInfo->mLogicalToVisualMap.Resize( lineInfo->mNumberOfCharacters, 0u );
222 std::vector<FriBidiChar> visualUnicodeBuffer;
223 visualUnicodeBuffer.insert( visualUnicodeBuffer.end(),
224 paragraphInfo->mLogicalUnicodeBuffer.begin() + lineInfo->mCharacterParagraphIndex,
225 paragraphInfo->mLogicalUnicodeBuffer.begin() + ( lineInfo->mCharacterParagraphIndex + lineInfo->mNumberOfCharacters ) );
227 // Pointers to the buffers.
228 FriBidiCharType* charactersTypeBufferPointer = ¶graphInfo->mCharactersTypeBuffer[lineInfo->mCharacterParagraphIndex];
229 FriBidiLevel* levelsBufferPointer = ¶graphInfo->mLevelsBuffer[lineInfo->mCharacterParagraphIndex];
230 FriBidiChar* visualUnicodeBufferPointer = &visualUnicodeBuffer[0u];
231 FriBidiStrIndex* visualToLogicalMapPointer = &lineInfo->mVisualToLogicalMap[0u];
233 // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table.
234 for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
236 lineInfo->mVisualToLogicalMap[ index ] = index;
239 fribidi_reorder_line( flags,
240 charactersTypeBufferPointer,
241 lineInfo->mNumberOfCharacters,
243 paragraphInfo->mDirection,
245 visualUnicodeBufferPointer,
246 visualToLogicalMapPointer );
248 // Fill the logical to visual mapping table.
249 for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index )
251 lineInfo->mLogicalToVisualMap[ lineInfo->mVisualToLogicalMap[ index ] ] = index;
254 std::vector<char> bidiTextConverted;
256 bidiTextConverted.resize( lineInfo->mNumberOfCharacters * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6.
257 // Currently Dali doesn't support this UTF-8 extension.
258 // Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character.
260 fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualUnicodeBufferPointer, lineInfo->mNumberOfCharacters, &bidiTextConverted[0u] );
262 lineInfo->mText = Text( &bidiTextConverted[0u] );
265 } // namespace TextProcessor
267 } // namespace Internal
269 } // namespace Toolkit