📄 dirscracceng.cpp
字号:
/*
* ============================================================================
* Name : CDirScrAccEng from DirScrAccEng.cpp
* Part of : DirScrAcc
* Created : 06/11/2003 by Forum Nokia
* Description:
* Engine for drawing using Direct Screen Access.
* Version :
* Copyright: Nokia Corporation
* ============================================================================
*/
#include "DirScrAccEng.h"
#include "DirScrAccRenderer.h"
#include <eikenv.h>
// This number is for runnning in the device. Drawing would be too fast if the number were smaller.
// For the emulator this number is less relevant. Emulator knows only ticks that are 1/10 seconds.
// Device ticks are 1/64 seconds.
const TInt KGenerationInterval = 10000;
_LIT(KDirScrAccTxt, "DirectScreenAccessDemo");
//
// class CDirScrAccEng
//
CDirScrAccEng::CDirScrAccEng(RWsSession& aClient, CWsScreenDevice& aScreenDevice, RWindow& aWindow, TBool aUseFrameBuffer)
: CTimer(CActive::EPriorityStandard),
iClient(aClient),
iScreenDevice(aScreenDevice),
iWindow(aWindow),
iDirectScreenAccess(0),
iGc(0),
iRegion(0),
iPosition(0,0),
iDrawing(EFalse),
iRenderer(0),
iScreenAddr(0),
iOffScreenBmp(0),
iUseFrameBuffer(aUseFrameBuffer)
{
iFlagRect.SetRect(iPosition, aWindow.Size());
// calculate the (used) frame buffer size in bytes
iFrameBufLen = iFlagRect.Width() * iFlagRect.Height() * 2;
}
CDirScrAccEng* CDirScrAccEng::NewL(RWsSession& aClient, CWsScreenDevice& aScreenDevice, RWindow& aWindow, TBool aUseFrameBuffer)
{
CDirScrAccEng* self = new (ELeave) CDirScrAccEng(aClient, aScreenDevice, aWindow, aUseFrameBuffer);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(); // self;
return self;
}
CDirScrAccEng::~CDirScrAccEng()
{
if(IsActive())
Cancel();
delete iDirectScreenAccess;
delete iRenderer;
delete iOffScreenBmp;
}
void CDirScrAccEng::ConstructL()
{
// contruct the timer
CTimer::ConstructL();
// Create the DSA object
iDirectScreenAccess = CDirectScreenAccess::NewL(iClient, iScreenDevice, iWindow, *this);
CActiveScheduler::Add(this);
// create the offscreen bitmap
iOffScreenBmp = new (ELeave) CFbsBitmap;
iOffScreenBmp->Create(iScreenDevice.SizeInPixels(), EColor4K);
// for emulator, always use offscreen bitmap
#if defined(__WINS__)
iUseFrameBuffer = EFalse;
#endif
if(iUseFrameBuffer)
{
// fetch screen buffer address
TScreenInfoV01 screenInfo;
TPckg<TScreenInfoV01> sInfo(screenInfo);
UserSvr::ScreenInfo(sInfo);
iScreenAddr = screenInfo.iScreenAddressValid ? (TUint8*)screenInfo.iScreenAddress : 0;
User::LeaveIfNull(iScreenAddr);
// skip the palette data in the beginning of frame buffer (16 entries in 12bit mode)
iScreenAddr += 16 * 2;
// initialise the raw redraw event (used when drawing directly to frame buffer)
iRedraw.Set(TRawEvent::ERedraw);
}
// create our renderer
iRenderer = CFlagRenderer::NewL(iFlagRect.Width(), iFlagRect.Height());
}
// Start Drawing
void CDirScrAccEng::StartDrawingL()
{
if (iDrawing)
User::Panic(KDirScrAccTxt, DirScrAccEngAlreadyStarted);
// Initialise DSA
// Trap the call to CDirectScreenAccess->StartL() to suppress system
// error notes (e.g. active screen saver may cause problems)
TRAPD(dsaErr, iDirectScreenAccess->StartL());
if(dsaErr == KErrNone)
{
// Get graphics context for it
iGc = iDirectScreenAccess->Gc();
// Get region that DSA can draw in
iRegion = iDirectScreenAccess->DrawingRegion();
// Set the display to clip to this region
iGc->SetClippingRegion(iRegion);
iDrawing = ETrue;
// request a timer event after a defined interval
After(TTimeIntervalMicroSeconds32(KGenerationInterval));
}
}
// Stop Drawing
void CDirScrAccEng::StopDrawing()
{
if (!iDrawing)
User::Panic(KDirScrAccTxt, DirScrAccEngAlreadyStopped);
// Cancel timer and display
// This is CActive::Cancel, which calls derived method DoCancel
Cancel();
iDrawing = EFalse;
}
// Implement MDirectScreenAccess
void CDirScrAccEng::Restart(RDirectScreenAccess::TTerminationReasons /*aReason*/)
{
// Restart display
// Note that this will result in the clipping region being updated
// so that menus, overlaying dialogs, etc. will not be drawn over
StartDrawingL();
}
void CDirScrAccEng::AbortNow(RDirectScreenAccess::TTerminationReasons /*aReason*/)
{
// Cancel timer and display
Cancel();
iDrawing = EFalse;
}
// Timer's RunL()
void CDirScrAccEng::RunL()
{
iRenderer->RenderNextFrameL((TUint8*)iOffScreenBmp->DataAddress());
// blit the offscreen bitmap (if used) to screen
if(!iUseFrameBuffer)
{
iGc->BitBlt(iPosition, iOffScreenBmp, iFlagRect);
// Force screen update: this is required for WINS, but may
// not be for all hardware.
// For Series 60 devices this is necessary,
// we can't access screen memory directly,
// rather we access a screen buffer.
iDirectScreenAccess->ScreenDevice()->Update();
}
else
{
// copy bitmap contents to frame buffer
Mem::Copy(iScreenAddr, iOffScreenBmp->DataAddress(), iFrameBufLen);
// Drawing to screen buffer (ScreenInfo) - force update
// We do not use Graphics context, so we generate an event to get screen refreshed
// As a side-effect, the backlight stays on
UserSvr::AddEvent(iRedraw);
}
// Renew request
After(TTimeIntervalMicroSeconds32(KGenerationInterval));
}
// Timer's DoCancel()
void CDirScrAccEng::DoCancel()
{
// Cancel timer
CTimer::DoCancel();
// Cancel DSA
iDirectScreenAccess->Cancel();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -