--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/playbackgc.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1063 @@
+// Copyright (c) 1994-2009 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:
+// GC.CPP
+// GC and Graphics functions
+//
+//
+
+#include "playbackgc.h"
+
+#include <e32std.h>
+#include <s32mem.h>
+
+#include "backedupwindow.h"
+#include "panics.h"
+#include "ScrDev.H"
+#include "windowgroup.h"
+#include "wsfont.h"
+#include "wstop.h"
+#include "Graphics/WSGRAPHICDRAWER.H"
+
+#if defined(__WINS__) && defined(_DEBUG)
+# include "offscreenbitmap.h"
+# define DEBUGOSB { CWsOffScreenBitmap * ofb = iWin->Screen()->OffScreenBitmap(); if (ofb) ofb->Update(); }
+#else
+# define DEBUGOSB
+#endif
+
+CPlaybackGc * CPlaybackGc::iSelf=NULL;
+
+GLREF_C RWsRegion* InternalizeRegionL(RReadStream& aReadStream);
+
+/*CPlaybackGc*/
+
+void CPlaybackGc::InitStaticsL()
+ {
+ iSelf=new(ELeave) CPlaybackGc();
+ iSelf->ConstructL();
+ }
+
+void CPlaybackGc::DeleteStatics()
+ {
+ delete iSelf;
+ iSelf = 0;
+ }
+
+CPlaybackGc::CPlaybackGc()
+ {
+ }
+
+void CPlaybackGc::ConstructL()
+ {
+ iSelf->iScratchBitmap=new(ELeave) CFbsBitmap();
+ iSelf->iScratchMaskBitmap=new(ELeave) CFbsBitmap();
+ iGcBuf = CBufSeg::NewL(512);
+ }
+
+CPlaybackGc::~CPlaybackGc()
+ {
+ delete iPolyPoints;
+ delete iGcBuf;
+ iCurrentClippingRegion = NULL;
+ delete iScratchBitmap;
+ delete iScratchMaskBitmap;
+ }
+
+void CPlaybackGc::Activate(CWsClientWindow * aWin, CFbsBitGc * aGc, const TRegion * aRegion)
+ {
+ iWin = aWin;
+ iGc = aGc;
+ iTargetRegion = aRegion;
+
+ iDrawRegion = iTargetRegion;
+ iMasterOrigin = iWin->Origin();
+ iOrigin.SetXY(0,0);
+ iGc->SetBrushColor(iWin->BackColor());
+ ResetClippingRect();
+ }
+
+void CPlaybackGc::Deactivate()
+ {
+ iWin = 0;
+ iGc = 0;
+ iTargetRegion = 0;
+ iDrawRegion = 0;
+ CancelUserClippingRegion();
+ }
+
+void CPlaybackGc::CancelUserClippingRegion()
+ {
+ if (iUserDefinedClippingRegion)
+ {
+ iUserDefinedClippingRegion->Destroy();
+ iUserDefinedClippingRegion = 0;
+ iDrawRegion = iTargetRegion;
+ }
+ }
+
+void CPlaybackGc::SetClippingRect(const TRect &aRect)
+ {
+ iClippingRect=aRect;
+ iClippingRect.Move(iOrigin);
+ iClippingRectSet=ETrue;
+ }
+
+void CPlaybackGc::ResetClippingRect()
+ {
+ iClippingRectSet=EFalse;
+ }
+
+void CPlaybackGc::CheckPolyData(const TAny* aDataPtr, TInt aHeaderSize, TInt aNumPoints)
+ {
+ TInt maxDataLen;
+ if (CWsClient::iCurrentCommand.iOpcode>0)
+ {
+ maxDataLen=CWsClient::EndOfCommandBuffer()-static_cast<const TUint8*>(aDataPtr);
+ }
+ else
+ {
+ maxDataLen=CWsClient::iCurrentCommand.iCmdLength;
+ }
+ const TInt dataSize=aHeaderSize+aNumPoints*sizeof(TPoint);
+ if (dataSize>maxDataLen)
+ GcOwnerPanic(EWservPanicBadPolyData);
+ }
+
+void CPlaybackGc::DoDrawPolygon(const TWsGcCmdDrawPolygon *aDrawPolygon)
+ {
+ CheckPolyData(aDrawPolygon, sizeof(TWsGcCmdDrawPolygon), aDrawPolygon->numPoints);
+ iGc->DrawPolygon((TPoint *)(aDrawPolygon+1),aDrawPolygon->numPoints,aDrawPolygon->fillRule);
+ }
+
+void CPlaybackGc::StartSegmentedDrawPolygonL(const TWsGcCmdStartSegmentedDrawPolygon *aDrawPolygon)
+ {
+ // In case a Playback have been done before all the segment is in the RedrawStore
+ // (This allocation is deleted only thanks to the EWsGcOpDrawSegmentedPolygon opcode
+ // which arrive after all the segments)
+ delete iPolyPoints;
+ iPolyPoints=NULL;
+
+ iPolyPoints=(TPoint *)User::AllocL(aDrawPolygon->totalNumPoints*sizeof(TPoint));
+ iPolyPointListSize=aDrawPolygon->totalNumPoints;
+ }
+
+void CPlaybackGc::SegmentedDrawPolygonData(const TWsGcCmdSegmentedDrawPolygonData *aDrawPolygon)
+ {
+ if (aDrawPolygon->index<0 || (aDrawPolygon->index + aDrawPolygon->numPoints) > iPolyPointListSize)
+ GcOwnerPanic(EWservPanicBadPolyData);
+ Mem::Copy(iPolyPoints+aDrawPolygon->index,aDrawPolygon+1,aDrawPolygon->numPoints*sizeof(TPoint));
+ }
+
+void CPlaybackGc::EndSegmentedPolygon()
+ {
+ delete iPolyPoints;
+ iPolyPoints=NULL;
+ }
+
+void CPlaybackGc::DoDrawPolyLine(const TWsGcCmdDrawPolyLine *aDrawPolyLine, TBool aContinued)
+ {
+ TInt numPoints=aDrawPolyLine->numPoints;
+ CheckPolyData(aDrawPolyLine, sizeof(TWsGcCmdDrawPolyLine), numPoints);
+ const TPoint *points=(TPoint *)(aDrawPolyLine+1);
+ if (aContinued)
+ {
+ numPoints++;
+ points=&aDrawPolyLine->last;
+ }
+ if (aDrawPolyLine->more) // more to come so don't draw the end point
+ iGc->DrawPolyLineNoEndPoint(points,numPoints);
+ else
+ iGc->DrawPolyLine(points,numPoints);
+ }
+
+void CPlaybackGc::GcOwnerPanic(TClientPanic aPanic)
+ {
+ iGc->SetClippingRegion(NULL);
+ iCurrentClippingRegion = NULL;
+ EndSegmentedPolygon();
+ iWin->WsOwner()->PPanic(aPanic);
+ }
+
+// implementing MWsGc
+
+MWsClient& CPlaybackGc::Client()
+ {
+ return *(iWin->WsOwner());
+ }
+
+MWsScreen& CPlaybackGc::Screen()
+ {
+ return *(iWin->Screen());
+ }
+
+TPoint CPlaybackGc::GcOrigin() const
+ {
+ return (iMasterOrigin + iOrigin);
+ }
+
+const TRegion& CPlaybackGc::ClippingRegion()
+ {
+ WS_ASSERT_ALWAYS(iCurrentClippingRegion,EWsPanicDrawCommandsInvalidState);
+ return* iCurrentClippingRegion;
+ }
+
+CFbsBitGc& CPlaybackGc::BitGc()
+ {
+ return *iGc;
+ }
+
+TInt CPlaybackGc::PushBitGcSettings()
+ {
+ // the buf format is len+data where data is written by the GC's ExternalizeL()
+ CBufBase& buf = *iGcBuf;
+ const TInt start = buf.Size();
+ RBufWriteStream out(buf,start);
+ TRAPD(err,out.WriteInt32L(0));
+ if(!err)
+ {
+ TRAP(err,iGc->ExternalizeL(out));
+ }
+ if(err) //rollback addition
+ {
+ buf.Delete(start,buf.Size()-start);
+ }
+ else //fixup len
+ {
+ TRAP_IGNORE(out.CommitL();) // can't see this failing
+ TPckgBuf<TInt32> pckg(buf.Size()-sizeof(TInt32)-start);
+ buf.Write(start,pckg);
+ }
+ return err;
+ }
+
+void CPlaybackGc::PopBitGcSettings()
+ {
+ CBufBase& buf = *iGcBuf;
+ TInt ofs = 0;
+ FOREVER
+ {
+ TInt chunk = 0;
+ RBufReadStream in(buf,ofs);
+ TRAPD(err,chunk = in.ReadInt32L());
+ if(err)
+ {
+ WS_ASSERT_DEBUG(err != 0, EWsPanicWsGraphic);
+ return;
+ }
+ if(ofs+sizeof(TInt32)+chunk >= buf.Size()) // the last chunk?
+ {
+ TRAP_IGNORE(iGc->InternalizeL(in));
+ buf.Delete(ofs,buf.Size()-ofs);
+ return;
+ }
+ ofs += chunk + sizeof(TInt32);
+ }
+ }
+
+const TTime& CPlaybackGc::Now() const
+ {
+ return iWin->Screen()->Now();
+ }
+
+void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow)
+ {
+ ScheduleAnimation(aRect,aFromNow,0,0);
+ }
+
+void CPlaybackGc::ScheduleAnimation(const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow,const TTimeIntervalMicroSeconds& aFreq,const TTimeIntervalMicroSeconds& aStop)
+ {
+ // convert window rect to screen rect
+ TRect rect(aRect);
+ rect.Move(GcOrigin());
+ // clip rect to window extent
+ rect.Intersection(iWin->Abs());
+ if (!rect.IsEmpty())
+ {
+ // and schedule it
+ iWin->Screen()->ScheduleAnimation(rect,aFromNow,aFreq,aStop);
+ }
+ }
+
+void CPlaybackGc::SetGcOrigin(const TPoint& aOrigin)
+ {
+ iOrigin = aOrigin - iMasterOrigin;
+ }
+
+
+void CPlaybackGc::RemoteReadDataAndDrawL(const CWsGraphicDrawer* aGraphic, CWsClient* aOwner, const TWsGcCmdUnion &aData)
+ {
+ TPtrC8 data;
+ HBufC8* dataBuf = NULL;
+ const TInt len = aData.WsGraphic->iDataLen;
+
+ if ((len >= KMaxTInt / 4) || (len < 0))
+ {
+ aOwner->PPanic(EWservPanicBuffer);
+ }
+ dataBuf = HBufC8::NewLC(len);
+ TPtr8 des = dataBuf->Des();
+ aOwner->RemoteRead(des, 0);
+
+ if(des.Size() != len)
+ {
+ aOwner->PPanic(EWservPanicBuffer);
+ }
+ data.Set(des);
+ aGraphic->Draw(*this, aData.WsGraphic->iRect, data);
+ CleanupStack::PopAndDestroy(dataBuf);
+ }
+
+TPtrC CPlaybackGc::BufferTPtr(TText* aStart,TInt aLen, const TDesC8& aCmdData)
+ {
+ if ((reinterpret_cast<TUint8*>(aStart) < aCmdData.Ptr()
+ || reinterpret_cast<TUint8*>(aStart+aLen) > (aCmdData.Ptr() + aCmdData.Size()) ))
+ {
+ GcOwnerPanic(EWservPanicBufferPtr);
+ }
+ TPtrC gcPtr;
+ gcPtr.Set(aStart,aLen);
+ return(gcPtr);
+ }
+
+void CPlaybackGc::DoDrawCommand(TWsGcOpcodes aOpcode, const TDesC8& aCmdData, const TRegion *aRegion)
+ {
+ TWsGcCmdUnion pData;
+ pData.any=aCmdData.Ptr();
+
+ if (aRegion)
+ {
+ WS_ASSERT_DEBUG(iWin,EWsPanicWindowNull);
+ if (aRegion->Count()==0)
+ return;
+ iGc->SetClippingRegion(aRegion);
+ WS_ASSERT_DEBUG(!iCurrentClippingRegion, EWsPanicDrawCommandsInvalidState);
+ iCurrentClippingRegion = aRegion;
+ }
+ switch(aOpcode)
+ {
+ case EWsGcOpDrawWsGraphic:
+ case EWsGcOpDrawWsGraphicPtr:
+ {
+ TRect screenRect(pData.WsGraphic->iRect);
+ screenRect.Move(GcOrigin());
+ if(iCurrentClippingRegion->Intersects(screenRect))
+ {
+ const TInt dataLen = pData.WsGraphic->iDataLen;
+ TGraphicDrawerId id;
+ id.iId = pData.WsGraphic->iId;
+ id.iIsUid = (pData.WsGraphic->iFlags & EWsGraphicIdUid);
+ CWsClient* owner = iWin->WsOwner();
+ const CWsGraphicDrawer* graphic = owner->WindowServer().ResolveGraphic(id);
+ if(graphic && graphic->IsSharedWith(owner->SecureId()))
+ {
+ if(aOpcode == EWsGcOpDrawWsGraphicPtr)
+ {
+ TRAPD(err, RemoteReadDataAndDrawL(graphic, owner, pData))
+ if(err)
+ WS_PANIC_DEBUG(EWsPanicWsGraphic);
+ }
+ else
+ graphic->Draw(*this,pData.WsGraphic->iRect,CWsClient::BufferTPtr8((TUint8*)(pData.WsGraphic+1),dataLen));
+
+ WS_ASSERT_DEBUG(!iGcBuf->Size(),EWsPanicWsGraphic);
+ iGcBuf->Reset();
+ }
+ }
+ break;
+ }
+ case EWsGcOpMapColorsLocal:
+ iGc->MapColors(pData.MapColorsLocal->rect, pData.MapColorsLocal->colors,pData.MapColorsLocal->numPairs,pData.MapColorsLocal->mapForwards);
+ break;
+ case EWsGcOpDrawPolyLineLocalBufLen:
+ iGc->DrawPolyLine(pData.DrawPolyLineLocalBufLen->points,pData.DrawPolyLineLocalBufLen->length);
+ break;
+ case EWsGcOpDrawPolyLineLocal:
+ iGc->DrawPolyLine(pData.PointList);
+ break;
+ case EWsGcOpDrawPolygonLocalBufLen:
+ iGc->DrawPolygon(pData.DrawPolygonLocalBufLen->points,pData.DrawPolygonLocalBufLen->length,pData.DrawPolygonLocalBufLen->fillRule);
+ break;
+ case EWsGcOpDrawPolygonLocal:
+ iGc->DrawPolygon(pData.DrawPolygonLocal->pointList,pData.DrawPolygonLocal->fillRule);
+ break;
+ case EWsGcOpDrawBitmapLocal:
+ iGc->DrawBitmap(pData.BitmapLocal->pos, pData.BitmapLocal->bitmap);
+ break;
+ case EWsGcOpDrawBitmap2Local:
+ iGc->DrawBitmap(pData.Bitmap2Local->rect, pData.Bitmap2Local->bitmap);
+ break;
+ case EWsGcOpDrawBitmap3Local:
+ iGc->DrawBitmap(pData.Bitmap3Local->rect, pData.Bitmap3Local->bitmap, pData.Bitmap3Local->srcRect);
+ break;
+ case EWsGcOpDrawBitmapMaskedLocal:
+ iGc->DrawBitmapMasked(pData.iBitmapMaskedLocal->iRect, pData.iBitmapMaskedLocal->iBitmap, pData.iBitmapMaskedLocal->iSrcRect, pData.iBitmapMaskedLocal->iMaskBitmap,pData.iBitmapMaskedLocal->iInvertMask);
+ break;
+ case EWsGcOpAlphaBlendBitmapsLocal:
+ iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmapsLocal->point,pData.AlphaBlendBitmapsLocal->iBitmap,
+ pData.AlphaBlendBitmapsLocal->source, pData.AlphaBlendBitmapsLocal->iAlpha,
+ pData.AlphaBlendBitmapsLocal->alphaPoint);
+
+ break;
+ case EWsGcOpDrawText:
+ iGc->DrawText(BufferTPtr((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData),pData.DrawText->pos);
+ break;
+ case EWsGcOpDrawBoxTextOptimised1:
+ iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData),pData.BoxTextO1->box,
+ pData.BoxTextO1->baselineOffset,CGraphicsContext::ELeft,0);
+ break;
+ case EWsGcOpDrawBoxTextOptimised2:
+ iGc->DrawText(BufferTPtr((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData),pData.BoxTextO2->box,
+ pData.BoxTextO2->baselineOffset,pData.BoxTextO2->horiz,pData.BoxTextO2->leftMrg);
+ break;
+ case EWsGcOpDrawTextPtr:
+ iGc->DrawText(*pData.DrawTextPtr->text,pData.DrawTextPtr->pos);
+ break;
+ case EWsGcOpDrawTextPtr1:
+ iGc->DrawText(*pData.DrawTextPtr->text);
+ break;
+ case EWsGcOpDrawBoxText:
+ iGc->DrawText(BufferTPtr((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData),pData.BoxText->box,pData.BoxText->baselineOffset,pData.BoxText->width,pData.BoxText->horiz,pData.BoxText->leftMrg);
+ break;
+ case EWsGcOpDrawBoxTextPtr:
+ iGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box,pData.DrawBoxTextPtr->baselineOffset,pData.DrawBoxTextPtr->width,pData.DrawBoxTextPtr->horiz,pData.DrawBoxTextPtr->leftMrg);
+ break;
+ case EWsGcOpDrawBoxTextPtr1:
+ iGc->DrawText(*pData.DrawBoxTextPtr->text,pData.DrawBoxTextPtr->box);
+ break;
+ case EWsGcOpDrawTextVertical:
+ iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData),pData.DrawTextVertical->pos
+ ,pData.DrawTextVertical->up);
+ break;
+ case EWsGcOpDrawTextVerticalPtr:
+ iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->pos,pData.DrawTextVerticalPtr->up);
+ break;
+ case EWsGcOpDrawTextVerticalPtr1:
+ iGc->DrawTextVertical(*pData.DrawTextVerticalPtr->text,pData.DrawTextVerticalPtr->up);
+ break;
+ case EWsGcOpDrawBoxTextVertical:
+ iGc->DrawTextVertical(BufferTPtr((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData),
+ pData.DrawBoxTextVertical->box, pData.DrawBoxTextVertical->baselineOffset,
+ pData.DrawBoxTextVertical->up,(CGraphicsContext::TTextAlign)pData.DrawBoxTextVertical->vert,pData.DrawBoxTextVertical->margin);
+ break;
+ case EWsGcOpDrawBoxTextVerticalPtr:
+ iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->baselineOffset
+ ,pData.DrawBoxTextVerticalPtr->width,pData.DrawBoxTextVerticalPtr->up,pData.DrawBoxTextVerticalPtr->vert,pData.DrawBoxTextVerticalPtr->margin);
+ break;
+ case EWsGcOpDrawBoxTextVerticalPtr1:
+ iGc->DrawTextVertical(*pData.DrawBoxTextVerticalPtr->text,pData.DrawBoxTextVerticalPtr->box,pData.DrawBoxTextVerticalPtr->up);
+ break;
+ case EWsGcOpDrawTextLocal:
+ iGc->DrawText(*pData.DrawTextLocal->desc,pData.DrawTextLocal->pos);
+ break;
+ case EWsGcOpDrawBoxTextLocal:
+ iGc->DrawText(*pData.BoxTextLocal->desc,pData.BoxTextLocal->box,pData.BoxTextLocal->baselineOffset,
+ pData.BoxTextLocal->horiz,pData.BoxTextLocal->leftMrg);
+ break;
+ case EWsGcOpDrawLine:
+ iGc->DrawLine(pData.DrawLine->pnt1,pData.DrawLine->pnt2);
+ break;
+ case EWsGcOpDrawTo:
+ iGc->DrawLine(iLinePos,*pData.Point);
+ break;
+ case EWsGcOpDrawBy:
+ iGc->DrawLine(iLinePos,iLinePos+(*pData.Point));
+ break;
+ case EWsGcOpPlot:
+ iGc->Plot(*pData.Point);
+ break;
+ case EWsGcOpMoveTo:
+ case EWsGcOpMoveBy:
+ break;
+ case EWsGcOpGdiBlt2Local:
+ iGc->BitBlt(pData.GdiBlt2Local->pos,pData.GdiBlt2Local->bitmap);
+ break;
+ case EWsGcOpGdiBlt3Local:
+ iGc->BitBlt(pData.GdiBlt3Local->pos,pData.GdiBlt3Local->bitmap, pData.GdiBlt3Local->rect);
+ break;
+ case EWsGcOpGdiBltMaskedLocal:
+ iGc->BitBltMasked(pData.GdiBltMaskedLocal->pos,pData.GdiBltMaskedLocal->bitmap,
+ pData.GdiBltMaskedLocal->rect,pData.GdiBltMaskedLocal->maskBitmap,
+ pData.GdiBltMaskedLocal->invertMask);
+ break;
+ case EWsGcOpGdiWsBlt2:
+ case EWsGcOpGdiWsBlt3:
+ case EWsGcOpGdiWsBltMasked:
+ case EWsGcOpGdiWsAlphaBlendBitmaps:
+ case EWsGcOpWsDrawBitmapMasked:
+ {
+ // Andy - we continually duplicate bitmaps in here, and yet we already have them
+ // somewhere as pointers so can't we both simplify and optimize this?
+ CFbsBitmap* scratchBitmap=iScratchBitmap;
+ CFbsBitmap* scratchMaskBimap=iScratchMaskBitmap;
+ TInt maskHandle=0;
+ TInt handle=WsBitmapHandle(aOpcode,pData, maskHandle);
+ CWsClient* owner=iWin->WsOwner();
+ if (owner!=NULL)
+ {
+ TInt wsBmpErr = KErrNone;
+ DWsBitmap *bitmap=(DWsBitmap *)owner->HandleToObj(handle, WS_HANDLE_BITMAP);
+ if (!bitmap)
+ wsBmpErr = KErrNotFound;
+ else
+ scratchBitmap=bitmap->FbsBitmap();
+ if (wsBmpErr == KErrNone)
+ if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps || aOpcode==EWsGcOpWsDrawBitmapMasked)
+ {
+ DWsBitmap *bitmap2=(DWsBitmap *)owner->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
+ if (!bitmap2)
+ wsBmpErr = KErrNotFound;
+ else
+ scratchMaskBimap=bitmap2->FbsBitmap();
+ }
+ if (wsBmpErr == KErrNone)
+ {
+ switch(aOpcode)
+ {
+ case EWsGcOpGdiWsBlt2:
+ iGc->BitBlt(pData.GdiBlt2->pos,scratchBitmap);
+ break;
+ case EWsGcOpGdiWsBlt3:
+ iGc->BitBlt(pData.GdiBlt3->pos,scratchBitmap, pData.GdiBlt3->rect);
+ break;
+ case EWsGcOpGdiWsBltMasked:
+ {
+ iGc->BitBltMasked(pData.GdiBltMasked->destination,scratchBitmap,
+ pData.GdiBltMasked->source, scratchMaskBimap,
+ pData.GdiBltMasked->invertMask);
+ }
+ break;
+ case EWsGcOpGdiWsAlphaBlendBitmaps:
+ {
+ iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point,scratchBitmap,
+ pData.AlphaBlendBitmaps->source, scratchMaskBimap,
+ pData.AlphaBlendBitmaps->alphaPoint);
+ }
+ break;
+ case EWsGcOpWsDrawBitmapMasked:
+ {
+ iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect,scratchBitmap,
+ pData.iBitmapMasked->iSrcRect,scratchMaskBimap,
+ pData.iBitmapMasked->iInvertMask);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case EWsGcOpGdiBlt2:
+ case EWsGcOpGdiBlt3:
+ case EWsGcOpGdiBltMasked:
+ case EWsGcOpGdiAlphaBlendBitmaps:
+ case EWsGcOpDrawBitmap:
+ case EWsGcOpDrawBitmap2:
+ case EWsGcOpDrawBitmap3:
+ case EWsGcOpDrawBitmapMasked:
+ {
+ TInt maskHandle=0;
+ TInt ret = iScratchBitmap->Duplicate(FbsBitmapHandle(aOpcode, pData,maskHandle));
+ if (ret == KErrNone)
+ {
+ switch(aOpcode)
+ {
+ case EWsGcOpGdiBlt2:
+ iGc->BitBlt(pData.GdiBlt2->pos,iScratchBitmap);
+ break;
+ case EWsGcOpGdiBlt3:
+ iGc->BitBlt(pData.GdiBlt3->pos,iScratchBitmap, pData.GdiBlt3->rect);
+ break;
+ case EWsGcOpGdiBltMasked:
+ {
+ ret = iScratchMaskBitmap->Duplicate(pData.GdiBltMasked->maskHandle);
+ if (ret == KErrNone)
+ {
+ iGc->BitBltMasked(pData.GdiBltMasked->destination,iScratchBitmap,
+ pData.GdiBltMasked->source, iScratchMaskBitmap,
+ pData.GdiBltMasked->invertMask);
+ iScratchMaskBitmap->Reset();
+ }
+ }
+ break;
+ case EWsGcOpGdiAlphaBlendBitmaps:
+ {
+ ret = iScratchMaskBitmap->Duplicate(pData.AlphaBlendBitmaps->alphaHandle);
+ if (ret == KErrNone)
+ {
+ iGc->AlphaBlendBitmaps(pData.AlphaBlendBitmaps->point, iScratchBitmap,
+ pData.AlphaBlendBitmaps->source, iScratchMaskBitmap,
+ pData.AlphaBlendBitmaps->alphaPoint);
+ iScratchMaskBitmap->Reset();
+ }
+ break;
+ }
+ case EWsGcOpDrawBitmap:
+ iGc->DrawBitmap(pData.Bitmap->pos, iScratchBitmap);
+ break;
+ case EWsGcOpDrawBitmap2:
+ iGc->DrawBitmap(pData.Bitmap2->rect, iScratchBitmap);
+ break;
+ case EWsGcOpDrawBitmap3:
+ iGc->DrawBitmap(pData.Bitmap3->rect, iScratchBitmap, pData.Bitmap3->srcRect);
+ break;
+ case EWsGcOpDrawBitmapMasked:
+ {
+ ret = iScratchMaskBitmap->Duplicate(pData.iBitmapMasked->iMaskHandle);
+ if (ret == KErrNone)
+ {
+ iGc->DrawBitmapMasked(pData.iBitmapMasked->iRect, iScratchBitmap,
+ pData.iBitmapMasked->iSrcRect, iScratchMaskBitmap,
+ pData.iBitmapMasked->iInvertMask);
+ iScratchMaskBitmap->Reset();
+ }
+ }
+ break;
+ }
+ iScratchBitmap->Reset();
+ }
+ break;
+ }
+ case EWsGcOpDrawSegmentedPolygon:
+ iGc->DrawPolygon(iPolyPoints,iPolyPointListSize,pData.DrawSegmentedPolygon->fillRule);
+ break;
+ case EWsGcOpDrawPolygon:
+ DoDrawPolygon(pData.Polygon);
+ break;
+ case EWsGcOpDrawPolyLine:
+ DoDrawPolyLine(pData.PolyLine, EFalse);
+ break;
+ case EWsGcOpDrawPolyLineContinued:
+ DoDrawPolyLine(pData.PolyLine, ETrue);
+ break;
+ case EWsGcOpClear:
+ iGc->Clear(TRect(iWin->Size()));
+ break;
+ case EWsGcOpClearRect:
+ iGc->Clear(*pData.Rect);
+ break;
+ case EWsGcOpDrawRect:
+ iGc->DrawRect(*pData.Rect);
+ break;
+ case EWsGcOpDrawEllipse:
+ iGc->DrawEllipse(*pData.Rect);
+ break;
+ case EWsGcOpDrawRoundRect:
+ iGc->DrawRoundRect(*pData.Rect,pData.RoundRect->ellipse);
+ break;
+ case EWsGcOpDrawArc:
+ iGc->DrawArc(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
+ break;
+ case EWsGcOpDrawPie:
+ iGc->DrawPie(*pData.Rect,pData.ArcOrPie->start,pData.ArcOrPie->end);
+ break;
+ case EWsGcOpCopyRect:
+ iGc->CopyRect(pData.CopyRect->pos,*pData.Rect);
+ break;
+ case EWsGcOpMapColors:
+ iGc->MapColors(pData.MapColors->rect,(TRgb *)(pData.MapColors+1),pData.MapColors->numPairs,pData.MapColors->mapForwards);
+ break;
+ default:
+ TRAP_IGNORE(iWin->OwnerPanic(EWservPanicOpcode));
+ break;
+ }
+ // DEBUGOSB // comment in for per-draw-command debug osb updates
+ iGc->SetClippingRegion(NULL);
+ iCurrentClippingRegion = NULL;
+ }
+
+TInt CPlaybackGc::WsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle)
+ {
+ TInt handle=0;
+ switch(aOpcode)
+ {
+ case EWsGcOpGdiWsBlt2:
+ handle=pData.GdiBlt2->handle;
+ break;
+ case EWsGcOpGdiWsBlt3:
+ handle=pData.GdiBlt3->handle;
+ break;
+ case EWsGcOpGdiWsBltMasked:
+ handle=pData.GdiBltMasked->handle;
+ aMaskHandle = pData.GdiBltMasked->maskHandle;
+ break;
+ case EWsGcOpGdiWsAlphaBlendBitmaps:
+ handle=pData.AlphaBlendBitmaps->bitmapHandle;
+ aMaskHandle = pData.AlphaBlendBitmaps->alphaHandle;
+ break;
+ case EWsGcOpWsDrawBitmapMasked:
+ handle=pData.iBitmapMasked->iHandle;
+ aMaskHandle=pData.iBitmapMasked->iMaskHandle;
+ break;
+ }
+ return handle;
+ }
+
+TInt CPlaybackGc::FbsBitmapHandle(TInt aOpcode, const TWsGcCmdUnion &pData, TInt& aMaskHandle)
+ {
+ TInt handle=0;
+ aMaskHandle=0;
+ switch(aOpcode)
+ {
+ case EWsGcOpGdiWsBlt2:
+ case EWsGcOpGdiWsBlt3:
+ case EWsGcOpGdiWsBltMasked:
+ case EWsGcOpGdiWsAlphaBlendBitmaps:
+ {
+ TInt maskHandle = 0;
+ DWsBitmap *bitmap=(DWsBitmap *)iWin->WsOwner()->HandleToObj(WsBitmapHandle(aOpcode,pData, maskHandle), WS_HANDLE_BITMAP);
+ WS_ASSERT_DEBUG(bitmap, EWsPanicDrawCommandsInvalidState);
+ if (bitmap)
+ handle=bitmap->FbsBitmap()->Handle();
+ if (aOpcode==EWsGcOpGdiWsBltMasked || aOpcode==EWsGcOpGdiWsAlphaBlendBitmaps)
+ {
+ DWsBitmap *bitmap2=(DWsBitmap *)iWin->WsOwner()->HandleToObj(maskHandle, WS_HANDLE_BITMAP);
+ WS_ASSERT_DEBUG(bitmap2, EWsPanicDrawCommandsInvalidState);
+ if (bitmap2)
+ aMaskHandle=bitmap2->FbsBitmap()->Handle();
+ }
+ break;
+ }
+ case EWsGcOpGdiBlt2:
+ handle=pData.GdiBlt2->handle;
+ break;
+ case EWsGcOpGdiBlt3:
+ handle=pData.GdiBlt3->handle;
+ break;
+ case EWsGcOpGdiBltMasked:
+ handle=pData.GdiBltMasked->handle;
+ aMaskHandle=pData.GdiBltMasked->maskHandle;
+ break;
+ case EWsGcOpGdiAlphaBlendBitmaps:
+ handle=pData.AlphaBlendBitmaps->bitmapHandle;
+ aMaskHandle=pData.AlphaBlendBitmaps->alphaHandle;
+ break;
+ case EWsGcOpDrawBitmap:
+ handle=pData.Bitmap->handle;
+ break;
+ case EWsGcOpDrawBitmap2:
+ handle=pData.Bitmap2->handle;
+ break;
+ case EWsGcOpDrawBitmap3:
+ handle=pData.Bitmap3->handle;
+ break;
+ case EWsGcOpDrawBitmapMasked:
+ handle=pData.iBitmapMasked->iHandle;
+ aMaskHandle=pData.iBitmapMasked->iMaskHandle;
+ break;
+ }
+ return handle;
+ }
+
+
+void CPlaybackGc::UpdateJustification(TText* aText,TInt aLen, const TDesC8& aCmdData)
+ {
+ iGc->UpdateJustification(BufferTPtr(aText,aLen,aCmdData));
+ }
+
+void CPlaybackGc::DoDrawing(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
+ {
+ TWsGcCmdUnion pData;
+ pData.any=aCmdData.Ptr();
+
+ // Andy. We do this every time? Shouldn't this be set up for us already by the render stage?
+ // infact, aren't we breaking the render stage by doing it here?
+ iGc->SetUserDisplayMode(iWin->DisplayMode());
+ if (iClippingRectSet)
+ {
+ iGc->SetOrigin(iMasterOrigin);
+ iGc->SetClippingRect(iClippingRect);
+ }
+ iGc->SetOrigin(iMasterOrigin + iOrigin);
+
+ DoDrawCommand(aOpcode,aCmdData,iDrawRegion);
+
+ iGc->CancelClippingRect();
+ iGc->SetUserDisplayMode(ENone);
+ switch(aOpcode)
+ {
+ case EWsGcOpDrawLine:
+ iLinePos=pData.DrawLine->pnt2;
+ break;
+ case EWsGcOpDrawTo:
+ case EWsGcOpMoveTo:
+ case EWsGcOpPlot:
+ iLinePos=(*pData.Point);
+ break;
+ case EWsGcOpDrawBy:
+ case EWsGcOpMoveBy:
+ iLinePos+=(*pData.Point);
+ break;
+ case EWsGcOpDrawSegmentedPolygon:
+ EndSegmentedPolygon();
+ break;
+ case EWsGcOpDrawText:
+ UpdateJustification((TText *)(pData.DrawText+1),pData.DrawText->length,aCmdData);
+ break;
+ case EWsGcOpDrawTextVertical:
+ UpdateJustification((TText *)(pData.DrawTextVertical+1),pData.DrawTextVertical->length,aCmdData);
+ break;
+ case EWsGcOpDrawBoxText:
+ UpdateJustification((TText *)(pData.BoxText+1),pData.BoxText->length,aCmdData);
+ break;
+ case EWsGcOpDrawBoxTextOptimised1:
+ UpdateJustification((TText *)(pData.BoxTextO1+1),pData.BoxTextO1->length,aCmdData);
+ break;
+ case EWsGcOpDrawBoxTextOptimised2:
+ UpdateJustification((TText *)(pData.BoxTextO2+1),pData.BoxTextO2->length,aCmdData);
+ break;
+ case EWsGcOpDrawBoxTextVertical:
+ UpdateJustification((TText *)(pData.DrawBoxTextVertical+1),pData.DrawBoxTextVertical->length,aCmdData);
+ break;
+ case EWsGcOpDrawTextLocal:
+ iGc->UpdateJustification(*pData.DrawTextLocal->desc);
+ break;
+ case EWsGcOpDrawBoxTextLocal:
+ iGc->UpdateJustification(*pData.BoxTextLocal->desc);
+ break;
+ case EWsGcOpDrawTextPtr:
+ iGc->UpdateJustification(*pData.DrawTextPtr->text);
+ break;
+ case EWsGcOpDrawTextVerticalPtr:
+ iGc->UpdateJustification(*pData.DrawTextVerticalPtr->text);
+ break;
+ case EWsGcOpDrawBoxTextPtr:
+ iGc->UpdateJustification(*pData.DrawBoxTextPtr->text);
+ break;
+ case EWsGcOpDrawBoxTextVerticalPtr:
+ iGc->UpdateJustification(*pData.DrawBoxTextVerticalPtr->text);
+ break;
+ }
+ }
+
+void CPlaybackGc::CommandL(TWsGcOpcodes aOpcode, const TDesC8& aCmdData)
+ {
+ TWsGcCmdUnion pData;
+ pData.any=aCmdData.Ptr();
+
+ switch(aOpcode)
+ {
+ case EWsGcOpStartSegmentedDrawPolygon:
+ StartSegmentedDrawPolygonL(pData.StartSegmentedDrawPolygon);
+ break;
+ case EWsGcOpSegmentedDrawPolygonData:
+ SegmentedDrawPolygonData(pData.SegmentedDrawPolygonData);
+ break;
+ case EWsGcOpSetClippingRegion:
+ WS_ASSERT_DEBUG(aOpcode != EWsGcOpSetClippingRegion, EWsPanicDrawCommandsInvalidState);
+ break;
+ case EWsGcOpSetClippingRect:
+ SetClippingRect(*pData.Rect);
+ break;
+ case EWsGcOpCancelClippingRect:
+ ResetClippingRect();
+ break;
+ case EWsGcOpCancelClippingRegion:
+ CancelUserClippingRegion();
+ break;
+ case EWsGcOpSetFaded:
+ iGc->SetFaded(*pData.Bool);
+ break;
+ case EWsGcOpSetFadeParams:
+ iGc->SetFadingParameters(WservEncoding::ExtractFirst8BitValue(*pData.UInt),WservEncoding::ExtractSecond8BitValue(*pData.UInt));
+ break;
+ case EWsGcOpSetDrawMode:
+ iGc->SetDrawMode((CGraphicsContext::TDrawMode)*pData.UInt);
+ break;
+ case EWsGcOpUseFont:
+ if (CWsFontCache::Instance()->UseFont(iFont, *pData.UInt))
+ iGc->UseFont(*pData.UInt);
+ else
+ iGc->UseFontNoDuplicate(iFont);
+ break;
+ case EWsGcOpDiscardFont:
+ CWsFontCache::Instance()->ReleaseFont(iFont);
+ iGc->DiscardFont();
+ break;
+ case EWsGcOpSetUnderlineStyle:
+ iGc->SetUnderlineStyle(*pData.SetUnderlineStyle);
+ break;
+ case EWsGcOpSetStrikethroughStyle:
+ iGc->SetStrikethroughStyle(*pData.SetStrikethroughStyle);
+ break;
+ case EWsGcOpUseBrushPattern:
+ iGc->UseBrushPattern(*pData.handle);
+ break;
+ case EWsGcOpDiscardBrushPattern:
+ iGc->DiscardBrushPattern();
+ break;
+ case EWsGcOpSetBrushColor:
+ iGc->SetBrushColor(*pData.rgb);
+ break;
+ case EWsGcOpSetPenColor:
+ iGc->SetPenColor(*pData.rgb);
+ break;
+ case EWsGcOpSetPenStyle:
+ iGc->SetPenStyle((CGraphicsContext::TPenStyle)*pData.UInt);
+ break;
+ case EWsGcOpSetPenSize:
+ iGc->SetPenSize(*pData.Size);
+ break;
+ case EWsGcOpSetBrushStyle:
+ iGc->SetBrushStyle((CGraphicsContext::TBrushStyle)*pData.UInt);
+ break;
+ case EWsGcOpReset:
+ CWsFontCache::Instance()->ReleaseFont(iFont);
+ iGc->Reset();
+ iOrigin.SetXY(0,0);
+ ResetClippingRect();
+ iGc->SetBrushColor(iWin->BackColor());
+ break;
+ case EWsGcOpSetBrushOrigin:
+ iGc->SetBrushOrigin(*pData.Point);
+ break;
+ case EWsGcOpSetDitherOrigin:
+ iGc->SetDitherOrigin(*pData.Point);
+ break;
+ case EWsGcOpSetWordJustification:
+ iGc->SetWordJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
+ break;
+ case EWsGcOpSetCharJustification:
+ iGc->SetCharJustification(pData.SetJustification->excessWidth, pData.SetJustification->numGaps);
+ break;
+ case EWsGcOpSetOrigin:
+ SetOrigin(*pData.Point);
+ break;
+ case EWsGcOpSetOpaque:
+ // Andy - opaque drawing has not been implemented yet.
+ //SetOpaque(*pData.Bool);
+ break;
+ case EWsGcOpSetShadowColor:
+ iGc->SetShadowColor(*pData.rgb);
+ break;
+ default: // Assume remaining functions will draw
+ {
+ DoDrawing(aOpcode,aCmdData);
+ return;
+ }
+ }
+ }
+
+void CPlaybackGc::SetOrigin(const TPoint &aOrigin)
+ {
+ iOrigin=aOrigin;
+ }
+
+/*------------------------------------------------------------------------------
+ Description: Retrieves graphics context information back from a given buffer
+ from a given start position.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeL(const CBufBase& aBuffer,TInt& aStartPos)
+ {
+ // Open the stream used for the input from the given start position
+ // in the buffer.
+ RBufReadStream bufReadStream;
+ bufReadStream.Open(aBuffer,aStartPos);
+ CleanupClosePushL(bufReadStream);
+
+ // Read the font/bitmap server data
+ iGc->InternalizeL(bufReadStream);
+
+ iOrigin.iX = bufReadStream.ReadInt32L();
+ iOrigin.iY = bufReadStream.ReadInt32L();
+
+ iClippingRectSet=bufReadStream.ReadInt8L();
+
+ // If there is a clipping rectangle data read it.
+ if (iClippingRectSet)
+ bufReadStream>>iClippingRect;
+
+ // Force FbsBitGc to reset its user clipping rect in case orientation has changed.
+ // The user clipping rect of FbsBitGc will be set to iClippingRect later before
+ // drawing the command.
+ iGc->CancelClippingRect();
+
+ // Read the clipping region data
+ InternalizeClippingRegionL(bufReadStream);
+
+ // Read the Alpha values for Brush and Pen colors.
+ InternalizeAlphaValueL(bufReadStream);
+
+ CleanupStack::PopAndDestroy(&bufReadStream);
+ }
+
+/*------------------------------------------------------------------------------
+ Description: Retrieves TRgb::alpha value information back from a given buffer
+ and updates the Brushcolor with the same.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeAlphaValueL(RReadStream& aReadStream)
+ {
+ TRgb brushColor(iGc->BrushColor());
+ brushColor.SetAlpha(aReadStream.ReadUint8L());
+ iGc->SetBrushColor(brushColor);
+ TRgb penColor(iGc->PenColor());
+ penColor.SetAlpha(aReadStream.ReadUint8L());
+ iGc->SetPenColor(penColor);
+ }
+
+/*------------------------------------------------------------------------------
+ Description: Helper method to retrieve clipping region data from a given
+ read stream.
+ -----------------------------------------------------------------------------*/
+void CPlaybackGc::InternalizeClippingRegionL(RReadStream& aReadStream)
+ {
+ WS_ASSERT_DEBUG(iTargetRegion, EWsPanicDrawCommandsInvalidState);
+ // Read flag to indicate if client had defined a clipping region
+ TBool clipRegion = aReadStream.ReadInt8L();
+ CancelUserClippingRegion();
+ if (clipRegion)
+ {
+ // Note that this clipping region is in window relative coordinates when
+ // received from the client (and being stored) but is in screen relative
+ // coordinates after being retrieved from the redraw store.
+ iUserDefinedClippingRegion = InternalizeRegionL(aReadStream);
+ iUserDefinedClippingRegion->Offset(iWin->Origin());
+ iUserDefinedClippingRegion->Intersect(*iTargetRegion);
+ if (iUserDefinedClippingRegion->CheckError()) // fallback to no user clipping region
+ {
+ CancelUserClippingRegion();
+ }
+ else
+ {
+ iDrawRegion = iUserDefinedClippingRegion;
+ }
+ }
+ }
+
+/**
+This pretty much replaces the whole of what was TDrawDestination
+This can only be sensibly called from outside a sequence of drawing commands,
+since it negates any user defined clipping regions.
+*/
+void CPlaybackGc::SetTargetRegion(const TRegion* aRegion)
+ {
+ iTargetRegion = aRegion;
+ iDrawRegion = iTargetRegion;
+ CancelUserClippingRegion();
+ }
+
+void CPlaybackGc::Reset()
+ {
+ iGc->Reset();
+ }
+
+TAny * CPlaybackGc::ResolveObjectInterface(TUint aId)
+ {
+ switch (aId)
+ {
+ case MWsWindow::EWsObjectInterfaceId:
+ return dynamic_cast<MWsWindow *>(iWin);
+ case MWsFader::EWsObjectInterfaceId:
+ return iWin->Screen()->Fader();
+ }
+ return NULL;
+ }