lafagnosticuifoundation/uigraphicsutils/gulsrc/GULBORDR.CPP
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lafagnosticuifoundation/uigraphicsutils/gulsrc/GULBORDR.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1002 @@
+// 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 <gdi.h>
+#include <gulbordr.h>
+#include <gulpanic.h>
+#include "GULSTD.H"
+#include "gullogicalborder.h"
+
+const TInt KTypeMask=0xFFFFFF00; 
+const TInt KAdjacentMask=0xF;
+
+const TInt KBorderTypeConversionMask=0x00FFFFFF;
+
+const TInt KBorderShift=0x8;
+const TInt KDepthBitPosition=0x4;
+const TInt KDepthShift=KBorderShift+KDepthBitPosition;
+
+//
+// Class MGulLogicalBorder
+//
+
+EXPORT_C void MGulLogicalBorder::MGulLogicalBorderReserved()
+	{
+	}
+
+//
+// Class GulTls
+//
+
+EXPORT_C void GulTls::SetLogicalBorder(MGulLogicalBorder* aLogicalBorder)
+	{
+	Dll::SetTls(REINTERPRET_CAST(TAny*,aLogicalBorder));
+	};
+
+EXPORT_C const MGulLogicalBorder* GulTls::LogicalBorder()
+	{
+	return REINTERPRET_CAST(const MGulLogicalBorder*,Dll::Tls());
+	}
+
+//
+// Class TGulBorder::TColors
+//
+
+EXPORT_C TGulBorder::TColors::TColors()
+	: iLine(KRgbBlack), iBack(KRgbWhite), iLight(KRgbWhite),
+	iMidlight(KRgbWhite), iMid(KRgbDarkGray), iDark(KRgbDarkGray), iInternalBack(KRgbWhite)
+/** Default constructor.
+
+Initialises the border colours to blacks, whites and greys. For details, see 
+the data members. */
+	{
+	}
+
+//
+// Class TGulBorder
+//
+
+EXPORT_C TGulBorder::TGulBorder()
+	: iType(0)
+/** Default constructor.
+
+The border type is initialised to zero (i.e. no border). */
+	{
+	}
+
+
+EXPORT_C TGulBorder::TGulBorder(TBorderType aType)
+	: iType(STATIC_CAST(TInt,aType)<<KBorderShift)
+/** Constructor with a border type.
+
+@param aType The border type. */
+    {
+	TranslateLegacyTypes();
+	}
+
+
+EXPORT_C TGulBorder::TGulBorder(TBorderType aType,TGulAdjacent aAdjacent)
+	: iType((STATIC_CAST(TInt,aType)<<KBorderShift)|aAdjacent)
+/** Constructor with a border type and an adjacency.
+
+@param aType The border type.
+@param aAdjacent Border adjacency. No outline is drawn for border sides that 
+are adjacent. */
+    {
+	TranslateLegacyTypes();
+	}
+
+EXPORT_C TGulBorder::TGulBorder(TInt aType)
+	: iType(aType<<KBorderShift)
+/** Constructor with a border type, specified as a TInt.
+
+@param aType The border type. Possible values are defined in the TBorderType 
+enumeration. */
+    {
+	TranslateLegacyTypes();
+	}
+
+
+EXPORT_C TGulBorder::TGulBorder(TInt aType,TGulAdjacent aAdjacent)
+	: iType((aType<<KBorderShift)|aAdjacent)
+/** Constructor with a border type, specified as a TInt, and a border adjacency.
+
+@param aType The border type.
+@param aAdjacent Border adjacency. No outline is drawn for border sides that 
+are adjacent. */
+    {
+	TranslateLegacyTypes();
+	}
+
+EXPORT_C void TGulBorder::SetType(TInt aType)
+/** Sets the border type.
+
+Descriptive borders use one of the values from the TBorderType enum. Logical 
+borders use one of the TLogicalType values. Custom border types can be created 
+by selecting one value from each of the enums T3DStyle and TConstructionStyle, 
+one or more values from each of the enums TOutlineStyle and TInlineStyle, 
+one or more values from the enums TThickness and TRounding and ORing all these 
+values together.
+
+@param aType The border type. */
+    {
+    iType&=(~KTypeMask);
+    iType|=(aType<<KBorderShift);
+
+	TranslateLegacyTypes();
+    }
+
+//
+// Translates legacy border types which now affect the adjacency as well as the border
+// primitive type.
+//
+void TGulBorder::TranslateLegacyTypes()
+	{
+	TInt internalType=InternalType();
+
+	if(internalType&EWithOverlap)
+		{
+		if(internalType&EHorizontal)
+			SetAdjacent(EGulAdjTop|EGulAdjBottom);
+		else
+			SetAdjacent(EGulAdjLeft|EGulAdjRight);
+	    iType|=(EWithOutline<<KBorderShift);
+		}
+	}
+
+
+EXPORT_C TInt TGulBorder::Type() const
+/** Gets the border type. 
+
+@return The border type. This is one of the values from the TBorderType (for 
+descriptive borders) or TLogicalType (for logical borders) enums. */
+    {
+    return (KBorderTypeConversionMask&((iType&KTypeMask)>>KBorderShift));
+    }
+
+EXPORT_C void TGulBorder::SetAdjacent(TInt aAdjacent)
+/** Sets the border adjacency.
+
+No outline is drawn for border sides that are adjacent.
+
+@param aAdjacent The border adjacency. For possible values, see the TGulAdjacent 
+enum. */
+    {
+    iType&=(~KAdjacentMask);
+    iType|=(KAdjacentMask & aAdjacent);
+    }
+
+inline TInt TGulBorder::Depth() const
+	{
+	return (iType>>KDepthShift)&0x3;
+	}
+
+EXPORT_C TBool TGulBorder::HasBorder() const
+/** Tests whether a border is present.
+
+No border is present if its type is ENoBorder.
+
+@return True if a border is present, otherwise false. */
+	{
+	return (!(((iType&KTypeMask)>>KBorderShift)==ENoBorder));
+	}
+
+
+EXPORT_C TInt TGulBorder::Adjacent() const
+/** Gets the border adjacency.
+
+No outline is drawn for border sides that are adjacent.
+
+@return The border adjacency. For possible values, see the TGulAdjacent enum. */
+	{
+	return iType&KAdjacentMask;
+	}
+
+
+inline TBool TGulBorder::IsSunken() const
+	{
+	return (iType>>KBorderShift)&ESunken;
+	}
+
+//
+// Returns the innner rectangular area of the outline
+// Simply returns the outer rectangle if there is no outline 
+//
+TRect TGulBorder::OutlineInnerRect(const TRect& aOuterRect) const
+    {
+	if (!(InternalType()&EWithOutline))
+		return aOuterRect;
+	
+	TRect inner=aOuterRect;
+    TMargins margins=OutlineMargins();
+    inner.iTl.iX+=margins.iLeft;
+    inner.iTl.iY+=margins.iTop;
+    inner.iBr.iX-=margins.iRight;
+    inner.iBr.iY-=margins.iBottom;
+    return inner;
+    }
+
+//
+// Returns the number of rounding pixels for the start of the mid-tone colored part of the border.
+//
+TInt TGulBorder::BorderRounding() const
+	{
+	TInt rounding=Rounding();
+	if (InternalType()&EWithOutline)
+		rounding--;
+	return (rounding<0 ? 0 : rounding);
+	}
+
+//
+// Returns the number of rounding pixels at the inline.
+//
+TInt TGulBorder::InlineRounding() const
+	{
+	TInt rounding=BorderRounding();
+	rounding-=Thickness();
+	return (rounding<0 ? 0 : rounding);
+	}
+
+EXPORT_C TMargins TGulBorder::Margins() const
+/** Returns the border margins.
+
+The border margins are four integers that represent the widths in pixels of 
+the top, bottom, left and right hand sides of the border.
+
+If the border is a logical border, then calculating the margins is delegated 
+to its implementation of MGulLogicalBorder::Margins().
+
+Otherwise, the margins are calculated by adding together the single pixel 
+border outline, if present (this is zero for adjacent sides), the border thickness 
+(containing the mid-tone highlights and lowlights), and the single pixel interior 
+outline, if present.
+
+@return The border margins. */
+    {
+	// Delegates the margin size determination to TLS instance of MGulLogicalBorder if logical border
+	if (InternalType()&ELogical)
+		{
+		const MGulLogicalBorder* logicalBorder=GulTls::LogicalBorder();
+		__ASSERT_DEBUG(logicalBorder,Panic(EEgulPanicNullTls));
+		return logicalBorder ? logicalBorder->Margins(*this) : TMargins();
+		}
+
+    TMargins margins=OutlineMargins();
+	
+	TMargins borderMargins=BorderMargins();
+
+	margins.iTop+=borderMargins.iTop;
+	margins.iLeft+=borderMargins.iLeft;
+	margins.iRight+=borderMargins.iRight;
+	margins.iBottom+=borderMargins.iBottom;
+
+	TMargins inlineMargins=InlineMargins();
+
+	margins.iTop+=inlineMargins.iTop;
+	margins.iLeft+=inlineMargins.iLeft;
+	margins.iRight+=inlineMargins.iRight;
+	margins.iBottom+=inlineMargins.iBottom;
+
+	return margins;
+    }
+
+//
+// Returns the margins for the single pixel outline only
+// Margins are zero if the border has no outline.
+// There is no margin on sides which are adjacent.
+//
+TMargins TGulBorder::OutlineMargins() const
+    {
+	TMargins margins;
+
+	margins.iTop=margins.iLeft=0;
+	margins.iBottom=margins.iRight=0;
+
+	if (!(InternalType()&EWithOutline))
+		return margins;
+
+	if (!(iType&EGulAdjLeft))
+		margins.iLeft+=1;
+
+	if (!(iType&EGulAdjTop))
+		margins.iTop+=1;
+
+	if (!(iType&EGulAdjRight))
+		margins.iRight+=1;
+
+	if (!(iType&EGulAdjBottom))
+		margins.iBottom+=1;
+
+    return margins;
+	}
+
+
+TMargins TGulBorder::BorderMargins() const
+    {
+    TMargins margins;
+
+	TInt topLeftMargin=0;
+	TInt bottomRightMargin=0;
+
+	if (InternalType()&EOneStep)
+		topLeftMargin=bottomRightMargin=Thickness();
+	else if (InternalType()&ETwoStep || InternalType()&EInvertedTwoStep)
+		{
+		if((InternalType()&ERaised && !(InternalType()&EInvertedTwoStep)) || (InternalType()&ESunken && (InternalType()&EInvertedTwoStep)))
+			{
+			topLeftMargin=1;
+			bottomRightMargin=Thickness()+1;
+			}
+		else
+			{
+			topLeftMargin=Thickness()+1;
+			bottomRightMargin=1;
+			}
+		}
+	else if (InternalType()&EThreeStep)
+		topLeftMargin=bottomRightMargin=Thickness()+1;
+
+	margins.iTop=topLeftMargin;
+	margins.iLeft=topLeftMargin;
+	margins.iBottom=bottomRightMargin;
+	margins.iRight=bottomRightMargin;
+
+	return margins;
+    }
+
+TMargins TGulBorder::InlineMargins() const
+    {
+    TMargins margins;
+
+	TInt marginWidth = 0;
+
+	if (InternalType()&EWithInline)
+		marginWidth++;
+
+	margins.iTop=marginWidth;
+	margins.iLeft=marginWidth;
+	margins.iBottom=marginWidth;
+	margins.iRight=marginWidth;
+	
+	return margins;
+    }
+
+EXPORT_C TSize TGulBorder::SizeDelta() const
+/** Returns the size difference between the inner and outer rectangles of the border.
+
+@return The size difference between the inner and outer rectangles. */
+    {
+    TMargins margins=Margins();
+    return TSize(margins.iLeft+margins.iRight,margins.iTop+margins.iBottom);
+    }
+
+EXPORT_C TRect TGulBorder::OuterRect(const TRect& aInnerRect) const
+/** Returns the rectangular area required to accommodate the inner rectangle aInnerRect
+and the border.
+
+@param aInnerRect The inner rectangular area.
+@return The enclosing rectangular area. */
+    {
+    TRect outer=aInnerRect;
+    TMargins margins=Margins();
+    outer.iTl.iX-=margins.iLeft;
+    outer.iTl.iY-=margins.iTop;
+    outer.iBr.iX+=margins.iRight;
+    outer.iBr.iY+=margins.iBottom;
+    return outer;
+    }
+
+EXPORT_C TRect TGulBorder::InnerRect(const TRect& aOuterRect) const
+/** Returns the rectangular area enclosed by the border.
+
+@param aOuterRect The border's containing rectangle.
+@return The inner rectangle. */
+    {
+    TRect inner=aOuterRect;
+    TMargins margins=Margins();
+    inner.iTl.iX+=margins.iLeft;
+    inner.iTl.iY+=margins.iTop;
+    inner.iBr.iX-=margins.iRight;
+    inner.iBr.iY-=margins.iBottom;
+    return inner;
+    }
+
+
+TRect TGulBorder::BorderInnerRect(const TRect& aOuterRect) const
+    {
+    TRect inner=aOuterRect;
+    TMargins margins=BorderMargins();
+    inner.iTl.iX+=margins.iLeft;
+    inner.iTl.iY+=margins.iTop;
+    inner.iBr.iX-=margins.iRight;
+    inner.iBr.iY-=margins.iBottom;
+    return inner;
+    }
+
+EXPORT_C void TGulBorder::Draw(CGraphicsContext& aGc,const TRect& aRect) const
+/** Draws the border using a graphics context, inside a containing rectangle, and 
+using default values for the border colours. 
+
+For details of the default border colours, see class TColors.
+
+This function does nothing if the border type is ENone. If the border is a 
+logical border, drawing is delegated to its implementation of MGulLogicalBorder::Draw().
+
+@param aGc The graphics context to draw through.
+@param aRect The containing rectangle. This defines the border's outline, i.e. 
+the border is drawn inside this rectangle.
+@see MGulLogicalBorder::Draw() */
+    {
+	TColors borderColors;
+	Draw(aGc,aRect,borderColors);
+    }
+
+EXPORT_C void TGulBorder::Draw(CGraphicsContext& aGc,const TRect& aRect, const TColors& aBorderColors) const
+/** Draws the border using a graphics context, inside a containing rectangle, and 
+using the border colours specified.
+
+This function does nothing if the border type is ENone. If the border is a 
+logical border, drawing is delegated to its implementation of MGulLogicalBorder::Draw().
+
+@param aGc The graphics context to draw through.
+@param aRect The containing rectangle. This defines the border's outline, i.e. 
+the border is drawn inside this rectangle.
+@param aBorderColors The border colours.
+@see MGulLogicalBorder::Draw() */
+    {
+    if (!HasBorder())
+        return;
+	
+	// Delegate drawing of logical border to TLS instance of MGulLogicalBorder if logical border
+	if (InternalType()&ELogical)
+		{
+		const MGulLogicalBorder* logicalBorder=GulTls::LogicalBorder();
+		__ASSERT_DEBUG(logicalBorder,Panic(EEgulPanicNullTls));
+		if(logicalBorder)
+			{
+			logicalBorder->Draw(*this,aGc,aRect,aBorderColors);
+			}
+		return;
+		}
+
+	TRect workingRect=aRect;
+	DrawOutline(aGc,workingRect,aBorderColors.iLine);
+
+	if (Thickness())
+		{
+		workingRect=OutlineInnerRect(workingRect);
+
+		if (InternalType()&EOneStep)
+			DrawOneStep(aGc,workingRect,aBorderColors.iMidlight,aBorderColors.iMid);
+		else if (InternalType()&ETwoStep)
+			DrawTwoStep(aGc,workingRect,aBorderColors.iLight,aBorderColors.iMidlight,aBorderColors.iMid,aBorderColors.iDark);
+		else if (InternalType()&EInvertedTwoStep)
+			DrawInvertedTwoStep(aGc,workingRect,aBorderColors.iLight,aBorderColors.iMidlight,aBorderColors.iMid,aBorderColors.iDark);
+		else if (InternalType()&EThreeStep)
+			DrawThreeStep(aGc,workingRect,aBorderColors.iBack,aBorderColors.iLight,aBorderColors.iMidlight,aBorderColors.iMid,aBorderColors.iDark);
+		}
+
+	workingRect=BorderInnerRect(workingRect);
+	DrawInline(aGc,workingRect,aBorderColors.iLine);
+    }
+
+
+void TGulBorder::DrawInline(CGraphicsContext& aGc,const TRect& aRect,TRgb aColor) const
+    {
+	if (!(InternalType()&EWithInline))
+		return;
+
+	TInt rounding=InlineRounding();
+
+	DrawTopLeft(aGc,aRect,aColor,rounding);
+	DrawBottomRight(aGc,aRect,aColor,rounding);
+	}
+
+//
+// Draws the optional single pixel outline
+// If there is no outline no drawing is done.
+//
+void TGulBorder::DrawOutline(CGraphicsContext& aGc,const TRect& aRect,TRgb aColor) const
+    {
+	if (!(InternalType()&EWithOutline))
+		return;
+
+	// legacy border types color support
+	TRgb color;
+	const TInt internalType=InternalType();
+	if(internalType&EBlack)
+		color=KRgbBlack;
+	else if(internalType&EGray)
+		color=KRgbGray;
+	else
+		color=aColor;
+	//
+
+	aGc.SetPenColor(color);
+	if (internalType&EDottedOutline)
+		aGc.SetPenStyle(CGraphicsContext::EDottedPen);
+
+	TInt rounding=Rounding();
+
+	if (rounding)
+		{
+		DrawTopLeft(aGc,aRect,color,rounding);
+		DrawBottomRight(aGc,aRect,color,rounding);
+		}
+	else
+		DrawRectOutline(aGc,aRect);
+
+	if (internalType&EDottedOutline)
+		aGc.SetPenStyle(CGraphicsContext::ESolidPen);
+	}
+
+
+//
+// Draws the rectangular version of the outline
+// The outline is not drawn on sides which are adjacent
+//
+void TGulBorder::DrawRectOutline(CGraphicsContext& aGc,const TRect& aRect) const
+    {
+	// left
+	if (!(iType&EGulAdjLeft))
+		aGc.DrawLine(TPoint(aRect.iTl.iX,aRect.iBr.iY-1),TPoint(aRect.iTl.iX,aRect.iTl.iY-1));
+
+	// top
+	if (!(iType&EGulAdjTop))
+		aGc.DrawLine(TPoint(aRect.iTl.iX,aRect.iTl.iY),TPoint(aRect.iBr.iX,aRect.iTl.iY));
+
+	// right
+	if (!(iType&EGulAdjRight))
+		aGc.DrawLine(TPoint(aRect.iBr.iX-1,aRect.iTl.iY),TPoint(aRect.iBr.iX-1,aRect.iBr.iY));
+	
+	// bottom
+	if (!(iType&EGulAdjBottom))
+		aGc.DrawLine(TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1),TPoint(aRect.iTl.iX-1,aRect.iBr.iY-1));
+	}
+
+//
+// Draws the one step border type.
+// This consists of repeated one pixel frames drawn in the mid-tone highlight and lowlight colors
+//	
+void TGulBorder::DrawOneStep(CGraphicsContext& aGc,const TRect& aRect,TRgb aMidlight,TRgb aMid) const
+    {	
+	TRect workingRect = aRect;
+
+	TRgb topOneColor=aMidlight;
+	TRgb bottomOneColor=aMid;
+
+	if (InternalType()&ESunken)
+		{
+		topOneColor=aMid;
+		bottomOneColor=aMidlight;
+		}
+
+	if (InternalType()&EFlat)
+		topOneColor=aMid;
+
+	TInt rounding=BorderRounding();
+
+	for(int i=0;i<Thickness();i++)
+		{
+		DrawBottomRight(aGc,workingRect,bottomOneColor,rounding);
+		DrawTopLeft(aGc,workingRect,topOneColor,rounding);
+		rounding--;
+		workingRect.Shrink(1,1);
+		}
+	}
+
+//
+// Draws the two step border type.
+// The outer closed frame is drawn in highlihgt and lowlight colors
+// A repeating one pixel half-frame is then drawn in either the mid-tone highlight or lowlight color.
+//
+void TGulBorder::DrawTwoStep(CGraphicsContext& aGc,const TRect& aRect,TRgb aLight,TRgb aMidlight,TRgb aMid,TRgb aDark) const
+    {	
+	TRect workingRect = aRect;
+	TBool drawTopLeftOnly=EFalse;
+
+	TRgb topOneColor=aMid;
+	TRgb bottomOneColor=aMid;
+	TRgb topTwoColor=aLight;
+	TRgb bottomTwoColor=aDark;
+
+	if (InternalType()&ESunken)
+		{
+		topTwoColor=aDark;
+		bottomTwoColor=aLight;
+		drawTopLeftOnly=ETrue;
+		}
+
+	if (InternalType()&EFlat)
+		{
+		topTwoColor=aMidlight;
+		bottomTwoColor=aMidlight;
+		drawTopLeftOnly=ETrue;
+		}
+	
+	TInt rounding=BorderRounding();
+
+	DrawBottomRight(aGc,workingRect,bottomTwoColor,rounding);
+	DrawTopLeft(aGc,workingRect,topTwoColor,rounding);
+	rounding--;
+	if (drawTopLeftOnly)
+		{
+		workingRect.iTl.iX+=1;
+		workingRect.iTl.iY+=1;
+		workingRect.iBr.iY-=1;
+		}
+	else
+		{
+		workingRect.iTl.iX+=1;
+		workingRect.iBr.iX-=1;
+		workingRect.iBr.iY-=1;
+		}
+
+	for(int i=0;i<Thickness();i++)
+		{
+		if (drawTopLeftOnly)
+			{
+			DrawTopLeft(aGc,workingRect,topOneColor,rounding);
+			rounding--;
+			workingRect.iTl.iX+=1;
+			workingRect.iTl.iY+=1;
+			}
+		else
+			{	
+			DrawBottomRight(aGc,workingRect,bottomOneColor,rounding);
+			rounding--;
+			workingRect.iBr.iX-=1;
+			workingRect.iBr.iY-=1;
+			}
+		}
+	}
+
+//
+// Draw the inverted two step border type.
+// As above the outer closed frame is drawn in highlihgt and lowlight colors
+// A repeating one pixel half-frame is then drawn in either the mid-tone highlight or lowlight color.
+// The difference is that the raised border show using top-left midlight etc.
+// Another small difference is that sunken has light, midlight colors swapped
+//
+void TGulBorder::DrawInvertedTwoStep(CGraphicsContext& aGc,const TRect& aRect,TRgb aLight,TRgb aMidlight,TRgb aMid,TRgb aDark) const
+    {	
+	TRect workingRect = aRect;
+	TBool drawTopLeftOnly=ETrue;
+
+	TRgb topOneColor=aMidlight;
+	TRgb bottomOneColor=aMidlight;
+	TRgb topTwoColor=aLight;
+	TRgb bottomTwoColor=aDark;
+
+	if (InternalType()&ESunken)
+		{
+		topTwoColor=aDark;
+		bottomTwoColor=aMidlight;
+		bottomOneColor=aLight;
+		drawTopLeftOnly=EFalse;
+		}
+
+	if (InternalType()&EFlat)
+		{
+		topTwoColor=aMid;
+		bottomTwoColor=aMid;
+		drawTopLeftOnly=EFalse;
+		}
+	
+	TInt rounding=BorderRounding();
+
+	DrawBottomRight(aGc,workingRect,bottomTwoColor,rounding);
+	DrawTopLeft(aGc,workingRect,topTwoColor,rounding);
+	rounding--;
+	if (drawTopLeftOnly)
+		{
+		workingRect.iTl.iX+=1;
+		workingRect.iTl.iY+=1;
+		workingRect.iBr.iY-=1;
+		}
+	else
+		{
+		workingRect.iTl.iX+=1;
+		workingRect.iBr.iX-=1;
+		workingRect.iBr.iY-=1;
+		}
+
+	for(int i=0;i<Thickness();i++)
+		{
+		if (drawTopLeftOnly)
+			{
+			DrawTopLeft(aGc,workingRect,topOneColor,rounding);
+			rounding--;
+			workingRect.iTl.iX+=1;
+			workingRect.iTl.iY+=1;
+			}
+		else
+			{	
+			DrawBottomRight(aGc,workingRect,bottomOneColor,rounding);
+			rounding--;
+			workingRect.iBr.iX-=1;
+			workingRect.iBr.iY-=1;
+			}
+		}
+	}
+
+//
+// Draws the three step border type.
+// The outer frame is drawn in combined colors
+// A repeating one pixel frame is then drawn in the mid-tone highlight and lowlight colors.
+// The inner frame is drawn in combined colors
+//
+void TGulBorder::DrawThreeStep(CGraphicsContext& aGc,const TRect& aRect,TRgb aBack,TRgb aLight,TRgb aMidlight,TRgb aMid,TRgb aDark) const
+    {
+	TRect workingRect = aRect;
+
+	TRgb topOneColor=aBack;
+	TRgb bottomOneColor=aMid;
+	TRgb topTwoColor=aLight;
+	TRgb bottomTwoColor=aDark;
+
+	if (InternalType()&ESunken)
+		{
+		topOneColor=aMid;
+		bottomOneColor=aBack;
+		topTwoColor=aDark;
+		bottomTwoColor=aLight;
+		}
+
+	if (InternalType()&EFlat)
+		{
+		topOneColor=aMid;
+		bottomOneColor=aMid;
+		topTwoColor=aMidlight;
+		bottomTwoColor=aMidlight;
+		}
+	
+	TInt rounding=BorderRounding();
+
+	DrawBottomRight(aGc,workingRect,bottomTwoColor,rounding);
+	DrawTopLeft(aGc,workingRect,topOneColor,rounding);
+	rounding--;
+	workingRect.Shrink(1,1);
+
+	for(int i=1;i<Thickness();i++)
+		{
+		DrawBottomRight(aGc,workingRect,bottomOneColor,rounding);
+		DrawTopLeft(aGc,workingRect,topOneColor,rounding);
+		rounding--;
+		workingRect.Shrink(1,1);
+		}
+
+	DrawBottomRight(aGc,workingRect,bottomOneColor,rounding);
+	DrawTopLeft(aGc,workingRect,topTwoColor,rounding);
+	}
+
+//
+// Draws the top left portion of the one pixel border frame
+//
+void TGulBorder::DrawTopLeft(CGraphicsContext& aGc,const TRect& aRect,TRgb aColor,const TInt aRounding) const
+    {
+	TInt xOffset=0;
+	TInt yOffset=0;
+
+	if ((InternalType()&EFlat) || (InternalType()&ERaised))
+		xOffset=1;
+
+	if(InternalType()&ESunken)
+		yOffset=1;
+
+	if((InternalType()&EFlat) && (InternalType()&EThreeStep))
+		{
+		xOffset=1;
+		yOffset=1;
+		}
+
+	aGc.SetPenColor(aColor);
+
+	if (aRounding>0)
+		DrawRoundedTopLeft(aGc,aRect,aRounding);
+	else
+		{
+		// left
+		aGc.DrawLine(TPoint(aRect.iTl.iX,aRect.iTl.iY),TPoint(aRect.iTl.iX,aRect.iBr.iY-yOffset));
+		// top
+		aGc.DrawLine(TPoint(aRect.iTl.iX,aRect.iTl.iY),TPoint(aRect.iBr.iX-xOffset,aRect.iTl.iY));
+		}
+	}
+
+//
+// Draws a rounded off version top left portion of the one pixel border frame
+//
+void TGulBorder::DrawRoundedTopLeft(CGraphicsContext& aGc,const TRect& aRect,const TInt aRounding) const
+    {
+	// left
+	aGc.DrawLine(TPoint(aRect.iTl.iX,aRect.iTl.iY+aRounding),TPoint(aRect.iTl.iX,aRect.iBr.iY-aRounding));
+	// top left corner
+	DrawRoundedCorner(aGc,TPoint(aRect.iTl.iX,aRect.iTl.iY+aRounding),aRounding,ETrue,ETrue);
+	// top
+	aGc.DrawLine(TPoint(aRect.iTl.iX+aRounding,aRect.iTl.iY),TPoint(aRect.iBr.iX-aRounding,aRect.iTl.iY));
+	}
+
+//
+// Draws the bottom right portion of the one pixel border frame
+//
+void TGulBorder::DrawBottomRight(CGraphicsContext& aGc,const TRect& aRect,TRgb aColor,const TInt aRounding) const
+    {
+	TInt xOffset=0;
+	TInt yOffset=0;
+
+	if ((InternalType()&EFlat) || (InternalType()&ERaised))
+		xOffset=1;
+
+	if(InternalType()&ESunken)
+		yOffset=1;
+
+	if((InternalType()&EFlat) && (InternalType()&EThreeStep))
+		{
+		xOffset=1;
+		yOffset=1;
+		}
+
+	aGc.SetPenColor(aColor);
+
+	if (aRounding>0)
+		DrawRoundedBottomRight(aGc,aRect,aRounding);
+	else
+		{
+		// right
+		aGc.DrawLine(TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1),TPoint(aRect.iBr.iX-1,aRect.iTl.iY-1+yOffset));
+		// bottom
+		aGc.DrawLine(TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1),TPoint(aRect.iTl.iX-1+xOffset,aRect.iBr.iY-1));
+		}
+	}
+
+//
+// Draws a rounded off version of the bottom right portion of the one pixel border frame
+//
+void TGulBorder::DrawRoundedBottomRight(CGraphicsContext& aGc,const TRect& aRect,const TInt aRounding) const
+    {
+	// top right corner
+	DrawRoundedCorner(aGc,TPoint(aRect.iBr.iX-1,aRect.iTl.iY+aRounding),aRounding,ETrue,EFalse);	
+	// right
+	aGc.DrawLine(TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1-aRounding),TPoint(aRect.iBr.iX-1,aRect.iTl.iY-1+aRounding));
+	// bottom right corner
+	DrawRoundedCorner(aGc,TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1-aRounding),aRounding,EFalse,EFalse);
+	// bottom
+	aGc.DrawLine(TPoint(aRect.iBr.iX-1-aRounding,aRect.iBr.iY-1),TPoint(aRect.iTl.iX-1+aRounding,aRect.iBr.iY-1));
+	// bottom left corner
+	DrawRoundedCorner(aGc,TPoint(aRect.iTl.iX,aRect.iBr.iY-1-aRounding),aRounding,EFalse,ETrue);
+	}
+
+//
+// Implements the rounded corner drawing algorithm
+// Rounded corners are convex, nestable, symmetric, favour drawing in two pixel steps and favour filling outer pixels 
+// Corners are drawn from aStart, breaching a gap of size (aRoundedLength,aRoundedLength)
+// and use aUp and aRight to determine direction
+// Drawing is done vertically from the start and horizontaly from the end till they meet in the middle.
+//
+void TGulBorder::DrawRoundedCorner(CGraphicsContext& aGc,const TPoint& aStart,const TInt aRoundedLength, const TBool aUp, const TBool aRight) const
+	{
+	if(aRoundedLength<2)
+		return;
+
+	TPoint end=aStart;
+	end.iX += aRight ? aRoundedLength : -aRoundedLength;
+	end.iY += aUp ? -aRoundedLength : aRoundedLength;
+
+	// draw from start
+	aGc.MoveTo(aStart);
+	TInt steps=aRoundedLength/3;
+	TInt count=0;
+	while(count<steps)
+		{
+		aRight ? aGc.MoveBy(TPoint(1,0)) : aGc.MoveBy(TPoint(-1,0));
+		aUp ? aGc.MoveBy(TPoint(0,-1)) : aGc.MoveBy(TPoint(0,1));		
+		aUp ? aGc.DrawLineBy(TPoint(0,-2)) : aGc.DrawLineBy(TPoint(0,2));
+		aUp ? aGc.MoveBy(TPoint(0,1)) : aGc.MoveBy(TPoint(0,-1));
+		count++;
+		}
+
+	// draw from end
+	aGc.MoveTo(end);
+	count=0;
+	while(count<steps)
+		{
+		aUp ? aGc.MoveBy(TPoint(0,1)) : aGc.MoveBy(TPoint(0,-1));
+		aRight ? aGc.MoveBy(TPoint(-1,0)) : aGc.MoveBy(TPoint(1,0));
+		aRight ? aGc.DrawLineBy(TPoint(-2,0)) : aGc.DrawLineBy(TPoint(2,0));
+		aRight ? aGc.MoveBy(TPoint(1,0)) : aGc.MoveBy(TPoint(-1,0));
+		count++;
+		}
+	
+	// draw mid point if necessary
+	if(aRoundedLength%3==2)
+		{
+		aUp ? aGc.MoveBy(TPoint(0,1)) : aGc.MoveBy(TPoint(0,-1));
+		aRight ? aGc.MoveBy(TPoint(-1,0)) : aGc.MoveBy(TPoint(1,0));
+		aRight ? aGc.DrawLineBy(TPoint(-1,0)) : aGc.DrawLineBy(TPoint(1,0));
+		}
+	}
+
+//
+// Returns the thickness of the part of the border which is colored in the mid-tone
+// highlights and lowlights. In general, this is not the same as the size of the border
+// margins.
+EXPORT_C TInt TGulBorder::Thickness() const
+/**
+@publishedPartner
+@deprecated
+*/
+	{
+	TInt thickness=0;
+
+	if (InternalType()&EAddOnePixel)
+		thickness++;
+
+	if (InternalType()&EAddTwoPixels)
+		thickness+=2;
+
+	if (InternalType()&EAddFourPixels)
+		thickness+=4;
+
+	return thickness;
+	}
+
+//
+// Returns the number of pixels which will be chipped of the corners of a border rectangle
+// to be joined by an rounding arc. The rounding is determined by the border type.
+//
+EXPORT_C TInt TGulBorder::Rounding() const
+/**
+@internalComponent
+@released
+*/
+	{
+	TInt rounding=0;
+	
+	if (InternalType()&EAddOneRoundingPixel)
+		rounding++;
+
+	if (InternalType()&EAddTwoRoundingPixels)
+		rounding+=2;
+
+	if (InternalType()&EAddFourRoundingPixels)
+		rounding+=4;
+
+	return rounding;
+	}
+
+
+//
+// Returns the width of the smallest margin possible, given the rounding of the border rectangle.
+// This is a simple mapping for the rounding range 0-7 and the current drawing algorithm,
+//
+TInt TGulBorder::RoundingMargin(const TInt aRoundedLength) const
+	{
+	TInt roundingMargin=0;
+
+	if (aRoundedLength>4)
+		roundingMargin=2;
+	else if (aRoundedLength>1)
+		roundingMargin=1;
+
+	return roundingMargin;
+	}
+
+
+inline TInt TGulBorder::InternalType() const
+	{
+	return (iType>>KBorderShift);
+	}
+
+