📄 swcursor.cpp
字号:
/*++
Copyright:
Copyright (c) 1998,2002-2003 BSQUARE Corporation. All rights reserved.
Module Name:
swcursor.h
Abstract:
This module is the implemenation of the software cursor.
Author:
Edward Sumanaseni, 5-Nov-1998
Revisions:
--*/
#include "headers.h"
#include "gpe.h"
#include "swcursor.h"
SOFT_CURSOR::SOFT_CURSOR(
IN GPE *pGpe
)
/*++
Routine Description:
SOFT_CURSOR class contructor.
Arguments:
pGpe - Pointer to a GPE object.
Returns:
None.
--*/
{
//
// Initialize data members.
//
m_pGpe = pGpe;
m_pANDSurf = NULL;
m_pXORSurf = NULL;
m_pBackBuf = NULL;
m_bCursorVisible = FALSE;
m_bCursorHidden = FALSE;
m_nCx = 0;
m_nCy = 0;
m_rclScreen.left = 0;
m_rclScreen.top = 0;
m_rclScreen.right = 0;
m_rclScreen.bottom = 0;
m_bFailedCreateSurfaces = TRUE;
m_eFormat = pGpe->PrimarySurface()->Format();
m_nBytesPerPixel = EGPEFormatToBpp[m_eFormat] / 8;
}
SOFT_CURSOR::~SOFT_CURSOR(
VOID
)
/*++
Routine Description:
SOFT_CURSOR class destructor.
Arguments:
None.
Returns:
None.
--*/
{
//
// Delete surfaces.
//
DeleteSurfaces();
}
VOID
SOFT_CURSOR::DeleteSurfaces(
VOID
)
/*++
Routine Description:
This routine deletes surfaces used by the software cursor.
Arguments:
None.
Return Value:
None.
--*/
{
if (m_pBackBuf != NULL) {
delete m_pBackBuf;
}
if (m_pANDSurf != NULL) {
delete m_pANDSurf;
}
if (m_pXORSurf != NULL) {
delete m_pXORSurf;
}
}
BOOL
SOFT_CURSOR::CreateSurfaces(
VOID
)
/*++
Routine Description:
This routine creates surfaces that are used by the software cursor.
Arguments:
None.
Return Value:
TURE if surfaces created, FALSE otherwise.
--*/
{
SCODE sc;
int SurfaceFlags = 0;
//
// Allocate cursor back buffer.
//
sc = m_pGpe->AllocSurface(
&m_pBackBuf,
SOFT_CURSOR_WIDTH_PIXELS,
SOFT_CURSOR_HEIGHT_PIXELS,
m_eFormat,
SurfaceFlags
);
if (FAILED(sc)) {
goto ErrorExit;
}
//
// Allocate AND mask surface.
//
sc = m_pGpe->AllocSurface(
&m_pANDSurf,
SOFT_CURSOR_WIDTH_PIXELS,
SOFT_CURSOR_HEIGHT_PIXELS,
m_eFormat,
SurfaceFlags
);
if (FAILED(sc)) {
goto ErrorExit;
}
//
// Allocate XOR mask surface.
//
sc = m_pGpe->AllocSurface(
&m_pXORSurf,
SOFT_CURSOR_WIDTH_PIXELS,
SOFT_CURSOR_HEIGHT_PIXELS,
m_eFormat,
SurfaceFlags
);
if (FAILED(sc)) {
goto ErrorExit;
}
//
// Surfaces successfully created.
//
m_bFailedCreateSurfaces = FALSE;
return TRUE;
ErrorExit:
m_bFailedCreateSurfaces = TRUE;
DeleteSurfaces();
return FALSE;
}
SCODE
SOFT_CURSOR::SetSWCursorShape(
IN GPESurf *pMask,
IN int cx,
IN int cy
)
/*++
Routine Description:
Sets the software cursor masks.
Arguments:
pMask - The surface of the AND and XOR masks.
cx - Cursor width in pixels.
cy - Cursor height in pixels.
Returns:
SCODE.
--*/
{
//
// Check parameters.
//
//
// Check sufaces.
//
if (m_bFailedCreateSurfaces) {
return ERROR_NOT_ENOUGH_MEMORY;
}
// hide the old cursor before we starting
// messing with the new one
HideSWCursor();
// Check the condition for just doing a CursorShow(FALSE)
if (pMask == NULL && cx == 0 && cy == 0) {
// leave the cursor hidden and get out
m_bCursorHidden = TRUE;
return S_OK;
}
// check for bad parameters
if (pMask == NULL || cx <= 0 || cy <= 0) {
return ERROR_INVALID_PARAMETER;
}
m_bCursorHidden = FALSE;
//
// Set cursor size.
//
m_nCx = cx;
m_nCy = cy;
m_rclCursor.left = 0;
m_rclCursor.right = m_nCx;
m_rclCursor.top = 0;
m_rclCursor.bottom = m_nCy;
int row, col;
int i;
int bitMask;
int maskStride = pMask->Stride();
int andStride = m_pANDSurf->Stride();
int xorStride = m_pXORSurf->Stride();
PUCHAR pucANDMask;
PUCHAR pucXORMask;
PUCHAR pANDDst8;
PUCHAR pXORDst8;
PUSHORT pANDDst16;
PUSHORT pXORDst16;
//m_pGpe->WaitForVBlank();
//
// Init AND and XOR surfaces.
//
for (row = 0; row < cy; row++) {
pucANDMask = (PUCHAR) pMask->Buffer() + (row * maskStride);
pucXORMask = (PUCHAR) pMask->Buffer() + ((row + cy) * maskStride);
pANDDst8 = (PUCHAR) m_pANDSurf->Buffer() + (row * andStride);
pXORDst8 = (PUCHAR) m_pXORSurf->Buffer() + (row * xorStride);
pANDDst16 = (PUSHORT) pANDDst8;
pXORDst16 = (PUSHORT) pXORDst8;
for (col = 0; col < cx / 8; col++) {
for (i = 0, bitMask = 0x80; i < 8; i++, bitMask >>= 1) {
if (m_eFormat == gpe8Bpp) {
*pANDDst8++ = (*pucANDMask & bitMask) ? 0xFF : 0x00;
*pXORDst8++ = (*pucXORMask & bitMask) ? 0xFF : 0x00;
}
else {
*pANDDst16++ = (*pucANDMask & bitMask) ? 0xFFFF : 0x0000;
*pXORDst16++ = (*pucXORMask & bitMask) ? 0xFFFF : 0x0000;
}
}
pucANDMask++;
pucXORMask++;
}
}
return S_OK;
}
VOID
SOFT_CURSOR::SurfaceCopy(
IN GPESurf *pSurfDst,
IN RECTL *prclDst,
IN GPESurf *pSurfSrc,
IN RECTL *prclSrc
)
/*++
Routine Description:
Source copy for surfaces having the same color depth.
Hardware acceleration is used if both surfaces are in video
memory.
Arguments:
pSurfDst - Destination surface.
prclDst - Destination surface bounding box.
pSurfSrc - Source surface.
prclSrc - Source surface bounding box.
Returns:
None.
--*/
{
//
// If one of the surfaces isn't in video memory,
// then we have to do the BLT without acceleration.
//
int dstStride = pSurfDst->Stride();
int srcStride = pSurfSrc->Stride();
int width = prclDst->right - prclDst->left;
int height = prclDst->bottom - prclDst->top;
PUCHAR pDstRow = (PUCHAR) (pSurfDst->Buffer()) +
(prclDst->top * dstStride) +
(m_nBytesPerPixel * prclDst->left);
PUCHAR pSrcRow = (PUCHAR) (pSurfSrc->Buffer()) +
(prclSrc->top * srcStride) +
(m_nBytesPerPixel * prclSrc->left);
//m_pGpe->WaitForNotBusy();
for (int i = height; i > 0; i--) {
memcpy(pDstRow, pSrcRow, width * m_nBytesPerPixel);
pDstRow += dstStride;
pSrcRow += srcStride;
}
}
SCODE
SOFT_CURSOR::HideSWCursor(
VOID
)
/*++
Routine Description:
Hides the software cursor.
Arguments:
None.
Returns:
SCODE.
--*/
{
if (m_bCursorVisible) {
SurfaceCopy(
m_pGpe->PrimarySurface(),
&m_rclScreen,
m_pBackBuf,
&m_rclCursor
);
m_bCursorVisible = FALSE;
}
return S_OK;
}
SCODE
SOFT_CURSOR::ShowSWCursor(
VOID
)
/*++
Routine Description:
Shows the software cursor.
Arguments:
None.
Returns:
SCODE.
--*/
{
if (!m_bCursorHidden && !m_bCursorVisible) {
//
// Get the destination surface.
//
GPESurf *pSurfDst = m_pGpe->PrimarySurface();
//
// Save back buffer.
//
SurfaceCopy(
m_pBackBuf,
&m_rclCursor,
pSurfDst,
&m_rclScreen
);
//
// Draw masks.
//
int row, col;
int dstStride = pSurfDst->Stride();
int srcANDStride = m_pANDSurf->Stride();
int srcXORStride = m_pXORSurf->Stride();
int width = m_rclScreen.right - m_rclScreen.left;
int height = m_rclScreen.bottom - m_rclScreen.top;
PUCHAR pDstRow = (PUCHAR) (pSurfDst->Buffer()) +
(m_rclScreen.top * dstStride) +
(m_nBytesPerPixel * m_rclScreen.left);
PUCHAR pSrcANDRow = (PUCHAR) (m_pANDSurf->Buffer()) +
(m_rclCursor.top * srcANDStride) +
(m_nBytesPerPixel * m_rclCursor.left);
PUCHAR pSrcXORRow = (PUCHAR) (m_pXORSurf->Buffer()) +
(m_rclCursor.top * srcXORStride) +
(m_nBytesPerPixel * m_rclCursor.left);
PUCHAR pDst8, pSrcAND8, pSrcXOR8;
PUSHORT pDst16, pSrcAND16, pSrcXOR16;
//m_pGpe->WaitForNotBusy();
if (m_eFormat == gpe8Bpp) {
//
// 8 Bpp format.
//
for (row = height; row > 0; row--) {
pDst8 = pDstRow;
pSrcAND8 = pSrcANDRow;
pSrcXOR8 = pSrcXORRow;
for (col = width; col > 0; col--) {
*pDst8 &= *pSrcAND8++;
*pDst8++ ^= *pSrcXOR8++;
}
pDstRow += dstStride;
pSrcANDRow += srcANDStride;
pSrcXORRow += srcXORStride;
}
}
else {
//
// 16 Bpp format.
//
for (row = height; row > 0; row--) {
pDst16 = (PUSHORT) pDstRow;
pSrcAND16 = (PUSHORT) pSrcANDRow;
pSrcXOR16 = (PUSHORT) pSrcXORRow;
for (col = width; col > 0; col--) {
*pDst16 &= *pSrcAND16++;
*pDst16++ ^= *pSrcXOR16++;
}
pDstRow += dstStride;
pSrcANDRow += srcANDStride;
pSrcXORRow += srcXORStride;
}
}
m_bCursorVisible = TRUE;
}
return S_OK;
}
SCODE
SOFT_CURSOR::MoveSWCursor(
IN int x,
IN int y,
IN int xOffset,
IN int yOffset
)
/*++
Routine Description:
This routine moves the software cursor to a new position.
Arugments:
x - New cursor screen X coordinate.
y - New cursor screen Y coordinate.
xOffset - X offset in cursor bitmap.
yOffset - Y offset in cursor bitmap.
Returns:
SCODE.
--*/
{
//m_pGpe->WaitForVBlank();
//
// Hide the old cursor.
//
HideSWCursor();
//
// Set new cursor and screen bounding rectangles.
//
m_rclCursor.left = 0;
m_rclCursor.right = m_nCx;
m_rclCursor.top = 0;
m_rclCursor.bottom = m_nCy;
m_rclScreen.left = x - xOffset;
m_rclScreen.right = m_rclScreen.left + m_nCx;
m_rclScreen.top = y - yOffset;
m_rclScreen.bottom = m_rclScreen.top + m_nCy;
int screenWidth = m_pGpe->ScreenWidth();
int screenHeight = m_pGpe->ScreenHeight();
// make sure at least part of the cursor is onscreen, if not then
// just default to drawing a zero sized cursor - ie nothing.
if (m_rclScreen.left > screenWidth || m_rclScreen.top > screenHeight
|| m_rclScreen.right < 0 || m_rclScreen.bottom < 0) {
m_rclScreen.left = m_rclScreen.right = screenWidth;
m_rclScreen.top = m_rclScreen.bottom = screenHeight;
m_rclCursor.left = m_rclCursor.right = 0;
m_rclCursor.top = m_rclCursor.bottom = 0;
}
//
// Clip to left edge of screen.
//
if (m_rclScreen.left < 0) {
m_rclScreen.left = 0;
m_rclCursor.left = m_rclCursor.right -
(m_rclScreen.right - m_rclScreen.left);
}
//
// Clip to right edge of screen.
//
if (m_rclScreen.right > screenWidth) {
m_rclScreen.right = screenWidth;
m_rclCursor.right = m_rclCursor.left +
(m_rclScreen.right - m_rclScreen.left);
}
//
// Clip to top of screen.
//
if (m_rclScreen.top < 0) {
m_rclScreen.top = 0;
m_rclCursor.top = m_rclCursor.bottom -
(m_rclScreen.bottom - m_rclScreen.top);
}
//
// Clip to bottom of screen.
//
if (m_rclScreen.bottom > screenHeight) {
m_rclScreen.bottom = screenHeight;
m_rclCursor.bottom = m_rclCursor.top +
(m_rclScreen.bottom - m_rclScreen.top);
}
//
// Draw the new cursor.
//
ShowSWCursor();
return S_OK;
}
BOOL
SOFT_CURSOR::CursorIntersect(
IN RECTL *prclBounds
)
/*++
Routine Description:
Tests for cursor intersection.
Arugments:
prclDst - Bounding box to test against cursor.
Returns:
TRUE if bounding box intersects with cursor screen location,
FALSE otherwise.
--*/
{
if (!m_bCursorVisible) {
return FALSE;
}
//
// Check for X intersect and Y intersection.
//
if (NULL==prclBounds) {
return FALSE;
}
if ((prclBounds->right > m_rclScreen.left) &&
(prclBounds->left < m_rclScreen.right) &&
(prclBounds->bottom > m_rclScreen.top) &&
(prclBounds->top < m_rclScreen.bottom)) {
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -