JD2022-TU1/main/extern/Camcam/LIBS/Input/FONT_IO.cpp

326 lines
No EOL
8.6 KiB
C++

#include "TRACK.h"
#include "MEDIA.h"
#define NB_CHARS 256
#define MAX_FONT_BOUND 63
class FONT_Grabber:public INPUT_IO
{
SIZE CharBounds[NB_CHARS];
SIZE CharPos[NB_CHARS];
ABC CharABC[NB_CHARS];
u32 FontMask;
HFONT hFont;
TEXTMETRIC FontMetrix;
public:
int INIT (class WORLD*);
int FRAME (void);
int END (void){return 0;};
IOTYPE GetType() {return IOtype_FONT;};
void * GetData(int dataIdx);
};
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Retrieve the bitmap color format, width, and height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
return NULL;
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1<< cClrBits));
// There is no RGBQUAD array for the 24-bit-per-pixel format.
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24)
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
// For Windows NT, the width must be DWORD aligned unless
// the bitmap is RLE compressed. This example shows this.
// For Windows 95/98/Me, the width must be WORD aligned unless the
// bitmap is RLE compressed.
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi->bmiHeader.biHeight;
// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
BOOL FONT_Grabber::INIT(WORLD *pScene)
{
LOGFONT fontStruct;
char tmpStr[512];
char *fontHeightInfo;
int len;
HWND hWnd;
HDC hDC , hDCBuff;
HBITMAP imgFont;
PBITMAPINFO imgInfo;
/* Load camcam font */
static u32 res = -1;
if (res == -1) res = AddFontResourceEx("./Fonts/HouseHolidayTT-Sans.ttf",FR_PRIVATE,0);
memset(&fontStruct, 0, sizeof(fontStruct));
len = (int)strlen((char *)MediaName) - 4;
MediaName[len] = 0;
FontMask = 0;
while ((MediaName[len - 1] <= 32 ||
MediaName[len - 1] == 'A'||
MediaName[len - 1] == 'B'||
MediaName[len - 1] == 'I'||
MediaName[len - 1] == 'U'||
MediaName[len - 1] == 'C'||
MediaName[len - 1] == 'T') && len > 0)
{
if (MediaName[len - 1] == 'A') FontMask |= 1<<0;
if (MediaName[len - 1] == 'B') FontMask |= 1<<1;
if (MediaName[len - 1] == 'I') FontMask |= 1<<2;
if (MediaName[len - 1] == 'U') FontMask |= 1<<3;
if (MediaName[len - 1] == 'C') FontMask |= 1<<4;
if (MediaName[len - 1] == 'T') FontMask |= 1<<5;
MediaName[len-- - 1] = 0;
}
fontHeightInfo = (char *)MediaName;
while (strchr(fontHeightInfo, ' ') != NULL)
fontHeightInfo = strchr(fontHeightInfo, ' ') + 1;
hWnd = GetDesktopWindow();
hDC = GetDC(hWnd);
fontStruct.lfHeight = - MulDiv(atoi(fontHeightInfo), GetDeviceCaps(hDC,LOGPIXELSY), 72);;
//fontStruct.lfWidth = 0;
//fontStruct.lfEscapement = 0;
//fontStruct.lfOrientation = 0;
if (FontMask & 1<<1)
fontStruct.lfWeight = FW_BOLD;
else
fontStruct.lfWeight = FW_NORMAL;
//fontStruct.lfStrikeOut = 0;
fontStruct.lfItalic = (FontMask & 1<<2) != 0;
fontStruct.lfUnderline = (FontMask & 1<<3) != 0;
fontStruct.lfCharSet = DEFAULT_CHARSET;
fontStruct.lfOutPrecision = OUT_DEFAULT_PRECIS;
fontStruct.lfClipPrecision = CLIP_DEFAULT_PRECIS;
if (FontMask & 1<<0)
fontStruct.lfQuality = CLEARTYPE_NATURAL_QUALITY;
else
fontStruct.lfQuality = NONANTIALIASED_QUALITY;
fontStruct.lfPitchAndFamily = FF_DONTCARE;
if (fontHeightInfo != (char *)MediaName)
strncpy(fontStruct.lfFaceName, (char *)MediaName, fontHeightInfo - (char *)MediaName- 1);
else
strcpy(fontStruct.lfFaceName, (char *)MediaName);
hFont = CreateFontIndirect(&fontStruct);
if (hFont == NULL)
return false;
hDCBuff = CreateCompatibleDC(hDC);
SelectObject(hDCBuff, hFont);
int imgXPos = 0, imgYPos = 0, asciiPos = 0;
int maxWidth = 0, maxHeight;
int xPos, yPos, pos;
GetTextMetrics(hDCBuff, &FontMetrix);
char oneChar = 0;
memset(CharABC, 0, sizeof(CharABC));
if (!GetCharABCWidths(hDCBuff, 0, 255, CharABC))
{
int width[256];
GetCharWidth32(hDCBuff, 0, 255, width);
for (int i=0; i<256; i++)
CharABC[i].abcB = width[i];
}
for (yPos=0; yPos<16; yPos++)
{
imgXPos = 1;
for (xPos=0; xPos<16; xPos++, oneChar++, asciiPos++)
{
GetTextExtentPoint32(hDCBuff, &oneChar, 1, CharBounds + asciiPos);
CharBounds[asciiPos].cx = abs(CharABC[asciiPos].abcA) + CharABC[asciiPos].abcB + abs(CharABC[asciiPos].abcC);
CharPos[asciiPos].cx = imgXPos;
CharPos[asciiPos].cy = imgYPos;
if (CharBounds[asciiPos].cx > MAX_FONT_BOUND)
CharBounds[asciiPos].cx = MAX_FONT_BOUND;
if (CharBounds[asciiPos].cy > MAX_FONT_BOUND)
CharBounds[asciiPos].cy = MAX_FONT_BOUND;
imgXPos += CharBounds[asciiPos].cx+1;
if (maxWidth < imgXPos) maxWidth = imgXPos;
}
imgYPos += FontMetrix.tmHeight + 1;
}
u32 ISX, ISY;
ISX = maxWidth;
ISY = imgYPos;
if (ISX & 3)
ISX += 4 - (ISX & 3);
if (ISY & 3)
ISY += 4 - (ISY & 3);
if (ISX == 0 ||
ISY == 0)
{
ReleaseDC(hWnd, hDC);
DeleteObject(hDCBuff);
DeleteObject(hFont);
return false;
}
Image.SetSize(ISX, ISY);
memset(Image.GetBase(), 0xFF, Image.PITCH*Image.SY*sizeof(s32));
imgFont = CreateCompatibleBitmap ( hDC, Image.SX, Image.SY );
SelectObject(hDCBuff, imgFont);
SetBkMode(hDCBuff, TRANSPARENT);
RECT charRect;
SetRect(&charRect, 0, 0, Image.SX, Image.SY);
SetTextColor(hDCBuff, RGB(255,255,255));
u32 colors[3];
HBRUSH colorsBrush[3];
colors[0] = RGB(255,0,0);
colors[1] = RGB(0,255,0);
colors[2] = RGB(0,0,255);
for (int y=0; y<3; y++)
colorsBrush[y] = CreateSolidBrush(colors[y]);
for (pos=0; pos<256; pos++, oneChar++)
{
charRect.left = CharPos[pos].cx;
charRect.top = CharPos[pos].cy;
charRect.right = charRect.left + CharBounds[pos].cx;
charRect.bottom = charRect.top + CharBounds[pos].cy;
//FillRect(hDCBuff, &charRect, colorsBrush[pos % 3]);
if (CharABC[pos].abcA < 0)
TextOut(hDCBuff, CharPos[pos].cx - CharABC[pos].abcA, CharPos[pos].cy, &oneChar, 1);
else
TextOut(hDCBuff, CharPos[pos].cx, CharPos[pos].cy, &oneChar, 1);
}
imgInfo = CreateBitmapInfoStruct(hWnd, imgFont);
imgInfo->bmiHeader.biPlanes = 1;
imgInfo->bmiHeader.biBitCount = 32;
imgInfo->bmiHeader.biCompression = BI_RGB;
GetDIBits(hDCBuff, imgFont, 0, Image.SY, Image.GetBase(), imgInfo, DIB_RGB_COLORS);
int counter = Image.SX * Image.SY;
s32 *pBASE = Image.GetBase();
//while (counter--)
// Image.BASE[counter] = (0xFF << 24) | (Image.BASE[counter] & 0xFFFFFF);
if (FontMask & 1<<5)
{
while (counter--)
pBASE[counter] = (pBASE[counter] & 0xFF) << 24 | 0xFFFFFF;
} else {
while (counter--)
pBASE[counter] = (pBASE[counter] & 0xFF) << 24 | (pBASE[counter] & 0xFFFFFF);
}
ReleaseDC(hWnd, hDC);
DeleteObject(imgInfo);
DeleteObject(imgFont);
DeleteObject(hDCBuff);
DeleteObject(hFont);
return true;
}
int FONT_Grabber::FRAME(void)
{
return 0;
};
void *FONT_Grabber::GetData(int dataIdx)
{
switch(dataIdx)
{
case 0:
return (void *)CharBounds;
case 1:
return (void *)CharPos;
case 2:
return (void *)FontMask;
case 3:
return (void *)&FontMetrix;
case 4:
return (void *)&CharABC;
}
return NULL;
}
INPUT_IO *FONT_CREATE(WORLD *pScene,char *Filename)
{
INPUT_IO *Ret;
Ret = (INPUT_IO *)new(FONT_Grabber);
strcpy((char*)Ret->MediaName,Filename);
if (!Ret->INIT(pScene))
{
delete Ret;
return NULL;
}
Ret->dTotalTime = 0;
Ret->dAvgFramePerSecond = 30.0;
return Ret;
}