--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/gdi/sgdi/BidiCopy.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,341 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "BidiCopy.h"
+#include <e32std.h>
+#include "mglyphs.inl"
+
+TInt BidiCopy::Mirror(TInt a)
+/**
+Find the mirror image of a character.
+@internalComponent
+*/
+ {
+ TInt current = MirrorStart(a);
+ unsigned long v = mGlyphArray[current];
+ TInt key = v >> 16;
+ // 1st easy-out: no steps at all for any at this key
+ if (key == 0)
+ return a;
+ // 2nd easy-out: no steps at all but we have found it
+ if (key == a)
+ return v & 0xFFFF;
+ TInt step = MirrorStep(a);
+ do {
+ current += step;
+ current &= (KMirrorTableSize-1);
+ key = mGlyphArray[current] >> 16;
+ if (key == a)
+ return mGlyphArray[current] & 0xFFFF;
+ } while (key != 0);
+ return a;
+ }
+
+void BidiCopy::ReverseCodes(TText* aText, TInt aLength)
+/**
+Reverse the contents of aText[0..aLength], so that aText[0] holds the
+value previously found in aText[aLength - 1], aText[1] holds the value
+previously held in aText[aLength - 2] and so on.
+@internalComponent
+*/
+ {
+ TText *text = aText; // backup
+
+ // reverse int16 by int16 (note: high surrogate + low surrogate will be reverse to low surrogate + high surrogate)
+ TText* end = aText + aLength - 1;
+ while (aText < end)
+ {
+ TText t = *aText;
+ *aText = *end;
+ *end = t;
+ ++aText;
+ --end;
+ }
+
+ CorrectSurrogatePairs(text, aLength);
+ }
+
+void BidiCopy::DeleteUnreversedSurrogates(TText* aText, TInt aLength)
+/**
+Replaces all surrogates with 0xFFFF that are not paired up the wrong
+way round.
+@internalComponent
+*/
+ {
+ if (aLength < 1)
+ return;
+ TText* end = aText + aLength;
+ while (aText < end)
+ {
+ if ((aText[0] & 0xF800) == 0xD800)
+ {
+ if ((aText[0] & 0xFC00) == 0xD800
+ && aText + 1 != end
+ && (aText[1] & 0xFC00) == 0xDC00)
+ ++aText;
+ else
+ aText[0] = 0xFFFF;
+ }
+ ++aText;
+ }
+ }
+
+void BidiCopy::CorrectSurrogatePairs(TText* aText, TInt aLength)
+/**
+Corrects all reversed surrogate pairs. Assumes that no unpaired
+surrogates are present.
+@internalComponent
+*/
+ {
+ TText* end = aText + aLength;
+ while (aText < end)
+ {
+ if ((aText[0] & 0xF800) == 0xD800)
+ {
+ // Surrogate pair discovered.
+ // Do we need to swap it?
+ ASSERT(aText + 1 < end);
+ ASSERT((aText[1] & 0xF800) == 0xD800);
+ if ((aText[0] & 0xFC00) == 0xDC00)
+ {
+ ASSERT((aText[1] & 0xFC00) == 0xD800);
+ TText t = aText[0];
+ aText[0] = aText[1];
+ aText[1] = t;
+ }
+ ++aText;
+ }
+ ++aText;
+ }
+ }
+
+void BidiCopy::CorrectGroups(TText* aText, TInt aLength)
+/**
+Correct all reversed groups (non-combiner followed by combining
+characters). Surrogate pairs may be reversed by this operation.
+Assumes that no unpaired surrogates are present.
+Leading and trailing 0xFFFFs are left alone.
+@internalComponent
+*/
+ {
+ TText *end = aText + aLength;
+ // Ignore leading 0xFFFFs. This helps Tagma's
+ // RTmTextCache::GetDisplayedText with its sentinels.
+ while (aText < end && *aText == 0xFFFF)
+ ++aText;
+ TText* groupStart = aText;
+ while (aText < end)
+ {
+ TText* next = aText + 1;
+ TInt c = aText[0];
+ if ((c & 0xFC00) == 0xD800)
+ {
+ ASSERT(aText + 1 < end);
+ ASSERT((aText[1] & 0xFC00) == 0xDC00);
+ c = (c << 10) + (aText[1] & 0x3FF)
+ + (0x10000 - 0xD800*0x400);
+ ++next;
+ }
+ // ignore non-characters
+ if ((c & 0xFFFE) != 0xFFFE)
+ {
+ // non-marks represent the end of groups that may need to
+ // be reversed
+ TChar ch = c;
+ if ((ch.GetCategory() & 0xFFFFFFF0) != TChar::EMarkGroup)
+ {
+ if (aText != groupStart)
+ ReverseCodes(groupStart, aText - groupStart + 1);
+ groupStart = next;
+ }
+ }
+ aText = next;
+ }
+ }
+
+void BidiCopy::SubstituteMirrorImages(TText* aText, TInt aLength)
+/**
+Reverse all mirror image characters. Will not change characters
+in the basic multilingual plane for surrogate pairs. Assumes
+that no unpaired surrogates are present.
+@internalComponent
+*/
+ {
+ TText *end = aText + aLength;
+ while (aText < end)
+ {
+ TText* next = aText + 1;
+ TInt c = aText[0];
+ if ((c & 0xFC00) == 0xD800)
+ {
+ ASSERT(aText + 1 < end);
+ ASSERT((aText[1] & 0xFC00) == 0xDC00);
+ c = (c << 10) + (aText[1] & 0x3FF)
+ + (0x10000 - 0xD800*0x400);
+ ++next;
+ }
+ TInt m = Mirror(c);
+ if (m != c)
+ {
+ if (m <= 0xFFFF)
+ {
+ aText[0] = static_cast<TText>(m);
+ if (0xFFFF < c)
+ aText[1] = 0xFFFF;
+ }
+ else if (0xFFFF < c)
+ {
+ aText[0] = static_cast<TText>((c >> 10) + 0xD760);
+ aText[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
+ }
+ }
+ aText = next;
+ }
+ }
+
+TText* BidiCopy::CopyMirror(TText* aDestination, const TText* aSource, TInt length)
+/**
+Copy some text, substituting mirrored characters.
+
+@return aDestination + number of TText codes output.
+@internalComponent
+*/
+ {
+ for (; length; --length, ++aDestination, ++aSource)
+ *aDestination = static_cast<TText>(Mirror(*aSource));
+ return aDestination;
+ }
+
+TText* BidiCopy::OutputTChar(TText* aDestination, TInt aToOutput)
+/**
+Write out the input character as UTF16.
+
+@return aDestination + number of TText codes output.
+@internalComponent
+*/
+ {
+ if (aToOutput > 0xFFFF)
+ {
+ TInt c = aToOutput;
+ aDestination[0] = static_cast<TText>((c >> 10) + 0xD760);
+ aDestination[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
+ return aDestination + 2;
+ }
+ *aDestination = static_cast<TText>(aToOutput);
+ return aDestination + 1;
+ }
+
+TText* BidiCopy::CopyBackwards(TText* aDestination,
+ const TText* aSource, TInt aLength)
+/**
+Copy the text backwards without substituting mirrored characters,
+checking for surrogate pairs or combining characters.
+
+@return aDestination + number of TText codes output.
+@internalComponent
+*/
+ {
+ TText *end = aDestination + aLength;
+ while (aDestination != end)
+ {
+ *--end = *aSource++;
+ }
+ return aDestination + aLength;
+ }
+
+TText* BidiCopy::CopyBackwardsWithMirroring(TText* aDestination,
+ const TText* aSource, TInt aLength)
+/**
+Copy the text backwards to the output without checking for surrogate
+pairs or combining characters, substituting mirrored characters.
+
+@return aDestination + number of TText codes output.
+@internalComponent
+*/
+ {
+ TText *end = aDestination + aLength;
+ while (aDestination != end)
+ {
+ *--end = static_cast<TText>(Mirror(*aSource++));
+ }
+ return aDestination + aLength;
+ }
+
+TText* BidiCopy::CopyGroupsBackwards(TText* aDestination,
+ const TText* aSource, TInt aLength)
+/**
+Copy the text backwards, substituting mirrored characters and correctly
+handling all surrogate pairs and combining characters.
+
+@return aDestination + number of TText codes output.
+@internalComponent
+*/
+ {
+ TText* retval = CopyBackwards(aDestination, aSource, aLength);
+ DeleteUnreversedSurrogates(aDestination, aLength);
+ SubstituteMirrorImages(aDestination, aLength);
+ CorrectGroups(aDestination, aLength);
+ CorrectSurrogatePairs(aDestination, aLength);
+ return retval;
+ }
+
+TBool BidiCopy::ImplicitDirectionalityIsRightToLeft(
+ const TText* aText, TInt aLength, TBool* aFound)
+/**
+Find out if the implicit directionality of a piece of text is right to
+left.
+
+@param aText Text to be examined, or the first portion of text to be examined.
+@param aLength Length of the text.
+@param aFound If non-null, returns ETrue if the directionality could be
+determined from aText. If not, and there is more text beyond, the function
+should be called with the next portion of text until aFound returns ETrue
+or there is no more text.
+@return ETrue if the directionality is right to left. If the directionality
+cannot be determined solely from this text, EFalse is returned. This is the
+implicit directionality of text that is composed entirely of neutrals.
+@internalComponent
+*/
+ {
+ if (aFound)
+ *aFound = ETrue;
+ const TText* end = aText + aLength;
+ TInt lastUtf16 = 0;
+ while (aText != end)
+ {
+ TInt code = *aText++;
+ if ((code & 0xFFFFFC00) == 0xD800
+ && (lastUtf16 & 0xFFFFFC00) == 0xDC00)
+ {
+ code = (code << 10) + (lastUtf16 & 0x3FF)
+ + (0x10000 - 0xD800*0x400);
+ }
+ lastUtf16 = code;
+ TChar c = code;
+ switch(c.GetBdCategory())
+ {
+ case TChar::ELeftToRight:
+ return EFalse;
+ case TChar::ERightToLeft:
+ case TChar::ERightToLeftArabic:
+ return ETrue;
+ default:
+ break;
+ }
+ }
+ if (aFound)
+ *aFound = EFalse;
+ return EFalse;
+ }