📄 terminalcontrols2font.cpp
字号:
/* terminals2font.cpp * * A terminal UI control using a CS2Font bitmap font * * Copyright 2002,2004-2005 Petteri Kangaslampi * * See license.txt for full copyright and license information.*/#include <e32std.h>#include <gdi.h>#include <eikenv.h>#include <e32svr.h>#include "terminalcontrols2font.h"#include "s2font.h"#include "oneshottimer.h"#include "logfile.h"#define KSelectCursorXor TRgb(0x00ffff00)const TInt KUpdateTimerDelay = 10000;_LIT(KTerminalControlS2Font, "tcs2");#ifdef LOGFILE_ENABLEDstatic void AssertFail(TInt aLine) { LFPRINT((_L("ASSERT FAIL: terminalcontrols2font.cpp %d"), aLine)); User::Panic(KTerminalControlS2Font, aLine);}#define assert(x) __ASSERT_ALWAYS(x, AssertFail(__LINE__))#else#define assert(x) __ASSERT_ALWAYS(x, User::Panic(KTerminalControlS2Font, __LINE__))#endif#define TRACE LFPRINT((_L("terminalcontrols2font.cpp %d"), __LINE__))// Factory methodCTerminalControlS2Font *CTerminalControlS2Font::NewL( MTerminalObserver &aObserver, const TRect &aRect, RWindow &aContainerWindow, CS2Font &aFont) { CTerminalControlS2Font *self = new (ELeave) CTerminalControlS2Font(aObserver, aFont); CleanupStack::PushL(self); self->ConstructL(aRect, aContainerWindow); CleanupStack::Pop(self); return self;}// ConstructorCTerminalControlS2Font::CTerminalControlS2Font( MTerminalObserver &aObserver, CS2Font &aFont) : CTerminalControl(aObserver), iFont(&aFont) { iFontHeight = iFont->FontSize().iHeight; iFontWidth = iFont->FontSize().iWidth;}// Second-phase constructorvoid CTerminalControlS2Font::ConstructL(const TRect &aRect, RWindow &aContainerWindow) { iTimer = COneShotTimer::NewL(TCallBack(UpdateCallBack, this)); CTerminalControl::ConstructL(aRect, aContainerWindow); }// DestructorCTerminalControlS2Font::~CTerminalControlS2Font() { delete [] iDirtyLeft; delete [] iDirtyRight; delete iTimer; delete iRowBitmapGc; delete iRowBitmapDevice; delete iRowBitmap; delete iRowTextBuf;}// Set fontvoid CTerminalControlS2Font::SetFontL(CS2Font &aFont) { iFont = &aFont; iFontHeight = iFont->FontSize().iHeight; iFontWidth = iFont->FontSize().iWidth; Resize();}// (re)allocate buffersvoid CTerminalControlS2Font::AllocateBuffersL() { delete [] iDirtyLeft; iDirtyLeft = NULL; delete [] iDirtyRight; iDirtyRight = NULL; delete iRowBitmapGc; iRowBitmapGc = NULL; delete iRowBitmapDevice; iRowBitmapDevice = NULL; delete iRowBitmap; iRowBitmap = NULL; delete iRowTextBuf; iRowTextBuf = NULL; iRowBitmap = new CFbsBitmap(); TDisplayMode displayMode = SystemGc().Device()->DisplayMode(); if ( (displayMode != EColor4K) && (displayMode != EColor64K) ) { displayMode = EColor64K; } User::LeaveIfError(iRowBitmap->Create(TSize(iCharWidth*iFontWidth, iFontHeight), displayMode)); iRowBitmapDevice = CFbsBitmapDevice::NewL(iRowBitmap); iRowBitmapGc = CFbsBitGc::NewL(); iDirtyLeft = new (ELeave) TInt[iCharHeight]; iDirtyRight = new (ELeave) TInt[iCharHeight]; iRowTextBuf = HBufC::NewL(iCharWidth); CTerminalControl::AllocateBuffersL();}// Clear buffersvoid CTerminalControlS2Font::Clear() { for ( TInt y = 0; y < iCharHeight; y++ ) { iDirtyLeft[y] = iCharWidth; iDirtyRight[y] = -1; } CTerminalControl::Clear();}// Updates one more characters on a line to the displayvoid CTerminalControlS2Font::UpdateDisplay(TInt aX, TInt aY, TInt aLength) { assert((aX >= 0) && ((aX + aLength) <= iCharWidth)); assert((aY >= 0) && (aY < iCharHeight)); // Mark the area dirty if ( iDirtyLeft[aY] > aX ) { iDirtyLeft[aY] = aX; } if ( iDirtyRight[aY] < (aX + aLength - 1) ) { iDirtyRight[aY] = aX + aLength - 1; } StartUpdateTimer();}// Updates one more characters on a line to the display.// This method requires a valid graphics context and window server sessionvoid CTerminalControlS2Font::UpdateWithGc(CBitmapContext &aGc, RWsSession &aWs, TInt aX, TInt aY, TInt aLength) const { assert((aX >= 0) && ((aX + aLength) <= iCharWidth)); assert((aY >= 0) && (aY < iCharHeight)); LFPRINT((_L("UpdateWithGc(gc, ws, %d, %d, %d)"), aX, aY, aLength)); TInt x0 = Rect().iTl.iX; TInt y0 = Rect().iTl.iY; // We'll first render all runs of identical updates at one go to the // bitmap, render the cursor if necessary, and finally blit the bitmap // to the screen TTerminalAttribute *attribs = &iAttributes[aY * iCharWidth + aX]; TInt x = 0; while ( x < aLength ) { // Initial attributes and colors TTerminalAttribute &a0 = attribs[x]; TRgb fg0, bg0; GetFinalColors(aX+x, aY, fg0, bg0); // Attributes and colors for this character TTerminalAttribute *a = &attribs[x]; TRgb fg, bg; GetFinalColors(aX+x, aY, fg, bg); TInt num = 0; do { num++; if ( (x+num) < aLength ) { a++; GetFinalColors(aX+x+num, aY, fg, bg); if ( (fg != fg0) || (bg != bg0) || (a->iBold != a0.iBold) || (a->iUnderline != a0.iUnderline) ) { break; } } } while ( (x+num) < aLength ); TPtr text = iRowTextBuf->Des(); text.Zero(); for ( TInt i = 0; i < num; i++ ) { TText c = FinalChar(aX+x+i, aY); // Our fonts contain nothing at the line break character, map // it to "CR" since we don't really have better alternatives if ( c == 0x2028 ) { c = 0x240d; } text.Append(c); } iFont->RenderText(*iRowBitmap, text, (aX+x) * iFontWidth, 0, fg0, bg0); x += num; } // Draw the selection cursor to the bitmap if necessary if ( iSelectMode && ((iSelectY == aY) && (iSelectX >= aX) && (iSelectX < (aX + aLength))) ) { iRowBitmapGc->Activate(iRowBitmapDevice); iRowBitmapGc->Reset(); iRowBitmapGc->SetBrushStyle(CGraphicsContext::ENullBrush); iRowBitmapGc->SetDrawMode(CGraphicsContext::EDrawModeXOR); iRowBitmapGc->SetPenStyle(CGraphicsContext::ESolidPen); iRowBitmapGc->SetPenColor(KSelectCursorXor); iRowBitmapGc->DrawRect(TRect(TPoint(iSelectX * iFontWidth, 0), TSize(iFontWidth, iFontHeight))); } // Blit aGc.BitBlt(TPoint(x0 + aX*iFontWidth, y0 + aY*iFontHeight), iRowBitmap, TRect(aX*iFontWidth, 0, (aX+aLength)*iFontWidth, iFontHeight)); aWs.Flush(); TRACE;}// CCoeControl::Draw()void CTerminalControlS2Font::Draw(const TRect & /*aRect*/) const { CWindowGc &gc = SystemGc(); gc.Reset(); RWsSession &ws = CCoeEnv::Static()->WsSession(); if ( iGrayed ) { gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.SetBrushColor(TRgb(0xcccccc)); gc.SetPenStyle(CGraphicsContext::ENullPen); gc.DrawRect(Rect()); } else { // Draw everything and mark all lines not dirty for ( TInt y = 0; y < iCharHeight; y++ ) { UpdateWithGc(gc, ws, 0, y, iCharWidth); iDirtyLeft[y] = iCharWidth; iDirtyRight[y] = -1; } }}// Start update timervoid CTerminalControlS2Font::StartUpdateTimer() { // We don't want to restart the timer for every update, just use it to // delay updates a bit so that we don't need to do too many small // updates if ( !iTimerRunning ) { iTimer->After(KUpdateTimerDelay); iTimerRunning = ETrue; }}// Update all dirty areas on the screenvoid CTerminalControlS2Font::Update() { iTimerRunning = EFalse; CWindowGc &gc = SystemGc(); gc.Activate(Window()); RWsSession &ws = CCoeEnv::Static()->WsSession(); // Go through each line, finding areas that need updating. On those lines // we'll first render all runs of identical updates at one go to the // bitmap, render the cursor if necessary, and finally blit the bitmap // to the screen for ( TInt y = 0; y < iCharHeight; y++ ) { // Skip lines that are fully up to date if ( (iDirtyRight[y] < iDirtyLeft[y]) ) { continue; } // Draw the line to the display UpdateWithGc(gc, ws, iDirtyLeft[y], y, iDirtyRight[y]-iDirtyLeft[y]+1); // No longer dirty iDirtyLeft[y] = iCharWidth; iDirtyRight[y] = -1; } gc.Deactivate();}// Update timer callbackTInt CTerminalControlS2Font::UpdateCallBack(TAny *aPtr) { ((CTerminalControlS2Font*)aPtr)->Update(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -