system/lib/lcd/gui/Core/GUI_DrawBitmapEx.c

156 lines
5.5 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 : GUI_DrawBitmapEx.c
Purpose : Draws a bitmap with free magnification
---------------------------END-OF-HEADER------------------------------
*/
#include "GUI_Private.h"
#include "stdlib.h"
/*********************************************************************
*
* static code
*
**********************************************************************
*/
/*********************************************************************
*
* GL_DrawBitmapEx
*/
static void GL_DrawBitmapEx(const GUI_BITMAP GUI_UNI_PTR * pBitmap, int x0, int y0,
int xCenter, int yCenter, int xMag, int yMag) {
LCD_PIXELINDEX Index, IndexPrev = 0;
LCD_COLOR Color;
int x, y, xi, yi, xSize, ySize, xAct, xStart, xMagAbs, xiMag, yMin, yMax, yEnd, yPrev, yStep;
char Cached, HasTrans = 0;
/* Use clipping rect to reduce calculation */
yMin = GUI_Context.ClipRect.y0;
yMax = GUI_Context.ClipRect.y1;
/* Init some values */
xSize = pBitmap->XSize;
ySize = pBitmap->YSize;
xMagAbs = ((xMag < 0) ? -xMag : xMag);
x0 -= (I32)((xMag < 0) ? xSize - xCenter - 1 : xCenter) * (I32)(xMagAbs) / (I32)(1000);
yEnd = y0 + GUI__DivideRound32(((I32)(-yCenter) * (I32)(yMag)), 1000);
yPrev = yEnd + 1;
yStep = (yMag < 0) ? -1 : 1;
if (pBitmap->pPal) {
if (pBitmap->pPal->HasTrans) {
HasTrans = 1;
}
}
for (yi = 0; yi < ySize; yi++) {
y = yEnd;
yEnd = y0 + GUI__DivideRound32(((I32)(yi + 1 - yCenter) * (I32)(yMag)), 1000);
if (y != yPrev) {
yPrev = y;
do {
if ((y >= yMin) && (y <= yMax)) {
xStart = -1;
x = 0;
xiMag = 0;
Cached = 0;
for (xi = 0; xi < xSize; xi++) {
xiMag += xMagAbs;
if (xiMag >= 1000) {
xAct = (xMag > 0) ? xi : xSize - xi - 1;
Index = GUI_GetBitmapPixelIndex(pBitmap, xAct, yi);
if (Index != IndexPrev || xStart == -1) {
if ((Index == 0) && HasTrans) {
/* Transparent color ... clear cache */
if (Cached) {
LCD_DrawHLine(x0 + xStart, y, x0 + x - 1);
Cached = 0;
}
} else {
/* Another color ... draw contents of cache */
if (Cached && xStart != -1) {
LCD_DrawHLine(x0 + xStart, y, x0 + x - 1);
}
xStart = x;
Cached = 1;
if (pBitmap->pMethods) {
Color = pBitmap->pMethods->pfIndex2Color(Index);
} else {
Color = pBitmap->pPal->pPalEntries[Index];
}
LCD_SetColorIndex(LCDDEV_L0_Color2Index(Color));
}
IndexPrev = Index;
}
do {
x++;
xiMag -= 1000;
} while (xiMag >= 1000);
}
}
/* Clear cache */
if (Cached) {
LCD_DrawHLine(x0 + xStart, y, x0 + x - 1);
}
}
y += yStep;
} while ((yMag < 0) ? (y > yEnd) : (y < yEnd));
}
}
}
/*********************************************************************
*
* public code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_DrawBitmapEx
*/
void GUI_DrawBitmapEx(const GUI_BITMAP GUI_UNI_PTR * pBitmap, int x0, int y0,
int xCenter, int yCenter, int xMag, int yMag) {
GUI_COLOR OldColor;
#if (GUI_WINSUPPORT)
GUI_RECT r;
#endif
GUI_LOCK();
OldColor = GUI_GetColor();
#if (GUI_WINSUPPORT)
WM_ADDORG(x0, y0);
if (xMag >= 0) {
r.x0 = x0 + GUI__DivideRound32(((I32)(-xCenter) * (I32)(xMag)), 1000);
r.x1 = x0 + GUI__DivideRound32(((I32)(pBitmap->XSize - xCenter - 1) * (I32)(xMag)), 1000);
} else {
r.x1 = x0 + GUI__DivideRound32(((I32)(-xCenter) * (I32)(xMag)), 1000);
r.x0 = x0 + GUI__DivideRound32(((I32)(pBitmap->XSize - xCenter - 1) * (I32)(xMag)), 1000);
}
if (yMag >= 0) {
r.y0 = y0 + GUI__DivideRound32(((I32)(-yCenter) * (I32)(yMag)), 1000);
r.y1 = y0 + GUI__DivideRound32(((I32)(pBitmap->YSize - yCenter - 1) * (I32)(yMag)), 1000);
} else {
r.y1 = y0 + GUI__DivideRound32(((I32)(-yCenter) * (I32)(yMag)), 1000);
r.y0 = y0 + GUI__DivideRound32(((I32)(pBitmap->YSize - yCenter - 1) * (I32)(yMag)), 1000);
}
WM_ITERATE_START(&r) {
#endif
GL_DrawBitmapEx(pBitmap, x0, y0, xCenter, yCenter, xMag, yMag);
#if (GUI_WINSUPPORT)
} WM_ITERATE_END();
#endif
GUI_SetColor(OldColor);
GUI_UNLOCK();
}
/*************************** End of file ****************************/