os/graphics/graphicsdeviceinterface/gdi/sgdi/BidiCopy.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicsdeviceinterface/gdi/sgdi/BidiCopy.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,341 @@
     1.4 +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "BidiCopy.h"
    1.20 +#include <e32std.h>
    1.21 +#include "mglyphs.inl"
    1.22 +
    1.23 +TInt BidiCopy::Mirror(TInt a)
    1.24 +/**
    1.25 +Find the mirror image of a character.
    1.26 +@internalComponent
    1.27 +*/
    1.28 +	{
    1.29 +	TInt current = MirrorStart(a);
    1.30 +	unsigned long v = mGlyphArray[current];
    1.31 +	TInt key = v >> 16;
    1.32 +	// 1st easy-out: no steps at all for any at this key
    1.33 +	if (key == 0)
    1.34 +		return a;
    1.35 +	// 2nd easy-out: no steps at all but we have found it
    1.36 +	if (key == a)
    1.37 +		return v & 0xFFFF;
    1.38 +	TInt step = MirrorStep(a);
    1.39 +	do	{
    1.40 +		current += step;
    1.41 +		current &= (KMirrorTableSize-1);
    1.42 +		key = mGlyphArray[current] >> 16;
    1.43 +		if (key == a)
    1.44 +			return mGlyphArray[current] & 0xFFFF;
    1.45 +		} while (key != 0);
    1.46 +	return a;
    1.47 +	}
    1.48 +
    1.49 +void BidiCopy::ReverseCodes(TText* aText, TInt aLength)
    1.50 +/**
    1.51 +Reverse the contents of aText[0..aLength], so that aText[0] holds the
    1.52 +value previously found in aText[aLength - 1], aText[1] holds the value
    1.53 +previously held in aText[aLength - 2] and so on.
    1.54 +@internalComponent
    1.55 +*/
    1.56 +	{
    1.57 +	TText *text = aText;	// backup
    1.58 +
    1.59 +	// reverse int16 by int16 (note: high surrogate + low surrogate will be reverse to low surrogate + high surrogate)
    1.60 +	TText* end = aText + aLength - 1;
    1.61 +	while (aText < end)
    1.62 +		{
    1.63 +		TText t = *aText;
    1.64 +		*aText = *end;
    1.65 +		*end = t;
    1.66 +		++aText;
    1.67 +		--end;
    1.68 +		}
    1.69 +
    1.70 +	CorrectSurrogatePairs(text, aLength);
    1.71 +	}
    1.72 +
    1.73 +void BidiCopy::DeleteUnreversedSurrogates(TText* aText, TInt aLength)
    1.74 +/**
    1.75 +Replaces all surrogates with 0xFFFF that are not paired up the wrong
    1.76 +way round.
    1.77 +@internalComponent
    1.78 +*/
    1.79 +	{
    1.80 +	if (aLength < 1)
    1.81 +		return;
    1.82 +	TText* end = aText + aLength;
    1.83 +	while (aText < end)
    1.84 +		{
    1.85 +		if ((aText[0] & 0xF800) == 0xD800)
    1.86 +			{
    1.87 +			if ((aText[0] & 0xFC00) == 0xD800
    1.88 +				&& aText + 1 != end
    1.89 +				&& (aText[1] & 0xFC00) == 0xDC00)
    1.90 +				++aText;
    1.91 +			else
    1.92 +				aText[0] = 0xFFFF;
    1.93 +			}
    1.94 +		++aText;
    1.95 +		}
    1.96 +	}
    1.97 +
    1.98 +void BidiCopy::CorrectSurrogatePairs(TText* aText, TInt aLength)
    1.99 +/**
   1.100 +Corrects all reversed surrogate pairs. Assumes that no unpaired
   1.101 +surrogates are present.
   1.102 +@internalComponent
   1.103 +*/
   1.104 +	{
   1.105 +	TText* end = aText + aLength;
   1.106 +	while (aText < end)
   1.107 +		{
   1.108 +		if ((aText[0] & 0xF800) == 0xD800)
   1.109 +			{
   1.110 +			// Surrogate pair discovered.
   1.111 +			// Do we need to swap it?
   1.112 +			ASSERT(aText + 1 < end);
   1.113 +			ASSERT((aText[1] & 0xF800) == 0xD800);
   1.114 +			if ((aText[0] & 0xFC00) == 0xDC00)
   1.115 +				{
   1.116 +				ASSERT((aText[1] & 0xFC00) == 0xD800);
   1.117 +				TText t = aText[0];
   1.118 +				aText[0] = aText[1];
   1.119 +				aText[1] = t;
   1.120 +				}
   1.121 +			++aText;
   1.122 +			}
   1.123 +		++aText;
   1.124 +		}
   1.125 +	}
   1.126 +
   1.127 +void BidiCopy::CorrectGroups(TText* aText, TInt aLength)
   1.128 +/**
   1.129 +Correct all reversed groups (non-combiner followed by combining
   1.130 +characters). Surrogate pairs may be reversed by this operation.
   1.131 +Assumes that no unpaired surrogates are present.
   1.132 +Leading and trailing 0xFFFFs are left alone.
   1.133 +@internalComponent
   1.134 +*/
   1.135 +	{
   1.136 +	TText *end = aText + aLength;
   1.137 +	// Ignore leading 0xFFFFs. This helps Tagma's
   1.138 +	// RTmTextCache::GetDisplayedText with its sentinels.
   1.139 +	while (aText < end && *aText == 0xFFFF)
   1.140 +		++aText;
   1.141 +	TText* groupStart = aText;
   1.142 +	while (aText < end)
   1.143 +		{
   1.144 +		TText* next = aText + 1;
   1.145 +		TInt c = aText[0];
   1.146 +		if ((c & 0xFC00) == 0xD800)
   1.147 +			{
   1.148 +			ASSERT(aText + 1 < end);
   1.149 +			ASSERT((aText[1] & 0xFC00) == 0xDC00);
   1.150 +			c = (c << 10) + (aText[1] & 0x3FF)
   1.151 +				+ (0x10000 - 0xD800*0x400);
   1.152 +			++next;
   1.153 +			}
   1.154 +		// ignore non-characters
   1.155 +		if ((c & 0xFFFE) != 0xFFFE)
   1.156 +			{
   1.157 +			// non-marks represent the end of groups that may need to
   1.158 +			// be reversed
   1.159 +			TChar ch = c;
   1.160 +			if ((ch.GetCategory() & 0xFFFFFFF0) != TChar::EMarkGroup)
   1.161 +				{
   1.162 +				if (aText != groupStart)
   1.163 +					ReverseCodes(groupStart, aText - groupStart + 1);
   1.164 +				groupStart = next;
   1.165 +				}
   1.166 +			}
   1.167 +		aText = next;
   1.168 +		}
   1.169 +	}
   1.170 +
   1.171 +void BidiCopy::SubstituteMirrorImages(TText* aText, TInt aLength)
   1.172 +/**
   1.173 +Reverse all mirror image characters. Will not change characters
   1.174 +in the basic multilingual plane for surrogate pairs. Assumes
   1.175 +that no unpaired surrogates are present.
   1.176 +@internalComponent
   1.177 +*/
   1.178 +	{
   1.179 +	TText *end = aText + aLength;
   1.180 +	while (aText < end)
   1.181 +		{
   1.182 +		TText* next = aText + 1;
   1.183 +		TInt c = aText[0];
   1.184 +		if ((c & 0xFC00) == 0xD800)
   1.185 +			{
   1.186 +			ASSERT(aText + 1 < end);
   1.187 +			ASSERT((aText[1] & 0xFC00) == 0xDC00);
   1.188 +			c = (c << 10) + (aText[1] & 0x3FF)
   1.189 +				+ (0x10000 - 0xD800*0x400);
   1.190 +			++next;
   1.191 +			}
   1.192 +		TInt m = Mirror(c);
   1.193 +		if (m != c)
   1.194 +			{
   1.195 +			if (m <= 0xFFFF)
   1.196 +				{
   1.197 +				aText[0] = static_cast<TText>(m);
   1.198 +				if (0xFFFF < c)
   1.199 +					aText[1] = 0xFFFF;
   1.200 +				}
   1.201 +			else if (0xFFFF < c)
   1.202 +				{
   1.203 +				aText[0] = static_cast<TText>((c >> 10) + 0xD760);
   1.204 +				aText[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
   1.205 +				}
   1.206 +			}
   1.207 +		aText = next;
   1.208 +		}
   1.209 +	}
   1.210 +
   1.211 +TText* BidiCopy::CopyMirror(TText* aDestination, const TText* aSource, TInt length)
   1.212 +/**
   1.213 +Copy some text, substituting mirrored characters.
   1.214 +
   1.215 +@return aDestination + number of TText codes output.
   1.216 +@internalComponent
   1.217 +*/
   1.218 +	{
   1.219 +	for (; length; --length, ++aDestination, ++aSource)
   1.220 +		*aDestination = static_cast<TText>(Mirror(*aSource));
   1.221 +	return aDestination;
   1.222 +	}
   1.223 +
   1.224 +TText* BidiCopy::OutputTChar(TText* aDestination, TInt aToOutput)
   1.225 +/**
   1.226 +Write out the input character as UTF16.
   1.227 +
   1.228 +@return aDestination + number of TText codes output.
   1.229 +@internalComponent
   1.230 +*/
   1.231 +	{
   1.232 +	if (aToOutput > 0xFFFF)
   1.233 +		{
   1.234 +		TInt c = aToOutput;
   1.235 +		aDestination[0] = static_cast<TText>((c >> 10) + 0xD760);
   1.236 +		aDestination[1] = static_cast<TText>((c & 0x3FF) + 0xDC00);
   1.237 +		return aDestination + 2;
   1.238 +		}
   1.239 +	*aDestination = static_cast<TText>(aToOutput);
   1.240 +	return aDestination + 1;
   1.241 +	}
   1.242 +
   1.243 +TText* BidiCopy::CopyBackwards(TText* aDestination,
   1.244 +	const TText* aSource, TInt aLength)
   1.245 +/**
   1.246 +Copy the text backwards without substituting mirrored characters,
   1.247 +checking for surrogate pairs or combining characters.
   1.248 +
   1.249 +@return aDestination + number of TText codes output.
   1.250 +@internalComponent
   1.251 +*/
   1.252 +	{
   1.253 +	TText *end = aDestination + aLength;
   1.254 +	while (aDestination != end)
   1.255 +		{
   1.256 +		*--end = *aSource++;
   1.257 +		}
   1.258 +	return aDestination + aLength;
   1.259 +	}
   1.260 +
   1.261 +TText* BidiCopy::CopyBackwardsWithMirroring(TText* aDestination,
   1.262 +	const TText* aSource, TInt aLength)
   1.263 +/**
   1.264 +Copy the text backwards to the output without checking for surrogate
   1.265 +pairs or combining characters, substituting mirrored characters.
   1.266 +
   1.267 +@return aDestination + number of TText codes output.
   1.268 +@internalComponent
   1.269 +*/
   1.270 +	{
   1.271 +	TText *end = aDestination + aLength;
   1.272 +	while (aDestination != end)
   1.273 +		{
   1.274 +		*--end = static_cast<TText>(Mirror(*aSource++));
   1.275 +		}
   1.276 +	return aDestination + aLength;
   1.277 +	}
   1.278 +
   1.279 +TText* BidiCopy::CopyGroupsBackwards(TText* aDestination,
   1.280 +	const TText* aSource, TInt aLength)
   1.281 +/**
   1.282 +Copy the text backwards, substituting mirrored characters and correctly
   1.283 +handling all surrogate pairs and combining characters.
   1.284 +
   1.285 +@return aDestination + number of TText codes output.
   1.286 +@internalComponent
   1.287 +*/
   1.288 +	{
   1.289 +	TText* retval = CopyBackwards(aDestination, aSource, aLength);
   1.290 +	DeleteUnreversedSurrogates(aDestination, aLength);
   1.291 +	SubstituteMirrorImages(aDestination, aLength);
   1.292 +	CorrectGroups(aDestination, aLength);
   1.293 +	CorrectSurrogatePairs(aDestination, aLength);
   1.294 +	return retval;
   1.295 +	}
   1.296 +
   1.297 +TBool BidiCopy::ImplicitDirectionalityIsRightToLeft(
   1.298 +	const TText* aText, TInt aLength, TBool* aFound)
   1.299 +/**
   1.300 +Find out if the implicit directionality of a piece of text is right to
   1.301 +left.
   1.302 +
   1.303 +@param aText Text to be examined, or the first portion of text to be examined.
   1.304 +@param aLength Length of the text.
   1.305 +@param aFound If non-null, returns ETrue if the directionality could be
   1.306 +determined from aText. If not, and there is more text beyond, the function 
   1.307 +should be called with the next portion of text until aFound returns ETrue 
   1.308 +or there is no more text.
   1.309 +@return	ETrue if the directionality is right to left. If the directionality
   1.310 +cannot be determined solely from this text, EFalse is returned.	This is the 
   1.311 +implicit directionality of text that is composed entirely of neutrals.
   1.312 +@internalComponent
   1.313 +*/
   1.314 +	{
   1.315 +	if (aFound)
   1.316 +		*aFound = ETrue;
   1.317 +	const TText* end = aText + aLength;
   1.318 +	TInt lastUtf16 = 0;
   1.319 +	while (aText != end)
   1.320 +		{
   1.321 +		TInt code = *aText++;
   1.322 +		if ((code & 0xFFFFFC00) == 0xD800
   1.323 +			&& (lastUtf16 & 0xFFFFFC00) == 0xDC00)
   1.324 +			{
   1.325 +			code = (code << 10) + (lastUtf16 & 0x3FF)
   1.326 +				+ (0x10000 - 0xD800*0x400);
   1.327 +			}
   1.328 +		lastUtf16 = code;
   1.329 +		TChar c = code;
   1.330 +		switch(c.GetBdCategory())
   1.331 +			{
   1.332 +		case TChar::ELeftToRight:
   1.333 +			return EFalse;
   1.334 +		case TChar::ERightToLeft:
   1.335 +		case TChar::ERightToLeftArabic:
   1.336 +			return ETrue;
   1.337 +		default:
   1.338 +			break;
   1.339 +			}
   1.340 +		}
   1.341 +	if (aFound)
   1.342 +		*aFound = EFalse;
   1.343 +	return EFalse;
   1.344 +	}