You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
615 lines
20 KiB
615 lines
20 KiB
/*==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/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
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==*/ |
|
/////////////////////////////////////////////////////////////////////////////// |
|
// // |
|
// plTextGenerator Class Functions // |
|
// Cyan, Inc. // |
|
// // |
|
//// Version History ////////////////////////////////////////////////////////// |
|
// // |
|
// 12.13.2001 mcn - Created. // |
|
// // |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
#include "HeadSpin.h" |
|
#include "hsWindows.h" |
|
#include "hsMatrix44.h" |
|
#include "pnKeyedObject/hsKeyedObject.h" |
|
#include "plTextGenerator.h" |
|
#include "plGImage/plMipmap.h" |
|
#include "plPipeline/hsGDeviceRef.h" |
|
#include "pnMessage/plRefMsg.h" |
|
|
|
#include "plgDispatch.h" |
|
#include "hsResMgr.h" |
|
|
|
// Because tempKeys haven't been fixed yet (mf says to blame Eric Ellis), reffing |
|
// objects when we have a tempKey (or they have a tempKey) just don't work. In |
|
// fact, it will do nasty things like crashing on shutdown. Until then, we simply |
|
// won't do the refs. Note that this is BAD, but given the only time we currently |
|
// use these objects are very limited, controlled cases that *should* be okay |
|
// for now, we should be reasonably safe. For now. |
|
//#define MCN_DO_REFS |
|
|
|
//// Constructor & Destructor ///////////////////////////////////////////////// |
|
|
|
plTextGenerator::plTextGenerator() |
|
{ |
|
fHost = nil; |
|
} |
|
|
|
plTextGenerator::plTextGenerator( plMipmap *host, uint16_t width, uint16_t height ) |
|
{ |
|
fHost = nil; |
|
Attach( host, width, height ); |
|
} |
|
|
|
plTextGenerator::~plTextGenerator() |
|
{ |
|
// This also won't work until tempKeys work, since the mipmap will be gone by |
|
// this time, in which case, calling Detach() crashes |
|
#ifdef MCN_DO_REFS |
|
Detach(); |
|
#endif |
|
} |
|
|
|
//// Attach /////////////////////////////////////////////////////////////////// |
|
// Grab onto a plMipmap, suck the texture out of it and replace it with our |
|
// own. |
|
|
|
void plTextGenerator::Attach( plMipmap *host, uint16_t width, uint16_t height ) |
|
{ |
|
uint16_t textWidth, textHeight; |
|
|
|
|
|
hsAssert( fHost == nil, "Attempting to attach an already attached plTextGenerator" ); |
|
|
|
fHost = host; |
|
|
|
/// Suck the old texture data out |
|
fHost->Reset(); |
|
|
|
/// Make some new |
|
|
|
// Note that we need POW-2 textures, so we go for the next one up that will |
|
// fit what we need |
|
for( textWidth = 1; textWidth < width; textWidth <<= 1 ); |
|
for( textHeight = 1; textHeight < height; textHeight <<= 1 ); |
|
|
|
fWidth = width; |
|
fHeight = height; |
|
fHost->fImage = (void *)IAllocateOSSurface( textWidth, textHeight ); |
|
fHost->SetConfig( plMipmap::kARGB32Config ); |
|
fHost->fWidth = textWidth; |
|
fHost->fHeight = textHeight; |
|
fHost->fPixelSize = 32; |
|
fHost->fRowBytes = textWidth * 4; |
|
fHost->fNumLevels = 1; |
|
fHost->fFlags |= plMipmap::kUserOwnsBitmap | plMipmap::kDontThrowAwayImage; |
|
fHost->fCompressionType = plMipmap::kUncompressed; |
|
fHost->fUncompressedInfo.fType = plMipmap::UncompressedInfo::kRGB8888; |
|
fHost->IBuildLevelSizes(); |
|
fHost->fTotalSize = fHost->GetLevelSize( 0 ); |
|
|
|
// Destroy the old texture ref, since it's probably completely nutsoid at this point. |
|
// This should force the pipeline to recreate one more suitable for our use |
|
fHost->SetDeviceRef( nil ); |
|
|
|
// Some init color |
|
hsColorRGBA color; |
|
color.Set( 0.f, 0.f, 0.f, 1.f ); |
|
ClearToColor( color ); |
|
FlushToHost(); |
|
|
|
#ifdef MCN_DO_REFS |
|
/// Of course, brilliantly enough, if we did an attach on the constructor, we don't have a key |
|
/// yet, so we better give ourselves one before we can call AddViaNotify() |
|
if( GetKey() == nil ) |
|
{ |
|
char str[ 256 ]; |
|
sprintf( str, "plTextGen:%s", fHost->GetKeyName() ); |
|
hsgResMgr::ResMgr()->NewKey( str, this, plLocation::kGlobalFixedLoc ); |
|
} |
|
|
|
/// Send ourselves a passive ref of the mipmap, so we get notified if and when it goes away |
|
hsgResMgr::ResMgr()->AddViaNotify( fHost->GetKey(), new plGenRefMsg( GetKey(), plRefMsg::kOnCreate, 0, 0 ), plRefFlags::kActiveRef ); |
|
#endif |
|
/// All done! |
|
} |
|
|
|
//// IAllocateOSSurface /////////////////////////////////////////////////////// |
|
// OS-specific. Allocates a rectangular bitmap of the given dimensions that |
|
// the OS can draw text into. Returns a pointer to the pixels. |
|
|
|
uint32_t *plTextGenerator::IAllocateOSSurface( uint16_t width, uint16_t height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
BITMAPINFO bmi; |
|
|
|
|
|
// 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 = width; |
|
bmi.bmiHeader.biHeight = -(int)height; |
|
bmi.bmiHeader.biPlanes = 1; |
|
bmi.bmiHeader.biCompression = BI_RGB; |
|
bmi.bmiHeader.biBitCount = 32; |
|
|
|
fWinRGBDC = CreateCompatibleDC( nil ); |
|
fWinRGBBitmap = CreateDIBSection( fWinRGBDC, &bmi, DIB_RGB_COLORS, (void **)&fWinRGBBits, nil, 0 ); |
|
SetMapMode( fWinRGBDC, MM_TEXT ); |
|
SetBkMode( fWinRGBDC, TRANSPARENT ); |
|
SetTextAlign( fWinRGBDC, TA_TOP | TA_LEFT ); |
|
|
|
SelectObject( fWinRGBDC, fWinRGBBitmap ); |
|
|
|
// Now create a second DC/bitmap combo, this one for writing alpha values to |
|
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) ); |
|
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); |
|
bmi.bmiHeader.biWidth = width; |
|
bmi.bmiHeader.biHeight = -(int)height; |
|
bmi.bmiHeader.biPlanes = 1; |
|
bmi.bmiHeader.biCompression = BI_RGB; |
|
bmi.bmiHeader.biBitCount = 8; |
|
|
|
fWinAlphaDC = CreateCompatibleDC( nil ); |
|
fWinAlphaBitmap = CreateDIBSection( fWinAlphaDC, &bmi, DIB_RGB_COLORS, (void **)&fWinAlphaBits, nil, 0 ); |
|
SetMapMode( fWinAlphaDC, MM_TEXT ); |
|
SetBkMode( fWinAlphaDC, TRANSPARENT ); |
|
SetTextAlign( fWinAlphaDC, TA_TOP | TA_LEFT ); |
|
|
|
SelectObject( fWinAlphaDC, fWinAlphaBitmap ); |
|
|
|
return (uint32_t *)fWinRGBBits; |
|
#else |
|
return nullptr; |
|
#endif |
|
} |
|
|
|
//// Detach /////////////////////////////////////////////////////////////////// |
|
// Release the mipmap unto itself. |
|
|
|
void plTextGenerator::Detach( void ) |
|
{ |
|
if( fHost == nil ) |
|
return; |
|
// hsAssert( fHost != nil, "Attempting to detach unattached host" ); |
|
|
|
SetFont( nil, 0 ); |
|
IDestroyOSSurface(); |
|
|
|
fHost->Reset(); |
|
fHost->fFlags &= ~( plMipmap::kUserOwnsBitmap | plMipmap::kDontThrowAwayImage ); |
|
|
|
// Destroy the old texture ref, since we're no longer using it |
|
fHost->SetDeviceRef( nil ); |
|
|
|
plMipmap *oldHost = fHost; |
|
|
|
fHost = nil; |
|
|
|
#ifdef MCN_DO_REFS |
|
// Now send ourselves a unref msg, just in case we were called directly (if this was done by |
|
// message, we'll get called a few times, but that's ok, we're set up to handle that, and it |
|
// won't happen 'cept on destruction so the speed penalty shouldn't be a problem) |
|
GetKey()->Release( oldHost->GetKey() ); |
|
#endif |
|
} |
|
|
|
//// IDestroyOSSurface //////////////////////////////////////////////////////// |
|
// Opposite of allocate. DUH! |
|
|
|
void plTextGenerator::IDestroyOSSurface( void ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
fHost->fImage = nil; // DeleteObject() will get rid of it for us |
|
DeleteObject( fWinRGBBitmap ); |
|
DeleteDC( fWinRGBDC ); |
|
|
|
DeleteObject( fWinAlphaBitmap ); |
|
DeleteDC( fWinAlphaDC ); |
|
|
|
#endif |
|
} |
|
|
|
//// ClearToColor ///////////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::ClearToColor( hsColorRGBA &color ) |
|
{ |
|
int i; |
|
uint32_t *data = (uint32_t *)fHost->fImage; |
|
uint32_t hexColor = color.ToARGB32(); |
|
|
|
#if HS_BUILD_FOR_WIN32 |
|
GdiFlush(); |
|
#endif |
|
|
|
for( i = 0; i < fHost->fWidth * fHost->fHeight; i++ ) |
|
data[ i ] = hexColor; |
|
|
|
// Fill our alpha bitmap as well, since we use that too |
|
#if HS_BUILD_FOR_WIN32 |
|
memset( fWinAlphaBits, (uint8_t)( color.a * 255.f ), fHost->fWidth * fHost->fHeight ); |
|
#endif |
|
} |
|
|
|
//// SetFont ////////////////////////////////////////////////////////////////// |
|
// OS-specific. Load the given font for drawing the text with. |
|
|
|
void plTextGenerator::SetFont( const char *face, uint16_t size, bool antiAliasRGB ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
if( fWinFont != nil ) |
|
{ |
|
DeleteObject( fWinFont ); |
|
fWinFont = nil; |
|
} |
|
if( fWinAlphaFont != nil ) |
|
{ |
|
DeleteObject( fWinAlphaFont ); |
|
fWinAlphaFont = nil; |
|
} |
|
|
|
if( face != nil ) |
|
{ |
|
int nHeight = -MulDiv( size, GetDeviceCaps( fWinRGBDC, LOGPIXELSY ), 72 ); |
|
fWinFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, |
|
CLIP_DEFAULT_PRECIS, antiAliasRGB ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, VARIABLE_PITCH, face ); |
|
hsAssert( fWinFont != nil, "Cannot create Windows font for plTextGenerator" ); |
|
|
|
// The font for the alpha channel is identical except that it's antialiased, whereas the RGB version isn't. |
|
fWinAlphaFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, |
|
CLIP_DEFAULT_PRECIS, (!antiAliasRGB) ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, VARIABLE_PITCH, face ); |
|
hsAssert( fWinAlphaFont != nil, "Cannot create Windows font for plTextGenerator" ); |
|
|
|
SelectObject( fWinRGBDC, fWinFont ); |
|
SelectObject( fWinAlphaDC, fWinAlphaFont ); |
|
} |
|
#endif |
|
} |
|
|
|
//// SetTextColor ///////////////////////////////////////////////////////////// |
|
// blockRGB basically forces the RGB channel to write in blocks instead of |
|
// actual characters. This isn't useful unless you're relying on the alpha |
|
// channel to do the text (opaque text and transparent background), in which |
|
// case you want plenty of block color in your RGB channel because it'll get |
|
// alpha-ed out by the alpha channel. |
|
|
|
void plTextGenerator::SetTextColor( hsColorRGBA &color, bool blockRGB ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
int r = (int)(color.r * 255.f); |
|
int g = (int)(color.g * 255.f); |
|
int b = (int)(color.b * 255.f); |
|
int a = (int)(color.a * 255.f); |
|
|
|
if( blockRGB ) |
|
{ |
|
::SetBkColor( fWinRGBDC, RGB( r, g, b ) ); |
|
::SetBkMode( fWinRGBDC, OPAQUE ); |
|
} |
|
else |
|
::SetBkMode( fWinRGBDC, TRANSPARENT ); |
|
|
|
::SetTextColor( fWinRGBDC, RGB( r, g, b ) ); |
|
::SetTextColor( fWinAlphaDC, RGB( a, a, a ) ); |
|
#endif |
|
} |
|
|
|
//// DrawString /////////////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::DrawString( uint16_t x, uint16_t y, const char *text ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
DrawString(x,y,wText); |
|
delete [] wText; |
|
} |
|
|
|
void plTextGenerator::DrawString( uint16_t x, uint16_t y, const wchar_t *text ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
::TextOutW( fWinRGBDC, x, y, text, wcslen( text ) ); |
|
::TextOutW( fWinAlphaDC, x, y, text, wcslen( text ) ); |
|
|
|
#endif |
|
} |
|
|
|
//// DrawClippedString //////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::DrawClippedString( int16_t x, int16_t y, const char *text, uint16_t width, uint16_t height ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
DrawClippedString(x,y,wText,width,height); |
|
delete [] wText; |
|
} |
|
|
|
void plTextGenerator::DrawClippedString( int16_t x, int16_t y, const wchar_t *text, uint16_t width, uint16_t height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT r; |
|
::SetRect( &r, x, y, x + width, y + height ); |
|
|
|
::ExtTextOutW( fWinRGBDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil ); |
|
::ExtTextOutW( fWinAlphaDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil ); |
|
|
|
#endif |
|
} |
|
|
|
//// DrawClippedString //////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::DrawClippedString( int16_t x, int16_t y, const char *text, uint16_t clipX, uint16_t clipY, uint16_t width, uint16_t height ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
DrawClippedString(x,y,wText,clipX,clipY,width,height); |
|
delete [] wText; |
|
} |
|
|
|
void plTextGenerator::DrawClippedString( int16_t x, int16_t y, const wchar_t *text, uint16_t clipX, uint16_t clipY, uint16_t width, uint16_t height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT r; |
|
::SetRect( &r, clipX, clipY, clipX + width, clipY + height ); |
|
|
|
::ExtTextOutW( fWinRGBDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil ); |
|
::ExtTextOutW( fWinAlphaDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil ); |
|
|
|
#endif |
|
} |
|
|
|
//// DrawWrappedString //////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::DrawWrappedString( uint16_t x, uint16_t y, const char *text, uint16_t width, uint16_t height ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
DrawWrappedString(x,y,wText,width,height); |
|
delete [] wText; |
|
} |
|
|
|
void plTextGenerator::DrawWrappedString( uint16_t x, uint16_t y, const wchar_t *text, uint16_t width, uint16_t height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT r; |
|
::SetRect( &r, x, y, x + width, y + height ); |
|
|
|
// HBRUSH brush = ::CreateSolidBrush( RGB( 255, 255, 255 ) ); |
|
// ::FillRect( fWinRGBDC, &r, brush ); |
|
// ::DeleteObject( brush ); |
|
::DrawTextW( fWinRGBDC, text, wcslen( text ), &r, |
|
DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK ); |
|
::DrawTextW( fWinAlphaDC, text, wcslen( text ), &r, |
|
DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK ); |
|
|
|
#endif |
|
} |
|
|
|
//// CalcStringWidth ////////////////////////////////////////////////////////// |
|
|
|
uint16_t plTextGenerator::CalcStringWidth( const char *text, uint16_t *height ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
uint16_t retVal = CalcStringWidth(wText,height); |
|
delete [] wText; |
|
return retVal; |
|
} |
|
|
|
uint16_t plTextGenerator::CalcStringWidth( const wchar_t *text, uint16_t *height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
SIZE size; |
|
::GetTextExtentPoint32W( fWinRGBDC, text, wcslen( text ), &size ); |
|
|
|
if( height != nil ) |
|
*height = (uint16_t)size.cy; |
|
|
|
return (uint16_t)size.cx; |
|
#else |
|
return 0; |
|
#endif |
|
} |
|
|
|
//// CalcWrappedStringSize //////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::CalcWrappedStringSize( const char *text, uint16_t *width, uint16_t *height ) |
|
{ |
|
wchar_t *wText = hsStringToWString(text); |
|
CalcWrappedStringSize(wText,width,height); |
|
delete [] wText; |
|
} |
|
|
|
void plTextGenerator::CalcWrappedStringSize( const wchar_t *text, uint16_t *width, uint16_t *height ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT r; |
|
::SetRect( &r, 0, 0, *width, 0 ); |
|
|
|
::DrawTextW( fWinRGBDC, text, wcslen( text ), &r, DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT ); |
|
|
|
*width = (uint16_t)(r.right); |
|
if( height != nil ) |
|
*height = (uint16_t)r.bottom; |
|
#endif |
|
} |
|
|
|
//// FillRect ///////////////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::FillRect( uint16_t x, uint16_t y, uint16_t width, uint16_t height, hsColorRGBA &color ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT rc; |
|
::SetRect( &rc, x, y, x + width, y + height ); |
|
|
|
int r = (int)(color.r * 255.f); |
|
int g = (int)(color.g * 255.f); |
|
int b = (int)(color.b * 255.f); |
|
int a = (int)(color.a * 255.f); |
|
|
|
HBRUSH brush = ::CreateSolidBrush( RGB( r, g, b ) ); |
|
::FillRect( fWinRGBDC, &rc, brush ); |
|
::DeleteObject( brush ); |
|
|
|
brush = ::CreateSolidBrush( RGB( a, a, a ) ); |
|
::FillRect( fWinAlphaDC, &rc, brush ); |
|
::DeleteObject( brush ); |
|
#endif |
|
} |
|
|
|
//// FrameRect //////////////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::FrameRect( uint16_t x, uint16_t y, uint16_t width, uint16_t height, hsColorRGBA &color ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
|
|
RECT rc; |
|
::SetRect( &rc, x, y, x + width, y + height ); |
|
|
|
int r = (int)(color.r * 255.f); |
|
int g = (int)(color.g * 255.f); |
|
int b = (int)(color.b * 255.f); |
|
int a = (int)(color.a * 255.f); |
|
|
|
HBRUSH brush = ::CreateSolidBrush( RGB( r, g, b ) ); |
|
::FrameRect( fWinRGBDC, &rc, brush ); |
|
::DeleteObject( brush ); |
|
|
|
brush = ::CreateSolidBrush( RGB( a, a, a ) ); |
|
::FrameRect( fWinAlphaDC, &rc, brush ); |
|
::DeleteObject( brush ); |
|
#endif |
|
} |
|
|
|
//// FlushToHost ////////////////////////////////////////////////////////////// |
|
|
|
void plTextGenerator::FlushToHost( void ) |
|
{ |
|
#if HS_BUILD_FOR_WIN32 |
|
// Flush the GDI first, to make sure it's done |
|
GdiFlush(); |
|
|
|
// Now copy our alpha channel over. I hate the GDI |
|
uint32_t i = fHost->fWidth * fHost->fHeight; |
|
uint32_t *dest = fWinRGBBits; |
|
uint8_t *src = fWinAlphaBits; |
|
|
|
/* while( i-- ) |
|
{ |
|
*dest &= 0x00ffffff; |
|
*dest |= ( *src ) << 24; |
|
// *dest |= ( *dest << 16 ) & 0xff000000; |
|
dest++; |
|
src++; |
|
} |
|
*/ |
|
do |
|
{ |
|
i--; |
|
dest[ i ] &= 0x00ffffff; |
|
dest[ i ] |= src[ i ] << 24; |
|
} while( i ); |
|
#endif |
|
|
|
// Dirty the mipmap's deviceRef, if there is one |
|
if( fHost->GetDeviceRef() != nil ) |
|
fHost->GetDeviceRef()->SetDirty( true ); |
|
} |
|
|
|
//// GetTextWidth/Height ////////////////////////////////////////////////////// |
|
|
|
uint16_t plTextGenerator::GetTextWidth( void ) |
|
{ |
|
return ( fHost != nil ) ? (uint16_t)(fHost->fWidth) : 0; |
|
} |
|
|
|
uint16_t plTextGenerator::GetTextHeight( void ) |
|
{ |
|
return ( fHost != nil ) ? (uint16_t)(fHost->fHeight) : 0; |
|
} |
|
|
|
//// GetLayerTransform //////////////////////////////////////////////////////// |
|
// Since the textGen can actually create a texture bigger than you were expecting, |
|
// you want to be able to apply a layer texture transform that will compensate. This |
|
// function will give you that transform. Just feed it into plLayer->SetTransform(). |
|
|
|
hsMatrix44 plTextGenerator::GetLayerTransform( void ) |
|
{ |
|
hsMatrix44 xform; |
|
hsVector3 scale; |
|
|
|
scale.Set( (float)GetWidth() / (float)GetTextWidth(), |
|
(float)GetHeight() / (float)GetTextHeight(), 1.f ); |
|
|
|
xform.MakeScaleMat( &scale ); |
|
return xform; |
|
} |
|
|
|
//// MsgReceive /////////////////////////////////////////////////////////////// |
|
|
|
bool plTextGenerator::MsgReceive( plMessage *msg ) |
|
{ |
|
#ifdef MCN_DO_REFS |
|
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg ); |
|
if( refMsg != nil ) |
|
{ |
|
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest ) ) |
|
{ |
|
// Don't do anything--already did an attach |
|
} |
|
else if( refMsg->GetContext() & ( plRefMsg::kOnDestroy | plRefMsg::kOnRemove ) ) |
|
{ |
|
Detach(); |
|
} |
|
return true; |
|
} |
|
#endif |
|
|
|
return hsKeyedObject::MsgReceive( msg ); |
|
}
|
|
|