class TextMaker
{
wchar_t m_buffer[1024];
HDC dc;
HFONT font;
HBITMAP bmp;
HDC bmpdc;
HBRUSH brush;
HPEN pen;
char *row;
int rowsize;
BITMAP b;
WORD cClrBits;
PBITMAPINFO pbmi;
LPBYTE lpBits;
PBITMAPINFOHEADER pbih;
TextMaker() {}
public:
TextMaker(const v4f& rect, int fontSize, const wchar_t* fontName)
{
int textureWidth = rect.z - rect.x;
int textureHeight = rect.w - rect.y;
rowsize = 0;
row = nullptr;
dc = CreateDC(L"DISPLAY", L"DISPLAY", 0, 0);
font = CreateFontW(
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72), 0,
0, 0,
FW_SEMIBOLD,
0, 0, 0, ANSI_CHARSET, 0, 0,
ANTIALIASED_QUALITY,
0, fontName);
bmp = CreateCompatibleBitmap(dc, textureWidth, textureHeight);
bmpdc = CreateCompatibleDC(dc);
LOGBRUSH lbrush;
lbrush.lbHatch = 0;
lbrush.lbStyle = BS_SOLID;
lbrush.lbColor = RGB(0, 0, 0);
brush = CreateBrushIndirect(&lbrush);
pen = CreatePen(PS_NULL, 0, 0);
GetObject(bmp, sizeof(BITMAP), (LPSTR)&b);
cClrBits = (WORD)(b.bmPlanes * b.bmBitsPixel);
pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = b.bmWidth;
pbmi->bmiHeader.biHeight = b.bmHeight;
pbmi->bmiHeader.biPlanes = b.bmPlanes;
pbmi->bmiHeader.biBitCount = b.bmBitsPixel;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits + 31) & ~31) / 8
* pbmi->bmiHeader.biHeight;
pbmi->bmiHeader.biClrImportant = 0;
pbih = (PBITMAPINFOHEADER)pbmi;
m_image = yyCreate<yyImage>();
m_image->m_width = textureWidth;
m_image->m_height = textureHeight;
m_image->m_format = yyImageFormat::R8G8B8A8;
m_image->m_bits = 32;
m_image->m_pitch = 4 * textureWidth;
m_image->m_dataSize = m_image->m_pitch * m_image->m_height;
m_image->m_data = (unsigned char*)yyMemAlloc(m_image->m_dataSize);
m_textureGPU = g_videoDriver->CreateTexture(m_image, true, false);
m_pictureBox = yyGUICreatePictureBox(rect, m_textureGPU, 1);
}
~TextMaker() {
LocalFree(pbmi);
GlobalFree(lpBits);
if(row)
delete[] row;
if (m_image)
yyDestroy(m_image);
DeleteDC(bmpdc);
DeleteObject(brush);
DeleteObject(pen);
DeleteObject(bmp);
DeleteObject(font);
DeleteDC(dc);
}
void set(const wchar_t* format, ...)
{
va_list arg;
va_start(arg, format);
_vsnwprintf(m_buffer, 1024, format, arg);
va_end(arg);
auto len = wcslen(m_buffer);
if (len)
{
SelectObject(dc, font);
SetTextAlign(dc, TA_LEFT | TA_TOP | TA_NOUPDATECP);
SelectObject(bmpdc, bmp);
SelectObject(bmpdc, pen);
SelectObject(bmpdc, brush);
SelectObject(bmpdc, font);
SetTextColor(bmpdc, RGB(255, 255, 255));
Rectangle(bmpdc, 0, 0, m_image->m_width, m_image->m_height);
SetBkMode(bmpdc, TRANSPARENT);
TextOutW(bmpdc, 10, 30, m_buffer, len);
if (!row)
{
lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
rowsize = ((pbmi->bmiHeader.biWidth * cClrBits + 31) & ~31) / 8;
row = new char[rowsize];
}
auto r = GetDIBits(dc, bmp, 0, (WORD)pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS);
for (int i = 0; i < (pbih->biHeight / 2); ++i)
{
memcpy(row, lpBits + (rowsize * i), rowsize);
memcpy(lpBits + (rowsize * i), lpBits + ((pbih->biHeight - 1 - i) * rowsize), rowsize);
memcpy(lpBits + ((pbih->biHeight - 1 - i) * rowsize), row, rowsize);
}
auto imageData = m_image->m_data;
if (cClrBits > 24)
{
for (LPBYTE m = lpBits; m < lpBits + pbih->biSizeImage; m += 4)
{
*imageData = m[0]; ++imageData;
*imageData = m[1]; ++imageData;
*imageData = m[2]; ++imageData;
unsigned char A = 0;
if (m[0] > 0)
{
A = 255 - (255 - m[0]);
}
*imageData = A; ++imageData;
}
}
}
g_videoDriver->UnloadTexture(m_textureGPU);
g_videoDriver->LoadTexture(m_textureGPU);
}
yyImage* m_image;
yyResource * m_textureGPU;
yyGUIPictureBox* m_pictureBox;
};