Initial commit
This commit is contained in:
335
Torque/SDK/engine/platformWin32/winFont.cc
Normal file
335
Torque/SDK/engine/platformWin32/winFont.cc
Normal file
@@ -0,0 +1,335 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformWin32/platformWin32.h"
|
||||
#include "platformWin32/winFont.h"
|
||||
#include "dgl/gNewFont.h"
|
||||
#include "dgl/gFont.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "math/mRect.h"
|
||||
#include "console/console.h"
|
||||
#include "core/unicode.h"
|
||||
|
||||
static HDC fontHDC = NULL;
|
||||
static HBITMAP fontBMP = NULL;
|
||||
|
||||
static U32 charsetMap[]=
|
||||
{
|
||||
ANSI_CHARSET,
|
||||
SYMBOL_CHARSET,
|
||||
SHIFTJIS_CHARSET,
|
||||
HANGEUL_CHARSET,
|
||||
HANGUL_CHARSET,
|
||||
GB2312_CHARSET,
|
||||
CHINESEBIG5_CHARSET,
|
||||
OEM_CHARSET,
|
||||
JOHAB_CHARSET,
|
||||
HEBREW_CHARSET,
|
||||
ARABIC_CHARSET,
|
||||
GREEK_CHARSET,
|
||||
TURKISH_CHARSET,
|
||||
VIETNAMESE_CHARSET,
|
||||
THAI_CHARSET,
|
||||
EASTEUROPE_CHARSET,
|
||||
RUSSIAN_CHARSET,
|
||||
MAC_CHARSET,
|
||||
BALTIC_CHARSET,
|
||||
};
|
||||
#define NUMCHARSETMAP (sizeof(charsetMap) / sizeof(U32))
|
||||
|
||||
void createFontInit(void);
|
||||
void createFontShutdown(void);
|
||||
void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r);
|
||||
|
||||
void createFontInit()
|
||||
{
|
||||
fontHDC = CreateCompatibleDC(NULL);
|
||||
fontBMP = CreateCompatibleBitmap(fontHDC, 256, 256);
|
||||
}
|
||||
|
||||
void createFontShutdown()
|
||||
{
|
||||
DeleteObject(fontBMP);
|
||||
DeleteObject(fontHDC);
|
||||
}
|
||||
|
||||
void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r)
|
||||
{
|
||||
for (S32 i = r.point.y; i < r.point.y + r.extent.y; i++)
|
||||
{
|
||||
for (S32 j = r.point.x; j < r.point.x + r.extent.x; j++)
|
||||
{
|
||||
COLORREF color = GetPixel(hSrcHDC, j, i);
|
||||
if (color)
|
||||
*pDstBMP->getAddress(j, i) = 255;
|
||||
else
|
||||
*pDstBMP->getAddress(j, i) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GOldFont *createFont(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */)
|
||||
{
|
||||
if(!name)
|
||||
return NULL;
|
||||
if(size < 1)
|
||||
return NULL;
|
||||
|
||||
if(charset > NUMCHARSETMAP)
|
||||
charset = TGE_ANSI_CHARSET;
|
||||
|
||||
#ifdef UNICODE
|
||||
UTF16 n[512];
|
||||
convertUTF8toUTF16((UTF8 *)name, n, sizeof(n));
|
||||
HFONT hNewFont = CreateFont(size,0,0,0,0,0,0,0,0,0,0,0,0,n);
|
||||
#else
|
||||
HFONT hNewFont = CreateFont(size,0,0,0,0,0,0,0,charsetMap[charset],0,0,0,0,name);
|
||||
#endif
|
||||
if(!hNewFont)
|
||||
return NULL;
|
||||
|
||||
GOldFont *retFont = new GOldFont;
|
||||
static U8 scratchPad[65536];
|
||||
|
||||
TEXTMETRIC textMetric;
|
||||
COLORREF backgroundColorRef = RGB( 0, 0, 0);
|
||||
COLORREF foregroundColorRef = RGB(255, 255, 255);
|
||||
|
||||
SelectObject(fontHDC, fontBMP);
|
||||
SelectObject(fontHDC, hNewFont);
|
||||
SetBkColor(fontHDC, backgroundColorRef);
|
||||
SetTextColor(fontHDC, foregroundColorRef);
|
||||
GetTextMetrics(fontHDC, &textMetric);
|
||||
MAT2 matrix;
|
||||
GLYPHMETRICS metrics;
|
||||
RectI clip;
|
||||
|
||||
FIXED zero;
|
||||
zero.fract = 0;
|
||||
zero.value = 0;
|
||||
FIXED one;
|
||||
one.fract = 0;
|
||||
one.value = 1;
|
||||
|
||||
matrix.eM11 = one;
|
||||
matrix.eM12 = zero;
|
||||
matrix.eM21 = zero;
|
||||
matrix.eM22 = one;
|
||||
S32 glyphCount = 0;
|
||||
|
||||
for(S32 i = 32; i < 256; i++)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
UTF16 c[2];
|
||||
const UTF8 t[] = { (const UTF8)i, 0 };
|
||||
|
||||
convertUTF8toUTF16(t, c, sizeof(c));
|
||||
#endif
|
||||
|
||||
if(GetGlyphOutline(
|
||||
fontHDC, // handle of device context
|
||||
#ifdef UNICODE
|
||||
c[0], // character to query
|
||||
#else
|
||||
i, // character to query
|
||||
#endif
|
||||
GGO_GRAY8_BITMAP, // format of data to return
|
||||
&metrics, // address of structure for metrics
|
||||
sizeof(scratchPad), // size of buffer for data
|
||||
scratchPad, // address of buffer for data
|
||||
&matrix // address of transformation matrix structure
|
||||
) != GDI_ERROR)
|
||||
{
|
||||
glyphCount++;
|
||||
U32 rowStride = (metrics.gmBlackBoxX + 3) & ~3; // DWORD aligned
|
||||
U32 size = rowStride * metrics.gmBlackBoxY;
|
||||
for(U32 j = 0; j < size; j++)
|
||||
{
|
||||
U32 pad = U32(scratchPad[j]) << 2;
|
||||
if(pad > 255)
|
||||
pad = 255;
|
||||
scratchPad[j] = pad;
|
||||
}
|
||||
S32 inc = metrics.gmCellIncX;
|
||||
if(inc < 0)
|
||||
inc = -inc;
|
||||
retFont->insertBitmap(i, scratchPad, rowStride, metrics.gmBlackBoxX, metrics.gmBlackBoxY, metrics.gmptGlyphOrigin.x, metrics.gmptGlyphOrigin.y, metrics.gmCellIncX);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef UNICODE
|
||||
UTF16 b = i;
|
||||
#else
|
||||
char b = i;
|
||||
#endif
|
||||
SIZE size;
|
||||
GetTextExtentPoint32(fontHDC, &b, 1, &size);
|
||||
if(size.cx)
|
||||
retFont->insertBitmap(i, scratchPad, 0, 0, 0, 0, 0, size.cx);
|
||||
}
|
||||
}
|
||||
retFont->pack(textMetric.tmHeight, textMetric.tmAscent);
|
||||
//clean up local vars
|
||||
DeleteObject(hNewFont);
|
||||
|
||||
if (!glyphCount)
|
||||
Con::errorf(ConsoleLogEntry::General,"Error creating font: %s %d",name, size);
|
||||
|
||||
return retFont;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// WinFont class
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PlatformFont *createPlatformFont(const char *name, U32 size, U32 charset /* = TGE_ANSI_CHARSET */)
|
||||
{
|
||||
PlatformFont *retFont = new WinFont;
|
||||
|
||||
if(retFont->create(name, size, charset))
|
||||
return retFont;
|
||||
|
||||
delete retFont;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WinFont::WinFont() : mFont(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
WinFont::~WinFont()
|
||||
{
|
||||
if(mFont)
|
||||
{
|
||||
DeleteObject(mFont);
|
||||
}
|
||||
}
|
||||
|
||||
bool WinFont::create(const char *name, U32 size, U32 charset /* = TGE_ANSI_CHARSET */)
|
||||
{
|
||||
if(name == NULL || size < 1)
|
||||
return false;
|
||||
|
||||
if(charset > NUMCHARSETMAP)
|
||||
charset = TGE_ANSI_CHARSET;
|
||||
|
||||
#ifdef UNICODE
|
||||
UTF16 n[512];
|
||||
convertUTF8toUTF16((UTF8 *)name, n, sizeof(n));
|
||||
mFont = CreateFont(size,0,0,0,0,0,0,0,DEFAULT_CHARSET,OUT_TT_PRECIS,0,PROOF_QUALITY,0,n);
|
||||
#else
|
||||
mFont = CreateFont(size,0,0,0,0,0,0,0,charsetMap[charset],OUT_TT_PRECIS,0,PROOF_QUALITY,0,name);
|
||||
#endif
|
||||
if(mFont == NULL)
|
||||
return false;
|
||||
|
||||
SelectObject(fontHDC, fontBMP);
|
||||
SelectObject(fontHDC, mFont);
|
||||
GetTextMetrics(fontHDC, &mTextMetric);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinFont::isValidChar(const UTF16 ch) const
|
||||
{
|
||||
return ch != 0 /* && (ch >= mTextMetric.tmFirstChar && ch <= mTextMetric.tmLastChar)*/;
|
||||
}
|
||||
|
||||
bool WinFont::isValidChar(const UTF8 *str) const
|
||||
{
|
||||
return isValidChar(oneUTF8toUTF32(str));
|
||||
}
|
||||
|
||||
|
||||
PlatformFont::CharInfo &WinFont::getCharInfo(const UTF16 ch) const
|
||||
{
|
||||
static PlatformFont::CharInfo c;
|
||||
|
||||
dMemset(&c, 0, sizeof(c));
|
||||
c.bitmapIndex = -1;
|
||||
|
||||
static U8 scratchPad[65536];
|
||||
|
||||
COLORREF backgroundColorRef = RGB( 0, 0, 0);
|
||||
COLORREF foregroundColorRef = RGB(255, 255, 255);
|
||||
SelectObject(fontHDC, fontBMP);
|
||||
SelectObject(fontHDC, mFont);
|
||||
SetBkColor(fontHDC, backgroundColorRef);
|
||||
SetTextColor(fontHDC, foregroundColorRef);
|
||||
|
||||
MAT2 matrix;
|
||||
GLYPHMETRICS metrics;
|
||||
RectI clip;
|
||||
|
||||
FIXED zero;
|
||||
zero.fract = 0;
|
||||
zero.value = 0;
|
||||
FIXED one;
|
||||
one.fract = 0;
|
||||
one.value = 1;
|
||||
|
||||
matrix.eM11 = one;
|
||||
matrix.eM12 = zero;
|
||||
matrix.eM21 = zero;
|
||||
matrix.eM22 = one;
|
||||
|
||||
|
||||
if(GetGlyphOutline(
|
||||
fontHDC, // handle of device context
|
||||
ch, // character to query
|
||||
GGO_GRAY8_BITMAP, // format of data to return
|
||||
&metrics, // address of structure for metrics
|
||||
sizeof(scratchPad), // size of buffer for data
|
||||
scratchPad, // address of buffer for data
|
||||
&matrix // address of transformation matrix structure
|
||||
) != GDI_ERROR)
|
||||
{
|
||||
U32 rowStride = (metrics.gmBlackBoxX + 3) & ~3; // DWORD aligned
|
||||
U32 size = rowStride * metrics.gmBlackBoxY;
|
||||
for(U32 j = 0; j < size; j++)
|
||||
{
|
||||
U32 pad = U32(scratchPad[j]) << 2;
|
||||
if(pad > 255)
|
||||
pad = 255;
|
||||
scratchPad[j] = pad;
|
||||
}
|
||||
S32 inc = metrics.gmCellIncX;
|
||||
if(inc < 0)
|
||||
inc = -inc;
|
||||
|
||||
c.xOffset = 0;
|
||||
c.yOffset = 0;
|
||||
c.width = metrics.gmBlackBoxX;
|
||||
c.height = metrics.gmBlackBoxY;
|
||||
c.xOrigin = metrics.gmptGlyphOrigin.x;
|
||||
c.yOrigin = metrics.gmptGlyphOrigin.y;
|
||||
c.xIncrement = metrics.gmCellIncX;
|
||||
|
||||
c.bitmapData = new U8[c.width * c.height];
|
||||
for(U32 y = 0; S32(y) < c.height; y++)
|
||||
{
|
||||
U32 x;
|
||||
for(x = 0; x < c.width; x++)
|
||||
c.bitmapData[y * c.width + x] = scratchPad[y * rowStride + x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE size;
|
||||
GetTextExtentPoint32W(fontHDC, &ch, 1, &size);
|
||||
if(size.cx)
|
||||
{
|
||||
c.xIncrement = size.cx;
|
||||
c.bitmapIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
PlatformFont::CharInfo &WinFont::getCharInfo(const UTF8 *str) const
|
||||
{
|
||||
return getCharInfo(oneUTF8toUTF32(str));
|
||||
}
|
||||
Reference in New Issue
Block a user