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 + }