--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/lcdgr/src/LcdGraphics.cpp Wed Sep 01 12:33:18 2010 +0100
@@ -0,0 +1,1236 @@
+/*
+* 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 <fbs.h>
+#include <biditext.h>
+#include <bitdev.h>
+#include <gdi.h>
+#include <e32math.h>
+
+#include "LcdGraphics.h"
+#include "LcdImage.h"
+#include <lcdgdrv.h>
+#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<MMIDFont*>(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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->DrawLine(&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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->DrawRect(&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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->FillRect(&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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->DrawArc(&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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->FillArc(&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);
+ // Ignore very small arc
+ if (aArcAngle >= 180 || (Abs(start.iX - end.iX) > 2 || Abs(start.iY - end.iY) > 2))
+ {
+ 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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+ iLcdDevice->FillTriangle(&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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+
+ if (iIsCanvasGraphicsItemTarget)
+ {
+ // Because rendering function, which is used for drawing image,
+ // doesn't allow to render on transparent target
+ // (@see BlitLineColor16MAMaskToColor16MAOpaque), we have to
+ // do it by ourselves.
+ error = iLcdDevice->DrawRegionForCanvasGraphicsItem
+ (
+ &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();
+
+ // MMIDCanvas::DrawBackground modifies settings of iContext.
+ // Reset pen and brush settings here, so they
+ // are re-applied again when needed.
+ iState = 0;
+ iContext->SetPenStyle(CGraphicsContext::ENullPen);
+ iContext->SetBrushStyle(CGraphicsContext::ENullBrush);
+}
+
+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<TUint8*>(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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+
+ if (iIsCanvasGraphicsItemTarget)
+ {
+ // Because rendering function, which is used for drawing
+ // RGB data, doesn't blend properly to transparent target
+ // (@see BlitLineColor16MAAlphaToColor16MAOpaque),
+ // we have to do it by ourselves.
+ err = iLcdDevice->DrawRegionForCanvasGraphicsItem
+ (
+ &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; i<count; i++)
+ {
+ TRect clip(iDeviceClipRect);
+ clip.Intersection(rects[i]);
+
+ error = iLcdDevice->DrawRegion(
+ &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