This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/lib/lcd/gui/Core/GUICurs.c

424 lines
12 KiB
C

/*
*********************************************************************************************************
* uC/GUI
* Universal graphic software for embedded applications
*
* (c) Copyright 2002, Micrium Inc., Weston, FL
* (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
* µC/GUI is protected by international copyright laws. Knowledge of the
* source code may not be used to write a similar product. This file may
* only be used in accordance with a license and should not be redistributed
* in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File : GUICurs.C
Purpose : Cursor routines of the graphics library
---------------------------END-OF-HEADER------------------------------
*/
#include <stddef.h> /* needed for definition of NULL */
#include "GUI_Private.h"
#if GUI_SUPPORT_CURSOR
/*********************************************************************
*
* static data
*
**********************************************************************
*/
static GUI_HMEM _hBuffer;
static GUI_RECT _Rect;
static char _CursorIsVis; /* Currently visible ? */
static char _CursorOn;
static const GUI_CURSOR GUI_UNI_PTR * _pCursor;
static U8 _CursorDeActCnt;
static int _AllocSize;
static int _x, _y; /* Position of hot spot */
static GUI_RECT _ClipRect;
static LCD_PIXELINDEX _ColorIndex[4]; /* Color-Cache */
/*********************************************************************
*
* static code, helper functions
*
**********************************************************************
*/
/*********************************************************************
*
* _SetPixelIndex
*
* Purpose
* Sets the pixel index for the Cursor.
* Note the following:
* - We do the clipping in this routine
* - We do NOT call the driver directly, but thru its API table.
* This allows others (e.g. the VNC server) to be in the loop-
*/
static void _SetPixelIndex(int x, int y, int Index) {
if ((y >= _ClipRect.y0) && (y <= _ClipRect.y1)) {
if ((x >= _ClipRect.x0) && (x <= _ClipRect.x1)) {
LCD_aAPI[0]->pfSetPixelIndex(x, y, Index);
}
}
}
/*********************************************************************
*
* _GetPixelIndex
*
* Purpose
* Gets a pixel index for the Cursor.
*/
static int _GetPixelIndex(int x, int y) {
if ((y >= _ClipRect.y0) && (y <= _ClipRect.y1)) {
if ((x >= _ClipRect.x0) && (x <= _ClipRect.x1)) {
return LCD_L0_GetPixelIndex(x, y);
}
}
return 0;
}
/*********************************************************************
*
* _Undraw
*
* Purpose
* Remove the cursors
*/
static void _Undraw(void) {
int x, y, xSize, ySize;
LCD_PIXELINDEX* pData;
/* Save bitmap data */
GUI_LOCK();
if (_hBuffer) {
pData = (LCD_PIXELINDEX*)GUI_ALLOC_h2p(_hBuffer);
xSize = _Rect.x1 - _Rect.x0 + 1;
ySize = _Rect.y1 - _Rect.y0 + 1;
for (y = 0; y < ySize; y++) {
for (x = 0; x < xSize; x++) {
_SetPixelIndex(x + _Rect.x0, y + _Rect.y0, *(pData + x));
}
pData += _pCursor->pBitmap->XSize;
}
}
GUI_UNLOCK();
}
/*********************************************************************
*
* _Log2Phys
*/
static int _Log2Phys(int Index) {
if (Index < 4) {
return _ColorIndex[Index];
} else {
LCD_COLOR Color = *(_pCursor->pBitmap->pPal->pPalEntries + Index);
return LCD_Color2Index(Color);
}
}
/*********************************************************************
*
* _Draw
*/
static void _Draw(void) {
int x, y, xSize, ySize;
LCD_PIXELINDEX* pData;
const GUI_BITMAP GUI_UNI_PTR * pBM;
GUI_LOCK();
if (_hBuffer) {
/* Save bitmap data */
pBM = _pCursor->pBitmap;
pData = (LCD_PIXELINDEX*)GUI_ALLOC_h2p(_hBuffer);
xSize = _Rect.x1 - _Rect.x0 + 1;
ySize = _Rect.y1 - _Rect.y0 + 1;
for (y = 0; y < ySize; y++) {
for (x = 0; x < xSize; x++) {
int BitmapPixel;
*(pData + x) = _GetPixelIndex(_Rect.x0 + x, _Rect.y0 + y);
BitmapPixel = GUI_GetBitmapPixelIndex(pBM, x, y);
if (BitmapPixel) {
_SetPixelIndex(_Rect.x0 + x, _Rect.y0 + y, _Log2Phys(BitmapPixel));
}
}
pData += pBM->XSize;
}
}
GUI_UNLOCK();
}
/*********************************************************************
*
* _CalcRect
*/
static void _CalcRect(void) {
if (_pCursor) {
_Rect.x0 = _x - _pCursor->xHot;
_Rect.y0 = _y - _pCursor->yHot;
_Rect.x1 = _Rect.x0 + _pCursor->pBitmap->XSize - 1;
_Rect.y1 = _Rect.y0 + _pCursor->pBitmap->YSize - 1;
}
}
/*********************************************************************
*
* _Hide
*/
static void _Hide(void) {
if (_CursorIsVis) {
_Undraw();
_CursorIsVis = 0;
}
}
/*********************************************************************
*
* _Show
*/
static void _Show(void) {
if (_CursorOn && (_CursorDeActCnt==0)) {
_CursorIsVis = 1;
_Draw();
}
}
/*********************************************************************
*
* _TempHide
*
* Purpose:
* Hide cursor if a part of the given rectangle is located in the
* rectangle used for the cursor. This routine is called automatically
* by the window manager. This way the window manager can
* automatically make sure that the cursor is always displayed
* correctly.
*
* Params:
* pRect Rectangle under consideration
*
* Return value:
* 0: No action taken
* Cursor was not visible or not affected because rectangles
* did not overlap
* 1: Cursor hidden -> WM needs to restore cursor after
* drawing operation
*/
static char _TempHide(const GUI_RECT* pRect) {
if (!_CursorIsVis) {
return 0; /* Cursor not visible -> nothing to do */
}
if ((pRect == NULL) || GUI_RectsIntersect(pRect, &_Rect)) {
_Hide(); /* Cursor needs to be hidden */
return 1;
}
return 0; /* Cursor not affected -> nothing to do */
}
/*********************************************************************
*
* _TempUnhide
*/
static void _TempUnhide(void) {
_Show();
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_CURSOR_Activate
*/
void GUI_CURSOR_Activate(void) {
GUI_LOCK();
if ((--_CursorDeActCnt) ==0) {
_Show();
}
GUI_UNLOCK();
}
/*********************************************************************
*
* GUI_CURSOR_Deactivate
*/
void GUI_CURSOR_Deactivate(void) {
GUI_LOCK();
if (_CursorDeActCnt++ ==0)
_Hide();
GUI_UNLOCK();
}
/*********************************************************************
*
* GUI_CURSOR_Select
*/
const GUI_CURSOR GUI_UNI_PTR * GUI_CURSOR_Select(const GUI_CURSOR GUI_UNI_PTR * pCursor) {
int AllocSize;
const GUI_BITMAP GUI_UNI_PTR * pBM;
const GUI_CURSOR GUI_UNI_PTR * pOldCursor;
GUI_LOCK();
pOldCursor = _pCursor;
if (pCursor != _pCursor) {
int i;
pBM = pCursor->pBitmap;
i = pBM->pPal->NumEntries > 4 ? 4 : pBM->pPal->NumEntries;
while (i--) {
LCD_COLOR Color = *(pBM->pPal->pPalEntries + i);
_ColorIndex[i] = LCD_Color2Index(Color);
}
_Hide();
AllocSize = pBM->XSize * pBM->YSize * sizeof(LCD_PIXELINDEX);
if (AllocSize != _AllocSize) {
GUI_ALLOC_Free(_hBuffer);
_hBuffer = 0;
}
_hBuffer = GUI_ALLOC_AllocZero(AllocSize);
_CursorOn = 1;
_pCursor = pCursor;
_CalcRect();
_Show();
}
GUI_UNLOCK();
return pOldCursor;
}
/*********************************************************************
*
* GUI_CURSOR_Hide
*/
void GUI_CURSOR_Hide(void) {
GUI_LOCK();
_Hide();
_CursorOn = 0;
/* Set function pointer which window manager can use */
GUI_CURSOR_pfTempHide = NULL;
GUI_CURSOR_pfTempUnhide = NULL;
GUI_UNLOCK();
}
/*********************************************************************
*
* GUI_CURSOR_Show
*/
void GUI_CURSOR_Show(void) {
GUI_LOCK();
LCDDEV_L0_GetRect(&_ClipRect);
_Hide();
_CursorOn = 1;
/* Set function pointer which window manager can use */
GUI_CURSOR_pfTempHide = _TempHide;
GUI_CURSOR_pfTempUnhide = _TempUnhide;
if (!_pCursor) {
GUI_CURSOR_Select(GUI_DEFAULT_CURSOR);
} else {
_Show();
}
GUI_UNLOCK();
}
/*********************************************************************
*
* GUI_CURSOR_SetPosition
*/
void GUI_CURSOR_SetPosition(int xNewPos, int yNewPos) {
int x, xStart, xStep, xEnd, xOff, xOverlapMin, xOverlapMax;
int y, yStart, yStep, yEnd, yOff, yOverlapMin, yOverlapMax;
int xSize;
LCD_PIXELINDEX* pData;
GUI_LOCK();
if (_hBuffer) {
if ((_x != xNewPos) | (_y != yNewPos)) {
if (_CursorOn) {
const GUI_BITMAP GUI_UNI_PTR * pBM = _pCursor->pBitmap;
/* Save & set clip rect */
/* Compute helper variables */
pData = (LCD_PIXELINDEX*)GUI_ALLOC_h2p(_hBuffer);
xSize = _pCursor->pBitmap->XSize;
xOff = xNewPos - _x;
if (xOff > 0) {
xStep = 1;
xStart = 0;
xEnd = _pCursor->pBitmap->XSize;
xOverlapMax = xEnd -1;
xOverlapMin = xOff;
} else {
xStep = -1;
xStart = xSize - 1;
xEnd = -1;
xOverlapMin = 0;
xOverlapMax = xStart + xOff;
}
yOff = yNewPos - _y;
if (yOff > 0) {
yStep = 1;
yStart = 0;
yEnd = _pCursor->pBitmap->YSize;
yOverlapMax = yEnd -1;
yOverlapMin = yOff;
} else {
yStep = -1;
yStart = _pCursor->pBitmap->YSize - 1;
yEnd = -1;
yOverlapMin = 0;
yOverlapMax = yStart + yOff;
}
/* Restore & Draw */
for (y = yStart; y != yEnd; y += yStep) {
char yOverlaps;
char yNewOverlaps;
int yNew = y + yOff;
yOverlaps = (y >= yOverlapMin) && (y <= yOverlapMax);
yNewOverlaps = (yNew >= yOverlapMin) && (yNew <= yOverlapMax);
for (x= xStart; x != xEnd; x += xStep) {
char xyOverlaps, xyNewOverlaps;
int BitmapPixel;
LCD_PIXELINDEX Pixel;
LCD_PIXELINDEX* pSave = pData + x + y * xSize;
int xNew = x + xOff;
BitmapPixel = GUI_GetBitmapPixelIndex(pBM, x, y);
xyOverlaps = (x >= xOverlapMin) && (x <= xOverlapMax) && yOverlaps;
xyNewOverlaps = (xNew >= xOverlapMin) && (xNew <= xOverlapMax) && yNewOverlaps;
/* Restore old pixel if it was not transparent */
if (BitmapPixel) {
if (!xyOverlaps || (GUI_GetBitmapPixelIndex(pBM, x - xOff, y - yOff) == 0)) {
_SetPixelIndex(x + _Rect.x0, y + _Rect.y0, *(pSave));
}
}
/* Save */
if (xyNewOverlaps) {
Pixel = *(pData + xNew + yNew * xSize);
} else {
Pixel = _GetPixelIndex(_Rect.x0 + xNew, _Rect.y0 + yNew);
}
*pSave = Pixel;
/* Write new ... We could write pixel by pixel here */
if (BitmapPixel) {
LCD_PIXELINDEX NewPixel = _Log2Phys(BitmapPixel);
_SetPixelIndex(_Rect.x0 + xNew, _Rect.y0 + yNew, NewPixel);
}
}
}
}
_x = xNewPos;
_y = yNewPos;
_CalcRect();
}
}
GUI_UNLOCK();
}
#else
void GUICurs_C(void);
void GUICurs_C(void) {} /* avoid empty object files */
#endif /* GUI_SUPPORT_CURSOR */
/*************************** End of file ****************************/