--- /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);
+ }
+
+ }