sl@0: /* sl@0: * Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Definitions for bidirectional text reordering. sl@0: * sl@0: * sl@0: */ sl@0: sl@0: sl@0: sl@0: #ifndef BIDI_H_ sl@0: #define BIDI_H_ sl@0: sl@0: #include sl@0: sl@0: class RWriteStream; sl@0: class RReadStream; sl@0: sl@0: sl@0: class TBidirectionalState sl@0: /** sl@0: The bidirectional state class. sl@0: This class contains functions that implement the Unicode Bidirectional Algorithm, sl@0: which changes text from logical order to display order for the correct display sl@0: of right-to-left scripts, like Arabic and Hebrew. A TBidirectionalState object sl@0: carries the embedding level and stack from one line to the next. On construction sl@0: it is in its 'start of paragraph' state. sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: { sl@0: friend class CTBiDi; sl@0: sl@0: public: sl@0: sl@0: class TRunInfo sl@0: /** sl@0: Information about a run of characters with the same bidirectional sl@0: category. sl@0: sl@0: An array of these representing a line is passed into, and reordered by, sl@0: ReorderLine(). sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: { sl@0: public: sl@0: /** Category of a run of text: passed to ReorderLine(); these are sl@0: passed in as TChar::TBdCategory values but are modified for internal sl@0: use. */ sl@0: TUint iCategory; sl@0: /** Embedding level of this run: used internally by ReorderLine(). */ sl@0: TUint8 iEmbeddingLevel; sl@0: /** Resolved direction of this run: 0 for left to right, 1 for right sl@0: to left. */ sl@0: TUint8 iDirection; sl@0: /** Index of this run after reordering. */ sl@0: TInt iIndex; sl@0: /** Start of text; returned by ReorderText(). */ sl@0: TInt iStart; sl@0: /** Length of text; returned by ReorderText(). */ sl@0: TInt iLength; sl@0: }; sl@0: sl@0: IMPORT_C TBidirectionalState(); sl@0: IMPORT_C void ReorderLine(TRunInfo* aRunInfo,TInt aRuns,TBool aParStart,TBool aParEnd,TBool aParRightToLeft, sl@0: TChar::TBdCategory aNextCategory,TChar::TBdCategory aNextStrongCategory, sl@0: TBool& aVisualEndIsAmbiguous); sl@0: IMPORT_C void ReorderLine(TRunInfo* aRunInfo,TInt aRuns,TBool aParStart,TBool aParEnd,TBool aParRightToLeft, sl@0: TChar::TBdCategory aNextCategory,TChar::TBdCategory aNextStrongCategory); sl@0: IMPORT_C static TInt ReorderText(const TText* aText,TInt aLength,TBool aParRightToLeft,TText*& aNewText); sl@0: IMPORT_C static void ReverseGroups(TText* aStart,TInt aLength); sl@0: IMPORT_C void Reset(); sl@0: IMPORT_C TBool IsDefault() const; sl@0: IMPORT_C TBool operator==(const TBidirectionalState& aState) const; sl@0: IMPORT_C void ExternalizeL(RWriteStream& aDest); sl@0: IMPORT_C void InternalizeL(RReadStream& aSource); sl@0: TBool ParRightToLeft() const { return iStack[0].iEmbeddingLevel & 1; } sl@0: sl@0: private: sl@0: // Bidirectional categories coded as bit flags sl@0: enum TCategory sl@0: { sl@0: ELeftToRight = 1 << TChar::ELeftToRight, sl@0: ELeftToRightEmbedding = 1 << TChar::ELeftToRightEmbedding, sl@0: ELeftToRightOverride = 1 << TChar::ELeftToRightOverride, sl@0: ERightToLeft = 1 << TChar::ERightToLeft, sl@0: ERightToLeftArabic = 1 << TChar::ERightToLeftArabic, sl@0: ERightToLeftEmbedding = 1 << TChar::ERightToLeftEmbedding, sl@0: ERightToLeftOverride = 1 << TChar::ERightToLeftOverride, sl@0: EPopDirectionalFormat = 1 << TChar::EPopDirectionalFormat, sl@0: EEuropeanNumber = 1 << TChar::EEuropeanNumber, sl@0: EEuropeanNumberSeparator = 1 << TChar::EEuropeanNumberSeparator, sl@0: EEuropeanNumberTerminator = 1 << TChar::EEuropeanNumberTerminator, sl@0: EArabicNumber = 1 << TChar::EArabicNumber, sl@0: ECommonNumberSeparator = 1 << TChar::ECommonNumberSeparator, sl@0: ENonSpacingMark = 1 << TChar::ENonSpacingMark, sl@0: EBoundaryNeutral = 1 << TChar::EBoundaryNeutral, sl@0: EParagraphSeparator = 1 << TChar::EParagraphSeparator, sl@0: ESegmentSeparator = 1 << TChar::ESegmentSeparator, sl@0: EWhitespace = 1 << TChar::EWhitespace, sl@0: EOtherNeutral = 1 << TChar::EOtherNeutral, sl@0: sl@0: // useful groups sl@0: EBdControlsGroup = ELeftToRightEmbedding | ERightToLeftEmbedding | sl@0: ELeftToRightOverride | ERightToLeftOverride | EPopDirectionalFormat, sl@0: ELeftToRightGroup = ELeftToRight | EEuropeanNumber | ELeftToRightOverride | ELeftToRightEmbedding, sl@0: ERightToLeftGroup = ERightToLeft | EArabicNumber | ERightToLeftArabic | ERightToLeftOverride | sl@0: ERightToLeftEmbedding, sl@0: EStrongGroup = ELeftToRightEmbedding | ERightToLeftEmbedding sl@0: | ELeftToRightOverride | ERightToLeftOverride sl@0: | ELeftToRight | ERightToLeft | ERightToLeftArabic, sl@0: sl@0: ENoCategory = 0 sl@0: }; sl@0: sl@0: enum sl@0: { sl@0: EMaxExplicitLevel = 61, sl@0: EMaxLevel = 63, sl@0: EMaxStackLevels = 62 sl@0: }; sl@0: sl@0: enum TOverrideState sl@0: { sl@0: ENoOverrideState = 0, sl@0: ELeftToRightOverrideState = ELeftToRightOverride, sl@0: ERightToLeftOverrideState = ERightToLeftOverride sl@0: }; sl@0: sl@0: class TStackItem sl@0: { sl@0: public: sl@0: TUint8 iEmbeddingLevel; // embedding level sl@0: TOverrideState iOverrideState; // directional override state sl@0: TCategory iStartCategory; // category that started this level; EOtherNeutral if none sl@0: }; sl@0: sl@0: private: sl@0: /** The information needed during line reordering. sl@0: WARNING: Class for internal use ONLY. Compatibility is not guaranteed in future releases. sl@0: */ sl@0: class TReorderContext sl@0: { sl@0: public: sl@0: void SetNextCategory(TChar::TBdCategory aCat); sl@0: void SetNextStrongCategory(TChar::TBdCategory aCat); sl@0: public: sl@0: /** Category at start of next line, or ON if at the end of the sl@0: paragraph. */ sl@0: TCategory iNextCategory; sl@0: /** Which of L, R or AL appears first in the remainder of the sl@0: paragraph, or ON if none. */ sl@0: TCategory iNextStrongCategory; sl@0: /** The run array for this line. */ sl@0: TRunInfo* iRunInfo; sl@0: /** The length of iRunInfo. */ sl@0: TInt iRuns; sl@0: /** Bitmap of categories currently present in iRunInfo. */ sl@0: TUint32 iCategories; sl@0: /** Found by the algorithm to set iPreviousStrongCategory. */ sl@0: TCategory iLastStrongCategory; sl@0: }; sl@0: sl@0: public: sl@0: static TInt GenerateBdRunArray(const TText* aText, TInt aLength, sl@0: TBidirectionalState::TRunInfo* aRun, TInt aMaxRuns); sl@0: sl@0: private: sl@0: const TStackItem& State() const { return iStack[iStackLevel]; } sl@0: TCategory Push(TCategory aStartCategory); sl@0: TCategory Pop(); sl@0: sl@0: public: sl@0: TBidirectionalState(TChar::TBdCategory aPrevCat, sl@0: TChar::TBdCategory aPrevStrongCat, TBool aParRightToLeft); sl@0: void HandleBdControls(TReorderContext& aContext); sl@0: void ResolveWeakTypesW1W2W3(TReorderContext& aContext); sl@0: void ResolveWeakTypesW4W5W6(TReorderContext& aContext); sl@0: void ResolveWeakTypesW7(TReorderContext& aContext); sl@0: void ResolveNeutralTypes(TReorderContext& aContext); sl@0: void ResolveImplicitLevels(TReorderContext& aContext); sl@0: void PrepareForNextLine(const TReorderContext& aContext); sl@0: void ReorderRuns(TReorderContext& aContext); sl@0: static TInt CatToNumber(TInt aCat); sl@0: static TCategory CharToBdCat(TChar::TBdCategory aCat); sl@0: static TCategory UintToBdCat(TUint aCat); sl@0: static void DeneutralizeRuns(TRunInfo* aStart, TRunInfo* aEnd, sl@0: TCategory aStartCategory, TCategory aEndCategory); sl@0: private: sl@0: TCategory iPreviousCategory; // category at end of last line, or EStartOfParagraph if at start of par sl@0: TCategory iPreviousStrongCategory; // L or R; derived from embedding level if at start of par sl@0: TInt16 iStackLevel; // current stack level sl@0: TInt8 iPushesBeyond60; // number of times Push called with iStackLevel == 60 and Left-To-Right category sl@0: TInt8 iPushesBeyond61; // number of times Push called with iStackLevel == 61 sl@0: TStackItem iStack[EMaxStackLevels]; // the stack of embedding levels sl@0: }; sl@0: sl@0: #endif // BIDI_H_