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 "bidirectional-support-impl.h"
22 #include <singleton-service-impl.h>
26 #include <fribidi/fribidi.h>
31 namespace TextAbstraction
37 struct BidirectionalSupport::BidirectionalInfo
39 FriBidiCharType* characterTypes; ///< The type of each character (right, left, neutral, ...)
40 FriBidiLevel* embeddedLevels; ///< Embedded levels.
41 FriBidiParType paragraphDirection; ///< The paragraph's direction.
44 BidirectionalSupport::BidirectionalSupport()
46 mParagraphBidirectionalInfo(),
51 BidirectionalSupport::~BidirectionalSupport()
53 // free all resources.
54 for( Vector<BidirectionalInfo*>::Iterator it = mParagraphBidirectionalInfo.Begin(),
55 endIt = mParagraphBidirectionalInfo.End();
59 BidirectionalInfo* info = *it;
61 free( info->embeddedLevels );
62 free( info->characterTypes );
67 TextAbstraction::BidirectionalSupport BidirectionalSupport::Get()
69 TextAbstraction::BidirectionalSupport bidirectionalSupportHandle;
71 SingletonService service( SingletonService::Get() );
74 // Check whether the singleton is already created
75 BaseHandle handle = service.GetSingleton( typeid( TextAbstraction::BidirectionalSupport ) );
78 // If so, downcast the handle
79 BidirectionalSupport* impl = dynamic_cast< Internal::BidirectionalSupport* >( handle.GetObjectPtr() );
80 bidirectionalSupportHandle = TextAbstraction::BidirectionalSupport( impl );
82 else // create and register the object
84 bidirectionalSupportHandle = TextAbstraction::BidirectionalSupport( new BidirectionalSupport );
85 service.Register( typeid( bidirectionalSupportHandle ), bidirectionalSupportHandle );
89 return bidirectionalSupportHandle;
92 BidiInfoIndex BidirectionalSupport::CreateInfo( const Character* const paragraph,
93 Length numberOfCharacters )
95 // Reserve memory for the paragraph's bidirectional info.
96 BidirectionalInfo* bidirectionalInfo = new BidirectionalInfo();
98 bidirectionalInfo->characterTypes = reinterpret_cast<FriBidiCharType*>( malloc( numberOfCharacters * sizeof( FriBidiCharType ) ) );
99 bidirectionalInfo->embeddedLevels = reinterpret_cast<FriBidiLevel*>( malloc( numberOfCharacters * sizeof( FriBidiLevel ) ) );
101 // Retrieve the type of each character..
102 fribidi_get_bidi_types( paragraph, numberOfCharacters, bidirectionalInfo->characterTypes );
104 // Retrieve the paragraph's direction.
105 bidirectionalInfo->paragraphDirection = fribidi_get_par_direction( paragraph, numberOfCharacters );
107 // Retrieve the embedding levels.
108 fribidi_get_par_embedding_levels( paragraph, numberOfCharacters, &bidirectionalInfo->paragraphDirection, bidirectionalInfo->embeddedLevels );
110 // Store the bidirectional info and return the index.
111 BidiInfoIndex index = 0u;
112 const std::size_t numberOfItems = mFreeIndices.Count();
113 if( numberOfItems != 0u )
115 Vector<BidiInfoIndex>::Iterator it = mFreeIndices.End() - 1u;
119 mFreeIndices.Remove( it );
121 *( mParagraphBidirectionalInfo.Begin() + index ) = bidirectionalInfo;
125 index = static_cast<BidiInfoIndex>( numberOfItems );
127 mParagraphBidirectionalInfo.PushBack( bidirectionalInfo );
133 void BidirectionalSupport::DestroyInfo( BidiInfoIndex bidiInfoIndex )
135 if( bidiInfoIndex >= mParagraphBidirectionalInfo.Count() )
140 // Retrieve the paragraph's bidirectional info.
141 Vector<BidirectionalInfo*>::Iterator it = mParagraphBidirectionalInfo.Begin() + bidiInfoIndex;
142 BidirectionalInfo* bidirectionalInfo = *it;
144 if( NULL != bidirectionalInfo )
146 // Free resources and destroy the container.
147 free( bidirectionalInfo->embeddedLevels );
148 free( bidirectionalInfo->characterTypes );
149 delete bidirectionalInfo;
154 // Add the index to the free indices vector.
155 mFreeIndices.PushBack( bidiInfoIndex );
158 void BidirectionalSupport::Reorder( BidiInfoIndex bidiInfoIndex,
159 CharacterIndex firstCharacterIndex,
160 Length numberOfCharacters,
161 CharacterIndex* visualToLogicalMap )
163 const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC;
165 // Retrieve the paragraph's bidirectional info.
166 const BidirectionalInfo* const bidirectionalInfo = *( mParagraphBidirectionalInfo.Begin() + bidiInfoIndex );
168 // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table.
169 for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
171 visualToLogicalMap[ index ] = index;
174 // Copy embedded levels as fribidi_reorder_line() may change them.
175 const uint32_t embeddedLevelsSize = numberOfCharacters * sizeof( FriBidiLevel );
176 FriBidiLevel* embeddedLevels = reinterpret_cast<FriBidiLevel*>( malloc( embeddedLevelsSize ) );
177 memcpy( embeddedLevels, bidirectionalInfo->embeddedLevels + firstCharacterIndex, embeddedLevelsSize );
180 fribidi_reorder_line( flags,
181 bidirectionalInfo->characterTypes + firstCharacterIndex,
184 bidirectionalInfo->paragraphDirection,
187 reinterpret_cast<FriBidiStrIndex*>( visualToLogicalMap ) );
190 free( embeddedLevels );
193 } // namespace Internal
195 } // namespace TextAbstraction