emailuis/uicomponents/src/fstextviewerlayouter.cpp
changeset 0 8466d47a6819
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailuis/uicomponents/src/fstextviewerlayouter.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1038 @@
+/*
+* Copyright (c) 2007 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:  Visual aligning class
+*
+*/
+
+
+//<cmail> removed __FS_ALFRED_SUPPORT flag
+//#include <fsconfig.h>
+//</cmail> removed __FS_ALFRED_SUPPORT flag
+#include "emailtrace.h"
+#include <gdi.h>
+#include <w32std.h>
+// <cmail> SF
+#include <alf/alfenv.h>
+#include <alf/alftextstyle.h>
+#include <alf/alftextstylemanager.h>
+// </cmail>
+#include <AknLayoutFont.h>
+#include <AknFontAccess.h> 
+#include <AknBidiTextUtils.h>
+// <cmail>
+#include <alf/alftextvisual.h>
+// </cmail>
+
+#include "fstextviewervisualizer.h"
+
+#include "fstextviewerlayouter.h"
+#include "fsrichtextobject.h"
+#include "fstextstylemanager.h"
+#include "fsrichtext.h"
+#include "fsrichtexttext.h"
+#include "fsrichtextsmiley.h"
+#include "fsrichtextpicture.h"
+#include "fstextviewercoordinator.h"
+#include "fstextviewervisualizerdata.h"
+#include "fstextparser.h"
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+CFsTextViewerLayouter* CFsTextViewerLayouter::NewL( CAlfEnv* aEnv )
+    {
+    FUNC_LOG;
+    CFsTextViewerLayouter* self = 
+        new (ELeave) CFsTextViewerLayouter( aEnv );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// ~CFsTextViewerLayouter
+// ---------------------------------------------------------------------------
+CFsTextViewerLayouter::~CFsTextViewerLayouter()
+    {
+    FUNC_LOG;
+    iCurrentLineArray.Close();
+    }
+
+// ---------------------------------------------------------------------------
+// MeasureBidiTextBoundsWidth
+// ---------------------------------------------------------------------------
+TInt CFsTextViewerLayouter::MeasureBidiTextBoundsWidth(
+    const CFont& aFont,
+    const TDesC& aText,
+    CFont::TMeasureTextInput::TFlags aOrder)
+    {
+    FUNC_LOG;
+//    return AknBidiTextUtils::MeasureTextBoundsWidth( aFont, aText, aOrder);
+    CFont::TMeasureTextInput input; 
+    input.iFlags = aOrder;
+    CFont::TMeasureTextOutput output; 
+    
+    TInt textAdvance = aFont.MeasureText( aText, &input, &output );
+	
+	TRect bounds = output.iBounds;
+	bounds.iTl.iX = Min(bounds.iTl.iX, 0);
+	bounds.iBr.iX = Max(bounds.iBr.iX, textAdvance);    
+    return bounds.Width();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CalculateSizeL
+// ---------------------------------------------------------------------------
+TSize CFsTextViewerLayouter::CalculateSizeL( MFsRichTextObject* aObject )
+    {
+    FUNC_LOG;
+    TSize retVal;
+
+    switch ( aObject->GetType() )
+        {
+        case MFsRichTextObject::EFsText:
+            {
+            if ( static_cast<CFsRichTextText*>(aObject)->GetHotSpot() && static_cast<CFsRichTextText*>(aObject)->GetText().Length() > 1 )
+                {
+                CAlfTextVisual* tmp = CAlfTextVisual::AddNewL( *iControl, iVisualizer->BackgroundLayout() );
+                tmp->SetTextL( static_cast<CFsRichTextText*>(aObject)->GetText() );
+                tmp->SetTextStyle( static_cast<CFsRichTextText*>(aObject)->GetStyleId() );
+                tmp->SetAlign( EAlfAlignHLeft, EAlfAlignVTop );
+                tmp->SetPadding( 0 );
+//                retVal = tmp->SubstringExtents( 0, static_cast<CFsRichTextText*>(aObject)->GetText().Length() - 1 ).Size();
+                retVal = tmp->TextExtents();
+                // <cmail> Platform layout change
+                //retVal.iWidth -= 4;
+                // </cmail> Platform layout change
+                tmp->RemoveAndDestroyAllD();
+                break;
+                }
+            
+            CFont* font;
+            User::LeaveIfNull( iScreenDev );
+        
+            CAlfTextStyle* textStyle(
+                iEnv->TextStyleManager().TextStyle(
+                    static_cast<CFsRichTextText*>(aObject)->GetStyleId() ) );
+
+            HBufC* typeface( textStyle->TypefaceNameL() );
+            CleanupStack::PushL( typeface );
+            TFontSpec fontSpec( *typeface, textStyle->TextSizeInTwips() );
+            if ( textStyle->IsBold() )
+				{
+				fontSpec.iFontStyle.SetStrokeWeight( EStrokeWeightBold );
+				}
+            if ( textStyle->IsItalic() )
+            	{
+            	fontSpec.iFontStyle.SetPosture( EPostureItalic );
+            	}
+
+            User::LeaveIfError(
+                iScreenDev->GetNearestFontInTwips(
+                    font, fontSpec ) );
+
+//            TAknFontSpecification aknFs(EAknFontCategoryPrimary, fontSpec, iScreenDev);
+//            aknFs.SetTextPaneHeight( iScreenDev->VerticalTwipsToPixels(fontSpec.iHeight));
+//            aknFs.SetTextPaneHeightIsDesignHeight( ETrue );
+//            font = 
+//                AknFontAccess::CreateLayoutFontFromSpecificationL( 
+//                    *iScreenDev, 
+//                    fontSpec.iTypeface,
+//                    aknFs ); 
+            
+
+//            retVal = TSize(
+//                    font->TextWidthInPixels(
+//                        static_cast<CFsRichTextText*>(aObject)->GetText() ), 
+//                    font->FontMaxHeight() );
+            
+            CleanupStack::PopAndDestroy( typeface );
+            TSize retVal1( MeasureBidiTextBoundsWidth( *font, static_cast<CFsRichTextText*>(aObject)->GetText(), CFont::TMeasureTextInput::EFVisualOrder), font->FontMaxHeight() );
+
+            retVal = retVal1;
+    
+            const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( font );
+            if ( layoutFont )
+            {
+                retVal.iHeight = font->HeightInPixels();
+                TInt textPaneHeight = layoutFont->TextPaneHeight();
+                TInt textPaneTopToBaseline = layoutFont->TextPaneTopToBaseline();
+        
+                retVal.iHeight += textPaneHeight - textPaneTopToBaseline;
+                retVal.iHeight += 1;
+                }
+            else
+                {
+                retVal.iHeight = Max(retVal.iHeight, font->HeightInPixels());
+                retVal.iHeight += 5; // the best approximation - fails on big (>=72) fonts
+                }
+            iScreenDev->ReleaseFont( font );
+//            if ( static_cast<CFsRichTextText*>(aObject)->GetHotSpot() && static_cast<CFsRichTextText*>(aObject)->GetText().Length() > 1 )
+//                {
+//                retVal.iWidth += 3;
+//                }
+            break;
+            }
+        case MFsRichTextObject::EFsTexture:
+            {
+            retVal = static_cast<CFsRichTextPicture*>
+                (aObject)->GetTextureSize();
+            retVal.iWidth += 3;
+            break;
+            }
+        case MFsRichTextObject::EFsSmiley:
+            {
+            if ( iSmileyEnabled )
+                {
+                retVal = static_cast<CFsRichTextSmiley*>
+                     (aObject)->GetPictureObject()->GetTextureSize();
+                }
+            else
+                {
+                CFont* font;
+                CFsRichTextText* object = 
+                    static_cast<CFsRichTextSmiley*>
+                     (aObject)->GetTextObject();
+                User::LeaveIfNull(iScreenDev);
+        
+                CAlfTextStyle* textStyle(
+                    iEnv->TextStyleManager().TextStyle(
+                        object->GetStyleId() ) );
+
+                HBufC* typeface( textStyle->TypefaceNameL() );
+                CleanupStack::PushL( typeface );
+                TFontSpec fontSpec( *typeface, textStyle->TextSizeInTwips() );
+
+                User::LeaveIfError(
+                    iScreenDev->GetNearestFontInTwips( font, fontSpec ) );
+
+                retVal = TSize(
+                        font->TextWidthInPixels( object->GetText() ), 
+                        font->FontMaxHeight() );
+                iScreenDev->ReleaseFont( font );
+                CleanupStack::PopAndDestroy( typeface );
+                break;
+                }
+            }
+        default:
+            {
+            break;
+            }
+        }
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// FindMaxLengthL
+// ---------------------------------------------------------------------------
+TInt CFsTextViewerLayouter::FindMaxLengthL( MFsRichTextObject* aObject )
+    {
+    FUNC_LOG;
+    TInt retVal = 0;
+    if ( aObject->GetType() == MFsRichTextObject::EFsText )
+        {
+        CFont* font;
+        User::LeaveIfNull( iScreenDev );
+            
+        CAlfTextStyle* textStyle(
+            iEnv->TextStyleManager().TextStyle(
+                static_cast<CFsRichTextText*>( aObject )->GetStyleId() ) );
+
+        HBufC* typeface( textStyle->TypefaceNameL() );
+        CleanupStack::PushL( typeface );
+        TFontSpec fontSpec( *typeface, textStyle->TextSizeInTwips() );
+
+        User::LeaveIfError(
+            iScreenDev->GetNearestFontInTwips(
+                font, fontSpec ) );
+        
+        retVal = font->TextCount( static_cast<CFsRichTextText*>(aObject)->GetText(), iDisplaySize.iWidth ) - 1;
+        iScreenDev->ReleaseFont( font );
+        CleanupStack::PopAndDestroy( typeface );
+        }
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// PrepareRangedVisL
+// ---------------------------------------------------------------------------
+TFsRangedVisual* CFsTextViewerLayouter::PrepareRangedVisL( 
+                        MFsRichTextObject* aObject,
+                        CAlfLayout* aLayout )
+    {
+    FUNC_LOG;
+    TFsRangedVisual* retVal = new (ELeave) TFsRangedVisual;
+    retVal->iVisual = NULL;
+    retVal->iHotspot = EFalse;
+    retVal->iEmbed = EFalse;
+
+    switch ( aObject->GetType() )
+        {
+        case MFsRichTextObject::EFsText:
+            {
+            retVal->iStart = aObject->GetBeginOfObject();
+            retVal->iEnd = aObject->GetEndOfObject();
+            retVal->iIsActive = ETrue;
+            retVal->iLayout = aLayout;
+            retVal->iIsText = ETrue;
+            retVal->iTextColor = 
+                static_cast<CFsRichTextText*>(aObject)->GetTextColor();
+            retVal->iTextStyleId = static_cast<CFsRichTextText*>(aObject)->GetStyleId();
+            retVal->iDirection = 
+                static_cast<CFsRichTextText*>(aObject)->GetTextDirection();
+            retVal->iSmiley = EFalse;
+            break;
+            }
+        case MFsRichTextObject::EFsTexture:
+            {
+            retVal->iStart = aObject->GetBeginOfObject(); 
+            retVal->iEnd = aObject->GetEndOfObject();
+            retVal->iIsActive = ETrue;
+            retVal->iLayout = aLayout;
+            retVal->iIsText = EFalse;
+            retVal->iSmiley = EFalse;
+            break;
+            }
+        case MFsRichTextObject::EFsSmiley:
+            {
+            if ( iSmileyEnabled )
+                {
+                retVal->iStart = aObject->GetBeginOfObject(); 
+                retVal->iEnd = aObject->GetEndOfObject();
+                retVal->iIsActive = ETrue;
+                retVal->iLayout = aLayout;
+                retVal->iIsText = EFalse;
+                retVal->iTextColor = 
+                    static_cast<CFsRichTextSmiley*>(aObject)->GetTextObject()->GetTextColor();
+                retVal->iTextStyleId = 
+                    static_cast<CFsRichTextSmiley*>(aObject)->GetTextObject()->GetStyleId();
+                }
+            else
+                {
+                retVal->iStart = aObject->GetBeginOfObject(); 
+                retVal->iEnd = aObject->GetEndOfObject();
+                retVal->iIsActive = ETrue;
+                retVal->iLayout = aLayout;
+                retVal->iIsText = ETrue;
+                retVal->iTextColor = 
+                    static_cast<CFsRichTextSmiley*>(aObject)->GetTextObject()->GetTextColor();
+                retVal->iTextStyleId = 
+                    static_cast<CFsRichTextSmiley*>(aObject)->GetTextObject()->GetStyleId();
+                }
+            retVal->iSmiley = ETrue;
+            break;
+            }
+        case MFsRichTextObject::EFsNewLine:
+            {
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+
+    if ( retVal->iIsActive )
+        {
+        if ( aObject->GetEmbeded() )
+            {
+            retVal->iId = aObject->GetIdOfEmbeded();
+            retVal->iEmbed = ETrue;
+            }
+        if ( aObject->GetHotSpot() )
+            {
+            retVal->iHotspotType = aObject->GetTypeOfHotSpot();
+            retVal->iId = aObject->GetIdOfHotSpot();
+            retVal->iHotspot = ETrue;
+            }
+        }
+
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// SetDisplaySize
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetDisplaySize( TSize aDisplaySize )
+    {
+    FUNC_LOG;
+    iDisplaySize = aDisplaySize;
+    }
+
+// ---------------------------------------------------------------------------
+// AppendObjectL
+// ---------------------------------------------------------------------------
+TBool CFsTextViewerLayouter::AppendObjectL( MFsRichTextObject* aObject, CAlfLayout* aLayout, CFsTextParser* aParser, TBool aRegisterSelects )
+    {
+    FUNC_LOG;
+    TRect objectRect;
+    TRect naturalRect;
+    TSize objectSize = CalculateSizeL( aObject );
+    
+    if ( objectSize.iWidth > iDisplaySize.iWidth )
+        {
+        if ( iLowestPicPosition > iCurrentLineOffset )
+            {
+            iCurrentLineOffset = iLowestPicPosition;
+            ConstructLineL();
+            }
+        if ( aObject->GetType() != MFsRichTextObject::EFsText )
+            {
+            // Resizing object to fit display width
+            const TInt KScalingFactor = 65536;
+            const TInt KTwo = 2;
+            
+            TInt resizeFactor = KScalingFactor * iDisplaySize.iWidth /
+                                objectSize.iWidth;
+            TInt height = objectSize.iHeight;
+            
+            objectSize.iWidth = iDisplaySize.iWidth;
+            
+            height = height * resizeFactor + KScalingFactor / KTwo;
+            objectSize.iHeight = height / KScalingFactor;
+            }
+        else
+            {
+            aParser->CutWord(
+                aObject->GetBeginOfObject(),
+                FindMaxLengthL( aObject ) );
+            return EFalse;
+            }
+        }
+    
+    TFsRangedVisual* currentVisual;
+    currentVisual = PrepareRangedVisL( aObject, aLayout );
+    if ( !aRegisterSelects )
+        {
+        currentVisual->iEmbed = EFalse;
+        }
+    
+    if ( iMainDirection == TBidiText::ELeftToRight )
+        {
+        objectRect = TRect( TPoint( iLastCol, iCurrentLineOffset ), objectSize );
+        }
+    else
+        {        
+        objectRect = TRect( TPoint( iLastCol - objectSize.iWidth, iCurrentLineOffset ), objectSize );
+        }
+    iNewLine = EFalse;
+    naturalRect = objectRect;
+    if ( iHelper->NextFreeCol( objectRect, iMainDirection ) )
+        {
+        ConstructLineL();
+        delete currentVisual;
+        currentVisual = NULL;
+        AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+        }
+    else
+        {
+        if ( objectRect != naturalRect )
+            {
+            currentVisual->iMoved = ETrue;
+            }
+        else 
+            {
+            currentVisual->iMoved = EFalse;
+            }
+        
+        if ( iMainDirection == TBidiText::ELeftToRight )
+            {
+            currentVisual->iRect = objectRect;
+            iLastCol = objectRect.iBr.iX;
+            iCurrentLineArray.Append( currentVisual );
+            }
+        else
+            {
+            currentVisual->iRect = objectRect;
+            iLastCol = objectRect.iTl.iX;
+            iCurrentLineArray.Append( currentVisual );
+            }
+        }
+    if ( objectRect.Height() > iLineHeight && aObject->GetType() != MFsRichTextObject::EFsTexture )
+        {
+        iLineHeight = objectRect.Height();
+        }
+    else if ( aObject->GetType() == MFsRichTextObject::EFsTexture || aObject->GetHotSpot() )
+        {
+        iHelper->RegisterObstacleL( objectRect );
+        if ( objectRect.iBr.iY > iLowestPicPosition )
+            {
+            iLowestPicPosition = objectRect.iBr.iY;
+            }
+        }
+//    if ( text )
+//    	{
+//    	delete text;
+//    	}
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// InsertObjectL
+// ---------------------------------------------------------------------------
+TBool CFsTextViewerLayouter::InsertObjectL( MFsRichTextObject* aObject, CAlfLayout* aLayout, CFsTextParser* aParser, TBool aRegisterSelects )
+    {
+    FUNC_LOG;
+    return AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+    //<cmail> following lines are commented out to avoid warnings
+    /*
+    TBool retVal = EFalse;
+    
+    TSize objectSize = CalculateSizeL( aObject );
+    if ( objectSize.iWidth > iDisplaySize.iWidth )
+        {
+        aParser->CutWord( 
+            aObject->GetBeginOfObject(),
+            FindMaxLengthL( aObject ) );
+        return EFalse;
+        }
+    
+    if ( ( objectSize.iWidth > iDisplaySize.iWidth - iLastCol && iMainDirection == TBidiText::ELeftToRight )
+            || ( objectSize.iWidth > iLastCol && iMainDirection == TBidiText::ERightToLeft ) )
+        {
+        ConstructLineL();
+        retVal = AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+        }
+    else //if ( 0 == iCurrentLineArray.Count() )
+        {
+        retVal = AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+        }*/
+    //</cmail>    
+//    else
+//        {
+//        if ( iMainDirection == TBidiText::ELeftToRight )
+//            {
+////            retVal = ReorderLineFromLeftL( aObject, aLayout, aParser, objectSize, aRegisterSelects );
+//            }
+//        else 
+//            {
+////            retVal = ReorderLineFromRightL( aObject, aLayout, aParser, objectSize, aRegisterSelects );
+//            }
+//        }
+    //<cmail> following lines are commented out to avoid warnings
+    //return retVal;
+    //</cmail>
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructLineL
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::ConstructLineL( TInt aHeight )
+    {
+    FUNC_LOG;
+    TInt i = 0;
+    TInt dY;
+    RPointerArray<TFsRangedVisual> finalLine;
+    
+    if ( 0 == iLineHeight )
+        {
+        iLineHeight = aHeight;
+        }
+    
+    for ( i = 0; i < iCurrentLineArray.Count(); ++i )
+        {
+        iCurrentLineArray[i]->iLineNumber = iLines;
+        if ( iCurrentLineArray[i]->iIsText )
+            {
+            dY = iLineHeight - iCurrentLineArray[i]->iRect.Height();
+            iCurrentLineArray[i]->iRect.iTl.iY += dY;
+            iCurrentLineArray[i]->iRect.iBr.iY += dY;
+            }
+        if ( i > 0
+                && iCurrentLineArray[i]->iIsText 
+                && finalLine[finalLine.Count() - 1]->iIsText
+//                && iCurrentLineArray[i]->iDirection == finalLine[finalLine.Count() - 1]->iDirection
+//                && iCurrentLineArray[i]->iDirection == iMainDirection
+                && iCurrentLineArray[i]->iTextStyleId == finalLine[finalLine.Count() - 1]->iTextStyleId
+                && iCurrentLineArray[i]->iTextColor == finalLine[finalLine.Count() - 1]->iTextColor
+                && ( !iCurrentLineArray[i]->iHotspot 
+                        ||
+                        iCurrentLineArray[i]->iId == finalLine[finalLine.Count() - 1]->iId
+                        )
+//                && !finalLine[finalLine.Count() - 1]->iHotspot
+                && !iCurrentLineArray[i]->iMoved
+//                && !iCurrentLineArray[i]->iEmbed
+//                && !finalLine[finalLine.Count() - 1]->iEmbed                
+                 )
+            
+            {
+            JoinRangedVisuals( finalLine[finalLine.Count() - 1], iCurrentLineArray[i] );
+            delete iCurrentLineArray[i];
+            iCurrentLineArray[i] = NULL;
+            }
+        else
+            {
+            finalLine.Append( iCurrentLineArray[i] );
+            }
+        }
+    
+    for ( i = 0; i < finalLine.Count(); ++i )
+        {
+        iNavigator->AppendVisualL( finalLine[i] );
+        }
+    finalLine.Close();
+    
+    if ( iMainDirection == TBidiText::ELeftToRight )
+        {
+        iLastCol = iLeftMargin;
+        }
+    else 
+        {
+        iLastCol = iDisplaySize.iWidth + iLeftMargin;
+        }
+    
+    iNewLine = ETrue;
+    
+    iCurrentLineArray.Reset();
+    iCurrentLineOffset += iLineHeight;
+    iLineHeight = 0;
+    ++iLines;
+    }
+
+// ---------------------------------------------------------------------------
+// JoinRangedVisuals
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::JoinRangedVisuals( TFsRangedVisual* aFirst, TFsRangedVisual* aSecond )
+    {
+    FUNC_LOG;
+/*        if ( aFirst->iRect.iTl.iX > aSecond->iRect.iTl.iX )
+            {
+            aFirst->iRect.iTl.iX = aSecond->iRect.iTl.iX;
+            }
+        else 
+            {
+            aFirst->iRect.iBr.iX = aSecond->iRect.iBr.iX;
+            }
+            */
+        TInt a = aFirst->iRect.iTl.iX;
+        TInt b = aFirst->iRect.iBr.iX;
+        TInt c = aSecond->iRect.iTl.iX;
+        TInt d = aSecond->iRect.iBr.iX;
+
+        TInt max = Max( Max(a, b), Max(d, c) );
+        TInt min = Min( Min(a, b), Min(d, c) );
+        aFirst->iRect.iTl.iX = min;
+        aFirst->iRect.iBr.iX = max;
+        aFirst->iStart = Min( aFirst->iStart, aSecond->iStart );
+        aFirst->iEnd = Max( aFirst->iEnd, aSecond->iEnd );
+    }
+
+// ---------------------------------------------------------------------------
+// GetCurrentLineOffset
+// ---------------------------------------------------------------------------
+TInt CFsTextViewerLayouter::GetCurrentLineOffset()
+    {
+    FUNC_LOG;
+    return iCurrentLineOffset;
+    }
+
+// ---------------------------------------------------------------------------
+// SetMargins
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetCurrentLineOffset( TInt aOffset )
+    {
+    FUNC_LOG;
+    iCurrentLineOffset = aOffset;
+    }
+
+// ---------------------------------------------------------------------------
+// SetMargins
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetMargins( const TInt aLeft, const TInt aRight )
+    {
+    FUNC_LOG;
+    iLeftMargin = aLeft;
+    iRightMargin = aRight;
+    if ( iMainDirection == TBidiText::ELeftToRight )
+        {
+        iLastCol = iLeftMargin;
+        }
+    else 
+        {
+        iLastCol = iDisplaySize.iWidth + iLeftMargin;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// SetHelper
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetHelper( CFsTextViewerCoordinator* aHelper )
+    {
+    FUNC_LOG;
+    iHelper = aHelper;
+    }
+
+// ---------------------------------------------------------------------------
+// SetNavigator
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetNavigator( CFsTextViewerVisualizerData* aNavigator )
+    {
+    FUNC_LOG;
+    iNavigator = aNavigator;
+    }
+
+// ---------------------------------------------------------------------------
+// Lines
+// ---------------------------------------------------------------------------
+TInt CFsTextViewerLayouter::Lines()
+    {
+    FUNC_LOG;
+    return iLines;
+    }
+
+// ---------------------------------------------------------------------------
+// EnableSmileys
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::EnableSmileys( TBool aEnable )
+    {
+    FUNC_LOG;
+    iSmileyEnabled = aEnable;
+    }
+
+// ---------------------------------------------------------------------------
+// SetPosition
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetPosition( TInt aLine, TInt aLineOffset )
+    {
+    FUNC_LOG;
+    iLines = aLine;
+    iCurrentLineOffset = aLineOffset;
+    }
+
+// ---------------------------------------------------------------------------
+// ChangeDirection
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::ChangeDirection( TBidiText::TDirectionality aDirection )
+    {
+    FUNC_LOG;
+    iMainDirection = aDirection;
+    if ( iMainDirection == TBidiText::ELeftToRight && iCurrentLineArray.Count() < 1 )
+		{
+		iLastCol = iLeftMargin;
+		}
+	else if ( iMainDirection == TBidiText::ERightToLeft && iCurrentLineArray.Count() < 1 )
+		{
+		iLastCol = iDisplaySize.iWidth + iLeftMargin;
+		}
+    }
+
+// ---------------------------------------------------------------------------
+// SetDirection
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::SetDirection( TBidiText::TDirectionality aDirection )
+    {
+    FUNC_LOG;
+    iMainDirection = aDirection;
+    if ( iMainDirection == TBidiText::ELeftToRight )
+        {
+        iLastCol = iLeftMargin;
+        }
+    else 
+        {
+        iLastCol = iDisplaySize.iWidth + iLeftMargin;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// GetDirection
+// ---------------------------------------------------------------------------
+TBidiText::TDirectionality CFsTextViewerLayouter::GetDirection()
+    {
+    FUNC_LOG;
+    return iMainDirection;
+    }
+
+// ---------------------------------------------------------------------------
+// IsNewLine
+// ---------------------------------------------------------------------------
+TBool CFsTextViewerLayouter::IsNewLine()
+    {
+    FUNC_LOG;
+    if ( iCurrentLineArray.Count() < 1 )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+void CFsTextViewerLayouter::ConstructL()
+    {
+    FUNC_LOG;
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CFsTextViewerLayouter
+// ---------------------------------------------------------------------------
+CFsTextViewerLayouter::CFsTextViewerLayouter( CAlfEnv* aEnv )
+    {
+    FUNC_LOG;
+    iScreenDev = CCoeEnv::Static()->ScreenDevice();
+    iEnv = aEnv;
+    iLines = 0;
+    iLowestPicPosition = 0;
+    iMainDirection = TBidiText::ELeftToRight;
+    }
+
+// ---------------------------------------------------------------------------
+// ReorderLineFromLeftL
+// ---------------------------------------------------------------------------
+TBool CFsTextViewerLayouter::ReorderLineFromLeftL( MFsRichTextObject* aObject, CAlfLayout* aLayout, CFsTextParser* aParser, TSize aObjectSize, TBool aRegisterSelects )
+    {
+    FUNC_LOG;
+//    TBool retVal = EFalse;
+//    TInt i = iCurrentLineArray.Count() - 1;
+//    TInt dX = aObjectSize.iWidth;
+//    TInt moveFrom = 0;
+//    TRect translatedObject;
+//    TRect origRect;
+//    while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+//        {
+//        translatedObject = iCurrentLineArray[i]->iRect;
+////        if ( iCurrentLineArray[i]->iIsText || iCurrentLineArray[i]->iSmiley )
+////            {
+//            iHelper->RemoveRect( iCurrentLineArray[i]->iRect );
+//            translatedObject.iTl.iX += dX;
+//            translatedObject.iBr.iX += dX;
+//            origRect = translatedObject;
+//            if ( iHelper->NextFreeCol( translatedObject, iMainDirection ) )
+//                {
+//                i = -100;
+//                }
+//            if ( origRect != translatedObject )
+//                {
+//                iCurrentLineArray[i]->iMoved = ETrue;
+//                }
+////            }
+//        moveFrom = i;
+//        --i;
+//        }
+//    if ( -101 == i )
+//        {
+//        ConstructLineL();
+//        retVal = AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+//        }
+//    else 
+//        {
+//        TFsRangedVisual* currentVisual; 
+//        currentVisual = PrepareRangedVisL( aObject, aLayout );
+//        if ( !aRegisterSelects )
+//            {
+//            currentVisual->iEmbed = EFalse;
+//            }
+//        currentVisual->iRect = TRect( iCurrentLineArray[moveFrom]->iRect.iTl, aObjectSize );
+//        iCurrentLineArray.Insert( currentVisual, moveFrom );
+//        for ( i = moveFrom + 1; i < iCurrentLineArray.Count(); ++i )
+//            {
+//            if ( iCurrentLineArray[i]->iIsText || iCurrentLineArray[i]->iSmiley )
+//                {
+//                iCurrentLineArray[i]->iRect.iTl.iX += dX;
+//                iCurrentLineArray[i]->iRect.iBr.iX += dX;
+//                }
+//            }
+//        if ( currentVisual->iRect.Height() > iLineHeight && aObject->GetType() != MFsRichTextObject::EFsTexture )
+//            {
+//            iLineHeight = currentVisual->iRect.Height();
+//            }
+//        }
+//    return retVal;
+    TBool retVal = EFalse;
+    TInt dX = aObjectSize.iWidth;
+    TInt moveFrom = 0;
+    TRect translatedObject;
+    TFsRangedVisual* visual = NULL;
+    TInt maxCol = 0;
+    // <cmail>TInt tmp = 0;
+    
+    TInt i = iCurrentLineArray.Count() - 1;
+    while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+        {
+        if ( !iCurrentLineArray[i]->iIsText )
+            {
+            iHelper->RemoveRect( iCurrentLineArray[i]->iRect );
+            }
+        --i;
+        }
+    i = iCurrentLineArray.Count() - 1;
+    while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+        {
+        translatedObject = TRect(iCurrentLineArray[i]->iRect.iTl, iCurrentLineArray[i]->iRect.iBr );
+        visual = iCurrentLineArray[i];
+            translatedObject.iTl.iX += dX;
+            translatedObject.iBr.iX += dX;
+        // <cmail> tmp = translatedObject.iTl.iX;
+        moveFrom = i;
+        if ( iHelper->NextFreeCol( translatedObject, TBidiText::ELeftToRight ) )
+                {
+                i = -100;
+                }
+        --i;
+        }
+    if ( -101 == i )
+        {
+        i = iCurrentLineArray.Count() - 1;
+        while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+            {
+            if ( !iCurrentLineArray[i]->iIsText )
+                {
+                translatedObject = TRect(iCurrentLineArray[i]->iRect.iTl, iCurrentLineArray[i]->iRect.iBr );
+                translatedObject.iTl.iX += dX;
+                translatedObject.iBr.iX += dX;
+                iHelper->RegisterObstacleL( iCurrentLineArray[i]->iRect );
+                }
+            --i;
+            }
+        ConstructLineL();
+        retVal = AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+        }
+    else 
+        {
+        TFsRangedVisual* currentVisual; 
+        currentVisual = PrepareRangedVisL( aObject, aLayout );
+        currentVisual->iMoved = EFalse;
+        if ( !aRegisterSelects )
+            {
+            currentVisual->iEmbed = EFalse;
+            }
+        
+        currentVisual->iRect = TRect( TPoint( iCurrentLineArray[moveFrom]->iRect.iTl.iX, iCurrentLineArray[moveFrom]->iRect.iTl.iY ), aObjectSize );
+        iCurrentLineArray.Insert( currentVisual, moveFrom );
+        
+        if ( aObject->GetType() == MFsRichTextObject::EFsTexture )
+            {
+            iHelper->RegisterObstacleL( currentVisual->iRect );
+            }
+        if ( currentVisual->iRect.Height() > iLineHeight && aObject->GetType() != MFsRichTextObject::EFsTexture )
+            {
+            iLineHeight = currentVisual->iRect.Height();
+            }
+        
+        for ( i = moveFrom + 1; i < iCurrentLineArray.Count(); ++i )
+                {
+//            if ( iCurrentLineArray[i]->iIsText || iCurrentLineArray[i]->iSmiley )
+//                {
+                visual = iCurrentLineArray[i];
+                iCurrentLineArray[i]->iRect.iTl.iX += dX;
+                iCurrentLineArray[i]->iRect.iBr.iX += dX;
+                iHelper->NextFreeCol( iCurrentLineArray[i]->iRect, TBidiText::ELeftToRight );
+                if ( !(visual->iIsText) )
+                    {
+                    iHelper->RegisterObstacleL( visual->iRect );
+                }
+               if ( visual->iRect.iBr.iX > maxCol )
+            {
+                   maxCol = visual->iRect.iBr.iX;
+                   }
+            }
+        }
+    iLastCol = maxCol;
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// ReorderLineFromRightL
+// ---------------------------------------------------------------------------
+TBool CFsTextViewerLayouter::ReorderLineFromRightL( MFsRichTextObject* aObject, CAlfLayout* aLayout, CFsTextParser* aParser, TSize aObjectSize, TBool aRegisterSelects )
+    {
+    FUNC_LOG;
+    TBool retVal = EFalse;
+    TInt dX = aObjectSize.iWidth;
+    TInt moveFrom = 0;
+    TRect translatedObject;
+    TFsRangedVisual* visual = NULL;
+    
+    TInt i = iCurrentLineArray.Count() - 1;
+    while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+        {
+        if ( !iCurrentLineArray[i]->iIsText )
+            {
+            iHelper->RemoveRect( iCurrentLineArray[i]->iRect );
+            }
+        --i;
+        }
+    i = iCurrentLineArray.Count() - 1;
+    while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+            {
+        translatedObject = TRect(iCurrentLineArray[i]->iRect.iTl, iCurrentLineArray[i]->iRect.iBr );
+        visual = iCurrentLineArray[i];
+            translatedObject.iTl.iX -= dX;
+            translatedObject.iBr.iX -= dX;
+        moveFrom = i;
+        if ( iHelper->NextFreeCol( translatedObject, TBidiText::ERightToLeft ) )
+                {
+                i = -100;
+                }
+        --i;
+        }
+    if ( -101 == i  )
+        {
+        i = iCurrentLineArray.Count() - 1;
+        while ( i >= 0 && iCurrentLineArray[i]->iDirection != iMainDirection )
+            {
+            if ( !iCurrentLineArray[i]->iIsText )
+                {
+                translatedObject = TRect(iCurrentLineArray[i]->iRect.iTl, iCurrentLineArray[i]->iRect.iBr );
+                translatedObject.iTl.iX -= dX;
+                translatedObject.iBr.iX -= dX;
+                iHelper->RegisterObstacleL( iCurrentLineArray[i]->iRect );
+                }
+            --i;
+            }
+        ConstructLineL();
+        retVal = AppendObjectL( aObject, aLayout, aParser, aRegisterSelects );
+        }
+    else 
+        {
+        TFsRangedVisual* currentVisual; 
+        currentVisual = PrepareRangedVisL( aObject, aLayout );
+        currentVisual->iMoved = EFalse;
+        if ( !aRegisterSelects )
+            {
+            currentVisual->iEmbed = EFalse;
+            }
+        
+        currentVisual->iRect = TRect( TPoint( iCurrentLineArray[moveFrom]->iRect.iBr.iX - dX, iCurrentLineArray[moveFrom]->iRect.iTl.iY ), aObjectSize );
+        iCurrentLineArray.Insert( currentVisual, moveFrom );
+        
+        if ( aObject->GetType() == MFsRichTextObject::EFsTexture )
+                {
+            iHelper->RegisterObstacleL( currentVisual->iRect );
+            }
+        if ( currentVisual->iRect.Height() > iLineHeight && aObject->GetType() != MFsRichTextObject::EFsTexture )
+            {
+            iLineHeight = currentVisual->iRect.Height();
+            }
+        
+        for ( i = moveFrom + 1; i < iCurrentLineArray.Count(); ++i )
+            {
+//            if ( iCurrentLineArray[i]->iIsText || iCurrentLineArray[i]->iSmiley )
+//                {
+                visual = iCurrentLineArray[i];
+                iCurrentLineArray[i]->iRect.iTl.iX -= dX;
+                iCurrentLineArray[i]->iRect.iBr.iX -= dX;
+                iHelper->NextFreeCol( iCurrentLineArray[i]->iRect, TBidiText::ERightToLeft );
+                if ( !(visual->iIsText) )
+                    {
+                    iHelper->RegisterObstacleL( visual->iRect );
+                    }
+            }
+        }
+    return retVal;
+    }
+