freertos_f407/User/system/lib/lcd/gui/MemDev/GUIDEV_WriteEx.c

273 lines
8.8 KiB
C

/*********************************************************************
* SEGGER MICROCONTROLLER SYSTEME GmbH *
* Solutions for real time microcontroller applications *
**********************************************************************
* *
* (c) 1996 - 2004 SEGGER Microcontroller Systeme GmbH *
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
***** emWin - Graphical user interface for embedded applications *****
emWin 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 re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File : GUIDEV_WriteEx.C
Purpose : Implementation of memory devices
---------------------------END-OF-HEADER------------------------------
*/
#include <string.h>
#include "GUI_Private.h"
#include "GUIDebug.h"
/* Memory device capabilities are compiled only if support for them is enabled.*/
#if GUI_SUPPORT_MEMDEV
/*********************************************************************
*
* static code
*
**********************************************************************
*/
/*********************************************************************
*
* _GetPixelIndex
*
*/
static int _GetPixelIndex(const U8* pData, int x, int y, int bpp, int BytesPerLine) {
if (bpp == 8) {
return (int)(*(pData + (y * BytesPerLine) + x));
} else {
return (int)(*(const U16*)(pData + (y * BytesPerLine) + (x << 1)));
}
}
/*********************************************************************
*
* _DrawHLineAlpha
*/
static void _DrawHLineAlpha(int x0, int y, int x1, int Intens) {
GUI_MEMDEV* pDev = GUI_MEMDEV_H2P(GUI_Context.hDevData);
GUI_USAGE_h hUsage = pDev->hUsage;
LCD_COLOR Color1, Color2;
int Len = x1 - x0 + 1;
if (hUsage) {
GUI_USAGE_AddHLine(GUI_USAGE_H2P(hUsage), x0, y, Len);
}
Color1 = LCD_Index2Color(LCD_COLORINDEX);
if (pDev->BitsPerPixel == 8) {
U8* pData;
pData = (U8*) GUI_MEMDEV__XY2PTR(x0, y);
while (Len--) {
Color2 = LCD_Index2Color(*(pData));
Color2 = LCD_MixColors256(Color1, Color2, Intens);
*(pData++) = LCD_Color2Index(Color2);
}
} else {
U16* pData;
pData = (U16*) GUI_MEMDEV__XY2PTR(x0, y);
while (Len--) {
Color2 = LCD_Index2Color(*(pData));
Color2 = LCD_MixColors256(Color1, Color2, Intens);
*(pData++) = LCD_Color2Index(Color2);
}
}
}
/*********************************************************************
*
* _DrawBitmapLineEx
*/
static void _DrawBitmapLineEx(int x0, int y0, int xOff, int yOff, int xSize, int xMag, int Alpha,
int bpp, int BytesPerLine, const U8* pData) {
int x, xi, xAct, xStart, xMagAbs, xiMag, xMin, xMax, Cached;
LCD_PIXELINDEX Index = 0, IndexPrev = 0;
/* Use clipping rect */
xMin = GUI_Context.ClipRect.x0 - x0;
xMax = GUI_Context.ClipRect.x1 - x0;
/* Init some values */
xMagAbs = (xMag > 0) ? xMag : -xMag;
x = (xOff * xMagAbs) / 1000;
xiMag = (xOff * xMagAbs) % 1000;
xStart = -1;
Cached = 0;
for (xi = 0; xi < xSize; xi++) {
xiMag += xMagAbs;
if (xiMag >= 1000) {
if (x <= xMax) {
xAct = (xMag > 0) ? xi : xSize - xi - 1;
Index = _GetPixelIndex(pData, xOff + xAct, yOff, bpp, BytesPerLine);
if ((Index != IndexPrev) || (xStart == -1)) {
if ((xStart != -1) && (x > xMin)) {
/* Clear cache */
if (xStart < xMin) {
xStart = xMin;
}
LCD_SetColorIndex(IndexPrev);
if (Alpha == 256 || !GUI_Context.hDevData) {
LCDDEV_L0_DrawHLine(x0 + xStart, y0, x0 + x - 1);
} else {
_DrawHLineAlpha(x0 + xStart, y0, x0 + x - 1, Alpha);
}
}
IndexPrev = Index;
xStart = x;
Cached = 1;
}
do {
x++;
xiMag -= 1000;
} while (xiMag >= 1000);
} else {
x = xMax + 1;
break;
}
}
}
if (Cached && (x > xMin)) {
/* Clear cache */
if (xStart < xMin) {
xStart = xMin;
}
LCD_SetColorIndex(Index);
if (Alpha == 256 || !GUI_Context.hDevData) {
LCDDEV_L0_DrawHLine(x0 + xStart, y0, x0 + x - 1);
} else {
_DrawHLineAlpha(x0 + xStart, y0, x0 + x - 1, Alpha);
}
}
}
/*********************************************************************
*
* _DrawBitmapEx
*/
static void _DrawBitmapEx(int x0, int y0, int xOff, int yOff, int xSize, int ySize, int xMag, int yMag,
int Alpha, int BmpSizeX, int BmpSizeY, int bpp, int BytesPerLine, const U8* pData) {
int y, yi, yMin, yMax, yEnd, yPrev;
yMin = GUI_Context.ClipRect.y0;
yMax = GUI_Context.ClipRect.y1;
if (xMag < 0) {
x0 -= (BmpSizeX - (xOff << 1) - xSize) * xMag / 1000;
}
if (yMag < 0) {
y0 -= (BmpSizeY - 1) * yMag / 1000;
}
yEnd = y0 + GUI__DivideRound32(((I32)(yOff) * yMag), 1000);
yPrev = yEnd + 1;
for (yi = yOff; yi < (yOff + ySize); yi++) {
y = yEnd;
yEnd = y0 + GUI__DivideRound32(((I32)(yi + 1) * yMag), 1000);
if (y != yPrev) {
yPrev = y;
do {
if ((y >= yMin) && (y <= yMax)) {
_DrawBitmapLineEx(x0, y, xOff, yi, xSize, xMag, Alpha, bpp, BytesPerLine, pData);
}
} while ((yMag < 0) ? (--y > yEnd) : (++y < yEnd));
}
}
}
/*********************************************************************
*
* _WriteExToActiveAt
*/
static void _WriteExToActiveAt(GUI_MEMDEV_Handle hMem, int x, int y, int xMag, int yMag, int Alpha) {
GUI_MEMDEV* pDev;
GUI_USAGE_h hUsage;
GUI_USAGE* pUsage;
U8* pData;
int yAct, yPrev, ySize, yi;
int BytesPerLine, bpp;
pDev = GUI_MEMDEV_H2P(hMem);
hUsage = pDev->hUsage;
ySize = pDev->YSize;
BytesPerLine = pDev->BytesPerLine;
pData = (U8*)(pDev + 1);
bpp = pDev->BitsPerPixel;
yPrev = y + 1;
if (hUsage) {
int xOff, xSize, y0;
pUsage = GUI_USAGE_H2P(hUsage);
for (yi = 0; yi < ySize; yi++) {
yAct = y + GUI__DivideRound32(((I32)(yi) * yMag), 1000);
if (yAct != yPrev) {
xOff = 0;
xSize = GUI_USAGE_GetNextDirty(pUsage, &xOff, yi);
if (xSize == pDev->XSize) {
/* If the entire line is affected, calculate the number of entire lines */
y0 = yi;
while (GUI_USAGE_GetNextDirty(pUsage, &xOff, yi + 1) == xSize) {
yi++;
}
_DrawBitmapEx(x, y, 0, y0, pDev->XSize, yi - y0 + 1, xMag, yMag, Alpha,
pDev->XSize, pDev->YSize, bpp, BytesPerLine, pData);
yPrev = y + GUI__DivideRound32(((I32)(yi) * yMag), 1000);
} else {
/* Draw the partial line which needs to be drawn */
while (xSize) {
_DrawBitmapEx(x, y, xOff, yi, xSize, 1, xMag, yMag, Alpha,
pDev->XSize, pDev->YSize, bpp, BytesPerLine, pData);
xOff += xSize;
xSize = GUI_USAGE_GetNextDirty(pUsage, &xOff, yi);
}
yPrev = yAct;
}
}
}
} else {
_DrawBitmapEx(x, y, 0, 0, pDev->XSize, ySize, xMag, yMag, Alpha,
pDev->XSize, pDev->YSize, bpp, BytesPerLine, pData);
}
}
/*********************************************************************
*
* public code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_MEMDEV_WriteExAt
*/
void GUI_MEMDEV_WriteExAt(GUI_MEMDEV_Handle hMem, int x, int y, int xMag, int yMag, int Alpha) {
if (hMem) {
GUI_MEMDEV* pDevData;
GUI_RECT ClipRectPrev;
GUI_LOCK();
pDevData = (GUI_MEMDEV*) GUI_ALLOC_h2p(hMem);
if (x == GUI_POS_AUTO) {
x = pDevData->x0;
y = pDevData->y0;
}
ClipRectPrev = GUI_Context.ClipRect;
LCD_SetClipRectMax();
_WriteExToActiveAt(hMem, x, y, xMag, yMag, Alpha);
GUI_Context.ClipRect = ClipRectPrev;
GUI_UNLOCK();
}
}
/*********************************************************************
*
* GUI_MEMDEV_WriteEx
*/
void GUI_MEMDEV_WriteEx(GUI_MEMDEV_Handle hMem, int xMag, int yMag, int Alpha) {
GUI_MEMDEV_WriteExAt(hMem, GUI_POS_AUTO, GUI_POS_AUTO, xMag, yMag, Alpha);
}
#else
void GUIDEV_WriteEx_C(void) {}
#endif /* GUI_SUPPORT_MEMDEV */
/*************************** end of file ****************************/