First public contribution.
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #include "mglyphs.inl"
20 TInt BidiCopy::Mirror(TInt a)
22 Find the mirror image of a character.
26 TInt current = MirrorStart(a);
27 unsigned long v = mGlyphArray[current];
29 // 1st easy-out: no steps at all for any at this key
32 // 2nd easy-out: no steps at all but we have found it
35 TInt step = MirrorStep(a);
38 current &= (KMirrorTableSize-1);
39 key = mGlyphArray[current] >> 16;
41 return mGlyphArray[current] & 0xFFFF;
46 void BidiCopy::ReverseCodes(TText* aText, TInt aLength)
48 Reverse the contents of aText[0..aLength], so that aText[0] holds the
49 value previously found in aText[aLength - 1], aText[1] holds the value
50 previously held in aText[aLength - 2] and so on.
54 TText *text = aText; // backup
56 // reverse int16 by int16 (note: high surrogate + low surrogate will be reverse to low surrogate + high surrogate)
57 TText* end = aText + aLength - 1;
67 CorrectSurrogatePairs(text, aLength);
70 void BidiCopy::DeleteUnreversedSurrogates(TText* aText, TInt aLength)
72 Replaces all surrogates with 0xFFFF that are not paired up the wrong
79 TText* end = aText + aLength;
82 if ((aText[0] & 0xF800) == 0xD800)
84 if ((aText[0] & 0xFC00) == 0xD800
86 && (aText[1] & 0xFC00) == 0xDC00)
95 void BidiCopy::CorrectSurrogatePairs(TText* aText, TInt aLength)
97 Corrects all reversed surrogate pairs. Assumes that no unpaired
98 surrogates are present.
102 TText* end = aText + aLength;
105 if ((aText[0] & 0xF800) == 0xD800)
107 // Surrogate pair discovered.
108 // Do we need to swap it?
109 ASSERT(aText + 1 < end);
110 ASSERT((aText[1] & 0xF800) == 0xD800);
111 if ((aText[0] & 0xFC00) == 0xDC00)
113 ASSERT((aText[1] & 0xFC00) == 0xD800);
124 void BidiCopy::CorrectGroups(TText* aText, TInt aLength)
126 Correct all reversed groups (non-combiner followed by combining
127 characters). Surrogate pairs may be reversed by this operation.
128 Assumes that no unpaired surrogates are present.
129 Leading and trailing 0xFFFFs are left alone.
133 TText *end = aText + aLength;
134 // Ignore leading 0xFFFFs. This helps Tagma's
135 // RTmTextCache::GetDisplayedText with its sentinels.
136 while (aText < end && *aText == 0xFFFF)
138 TText* groupStart = aText;
141 TText* next = aText + 1;
143 if ((c & 0xFC00) == 0xD800)
145 ASSERT(aText + 1 < end);
146 ASSERT((aText[1] & 0xFC00) == 0xDC00);
147 c = (c << 10) + (aText[1] & 0x3FF)
148 + (0x10000 - 0xD800*0x400);
151 // ignore non-characters
152 if ((c & 0xFFFE) != 0xFFFE)
154 // non-marks represent the end of groups that may need to
157 if ((ch.GetCategory() & 0xFFFFFFF0) != TChar::EMarkGroup)
159 if (aText != groupStart)
160 ReverseCodes(groupStart, aText - groupStart + 1);
168 void BidiCopy::SubstituteMirrorImages(TText* aText, TInt aLength)
170 Reverse all mirror image characters. Will not change characters
171 in the basic multilingual plane for surrogate pairs. Assumes
172 that no unpaired surrogates are present.
176 TText *end = aText + aLength;
179 TText* next = aText + 1;
181 if ((c & 0xFC00) == 0xD800)
183 ASSERT(aText + 1 < end);
184 ASSERT((aText[1] & 0xFC00) == 0xDC00);
185 c = (c << 10) + (aText[1] & 0x3FF)
186 + (0x10000 - 0xD800*0x400);
194 aText[0] = static_cast<TText>(m);
200 aText[0] = static_cast<TText>((c >> 10) + 0xD760);
201 aText[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
208 TText* BidiCopy::CopyMirror(TText* aDestination, const TText* aSource, TInt length)
210 Copy some text, substituting mirrored characters.
212 @return aDestination + number of TText codes output.
216 for (; length; --length, ++aDestination, ++aSource)
217 *aDestination = static_cast<TText>(Mirror(*aSource));
221 TText* BidiCopy::OutputTChar(TText* aDestination, TInt aToOutput)
223 Write out the input character as UTF16.
225 @return aDestination + number of TText codes output.
229 if (aToOutput > 0xFFFF)
232 aDestination[0] = static_cast<TText>((c >> 10) + 0xD760);
233 aDestination[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
234 return aDestination + 2;
236 *aDestination = static_cast<TText>(aToOutput);
237 return aDestination + 1;
240 TText* BidiCopy::CopyBackwards(TText* aDestination,
241 const TText* aSource, TInt aLength)
243 Copy the text backwards without substituting mirrored characters,
244 checking for surrogate pairs or combining characters.
246 @return aDestination + number of TText codes output.
250 TText *end = aDestination + aLength;
251 while (aDestination != end)
255 return aDestination + aLength;
258 TText* BidiCopy::CopyBackwardsWithMirroring(TText* aDestination,
259 const TText* aSource, TInt aLength)
261 Copy the text backwards to the output without checking for surrogate
262 pairs or combining characters, substituting mirrored characters.
264 @return aDestination + number of TText codes output.
268 TText *end = aDestination + aLength;
269 while (aDestination != end)
271 *--end = static_cast<TText>(Mirror(*aSource++));
273 return aDestination + aLength;
276 TText* BidiCopy::CopyGroupsBackwards(TText* aDestination,
277 const TText* aSource, TInt aLength)
279 Copy the text backwards, substituting mirrored characters and correctly
280 handling all surrogate pairs and combining characters.
282 @return aDestination + number of TText codes output.
286 TText* retval = CopyBackwards(aDestination, aSource, aLength);
287 DeleteUnreversedSurrogates(aDestination, aLength);
288 SubstituteMirrorImages(aDestination, aLength);
289 CorrectGroups(aDestination, aLength);
290 CorrectSurrogatePairs(aDestination, aLength);
294 TBool BidiCopy::ImplicitDirectionalityIsRightToLeft(
295 const TText* aText, TInt aLength, TBool* aFound)
297 Find out if the implicit directionality of a piece of text is right to
300 @param aText Text to be examined, or the first portion of text to be examined.
301 @param aLength Length of the text.
302 @param aFound If non-null, returns ETrue if the directionality could be
303 determined from aText. If not, and there is more text beyond, the function
304 should be called with the next portion of text until aFound returns ETrue
305 or there is no more text.
306 @return ETrue if the directionality is right to left. If the directionality
307 cannot be determined solely from this text, EFalse is returned. This is the
308 implicit directionality of text that is composed entirely of neutrals.
314 const TText* end = aText + aLength;
318 TInt code = *aText++;
319 if ((code & 0xFFFFFC00) == 0xD800
320 && (lastUtf16 & 0xFFFFFC00) == 0xDC00)
322 code = (code << 10) + (lastUtf16 & 0x3FF)
323 + (0x10000 - 0xD800*0x400);
327 switch(c.GetBdCategory())
329 case TChar::ELeftToRight:
331 case TChar::ERightToLeft:
332 case TChar::ERightToLeftArabic: