Files
player/Project/Src/MyWin/MyWinCore/mywin_lcd.c

661 lines
14 KiB
C
Raw Normal View History

2025-06-27 00:32:57 +08:00
#include "mywin_inc.h"
WIN_LcdStruct *WIN_CreatVirtualLcd (int x_size,int y_size)
{
WIN_LcdStruct *ret=mymalloc (sizeof (WIN_LcdStruct));
mymemset (ret,0,sizeof (WIN_LcdStruct));
ret->x_size=x_size;
ret->y_size=y_size;
ret->WindowSrcX=0;
ret->WindowSrcY=0;
ret->WindowDstX=ret->x_size-1;
ret->WindowDstY=ret->y_size-1;
ret->ScreenDis=1;
ret->BackColor=0;
ret->Color=0xffff;
ret->DrawMode=1;
ret->DrawAddr=mymalloc (ret->x_size*ret->y_size*2);
return ret;
}
void WIN_DeleteVirtualLcd (WIN_LcdStruct *lcd)
{
if (lcd->DrawAddr) myfree (lcd->DrawAddr);
myfree (lcd);
}
//设置屏幕显示方向
void WIN_LcdSetScreenDis (WIN_LcdStruct *lcd,int d)
{
if (d) lcd->ScreenDis=1;
else lcd->ScreenDis=0;
}
//设置活动窗口
void WIN_LcdSetWindow (WIN_LcdStruct *lcd,int x_s,int y_s,int x_size,int y_size)
{
int dstx=0;
int dsty=0;
if (x_size<1) x_size=1;
if (y_size<1) y_size=1;
if (x_s>lcd->x_size-1) x_s=lcd->x_size-1;
else if (x_s<0) x_s=0;
if (y_s>lcd->y_size-1) y_s=lcd->y_size-1;
else if (y_s<0) y_s=0;
dstx=x_s+x_size-1;
dsty=y_s+y_size-1;
if (dstx>lcd->x_size-1) dstx=lcd->x_size-1;
else if (dstx<0) dstx=0;
if (dsty>lcd->y_size-1) dsty=lcd->y_size-1;
else if (dsty<0) dsty=0;
lcd->WindowSrcX=x_s;
lcd->WindowSrcY=y_s;
lcd->WindowDstX=dstx;
lcd->WindowDstY=dsty;
}
int WIN_LcdGetWindowSizeX (WIN_LcdStruct *lcd)
{
return lcd->WindowDstX-lcd->WindowSrcX+1;
}
int WIN_LcdGetWindowSizeY (WIN_LcdStruct *lcd)
{
return lcd->WindowDstY-lcd->WindowSrcY+1;
}
int WIN_LcdGetLcdSizeX(WIN_LcdStruct *lcd)
{
return lcd->x_size;
}
int WIN_LcdGetLcdSizeY (WIN_LcdStruct *lcd)
{
return lcd->y_size;
}
u32 WIN_LcdSetLcdColor (WIN_LcdStruct *lcd,u32 color)
{
u32 ret=lcd->Color;
//g_lcd_struct.Color=color;
lcd->Color=COLOR888TO565(color);
return ret;
}
u32 WIN_LcdSetLcdBkColor (WIN_LcdStruct *lcd,u32 color)
{
u32 ret=lcd->BackColor;
//g_lcd_struct.BackColor=color;
lcd->BackColor=COLOR888TO565(color);
return ret;
}
u32 WIN_LcdSetLcdColor16 (WIN_LcdStruct *lcd,u32 color)
{
u32 ret=lcd->Color;
lcd->Color=(color);
return ret;
}
u32 WIN_LcdSetLcdBkColor16 (WIN_LcdStruct *lcd,u32 color)
{
u32 ret=lcd->BackColor;
lcd->BackColor=(color);
return ret;
}
u32 WIN_LcdGetLcdColor (WIN_LcdStruct *lcd)
{
u32 ret=lcd->Color;
return COLOR565TO888(ret);
}
u32 WIN_LcdGetLcdBkColor (WIN_LcdStruct *lcd)
{
u32 ret=lcd->BackColor;
return COLOR565TO888(ret);
}
u32 WIN_LcdGetLcdColor16 (WIN_LcdStruct *lcd)
{
u32 ret=lcd->Color;
return ret;
}
u32 WIN_LcdGetLcdBkColor16 (WIN_LcdStruct *lcd)
{
u32 ret=lcd->BackColor;
return ret;
}
//设置绘制模式1不绘制背景0绘制背景
void WIN_LcdSetLcdDrawMode (WIN_LcdStruct *lcd,int mode)
{
if (mode)
{
lcd->DrawMode=1;//此时调用画点函数时不绘制背景色
}
else
{
lcd->DrawMode=0;
}
}
//填充一条线,以窗口的起点为起点,最大填充到窗口的终点位置
static void WIN_LcdFillLine16 (WIN_LcdStruct *lcd,u16 *buff,int y,int xsize)
{
u16 *addr=lcd->DrawAddr;
int xsizeMax=lcd->WindowDstX+1-lcd->WindowSrcX;
if (xsize>xsizeMax) xsize=xsizeMax;
if (lcd->ScreenDis)
{
addr=&addr[y*lcd->x_size+lcd->WindowSrcX];
for (int x=0;x<xsize;x++)
{
addr[x]=*buff;
buff++;
}
}
else
{
addr=&addr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+lcd->WindowSrcX)];
for (int x=0;x<xsize;x++)
{
*addr--=*buff;
buff++;
}
}
}
//把图像填充到屏幕的活动窗口中,
//参数xsize,图像的宽度
//参数ysize,图像的高度
static void WIN_LcdFillRect16 (WIN_LcdStruct *lcd,u16 *buff,int xsize,int ysize)
{
int ysizeMax=lcd->WindowDstY+1-lcd->WindowSrcY;
if (ysize>ysizeMax) ysize=ysizeMax;
for (int y=0;y<ysize;y++)
{
WIN_LcdFillLine16 (lcd,buff,y+lcd->WindowSrcY,xsize);
buff+=xsize;
}
}
//把图像偏移之后填充到屏幕的活动窗口中,
//参数x_s,图像要显示的横向起始坐标
//参数y_s图像要显示的纵向起始坐标
//参数xsize,图像的宽度
//参数ysize,图像的高度
static void WIN_LcdFillRectOff16 (WIN_LcdStruct *lcd,u16 *buff,int x_s,int y_s,int xsize,int ysize)
{
int offset=y_s*xsize+x_s;
WIN_LcdFillRect16(lcd,buff+offset,xsize,ysize-y_s);
}
//在活动窗口的指定位置显示图片
//参数s_x,图像在绘图窗口中的坐标
//参数s_y,图像在绘图冲口中的坐标
//参数s_xsize,要绘制的部分图像大小
//参数s_ysize,要绘制的部分图像大小
//参数x_s,图像要显示的横向起始坐标
//参数y_s图像要显示的纵向起始坐标
//参数xsize,图像的宽度
//参数ysize,图像的高度
void WIN_LcdFillRectOff16At (WIN_LcdStruct *lcd,int s_x,int s_y,int s_xsize,int s_ysize,u16 *buff,int x_s,int y_s,int xsize,int ysize)
{
//保存以前的窗口大小
int w_x=lcd->WindowSrcX;
int w_y=lcd->WindowSrcY;
int w_x_e=lcd->WindowDstX;
int w_y_e=lcd->WindowDstY;
//设置新的窗口大小
lcd->WindowSrcX=w_x+s_x;
lcd->WindowSrcY=w_y+s_y;
lcd->WindowDstX=lcd->WindowSrcX+s_xsize-1;
lcd->WindowDstY=lcd->WindowSrcY+s_ysize-1;
//限制新的绘图区不能在以前的窗口之外
if (lcd->WindowDstX>w_x_e) lcd->WindowDstX=w_x_e;
if (lcd->WindowDstY>w_y_e) lcd->WindowDstY=w_y_e;
//绘图
WIN_LcdFillRectOff16 (lcd,buff,x_s+s_x,y_s+s_y,xsize,ysize);
//恢复以前的绘图区
lcd->WindowSrcX=w_x;
lcd->WindowSrcY=w_y;
lcd->WindowDstX=w_x_e;
lcd->WindowDstY=w_y_e;
}
//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围
void WIN_LcdDrawPointSafe (WIN_LcdStruct *lcd,int x,int y,int mode)
{
x+=lcd->WindowSrcX;
y+=lcd->WindowSrcY;
//在窗口以外的不画
if (x<lcd->WindowSrcX||x>lcd->WindowDstX) return;
if (y<lcd->WindowSrcY||y>lcd->WindowDstY) return;
u16 *DrawAddr=lcd->DrawAddr;
if (mode)
{
if (lcd->ScreenDis)
DrawAddr[(y*lcd->x_size+x)]=lcd->Color;
else
DrawAddr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=lcd->Color;
}
else if (lcd->DrawMode==0)
{
if (lcd->ScreenDis)
DrawAddr[(y*lcd->x_size+x)]=lcd->BackColor;
else
DrawAddr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=lcd->BackColor;
}
else//当g_lcd_struct.DrawMode==1时不绘制背景色
{
}
}
//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围
//以指定颜色画点,而不是前景色
void WIN_LcdDrawPointSafeColor (WIN_LcdStruct *lcd,int x,int y,u16 color)
{
x+=lcd->WindowSrcX;
y+=lcd->WindowSrcY;
//在窗口以外的不画
if (x<lcd->WindowSrcX||x>lcd->WindowDstX) return;
if (y<lcd->WindowSrcY||y>lcd->WindowDstY) return;
u16 *DrawAddr=lcd->DrawAddr;
if (1)
{
if (lcd->ScreenDis)
DrawAddr[(y*lcd->x_size+x)]=color;
else
DrawAddr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=color;
}
}
//快速ALPHA BLENDING算法.
//src:源颜色
//dst:目标颜色
//alpha:透明程度(0~32)
//返回值:混合后的颜色.
static u16 alpha_blend565(u16 src,u16 dst,u8 alpha)
{
u32 src2;
u32 dst2;
//Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB|
src2=((src<<16)|src)&0x07E0F81F;
dst2=((dst<<16)|dst)&0x07E0F81F;
//Perform blending R:G:B with alpha in range 0..32
//Note that the reason that alpha may not exceed 32 is that there are only
//5bits of space between each R:G:B value, any higher value will overflow
//into the next component and deliver ugly result.
dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;
return (dst2>>16)|dst2;
}
//以指定色透明度画点0~32,0,全透明31不透明
void WIN_LcdDrawPointSafeColorAlpha (WIN_LcdStruct *lcd,int x,int y,u16 color,u8 alpha)
{
x+=lcd->WindowSrcX;
y+=lcd->WindowSrcY;
//在窗口以外的不画
if (x<lcd->WindowSrcX||x>lcd->WindowDstX) return;
if (y<lcd->WindowSrcY||y>lcd->WindowDstY) return;
if (alpha>31 ) alpha=31;
if (alpha==0) return;
u16 *DrawAddr=lcd->DrawAddr;
u16 color_old=0;
if (1)
{
if (lcd->ScreenDis)
{
color_old=DrawAddr[(y*lcd->x_size+x)];
color=alpha_blend565 (color_old,color,alpha);
DrawAddr[(y*lcd->x_size+x)]=color;
}
else
{
color_old=DrawAddr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)];
color=alpha_blend565 (color_old,color,alpha);
DrawAddr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=color;
}
}
}
//填充矩形,已窗口坐标为原点
void WIN_LcdFillRectByColor (WIN_LcdStruct *lcd,int x,int y,int x_size,int y_size)
{
for (int i=y;i<y+y_size;i++)
{
for (int j=x;j<x+x_size;j++)
{
WIN_LcdDrawPointSafe (lcd,j,i,1);
}
}
}
//以透明度填充矩形,已窗口坐标为原点
void WIN_LcdFillRectByColorAlpha (WIN_LcdStruct *lcd,int x,int y,int x_size,int y_size,u8 alpha)
{
for (int i=y;i<y+y_size;i++)
{
for (int j=x;j<x+x_size;j++)
{
WIN_LcdDrawPointSafeColorAlpha (lcd,j,i,lcd->Color,alpha);
}
}
}
//绘制图标,图标使用const数组编译在程序里其本身已经附带了大小等参数
//此函数效率比较低,只用于绘制小图标,绘制图片使用矩形填充函数
void WIN_LcdDrawImag (WIN_LcdStruct *lcd,int x,int y,int xsize,int ysize,const u8 *buff)
{
if (buff==0) return ;
u8 scan=buff[0];
u8 gray=buff[1];
u16 w=*((u16*)&buff[2]);
u16 h=*((u16*)&buff[4]);
u8 is565=buff[6];
u8 rgb=buff[7];
//必须所有参数都符合要求
if ((scan!=0x00)||(gray!=0x10)||(w>WIN_IMAGE_MAXSIZE)||(h>WIN_IMAGE_MAXSIZE)||(is565!=0x01)||(rgb!=0x1b))
return;
u16 *imag=(u16 *)(buff+8);
if (xsize>w) xsize=w;
if (ysize>h) ysize=h;
for (int j=y;j<y+ysize;j++)
{
for (int i=0;i<xsize;i++)
{
WIN_LcdDrawPointSafe(lcd,i+x,j,imag[i]);
}
imag+=w;
}
}
//绘制图标,但是不绘制指定颜色
void WIN_LcdDrawImagButColor (WIN_LcdStruct *lcd,int x,int y,int xsize,int ysize,const u8 *buff,u16 color)
{
if (buff==0) return ;
u8 scan=buff[0];
u8 gray=buff[1];
u16 w=*((u16*)&buff[2]);
u16 h=*((u16*)&buff[4]);
u8 is565=buff[6];
u8 rgb=buff[7];
//必须所有参数都符合要求
if ((scan!=0x00)||(gray!=0x10)||(w>WIN_IMAGE_MAXSIZE)||(h>WIN_IMAGE_MAXSIZE)||(is565!=0x01)||(rgb!=0x1b))
return;
u16 *imag=(u16 *)(buff+8);
if (xsize>w) xsize=w;
if (ysize>h) ysize=h;
for (int j=y;j<y+ysize;j++)
{
for (int i=0;i<xsize;i++)
{
if (imag[i]!=color)
WIN_LcdDrawPointSafe(lcd,i+x,j,imag[i]);
}
imag+=w;
}
}
//绘制图标,把图像的有效部分绘制为指定颜色
//此函数效率比较低,只用于绘制小图标,绘制图片使用矩形填充函数
void WIN_LcdDrawImagByColor (WIN_LcdStruct *lcd,int x,int y,int xsize,int ysize,const u8 *buff,u16 color)
{
if (buff==0) return ;
u8 scan=buff[0];
u8 gray=buff[1];
u16 w=*((u16*)&buff[2]);
u16 h=*((u16*)&buff[4]);
u8 is565=buff[6];
u8 rgb=buff[7];
//必须所有参数都符合要求
if ((scan!=0x00)||(gray!=0x10)||(w>WIN_IMAGE_MAXSIZE)||(h>WIN_IMAGE_MAXSIZE)||(is565!=0x01)||(rgb!=0x1b))
return;
u16 *imag=(u16 *)(buff+8);
if (xsize>w) xsize=w;
if (ysize>h) ysize=h;
for (int j=y;j<y+ysize;j++)
{
for (int i=0;i<xsize;i++)
{
if ((imag[i]!=0x0000)&&(imag[i]!=0xffff))
WIN_LcdDrawPointSafeColor (lcd,i+x,j,color);
}
imag+=w;
}
}
//绘制图标,把原图像转化为透明度,用指定颜色来绘制
//此函数效率比较低,只用于绘制小图标,绘制图片使用矩形填充函数
void WIN_LcdDrawImagByAlpha (WIN_LcdStruct *lcd,int x,int y,int xsize,int ysize,const u8 *buff,u16 color)
{
if (buff==0) return ;
u8 scan=buff[0];
u8 gray=buff[1];
u16 w=*((u16*)&buff[2]);
u16 h=*((u16*)&buff[4]);
u8 is565=buff[6];
u8 rgb=buff[7];
//必须所有参数都符合要求
if ((scan!=0x00)||(gray!=0x10)||(w>WIN_IMAGE_MAXSIZE)||(h>WIN_IMAGE_MAXSIZE)||(is565!=0x01)||(rgb!=0x1b))
return;
u16 *imag=(u16 *)(buff+8);
u8 r,g,b;
u8 alpha=0;
if (xsize>w) xsize=w;
if (ysize>h) ysize=h;
for (int j=y;j<y+ysize;j++)
{
for (int i=0;i<xsize;i++)
{
//只绘制无效窗口内的屏幕
// WIN_Struct *ewin=WIN_GetWinStruct();
// if (POS_InRect (ewin->Invalid_x,ewin->Invalid_y,ewin->Invalid_x_size,ewin->Invalid_y_size,i+x,j))
{
//白色全透明不绘制,加快速度
if ((imag[i]!=0x0000)&&(imag[i]!=0xffff))
{
WIN_LcdDrawPointSafeColorAlpha (lcd,i+x,j,color,31-(imag[i]>>11));
}
else if (imag[i]==0x0000)
{
//不透明直接画原来的颜色
WIN_LcdDrawPointSafeColor (lcd,i+x,j,color);
}
}
}
imag+=w;
}
}
//清除绘图窗口内的显示
void WIN_LcdClear (WIN_LcdStruct *lcd)
{
u16 *addr=lcd->DrawAddr;
for (int y=lcd->WindowSrcY;y<=lcd->WindowDstY;y++)
{
if (lcd->ScreenDis)
{
for (int x=lcd->WindowSrcX;x<=lcd->WindowDstX;x++)
{
addr[(y*lcd->x_size+x)]=lcd->BackColor;
}
}
else
{
for (int x=lcd->WindowSrcX;x<=lcd->WindowDstX;x++)
{
addr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=lcd->BackColor;
}
}
}
}
//清除矩形内的显示
void WIN_LcdClearRect (WIN_LcdStruct *lcd,int x,int y,int x_size,int y_size)
{
u16 *addr=lcd->DrawAddr;
x=x+lcd->WindowSrcX;
y=y+lcd->WindowSrcY;
int x_e=x+x_size-1;
if (x_e>lcd->WindowDstX)
x_e=lcd->WindowDstX;
int y_e=y+y_size-1;
if (y_e>lcd->WindowDstY)
y_e=lcd->WindowDstY;
int temp=x;
for (;y<=y_e;y++)
{
if (lcd->ScreenDis)
{
for (x=temp;x<=x_e;x++)
{
addr[(y*lcd->x_size+x)]=lcd->BackColor;
}
}
else
{
for (x=temp;x<=x_e;x++)
{
addr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)]=lcd->BackColor;
}
}
}
}
//获取指定矩形空间的屏幕颜色,屏幕的绝对坐标
void WIN_LcdGetColors (WIN_LcdStruct *lcd,u16 *buff,int x_s,int y_s,int x_size,int y_size)
{
u16 *addr=lcd->DrawAddr;
if (x_s<0) x_s=0;
else if (x_s>lcd->x_size-1) x_s=lcd->x_size-1;
if (y_s<0) y_s=0;
else if (y_s>lcd->y_size-1) y_s=lcd->y_size-1;
if (x_size>lcd->x_size-x_s) x_size= lcd->x_size-x_s;
else if (x_size<0) x_size=0;
if (y_size>lcd->y_size-y_s) y_size= lcd->y_size-y_s;
else if (y_size<0) y_size=0;
for (int y=y_s;y<y_size+y_s;y++)
{
if (lcd->ScreenDis)
{
for (int x=x_s;x<x_size+x_s;x++)
{
u32 temp=addr[(y*lcd->x_size+x)];
*buff=temp;
buff++;
}
}
else
{
for (int x=x_s;x<x_size+x_s;x++)
{
u32 temp=addr[lcd->x_size*lcd->y_size-1-(y*lcd->x_size+x)];
*buff=temp;
buff++;
}
}
}
}