diff -r f5050f1da672 -r 04becd199f91 javauis/lcdui_akn/lcdgr/src/LcdGraphics.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdgr/src/LcdGraphics.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,1226 @@ +/* +* Copyright (c) 2005-2006 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 +#include + +#include "LcdGraphics.h" +#include "LcdImage.h" +#include +#include "LcdBitmapSurface.h" + +#include "DebugArg.h" + +#include "LcdWindowSurface.h" + +TPoint AnchorPoint(const TPoint& aPoint, TInt aAnchor, const TSize& aSize); +void ArcVectors(TPoint& aStart, TPoint& aEnd, const TRect& aRect, TInt aStartAngle, TInt aArcAngle); +TPoint Vector(const TReal& aAngle, const TSize& aSize); + +#ifdef _DEBUG +class MyBitmapLockCountHack +{ +public: + TInt iCount; +}; +#define CHECK_BITMAP_LOCK() ASSERT( ((MyBitmapLockCountHack*)(&iCount))->iCount == 0 ) +#else +#define CHECK_BITMAP_LOCK() +#endif + +const TUint32 KARGBBlack = 0xff000000; + +/** + * Map lcdui stroke style to GDI pen style. + */ +inline CGraphicsContext::TPenStyle PenStyle(TStrokeStyle aStrokeStyle) +{ + return (aStrokeStyle == EStrokeDotted ? CGraphicsContext::EDottedPen : CGraphicsContext::ESolidPen); +} + +// +// CLcdGraphics inline methods +// +inline void CLcdGraphics::SetPenOn() +{ + if (0 == (iState & EPenOn)) + { + iContext->SetPenStyle(PenStyle(iStrokeStyle)); + iState |= EPenOn; + } + if (0 == (iState & EPenColor)) + { + iContext->SetPenColor(TRgb::Color16MA(iColor)); + iState |= EPenColor; + } +} + +inline void CLcdGraphics::SetPenOff() +{ + if (iState & EPenOn) + { + iContext->SetPenStyle(CGraphicsContext::ENullPen); + iState ^= EPenOn; + } +} + +inline void CLcdGraphics::SetBrushOn() +{ + if (0 == (iState & EBrushOn)) + { + iContext->SetBrushStyle(CGraphicsContext::ESolidBrush); + iState |= EBrushOn; + } + if (0 == (iState & EBrushColor)) + { + iContext->SetBrushColor(TRgb::Color16MA(iColor)); + iState |= EBrushColor; + } +} + +inline void CLcdGraphics::SetBrushOff() +{ + if (iState & EBrushOn) + { + iContext->SetBrushStyle(CGraphicsContext::ENullBrush); + iState ^= EBrushOn; + } +} + +inline void CLcdGraphics::LineMode() +{ + SetPenOn(); +} + +inline void CLcdGraphics::FillMode() +{ + SetPenOff(); + SetBrushOn(); +} + +inline void CLcdGraphics::OutlineMode() +{ + SetPenOn(); + SetBrushOff(); +} + +CLcdGraphics* CLcdGraphics::NewL(CLcdGraphicsDriver& aDriver, CCoeControl& aWindow, MDirectContainer& aContainer, TBool aUpdate) +{ + return CLcdGraphics::NewL(aDriver, CLcdWindowSurface::NewL(aWindow, aContainer, aUpdate)); +} + +CLcdGraphics* CLcdGraphics::NewL(CLcdGraphicsDriver& aDriver, const CFbsBitmap* aBitmap) +{ + return CLcdGraphics::NewL(aDriver, CLcdBitmapSurface::NewL(aBitmap)); +} + +// +// aSurface is NOT on cleanup stack. +// +CLcdGraphics* CLcdGraphics::NewL(CLcdGraphicsDriver& aDriver, CLcdSurface* aSurface) +{ + CleanupStack::PushL(aSurface); + CLcdGraphics* graphics = new(ELeave) CLcdGraphics(aDriver, aSurface); + CleanupStack::Pop(aSurface); + CleanupStack::PushL(graphics); + graphics->ConstructL(); + CleanupStack::Pop(graphics); + return graphics; +} + +// +// +// +CLcdGraphics::CLcdGraphics(CLcdGraphicsDriver& aDriver, CLcdSurface* aSurface) + : iLcdDriver(aDriver) + , iSurface(aSurface) + , iIsCanvasGraphicsItemTarget(EFalse) +{ + iStrokeStyle = EStrokeSolid; + iColor = KARGBBlack; + iFont = NULL; + iState = EPenOn|EPenColor; // Initial state of context +} + +void CLcdGraphics::ConstructL() +{ + // + // We require a CLcdGraphicsDevice for transforming bitblts which are + // not supported by BITGDI. If the driver cannot create a device for + // this surface type we will fail here. A line buffer could be used to + // implement a slow version of the transforming blitters to avoid this + // failure mode. + // + iLcdDevice = iLcdDriver.CreateDeviceL(iSurface->ImageType()); + iLcdDrawCaps = iLcdDevice->DrawingCaps(); + + iDeviceBounds = iSurface->Bounds(); + iDeviceOrigin = iDeviceBounds.iTl; + iDeviceClipRect = iDeviceBounds; + + iOrigin = TPoint(); + iClipRect = TRect(iDeviceBounds.Size()); + +#ifdef __SERIES60_ + iMIDPictograph = CMIDPictograph::NewL(); +#endif +} + +CLcdGraphics::~CLcdGraphics() +{ + delete iLcdDevice; + delete iSurface; +#ifdef __SERIES60_ + delete iMIDPictograph; +#endif +} + +void CLcdGraphics::Begin() +{ + CHECK_BITMAP_LOCK(); + + TRect bounds = iSurface->Bounds(); + if (bounds != iDeviceBounds) + { + iDeviceBounds = bounds; + iDeviceOrigin = iDeviceBounds.iTl + iOrigin; + iDeviceClipRect = iClipRect; + iDeviceClipRect.Move(iDeviceOrigin); + iDeviceClipRect.Intersection(bounds); + } + + CBitmapContext* context = iSurface->Context(); + if (context != iContext) + { + iContext = context; + ASSERT(iContext); + iState = 0; + iContext->SetPenStyle(CGraphicsContext::ENullPen); + iContext->SetBrushStyle(CGraphicsContext::ENullBrush); + iContext->SetOrigin(iOrigin); + iContext->SetClippingRect(iClipRect); + if (iFont) + { + iContext->UseFont(iFont); + iContext->SetUnderlineStyle(iUnderline); + } + } +} + +void CLcdGraphics::End() +{ + // + // This may not be required if we have CLcdGraphics::Flush(rect) + // + //iSurface->Update(); + + CHECK_BITMAP_LOCK(); +} + +/** +Maps a color provided as 32bit rgb triple to the closest color representable +in the target devices display mode. returns the result as a 32bit rgb triple. +*/ +TUint32 CLcdGraphics::QuantizeColor(TUint32 aRGB32) +{ + if (iLcdDevice) + { + return iLcdDevice->Quantize(aRGB32); + } + return aRGB32; // iLcdDriver.Quantize( iFbsBitmap->DisplayMode(), aRGB32 ); +} + +CLcdSurface* CLcdGraphics::Surface() +{ + return iSurface; +} + +void CLcdGraphics::SetColor(TUint32 aColor) +{ + if (iColor != aColor) + { + iColor = aColor; + iState &= ~(EPenColor|EBrushColor); + } +} + +TUint32 CLcdGraphics::Color() const +{ + return iColor; +} + +void CLcdGraphics::SetClipRect(const TPoint& aPosition, const TSize& aSize) +{ + // + // We keep a copy of the clipping rectangle for the + // blitters. Clip rect is supplied in translated + // coordinates, we map to device coords. + // + iClipRect = TRect(aPosition, aSize); + iContext->SetClippingRect(iClipRect); + iDeviceClipRect = iClipRect; + iDeviceClipRect.Move(iDeviceOrigin); + iDeviceClipRect.Intersection(iDeviceBounds); +} + +const TRect& CLcdGraphics::ClipRect() const +{ + return iClipRect; +} + +void CLcdGraphics::Translate(const TPoint& aPoint) +{ + // + // Context stores clip rect in translated coords so there + // is no need to update the clipping rect. + // + iContext->SetOrigin(aPoint); + iClipRect.Move(iOrigin - aPoint); + iOrigin = aPoint; + iDeviceOrigin = aPoint + iDeviceBounds.iTl; +} + +const TPoint& CLcdGraphics::Origin() const +{ + return iOrigin; +} + +void CLcdGraphics::SetStrokeStyle(TStrokeStyle aStyle) +{ + if (iStrokeStyle != aStyle) + { + iStrokeStyle = aStyle; + if (iState & EPenOn) + { + iContext->SetPenStyle(PenStyle(iStrokeStyle)); + } + } +} + +TStrokeStyle CLcdGraphics::StrokeStyle() const +{ + return iStrokeStyle; +} + +void CLcdGraphics::SetFont(TUint32 aFontID) +{ + MMIDFont* font = reinterpret_cast(aFontID << 2); + iFont = font->Font(); + iUnderline = font->IsUnderlined() ? EUnderlineOn : EUnderlineOff; + iHeight = font->Height(); + iContext->UseFont(iFont); + iContext->SetUnderlineStyle(iUnderline); +} + +void CLcdGraphics::Reset(const TSize& aSize) +{ + TRect deviceBounds(iDeviceBounds.iTl, aSize); + iDeviceBounds = deviceBounds; + iState = 0; + iColor = KARGBBlack; + iStrokeStyle = EStrokeSolid; + iOrigin = TPoint(0,0); + iClipRect = TRect(iDeviceBounds.Size()); + iDeviceClipRect = iDeviceBounds; + iDeviceOrigin = iDeviceBounds.iTl; + iContext->SetPenStyle(CGraphicsContext::ENullPen); + iContext->SetBrushStyle(CGraphicsContext::ENullBrush); + iContext->SetOrigin(iOrigin); + iContext->SetClippingRect(iClipRect); +} + +void CLcdGraphics::DrawLine(const TPoint& aPoint1, const TPoint& aPoint2) +{ + TInt caps = CLcdGraphicsDevice::ECapDrawLine; + if (iStrokeStyle == EStrokeDotted) + { + caps |= CLcdGraphicsDevice::ECapStrokeDotted; + } + if ((iLcdDrawCaps & caps) == caps) + { + ASSERT(iLcdDevice); + + TPoint p1(aPoint1); + TPoint p2(aPoint2); + + p1 += iDeviceOrigin; + p2 += iDeviceOrigin; + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawLine(&iBitmap, p1, p2, iColor, (TStrokeStyle)iStrokeStyle, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + LineMode(); + const TPoint& p1 = aPoint1; + TPoint p2 = aPoint2; + if (p1.iY == p2.iY) + { + /** + Horizontal special case - adjust coords to include endpoint + */ + if (p2.iX > p1.iX) + { + ++ p2.iX; + } + else + { + -- p2.iX; + } + iContext->DrawLine(p1,p2); + } + else if (p1.iX == p2.iX) + { + /** + Vertical special case - adjust coords to include endpoint + */ + if (p2.iY > p1.iY) + { + ++ p2.iY; + } + else + { + -- p2.iY; + } + iContext->DrawLine(p1, p2); + } + else + { + /** + General slope - have to plot last point since SymbianOS GDI does + not draw the last point on a line. + */ + iContext->DrawLine(p1, p2); + iContext->Plot(p2); + } + } +} + +void CLcdGraphics::DrawRect(const TPoint& aPosition, const TSize& aSize) +{ + // + // adjust coords for stroked primitives + // + TRect rect(aPosition, aSize); + rect.iBr.iX++; + rect.iBr.iY++; + + TInt caps = CLcdGraphicsDevice::ECapDrawRect; + if (iStrokeStyle == EStrokeDotted) + { + caps |= CLcdGraphicsDevice::ECapStrokeDotted; + } + if ((iLcdDrawCaps & caps) == caps) + { + ASSERT(iLcdDevice); + + rect.Move(iDeviceOrigin); + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawRect(&iBitmap, rect, iColor, (TStrokeStyle)iStrokeStyle, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + OutlineMode(); + iContext->DrawRect(rect); + } +} + +void CLcdGraphics::FillRect(const TPoint& aPosition, const TSize& aSize) +{ + TRect rect(aPosition, aSize); + if (iLcdDrawCaps & CLcdGraphicsDevice::ECapFillRect) + { + ASSERT(iLcdDevice); + rect.Move(iDeviceOrigin); + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iFillRect(&iBitmap, rect, iColor, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + FillMode(); + iContext->DrawRect(rect); + } +} + +void CLcdGraphics::DrawArc(const TPoint& aPosition, const TSize& aSize, TInt aStartAngle, TInt aArcAngle) +{ + if (!aArcAngle) + { + return; + } + + TRect rect(aPosition, aSize); + rect.iBr.iX++; + rect.iBr.iY++; + + TInt caps = CLcdGraphicsDevice::ECapDrawArc; + if (iStrokeStyle == EStrokeDotted) + { + caps |= CLcdGraphicsDevice::ECapStrokeDotted; + } + if ((iLcdDrawCaps & caps) == caps) + { + ASSERT(iLcdDevice); + + rect.Move(iDeviceOrigin); + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawArc(&iBitmap, rect, aStartAngle, aArcAngle, iColor, iStrokeStyle, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + OutlineMode(); + TPoint start; + TPoint end; + ArcVectors(start, end, rect, aStartAngle, aArcAngle); + iContext->DrawArc(rect,start,end); + } +} + +void CLcdGraphics::FillArc(const TPoint& aPosition, const TSize& aSize, TInt aStartAngle, TInt aArcAngle) +{ + if (!aArcAngle) + { + return; + } + TRect rect(aPosition, aSize); + if (iLcdDrawCaps & CLcdGraphicsDevice::ECapFillArc) + { + ASSERT(iLcdDevice); + rect.Move(iDeviceOrigin); + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iFillArc(&iBitmap, rect, aStartAngle, aArcAngle, iColor, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + // Temporarily turn on the pen and set the pen color. + SetPenOff(); + SetBrushOn(); + + // Grow the bounding rect by a 1 pixel border. + rect.Grow(1,1); + + TPoint start; + TPoint end; + ArcVectors(start, end, rect, aStartAngle, aArcAngle); + iContext->DrawPie(rect,start,end); + } +} + +void CLcdGraphics::CopyArea(const TPoint& aAreaPosition, const TSize& aAreaSize, const TPoint& aPoint, TInt aAnchor) +{ + TRect rect(aAreaPosition, aAreaSize); + TPoint vector = AnchorPoint(aPoint, aAnchor, aAreaSize) - aAreaPosition; + iContext->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); + iContext->CopyRect(vector, rect); + iContext->SetDrawMode(CGraphicsContext::EDrawModePEN); +} + +void CLcdGraphics::DrawRoundRect(const TPoint& aPosition, const TSize& aSize, const TSize& aCornerDiameter) +{ + TRect rect(aPosition, aSize); + rect.iBr.iX++; + rect.iBr.iY++; + TSize cornerRadii; + cornerRadii.iWidth = aCornerDiameter.iWidth/2; + cornerRadii.iHeight = aCornerDiameter.iHeight/2; + OutlineMode(); + iContext->DrawRoundRect(rect, cornerRadii); +} + +void CLcdGraphics::FillRoundRect(const TPoint& aPosition, const TSize& aSize, const TSize& aCornerDiameter) +{ + TRect rect(aPosition, aSize); + TSize cornerRadii; + cornerRadii.iWidth = aCornerDiameter.iWidth/2; + cornerRadii.iHeight = aCornerDiameter.iHeight/2; + + // Temporarily turn on the pen and set the pen color. + SetBrushOn(); + iContext->SetPenColor(TRgb::Color16MA(iColor)); + iContext->SetPenStyle(CGraphicsContext::ESolidPen); + iContext->DrawRoundRect(rect, cornerRadii); + iState |= EPenOn; + SetPenOff(); // keep in sync with stroke style +} + +void CLcdGraphics::FillTriangle(const TPoint aPoints[3]) +{ +#ifdef RD_JAVA_NGA_ENABLED + // Lcdgd implementation for fillTriangle does not support alpha blending, + // use CFbsBitGc in case of non-opaque color. + if ((iLcdDrawCaps & CLcdGraphicsDevice::ECapFillTriangle) && + ((iColor & 0xFF000000) == 0xFF000000)) +#else + if (iLcdDrawCaps & CLcdGraphicsDevice::ECapFillTriangle) +#endif + { + ASSERT(iLcdDevice); + TPoint points[3]; + points[0] = aPoints[0]+iDeviceOrigin; + points[1] = aPoints[1]+iDeviceOrigin; + points[2] = aPoints[2]+iDeviceOrigin; + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iFillTriangle(&iBitmap, points, iColor, clip); + } + } + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + else + { + // Temporarily set solid pen style and the pen color. + SetBrushOn(); + iContext->SetPenColor(TRgb::Color16MA(iColor)); + iContext->SetPenStyle(CGraphicsContext::ESolidPen); + iContext->DrawPolygon(aPoints, 3, CGraphicsContext::EAlternate); + SetPenOff(); // keep in sync with stroke style + } +} + +// --------------------------------------------------------------------------- +// CMIDGraphics::DrawImage() +// --------------------------------------------------------------------------- +// +void CLcdGraphics::DrawImage( + const CLcdImage& aImage, const TPoint& aPoint, TInt aAnchor, TBool aPremultiplied) +{ + TPoint regionPos; + TSize regionSize(aImage.Size()); + (void) DrawRegion( + aImage, regionPos, regionSize, ETransNone, aPoint, aAnchor, aPremultiplied); +} + +// --------------------------------------------------------------------------- +// CMIDGraphics::DrawRegion() +// Returns error if no blitter found. +// --------------------------------------------------------------------------- +// +TInt CLcdGraphics::DrawRegion +( + const CLcdImage& aImage, + const TPoint& aRegionPos, + const TSize& aRegionSize, + TInt aTransform, + const TPoint& aPoint, + TInt aAnchor, + TBool aPremultiplied +) +{ + ASSERT(iLcdDrawCaps & CLcdGraphicsDevice::ECapDrawRegion); + ASSERT(iLcdDevice); + + TTransformType transform = (TTransformType)aTransform; + TAnchor anchor = (TAnchor)aAnchor; + + TRect srcRect(aRegionPos, aRegionSize); + TPoint dstPoint(iDeviceOrigin + aPoint); + + TAcceleratedBitmapInfo srcColor; + TAcceleratedBitmapInfo srcAlpha; + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + aImage.Lock(iCount, srcColor, srcAlpha); + + // + // Compute destination rectangle with anchor point at aRegion.iDstPoint. + // + TRect dstRect = CalcDstRect(dstPoint, srcRect.Size(), transform, anchor); + TInt error = KErrNone; + + TTransparency transparency = aImage.Transparency(); + +#ifdef RD_JAVA_NGA_ENABLED + // In S60 9.2 and onward the target canvas offscreen is not necessarily + // fully opaque when the M3G API is using hardware accelerated OpenGL ES API. + // Note that in this case target pixels are in premultiplied form. + if (aPremultiplied) + { + if (transparency == ETransparencyMaskChannel) + { + // Target contains premultiplied pixel components and + // and source contains transparent pixels + transparency = ETransparencyMaskChannelPre; + } + if (transparency == ETransparencyAlphaChannel) + { + // Target contains premultiplied pixel components and + // and source contains transparent pixels + transparency = ETransparencyAlphaChannelPre; + } + } +#else // !RD_JAVA_NGA_ENABLED + (void)aPremultiplied; // Just to remove a compiler warning +#endif // RD_JAVA_NGA_ENABLED + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawRegionForCanvasGraphicsItem + ( + &iBitmap, + dstRect, + &srcColor, + srcAlpha.iAddress ? &srcAlpha : NULL, + aImage.Transparency(), + srcRect, + transform, + clip, + ECanvasGraphicsItemImageRendering + ); + } + else + { + error = iLcdDevice->DrawRegion + ( + &iBitmap, + dstRect, + &srcColor, + srcAlpha.iAddress ? &srcAlpha : NULL, + transparency, + srcRect, + transform, + clip + ); + } + } + } + + aImage.Unlock(iCount); + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + + ASSERT(error == KErrNone); + + return error; +} + +void CLcdGraphics::DrawBackground(MMIDCanvas* aCanvas, const TPoint& aPosition, const TSize& aSize) +{ + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + aCanvas->DrawBackground(*iContext, aPosition, aSize); + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + +} + +TInt CLcdGraphics::DrawPixels +( + TInt aType, + const TUint8* aAddress, + TInt DEBUG_ARG(aLength), + TInt aScanLength, + TBool aAlpha, + const TPoint& aPosition, + const TSize& aSize, + TInt aTransform, + TBool aPremultiplied +) +{ + ASSERT(iLcdDevice); + TInt err = KErrNotSupported; + if (aType == 0) // we could support others now. + { + ASSERT(iLcdDrawCaps & CLcdGraphicsDevice::ECapDrawRegion); + ASSERT((((TUint32)aAddress) & 0x3) == 0); // must be word aligned + ASSERT(aLength >= ((aSize.iHeight-1)*aScanLength + aSize.iWidth*sizeof(TUint32))); + ASSERT(aScanLength >= 0); + + TTransformType transform = (TTransformType)aTransform; + TTransparency transparency = (aAlpha ? ETransparencyAlphaChannel : ETransparencyIgnoreChannel); + + TAcceleratedBitmapInfo srcBitmap; + + CLcdGraphicsDriver::TDriverInfo info; + iLcdDriver.GetDriverInfo(info); + + srcBitmap.iPhysicalAddress = NULL; + srcBitmap.iAddress = const_cast(aAddress); + srcBitmap.iDisplayMode = info.iARGB8888Mode; + srcBitmap.iSize = aSize; + srcBitmap.iLinePitch = aScanLength; + srcBitmap.iPixelShift = 5; // 32bpp + + + TRect srcRect(aSize); + TRect dstRect(aPosition, aSize); + dstRect.Move(iDeviceOrigin); + + CHECK_BITMAP_LOCK(); + + iSurface->Begin(iBitmap, iCount); + +#ifdef RD_JAVA_NGA_ENABLED + // In S60 9.2 and onward the target canvas offscreen is not necessarily + // fully opaque when the M3G API is using hardware accelerated OpenGL ES API. + // Note that in this case target pixels are in premultiplied form. + if (aPremultiplied && transparency == ETransparencyAlphaChannel) + { + // Target contains premultiplied pixel components and + // and source contains transparent pixels + transparency = ETransparencyAlphaChannelPre; + } +#else // !RD_JAVA_NGA_ENABLED + (void)aPremultiplied; // Just to remove a compiler warning +#endif // RD_JAVA_NGA_ENABLED + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawRegionForCanvasGraphicsItem + ( + &iBitmap, + dstRect, + &srcBitmap, + NULL, + transparency, + srcRect, + transform, + clip, + ECanvasGraphicsItemRGBRendering + ); + } + else + { + err = iLcdDevice->DrawRegion + ( + &iBitmap, + dstRect, + &srcBitmap, + NULL, + transparency, + srcRect, + transform, + clip + ); + } + } + } + + + iSurface->End(iCount); + + CHECK_BITMAP_LOCK(); + } + return err; +} + +static TBool IsUniformlyLeftToRight(const TDesC& aText) +{ + const TInt length = aText.Length(); + + for (TInt i = 0; i < length; i++) + { + switch (TChar(aText[i]).GetBdCategory()) + { + case TChar::ERightToLeft: + case TChar::ERightToLeftArabic: + case TChar::ERightToLeftEmbedding: + case TChar::ERightToLeftOverride: + case TChar::EArabicNumber: + + return EFalse; + + default: + ; + } + } + return ETrue; +} + +void CLcdGraphics::DrawText(const TDesC& aText, const TPoint& aPoint, TInt aAnchor) +{ + LineMode(); + + ASSERT(iFont); + TPoint pos = aPoint; + + if (aAnchor & EAnchorTop) + { + pos.iY += iFont->FontMaxAscent(); + } + else if (aAnchor & EAnchorBottom) + { + pos.iY -= (iHeight - iFont->FontMaxAscent()); // iHeight includes leading + } + + if (aAnchor & EAnchorHCenter) + { + pos.iX -= iFont->TextWidthInPixels(aText)/2; + } + else if (aAnchor & EAnchorRight) + { + pos.iX -= iFont->TextWidthInPixels(aText); + } + + if (IsUniformlyLeftToRight(aText)) + { +#ifdef __SERIES60_ + CAknPictographInterface* aknPictographInterface = iMIDPictograph->PictographInterface(); + + if (aknPictographInterface) + { + MAknPictographDrawer* aknPictographDrawer = aknPictographInterface->Interface(); + aknPictographDrawer->DrawText(*iContext, *iFont, aText, pos); + } + else + { + iContext->DrawText(aText, pos); + } + +#else + iContext->DrawText(aText, pos); +#endif + } + else + { + TBidiText* bidiText = NULL; + + TRAPD(status, bidiText = TBidiText::NewL(aText, 1)); + if (status != KErrNone) + { + return; + } + bidiText->WrapText(iFont->TextWidthInPixels(aText), *iFont); +#ifdef __SERIES60_ + CAknPictographInterface* aknPictographInterface = iMIDPictograph->PictographInterface(); + + if (aknPictographInterface) + { + MAknPictographDrawer* aknPictographDrawer = aknPictographInterface->Interface(); + aknPictographDrawer->DrawText(*iContext, *iFont, aText, pos); + } + else + { + bidiText->DrawText(*iContext, pos); + } +#else + bidiText->DrawText(*iContext, pos); +#endif + delete bidiText; + } +} + +void CLcdGraphics::Flush(const TPoint& aPosition, const TSize& aSize) +{ + TRect deviceRect(aPosition, aSize); + deviceRect.Move(iDeviceBounds.iTl); + iSurface->Update(deviceRect); +} + +#ifdef RD_JAVA_NGA_ENABLED + +// --------------------------------------------------------------------------- +// CLcdGraphics::CopyGraphics() +// Copies source graphics content +// --------------------------------------------------------------------------- +// +TInt CLcdGraphics::CopyGraphics(CLcdGraphics* aSrcGraphics) +{ + ASSERT(iLcdDevice); + CLcdSurface* srcSurface = aSrcGraphics->Surface(); + TInt error = KErrNone; + CHECK_BITMAP_LOCK(); + iSurface->Begin(iBitmap, iCount); + srcSurface->Begin(aSrcGraphics->iBitmap, iCount); + + RRegion* visibleRegion = iSurface->VisibleRegion(); + if (iBitmap.iAddress && visibleRegion) + { + const TRect* rects = visibleRegion->RectangleList(); + const TInt count = visibleRegion->Count(); + for (TInt i=0; iDrawRegion( + &iBitmap, + iSurface->Bounds(), + &aSrcGraphics->iBitmap, + NULL, + ETransparencyIgnoreChannel, + iSurface->Bounds(), + ETransNone, + clip); + } + } + srcSurface->End(iCount); + iSurface->End(iCount); + CHECK_BITMAP_LOCK(); + ASSERT(error == KErrNone); + return error; +} + +#endif // RD_JAVA_NGA_ENABLED + +void ArcVectors(TPoint& aStart, TPoint& aEnd, const TRect& aRect, TInt aStartAngle, TInt aArcAngle) +{ + TPoint point = aRect.iTl; + TSize size = aRect.Size(); + + // + // Center. + // + point.iX += size.iWidth/2; + point.iY += size.iHeight/2; + + if (aArcAngle>=360 || aArcAngle <=-360) + { + aStart = point; + aStart.iX += size.iWidth/2; + aEnd = aStart; + } + else + { + TInt begAngle = aStartAngle; + TInt endAngle = aStartAngle+aArcAngle; + if (aArcAngle < 0) + { + begAngle = endAngle; + endAngle = aStartAngle; + } + aEnd = point + Vector(endAngle, size); + aStart = point + Vector(begAngle, size); + } +} + +TPoint Vector(const TReal& aAngle, const TSize& aSize) +{ + TReal angle(aAngle * KDegToRad); + + TReal x; + Math::Cos(x, angle); + + TReal y; + Math::Sin(y, angle); + + x *= aSize.iWidth; + y *= -aSize.iHeight; + + return TPoint((TInt)x, (TInt)y); +} + +TPoint AnchorPoint(const TPoint& aPoint, TInt aAnchor, const TSize& aSize) +{ + TPoint point = aPoint; + + if (aAnchor & MMIDGraphics::EAnchorRight) + { + point.iX -= aSize.iWidth; + } + else if (aAnchor & MMIDGraphics::EAnchorHCenter) + { + point.iX -= aSize.iWidth/2; + } + + if (aAnchor & MMIDGraphics::EAnchorVCenter) + { + point.iY -= aSize.iHeight/2; + } + else if (aAnchor & MMIDGraphics::EAnchorBottom) + { + point.iY -= aSize.iHeight; + } + + return point; +} + +void CLcdGraphics::SetCanvasGraphicsItemtarget(TBool aIsCanvasGraphicsItemTarget) +{ + iIsCanvasGraphicsItemTarget = aIsCanvasGraphicsItemTarget; +} + +///////////////////////////////////////////////////////////// +// CMIDPictograph is for Pictograpgh in S60 +// +//////////////////////////////////////////////////////////// +#ifdef __SERIES60_ + +CMIDPictograph* CMIDPictograph::NewL() +{ + CMIDPictograph* self = new(ELeave) CMIDPictograph; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; +} +// +CMIDPictograph::CMIDPictograph() {} +void CMIDPictograph::ConstructL() +{ + CCoeControl *dummyControl = NULL; + iPictographInterface = CAknPictographInterface::NewL(*dummyControl, *this); +} +//Not doing any thing, Canvas has to draw the pictograph +//by calling draw again and again. +void CMIDPictograph::DrawPictographArea() {} +CAknPictographInterface* CMIDPictograph::PictographInterface() +{ + return iPictographInterface; +} + +CMIDPictograph::~CMIDPictograph() +{ + delete iPictographInterface; +} + +#endif