324 lines
8.7 KiB
C++
324 lines
8.7 KiB
C++
|
/******************************Module*Header*******************************\
|
||
|
* Module Name: CFile.cpp
|
||
|
*
|
||
|
* This file contains the code to support the functionality test harness
|
||
|
* for GDI+. This includes menu options and calling the appropriate
|
||
|
* functions for execution.
|
||
|
*
|
||
|
* Created: 05-May-2000 - Jeff Vezina [t-jfvez]
|
||
|
*
|
||
|
* Copyright (c) 2000 Microsoft Corporation
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
#include "CFile.h"
|
||
|
#include "CFuncTest.h"
|
||
|
|
||
|
extern CFuncTest g_FuncTest;
|
||
|
|
||
|
CFile::CFile(BOOL bRegression,int nBits)
|
||
|
{
|
||
|
sprintf(m_szName,"File %d bits",nBits);
|
||
|
m_nBits=nBits;
|
||
|
m_hDC=NULL;
|
||
|
m_hBM=NULL;
|
||
|
m_hBMOld=NULL;
|
||
|
|
||
|
InitPalettes();
|
||
|
m_bRegression=bRegression;
|
||
|
}
|
||
|
|
||
|
CFile::~CFile()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
Graphics *CFile::PreDraw(int &nOffsetX,int &nOffsetY)
|
||
|
{
|
||
|
Graphics *g=NULL;
|
||
|
PVOID pvBits = NULL;
|
||
|
HDC hdcWnd=GetDC(g_FuncTest.m_hWndMain);
|
||
|
|
||
|
// these combined give BITMAPINFO structure.
|
||
|
struct {
|
||
|
BITMAPINFOHEADER bmih;
|
||
|
union {
|
||
|
RGBQUAD1 rgbquad1;
|
||
|
RGBQUAD2 rgbquad2;
|
||
|
RGBQUAD4 rgbquad4;
|
||
|
RGBQUAD8 rgbquad8;
|
||
|
RGBQUAD16 rgbquad16;
|
||
|
RGBQUAD24 rgbquad24;
|
||
|
RGBQUAD32 rgbquad32;
|
||
|
};
|
||
|
} bmi;
|
||
|
|
||
|
bmi.bmih.biSize = sizeof(BITMAPINFOHEADER);
|
||
|
bmi.bmih.biWidth = (int)TESTAREAWIDTH;
|
||
|
bmi.bmih.biHeight = (int)TESTAREAHEIGHT;
|
||
|
bmi.bmih.biPlanes = 1;
|
||
|
bmi.bmih.biBitCount = (WORD)m_nBits;
|
||
|
bmi.bmih.biCompression = BI_RGB;
|
||
|
bmi.bmih.biSizeImage = 0;
|
||
|
bmi.bmih.biXPelsPerMeter = 0;
|
||
|
bmi.bmih.biYPelsPerMeter = 0;
|
||
|
bmi.bmih.biClrUsed = 0; // only used for <= 16bpp
|
||
|
bmi.bmih.biClrImportant = 0;
|
||
|
|
||
|
// create appropriate rgb table.
|
||
|
switch (m_nBits)
|
||
|
{
|
||
|
case 1: memcpy(bmi.rgbquad1, m_rgbQuad1, sizeof(m_rgbQuad1));
|
||
|
break;
|
||
|
|
||
|
case 2: memcpy(bmi.rgbquad2, m_rgbQuad2, sizeof(m_rgbQuad2));
|
||
|
break;
|
||
|
|
||
|
case 4: memcpy(bmi.rgbquad4, m_rgbQuad4, sizeof(m_rgbQuad4));
|
||
|
break;
|
||
|
|
||
|
case 8: memcpy(bmi.rgbquad8, m_rgbQuad8, sizeof(m_rgbQuad8));
|
||
|
break;
|
||
|
|
||
|
case 16: memcpy(bmi.rgbquad16, m_rgbQuad16, sizeof(m_rgbQuad16));
|
||
|
break;
|
||
|
|
||
|
case 24: memcpy(bmi.rgbquad24, m_rgbQuad24, sizeof(m_rgbQuad24));
|
||
|
break;
|
||
|
|
||
|
case 32: memcpy(bmi.rgbquad32, m_rgbQuad32, sizeof(m_rgbQuad32));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
m_hBM=CreateDIBSection(hdcWnd,(BITMAPINFO*)&bmi,DIB_RGB_COLORS,&pvBits,NULL,0);
|
||
|
if (!m_hBM)
|
||
|
{
|
||
|
MessageBoxA(NULL,"Can't create DIB Section.","",MB_OK);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
// create DC for our DIB
|
||
|
m_hDC=CreateCompatibleDC(hdcWnd);
|
||
|
m_hBMOld=(HBITMAP)SelectObject(m_hDC,m_hBM);
|
||
|
|
||
|
// Set the background to main window background
|
||
|
BitBlt(m_hDC, 0, 0, (int)TESTAREAWIDTH, (int)TESTAREAHEIGHT, hdcWnd, nOffsetX, nOffsetY, SRCCOPY);
|
||
|
// PatBlt(m_hDC, 0, 0, (int)TESTAREAWIDTH, (int)TESTAREAHEIGHT, WHITENESS);
|
||
|
|
||
|
// if (m_nBits == 32)
|
||
|
// g = Graphics::FromDib32(pvBits, rClient.right, rClient.bottom);
|
||
|
// else
|
||
|
g = Graphics::FromHDC(m_hDC);
|
||
|
|
||
|
// Since we are doing the test on another surface
|
||
|
nOffsetX=0;
|
||
|
nOffsetY=0;
|
||
|
|
||
|
ReleaseDC(g_FuncTest.m_hWndMain,hdcWnd);
|
||
|
|
||
|
return g;
|
||
|
}
|
||
|
|
||
|
void CFile::PostDraw(RECT rTestArea)
|
||
|
{
|
||
|
char *szTitle="TestDIB.bmp";
|
||
|
HDC hdcOrig = GetDC(g_FuncTest.m_hWndMain);
|
||
|
|
||
|
// blit from the DIB to screen so we see the results, we use
|
||
|
// GDI for this.
|
||
|
|
||
|
BitBlt(hdcOrig, rTestArea.left, rTestArea.top, (int)TESTAREAWIDTH, (int)TESTAREAHEIGHT, m_hDC, 0, 0, SRCCOPY);
|
||
|
|
||
|
BOOL success = WriteBitmap(szTitle, m_hBM, (int)TESTAREAWIDTH, (int)TESTAREAHEIGHT);
|
||
|
|
||
|
ReleaseDC(g_FuncTest.m_hWndMain,hdcOrig);
|
||
|
SelectObject(m_hDC,m_hBMOld);
|
||
|
DeleteDC(m_hDC);
|
||
|
DeleteObject(m_hBM);
|
||
|
}
|
||
|
|
||
|
void CFile::InitPalettes()
|
||
|
{
|
||
|
BYTE red=0,green=0,blue=0;
|
||
|
RGBQUAD1 rgbQuad1 = { { 0, 0, 0, 0 },
|
||
|
{ 0xff, 0xff, 0xff, 0 } };
|
||
|
RGBQUAD2 rgbQuad2 = { { 0x80, 0x80, 0x80, 0 },
|
||
|
{ 0x80, 0, 0, 0 },
|
||
|
{ 0, 0x80, 0, 0 },
|
||
|
{ 0, 0, 0x80, 0 } };
|
||
|
RGBQUAD4 rgbQuad4 = { // B G R
|
||
|
{ 0, 0, 0, 0 }, // 0
|
||
|
{ 0, 0, 0x80,0 }, // 1
|
||
|
{ 0, 0x80,0, 0 }, // 2
|
||
|
{ 0, 0x80,0x80,0 }, // 3
|
||
|
{ 0x80,0, 0, 0 }, // 4
|
||
|
{ 0x80,0, 0x80,0 }, // 5
|
||
|
{ 0x80,0x80,0, 0 }, // 6
|
||
|
{ 0x80,0x80,0x80,0 }, // 7
|
||
|
{ 0xC0,0xC0,0xC0,0 }, // 8
|
||
|
{ 0, 0, 0xFF,0 }, // 9
|
||
|
{ 0, 0xFF,0, 0 }, // 10
|
||
|
{ 0, 0xFF,0xFF,0 }, // 11
|
||
|
{ 0xFF,0, 0, 0 }, // 12
|
||
|
{ 0xFF,0, 0xFF,0 }, // 13
|
||
|
{ 0xFF,0xFF,0, 0 }, // 14
|
||
|
{ 0xFF,0xFF,0xFF,0 } }; // 15
|
||
|
RGBQUAD16 rgbQuad16 = { { 0, 0x7c, 0, 0 }, { 0xe0, 03, 0, 0 }, { 0x1f, 0, 0, 0 } };
|
||
|
RGBQUAD24 rgbQuad24 = { { 0, 0, 0xff, 0 }, { 0, 0xff, 0, 0 }, { 0xff, 0, 0, 0 } };
|
||
|
RGBQUAD32 rgbQuad32 = { { 0, 0, 0xff, 0 }, { 0, 0xff, 0, 0 }, { 0xff, 0, 0 ,0 } };
|
||
|
|
||
|
memcpy(m_rgbQuad1,rgbQuad1,sizeof(rgbQuad1));
|
||
|
memcpy(m_rgbQuad2,rgbQuad2,sizeof(rgbQuad2));
|
||
|
memcpy(m_rgbQuad4,rgbQuad4,sizeof(rgbQuad4));
|
||
|
memcpy(m_rgbQuad16,rgbQuad16,sizeof(rgbQuad16));
|
||
|
memcpy(m_rgbQuad24,rgbQuad24,sizeof(rgbQuad24));
|
||
|
memcpy(m_rgbQuad32,rgbQuad32,sizeof(rgbQuad32));
|
||
|
|
||
|
ZeroMemory(m_rgbQuad8,sizeof(m_rgbQuad8));
|
||
|
for (INT i=0; i<256; i++)
|
||
|
{
|
||
|
m_rgbQuad8[i].rgbRed=red;
|
||
|
m_rgbQuad8[i].rgbGreen=green;
|
||
|
m_rgbQuad8[i].rgbBlue=blue;
|
||
|
|
||
|
if (!(red+=32))
|
||
|
{
|
||
|
if (!(green+=32))
|
||
|
{
|
||
|
blue+=64;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// for system colors (last 20), use those from 4 bpp palette table.
|
||
|
for (INT j=248; j<256; j++)
|
||
|
{
|
||
|
m_rgbQuad8[j].rgbRed=m_rgbQuad4[j-240].rgbRed;
|
||
|
m_rgbQuad8[j].rgbGreen=m_rgbQuad4[j-240].rgbGreen;
|
||
|
m_rgbQuad8[j].rgbBlue=m_rgbQuad4[j-240].rgbBlue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CFile::WriteBitmap(char *szTitle, HBITMAP hbitmap, INT width, INT height)
|
||
|
{
|
||
|
BITMAPFILEHEADER fileHeader;
|
||
|
BITMAPINFOHEADER infoHeader;
|
||
|
|
||
|
memset(&fileHeader, 0, sizeof(fileHeader));
|
||
|
memset(&infoHeader, 0, sizeof(infoHeader));
|
||
|
|
||
|
fileHeader.bfType = 0x4d42;
|
||
|
fileHeader.bfOffBits = sizeof(fileHeader) + sizeof(infoHeader);
|
||
|
|
||
|
infoHeader.biSize = sizeof(infoHeader);
|
||
|
infoHeader.biPlanes = 1;
|
||
|
infoHeader.biWidth = width;
|
||
|
infoHeader.biHeight = height;
|
||
|
infoHeader.biBitCount = 24;
|
||
|
infoHeader.biXPelsPerMeter = 3780;
|
||
|
infoHeader.biYPelsPerMeter = 3780;
|
||
|
|
||
|
BITMAPINFO bmInfo;
|
||
|
bmInfo.bmiHeader = infoHeader;
|
||
|
VOID* bits = malloc(infoHeader.biWidth*infoHeader.biHeight*3);
|
||
|
|
||
|
BOOL success = FALSE;
|
||
|
|
||
|
if(bits)
|
||
|
{
|
||
|
HDC hdc = CreateCompatibleDC(NULL);
|
||
|
INT n = GetDIBits(hdc, hbitmap, 0, height,
|
||
|
bits, &bmInfo, DIB_RGB_COLORS);
|
||
|
|
||
|
infoHeader.biHeight = n;
|
||
|
INT bitsSize = infoHeader.biHeight*infoHeader.biWidth*3;
|
||
|
fileHeader.bfSize = sizeof(fileHeader) + sizeof(infoHeader)
|
||
|
+ bitsSize;
|
||
|
|
||
|
DeleteDC(hdc);
|
||
|
|
||
|
HANDLE hFile = CreateFileA(szTitle,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
BOOL deleteFile = FALSE;
|
||
|
DWORD dwPtr;
|
||
|
DWORD dwError;
|
||
|
|
||
|
if(hFile == INVALID_HANDLE_VALUE)
|
||
|
goto cleanUp2;
|
||
|
|
||
|
dwPtr = SetFilePointer (hFile, 0, NULL, FILE_BEGIN) ;
|
||
|
|
||
|
dwError;
|
||
|
|
||
|
if(dwPtr == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR)
|
||
|
{
|
||
|
deleteFile = TRUE;
|
||
|
goto cleanUp1;
|
||
|
}
|
||
|
|
||
|
DWORD bytesToWrite;
|
||
|
DWORD bytesWritten;
|
||
|
|
||
|
bytesToWrite = sizeof(fileHeader);
|
||
|
success = WriteFile(
|
||
|
hFile,
|
||
|
&fileHeader,
|
||
|
bytesToWrite,
|
||
|
&bytesWritten,
|
||
|
NULL);
|
||
|
|
||
|
if(!success || bytesWritten != bytesToWrite)
|
||
|
{
|
||
|
success = FALSE;
|
||
|
deleteFile = TRUE;
|
||
|
goto cleanUp1;
|
||
|
}
|
||
|
|
||
|
bytesToWrite = sizeof(infoHeader);
|
||
|
success = WriteFile(
|
||
|
hFile,
|
||
|
&infoHeader,
|
||
|
bytesToWrite,
|
||
|
&bytesWritten,
|
||
|
NULL);
|
||
|
|
||
|
if(!success || bytesWritten != bytesToWrite)
|
||
|
{
|
||
|
success = FALSE;
|
||
|
deleteFile = TRUE;
|
||
|
goto cleanUp1;
|
||
|
}
|
||
|
|
||
|
bytesToWrite = bitsSize;
|
||
|
success = WriteFile(
|
||
|
hFile,
|
||
|
bits,
|
||
|
bytesToWrite,
|
||
|
&bytesWritten,
|
||
|
NULL);
|
||
|
|
||
|
if(!success || bytesWritten != bytesToWrite)
|
||
|
{
|
||
|
success = FALSE;
|
||
|
deleteFile = TRUE;
|
||
|
goto cleanUp1;
|
||
|
}
|
||
|
|
||
|
success = TRUE;
|
||
|
|
||
|
cleanUp1:
|
||
|
CloseHandle(hFile);
|
||
|
if(deleteFile)
|
||
|
DeleteFileA(szTitle);
|
||
|
|
||
|
cleanUp2:
|
||
|
free(bits);
|
||
|
}
|
||
|
|
||
|
return success;
|
||
|
}
|