diff -r 000000000000 -r 2f259fa3e83a lafagnosticuifoundation/uigraphicsutils/gulsrc/GULBORDR.CPP --- /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 +#include +#include +#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)); + } + +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;i0) + 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(count4) + roundingMargin=2; + else if (aRoundedLength>1) + roundingMargin=1; + + return roundingMargin; + } + + +inline TInt TGulBorder::InternalType() const + { + return (iType>>KBorderShift); + } + +