diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiGradientBrush.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiGradientBrush.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,300 @@ +/* +* Copyright (c) 2006-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: Implementation of CHuiLinearGradientBrush - a Brush that is +* able to draw linear color gradients. +* +*/ + + + +#include "uiacceltk/HuiGradientBrush.h" // Class definition +#include "uiacceltk/HuiDrawing.h" +#include "uiacceltk/HuiVisual.h" +#include "uiacceltk/HuiUtil.h" + + +EXPORT_C CHuiGradientBrush* CHuiGradientBrush::NewL() + { + CHuiGradientBrush* self = NewLC(); + CleanupStack::Pop(); + return self; + } + + +EXPORT_C CHuiGradientBrush* CHuiGradientBrush::NewLC() + { + CHuiGradientBrush* self = new (ELeave) CHuiGradientBrush(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + + +CHuiGradientBrush::CHuiGradientBrush() + : CHuiBrush(), + iDirection(EDirectionRight) + { + } + + +void CHuiGradientBrush::ConstructL() + { + SColor defaultColor; + defaultColor.iPosition = 0; + defaultColor.iColor = KRgbWhite; + defaultColor.iOpacity = 1.0; + User::LeaveIfError(iColors.Append(defaultColor)); + } + + +CHuiGradientBrush::~CHuiGradientBrush() + { + iColors.Reset(); + } + + +EXPORT_C void CHuiGradientBrush::SetDirection(TDirection aDirection) + { + iDirection = aDirection; + SetChanged(); + } + + +void CHuiGradientBrush::Draw(CHuiGc& aGc, const MHuiBrushGuide& aGuide) const + { + TRect content = aGuide.BrushRect(); + TReal32 opacity = aGuide.BrushOpacity() * iOpacity.Now(); + + if(opacity <= 0) + { + return; + } + + TBool useTexture = EFalse; + TReal32 texCoords[8]; + THuiRealRect texCoordRect; + + aGc.SetPenAlpha(TInt(opacity * 255)); + + if(iImage.HasTexture()) + { + useTexture = ETrue; + iImage.GetTexCoords(texCoords); + aGc.Enable(CHuiGc::EFeatureTexturing); + iImage.Texture().Bind(); + } + else + { + aGc.Disable(CHuiGc::EFeatureTexturing); + } + + // Optimization for gradientbrush (MNIA-7G79GD). Draws a simple rect with one color + // if there really isn't anything to gradient. + // Updated optimization to work with single semi-transparent color + if(iColors.Count() == 1 && !iImage.HasTexture() && (iColors[0].iOpacity * opacity) >= 1 ) + { + aGc.SetPenColor(iColors[0].iColor); + aGc.DrawRect(content); + return; + } + + aGc.Enable(CHuiGc::EFeatureBlending); + + TInt segments = iColors.Count() - 1; + if(segments <= 0) + { + segments = 1; + } + + TInt length = content.Width(); + TBool isHoriz = ETrue; + TBool invert = EFalse; + CHuiGc::TGradientType gradientType; + + switch(iDirection) + { + default: + case EDirectionUp: + gradientType = CHuiGc::EGradientLinearUp; + isHoriz = EFalse; + length = content.Height(); + invert = ETrue; + break; + + case EDirectionDown: + gradientType = CHuiGc::EGradientLinearDown; + isHoriz = EFalse; + length = content.Height(); + break; + + case EDirectionRight: + gradientType = CHuiGc::EGradientLinearRight; + break; + + case EDirectionLeft: + gradientType = CHuiGc::EGradientLinearLeft; + invert = ETrue; + break; + } + + for(TInt start = 0; start < segments; ++start) + { + TReal32 startPosition = iColors[start].iPosition; + + TInt end = start + 1; + TReal32 endPosition; + if(end >= iColors.Count()) + { + end = iColors.Count() - 1; + endPosition = 1; + } + else + { + endPosition = iColors[end].iPosition; + } + + if(iColors[start].iOpacity <= 0 && iColors[end].iOpacity <= 0) + { + // Won't be visible. + continue; + } + + if(invert) + { + // Inverted direction. + startPosition = 1 - startPosition; + endPosition = 1 - endPosition; + } + + TInt beginCoord = (isHoriz? content.iTl.iX : content.iTl.iY); + TInt startCoord = beginCoord + TInt(startPosition * length); + TInt endCoord = beginCoord + TInt(endPosition * length); + + TRect segmentRect; + + if(isHoriz) + { + segmentRect.iTl = TPoint(startCoord, content.iTl.iY); + segmentRect.iBr = TPoint(endCoord, content.iBr.iY); + } + else + { + segmentRect.iTl = TPoint(content.iTl.iX, startCoord); + segmentRect.iBr = TPoint(content.iBr.iX, endCoord); + } + + // Calculate texture coordinates, if necessary. + if(useTexture) + { + if(isHoriz) + { + texCoordRect.iTl.iX = HuiUtil::Interpolate(startPosition, texCoords[0], texCoords[2]); + texCoordRect.iTl.iY = texCoords[3]; + texCoordRect.iBr.iX = HuiUtil::Interpolate(endPosition, texCoords[0], texCoords[2]); + texCoordRect.iBr.iY = texCoords[5]; + } + else + { + texCoordRect.iTl.iX = texCoords[0]; + texCoordRect.iTl.iY = HuiUtil::Interpolate(startPosition, texCoords[3], texCoords[5]); + texCoordRect.iBr.iX = texCoords[2]; + texCoordRect.iBr.iY = HuiUtil::Interpolate(endPosition, texCoords[3], texCoords[5]); + } + } + + aGc.DrawGradient(gradientType, segmentRect, + iColors[start].iColor, iColors[end].iColor, + iColors[start].iOpacity * opacity, + iColors[end].iOpacity * opacity, + useTexture? &texCoordRect : NULL); + } + aGc.Disable(CHuiGc::EFeatureBlending); + } + + +EXPORT_C void CHuiGradientBrush::SetColor(const TRgb& aColor, TReal32 aOpacity) __SOFTFP + { + while(iColors.Count() > 1) + { + iColors.Remove(iColors.Count() - 1); + } + + SColor color; + color.iPosition = 0; + color.iColor = aColor; + color.iOpacity = aOpacity; + + iColors[0] = color; + + SetChanged(); + } + + +EXPORT_C TRgb CHuiGradientBrush::Color(TInt aIndex) const + { + // make sure aIndex is not out of bounds + if ( aIndex < iColors.Count() ) + { + return iColors[aIndex].iColor; + } + else + { + // default color always exists + return iColors[0].iColor; + } + } + + +EXPORT_C TReal32 CHuiGradientBrush::Opacity(TInt aIndex) const __SOFTFP + { + // make sure aIndex is not out of bounds + // make sure aIndex is not out of bounds + if ( aIndex < iColors.Count() ) + { + return iColors[aIndex].iOpacity; + } + else + { + // default color always exists + return iColors[0].iOpacity; + } + } + + +EXPORT_C void CHuiGradientBrush::AppendColorL(TReal32 aPosition, + const TRgb& aColor, + TReal32 aOpacity) __SOFTFP + { + SColor color; + + color.iPosition = aPosition; + color.iColor = aColor; + color.iOpacity = aOpacity; + User::LeaveIfError(iColors.Append(color)); + + SetChanged(); + } + + +EXPORT_C void CHuiGradientBrush::SetImage(const THuiImage& aImage) + { + iImage = aImage; + SetChanged(); + } + + +EXPORT_C const THuiImage& CHuiGradientBrush::Image() const + { + return iImage; + }