📄 wingdi.c
字号:
/******************************************************************************
*
* Copyright 2006 National ASIC Center, All right Reserved
*
* FILE NAME: gdi.c
* PROGRAMMER: ming.c
* Date of Creation: 2006/08/8
*
* DESCRIPTION:
* GDI (图形设备接口)
* NOTE:
* 本单元的设计优劣直接决定了整个GUI的显示速度,因此本单元的设计宗旨为:
* 追求执行速度为主,尽可能适当的以牺牲代码长度来换取执行速度
* FUNCTIONS LIST:
* -----------------------------------------------------------------------------
*
* -----------------------------------------------------------------------------
*
* MODIFICATION HISTORY
* LastModify 2006/10/30
******************************************************************************/
//---------------------------------------------------------------------------
#include <stdarg.h>
#include "mingui.h"
//---------------------------------------------------------------------------
static TWndCanvas *CM_AlocateCanvas(HWND hWnd);
void cmPixelOpt( PIXEL *desPixelPos, int desBitOffset, PIXEL srcValue, DWORD dwRop);
void cmHorLineOpt(PIXEL *desAddr, int desOffset, PIXEL *srcAddr, int srcOffset, int width, DWORD dwRop);
void cmHorLineXor(PIXEL *desAddr, int desOffset, PIXEL *srcAddr, int srcOffset, int width);
void cmHorLineFilterOpt(PIXEL *desAddr, int desOffset, PIXEL *srcAddr, int srcOffset, int width,PIXEL filterPixel,DWORD dwRop);
void cmHorLineFilterCopy(PIXEL *desAddr, int desOffset, PIXEL *srcAddr, int srcOffset, int width,PIXEL filterPixel);
void cmHorLineXorFilter(PIXEL *desAddr, int desOffset, PIXEL *srcAddr, int srcOffset, int width,PIXEL filterPixel);
void CM_ScaleBoxOpt(TWndCanvas *desCanvas, int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,TWndCanvas *srcCanvas, int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,DWORD dwRop);
void CM_ScaleBoxCopy(TWndCanvas *desCanvas, int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,TWndCanvas *srcCanvas, int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc);
void CM_ScaleBoxFilterCopy(TWndCanvas *desCanvas,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,TWndCanvas *srcCanvas, int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc);
void CM_ScaleBoxFilterOpt(TWndCanvas *desCanvas,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,TWndCanvas *srcCanvas, int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,DWORD dwRop);
/////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
//绘图边界检查.只要作CANVAS边界溢出检查,至于LCD视域边界检查则放在WriteToLCD中去做
//这时检查的目的是阻止画笔超出VRAM区域
//---------------------------------------------------------------------------
#if (VRAM_RANGE_CHECK==true)
//---------------------------------------------------------------------------
#define CHECK_CANVAS_RECT(ACanvas,x,y,width,height)\
{ if(ACanvas)\
{ if(x<(ACanvas)->ClipRect.left)\
{ width -= (ACanvas)->ClipRect.left - (x); \
x=(ACanvas)->ClipRect.left;\
}\
if(x+width > (ACanvas)->ClipRect.right)\
{ width = (ACanvas)->ClipRect.right-x;\
}\
if(width<=0)return;\
if(y<(ACanvas)->ClipRect.top)\
{ height -= (ACanvas)->ClipRect.top - (y); \
y=(ACanvas)->ClipRect.top;\
}\
if(y+height > (ACanvas)->ClipRect.bottom)\
{ height=(ACanvas)->ClipRect.bottom-y;\
}\
if(height<=0)return;\
}else return; \
}
//---------------------------------------------------------------------------
#define CHECK_CANVAS_HORLINE(ACanvas,x,y,width)\
if((ACanvas) && width>0 && y>=(ACanvas)->ClipRect.top && y<(ACanvas)->ClipRect.bottom)\
{ if(x<(ACanvas)->ClipRect.left)\
{ width -= (ACanvas)->ClipRect.left - (x); \
if(width<=0)return;\
x=(ACanvas)->ClipRect.left;\
}\
if(x+width>(ACanvas)->ClipRect.right)\
{ width=(ACanvas)->ClipRect.right-x;\
if(width<=0)return;\
}\
}else return;
//---------------------------------------------------------------------------
#define CHECK_CANVAS_VERLINE(ACanvas,x,y,height)\
if((ACanvas) && height>0 && x>=(ACanvas)->ClipRect.left && x<(ACanvas)->ClipRect.right)\
{ if(y<(ACanvas)->ClipRect.top)\
{ height -= (ACanvas)->ClipRect.top - (y); \
if(height<=0)return;\
y=(ACanvas)->ClipRect.top;\
}\
if(y+height>(ACanvas)->ClipRect.bottom)\
{ height=(ACanvas)->ClipRect.bottom-y;\
if(height<=0)return;\
}\
} else return;
//---------------------------------------------------------------------------
#else
//---------------------------------------------------------------------------
#define CHECK_CANVAS_RECT(ACanvas,x,y,width,height)
#define CHECK_CANVAS_HORLINE(ACanvas,x,y,width)
#define CHECK_CANVAS_VERLINE(ACanvas,x,y,height)
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//The function retrieves a handle of a display device context (DC) for the client area of the specified window.
//The display device context can be used in subsequent GDI functions to draw in the window area.
//---------------------------------------------------------------------------
HDC GetDC(HWND hWnd)
{ if(IsWnd(hWnd))
{ TWndCanvas *dcCanvas=CM_AlocateCanvas(hWnd);
if(dcCanvas)
{ PWND parentWnd=((PWND)hWnd)->Parent;
if( parentWnd==NULL || parentWnd==g_RootWnd || (parentWnd->Parent==g_RootWnd && RectInRect(&((PWND)hWnd)->WndRect,&parentWnd->ClientRect)) )
{ dcCanvas->ClipRect.left=0;
dcCanvas->ClipRect.top=0;
dcCanvas->ClipRect.right=absWidth(hWnd);
dcCanvas->ClipRect.bottom=absHeight(hWnd);
}
else
{ TRECT *cliparea=&(dcCanvas->ClipRect);
*cliparea=((PWND)hWnd)->WndRect;
while(parentWnd!=g_RootWnd)
{ if(!RectIntersect(cliparea,&parentWnd->ClientRect))
{ break;
}
parentWnd=parentWnd->Parent;
}
OffsetRect(cliparea,-((PWND)hWnd)->WndRect.left,-((PWND)hWnd)->WndRect.top);
}
dcCanvas->VX=((PWND)hWnd)->WndRect.left - dcCanvas->Vram->Left;
dcCanvas->VY=((PWND)hWnd)->WndRect.top - dcCanvas->Vram->Top;
return (HDC)dcCanvas;
}
}
return (HDC)NULL;
}
/*
The difference between GetDC() and GetClientDC() is the reference coordinate and the clip area for painting ;
when painting with dc created by GetDC,the coordinate is relative to the window which own the dc.
while painting with clientDC,the coordinate is relative to the owner's client area, and the border area is cliped.
*/
//---------------------------------------------------------------------------
HDC GetClientDC(HWND hWnd)
{ if(IsWnd(hWnd))
{ TWndCanvas *dcCanvas=CM_AlocateCanvas(hWnd);
if(dcCanvas)
{ PWND parentWnd=((PWND)hWnd)->Parent;
if( parentWnd==NULL || parentWnd==g_RootWnd || (parentWnd->Parent==g_RootWnd && RectInRect(&((PWND)hWnd)->ClientRect,&parentWnd->ClientRect)) )
{ dcCanvas->ClipRect.left=0;
dcCanvas->ClipRect.top=0;
dcCanvas->ClipRect.right=crWidth(hWnd);
dcCanvas->ClipRect.bottom=crHeight(hWnd);
}
else
{ TRECT *cliparea=&(dcCanvas->ClipRect);
*cliparea=((PWND)hWnd)->ClientRect;
while(parentWnd!=g_RootWnd)
{ if(!RectIntersect(cliparea,&parentWnd->ClientRect))
{ break;
}
parentWnd=parentWnd->Parent;
}
OffsetRect(cliparea,-((PWND)hWnd)->ClientRect.left,-((PWND)hWnd)->ClientRect.top);
}
dcCanvas->VX=((PWND)hWnd)->ClientRect.left - dcCanvas->Vram->Left;;
dcCanvas->VY=((PWND)hWnd)->ClientRect.top - dcCanvas->Vram->Top;
return (HDC)dcCanvas;
}
}
return (HDC)NULL;
}
//---------------------------------------------------------------------------
HDC GetDesktopDC(void)
{ if(!IsWnd(g_RootWnd))
{ extern BOOL GUI_Initialize(void);
if(!GUI_Initialize())
{ DebugAlert("GUI初试化失败");
return NULL;
}
}
return GetDC((HWND)g_RootWnd);
}
//---------------------------------------------------------------------------
void ReleaseDC(HDC dc)
{ if(dc)
{ TWndCanvas *pdc=(TWndCanvas *)dc;
if(pdc->Owner)
{ TWndCanvas *topcanvas=pdc->Owner->Canvas;
if(pdc==topcanvas)
{ pdc->Owner->Canvas=pdc->Next;
}
else
{ while(topcanvas)
{ if(topcanvas->Next==pdc)
{ topcanvas->Next=pdc->Next;
break;
}
else topcanvas=topcanvas->Next;
}
if(!topcanvas) return; /*release dc fail*/
}
pdc->Owner=NULL;
if(!pdc->Prev) /*代表从堆上临时分配的DC*/
{ FreeMem(pdc);
}
else
{ if(!DC_FreeList)
{ DC_FreeList=pdc;
pdc->Next=pdc->Prev=pdc;
}
else
{ NODE_PREV_INSERT(pdc,DC_FreeList);
}
}
}
}
}
//---------------------------------------------------------------------------
TWndCanvas *CM_AlocateCanvas(HWND hWnd)
{ TWndCanvas *dcCanvas;
if(DC_FreeList)
{ dcCanvas=DC_FreeList;
if(DC_FreeList->Next!=DC_FreeList)
{ DC_FreeList=DC_FreeList->Next;
NODE_REMOVE(dcCanvas);
}
else
DC_FreeList=NULL;
}
else
{ dcCanvas=(TWndCanvas *)GetMem(sizeof(TWndCanvas));
if(dcCanvas)
{ dcCanvas->Prev=NULL; /*代表从堆上临时分配的DC*/
}
else
{ DebugAlert("GetDC(HWND) fail! \n not enough memory!");
return NULL;
}
}
dcCanvas->Next=((PWND)hWnd)->Canvas;
((PWND)hWnd)->Canvas=dcCanvas;
dcCanvas->Owner=(PWND)hWnd;
dcCanvas->Vram=((PWND)hWnd)->Family->Vram;
dcCanvas->Mode=0;
dcCanvas->Background=WNDPTR(hWnd)->Background;
dcCanvas->Foreground=WNDPTR(hWnd)->Foreground;
return dcCanvas;
}
//---------------------------------------------------------------------------
VRAM *CreateVRAM(int LcdOffsetX,int LcdOffsetY, int width, int height, PIXEL *FrameBuffer,BOOL ZeroInitialize)
{ DWORD BytePerLine = ( (width*BITS_PER_PIXEL+31)>>3 )& ~0x3; /*字节总数必须为4的整数位,以与winbmp格式兼容*/
DWORD UnitPerLine= BytePerLine / UNIT_BYTE;
VRAM *vram = (VRAM *)GetMem(sizeof(VRAM));
vram->FrameBufferOwned=(FrameBuffer==NULL);
vram->FrameBufferSize = BytePerLine * height;
if(!FrameBuffer) FrameBuffer=(PIXEL *)GetMem(vram->FrameBufferSize);
vram->Left = LcdOffsetX;
vram->Top = LcdOffsetY;
vram->Width = width;
vram->Height = height;
vram->BytePerLine = BytePerLine;
vram->UnitPerLine = UnitPerLine;
vram->FrameBuffer=FrameBuffer;
vram->GroupOperation=0;
if(ZeroInitialize) memset( vram->FrameBuffer, 0, vram->FrameBufferSize );
return vram;
}
//---------------------------------------------------------------------------
//FreeVRAM 释放一块指定的vram
void FreeVRAM(VRAM *vram )
{ if(vram)
{ if(vram->FrameBufferOwned)FreeMem(vram->FrameBuffer);
FreeMem(vram);
}
}
/*---------------------------------------------------------------------------
FUNCTION
ColorMapToPixel
DESCRIPTION
返回RGB颜色的索引号
对于不同的LCD控制器,调色板的颜色索引顺序有可能不同,因此必须改写本函数
---------------------------------------------------------------------------*/
PIXEL ColorMapToPixel(RGBQUAD *rgbColor) {
#if (BITS_PER_PIXEL<8) /*灰度屏: 计算亮度*/
int lightscale = 3 * rgbColor->r + 6 * rgbColor->g + rgbColor->b ;
#endif
#if (BITS_PER_PIXEL==1)
return (lightscale>630)?0:1;
#elif(BITS_PER_PIXEL==2)
if(lightscale>630) return (lightscale>1430)?0:1;
else return (lightscale>150)?2:3;
#elif(BITS_PER_PIXEL==4)
if(lightscale>630)
{ if(lightscale>1430)
{ if(lightscale>1950) return (lightscale>2240)?0:1;
else return (lightscale>1680)?2:3;
}
else
{ if(lightscale>990) return (lightscale>1200)?4:5;
else return (lightscale>800)?6:7;
}
}
else
{ if(lightscale>150)
{ if(lightscale>350) return (lightscale>480)?8:9;
else return (lightscale>240)?10:11;
}
else
{ if(lightscale>30) return (lightscale>80)?12:13;
else return (lightscale>0)?14:15;
}
}
#elif(BITS_PER_PIXEL==8)
int temp,mappixel;
temp=rgbColor->r >>(8-INDEX_RED_BITWIDTH);
mappixel = temp<<(INDEX_GREEN_BITWIDTH+INDEX_BLUE_BITWIDTH);
temp=rgbColor->g >> (8-INDEX_GREEN_BITWIDTH);
mappixel |= temp << INDEX_BLUE_BITWIDTH;
mappixel |= rgbColor->b >> (8-INDEX_BLUE_BITWIDTH) ;
return mappixel;
#elif(BITS_PER_PIXEL==16)
int mappixel = ( rgbColor->r << 8) & ~BITS_MASK(INDEX_GREEN_BITWIDTH+INDEX_BLUE_BITWIDTH);
mappixel |= ( rgbColor->g << (8-INDEX_RED_BITWIDTH) ) & ~BITS_MASK(INDEX_BLUE_BITWIDTH);
mappixel |= rgbColor->b >> (8-INDEX_BLUE_BITWIDTH) ;
return mappixel;
#elif(BITS_PER_PIXEL==24 || BITS_PER_PIXEL==32)
return *(DWORD *)rgbColor;
#else
return -1;
#endif
}
void PixelMapToColor(int index,RGBQUAD *rgbColor) {
#if(BITS_PER_PIXEL==1)
{ if(index==0)
{ rgbColor->r=0x99;
rgbColor->g=0xaa;
rgbColor->b=0x99;
rgbColor->a=0;
}
else
{ rgbColor->r=rgbColor->g=rgbColor->b=rgbColor->a=0;
}
}
#elif(BITS_PER_PIXEL<8)
{ int temp = (1<<BITS_PER_PIXEL) - index;
if(temp>=2) temp= ( temp * temp * 255 ) >> ( BITS_PER_PIXEL <<1 );
else temp = 0;
rgbColor->r=rgbColor->g=rgbColor->b=temp;
rgbColor->a=0;
}
#elif(BITS_PER_PIXEL==8 || BITS_PER_PIXEL==16)
{ int temp;
temp=index>>(INDEX_GREEN_BITWIDTH+INDEX_BLUE_BITWIDTH);
rgbColor->r = (BYTE) ( temp<<(8-INDEX_RED_BITWIDTH) );
temp=index>>INDEX_BLUE_BITWIDTH;
rgbColor->g = (BYTE) ( temp<<(8-INDEX_GREEN_BITWIDTH) );
rgbColor->b = (BYTE) ( index<<(8-INDEX_BLUE_BITWIDTH) );
rgbColor->a = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -