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