diff -r 000000000000 -r 1fb32624e06b textrendering/texthandling/stext/TXTFMSTM.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/textrendering/texthandling/stext/TXTFMSTM.CPP Tue Feb 02 02:02:46 2010 +0200 @@ -0,0 +1,1838 @@ +/* +* Copyright (c) 1997-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 +#include "TXTFRMAT.H" +#include + +#include "TXTSTD.H" + +const TInt KMaxFormatStreamLength=0x400; // 1024 bytes + +// Standard attributes +const TUint KFontProportional=0x01; +const TUint KFontSerif=0x02; +const TUint KFontSymbol=0x04; + +const TUint KTypefaceFlags=sizeof(TUint8); +const TInt KTypeSize=sizeof(TUint8); +const TInt KColor=sizeof(TUint8)+sizeof(TUint8)+sizeof(TUint8); +const TInt KFontHeight=sizeof(TInt32); +const TInt KParaBorderThickness=sizeof(TInt32); +const TInt KTabPosition=sizeof(TUint32); +const TInt KTabType=sizeof(TUint8); + +// Paragraph format attributes +const TInt KVariableLengthAttribute=0; +const TInt KParaLanguage=sizeof(TUint8); +const TInt KParaFillColor=KColor; +const TInt KParaLeftMargin=sizeof(TInt32); +const TInt KParaRightMargin=sizeof(TInt32); +const TInt KParaIndent=sizeof(TInt32); +const TInt KParaAlignment=sizeof(TUint8); +const TInt KParaVerticalAlignment=sizeof(TUint8); +const TInt KParaLineSpacing=sizeof(TInt32); +const TInt KParaLineSpacingControl=sizeof(TUint8); +const TInt KParaSpaceBefore=sizeof(TInt32); +const TInt KParaSpaceAfter=sizeof(TInt32); +const TInt KParaKeepTogether=sizeof(TUint8); +const TInt KParaKeepWithNext=sizeof(TUint8); +const TInt KParaStartNewPage=sizeof(TUint8); +const TInt KParaWidowOrphan=sizeof(TUint8); +const TInt KParaWrap=sizeof(TUint8); +const TInt KParaBorderMargin=sizeof(TInt32); +const TInt KParaTopBorder=sizeof(TUint8)+KParaBorderThickness+KColor+sizeof(TUint8);//linestyle/thickness/color/autocolor +const TInt KParaBottomBorder=KParaTopBorder; +const TInt KParaLeftBorder=KParaTopBorder; +const TInt KParaRightBorder=KParaTopBorder; +const TInt KParaBullet=KVariableLengthAttribute; +const TInt KParaDefaultTabWidth=sizeof(TUint32); +const TInt KParaTabStop=KTabPosition+KTabType; +const TInt KParaFillSystemColor=sizeof(TUint8); +const TInt KParaBulletSystemColor=sizeof(TUint8); +const TInt KParaTopBorderSystemColor=sizeof(TUint8); +const TInt KParaBottomBorderSystemColor=sizeof(TUint8); +const TInt KParaLeftBorderSystemColor=sizeof(TUint8); +const TInt KParaRightBorderSystemColor=sizeof(TUint8); +const TInt KParaLanguageX=sizeof(TInt32); +const TInt KParaBulletX=sizeof(TInt32) + 2; +const TInt KBitmapType=sizeof(TUint8); + +// Character format attributes +const TInt KCharLanguage=sizeof(TUint8); +const TInt KCharColor=KColor; +const TInt KCharHighlightColor=KColor; +const TInt KCharHighlightStyle=sizeof(TUint8); +const TInt KCharStrikethrough=sizeof(TUint8); +const TInt KCharUnderline=sizeof(TUint8); +const TInt KCharStrokeWeight=sizeof(TUint8); +const TInt KCharPosture=sizeof(TUint8); +const TInt KCharPrintPos=sizeof(TUint8); +const TInt KCharFontHeight=KFontHeight; +const TInt KCharTypeface=KVariableLengthAttribute; +const TInt KCharHiddenText=sizeof(TUint8); +const TInt KCharPictureAlignment=sizeof(TUint8); +const TInt KCharTextSystemColor=sizeof(TUint8); +const TInt KCharFontHighlightSystemColor=sizeof(TUint8); +const TInt KCharLanguageX=sizeof(TInt32); +const TInt KCharParserTag=sizeof(TUint32); + +/* +Lookup table indexed by TTextFormatAttribute enumerated constants. +Specifies the length in bytes of the format attributes. +*/ +static const TInt8 TheAttributeLength[EAttributeCount] = + { + // Paragraph attribute value lengths. + KParaLanguage, + KParaFillColor, + KParaLeftMargin, + KParaRightMargin, + KParaIndent, + KParaAlignment, + KParaVerticalAlignment, + KParaLineSpacing, + KParaLineSpacingControl, + KParaSpaceBefore, + KParaSpaceAfter, + KParaKeepTogether, + KParaKeepWithNext, + KParaStartNewPage, + KParaWidowOrphan, + KParaWrap, + KParaBorderMargin, + KParaTopBorder, + KParaBottomBorder, + KParaLeftBorder, + KParaRightBorder, + KParaBullet, + KParaDefaultTabWidth, + KParaTabStop, + + // Character attribute value lengths. + KCharLanguage, + KCharColor, + KCharHighlightColor, + KCharHighlightStyle, + KCharFontHeight, + KCharStrikethrough, + KCharUnderline, + KCharStrokeWeight, + KCharPosture, + KCharPrintPos, + KCharTypeface, + KCharHiddenText, + KCharPictureAlignment, + + // Lengths of extended attributes. + KParaFillSystemColor, + KParaBulletSystemColor, + KParaTopBorderSystemColor, + KParaBottomBorderSystemColor, + KParaLeftBorderSystemColor, + KParaRightBorderSystemColor, + KCharTextSystemColor, + KCharFontHighlightSystemColor, + KParaLanguageX, + KCharLanguageX, + KParaBulletX, + KBitmapType, + + // Lengths of internal attributes + KCharParserTag + }; + + +DLLEXPORT_C void RFormatStream::__DbgTestInvariant()const +// Provides class invariants. +// This class invariant checks the integrity of a completed format stream. +// As such, this invariant is only called by those methods that act upon a completed +// format stream; that is, not the set methods, since the format stream will not be complete until +// this call has completed. +// + { +#ifdef _DEBUG + __ASSERT_DEBUG(DoInvariantCheck(),User::Invariant()); +#endif + } + +void RFormatStream::TestInvariantL()const +// Provides class invariants. +// This class invariant checks the integrity of a completed format stream. +// As such, this invariant is only called by those methods that act upon a completed +// format stream; that is, not the set methods, since the format stream will not be complete until +// this call has completed. +// + { + if (!DoInvariantCheck()) + User::Leave(KErrCorrupt); + } + +TBool RFormatStream::DoInvariantCheck() const +// Provides class invariants. +// This class invariant checks the integrity of a completed format stream. +// As such, this invariant is only called by those methods that act upon a completed +// format stream; that is, not the set methods, since the format stream will not be complete until +// this call has completed. +// + { + if (!iBase) + return ETrue; + if (iEnd>iBase) + {// Assert: stream is self consistent + // Walks through the stream (aBuffer), checking that it is in a consistent state. + // (1) All entries in the buffer conform to a TYPE-VALUE structure, checking that + // types do not occur in contiguous bytes. ie there is a value. + // (2) Checks that all encountered types are valid types. + // (3) Checks that the buffer has not changed size as a result of this check + // (4) Checks that all attributes in the stream occur only once. Done by taking a register + // as each attribute is read from the stream. (The exception to this rule are Tab identifiers + // which, if present, will typically occur several times in the stream). + // + enum {ENotPresent,EPresent}; + TInt8 attributeRegister[EAttributeCount]; + for (TInt offset=0;offset=streamLoc)) return EFalse; + streamLoc=tempStreamLoc; + } +// Assert: everything is still the same size. + if (!(streamLoc==endOfStreamLoc)) return EFalse; + } + return ETrue; + } + +static inline TUint32 Read32(const TUint8* aPtr) + { + TUint32 val = aPtr[0]; + val |= aPtr[1] << 8; + val |= aPtr[2] << 16; + val |= aPtr[3] << 24; + return val; + } + + +static inline void Write32(TUint8*& aPtr,TUint32 aVal) + { + *aPtr++ = TUint8(aVal); + *aPtr++ = TUint8(aVal >> 8); + *aPtr++ = TUint8(aVal >> 16); + *aPtr++ = TUint8(aVal >> 24); + } + + +RFormatStream::RFormatStream(): + iBase(NULL), + iEnd(NULL) + { + } + + +// Allocate the buffer +void RFormatStream::AllocL(TInt aSize) + { + TUint8* pT = reinterpret_cast(User::ReAllocL(iBase, aSize)); + + iBase=pT; + iEnd=pT+aSize; + } + + +void RFormatStream::Reset() +// Free all storage +// + { + if (iBase) + { + User::Free(iBase); + iBase = iEnd = NULL; + } + } + + +void RFormatStream::CopyL(const RFormatStream& aSource) + { + TInt size = aSource.iEnd - aSource.iBase; + __ASSERT_DEBUG(size >= 0,Panic(EDebug)); + if (size == 0) + Reset(); + else + { + AllocL(size); + Mem::Copy(iBase,aSource.iBase,size); + } + } + + +/* +Write the bytecode to a stream. Don't write internal attributes; these are not part of the stored format, +but are used for transitory marking of text by URL parsers, etc. +*/ +void RFormatStream::ExternalizeL(RWriteStream& aStream) const + { + __TEST_INVARIANT; + + const TUint8* base=iBase; + if (base) + { + const TUint8* end = base; + while (end < iEnd && *end < EExternalizedAttributeCount) + { + int bytes = TheAttributeLength[*end++]; + if (bytes == 0) + bytes = *end++; + end += bytes; + } + int length = end - base; + aStream.WriteInt32L(length); + aStream.WriteL(base,length); + } + else + aStream.WriteInt32L(0); + } + + +void RFormatStream::InternalizeL(RReadStream& aStream) +// Load the buffer from the specified stream +// + { + TestInvariantL(); + + TInt length=aStream.ReadInt32L(); + // + if (length<0 || length>KMaxFormatStreamLength) + User::Leave(KErrCorrupt); + // + if (length==0) + Reset(); + else + { + AllocL(length); + aStream.ReadL(iBase,length); + } + + TestInvariantL(); + } + + +// Return a pointer to the stored bytecode and put its length in bytes in aLength. +const TUint8* RFormatStream::Ptr(TInt& aLength) const + { + __TEST_INVARIANT; + aLength=iEnd-iBase; + __ASSERT_DEBUG((iBase==NULL && aLength==0) || (iBase!=NULL && aLength>0),Panic(ECorruptFormatLayer)); + return iBase; + } + + +// Save the attributes of aCharFormat specified by the corresponding mask aMask. +void RFormatStream::SetCharFormatL(const TCharFormatX& aCharFormatX,const TCharFormatXMask& aMask) + { + TInt size=DoCalcSizeCharFormat(aCharFormatX,aMask); + if (size==0) + Reset(); + else + { + AllocL(size); // delete the current contents, after allocing a temporary + DoStoreCharFormat(aCharFormatX,aMask); + } + + __TEST_INVARIANT; + } + + +void RFormatStream::SetParaFormatL(const CParaFormat& aDesiredFormat,const TParaFormatMask& aDesiredMask, + const CParaFormat& aCurrentFormat) +// Sets the format layer with the specified paragraph format attributes. +// If a leave occurs at any stage, then revert back to original state, and +// propagate the leave. +// + { + TInt size=DoCalcSizeParaFormat(aDesiredFormat,aDesiredMask,aCurrentFormat); + if (size==0) + Reset(); + else + { + AllocL(size); // delete the current contents, after allocing a temporary + DoSetParaFormat(aDesiredFormat,aDesiredMask,aCurrentFormat); + } + + __TEST_INVARIANT; + } + +// Write an auxiliary attribute for a system colour byte. Update aPtr. +static void WriteSystemColor(TUint8*& aPtr,TTextFormatNonMaskableAttribute aAttrib,const TLogicalRgb& aColor) + { + TUint8 index = (TUint8)aColor.SystemColorIndex(); + if (index) + { + *aPtr++ = TUint8(aAttrib); + *aPtr++ = index; + } + } + + +// Read a system colour byte into a logical colour. Don't change aPtr. +static void ReadSystemColor(const TUint8* aPtr,TLogicalRgb& aColor) + { + TUint index = *aPtr; + aColor.SetSystemColorIndex(index); + } + + +// Write paragraph attributes specified by aDesiredMask from aDesiredFormat to the stream. +void RFormatStream::DoSetParaFormat(const CParaFormat& aDesiredFormat, + TParaFormatMask aMask, + const CParaFormat& aCurrentFormat) + { + TUint8* ptr=iBase; + if (aMask.AttribIsSet(EAttFillColor)) + { + *ptr++=TUint8(EAttFillColor); + ptr=Store(ptr,aDesiredFormat.iFillColor); + } + if (aMask.AttribIsSet(EAttLeftMargin)) + { + *ptr++=TUint8(EAttLeftMargin); + Write32(ptr,aDesiredFormat.iLeftMarginInTwips); + } + if (aMask.AttribIsSet(EAttRightMargin)) + { + *ptr++=TUint8(EAttRightMargin); + Write32(ptr,aDesiredFormat.iRightMarginInTwips); + } + if (aMask.AttribIsSet(EAttIndent)) + { + *ptr++=TUint8(EAttIndent); + Write32(ptr,aDesiredFormat.iIndentInTwips); + } + if (aMask.AttribIsSet(EAttAlignment)) + { + *ptr++=TUint8(EAttAlignment); + *ptr++=TUint8(aDesiredFormat.iHorizontalAlignment); + } + if (aMask.AttribIsSet(EAttVerticalAlignment)) + { + *ptr++=TUint8(EAttVerticalAlignment); + *ptr++=TUint8(aDesiredFormat.iVerticalAlignment); + } + if (aMask.AttribIsSet(EAttLineSpacing)) + { + *ptr++=TUint8(EAttLineSpacing); + Write32(ptr,aDesiredFormat.iLineSpacingInTwips); + } + if (aMask.AttribIsSet(EAttLineSpacingControl)) + { + *ptr++=TUint8(EAttLineSpacingControl); + *ptr++=TUint8(aDesiredFormat.iLineSpacingControl); + } + if (aMask.AttribIsSet(EAttSpaceBefore)) + { + *ptr++=TUint8(EAttSpaceBefore); + Write32(ptr,aDesiredFormat.iSpaceBeforeInTwips); + } + if (aMask.AttribIsSet(EAttSpaceAfter)) + { + *ptr++=TUint8(EAttSpaceAfter); + Write32(ptr,aDesiredFormat.iSpaceAfterInTwips); + } + if (aMask.AttribIsSet(EAttKeepTogether)) + { + *ptr++=TUint8(EAttKeepTogether); + *ptr++=TUint8(aDesiredFormat.iKeepTogether!=EFalse); + } + if (aMask.AttribIsSet(EAttKeepWithNext)) + { + *ptr++=TUint8(EAttKeepWithNext); + *ptr++=TUint8(aDesiredFormat.iKeepWithNext!=EFalse); + } + if (aMask.AttribIsSet(EAttStartNewPage)) + { + *ptr++=TUint8(EAttStartNewPage); + *ptr++=TUint8(aDesiredFormat.iStartNewPage!=EFalse); + } + if (aMask.AttribIsSet(EAttWidowOrphan)) + { + *ptr++=TUint8(EAttWidowOrphan); + *ptr++=TUint8(aDesiredFormat.iWidowOrphan!=EFalse); + } + if (aMask.AttribIsSet(EAttWrap)) + { + *ptr++=TUint8(EAttWrap); + *ptr++=TUint8(aDesiredFormat.iWrap!=EFalse); + } + if (aMask.AttribIsSet(EAttBorderMargin)) + { + *ptr++=TUint8(EAttBorderMargin); + Write32(ptr,aDesiredFormat.iBorderMarginInTwips); + } + if ( aDesiredFormat.BordersPresent() || aCurrentFormat.BordersPresent() ) + { + if (aMask.AttribIsSet(EAttTopBorder)) + ptr=StoreBorder(ptr,EAttTopBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop)); + if (aMask.AttribIsSet(EAttBottomBorder)) + ptr=StoreBorder(ptr,EAttBottomBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom)); + if (aMask.AttribIsSet(EAttLeftBorder)) + ptr=StoreBorder(ptr,EAttLeftBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft)); + if (aMask.AttribIsSet(EAttRightBorder)) + ptr=StoreBorder(ptr,EAttRightBorder,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight)); + } + if (aMask.AttribIsSet(EAttDefaultTabWidth)) + { + *ptr++=TUint8(EAttDefaultTabWidth); + Write32(ptr,aDesiredFormat.iDefaultTabWidthInTwips); + } + if (aMask.AttribIsSet(EAttTabStop)) + { + TUint8* tptr=ptr; // prevent stacking of ptr; + StoreTabs(tptr,aDesiredFormat,aCurrentFormat,ETrue); + ptr=tptr; + } + if (aMask.AttribIsSet(EAttBullet)) + { + if (aDesiredFormat.iBullet || aCurrentFormat.iBullet) + { + if (aDesiredFormat.iBullet) + ptr = StoreBullet(ptr,*aDesiredFormat.iBullet); + else if (aCurrentFormat.iBullet) + ptr = StoreBullet(ptr,TBullet()); + } + } + if (!(aDesiredFormat.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttParaLanguage)) + { + *ptr++=TUint8(EAttParaLanguage); + *ptr++=TUint8(aDesiredFormat.iLanguage); + } + + /* + Write the auxiliary attributes for system colours, language codes greater than 255, etc. + These must go at the end of the stream because they will not be recognised by earlier versions + of ETEXT and will prevent any further attributes from being read. + */ + if (aMask.AttribIsSet(EAttFillColor)) + WriteSystemColor(ptr,EAttFillSystemColor,aDesiredFormat.iFillColor); + if (aMask.AttribIsSet(EAttBullet)) + { + if (aDesiredFormat.iBullet) + WriteSystemColor(ptr,EAttBulletSystemColor,aDesiredFormat.iBullet->iColor); + else if (aCurrentFormat.iBullet) + WriteSystemColor(ptr,EAttBulletSystemColor,TBullet().iColor); + } + if (aDesiredFormat.BordersPresent()) + { + if (aMask.AttribIsSet(EAttTopBorder)) + WriteSystemColor(ptr,EAttTopBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop).iColor); + if (aMask.AttribIsSet(EAttBottomBorder)) + WriteSystemColor(ptr,EAttBottomBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom).iColor); + if (aMask.AttribIsSet(EAttLeftBorder)) + WriteSystemColor(ptr,EAttLeftBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft).iColor); + if (aMask.AttribIsSet(EAttRightBorder)) + WriteSystemColor(ptr,EAttRightBorderSystemColor,aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight).iColor); + } + if ((aDesiredFormat.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttParaLanguage)) + { + *ptr++ = TUint8(EAttParaLanguageX); + Write32(ptr,aDesiredFormat.iLanguage); + } + if (aMask.AttribIsSet(EAttBullet)) + { + if (aDesiredFormat.iBullet || aCurrentFormat.iBullet) + { + TBullet bullet; + const TBullet* b = aDesiredFormat.iBullet; + if (!b) + b = • + *ptr++ = TUint8(EAttBulletX); + *ptr++ = TUint8(b->iStyle); + Write32(ptr,b->iStartNumber); + *ptr++ = TUint8(b->iAlignment); + } + } + } + + +TInt RFormatStream::DoCalcSizeParaFormat(const CParaFormat& aDesiredFormat,TParaFormatMask aMask, + const CParaFormat& aCurrentFormat) +// determine the amount of memory required to store the +// specified attriubutes from the specified paragraph format. +// + { + TInt size=0; + if (aMask.AttribIsSet(EAttFillColor)) + { + size+=(KTypeSize+KParaFillColor); + if (aDesiredFormat.iFillColor.SystemColorIndex()) + size += KTypeSize + KParaFillSystemColor; + } + if (aMask.AttribIsSet(EAttLeftMargin)) + size+=(KTypeSize+KParaLeftMargin); + if (aMask.AttribIsSet(EAttRightMargin)) + size+=(KTypeSize+KParaRightMargin); + if (aMask.AttribIsSet(EAttIndent)) + size+=(KTypeSize+KParaIndent); + if (aMask.AttribIsSet(EAttAlignment)) + size+=(KTypeSize+KParaAlignment); + if (aMask.AttribIsSet(EAttVerticalAlignment)) + size+=(KTypeSize+KParaVerticalAlignment); + if (aMask.AttribIsSet(EAttLineSpacing)) + size+=(KTypeSize+KParaLineSpacing); + if (aMask.AttribIsSet(EAttLineSpacingControl)) + size+=(KTypeSize+KParaLineSpacingControl); + if (aMask.AttribIsSet(EAttSpaceBefore)) + size+=(KTypeSize+KParaSpaceBefore); + if (aMask.AttribIsSet(EAttSpaceAfter)) + size+=(KTypeSize+KParaSpaceAfter); + if (aMask.AttribIsSet(EAttKeepTogether)) + size+=(KTypeSize+KParaKeepTogether); + if (aMask.AttribIsSet(EAttKeepWithNext)) + size+=(KTypeSize+KParaKeepWithNext); + if (aMask.AttribIsSet(EAttStartNewPage)) + size+=(KTypeSize+KParaStartNewPage); + if (aMask.AttribIsSet(EAttWidowOrphan)) + size+=(KTypeSize+KParaWidowOrphan); + if (aMask.AttribIsSet(EAttWrap)) + size+=(KTypeSize+KParaWrap); + if (aMask.AttribIsSet(EAttBorderMargin)) + size+=(KTypeSize+KParaBorderMargin); + if ( aDesiredFormat.BordersPresent() || aCurrentFormat.BordersPresent() ) + { + if (aMask.AttribIsSet(EAttTopBorder)) + { + size+=(KTypeSize+ + sizeof(TUint8)+ // line style + sizeof(TInt32)+ // line thickness + KColor+ + sizeof(TUint8)); // auto color flag + if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderTop).iColor.SystemColorIndex()) + size += KTypeSize + KParaTopBorderSystemColor; + } + if (aMask.AttribIsSet(EAttBottomBorder)) + { + size+=(KTypeSize+ + sizeof(TUint8)+ // line style + sizeof(TInt32)+ // line thickness + KColor+ + sizeof(TUint8)); // auto color flag + if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderBottom).iColor.SystemColorIndex()) + size += KTypeSize + KParaBottomBorderSystemColor; + } + if (aMask.AttribIsSet(EAttLeftBorder)) + { + size+=(KTypeSize+ + sizeof(TUint8)+ // line style + sizeof(TInt32)+ // line thickness + KColor+ + sizeof(TUint8)); // auto color flag + if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderLeft).iColor.SystemColorIndex()) + size += KTypeSize + KParaLeftBorderSystemColor; + } + if (aMask.AttribIsSet(EAttRightBorder)) + { + size+=(KTypeSize+ + sizeof(TUint8)+ // line style + sizeof(TInt32)+ // line thickness + KColor+ + sizeof(TUint8)); // auto color flag + if (aDesiredFormat.ParaBorder(CParaFormat::EParaBorderRight).iColor.SystemColorIndex()) + size += KTypeSize + KParaBulletSystemColor; + } + } + if (aMask.AttribIsSet(EAttDefaultTabWidth)) + size+=(KTypeSize+KParaDefaultTabWidth); + if (aMask.AttribIsSet(EAttTabStop)) + { + TUint8* ptr=NULL; + size+=StoreTabs(ptr,aDesiredFormat,aCurrentFormat,EFalse); + } + if (aMask.AttribIsSet(EAttBullet)) + { + if (aDesiredFormat.iBullet || aCurrentFormat.iBullet) + { + size += KTypeSize + + sizeof(TUint8) + // length of following data + sizeof(TText) + // iCharacterCode + KFontHeight + // iHeightInTwips + sizeof(TUint8) + // iHanging indent + KCharColor + // iColor + sizeof(TUint8) + // typeface name size + KTypefaceFlags; // typeface flags + + if (aDesiredFormat.iBullet) + size += aDesiredFormat.iBullet->iTypeface.iName.Size(); // font name + + if ((aDesiredFormat.iBullet && aDesiredFormat.iBullet->iColor.SystemColorIndex()) || + (aCurrentFormat.iBullet)) + size += KTypeSize + KParaBulletSystemColor; + + size += KTypeSize + KParaBulletX; + } + } + if (aMask.AttribIsSet(EAttParaLanguage)) + { + if (aDesiredFormat.iLanguage & ~0xFF) + size += KTypeSize + KParaLanguageX; + else + size += KTypeSize + KParaLanguage; + } + return size; + } + + +// Store the specified values in this (allocated) format stream. +void RFormatStream::DoStoreCharFormat(const TCharFormatX& aCharFormat,TCharFormatXMask aMask) + { + TUint8* ptr = iBase; + const TCharFormat format = aCharFormat.iCharFormat; + + if (aMask.AttribIsSet(EAttColor)) + { + *ptr++=TUint8(EAttColor); + ptr=Store(ptr,format.iFontPresentation.iTextColor); + } + if (aMask.AttribIsSet(EAttFontHighlightColor)) + { + *ptr++=TUint8(EAttFontHighlightColor); + ptr=Store(ptr,format.iFontPresentation.iHighlightColor); + } + if (aMask.AttribIsSet(EAttFontHighlightStyle)) + { + *ptr++=TUint8(EAttFontHighlightStyle); + *ptr++=(TUint8)format.iFontPresentation.iHighlightStyle; + } + if (aMask.AttribIsSet(EAttFontStrikethrough)) + { + *ptr++=TUint8(EAttFontStrikethrough); + *ptr++=(TUint8)format.iFontPresentation.iStrikethrough; + } + if (aMask.AttribIsSet(EAttFontUnderline)) + { + *ptr++=TUint8(EAttFontUnderline); + *ptr++=(TUint8)format.iFontPresentation.iUnderline; + } + if (aMask.AttribIsSet(EAttFontHeight)) + { + *ptr++=TUint8(EAttFontHeight); + Write32(ptr,format.iFontSpec.iHeight); + } + if (aMask.AttribIsSet(EAttFontPosture)) + { + *ptr++=TUint8(EAttFontPosture); + *ptr++=TUint8(format.iFontSpec.iFontStyle.Posture()); + } + if (aMask.AttribIsSet(EAttFontStrokeWeight)) + { + *ptr++=TUint8(EAttFontStrokeWeight); + *ptr++=TUint8(format.iFontSpec.iFontStyle.StrokeWeight()); + } + if (aMask.AttribIsSet(EAttFontPrintPos)) + { + *ptr++=TUint8(EAttFontPrintPos); + *ptr++=TUint8(format.iFontSpec.iFontStyle.PrintPosition()); + } + if (aMask.AttribIsSet(EAttFontTypeface)) + { + *ptr++=TUint8(EAttFontTypeface); + ptr=Store(ptr,format.iFontSpec.iTypeface); + *ptr++=TUint8(EAttBitmapType); + *ptr++=TUint8(format.iFontSpec.iFontStyle.BitmapType()); + } + if (!(format.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttCharLanguage)) + { + *ptr++=TUint8(EAttCharLanguage); + *ptr++=TUint8(format.iLanguage); + } + if (aMask.AttribIsSet(EAttFontHiddenText)) + { + *ptr++=TUint8(EAttFontHiddenText); + *ptr++=TUint8(format.iFontPresentation.iHiddenText!=EFalse); + } + if (aMask.AttribIsSet(EAttFontPictureAlignment)) + { + *ptr++=TUint8(EAttFontPictureAlignment); + *ptr++=TUint8(format.iFontPresentation.iPictureAlignment); + } + + // Auxiliary attributes for system colours, etc. + if (aMask.AttribIsSet(EAttColor)) + WriteSystemColor(ptr,EAttTextSystemColor,format.iFontPresentation.iTextColor); + if (aMask.AttribIsSet(EAttFontHighlightColor)) + WriteSystemColor(ptr,EAttFontHighlightSystemColor,format.iFontPresentation.iHighlightColor); + if ((format.iLanguage & ~0xFF) && aMask.AttribIsSet(EAttCharLanguage)) + { + *ptr++ = TUint8(EAttCharLanguageX); + Write32(ptr,format.iLanguage); + } + + // Internal character attributes: + if (aMask.AttribIsSet(EAttParserTag)) + { + *ptr++ = TUint8(EAttParserTag); + Write32(ptr,aCharFormat.iParserTag); + } + } + + +TInt RFormatStream::DoCalcSizeCharFormat(const TCharFormatX& aCharFormatX,const TCharFormatXMask& aMask) + { + TInt size = 0; + const TCharFormat format = aCharFormatX.iCharFormat; + + if (aMask.AttribIsSet(EAttColor)) + { + size+=(KTypeSize+KCharColor); + if (format.iFontPresentation.iTextColor.SystemColorIndex()) + size += KTypeSize + KCharTextSystemColor; + } + if (aMask.AttribIsSet(EAttFontHighlightColor)) + { + size+=(KTypeSize+KCharHighlightColor); + if (format.iFontPresentation.iHighlightColor.SystemColorIndex()) + size += KTypeSize + KCharFontHighlightSystemColor; + } + if (aMask.AttribIsSet(EAttFontHighlightStyle)) + size+=(KTypeSize+KCharHighlightStyle); + if (aMask.AttribIsSet(EAttFontStrikethrough)) + size+=(KTypeSize+KCharStrikethrough); + if (aMask.AttribIsSet(EAttFontUnderline)) + size+=(KTypeSize+KCharUnderline); + if (aMask.AttribIsSet(EAttFontHeight)) + size+=(KTypeSize+KCharFontHeight); + if (aMask.AttribIsSet(EAttFontPosture)) + size+=(KTypeSize+KCharPosture); + if (aMask.AttribIsSet(EAttFontStrokeWeight)) + size+=(KTypeSize+KCharStrokeWeight); + if (aMask.AttribIsSet(EAttFontPrintPos)) + size+=(KTypeSize+KCharPrintPos); + if (aMask.AttribIsSet(EAttFontTypeface)) + { + TUint8 length=(TUint8)format.iFontSpec.iTypeface.iName.Size(); + size+=(KTypeSize+sizeof(TUint8)+length+sizeof(TUint8)); // size in bytes + size+=(KTypeSize+KBitmapType); + } + if (aMask.AttribIsSet(EAttCharLanguage)) + { + if (format.iLanguage & ~0xFF) + size += KTypeSize + KCharLanguageX; + else + size += KTypeSize + KCharLanguage; + } + if (aMask.AttribIsSet(EAttFontHiddenText)) + size+=(KTypeSize+KCharHiddenText); + if (aMask.AttribIsSet(EAttFontPictureAlignment)) + size+=(KTypeSize+KCharPictureAlignment); + + // Internal character attributes + if (aMask.AttribIsSet(EAttParserTag)) + size += KTypeSize + KCharParserTag; + + return size; + } + +void RFormatStream::RemoveRedundantCharFormat(TCharFormatMask& aMask, + const TCharFormatX& aFormat,const TCharFormatX& aEffectiveFormat) + { + TCharFormatXMask mask = aMask; + const TCharFormat format = aFormat.iCharFormat; + const TCharFormat effective_format = aEffectiveFormat.iCharFormat; + + if (mask.AttribIsSet(EAttColor)) + { + if (format.iFontPresentation.iTextColor==effective_format.iFontPresentation.iTextColor) + mask.ClearAttrib(EAttColor); + } + if (mask.AttribIsSet(EAttFontHighlightColor)) + { + if (format.iFontPresentation.iHighlightColor==effective_format.iFontPresentation.iHighlightColor) + mask.ClearAttrib(EAttFontHighlightColor); + } + if (mask.AttribIsSet(EAttFontHighlightStyle)) + { + if (format.iFontPresentation.iHighlightStyle==effective_format.iFontPresentation.iHighlightStyle) + mask.ClearAttrib(EAttFontHighlightStyle); + } + if (mask.AttribIsSet(EAttFontStrikethrough)) + { + if (format.iFontPresentation.iStrikethrough==effective_format.iFontPresentation.iStrikethrough) + mask.ClearAttrib(EAttFontStrikethrough); + } + if (mask.AttribIsSet(EAttFontUnderline)) + { + if (format.iFontPresentation.iUnderline==effective_format.iFontPresentation.iUnderline) + mask.ClearAttrib(EAttFontUnderline); + } + if (mask.AttribIsSet(EAttFontHeight)) + { + if (format.iFontSpec.iHeight==effective_format.iFontSpec.iHeight) + mask.ClearAttrib(EAttFontHeight); + } + if (mask.AttribIsSet(EAttFontPosture)) + { + if (format.iFontSpec.iFontStyle.Posture()==effective_format.iFontSpec.iFontStyle.Posture()) + mask.ClearAttrib(EAttFontPosture); + } + if (mask.AttribIsSet(EAttFontStrokeWeight)) + { + if (format.iFontSpec.iFontStyle.StrokeWeight()==effective_format.iFontSpec.iFontStyle.StrokeWeight()) + mask.ClearAttrib(EAttFontStrokeWeight); + } + if (mask.AttribIsSet(EAttFontPrintPos)) + { + if (format.iFontSpec.iFontStyle.PrintPosition()==effective_format.iFontSpec.iFontStyle.PrintPosition()) + mask.ClearAttrib(EAttFontPrintPos); + } + if (mask.AttribIsSet(EAttFontTypeface)) + { + if (format.iFontSpec.iTypeface==effective_format.iFontSpec.iTypeface) + mask.ClearAttrib(EAttFontTypeface); + } + if (mask.AttribIsSet(EAttCharLanguage)) + { + if (format.iLanguage==effective_format.iLanguage) + mask.ClearAttrib(EAttCharLanguage); + } + if (mask.AttribIsSet(EAttFontHiddenText)) + { + if (format.iFontPresentation.iHiddenText==effective_format.iFontPresentation.iHiddenText) + mask.ClearAttrib(EAttFontHiddenText); + } + if (mask.AttribIsSet(EAttFontPictureAlignment)) + { + if (format.iFontPresentation.iPictureAlignment==effective_format.iFontPresentation.iPictureAlignment) + mask.ClearAttrib(EAttFontPictureAlignment); + } + if (mask.AttribIsSet(EAttParserTag)) + { + if (aFormat.iParserTag == aEffectiveFormat.iParserTag) + mask.ClearAttrib(EAttParserTag); + } + aMask = mask; + } + + +void RFormatStream::SenseParaFormatL(CParaFormat& aParaFormat,TParaFormatMask& aMask,CParaFormat::TParaFormatGetMode aMode)const +// Dumps contents of the stream into aParaFormat. The attributes written to aParaFormat +// are determined by the mode, aMode. +// If the mode is EAllAttributes, then all attributes are written, +// if the mode is EFixedAttributes, then only the fixed atttibutes are written, +// ie, not tabs,borders,bullet (which are variable). +// For each format attribute found in the stream: +// write it into a ParaFormat if the corresponding flag in aMask is not set, +// and set this flag showing the attribute has been written into aParaFormat. +// +// If aMode is EAllAttributes this function may leave through out-of-memory allocating paragraph borders, +// bullets or tabs. +// If aMode is EFixedAttributes, this function is guaranteed not to leave. +// + { + __TEST_INVARIANT; + + TUint8* ptr=iBase; + if (ptr==NULL) + return; + TParaFormatMask old_mask = aMask; + TParaFormatMask new_mask = aMask; + TUint8* end=iEnd; + TParaBorder* b = NULL; + + while (ptr < end) + { + TUint8 type = *ptr; + ptr += KTypeSize; + switch (type) + { + case EAttFillColor: + if (!old_mask.AttribIsSet(EAttFillColor)) + { + new_mask.SetAttrib(EAttFillColor); + ptr=ReadValue(ptr,aParaFormat.iFillColor); + } + else + ptr+=KParaFillColor; + break; + case EAttLeftMargin: + if (!old_mask.AttribIsSet(EAttLeftMargin)) + { + new_mask.SetAttrib(EAttLeftMargin); + aParaFormat.iLeftMarginInTwips = Read32(ptr); + } + ptr+=KParaLeftMargin; + break; + case EAttRightMargin: + if (!old_mask.AttribIsSet(EAttRightMargin)) + { + new_mask.SetAttrib(EAttRightMargin); + aParaFormat.iRightMarginInTwips = Read32(ptr); + } + ptr+=KParaRightMargin; + break; + case EAttIndent: + if (!old_mask.AttribIsSet(EAttIndent)) + { + new_mask.SetAttrib(EAttIndent); + aParaFormat.iIndentInTwips = Read32(ptr); + } + ptr+=KParaIndent; + break; + case EAttAlignment: + if (!old_mask.AttribIsSet(EAttAlignment)) + { + new_mask.SetAttrib(EAttAlignment); + aParaFormat.iHorizontalAlignment=CParaFormat::TAlignment(*ptr); + } + ptr+=KParaAlignment; + break; + case EAttVerticalAlignment: + if (!old_mask.AttribIsSet(EAttVerticalAlignment)) + { + new_mask.SetAttrib(EAttVerticalAlignment); + aParaFormat.iVerticalAlignment=CParaFormat::TAlignment(*ptr); + } + ptr+=KParaVerticalAlignment; + break; + case EAttLineSpacing: + if (!old_mask.AttribIsSet(EAttLineSpacing)) + { + new_mask.SetAttrib(EAttLineSpacing); + aParaFormat.iLineSpacingInTwips = Read32(ptr); + } + ptr+=KParaLineSpacing; + break; + case EAttLineSpacingControl: + if (!old_mask.AttribIsSet(EAttLineSpacingControl)) + { + new_mask.SetAttrib(EAttLineSpacingControl); + aParaFormat.iLineSpacingControl=(CParaFormat::TLineSpacingControl)*ptr; + } + ptr+=KParaLineSpacingControl; + break; + case EAttSpaceBefore: + if (!old_mask.AttribIsSet(EAttSpaceBefore)) + { + new_mask.SetAttrib(EAttSpaceBefore); + aParaFormat.iSpaceBeforeInTwips = Read32(ptr); + } + ptr+=KParaSpaceBefore; + break; + case EAttSpaceAfter: + if (!old_mask.AttribIsSet(EAttSpaceAfter)) + { + new_mask.SetAttrib(EAttSpaceAfter); + aParaFormat.iSpaceAfterInTwips = Read32(ptr); + } + ptr+=KParaSpaceAfter; + break; + case EAttKeepTogether: + if (!old_mask.AttribIsSet(EAttKeepTogether)) + { + new_mask.SetAttrib(EAttKeepTogether); + aParaFormat.iKeepTogether=TBool(*ptr); + } + ptr+=KParaKeepTogether; + break; + case EAttKeepWithNext: + if (!old_mask.AttribIsSet(EAttKeepWithNext)) + { + new_mask.SetAttrib(EAttKeepWithNext); + aParaFormat.iKeepWithNext=(TBool)*ptr; + } + ptr+=KParaKeepWithNext; + break; + case EAttStartNewPage: + if (!old_mask.AttribIsSet(EAttStartNewPage)) + { + new_mask.SetAttrib(EAttStartNewPage); + aParaFormat.iStartNewPage=TBool(*ptr); + } + ptr+=KParaStartNewPage; + break; + case EAttWidowOrphan: + if (!old_mask.AttribIsSet(EAttWidowOrphan)) + { + new_mask.SetAttrib(EAttWidowOrphan); + aParaFormat.iWidowOrphan=TBool(*ptr); + } + ptr+=KParaWidowOrphan; + break; + case EAttWrap: + if (!old_mask.AttribIsSet(EAttWrap)) + { + new_mask.SetAttrib(EAttWrap); + aParaFormat.iWrap=TBool(*ptr); + } + ptr+=KParaWrap; + break; + case EAttBorderMargin: + if (!old_mask.AttribIsSet(EAttBorderMargin)) + { + new_mask.SetAttrib(EAttBorderMargin); + aParaFormat.iBorderMarginInTwips = Read32(ptr); + } + ptr+=KParaBorderMargin; + break; + case EAttTopBorder: + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttTopBorder) ) + { + ptr+=KParaTopBorder; + } + else + { + TParaBorder border; + ptr=ReadValue(ptr,border); + aParaFormat.SetParaBorderL(CParaFormat::EParaBorderTop,border); + new_mask.SetAttrib(EAttTopBorder); + } + break; + case EAttBottomBorder: + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBottomBorder)) + { + ptr+=KParaBottomBorder; + } + else + { + TParaBorder border; + ptr=ReadValue(ptr,border); + aParaFormat.SetParaBorderL(CParaFormat::EParaBorderBottom,border); + new_mask.SetAttrib(EAttBottomBorder); + } + break; + case EAttLeftBorder: + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttLeftBorder)) + { + ptr+=KParaLeftBorder; + } + else + { + TParaBorder border; + ptr=ReadValue(ptr,border); + aParaFormat.SetParaBorderL(CParaFormat::EParaBorderLeft,border); + new_mask.SetAttrib(EAttLeftBorder); + } + break; + case EAttRightBorder: + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttRightBorder)) + { + ptr+=KParaRightBorder; + } + else + { + TParaBorder border; + ptr=ReadValue(ptr,border); + aParaFormat.SetParaBorderL(CParaFormat::EParaBorderRight,border); + new_mask.SetAttrib(EAttRightBorder); + } + break; + case EAttDefaultTabWidth: + if (!old_mask.AttribIsSet(EAttDefaultTabWidth)) + { + new_mask.SetAttrib(EAttDefaultTabWidth); + aParaFormat.iDefaultTabWidthInTwips = Read32(ptr); + } + ptr+=KParaDefaultTabWidth; + break; + case EAttTabStop: + { + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttTabStop)) + ptr += KParaTabStop; + else + { + ptr=ReadTabL(ptr,aParaFormat); + new_mask.SetAttrib(EAttTabStop); + } + break; + } + case EAttBullet: + { + if (aMode==CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBullet)) + { + ptr+=*ptr+1; // variable length attribute + } + else + { + TBullet* bullet=aParaFormat.iBullet; + if (!bullet) + aParaFormat.iBullet=bullet=new(ELeave) TBullet; + ptr=ReadValue(ptr,*bullet); + new_mask.SetAttrib(EAttBullet); + //coverity[memory_leak] + } + break; + } + case EAttParaLanguage: + if (!old_mask.AttribIsSet(EAttParaLanguage)) + { + new_mask.SetAttrib(EAttParaLanguage); + aParaFormat.iLanguage=TInt32(*ptr); + } + ptr+=KParaLanguage; + break; + + // Auxiliary attributes for system colours, etc. + case EAttFillSystemColor: + if (!old_mask.AttribIsSet(EAttFillColor)) + ReadSystemColor(ptr,aParaFormat.iFillColor); + ptr++; + break; + case EAttBulletSystemColor: + if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttBullet) && + aParaFormat.iBullet) + ReadSystemColor(ptr,aParaFormat.iBullet->iColor); + ptr++; + break; + case EAttTopBorderSystemColor: + if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttTopBorder)) + { + b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderTop); + if (b) + ReadSystemColor(ptr,b->iColor); + } + ptr++; + break; + case EAttBottomBorderSystemColor: + if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttBottomBorder)) + { + b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderBottom); + if (b) + ReadSystemColor(ptr,b->iColor); + } + ptr++; + break; + case EAttLeftBorderSystemColor: + if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttLeftBorder)) + { + b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderLeft); + if (b) + ReadSystemColor(ptr,b->iColor); + } + ptr++; + break; + case EAttRightBorderSystemColor: + if (aMode != CParaFormat::EFixedAttributes && !old_mask.AttribIsSet(EAttRightBorder)) + { + b = aParaFormat.ParaBorderPtr(CParaFormat::EParaBorderRight); + if (b) + ReadSystemColor(ptr,b->iColor); + } + ptr++; + break; + case EAttParaLanguageX: + if (!old_mask.AttribIsSet(EAttParaLanguage)) + { + new_mask.SetAttrib(EAttParaLanguage); + aParaFormat.iLanguage = Read32(ptr); + } + ptr += KParaLanguageX; + break; + case EAttBulletX: + if (aMode == CParaFormat::EFixedAttributes || old_mask.AttribIsSet(EAttBullet) || + !aParaFormat.iBullet) + ptr += KParaBulletX; + else + { + aParaFormat.iBullet->iStyle = (TBullet::TStyle)(*ptr++); + aParaFormat.iBullet->iStartNumber = Read32(ptr); + ptr += sizeof(TInt32); + aParaFormat.iBullet->iAlignment = (TBullet::TAlignment)(*ptr++); + } + break; + + default: // have maybe read an attribute defined by a later version; stop here + aMask = new_mask; + return; + } + } + aMask = new_mask; + } + +/* +Extract format attributes selected by cleared bits in aMask. +Put them into aCharFormatX if the corresponding bit in aMask is NOT set, and set the bit. +*/ +void RFormatStream::SenseCharFormat(TCharFormatX& aCharFormat,TCharFormatXMask& aMask) const + { + __TEST_INVARIANT; + + TUint8* ptr = iBase; + if (ptr == NULL) + return; + TCharFormatXMask old_mask = aMask; + TCharFormatXMask new_mask = aMask; + TUint8* end = iEnd; + TCharFormat& format = aCharFormat.iCharFormat; + + while (ptr (*ptr)); + } + ptr+=KBitmapType; + break; + case EAttCharLanguage: + if (!old_mask.AttribIsSet(EAttCharLanguage)) + { + new_mask.SetAttrib(EAttCharLanguage); + format.iLanguage=*ptr; + } + ptr+=KCharLanguage; + break; + case EAttFontHiddenText: + if (!old_mask.AttribIsSet(EAttFontHiddenText)) + { + new_mask.SetAttrib(EAttFontHiddenText); + format.iFontPresentation.iHiddenText=(TBool)*ptr; + } + ptr+=KCharHiddenText; + break; + case EAttFontPictureAlignment: + if (!old_mask.AttribIsSet(EAttFontPictureAlignment)) + { + new_mask.SetAttrib(EAttFontPictureAlignment); + format.iFontPresentation.iPictureAlignment=(TFontPresentation::TAlignment)*ptr; + } + ptr+=KCharPictureAlignment; + break; + + // Auxiliary attributes for system colours, etc. + case EAttTextSystemColor: + if (!old_mask.AttribIsSet(EAttColor)) + ReadSystemColor(ptr,format.iFontPresentation.iTextColor); + ptr++; + break; + + case EAttFontHighlightSystemColor: + if (!old_mask.AttribIsSet(EAttFontHighlightColor)) + ReadSystemColor(ptr,format.iFontPresentation.iHighlightColor); + ptr++; + break; + + case EAttCharLanguageX: + if (!old_mask.AttribIsSet(EAttCharLanguage)) + { + new_mask.SetAttrib(EAttCharLanguage); + format.iLanguage = Read32(ptr); + } + ptr += KCharLanguageX; + break; + + // Internal character attributes: + case EAttParserTag: + if (!old_mask.AttribIsSet(EAttParserTag)) + { + new_mask.SetAttrib(EAttParserTag); + aCharFormat.iParserTag = Read32(ptr); + } + ptr += KCharParserTag; + break; + + default: // have maybe read an attribute defined by a later version; stop here + aMask = new_mask; + return; + } + } + aMask = new_mask; + } + +/** Swaps the contents of this stream with aStream. +@param aStream Object to swap contents with. */ +void RFormatStream::Swap(RFormatStream& aStream) + { + TUint8* t = iBase; + iBase = aStream.iBase; + aStream.iBase = t; + t = iEnd; + iEnd = aStream.iEnd; + aStream.iEnd = t; + } + +TInt RFormatStream::StoreTabs(TUint8*& aPtr,const CParaFormat& aDesiredFormat,const CParaFormat& aCurrentFormat,TBool aStoreData) +// Merges the tabs from the desired paraFormat with those from the current effective paraFormat, resolving differences +// as described below, and store the resultant tablist in this layer. +// If aStoreData is false, then return the number of bytes necessary to store all required tabs +// + { + TInt requiredTabCount=0; + TInt desiredTabCount=aDesiredFormat.TabCount(); + TInt currentTabCount=aCurrentFormat.TabCount(); + if (desiredTabCount==0 && currentTabCount==0) + {// Nothing needs to be stored. + return requiredTabCount; + } + if (desiredTabCount>0 && currentTabCount>0) + {// The 2 tab lists need merging. + requiredTabCount=MergeTabLists(aPtr,aDesiredFormat,desiredTabCount,aCurrentFormat,currentTabCount,aStoreData); + } + else if (desiredTabCount>0 && currentTabCount==0) + {// There are no previous tabs to merge so just store all the desired ones. + if (aStoreData) + StoreAllTabs(aPtr,aDesiredFormat); + else + requiredTabCount+=desiredTabCount; + } + else if (desiredTabCount==0 && currentTabCount>0) + {// We want to delete (NULL) all existing tabs. + if (aStoreData) + { + for (TInt index=0;index Store the desired tab. +// (2) Tab is in current but not desired --> Null the current and store. +// (3) Tab is in both current and desired --> +// (i) if tab type is the same then store nothing -- rely on the base one being inherited. +// (ii)if tab type is not same then store the current -- overriding whatevers in the base. +// + { + TInt requiredTabCount=0; + TInt offsetInDesired,offsetInCurrent; + offsetInDesired=offsetInCurrent=0; + TTabStop desiredTab,currentTab; + while ((offsetInDesired!=aDesiredTabCount) && (offsetInCurrent!=aCurrentTabCount)) + {// Do this until we exhaust one of the tab lists. + desiredTab=aDesiredFormat.TabStop(offsetInDesired); + currentTab=aCurrentFormat.TabStop(offsetInCurrent); + if (desiredTab.iTwipsPositioncurrentTab.iTwipsPosition) + { + if (aStoreData) + { + currentTab.iType=TTabStop::ENullTab; // Null the current current tab. + aPtr=StoreTab(aPtr,currentTab); // Store NULL'd currentTab + } + else + requiredTabCount++; + offsetInCurrent++; // Move to the next tab in the current tablist. + continue; + } + if (desiredTab.iTwipsPosition==currentTab.iTwipsPosition) + { + if (desiredTab.iType!=currentTab.iType) + {// Store desired type to override the one from the lower layer. + if (aStoreData) + aPtr=StoreTab(aPtr,desiredTab); + else + requiredTabCount++; + }// Otherwise rely on the one in the base - store nothing but increment. + offsetInDesired++; + offsetInCurrent++; + continue; + } + } + TInt currentLeftToDo=aCurrentTabCount-offsetInCurrent; + TInt desiredLeftToDo=aDesiredTabCount-offsetInDesired; + // Spot which list is exhausted and process the rest of the remainder appropriately. + if (currentLeftToDo) + {// Store null'd remainder of current tab list. + for (;offsetInCurrent> 8); + aPtr += sizeof(TText); + + // Store the hanging indent + *aPtr++ = TUint8(aBullet.iHangingIndent != FALSE); + + // Store the colour. + aPtr = Store(aPtr,aBullet.iColor); + + // Store the typeface + aPtr = Store(aPtr,aBullet.iTypeface); + + // Store the number of data bytes stored. + *length_ptr = (TUint8)(aPtr - length_ptr - 1); + + return aPtr; + } + + +TUint8* RFormatStream::StoreBorder(TUint8* aPtr,TTextFormatAttribute aType,const TParaBorder& aSource) +// Stores paragraph border attributes. +// Writes the line style, thickness,autoColor flag +// and Color, from aSource to the end of the format stream. +// aType is converted from an enum to a TUint8 as it is stored in the format stream. +// + { + *aPtr++=TUint8(aType); + // border line style + *aPtr++=TUint8(aSource.iLineStyle); + // border line thickness + Write32(aPtr,aSource.iThickness); + // border color + aPtr=Store(aPtr,aSource.iColor); + // border autocolor + *aPtr++=TUint8(aSource.iAutoColor!=EFalse); + return aPtr; + } + + +TUint8* RFormatStream::StoreTab(TUint8* aPtr,const TTabStop& aSource) +// Stores a tabstop compound attribute at the end of the stream. +// Writes the tabstop twips position and the tab type, from aSource, to the end of the format stream. +// aType is converted from an enum to a TUint8 as it is stored in the format stream. +// The tab type is compressed from a TTabType enum to a TUint8. +// Uses InsertL, which may cause expansion of the stream storage, and thus may fail. +// + { + *aPtr++=TUint8(EAttTabStop); + // Store tab poisition. + Write32(aPtr,aSource.iTwipsPosition); + // Compress the tab type. + *aPtr++=TUint8(aSource.iType); + return aPtr; + } + + +TUint8* RFormatStream::Store(TUint8* aPtr,const TLogicalRgb& aRgb) + // Store color value + // + { + *aPtr++=TUint8(aRgb.Red()); + *aPtr++=TUint8(aRgb.Green()); + *aPtr++=TUint8(aRgb.Blue()); + return aPtr; + } + + +TUint8* RFormatStream::Store(TUint8* aPtr,const TTypeface& aTypeface) +// Stores typeface name and flags. +// + { + // + // Store typeface name size + TUint8 length=TUint8(aTypeface.iName.Size()); + length+=KTypefaceFlags; + *aPtr++=length; // byte count. + // + // Store typeface name + aPtr=Mem::Copy(aPtr,aTypeface.iName.Ptr(),length-KTypefaceFlags); + // + // Store typeface flags + TUint8 flags=0; + if (aTypeface.IsProportional()) + flags|=KFontProportional; + if (aTypeface.IsSerif()) + flags|=KFontSerif; + if (aTypeface.IsSymbol()) + flags|=KFontSymbol; + *aPtr=flags; + aPtr+=KTypefaceFlags; + // + return aPtr; + } + +TUint8* RFormatStream::ReadValue(TUint8* aPtr,TLogicalRgb& aRgb)const +// Reads a color value from storage. +// + { + aRgb.SetRed(*aPtr++); + aRgb.SetGreen(*aPtr++); + aRgb.SetBlue(*aPtr++); + aRgb.SetSystemColorIndex(0); + return aPtr; + } + + +TUint8* RFormatStream::ReadValue(TUint8* aPtr,TParaBorder& aBorder)const +// Reads a paragraph border from storage. +// + { + // Read line style + aBorder.iLineStyle=TParaBorder::TLineStyle(*aPtr++); + // Read thickness + aBorder.iThickness = Read32(aPtr); + aPtr+=sizeof(TInt32); + // Read color + aPtr=ReadValue(aPtr,aBorder.iColor); // returns aPtr + // Read autocolor + aBorder.iAutoColor=TBool(*aPtr++); + return aPtr; + } + + +TUint8* RFormatStream::ReadValue(TUint8* aPtr,TBullet& aBullet)const +// Read the bullet compound attribute. +// + { + // Read the length of this bullet attribute + aPtr++; // length not used in this context, skip it + // Read bullet twips height into target + aBullet.iHeightInTwips = Read32(aPtr); + aPtr+=sizeof(TInt32); + // Read bullet character code into target. + aBullet.iCharacterCode = (TText)aPtr[0] | ((TText)aPtr[1] << 8); + aPtr+=sizeof(TText); + // Read hanging indent. + aBullet.iHangingIndent=TBool(*aPtr++); + // Read Color. + aPtr=ReadValue(aPtr,aBullet.iColor); // returns aPtr + // Read typeface + return ReadValue(aPtr,aBullet.iTypeface); // returns aPtr + } + + +TUint8* RFormatStream::ReadValue(TUint8* aPtr,TTypeface& aTypeface)const +// Read a typeface name from storage and associated flags. +// + { + // + // Read typeface name size + TInt length=*aPtr++; + // + // Read typeface name + TInt typefaceLength=length-KTypefaceFlags; + __ASSERT_DEBUG((typefaceLength%2)==0,Panic(ECorruptFormatLayer)); // must be an even number + + TPtr name=aTypeface.iName.Des(); + Mem::Copy(CONST_CAST(TText*,name.Ptr()),aPtr,typefaceLength); + typefaceLength>>=1; + name.SetLength(typefaceLength); + + aPtr+=length-KTypefaceFlags; + // + // Read typeface name flags + TInt attrib=0; + TUint flags=*aPtr; + if (flags & KFontProportional) + attrib|=TTypeface::EProportional; + if (flags & KFontSerif) + attrib|=TTypeface::ESerif; + if (flags & KFontSymbol) + attrib|=TTypeface::ESymbol; + aTypeface.SetAttributes(attrib); // reset the attributes + return aPtr+KTypefaceFlags; + } + + +TUint8* RFormatStream::ReadTabL(TUint8* aPtr,CParaFormat& aTarget)const +// Read the tab stop data from the stream, located at aPos, into +// a temporary TTabStop, and use this to fill in aTarget. +// Does not read the tab if one already exists at the same twips position. +// (Implementation of tab inheritance policy). +// aPos is updated manually, rather than using Length(), since this is +// a compound attribute. +// + { + TTabStop tab; + // Read tab position + tab.iTwipsPosition = Read32(aPtr); + aPtr+=sizeof(TInt32); + // Read tab type + tab.iType=TTabStop::TTabType(*aPtr++); + // Set this tab in the paragraph format + TInt ret=aTarget.LocateTab(tab.iTwipsPosition); // is this necessary + if (ret==KTabNotFound) + aTarget.StoreTabL(tab); + return aPtr; + } + + +TInt RFormatStream::Length(TUint8*& aPtr,TTextFormatAttribute aType) const +// Returns the length of a Type's value +// A length of zero in the lookup table, indicates a variable +// length value. In this case, the length is stored in the byte +// following the type, which is read and returned. +// aPtr is incremented by the appropriate amount following a read. +// + { + TInt length=TheAttributeLength[aType]; + + __ASSERT_DEBUG(length>=0,Panic(EAttributeLengthLookupNegative)); + if (length>0) + return length; + else + return *aPtr++; + }