mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 10:37:41 -04:00
Fix line endings and tabs
This commit is contained in:
@ -1,431 +1,431 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plTextFont Class Functions //
|
||||
// Cyan, Inc. //
|
||||
// //
|
||||
//// Version History //////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.19.2001 mcn - Created. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsWindows.h"
|
||||
#include "HeadSpin.h"
|
||||
#include "plTextFont.h"
|
||||
#include "plDebugText.h"
|
||||
|
||||
#define DisplayableChar(c) (c >= 0 && c <= 128)
|
||||
|
||||
//// Constructor & Destructor /////////////////////////////////////////////////
|
||||
|
||||
plTextFont::plTextFont( plPipeline *pipe )
|
||||
{
|
||||
fMaxNumIndices = 1024;
|
||||
fInitialized = false;
|
||||
fPipe = pipe;
|
||||
}
|
||||
|
||||
plTextFont::~plTextFont()
|
||||
{
|
||||
IUnlink();
|
||||
}
|
||||
|
||||
//// IInitFontTexture /////////////////////////////////////////////////////////
|
||||
|
||||
UInt16 *plTextFont::IInitFontTexture( void )
|
||||
{
|
||||
int nHeight, x, y, c;
|
||||
char myChar[ 2 ] = "x";
|
||||
UInt16 *tBits;
|
||||
|
||||
DWORD *bitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
HDC hDC;
|
||||
HBITMAP hBitmap;
|
||||
HFONT hFont;
|
||||
SIZE size;
|
||||
BYTE bAlpha;
|
||||
|
||||
|
||||
// Figure out our texture size
|
||||
if( fSize > 40 )
|
||||
fTextureWidth = fTextureHeight = 1024;
|
||||
else if( fSize > 20 )
|
||||
fTextureWidth = fTextureHeight = 512;
|
||||
else
|
||||
fTextureWidth = fTextureHeight = 256;
|
||||
|
||||
|
||||
// Create a new DC and bitmap that we can draw characters to
|
||||
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
|
||||
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
|
||||
bmi.bmiHeader.biWidth = fTextureWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)fTextureHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
hDC = CreateCompatibleDC( nil );
|
||||
hBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (void **)&bitmapBits, nil, 0 );
|
||||
SetMapMode( hDC, MM_TEXT );
|
||||
|
||||
nHeight = -MulDiv( fSize, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
|
||||
fFontHeight = -nHeight;
|
||||
|
||||
hFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, fFace );
|
||||
hsAssert( hFont != nil, "Cannot create Windows font" );
|
||||
|
||||
SelectObject( hDC, hBitmap );
|
||||
SelectObject( hDC, hFont );
|
||||
|
||||
// Set text colors
|
||||
SetTextColor( hDC, RGB( 255, 255, 255 ) );
|
||||
SetBkColor( hDC, 0 );
|
||||
SetTextAlign( hDC, TA_TOP );
|
||||
|
||||
// Loop through characters, drawing them one at a time
|
||||
RECT r;
|
||||
r.left = r.top = 0;
|
||||
r.right = r.bottom = 10;
|
||||
FillRect( hDC, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );
|
||||
|
||||
// (Make first character a black dot, for filling rectangles)
|
||||
SetPixel( hDC, 0, 0, RGB( 255, 255, 255 ) );
|
||||
for( c = 32, x = 1, y = 0; c < 127; c++ )
|
||||
{
|
||||
myChar[ 0 ] = c;
|
||||
GetTextExtentPoint32( hDC, myChar, 1, &size );
|
||||
|
||||
if( (UInt32)( x + size.cx + 1 ) > fTextureWidth )
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy + 1;
|
||||
}
|
||||
|
||||
ExtTextOut( hDC, x, y, ETO_OPAQUE, nil, myChar, 1, nil );
|
||||
|
||||
fCharInfo[ c ].fW = (UInt16)size.cx;
|
||||
fCharInfo[ c ].fH = (UInt16)size.cy;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fX = (float)x / (float)fTextureWidth;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fY = (float)y / (float)fTextureHeight;
|
||||
fCharInfo[ c ].fUVs[ 1 ].fX = (float)( x + size.cx ) / (float)fTextureWidth;
|
||||
fCharInfo[ c ].fUVs[ 1 ].fY = (float)( y + size.cy ) / (float)fTextureHeight;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fZ = fCharInfo[ c ].fUVs[ 1 ].fZ = 0;
|
||||
|
||||
x += size.cx + 1;
|
||||
}
|
||||
fCharInfo[ 32 ].fUVs[ 1 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
|
||||
|
||||
// Special case the tab key
|
||||
fCharInfo[ '\t' ].fUVs[ 1 ].fX = fCharInfo[ '\t' ].fUVs[ 0 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
|
||||
fCharInfo[ '\t' ].fUVs[ 1 ].fY = fCharInfo[ '\t' ].fUVs[ 0 ].fY = 0;
|
||||
fCharInfo[ '\t' ].fUVs[ 0 ].fZ = fCharInfo[ '\t' ].fUVs[ 1 ].fZ = 0;
|
||||
fCharInfo[ '\t' ].fW = fCharInfo[ 32 ].fW * 4;
|
||||
fCharInfo[ '\t' ].fH = fCharInfo[ 32 ].fH;
|
||||
|
||||
/// Now create the data block
|
||||
UInt16 *data = TRACKED_NEW UInt16[ fTextureWidth * fTextureHeight ];
|
||||
tBits = data;
|
||||
for( y = 0; y < fTextureHeight; y++ )
|
||||
{
|
||||
for( x = 0; x < fTextureWidth; x++ )
|
||||
{
|
||||
bAlpha = (BYTE)( ( bitmapBits[ fTextureWidth * y + x ] & 0xff ) >> 4 );
|
||||
|
||||
if( bitmapBits[ fTextureWidth * y + x ] )
|
||||
*tBits = 0xffff;
|
||||
else
|
||||
*tBits = 0;
|
||||
|
||||
tBits++;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
DeleteObject( hBitmap );
|
||||
DeleteDC( hDC );
|
||||
DeleteObject( hFont );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//// Create ///////////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::Create( char *face, UInt16 size )
|
||||
{
|
||||
// Init normal stuff
|
||||
strncpy( fFace, face, sizeof( fFace ) );
|
||||
fSize = size;
|
||||
}
|
||||
|
||||
//// IInitObjects /////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::IInitObjects( void )
|
||||
{
|
||||
UInt16 *data;
|
||||
|
||||
|
||||
// Create texture
|
||||
data = IInitFontTexture();
|
||||
hsAssert( data != nil, "Cannot create font texture" );
|
||||
|
||||
ICreateTexture( data );
|
||||
delete [] data;
|
||||
|
||||
// Create state blocks
|
||||
IInitStateBlocks();
|
||||
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
//// DrawString ///////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::DrawString( const char *string, int sX, int sY, UInt32 hexColor,
|
||||
UInt8 style, UInt32 rightEdge )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
|
||||
int i, j, width, height, count, thisCount, italOffset;
|
||||
float x = (float)sX;
|
||||
char c, *strPtr;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Set up to draw
|
||||
italOffset = ( style & plDebugText::kStyleItalic ) ? fSize / 2: 0;
|
||||
count = strlen( string );
|
||||
strPtr = (char *)string;
|
||||
while( count > 0 )
|
||||
{
|
||||
thisCount = ( count > 64 ) ? 64 : count;
|
||||
count -= thisCount;
|
||||
|
||||
// Create an array for our vertices
|
||||
verts.SetCountAndZero( thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ) );
|
||||
|
||||
// Fill them all up now
|
||||
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
}
|
||||
|
||||
for( i = 0, j = 0; i < thisCount; i++, j += 6 )
|
||||
{
|
||||
c = strPtr[ i ];
|
||||
// make sure its a character we will display
|
||||
if ( DisplayableChar(c) )
|
||||
{
|
||||
width = fCharInfo[ c ].fW + 1;
|
||||
height = fCharInfo[ c ].fH + 1;
|
||||
|
||||
if( rightEdge > 0 && x + width + italOffset >= rightEdge )
|
||||
{
|
||||
count = 0;
|
||||
thisCount = i;
|
||||
break;
|
||||
}
|
||||
|
||||
verts[ j ].fPoint.fX = x + italOffset;
|
||||
verts[ j ].fPoint.fY = (float)sY;
|
||||
verts[ j ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
|
||||
verts[ j + 1 ].fPoint.fX = x + width + italOffset;
|
||||
verts[ j + 1 ].fPoint.fY = (float)sY;
|
||||
verts[ j + 1 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 1 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
|
||||
|
||||
verts[ j + 2 ].fPoint.fX = x;
|
||||
verts[ j + 2 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 2 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 2 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
|
||||
|
||||
verts[ j + 3 ].fPoint.fX = x;
|
||||
verts[ j + 3 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 3 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 3 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
|
||||
|
||||
verts[ j + 4 ].fPoint.fX = x + width + italOffset;
|
||||
verts[ j + 4 ].fPoint.fY = (float)sY;
|
||||
verts[ j + 4 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 4 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
|
||||
|
||||
verts[ j + 5 ].fPoint.fX = x + width;
|
||||
verts[ j + 5 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 5 ].fUV = fCharInfo[ c ].fUVs[ 1 ];
|
||||
|
||||
x += width + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( thisCount == 0 )
|
||||
break;
|
||||
|
||||
if( style & plDebugText::kStyleBold )
|
||||
{
|
||||
for( i = 0; i < thisCount * 6; i++, j++ )
|
||||
{
|
||||
verts[ j ] = verts[ i ];
|
||||
verts[ j ].fPoint.fX = verts[ j ].fPoint.fX + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
|
||||
#if 0
|
||||
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i += 3 )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
hsAssert( verts[ i + j ].fPoint.fX >= 0, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fY >= 0, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fX < 1024, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fY < 768, "Text point out of range" );
|
||||
}
|
||||
int lt = ( verts[ i ].fPoint.fX < verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
|
||||
lt = ( verts[ i + 2 ].fPoint.fX < lt ? verts[ i + 2 ].fPoint.fX : lt );
|
||||
|
||||
int tp = ( verts[ i ].fPoint.fY < verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
|
||||
tp = ( verts[ i + 2 ].fPoint.fY < tp ? verts[ i + 2 ].fPoint.fY : tp );
|
||||
|
||||
int rt = ( verts[ i ].fPoint.fX > verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
|
||||
rt = ( verts[ i + 2 ].fPoint.fX > rt ? verts[ i + 2 ].fPoint.fX : rt );
|
||||
|
||||
int bt = ( verts[ i ].fPoint.fY > verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
|
||||
bt = ( verts[ i + 2 ].fPoint.fY > bt ? verts[ i + 2 ].fPoint.fY : bt );
|
||||
|
||||
hsAssert( rt - lt < 32, "Text character too big" );
|
||||
hsAssert( bt - tp < 32, "Text character too big" );
|
||||
}
|
||||
#endif
|
||||
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
|
||||
|
||||
|
||||
/// Draw a set of tris now
|
||||
IDrawPrimitive( thisCount * ( ( style & plDebugText::kStyleBold ) ? 4 : 2 ), verts.AcquireArray() );
|
||||
|
||||
strPtr += thisCount;
|
||||
}
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
//// CalcStringWidth //////////////////////////////////////////////////////////
|
||||
|
||||
UInt32 plTextFont::CalcStringWidth( const char *string )
|
||||
{
|
||||
int i, width = 0;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
for( i = 0; i < strlen( string ); i++ )
|
||||
{
|
||||
// make sure its a character we will display
|
||||
if ( DisplayableChar(string[i]) )
|
||||
width += fCharInfo[ string[ i ] ].fW + 2;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
//// DrawRect /////////////////////////////////////////////////////////////////
|
||||
// TEMPORARY function to draw a flat-shaded 2D rectangle to the screen. Used
|
||||
// to create a background for our console; will be obliterated once we figure
|
||||
// a better way to do so.
|
||||
|
||||
void plTextFont::DrawRect( int left, int top, int right, int bottom, UInt32 hexColor )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
int i;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Draw!
|
||||
verts.SetCountAndZero( 6 );
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
|
||||
}
|
||||
|
||||
verts[ 0 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = (float)left;
|
||||
verts[ 1 ].fPoint.fX = verts[ 4 ].fPoint.fX = verts[ 5 ].fPoint.fX = (float)right;
|
||||
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 4 ].fPoint.fY = (float)top;
|
||||
verts[ 2 ].fPoint.fY = verts[ 3 ].fPoint.fY = verts[ 5 ].fPoint.fY = (float)bottom;
|
||||
|
||||
// omg I had this at 6...just slap the dunce cap on me...-mcn
|
||||
IDrawPrimitive( 2, verts.AcquireArray() );
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
//// Draw3DBorder /////////////////////////////////////////////////////////////
|
||||
// Draws a 3d border, upper-left with the first color, lower-right with the
|
||||
// second. I just LOOOOVE temporary functions :)
|
||||
// Note: this way sucks. Live with it.
|
||||
|
||||
void plTextFont::Draw3DBorder( int left, int top, int right, int bottom, UInt32 hexColor1, UInt32 hexColor2 )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
int i;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Draw!
|
||||
verts.SetCountAndZero( 8 );
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor1;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
|
||||
}
|
||||
|
||||
verts[ 1 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = verts[ 4 ].fPoint.fX = (float)left;
|
||||
verts[ 0 ].fPoint.fX = verts[ 5 ].fPoint.fX = verts[ 6 ].fPoint.fX = verts[ 7 ].fPoint.fX = (float)right;
|
||||
|
||||
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 2 ].fPoint.fY = verts[ 7 ].fPoint.fY = (float)top;
|
||||
verts[ 3 ].fPoint.fY = verts[ 4 ].fPoint.fY = verts[ 5 ].fPoint.fY = verts[ 6 ].fPoint.fY = (float)bottom;
|
||||
|
||||
for( i = 4; i < 8; i++ )
|
||||
verts[ i ].fColor = hexColor2;
|
||||
|
||||
IDrawLines( 4, verts.AcquireArray() );
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plTextFont Class Functions //
|
||||
// Cyan, Inc. //
|
||||
// //
|
||||
//// Version History //////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.19.2001 mcn - Created. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsWindows.h"
|
||||
#include "HeadSpin.h"
|
||||
#include "plTextFont.h"
|
||||
#include "plDebugText.h"
|
||||
|
||||
#define DisplayableChar(c) (c >= 0 && c <= 128)
|
||||
|
||||
//// Constructor & Destructor /////////////////////////////////////////////////
|
||||
|
||||
plTextFont::plTextFont( plPipeline *pipe )
|
||||
{
|
||||
fMaxNumIndices = 1024;
|
||||
fInitialized = false;
|
||||
fPipe = pipe;
|
||||
}
|
||||
|
||||
plTextFont::~plTextFont()
|
||||
{
|
||||
IUnlink();
|
||||
}
|
||||
|
||||
//// IInitFontTexture /////////////////////////////////////////////////////////
|
||||
|
||||
UInt16 *plTextFont::IInitFontTexture( void )
|
||||
{
|
||||
int nHeight, x, y, c;
|
||||
char myChar[ 2 ] = "x";
|
||||
UInt16 *tBits;
|
||||
|
||||
DWORD *bitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
HDC hDC;
|
||||
HBITMAP hBitmap;
|
||||
HFONT hFont;
|
||||
SIZE size;
|
||||
BYTE bAlpha;
|
||||
|
||||
|
||||
// Figure out our texture size
|
||||
if( fSize > 40 )
|
||||
fTextureWidth = fTextureHeight = 1024;
|
||||
else if( fSize > 20 )
|
||||
fTextureWidth = fTextureHeight = 512;
|
||||
else
|
||||
fTextureWidth = fTextureHeight = 256;
|
||||
|
||||
|
||||
// Create a new DC and bitmap that we can draw characters to
|
||||
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
|
||||
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
|
||||
bmi.bmiHeader.biWidth = fTextureWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)fTextureHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
hDC = CreateCompatibleDC( nil );
|
||||
hBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (void **)&bitmapBits, nil, 0 );
|
||||
SetMapMode( hDC, MM_TEXT );
|
||||
|
||||
nHeight = -MulDiv( fSize, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
|
||||
fFontHeight = -nHeight;
|
||||
|
||||
hFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, fFace );
|
||||
hsAssert( hFont != nil, "Cannot create Windows font" );
|
||||
|
||||
SelectObject( hDC, hBitmap );
|
||||
SelectObject( hDC, hFont );
|
||||
|
||||
// Set text colors
|
||||
SetTextColor( hDC, RGB( 255, 255, 255 ) );
|
||||
SetBkColor( hDC, 0 );
|
||||
SetTextAlign( hDC, TA_TOP );
|
||||
|
||||
// Loop through characters, drawing them one at a time
|
||||
RECT r;
|
||||
r.left = r.top = 0;
|
||||
r.right = r.bottom = 10;
|
||||
FillRect( hDC, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );
|
||||
|
||||
// (Make first character a black dot, for filling rectangles)
|
||||
SetPixel( hDC, 0, 0, RGB( 255, 255, 255 ) );
|
||||
for( c = 32, x = 1, y = 0; c < 127; c++ )
|
||||
{
|
||||
myChar[ 0 ] = c;
|
||||
GetTextExtentPoint32( hDC, myChar, 1, &size );
|
||||
|
||||
if( (UInt32)( x + size.cx + 1 ) > fTextureWidth )
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy + 1;
|
||||
}
|
||||
|
||||
ExtTextOut( hDC, x, y, ETO_OPAQUE, nil, myChar, 1, nil );
|
||||
|
||||
fCharInfo[ c ].fW = (UInt16)size.cx;
|
||||
fCharInfo[ c ].fH = (UInt16)size.cy;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fX = (float)x / (float)fTextureWidth;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fY = (float)y / (float)fTextureHeight;
|
||||
fCharInfo[ c ].fUVs[ 1 ].fX = (float)( x + size.cx ) / (float)fTextureWidth;
|
||||
fCharInfo[ c ].fUVs[ 1 ].fY = (float)( y + size.cy ) / (float)fTextureHeight;
|
||||
fCharInfo[ c ].fUVs[ 0 ].fZ = fCharInfo[ c ].fUVs[ 1 ].fZ = 0;
|
||||
|
||||
x += size.cx + 1;
|
||||
}
|
||||
fCharInfo[ 32 ].fUVs[ 1 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
|
||||
|
||||
// Special case the tab key
|
||||
fCharInfo[ '\t' ].fUVs[ 1 ].fX = fCharInfo[ '\t' ].fUVs[ 0 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
|
||||
fCharInfo[ '\t' ].fUVs[ 1 ].fY = fCharInfo[ '\t' ].fUVs[ 0 ].fY = 0;
|
||||
fCharInfo[ '\t' ].fUVs[ 0 ].fZ = fCharInfo[ '\t' ].fUVs[ 1 ].fZ = 0;
|
||||
fCharInfo[ '\t' ].fW = fCharInfo[ 32 ].fW * 4;
|
||||
fCharInfo[ '\t' ].fH = fCharInfo[ 32 ].fH;
|
||||
|
||||
/// Now create the data block
|
||||
UInt16 *data = TRACKED_NEW UInt16[ fTextureWidth * fTextureHeight ];
|
||||
tBits = data;
|
||||
for( y = 0; y < fTextureHeight; y++ )
|
||||
{
|
||||
for( x = 0; x < fTextureWidth; x++ )
|
||||
{
|
||||
bAlpha = (BYTE)( ( bitmapBits[ fTextureWidth * y + x ] & 0xff ) >> 4 );
|
||||
|
||||
if( bitmapBits[ fTextureWidth * y + x ] )
|
||||
*tBits = 0xffff;
|
||||
else
|
||||
*tBits = 0;
|
||||
|
||||
tBits++;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup and return
|
||||
DeleteObject( hBitmap );
|
||||
DeleteDC( hDC );
|
||||
DeleteObject( hFont );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//// Create ///////////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::Create( char *face, UInt16 size )
|
||||
{
|
||||
// Init normal stuff
|
||||
strncpy( fFace, face, sizeof( fFace ) );
|
||||
fSize = size;
|
||||
}
|
||||
|
||||
//// IInitObjects /////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::IInitObjects( void )
|
||||
{
|
||||
UInt16 *data;
|
||||
|
||||
|
||||
// Create texture
|
||||
data = IInitFontTexture();
|
||||
hsAssert( data != nil, "Cannot create font texture" );
|
||||
|
||||
ICreateTexture( data );
|
||||
delete [] data;
|
||||
|
||||
// Create state blocks
|
||||
IInitStateBlocks();
|
||||
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
//// DrawString ///////////////////////////////////////////////////////////////
|
||||
|
||||
void plTextFont::DrawString( const char *string, int sX, int sY, UInt32 hexColor,
|
||||
UInt8 style, UInt32 rightEdge )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
|
||||
int i, j, width, height, count, thisCount, italOffset;
|
||||
float x = (float)sX;
|
||||
char c, *strPtr;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Set up to draw
|
||||
italOffset = ( style & plDebugText::kStyleItalic ) ? fSize / 2: 0;
|
||||
count = strlen( string );
|
||||
strPtr = (char *)string;
|
||||
while( count > 0 )
|
||||
{
|
||||
thisCount = ( count > 64 ) ? 64 : count;
|
||||
count -= thisCount;
|
||||
|
||||
// Create an array for our vertices
|
||||
verts.SetCountAndZero( thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ) );
|
||||
|
||||
// Fill them all up now
|
||||
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
}
|
||||
|
||||
for( i = 0, j = 0; i < thisCount; i++, j += 6 )
|
||||
{
|
||||
c = strPtr[ i ];
|
||||
// make sure its a character we will display
|
||||
if ( DisplayableChar(c) )
|
||||
{
|
||||
width = fCharInfo[ c ].fW + 1;
|
||||
height = fCharInfo[ c ].fH + 1;
|
||||
|
||||
if( rightEdge > 0 && x + width + italOffset >= rightEdge )
|
||||
{
|
||||
count = 0;
|
||||
thisCount = i;
|
||||
break;
|
||||
}
|
||||
|
||||
verts[ j ].fPoint.fX = x + italOffset;
|
||||
verts[ j ].fPoint.fY = (float)sY;
|
||||
verts[ j ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
|
||||
verts[ j + 1 ].fPoint.fX = x + width + italOffset;
|
||||
verts[ j + 1 ].fPoint.fY = (float)sY;
|
||||
verts[ j + 1 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 1 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
|
||||
|
||||
verts[ j + 2 ].fPoint.fX = x;
|
||||
verts[ j + 2 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 2 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 2 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
|
||||
|
||||
verts[ j + 3 ].fPoint.fX = x;
|
||||
verts[ j + 3 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 3 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 3 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
|
||||
|
||||
verts[ j + 4 ].fPoint.fX = x + width + italOffset;
|
||||
verts[ j + 4 ].fPoint.fY = (float)sY;
|
||||
verts[ j + 4 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
|
||||
verts[ j + 4 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
|
||||
|
||||
verts[ j + 5 ].fPoint.fX = x + width;
|
||||
verts[ j + 5 ].fPoint.fY = (float)sY + height;
|
||||
verts[ j + 5 ].fUV = fCharInfo[ c ].fUVs[ 1 ];
|
||||
|
||||
x += width + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( thisCount == 0 )
|
||||
break;
|
||||
|
||||
if( style & plDebugText::kStyleBold )
|
||||
{
|
||||
for( i = 0; i < thisCount * 6; i++, j++ )
|
||||
{
|
||||
verts[ j ] = verts[ i ];
|
||||
verts[ j ].fPoint.fX = verts[ j ].fPoint.fX + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
|
||||
#if 0
|
||||
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i += 3 )
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
hsAssert( verts[ i + j ].fPoint.fX >= 0, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fY >= 0, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fX < 1024, "Text point out of range" );
|
||||
hsAssert( verts[ i + j ].fPoint.fY < 768, "Text point out of range" );
|
||||
}
|
||||
int lt = ( verts[ i ].fPoint.fX < verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
|
||||
lt = ( verts[ i + 2 ].fPoint.fX < lt ? verts[ i + 2 ].fPoint.fX : lt );
|
||||
|
||||
int tp = ( verts[ i ].fPoint.fY < verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
|
||||
tp = ( verts[ i + 2 ].fPoint.fY < tp ? verts[ i + 2 ].fPoint.fY : tp );
|
||||
|
||||
int rt = ( verts[ i ].fPoint.fX > verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
|
||||
rt = ( verts[ i + 2 ].fPoint.fX > rt ? verts[ i + 2 ].fPoint.fX : rt );
|
||||
|
||||
int bt = ( verts[ i ].fPoint.fY > verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
|
||||
bt = ( verts[ i + 2 ].fPoint.fY > bt ? verts[ i + 2 ].fPoint.fY : bt );
|
||||
|
||||
hsAssert( rt - lt < 32, "Text character too big" );
|
||||
hsAssert( bt - tp < 32, "Text character too big" );
|
||||
}
|
||||
#endif
|
||||
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
|
||||
|
||||
|
||||
/// Draw a set of tris now
|
||||
IDrawPrimitive( thisCount * ( ( style & plDebugText::kStyleBold ) ? 4 : 2 ), verts.AcquireArray() );
|
||||
|
||||
strPtr += thisCount;
|
||||
}
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
//// CalcStringWidth //////////////////////////////////////////////////////////
|
||||
|
||||
UInt32 plTextFont::CalcStringWidth( const char *string )
|
||||
{
|
||||
int i, width = 0;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
for( i = 0; i < strlen( string ); i++ )
|
||||
{
|
||||
// make sure its a character we will display
|
||||
if ( DisplayableChar(string[i]) )
|
||||
width += fCharInfo[ string[ i ] ].fW + 2;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
//// DrawRect /////////////////////////////////////////////////////////////////
|
||||
// TEMPORARY function to draw a flat-shaded 2D rectangle to the screen. Used
|
||||
// to create a background for our console; will be obliterated once we figure
|
||||
// a better way to do so.
|
||||
|
||||
void plTextFont::DrawRect( int left, int top, int right, int bottom, UInt32 hexColor )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
int i;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Draw!
|
||||
verts.SetCountAndZero( 6 );
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
|
||||
}
|
||||
|
||||
verts[ 0 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = (float)left;
|
||||
verts[ 1 ].fPoint.fX = verts[ 4 ].fPoint.fX = verts[ 5 ].fPoint.fX = (float)right;
|
||||
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 4 ].fPoint.fY = (float)top;
|
||||
verts[ 2 ].fPoint.fY = verts[ 3 ].fPoint.fY = verts[ 5 ].fPoint.fY = (float)bottom;
|
||||
|
||||
// omg I had this at 6...just slap the dunce cap on me...-mcn
|
||||
IDrawPrimitive( 2, verts.AcquireArray() );
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
//// Draw3DBorder /////////////////////////////////////////////////////////////
|
||||
// Draws a 3d border, upper-left with the first color, lower-right with the
|
||||
// second. I just LOOOOVE temporary functions :)
|
||||
// Note: this way sucks. Live with it.
|
||||
|
||||
void plTextFont::Draw3DBorder( int left, int top, int right, int bottom, UInt32 hexColor1, UInt32 hexColor2 )
|
||||
{
|
||||
static hsTArray<plFontVertex> verts;
|
||||
int i;
|
||||
|
||||
|
||||
if( !fInitialized )
|
||||
IInitObjects();
|
||||
|
||||
/// Draw!
|
||||
verts.SetCountAndZero( 8 );
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
verts[ i ].fColor = hexColor1;
|
||||
verts[ i ].fPoint.fZ = 0;
|
||||
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
|
||||
}
|
||||
|
||||
verts[ 1 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = verts[ 4 ].fPoint.fX = (float)left;
|
||||
verts[ 0 ].fPoint.fX = verts[ 5 ].fPoint.fX = verts[ 6 ].fPoint.fX = verts[ 7 ].fPoint.fX = (float)right;
|
||||
|
||||
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 2 ].fPoint.fY = verts[ 7 ].fPoint.fY = (float)top;
|
||||
verts[ 3 ].fPoint.fY = verts[ 4 ].fPoint.fY = verts[ 5 ].fPoint.fY = verts[ 6 ].fPoint.fY = (float)bottom;
|
||||
|
||||
for( i = 4; i < 8; i++ )
|
||||
verts[ i ].fColor = hexColor2;
|
||||
|
||||
IDrawLines( 4, verts.AcquireArray() );
|
||||
|
||||
/// All done!
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user