diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/src/HuiGc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/src/HuiGc.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,829 @@ +/* +* 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 for CHuiGc (graphics context) class. +* +*/ + + + +#include "uiacceltk/HuiGc.h" // Class definition +#include "HuiRenderPlugin.h" +#include "uiacceltk/HuiSegmentedTexture.h" +#include "uiacceltk/HuiTextMesh.h" +#include "uiacceltk/HuiFont.h" +#include "uiacceltk/HuiImage.h" +#include "uiacceltk/HuiTransformation.h" +#include "uiacceltk/HuiPanic.h" +#include "uiacceltk/HuiUtil.h" // For hui assert. +#include "uiacceltk/HuiTransformation.h" + +#include +#include + +const TInt KHuiMaxRecycledRegionCount = 20; + +/** Default offset from the Z=0 plane (which 2D projection uses) to the + eyepoint, in 3D projection mode. */ +LOCAL_D const TReal32 KDefaultOffset2D = 1199.0; + + +EXPORT_C CHuiGc::CHuiGc() + : iOrientation(EOrientationNormal), + iNearClipDistance(20.f), + iFarClipDistance(10000.f), + iFovFactor(1.f), + iPenColor(TRgb(255, 255, 255)), iPenAlpha(255), + iAlignHorizontal(EHuiAlignHLeft), iAlignVertical(EHuiAlignVTop), + iFrustumOffsetCompleteness(1.f), + iQuality(EHuiQualityAccurate), + iClipRegionStackCount(0) + { + /// @todo Fix this: The real default is 1.f, but the application should + /// be able to adjust the completeness. Wowidle/Mmenu have been + /// developed with .666f. + iFrustumOffsetCompleteness = .666f; + } + +EXPORT_C CHuiGc::~CHuiGc() + { + iTempRegion.Close(); + iClipRegion.Close(); + iClipRegionStack.Reset(); + iRecycledRegions.ResetAndDestroy(); + iWindowTransform = NULL; + iCurrentFont = NULL; + } + + +EXPORT_C void CHuiGc::SetQuality(THuiQuality aQuality) + { + iQuality = aQuality; + } + + +EXPORT_C THuiQuality CHuiGc::Quality() const + { + return iQuality; + } + + +EXPORT_C void CHuiGc::SetDisplayArea(const TRect& aDisplayArea) + { + iDisplayArea = aDisplayArea; + iClipRegion.Clear(); + iClipRegion.AddRect(aDisplayArea); + } + + +EXPORT_C TRect CHuiGc::DisplayArea() const + { + if(iOrientation == EOrientationNormal) + { + return iDisplayArea; + } + else + { + TInt width = iDisplayArea.Width(); + TInt height = iDisplayArea.Height(); + /// @todo Should not always be at the top left corner. + TRect rect(TPoint(0, 0), TSize(height, width)); + return rect; + } + } + + +EXPORT_C void CHuiGc::SetOrientation(TOrientation aOrientation) + { + iOrientation = aOrientation; + } + + +EXPORT_C CHuiGc::TOrientation CHuiGc::Orientation() const + { + return iOrientation; + } + + +EXPORT_C void CHuiGc::SetProjection(TProjection aProjection) + { + SetProjection(aProjection, iDisplayArea); + } + + +EXPORT_C CHuiGc::TProjection CHuiGc::Projection() const + { + return iProjection; + } + + +EXPORT_C void CHuiGc::SetProjection(TProjection aProjection, const TRect& aViewport) + { + iProjection = aProjection; + iProjectionViewport = aViewport; + iFrustumOffset = THuiRealPoint(0.f, 0.f); + + UpdateProjection(); + } + + +EXPORT_C void CHuiGc::SetFrustumOffset(const THuiRealPoint& aFrustumOffset) + { + if(!iDisplayArea.Width() || !iDisplayArea.Height()) + { + return; + } + + THuiRealPoint local = aFrustumOffset; + TRect area = DisplayArea(); // Orientation applied. + local.iX -= area.Width()/2.f; + local.iY -= area.Height()/2.f; + local.iX /= area.Width()/2.f; + local.iY /= area.Height()/2.f; + + // Adjust so that the perspective correction isn't complete. + local.iX *= iFrustumOffsetCompleteness; + local.iY *= iFrustumOffsetCompleteness; + + iFrustumOffset = local; + + UpdateProjection(); + } + + +EXPORT_C void CHuiGc::Disable(TFeature aFeature) + { + Enable(aFeature, EFalse); + } + + +EXPORT_C TRect CHuiGc::UnOrientRect(const TRect& aOrientedRect) const + { + if(iOrientation == EOrientationCCW90) + { + // Un-orient 90 degrees clockwise. + TSize size(aOrientedRect.Height(), aOrientedRect.Width()); + TPoint pos(iDisplayArea.Width() - aOrientedRect.iBr.iY, + aOrientedRect.iTl.iX); + return TRect(pos, size); + } + else if(iOrientation == EOrientationCW90) + { + // Un-orient 90 degrees counterclockwise. + TSize size(aOrientedRect.Height(), aOrientedRect.Width()); + TPoint pos(aOrientedRect.iTl.iY, + iDisplayArea.Height() - aOrientedRect.iBr.iX); + return TRect(pos, size); + } + else + { + // No change because there is no orientation. + return aOrientedRect; + } + } + +EXPORT_C void CHuiGc::UnOrientRegion(TRegion& aOrientedRegion) const + { + if(iOrientation == EOrientationCCW90 || iOrientation == EOrientationCW90) + { + iTempRegion.Clear(); + for (TInt i=0; i < aOrientedRegion.Count(); i++) + { + iTempRegion.AddRect(UnOrientRect(aOrientedRegion[i])); + } + aOrientedRegion.Copy(iTempRegion); + } + else + { + // No change because there is no orientation. + } + } + +EXPORT_C void CHuiGc::PushClip() + { + RRegion* newRegion = CreateRecycledRegion(); + + if (newRegion) + { + newRegion->Copy(iClipRegion); + iClipRegionStack.Append(newRegion); + } + + // Out of memory situation is handled by keeping separate + // counter which is checked at pop. + iClipRegionStackCount++; + } + +EXPORT_C void CHuiGc::PopClip() + { + __ASSERT_ALWAYS(iClipRegionStack.Count() > 0, + THuiPanic::Panic(THuiPanic::EGcClipStackPopFromEmpty)); + + // Check if out of memory situation has happened in the push, so we don't pop + // because we have not really pushed anything. + if (iClipRegionStackCount > iClipRegionStack.Count()) + { + iClipRegionStackCount--; + return; + } + + if(iClipRegionStack.Count() > 0) + { + TInt index = iClipRegionStack.Count() - 1; + SetClipRegion(*iClipRegionStack[index]); + RRegion* region = iClipRegionStack[index]; + iClipRegionStack.Remove(index); + DeleteRecycledRegion(region); + region = NULL; + iClipRegionStackCount--; + } + } + +EXPORT_C void CHuiGc::SetClip(const TRect& aClipRect) + { + HUI_ASSERT(aClipRect.Width() >= 0); + HUI_ASSERT(aClipRect.Height() >= 0); + + iTempRegion.Clear(); + iTempRegion.AddRect(aClipRect); + CHuiGc::SetClipRegion(iTempRegion); + } + +EXPORT_C TRect CHuiGc::ClipRect() const + { + // This does not really provide actually valid data anymore + // since clipping is done with a region. + return iClipRegion.BoundingRect(); + } + +const TRegion& CHuiGc::ClipRegion() const + { + return iClipRegion; + } + + +EXPORT_C void CHuiGc::Clip(const TRect& aClipRect) + { + HUI_ASSERT(aClipRect.Width() >= 0); + HUI_ASSERT(aClipRect.Height() >= 0); + + if(iClipRegion.Intersects(aClipRect)) + { + iTempRegion.Clear(); + iTempRegion.AddRect(aClipRect); + iClipRegion.Intersect(iTempRegion); + } + else + { + // Empty clipping rectangle. + iClipRegion.Clear(); + } + + SetClipRegion(iClipRegion); + } + +EXPORT_C void CHuiGc::Clip(const TRegion& aClipRegion) + { + iClipRegion.Intersect(aClipRegion); + SetClipRegion(iClipRegion); + } + +EXPORT_C void CHuiGc::SetClipRegion(const TRegion& aClipRegion) + { + if (&aClipRegion != &iClipRegion) + { + iClipRegion.Copy(aClipRegion); + } + } + +EXPORT_C void CHuiGc::CancelClipping() + { + } + +EXPORT_C TInt CHuiGc::ClipStackCount() const + { + return iClipRegionStack.Count(); + } + + +EXPORT_C void CHuiGc::SetAlign(THuiAlignHorizontal aHorizontalAlign, + THuiAlignVertical aVerticalAlign) + { + switch(aHorizontalAlign) + { + case EHuiAlignHLocale: + iAlignHorizontal = LocaleTextAlignment(); + break; + + case EHuiAlignHLocaleMirrored: + iAlignHorizontal = LocaleTextAlignment(); + if(iAlignHorizontal == EHuiAlignHLeft) + { + iAlignHorizontal = EHuiAlignHRight; + } + else + { + iAlignHorizontal = EHuiAlignHLeft; + } + break; + + default: + iAlignHorizontal = aHorizontalAlign; + break; + } + + iAlignVertical = aVerticalAlign; + } + + +EXPORT_C THuiAlignHorizontal CHuiGc::AlignHorizontal() const + { + return iAlignHorizontal; + } + + +EXPORT_C THuiAlignVertical CHuiGc::AlignVertical() const + { + return iAlignVertical; + } + + +EXPORT_C void CHuiGc::SetPenColor(const TRgb& aColor) + { + iPenColor = aColor; + } + + +EXPORT_C TRgb CHuiGc::PenColor() const + { + return iPenColor; + } + + +EXPORT_C void CHuiGc::SetPenColorAlpha(const TRgb& aColor) + { + iPenColor = aColor; + iPenColor.SetAlpha(255); + + iPenAlpha = TUint8(aColor.Alpha()); // 8 bits should be enough + } + + +EXPORT_C TRgb CHuiGc::PenColorAlpha() const + { + TRgb color = iPenColor; + color.SetAlpha(iPenAlpha); + return color; + } + + +EXPORT_C void CHuiGc::SetPenAlpha(TInt aAlpha) + { + if(aAlpha < 0) + { + aAlpha = 0; + } + else if(aAlpha > 255) + { + aAlpha = 255; + } + else + { + // for PC lint + } + iPenAlpha = TUint8(aAlpha); // 8 bits should be enough + } + + +EXPORT_C TInt CHuiGc::PenAlpha() const + { + return iPenAlpha; + } + + +EXPORT_C void CHuiGc::SetFont(THuiFont& aFont) + { + iCurrentFont = &aFont; + } + + +EXPORT_C void CHuiGc::DrawTextL(const TDesC& aText, + const THuiRealRect& aBounds, + TReal32 aShadow) __SOFTFP + { + if(!Font()) + { + return; + } + CHuiTextMesh* mesh = CHuiStatic::Renderer().CreateTextMeshL(); + CleanupStack::PushL(mesh); + mesh->SetTextL(aText, ETrue); + DrawText(*mesh, aBounds, aShadow); + CleanupStack::PopAndDestroy(mesh); + } + + +EXPORT_C void CHuiGc::DrawText(const CHuiTextMesh& aTextMesh, + const THuiRealRect& aBounds, + TReal32 aShadow) __SOFTFP + { + /** @todo This could be generalized: MHuiBoundedDrawable (for example) */ + + // Font is defined in the text mesh. + + // Real bounding size of the text. + TSize textBounds = aTextMesh.Extents(); + + // Reference origin for the text. + TPoint offset = AlignOffset(aBounds.Size()); + + // Actual starting point for glyphs. + THuiRealPoint pos = aBounds.iTl - offset; + switch(AlignHorizontal()) + { + case EHuiAlignHRight: + pos.iX -= textBounds.iWidth; + break; + + case EHuiAlignHCenter: + pos.iX -= textBounds.iWidth / 2; // or 2.f? + break; + + default: + break; + } + switch(AlignVertical()) + { + case EHuiAlignVBottom: + pos.iY -= textBounds.iHeight; + break; + + case EHuiAlignVCenter: + pos.iY -= textBounds.iHeight / 2; // or 2.f? + break; + + default: + break; + } + + + // Apply the position. + Push(EHuiGcMatrixModel); + Translate(EHuiGcMatrixModel, pos.iX, pos.iY, 0.f); + + aTextMesh.Draw(*this, aShadow); + + Pop(EHuiGcMatrixModel); + } + + +EXPORT_C void CHuiGc::DrawImage(const THuiImage& aImage, + const THuiRealPoint& aPos, + const THuiRealSize& aSize) + { + if(!aImage.HasTexture()) + { + return; + } + + THuiRealPoint topLeft = aPos + AlignOffset(aSize); + UpdateColor(); + + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, THuiRealRect(topLeft,aSize)); + + DoDrawImage(aImage, topLeft, aSize); + } + + +EXPORT_C void CHuiGc::DrawImages(const THuiImage& aImage, + const THuiImage& aImage2, + const THuiRealPoint& aPos, + const THuiRealSize& aSize) + { + if(!aImage.HasTexture() || !aImage2.HasTexture()) + { + return; + } + + THuiRealPoint topLeft = aPos + AlignOffset(aSize); + UpdateColor(); + + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, THuiRealRect(topLeft,aSize)); + NotifyImagePreferredSize(aImage2, THuiRealRect(topLeft,aSize)); + + DoDrawImages(aImage, aImage2, topLeft, aSize); + } + + +EXPORT_C void CHuiGc::DrawImage(const THuiImage& aImage, + const THuiRealRect& aBounds) + { + if(!aImage.HasTexture()) + { + return; + } + + TSize space(TInt(aBounds.Width() - aImage.Texture().Size().iWidth), + TInt(aBounds.Height() - aImage.Texture().Size().iHeight)); + + TPoint topLeft = aBounds.iTl - AlignOffset(space); + + UpdateColor(); + + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, aBounds); + + DoDrawImage(aImage, topLeft, aImage.Texture().Size()); + } + + +EXPORT_C void CHuiGc::DrawImage( const THuiImage& aImage, + const THuiRealSize& aSize, + const THuiRealRect& aBounds) + { + if(!aImage.HasTexture()) + { + return; + } + + TSize space(TInt(aBounds.Width() - aSize.iWidth), + TInt(aBounds.Height() - aSize.iHeight)); + + TPoint topLeft = aBounds.iTl - AlignOffset(space); + + UpdateColor(); + + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, THuiRealRect(topLeft,aSize)); + + DoDrawImage(aImage, topLeft, aSize); + } + + +EXPORT_C void CHuiGc::DrawImages(const THuiImage& aImage, + const THuiImage& aImage2, + const THuiRealSize& aSize, + const THuiRealRect& aBounds) + { + if(!aImage.HasTexture() || !aImage2.HasTexture()) + { + return; + } + + TSize space(TInt(aBounds.Width() - aSize.iWidth), + TInt(aBounds.Height() - aSize.iHeight)); + + TPoint topLeft = aBounds.iTl - AlignOffset(space); + + UpdateColor(); + + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, THuiRealRect(topLeft,aSize)); + NotifyImagePreferredSize(aImage2, THuiRealRect(topLeft,aSize)); + + DoDrawImages(aImage, aImage2, topLeft, aSize); + } + + +EXPORT_C THuiFont* CHuiGc::Font() + { + return iCurrentFont; + } + + +EXPORT_C TPoint CHuiGc::AlignOffset(const TSize& aBounds) const + { + TPoint offset(0, 0); + + switch(iAlignHorizontal) + { + case EHuiAlignHRight: + offset.iX = -aBounds.iWidth; + break; + + case EHuiAlignHCenter: + offset.iX = -aBounds.iWidth / 2; + break; + + default: + offset.iX = 0; + break; + } + + switch(iAlignVertical) + { + case EHuiAlignVBottom: + offset.iY = -aBounds.iHeight; + break; + + case EHuiAlignVCenter: + offset.iY = -aBounds.iHeight / 2; + break; + + default: + offset.iY = 0; + break; + } + + return offset; + } + + +EXPORT_C TReal32 CHuiGc::Offset2D() const __SOFTFP + { + /// @todo Make this configurable. + //return 100.0 / FovFactor(); + return KDefaultOffset2D; + } + + +EXPORT_C void +CHuiGc::SetWindowTransformation(CHuiTransformation* aWindowTransformation) + { + iWindowTransform = aWindowTransformation; + } + + +EXPORT_C TReal32 CHuiGc::NearClipDistance() const __SOFTFP + { + return iNearClipDistance; + } + + +EXPORT_C TReal32 CHuiGc::FarClipDistance() const __SOFTFP + { + return iFarClipDistance; + } + + +EXPORT_C TRect CHuiGc::ProjectionViewport() const + { + return iProjectionViewport; + } + + +EXPORT_C TRect CHuiGc::RawDisplayArea() const + { + return iDisplayArea; + } + + +EXPORT_C const CHuiTransformation* CHuiGc::WindowTransformation() const + { + return iWindowTransform; + } + + +EXPORT_C THuiRealPoint CHuiGc::FrustumOffset() const + { + return iFrustumOffset; + } + + +EXPORT_C TReal32 CHuiGc::FovFactor() const __SOFTFP + { + return 1.f / iFovFactor; + } + + +EXPORT_C THuiAlignHorizontal CHuiGc::LocaleTextAlignment() + { + if(CHuiStatic::LayoutMirrored()) + { + return EHuiAlignHRight; + } + return EHuiAlignHLeft; + } + +EXPORT_C void CHuiGc::DrawStretchImage(TStretchMode /*aMode*/, + const THuiImage& aImage, + const THuiRealRect& aRect, + TInt /*aStretchStartWidth*/, + TInt /*aStretchEndWidth*/) + { + // Update texture preferred size, toolkit may use this information to resize texture + NotifyImagePreferredSize(aImage, aRect); + } + + +EXPORT_C void CHuiGc::NotifyImagePreferredSize(const THuiImage& aImage, THuiRealRect aRect) + { + const CHuiTexture* texture = aImage.ImageDefaultTexture(); + + if (texture) + { + CHuiTexture* notifiedTexture = const_cast (texture); + if (notifiedTexture->IsAutoSizeCalculationEnabled()) + { + TReal32 xratio = 1; + TReal32 yratio = 1; + + // Take into account used texture coordinates of THuiImage + TReal32 relativeWidth = aImage.BottomRight().iX - aImage.TopLeft().iX; + TReal32 relativeHeight = aImage.BottomRight().iY - aImage.TopLeft().iY; + + if (relativeWidth != 0.f && relativeHeight != 0.f) + { + xratio *= (1/relativeWidth); + yratio *= (1/relativeHeight); + } + + TReal32 width = aRect.Size().iWidth * xratio; + TReal32 height = aRect.Size().iHeight * yratio; + + // Take into account window transformation scale (To enable HiRes TV-OUT textures) + // Other transformations are ignored for now. Possible those could be optionally + // taken into account as well if resizing algortihm is lazy enough. + CHuiTransformation* wt = (CHuiTransformation*)WindowTransformation(); + if (wt) + { + TInt count = wt->Count(); + for (TInt i=0;iStep(i); + if (step.iType == CHuiTransformation::ETypeScale) + { + width = width * step.iParams[EHuiTransformParamTranslateX].Now(); + height = height * step.iParams[EHuiTransformParamTranslateY].Now(); + } + } + } + + + notifiedTexture->NotifyPreferredSize(THuiRealSize(width,height)); + } + } + } + +EXPORT_C void CHuiGc::TransformDirtyRect(THuiRealRect& /*aRect*/) + { + // No sensible implementation for HuiGc base class. Implement at least in + // HuiBitgdiGc child class. + } + +EXPORT_C void CHuiGc::EnableTransformedClippingRects(TBool /*aEnable*/) + { + // No sensible implementation for HuiGc base class. Implement at least in + // HuiBitgdiGc child class. + } + +EXPORT_C void CHuiGc::SetClip(const TRect& /*aClipRect*/, TBool /*aTransformClipRect*/) + { + // No sensible implementation for HuiGc base class. Implement at least in + // HuiBitgdiGc child class. + } + +EXPORT_C void CHuiGc::GcExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams) + { + // If no extension with given UID was found, indicate it by returning null + *aExtensionParams = NULL; + } + +RRegion* CHuiGc::CreateRecycledRegion() + { + RRegion* region = NULL; + if (iRecycledRegions.Count()) + { + // If there are recycled regionbufs, use one of those + TInt last = iRecycledRegions.Count() - 1; + region = iRecycledRegions[last]; + iRecycledRegions.Remove(last); + } + else + { + // No recycled regionbufs available, create new one + region = new RRegionBuf(); + } + return region; + } + +void CHuiGc::DeleteRecycledRegion(RRegion* aRegion) + { + TInt error = KErrNone; + + if (iRecycledRegions.Count() < KHuiMaxRecycledRegionCount) + { + aRegion->Clear(); + error = iRecycledRegions.Append(aRegion); + if (error) + { + aRegion->Destroy(); + } + } + else + { + aRegion->Destroy(); + } + }