Chop out the code that handles "additional _E32Dll entry point after last ordinal position". I can't agree with that as how the DLL is supposed to work, and gives errors for me. Maybe the scripts to re-generate the jump tables have not been tried recently so its not a problem that's been hit by others.
// 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;
}