diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/gdi/sgdi/LinebreakComplex.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicsdeviceinterface/gdi/sgdi/LinebreakComplex.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,388 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + + +#include +#include +#include "LineBreak.h" +#include "LineBreakImp.h" +#include "GlyphSel.h" + +const TText16 KThaiCodePageStart = 0x0E00; +const TText16 KThaiCodePageEnd = 0x0E5C; +const TUint KNumThaiCharacters = KThaiCodePageEnd - KThaiCodePageStart; + +/** + Ecanpsulates rules for when Thai character sequence line breaking. +@internalComponent +*/ +class ThaiLinebreakRules + { +public: + enum TCharClassification + { + EOutOfRange, + + EConsOAng, + EConsYoYak, + EConsHoHip, + EConsWoWean, + EConsDigraph, + EConsOther, + + EPostVowelA, + EPostVowelAA, + EPostVowelOther, + EPreVowel, + + EDepMaiHanAkat, + EDepSaraI, + EDepOther, + + // marker for end + EMaxClassification + }; + enum + { + KOutOfRangeFlag = 1 << EOutOfRange, + KConsOAngFlag = 1 << EConsOAng, + KConsYoYakFlag = 1 << EConsYoYak, + KConsHoHipFlag = 1 << EConsHoHip, + KConsWoWeanFlag = 1 << EConsWoWean, + KConsDigraphFlag = 1 << EConsDigraph, + KConsOtherFlag = 1 << EConsOther, + KPostVowelAFlag = 1 << EPostVowelA, + KPostVowelAAFlag = 1 << EPostVowelAA, + KPostVowelOtherFlag = 1 << EPostVowelOther, + KPreVowelFlag = 1 << EPreVowel, + KDepMaiHanAkatFlag = 1 << EDepMaiHanAkat, + KDepSaraIFlag = 1 << EDepSaraI, + KDepOtherFlag = 1 << EDepOther, + + KSpecialDepFlags = KDepMaiHanAkatFlag | KDepSaraIFlag, + KPostVowelFlags = KPostVowelAFlag | KPostVowelAAFlag | KPostVowelOtherFlag, + KConsFlags = KConsOtherFlag | KConsDigraphFlag | KConsWoWeanFlag + | KConsHoHipFlag | KConsYoYakFlag | KConsOAngFlag, + KAllFlags = KOutOfRangeFlag | KConsOAngFlag | KConsYoYakFlag + | KConsHoHipFlag | KConsWoWeanFlag | KConsDigraphFlag + | KConsOtherFlag | KPostVowelAFlag | KPostVowelAAFlag + | KPostVowelOtherFlag | KPreVowelFlag | KDepMaiHanAkatFlag + | KDepSaraIFlag | KDepOtherFlag + }; + + /** Returns the Thai linebreaking class of the character. */ + static TCharClassification Class(TInt aChar); + /** Returns true if aChar is a combining character according to aBreaker. */ + static TBool IsCombiningChar(TInt aChar, const MLineBreaker& aBreaker); + /** Returns the Thai linebreaking class of the character at (*aChar), + searching backwards for the base character if it is foreign and of type CM. + @param aChar The position of the character within the string. + @param aStart The start of the string. + @param aBreaker The line breaker to query for line breaking class. + */ + static TCharClassification DerivedClass(const TText* aChar, + const TText* aStart, const MLineBreaker& aBreaker); + /** + Gets the line break rule for the previous and current character pair + @param aPrevClass Class of the previous character. + @param aClass Class of the current character. + @return the rule code corresponding to the input pair. + */ + static TBool BreakAllowedBetween( + TCharClassification aPrevClass, TCharClassification aClass); + /** Returns whether a line break is allowed before the SA character at + (*aChar). + @param aChar The position of the character within the string. + @param aStart The start of the string. + @param aBreaker The line breaker to query for line breaking class. + */ + static TBool BreakAllowedAt(const TText* aChar, + const TText* aStart, const MLineBreaker& aBreaker); + + /** + Classification of each character + */ + static const TUint8 KCharClassifications[KNumThaiCharacters]; + + /** + Rules table of prev to next character + */ + static const TUint32 KRules[EMaxClassification]; + }; + +const TUint8 ThaiLinebreakRules::KCharClassifications[KNumThaiCharacters] = + { + EOutOfRange, // 0x0E00 + EConsOther, // 0x0E01 + EConsOther, // 0x0E02 + EConsOther, // 0x0E03 + EConsOther, // 0x0E04 + EConsOther, // 0x0E05 + EConsOther, // 0x0E06 + EConsDigraph, // 0x0E07 + EConsOther, // 0x0E08 + EConsOther, // 0x0E09 + EConsOther, // 0x0E0A + EConsOther, // 0x0E0B + EConsOther, // 0x0E0C + EConsOther, // 0x0E0D + EConsOther, // 0x0E0E + EConsOther, // 0x0E0F + + EConsOther, // 0x0E10 + EConsOther, // 0x0E11 + EConsOther, // 0x0E12 + EConsOther, // 0x0E13 + EConsOther, // 0x0E14 + EConsOther, // 0x0E15 + EConsOther, // 0x0E16 + EConsOther, // 0x0E17 + EConsOther, // 0x0E18 + EConsDigraph, // 0x0E19 + EConsOther, // 0x0E1A + EConsOther, // 0x0E1B + EConsOther, // 0x0E1C + EConsOther, // 0x0E1D + EConsOther, // 0x0E1E + EConsOther, // 0x0E1F + + EConsOther, // 0x0E20 + EConsDigraph, // 0x0E21 + EConsYoYak, // 0x0E22 + EConsDigraph, // 0x0E23 + EConsOther, // 0x0E24 + EConsDigraph, // 0x0E25 + EConsOther, // 0x0E26 + EConsWoWean, // 0x0E27 + EConsOther, // 0x0E28 + EConsOther, // 0x0E29 + EConsOther, // 0x0E2A + EConsHoHip, // 0x0E2B + EConsOther, // 0x0E2C + EConsOAng, // 0x0E2D + EConsOther, // 0x0E2E + EOutOfRange, // 0x0E2F + + EPostVowelA, // 0x0E30 + EDepMaiHanAkat, // 0x0E31 + EPostVowelAA, // 0x0E32 + EPostVowelOther,// 0x0E33 + + EDepSaraI, // 0x0E34 + EDepOther, // 0x0E35 + EDepOther, // 0x0E36 + EDepOther, // 0x0E37 + EDepOther, // 0x0E38 + EDepOther, // 0x0E39 + EDepOther, // 0x0E3A + + EOutOfRange, // 0x0E3B + EOutOfRange, // 0x0E3C + EOutOfRange, // 0x0E3D + EOutOfRange, // 0x0E3E + EOutOfRange, // 0x0E3F + + EPreVowel, // 0x0E40 + EPreVowel, // 0x0E41 + EPreVowel, // 0x0E42 + EPreVowel, // 0x0E43 + EPreVowel, // 0x0E44 + + EPostVowelOther,// 0x0E45 + EOutOfRange, // 0x0E46 + + EDepOther, // 0x0E47 + EDepOther, // 0x0E48 + EDepOther, // 0x0E49 + EDepOther, // 0x0E4A + EDepOther, // 0x0E4B + EDepOther, // 0x0E4C + EDepOther, // 0x0E4D + EDepOther, // 0x0E4E + EOutOfRange, // 0x0E4F + + EOutOfRange, // 0x0E50 + EOutOfRange, // 0x0E51 + EOutOfRange, // 0x0E52 + EOutOfRange, // 0x0E53 + EOutOfRange, // 0x0E54 + EOutOfRange, // 0x0E55 + EOutOfRange, // 0x0E56 + EOutOfRange, // 0x0E57 + EOutOfRange, // 0x0E58 + EOutOfRange, // 0x0E59 + EOutOfRange, // 0x0E5A + EOutOfRange // 0x0E5B + }; + +const TUint32 KNormalBreaksBeforeCons = + ThaiLinebreakRules::KPreVowelFlag + | ThaiLinebreakRules::KConsOtherFlag + | ThaiLinebreakRules::KConsDigraphFlag + | ThaiLinebreakRules::KConsHoHipFlag + | ThaiLinebreakRules::KOutOfRangeFlag; +const TUint32 KNormalBreaksBeforePostVowel = + ThaiLinebreakRules::KPreVowelFlag + | ThaiLinebreakRules::KPostVowelFlags + | ThaiLinebreakRules::KConsFlags + | ThaiLinebreakRules::KOutOfRangeFlag; +const TUint32 ThaiLinebreakRules::KRules[EMaxClassification] = + { + /* Prev Char EOutOfRange */ + KAllFlags - KOutOfRangeFlag, + /* Prev Char EConsOAng */ + KNormalBreaksBeforeCons, + /* Prev Char EConsYoYak */ + KNormalBreaksBeforeCons, + /* Prev Char EConsHoHip */ + KNormalBreaksBeforeCons - KConsDigraphFlag, + /* Prev Char EConsWoWean */ + KNormalBreaksBeforeCons - KConsDigraphFlag - KConsHoHipFlag, + /* Prev Char EConsDigraph */ + KNormalBreaksBeforeCons, + /* Prev Char EConsOther */ + KNormalBreaksBeforeCons, + /* Prev Char EPostVowelA */ + KNormalBreaksBeforePostVowel, + /* Prev Char EPostVowelAA */ + KNormalBreaksBeforePostVowel - KPostVowelAFlag, + /* Prev Char EPostVowelOther */ + KNormalBreaksBeforePostVowel, + /* Prev Char EPreVowel */ + KPreVowelFlag | KPostVowelFlags | KOutOfRangeFlag, + /* Prev Char EDepMaiHanAkat */ + KSpecialDepFlags | KPreVowelFlag | KPostVowelAAFlag + | KPostVowelAFlag | KOutOfRangeFlag, + /* Prev Char EDepSaraI */ + KSpecialDepFlags | KPreVowelFlag | KPostVowelAAFlag + | KPostVowelAFlag | KOutOfRangeFlag, + /* Prev Char EDepOther */ + KSpecialDepFlags | KPreVowelFlag | KPostVowelAAFlag + | KPostVowelAFlag | KConsOtherFlag | KConsDigraphFlag + | KConsWoWeanFlag | KConsHoHipFlag | KOutOfRangeFlag + }; + +ThaiLinebreakRules::TCharClassification ThaiLinebreakRules::Class(TInt a) + { + return static_cast( + (KThaiCodePageStart <= a && a < KThaiCodePageEnd) ? + KCharClassifications[a - KThaiCodePageStart] : + EOutOfRange); + } + +TBool ThaiLinebreakRules::IsCombiningChar(TInt aChar, + const MLineBreaker& aBreaker) + { + TUint dummy1, dummy2; + return aBreaker.LineBreakClass(aChar, dummy1, dummy2) == MLineBreaker::ECmLineBreakClass; + } + +ThaiLinebreakRules::TCharClassification ThaiLinebreakRules::DerivedClass( + const TText* aChar, const TText* aStart, const MLineBreaker& aBreaker) + { + ThaiLinebreakRules::TCharClassification c = Class(*aChar); + while (c == EOutOfRange && aChar != aStart + && IsCombiningChar(*aChar, aBreaker)) + { + --aChar; + c = Class(*aChar); + } + return c; + } + +TBool ThaiLinebreakRules::BreakAllowedBetween( + ThaiLinebreakRules::TCharClassification aClass, + ThaiLinebreakRules::TCharClassification aNextClass) + { + return KRules[aClass] & (1 << aNextClass); + } + +TBool ThaiLinebreakRules::BreakAllowedAt(const TText* aChar, + const TText* aStart, const MLineBreaker& aBreaker) + { + __ASSERT_DEBUG(aStart < aChar, User::Invariant()); + TCharClassification c = Class(*aChar); + if (c == EOutOfRange && IsCombiningChar(*aChar, aBreaker)) + return EFalse; + return BreakAllowedBetween(DerivedClass(aChar - 1, aStart, aBreaker), c); + } + +/** + Returns whether a line break is possible within a run of characters all having + the class ESaLineBreakClass (Complex content). Languages with Unicocde + characters having such a class include: Thai, Lao, Myanmar and Khmer. This + default implementation of the GetLineBreakInContext() method only supports the + Thai script. Breaks are determined in Thai based on a simple understanding of + syllable boundaries. When characters from the other unsupported Sa class + languages are found the method exits with EFalse. +@param aText + The text to be searched, which is a contiguous run of characters of class SA + (or CM attatched to SA). The break position may be restricted further by + aMinBreakPos and aMaxBreakPos, but more text is provided for extra context + should it be needed. +@param aMinBreakPos + The start of the text to be considered for line breaks. +@param aMaxBreakPos + The end of the text to be considered for line breaks. +@param aForwards + ETrue if aBreakPos is to be set with the first legal break position, + EFalse if aBreakPos is to be set with the last legal break position. +@param aBreakPos + If break position found on exit its value is >= Min and <= Max + positions supplied. +@return TBool + ETrue if and only if a legal break was found, EFalse otherwise. +@publishedAll +@released +*/ +EXPORT_C TBool MLineBreaker::GetLineBreakInContext(const TDesC16& aText, + TInt aMinBreakPos, TInt aMaxBreakPos, TBool aForwards, + TInt& aBreakPos) const + { + __ASSERT_DEBUG (0 <= aMinBreakPos && aMaxBreakPos <= aText.Length(), + Panic(ELineBreakPanic_InvalidInputParam)); + + TInt length = aText.Length(); + + if (aMinBreakPos < 1) + aMinBreakPos = 1; + if (length - 1 < aMaxBreakPos) + aMaxBreakPos = length - 1; + if (aMaxBreakPos < aMinBreakPos) + return EFalse; + + const TText16* text = aText.Ptr(); + + if (*text == KZeroWidthSpace) + { + aBreakPos = aMinBreakPos; + return ETrue; + } + else if (*(text+length-1) == KZeroWidthSpace) + return EFalse; + + TInt start = aForwards? aMinBreakPos : aMaxBreakPos; + TInt end = aForwards? aMaxBreakPos + 1 : aMinBreakPos - 1; + TInt direction = aForwards? 1 : -1; + for (TInt i = start; i != end; i += direction) + { + if (ThaiLinebreakRules::BreakAllowedAt(text + i, text, *this)) + { + aBreakPos = i; + return ETrue; + } + } + return EFalse; + }