diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiImageBrush.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiImageBrush.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,334 @@ +/* +* 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: Implements a brush that is able to draw images. +* +*/ + + + +#include "uiacceltk/HuiImageBrush.h" // Class definition +#include "uiacceltk/HuiDrawing.h" +#include "uiacceltk/HuiVisual.h" +#include "uiacceltk/HuiUtil.h" + + +EXPORT_C CHuiImageBrush* +CHuiImageBrush::NewL(const THuiImage & aImage) + { + CHuiImageBrush* self = NewLC(aImage); + CleanupStack::Pop(); + return self; + } + + +EXPORT_C CHuiImageBrush* CHuiImageBrush::NewLC(const THuiImage & aImage) + { + CHuiImageBrush* self = new (ELeave) CHuiImageBrush(aImage); + CleanupStack::PushL(self); + return self; + } + + +CHuiImageBrush::CHuiImageBrush(const THuiImage & aImage) + : iImage(aImage), + iScaleMode(CHuiImageVisual::EScaleFit), + iLeftBorderWidth(0), + iRightBorderWidth(0), + iTopBorderWidth(0), + iBottomBorderWidth(0) + + { + SetClipToVisual(EFalse); + iScale.Set(1.f); + iImageOffset.iX.Set(0.f); + iImageOffset.iY.Set(0.f); + } + +EXPORT_C CHuiImageBrush::~CHuiImageBrush() + { + } + +EXPORT_C void CHuiImageBrush::SetScaleMode( + CHuiImageVisual::TScaleMode aScaleMode) + { + iScaleMode = aScaleMode; + SetChanged(); + } + +EXPORT_C void CHuiImageBrush::SetImage(const THuiImage& aImage) + { + iImage = aImage; + SetChanged(); + } + +EXPORT_C const THuiImage& CHuiImageBrush::Image() const + { + return iImage; + } + + +EXPORT_C void CHuiImageBrush::SetBorders(TInt aLeftBorderPixels, + TInt aRightBorderPixels, + TInt aTopBorderPixels, + TInt aBottomBorderPixels) + { + iLeftBorderWidth = aLeftBorderPixels; + iRightBorderWidth = aRightBorderPixels; + iTopBorderWidth = aTopBorderPixels; + iBottomBorderWidth = aBottomBorderPixels; + SetChanged(); + } + +EXPORT_C TBool CHuiImageBrush::BorderDrawingEnabled() const + { + return ((iLeftBorderWidth!=0) || (iRightBorderWidth!=0) + || (iTopBorderWidth!=0) || (iBottomBorderWidth!=0)); + } + +EXPORT_C TBool CHuiImageBrush::CenterDrawingEnabled() const + { + if(!iImage.HasTexture()) + { + return EFalse; + } + // determine if there are center pixels available inside borders + // if not, we can't draw the center.. + TSize imageSize = iImage.Texture().Size(); + if(((imageSize.iWidth - iLeftBorderWidth) - iRightBorderWidth <= 0) + || ((imageSize.iHeight - iTopBorderWidth) - iBottomBorderWidth <= 0)) + { + return EFalse; + } + + return ETrue; + } + +EXPORT_C void CHuiImageBrush::ExpandVisualRect(TRect& aRect) const + { + if ( CenterDrawingEnabled() ) + { + THuiRealRect contentArea(aRect); + + // Get the scaled size + THuiRealSize imageSize( iImage.Texture().Size() ); + if ( iScaleMode == CHuiImageVisual::EScaleFit ) + { + imageSize = contentArea.Size() * iScale.Now(); + } + else + { + TReal32 scale = HuiUtil::CalculateScaleFactorFromScaleMode( + contentArea.Size(), + iImage.Texture().Size(), + iScaleMode, + iScale.Now() ); + imageSize = imageSize * scale; + } + + THuiRealPoint mid = contentArea.Center(); + + // Move mid point based on the offset + TReal32 xOffset = 0; + TReal32 yOffset = 0; + + xOffset = contentArea.Width() * iImageOffset.iX.Now(); + yOffset = contentArea.Height() * iImageOffset.iY.Now(); + + mid += THuiRealPoint( xOffset, yOffset ); + + // expand the dirty area rect if needed + aRect.iTl.iX = Min( aRect.iTl.iX, mid.iX-imageSize.iWidth/2.f ); + aRect.iTl.iY = Min( aRect.iTl.iY, mid.iY-imageSize.iHeight/2.f ); + aRect.iBr.iX = Max( aRect.iBr.iX, mid.iX+imageSize.iWidth/2.f ); + aRect.iBr.iY = Max( aRect.iBr.iY, mid.iY+imageSize.iHeight/2.f ); + } + + if(BorderDrawingEnabled()) + { + // expand the area of the content to include the border: + aRect.Grow((Max(iLeftBorderWidth, 0) + Max(iRightBorderWidth, 0)) / 2, + (Max(iTopBorderWidth, 0) + Max(iBottomBorderWidth, 0)) / 2); + // move the area to justify the border width differencies + aRect.Move((Max(iRightBorderWidth, 0)-Max(iLeftBorderWidth, 0)) / 2, + (Max(iTopBorderWidth, 0)-Max(iBottomBorderWidth, 0)) / 2); + } + } + +TBool CHuiImageBrush::Changed() const + { + if ( CHuiBrush::Changed() ) + { + return ETrue; + } + return iImageOffset.Changed() || iScale.Changed() || iImage.Changed(); + } + +void CHuiImageBrush::ClearChanged() + { + CHuiBrush::ClearChanged(); + iImageOffset.ClearChanged(); + iScale.ClearChanged(); + iImage.ClearChanged(); + } + +EXPORT_C void CHuiImageBrush::Draw(CHuiGc& aGc, const MHuiBrushGuide& aGuide) const + { + + TBool borderDrawing = BorderDrawingEnabled(); + TBool centerDrawing = CenterDrawingEnabled(); + + TReal32 opacity = aGuide.BrushOpacity() * iOpacity.Now(); + aGc.SetPenColor(KRgbWhite); + aGc.SetPenAlpha(TInt(opacity * 255.f)); + + if(centerDrawing) + { + THuiRealRect contentArea = aGuide.BrushRect(); + + aGc.Enable(CHuiGc::EFeatureBlending); + + if(borderDrawing) + { + // contract the content area if the borders + // have been defined to be inside + if(iLeftBorderWidth < 0) + { + contentArea.iTl.iX -= iLeftBorderWidth; + } + if(iRightBorderWidth < 0) + { + contentArea.iBr.iX += iRightBorderWidth; + } + if(iTopBorderWidth < 0) + { + contentArea.iTl.iY -= iTopBorderWidth; + } + if(iBottomBorderWidth < 0) + { + contentArea.iBr.iY += iBottomBorderWidth; + } + + // Read in the original texture coordinates (NOTE: not affected + // by any renderer-specific texcoord manipulations, like the Gles POT trick). + TSize imageSize(iImage.Texture().Size()); + THuiRealPoint tl = iImage.TopLeft(), br = iImage.BottomRight(); + TReal32 widthU = br.iX - tl.iX; + TReal32 heightV = br.iY - tl.iY; + + // Remove borders by adjusting texture coordinates. + // But don't divide by 0 + if ( imageSize.iWidth != 0 && imageSize.iHeight != 0 ) + { + tl.iX += ((TReal32)Abs(iLeftBorderWidth) / (TReal32)imageSize.iWidth) * widthU; + br.iX -= ((TReal32)Abs(iRightBorderWidth) / (TReal32)imageSize.iWidth) * widthU; + tl.iY += ((TReal32)Abs(iTopBorderWidth) / (TReal32)imageSize.iHeight) * heightV; + br.iY -= ((TReal32)Abs(iBottomBorderWidth) / (TReal32)imageSize.iHeight) * heightV; + } + + // Create temporary Image with adjusted texcoords + THuiImage imageBordersRemoved; + imageBordersRemoved.SetTexture(iImage.TextureIf()); + imageBordersRemoved.SetTexCoords(tl.iX, tl.iY, br.iX, br.iY); + + // Draw the image without the borders. + aGc.DrawStretchImage(CHuiGc::EStretchFull, + imageBordersRemoved, + contentArea); + } + else + { + + TReal32 scale = HuiUtil::CalculateScaleFactorFromScaleMode( + contentArea.Size(), + iImage.Texture().Size(), + iScaleMode, + iScale.Now() ); + + // Determine offset. + TReal32 xOffset = 0; + TReal32 yOffset = 0; + + xOffset = aGuide.BrushRect().Width() * iImageOffset.iX.Now(); + yOffset = aGuide.BrushRect().Height() * iImageOffset.iY.Now(); + + + // Do scaling + TBool doTranslate = !HuiUtil::RealCompare( scale, 1.f ) || !HuiUtil::RealCompare(xOffset,0.f) || !HuiUtil::RealCompare(yOffset,0.f); + if( doTranslate ) + { + /** @todo GC must provide some support for transformations. */ + aGc.Push(EHuiGcMatrixModel); + + // Rotate around the midpoint of the visual. + THuiRealPoint mid = contentArea.Center(); + + aGc.Translate(EHuiGcMatrixModel, mid.iX + xOffset, mid.iY + yOffset, 0.f); + if( !HuiUtil::RealCompare( scale, 1.f ) ) + { + aGc.Scale(EHuiGcMatrixModel, scale, scale, 1.f); + } + aGc.Translate(EHuiGcMatrixModel, -mid.iX, -mid.iY, 0.f); + } + + // Use the appropriate alignment in the graphics context. + if(iScaleMode == CHuiImageVisual::EScaleFit) + { + aGc.SetAlign(EHuiAlignHLeft, EHuiAlignVTop); + } + else + { + aGc.SetAlign(EHuiAlignHCenter, EHuiAlignVCenter); + } + + // draw the image + if(iScaleMode == CHuiImageVisual::EScaleFit) + { + aGc.DrawImage(iImage, contentArea.iTl, contentArea.Size()); + } + else + { + aGc.DrawImage(iImage, contentArea); + } + + // Restore original transformation. + if( doTranslate ) + { + aGc.Pop(EHuiGcMatrixModel); + } + + } + + } + + if(borderDrawing) + { + THuiRealRect contentArea = aGuide.BrushRect(); + + // expand the area of the content to include the border: + contentArea.Grow((Max(iLeftBorderWidth, 0) + Max(iRightBorderWidth, 0)) / 2, + (Max(iTopBorderWidth, 0) + Max(iBottomBorderWidth, 0)) / 2); + // move the area to justify the border width differencies + contentArea.Move((Max(iRightBorderWidth, 0)-Max(iLeftBorderWidth, 0)) / 2, + (Max(iTopBorderWidth, 0)-Max(iBottomBorderWidth, 0)) / 2); + + aGc.DrawBorders(contentArea.Round(), + Abs(iLeftBorderWidth), + Abs(iRightBorderWidth), + Abs(iTopBorderWidth), + Abs(iBottomBorderWidth), + CHuiGc::EBorderFixedCorners, + &iImage); + } + + }