• No results found

OpenGL Based Code CReaderView

In document A software based low vision aid (Page 67-79)

void CReaderView::renderText() {

// position raster

glRasterPos2d(-2,-1);

// load the string (or part of) into OpenGL’s back buffer glListBase(1000); glCallLists( m_textStrAll.GetLength(), GL_UNSIGNED_BYTE, CString(m_textStrAll) ); } void CReaderView::displayText() {

// translate the view into new position float posx = float(m_pos.x)/100;

glTranslatef(posx, 0, 0);

// flush any other drawing commands glFinish();

// finally swap the buffers SwapBuffers( hDC ); } void CReaderView::scroller() { if ( m_bRenderText ) {

// Clear out the color & depth buffers firstly

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); renderText();

}

displayText();

// increment the text position

if (!m_pause) m_pos.x -= m_scrollIncrement; }

59

void CReaderView::setFont() {

// prepare the fonts & sizes for the text CFont font;

font.CreateFontIndirect(&m_logFont);

// select font into the current device context HDC hDC = wglGetCurrentDC();

SelectObject( hDC, HFONT(font));

// create the list of font glyphs for use wglUseFontBitmaps(hDC, 0, 256, 1000); // set the background (clearing) colour glClearColor(0.0F, 0.0F, 0.4F, 1.0F); m_bRenderText = true;

60

Appendix A.3

DirectDraw Based Code

CReaderView

The member m_DD refers to the instance of DDGraphics. m_bufferSize is set by calling the DDGraphics function GetBufferSize().

void CReaderView::displayText() {

CRect rSrc = m_rSrcBlt;

// check for source window moving outwith the buffer if (rSrc.right >= m_bufferSize.cx)

{

// prepare to render used-up surface m_DD.RotateBackSurfaces();

// adjust rSrc back to just before start of the buffer rSrc.right = rSrc.right - m_bufferSize.cx;

rSrc.left = rSrc.left - m_bufferSize.cx; m_rSrcBlt = rSrc;

m_renderText = true; }

m_DD.Blt(m_rDstBlt, m_rSrcBlt); }

61

void CReaderView::scroller() {

if (!m_pause) {

// increment the scrolling source window position m_rSrcBlt.left += m_scrollIncrement;

m_rSrcBlt.right += m_scrollIncrement; }

// display the rendered text to screen displayText();

// perform a render to the offscreen buffer if necessary if ( m_renderText == true )

{

int charsRendered = 0;

// do the render, keeping track of characters shown charsRendered = renderText( m_textToShow );

// store an index to the last character displayed m_lastChar = m_lastChar + charsRendered;

// remove the remaining string yet to be rendered m_textToShow = m_textStrAll.Mid(m_lastChar); // check if a new string needs to be loaded if ( m_textToShow.IsEmpty() )

initiateText(); }

62

int CReaderView::renderText(CString drawMe) {

// obtain the desired font CFont font;

font.CreateFontIndirect(&m_logFont); // obtain the text to be displayed CString text = drawMe;

//// not safe for debugging beyond here – screen locked! // retrieve a handle to the GDI-style device context // of a DirectDraw offscreen (back) surface

HDC hDC;

m_DD.GetBackSurfaceDC( &hDC);

// fill the offscreen rectangle in the background color CBrush brBackground( m_backColour );

CRect rscreen = CRect(CPoint(0,0), m_surfaceSize ); FillRect(hDC, rscreen, brBackground);

// create a rectangle in the background color

CRect rect( 0, 0, m_bufferSize.cx, m_bufferSize.cy ); CBrush brBackground( m_backColour );

// prepare text attributes SetBkColor(hDC, m_backColour); SetTextColor(hDC, m_textColour); SelectObject( hDC, font );

// get widths of all characters in selected font GetCharWidth( hDC, 0, 255, &*m_lpAllCharWidths );

// calculate how much of string will fit on this surface for (int i = 0, lineLength = 0; i < text.GetLength(); i++) {

int charWidth = m_lpAllCharWidths[ text[ i ] ];

if ( lineLength + charWidth > m_surfaceSize.cx ) break; lineLength += charWidth;

}

// write the first i characters to the offscreen surface TextOut( hDC, 0, 0, text, i);

//// Now release the DC... screen unlocked again! m_DD.ReleaseBackSurfaceDC(hDC);

// now that the first i characters of text have been written // remove them from the string

text = text.Mid(i); m_bRenderText = false;

// return index of the last character displayed in given string return (drawMe.GetLength() - text.GetLength());

63

DDGraphics

void DDGraphics::Initialise( HWND hwndScreen ) {

// release any previous instances of DD object m_lpDD->Release();

m_lpDD = NULL;

CreateDD( hwndScreen ); GetCaps( hwndScreen );

// create surfaces with size of current screen CreatePrimarySurface( hwndScreen );

CreateBackSurfaces(); }

// create the DirectDraw object

// Note that extra code is required to ensure

// DirectDraw uses its version 2 interface, DirectDraw2 void DDGraphics::CreateDD( HWND hWnd )

{

LPDIRECTDRAW lpOldDD;

// create ‘old’ style DirectDraw object DirectDrawCreate( NULL, &lpOldDD, NULL ); // set DirectDraw for normal windows app

lpOldDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL ); // query the interface for DirectDraw2 object

lpOldDD->QueryInterface( IID_IDirectDraw2, (LPVOID *)&m_lpDD ); // release old DD object

lpOldDD->Release(); }

64

void DDGraphics::GetCaps( HWND hWnd ) {

// get device capabilies

DDCAPS hwCaps = {0}, helCaps = {0}; hwCaps.dwSize = sizeof(DDCAPS);

helCaps.dwSize = sizeof(DDCAPS);

// look for hardware features of interest to us m_lpDD->GetCaps(&hwCaps, &helCaps);

// is there a h/w blitter to blt between surfaces

m_bCanBltVidMem = (hwCaps.dwCaps & DDCAPS_BLT) ? true : false; // find the maximum device screen width and height

HDC hdc;

hdc = GetDC(hWnd);

m_screenWidth = GetDeviceCaps( hdc, HORZRES ); m_screenHeight = GetDeviceCaps( hdc, VERTRES ); ReleaseDC(hWnd, hdc);

// find out how much video memory there is to play with DWORD dwTotal, dwFree;

DDSCAPS ddsCaps;

ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

m_lpDD->GetAvailableVidMem(&ddsCaps, &dwTotal, &dwFree); // check there is enough video memory for 4 surfaces // i.e. primary and 3 offscreen

if ( int(dwFree) < 4 * dwWidth * dwHeight ) m_bVidMemFree = false;

65

void DDGraphics::CreatePrimarySurface( HWND hWnd ) {

// create the primary surface and attach a window clipper // Note that to be compatible with DirectDraw2, the surface // must be set up using a DirectDrawSurface3 interface LPDIRECTDRAWSURFACE lpOldSurf;

LPDIRECTDRAWCLIPPER lpddClipper;

HDC hdc;

int i;

// initialise surface descriptor

ZeroMemory(&m_sdPrimary, sizeof(m_sdPrimary));

m_sdPrimary.dwSize = sizeof(m_sdPrimary);

m_sdPrimary.dwFlags = DDSD_CAPS;

m_sdPrimary.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// create a primary surface

m_lpDD->CreateSurface(&m_sdPrimary, &lpOldSurf, NULL); // update to a DirectDraw3 compatible surface

lpOldSurf->QueryInterface(IID_IDirectDrawSurface3, &m_lpPrimSurf); // release the old surface pointer

lpOldSurf->Release();

// create a clipper: this ensures the primary surface is the // same size as the application’s window.

DirectDrawCreateClipper(0UL, &lpddClipper, NULL); // set the application window to be clipped

lpddClipper->SetHWnd(0UL, hWnd);

// attach the clipper to the primary surface and release pointer m_lpPrimSurf->SetClipper(lpddClipper);

lpddClipper->Release(); }

66

void DDGraphics::CreateBackSurfaces( HWND hWnd ) {

// Note that to be compatible with DirectDraw2, the surfaces // must be set up using a DirectDrawSurface3 interface

LPDIRECTDRAWSURFACE lpOldBackSurf1; LPDIRECTDRAWSURFACE lpOldBackSurf2; LPDIRECTDRAWSURFACE lpOldBackSurf; // set description of the back surfaces

m_sdBack.dwHeight = m_screenHeight;

m_sdBack.dwWidth = m_screenWidth;

m_sdBack.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

m_sdBack.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; // if we can use video memory, then do so.

if ( m_bCanBltVidMem && m_bVidMemFree )

m_sdBack.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; // create the first back surface

m_lpDD->CreateSurface(&m_sdBack, &lpOldBackSurf, NULL); // employ the DirectDraw3 imterface for this surface lpOldBackSurf->QueryInterface(IID_IDirectDrawSurface3,

(LPVOID *)&m_lpBackSurf); // release the old surface pointer

lpOldBackSurf->Release();

// do the same for 2nd surfaces

m_lpDD->CreateSurface(&m_sdBack, &lpOldBackSurf2, NULL); lpOldBackSurf2->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&m_lpBltSurf2); // release the old surface pointer

lpOldBackSurf2->Release(); // and finally the 3r surface

m_lpDD->CreateSurface(&m_sdBack, &lpOldBackSurf1, NULL); lpOldBackSurf1->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&m_lpBltSurf1); lpOldBackSurf1->Release();

67

void DDGraphics::Blt(CRect rDst, CRect rSrc) {

// blit from two separate surfaces, treating them a single buffer // assumes source and destination are the same size

CRect rSrc1 = rSrc, rSrc2 = rSrc, rDst1 = rDst, rDst2 = rDst; // destination width

int dwidth = rDst.right - rDst.left;

// rSrc1 and rSrc2 should never go outwith 0 and m_surfaceWidth // if source has negative left edge, wrap rSrc1

// back around onto its surface if ( rSrc.left <= 0 )

rSrc1.left = rSrc.left + m_surfaceWidth; // if right edge scrolls past buffer boundary, // wrap rSrc2 around to beginning of its surface if ( rSrc.right >= ( 2 * m_screenWidth ) )

rSrc2.right = rSrc.right - m_surfaceWidth; // set fixed points of two sub rectangles

rSrc1.right = surfaceWidth; rSrc2.left = 0;

// get new widths of source rectangles int width1 = rSrc1.right – rSrc1.left; int width2 = rSrc2.right – rSrc2.left;

// adjust destination rectangles to match these widths rDst1.right = rDst1.left + width1;

rDst2.left = rDst2.right – width2; // perform the blitting operations

// provided the source rectangles are valid if (width1 > 0)

m_lpPrimSurf->Blt( &rDst1, m_lpBltSurf1, &rSrc1 ); if (width2 > 0)

m_lpPrimSurf->Blt( &rDst2, m_lpBltSurf2, &rSrc2 ); }

68

void DDGraphics::RotateBackSurfaces(BOOL forward) {

// this function flips the three back surfaces // in a circular fashion LPDIRECTDRAWSURFACE3 tmpSurf; if (forward) { tmpSurf = m_lpBackSurf; m_lpBackSurf = m_lpBltSurf2; m_lpBltSurf2 = m_lpBltSurf1; m_lpBltSurf1 = tmpSurf; } else // backwards { tmpSurf = m_lpBltSurf1; m_lpBltSurf1 = m_lpBltSurf2; m_lpBltSurf2 = m_lpBackSurf; m_lpBackSurf = tmpSurf; } }

69

DDGraphics Page Flipping

The code for Page flipping is included for completeness. It has not yet been integrated into the main application.

void DDGraphics::CreateFlipSurfaces() {

// create two back buffer flippable surfaces LPDIRECTDRAWSURFACE lpFlipSurf1;

LPDIRECTDRAWSURFACE lpFlipSurf2;

// flippable back surfaces should be almost identical to primary // so describe primary surface and copy onto flip descriptionS m_lpPrimSurf->GetSurfaceDesc(&m_sdPrimary);

memcpy(&m_sdFlip, &m_sdPrimary, sizeof(DDSURFACEDESC)); m_sdFlip.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

m_sdFlip.dwFlags = DDSD_WIDTH | DDSD_HEIGHT

| DDSD_PIXELFORMAT | DDSD_CAPS; // if we can use video memory, then do so.

if (m_bCanBltVidMem)

m_sdBack.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; // now create flip surface 1 in similar manner as before m_lpDD->CreateSurface(&m_sdFlip, &lpFlipSurf1, NULL); lpFlipSurf1->QueryInterface( IID_IDirectDrawSurface3,

(LPVOID *)&m_lpFlipSurf1); // now create flip surface 2

m_lpDD->CreateSurface(&m_sdFlip, &lpFlipSurf2, NULL); lpFlipSurf1->QueryInterface( IID_IDirectDrawSurface3,

(LPVOID *)&m_lpFlipSurf2); // attach flip surfaces to the primary

m_lpPrimSurf->AddAttachedSurface(m_lpFlipSurf1); m_lpPrimSurf->AddAttachedSurface(m_lpFlipSurf2); }

void DDGraphics::Flip() {

// flip with wait until finished flag

return m_lpPrimSurf->Flip(NULL, (DWORD)DDFLIP_WAIT); }

70

Appendix A.4

In document A software based low vision aid (Page 67-79)

Related documents