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.
16 #include "BidiCompact.h"
20 static const TInt KZeroWidthJoiner = 0x200D;
21 // This gets round the compiler warning about converting
22 // EFRightToLeft to unsigned long.
23 inline TUint FRightToLeft() { return static_cast<TUint>(TRunInfoCompact::EFRightToLeft); }
26 Constructs a run description without considering optimisations based
28 @param aStart Index of the start of the run.
29 @param aLength Length of the run.
30 @param aReverse ETrue if the run is right-to-left.
33 TRunInfoCompact::TRunInfoCompact(TInt aStart, TInt aLength,
35 : iStart(aStart), iLengthAndType(aLength)
38 iLengthAndType |= FRightToLeft();
42 Constructs a run description.
44 @param aStart Index of the start of the run.
45 @param aLength Length of the run.
46 @param aReverse ETrue if the run is right-to-left.
47 @param aText The text that this run refers to (starting at index 0, not
48 the start of the run). This is required only to determine if optimisations
49 to the re-ordering are possible.
52 TRunInfoCompact::TRunInfoCompact(TInt aStart, TInt aLength,
53 TBool aReverse, const TText* aText)
54 : iStart(aStart), iLengthAndType(aLength)
57 ASSERT(aLength < 0x10000000);
61 iLengthAndType |= FRightToLeft();
62 TUint32 flags = EFNoPairsNoCombiners | EFNoMirroredCharacters;
65 for (const TText* end = aText + aLength; aText < end && flags; ++aText)
68 if ((code & 0xF800) == 0xD800)
70 flags &= ~EFNoPairsNoCombiners;
71 if ((code & 0xFC00) == 0xDC00
73 && (aText[1] & 0xFC00) == 0xD800)
75 code = (aText[1] << 10) + (code & 0x3FF)
76 + (0x10000 - 0xD800*0x400);
81 if (c.GetCombiningClass() != 0)
82 flags &= ~EFNoPairsNoCombiners;
83 if (BidiCopy::Mirror(code) != code)
84 flags &= ~EFNoMirroredCharacters;
86 iLengthAndType |= flags;
90 Attempts to extend a run.
92 @param aToBeAdded The run to be merged.
93 @return ETrue if extension succeeded, EFalse if not.
96 TBool TRunInfoCompact::AddRun(const TRunInfoCompact& aToBeAdded)
98 TInt length = Length();
105 // Are both runs in the same direction?
106 if ((iLengthAndType ^ aToBeAdded.iLengthAndType) & FRightToLeft())
109 TBool rightToLeft = TypeFlags() & EFRightToLeft;
110 TInt end = rightToLeft?
111 Start() - Length() : Start() + Length();
113 if (end != aToBeAdded.Start())
116 length += aToBeAdded.Length();
118 iLengthAndType = length | (TypeFlags() & aToBeAdded.TypeFlags());
121 iStart -= aToBeAdded.Length();
127 Reorders text described by this run according to aContext. Allow 6 extra
128 bytes for a truncation.
129 @param aDestination Where to write this run of visually-ordered text to.
130 @param aContext The source of the text to be ordered.
131 @return The first byte not written to: in other words, what aDestination
132 should be updated to.
135 TText* TRunInfoCompact::Reorder(TText* aDestination,
136 const TRunInfoCompact::TReorderingContext& aContext) const
138 TInt start = Start();
139 if (aContext.iEnd < start)
142 TInt end = Start() + Length();
143 if (end <= aContext.iStart)
146 TBool startJoins = EFalse;
147 if (start <= aContext.iStart)
149 start = aContext.iStart;
150 startJoins = aContext.iJoinsAtStart;
152 TBool truncated = EFalse;
153 TBool endJoins = EFalse;
154 if (aContext.iEnd <= end)
156 if (aContext.iEnd < end
157 && aContext.iTruncation != 0xFFFF)
160 endJoins = aContext.iJoinsAtEnd;
162 TInt length = end - start;
163 if (length == 0 && !truncated)
166 const TText* source = aContext.iSource + start;
167 if (TypeFlags() & FRightToLeft())
171 aDestination = BidiCopy::OutputTChar(aDestination, aContext.iTruncation);
173 *(aDestination++) = KZeroWidthJoiner;
174 if (TypeFlags() & EFNoPairsNoCombiners)
177 aDestination = TypeFlags() & EFNoMirroredCharacters?
178 BidiCopy::CopyBackwards(aDestination, source, length)
179 : BidiCopy::CopyBackwardsWithMirroring(aDestination, source, length);
183 aDestination = BidiCopy::CopyGroupsBackwards(aDestination, source, length);
185 *aDestination++ = KZeroWidthJoiner;
190 *aDestination++ = KZeroWidthJoiner;
191 Mem::Copy(aDestination, source, length * sizeof(TText));
192 aDestination += length;
194 *aDestination++ = KZeroWidthJoiner;
196 aDestination = BidiCopy::OutputTChar(aDestination, aContext.iTruncation);
201 Converts an array of aArraySize TBidirectionalState::TRunInfos into a
204 @param aBuffer Memory to output to, or null just to find out how large the output
205 array will need to be.
206 @param aText The text that aRunArray refers to.
207 @param aRunArray The array to be converted.
208 @param aArraySize The length of aRunArray.
209 @return The length of the output array.
212 TInt TRunInfoCompact::Convert(TRunInfoCompact* aBuffer, const TDesC& aText,
213 const TBidirectionalState::TRunInfo* aRunArray, TInt aArraySize)
215 const TText* text = aText.Ptr();
218 TRunInfoCompact currentRun;
221 TRunInfoCompact newRun(aRunArray->iStart, aRunArray->iLength,
222 aRunArray->iDirection, text);
224 if (!currentRun.AddRun(newRun))
227 *aBuffer++ = currentRun;
231 ++aRunArray; //point to next run
233 if (0 < currentRun.Length())
236 *aBuffer++ = currentRun;
244 Utility tells whether a character will form a join with the previous
247 @param aText The text.
248 @param aIndex The index into aText of the character to test.
249 @return ETrue if there is a join before the character.
251 TBool TRunInfoCompact::JoinBefore(const TText* aText, TInt aIndex)
253 TInt charUnderTest = aText[aIndex];
254 if (!CFont::CharactersJoin(charUnderTest, KZeroWidthJoiner))
255 // Character does not join with anything, so we
256 // will not do any more work.
261 TInt c = aText[aIndex];
262 // If it is an Arabic point, we will skip it.
263 if (0x64B <= c && c < 0x671
264 && !(0x656 <= c && c < 0x670))
266 return CFont::CharactersJoin(charUnderTest, c);