mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Merged in cwalther/cwe/textrendering (pull request #36)
Shadowed Chat and Player List Text This implements the (existing but unimplemented) plDynamicTextMap::kFontShadowed flag, making the text of the mini KI (player list and chat) better readable on light and patterned backgrounds. For best results, an additional Python change is recommended: MOULSCRIPT-ou PR #23. From H-uru/Plasma#392.
This commit is contained in:
@ -71,6 +71,7 @@ struct hsColorRGBA {
|
||||
|
||||
hsColorRGBA& FromARGB32(UInt32 c);
|
||||
UInt32 ToARGB32() const;
|
||||
UInt32 ToARGB32Premultiplied() const;
|
||||
|
||||
void Read(hsStream *stream);
|
||||
void Write(hsStream *stream) const;
|
||||
@ -109,6 +110,14 @@ inline UInt32 hsColorRGBA::ToARGB32() const
|
||||
| (UInt32(b * 255.99f) << 0);
|
||||
}
|
||||
|
||||
inline UInt32 hsColorRGBA::ToARGB32Premultiplied() const
|
||||
{
|
||||
return (UInt32(a * 255.0f + 0.5f) << 24)
|
||||
| (UInt32(a * r * 255.0f + 0.5f) << 16)
|
||||
| (UInt32(a * g * 255.0f + 0.5f) << 8)
|
||||
| (UInt32(a * b * 255.0f + 0.5f) << 0);
|
||||
}
|
||||
|
||||
inline hsColorRGBA operator+(const hsColorRGBA& s, const hsColorRGBA& t)
|
||||
{
|
||||
hsColorRGBA res;
|
||||
|
@ -56,6 +56,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plDeviceRecreateMsg.h"
|
||||
#include "../pnSceneObject/plDrawInterface.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../pnSceneObject/plAudioInterface.h"
|
||||
@ -584,14 +585,16 @@ plProfile_CreateTimer("Gui", "RenderSetup", GUITime);
|
||||
hsBool pfGUIControlMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plRenderMsg* rend = plRenderMsg::ConvertNoRef( msg );
|
||||
plDeviceRecreateMsg* device = plDeviceRecreateMsg::ConvertNoRef(msg);
|
||||
if (rend || device) {
|
||||
plPipeline* pipe = rend ? rend->Pipeline() : device->Pipeline();
|
||||
|
||||
if( rend )
|
||||
{
|
||||
plProfile_BeginLap(GUITime, this->GetKey()->GetUoid().GetObjectName());
|
||||
// Only need it once
|
||||
if( ISetUpDynTextMap( rend->Pipeline() ) )
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plRenderMsg::Index(), GetKey() );
|
||||
ISetUpDynTextMap(pipe);
|
||||
plProfile_EndLap(GUITime, this->GetKey()->GetUoid().GetObjectName());
|
||||
|
||||
if (rend)
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -603,12 +606,16 @@ hsBool pfGUIControlMod::MsgReceive( plMessage *msg )
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fDynTextMap = plDynamicTextMap::ConvertNoRef( refMsg->GetRef() );
|
||||
// Register for a render msg so we can leech the material when we finally
|
||||
// have a pipeline to work with
|
||||
|
||||
// These tell us when we need to (re-)initialize the DTM
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plRenderMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plDeviceRecreateMsg::Index(), GetKey() );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDynTextMap = nil;
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plDeviceRecreateMsg::Index(), GetKey() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefDynTextLayer )
|
||||
@ -688,7 +695,7 @@ hsBool pfGUIControlMod::ISetUpDynTextMap( plPipeline *pipe )
|
||||
extraH -= height;
|
||||
|
||||
fDynTextMap->Reset();
|
||||
fDynTextMap->Create( width, height, HasFlag( kXparentBgnd ), extraW, extraH );
|
||||
fDynTextMap->Create( width, height, HasFlag( kXparentBgnd ), extraW, extraH, true );
|
||||
|
||||
fDynTextMap->SetFont( GetColorScheme()->fFontFace, GetColorScheme()->fFontSize, GetColorScheme()->fFontFlags,
|
||||
HasFlag( kXparentBgnd ) ? false : true );
|
||||
@ -699,6 +706,7 @@ hsBool pfGUIControlMod::ISetUpDynTextMap( plPipeline *pipe )
|
||||
// out with 1:1 mapping from textel to pixel
|
||||
plLayer *layer = (plLayer *)fDynTextLayer;
|
||||
layer->SetTransform( fDynTextMap->GetLayerTransform() );
|
||||
layer->SetBlendFlags( layer->GetBlendFlags() | hsGMatState::kBlendAlphaPremultiplied );
|
||||
|
||||
// Let the derived classes do their things
|
||||
IPostSetUpDynTextMap();
|
||||
|
@ -247,6 +247,8 @@ class pfGUIControlMod : public plSingleModifier
|
||||
virtual void SetColorScheme( pfGUIColorScheme *newScheme );
|
||||
pfGUIColorScheme *GetColorScheme( void ) const;
|
||||
|
||||
virtual void UpdateColorScheme() { IPostSetUpDynTextMap(); IUpdate(); }
|
||||
|
||||
// should be override by specific GUIcontrol
|
||||
virtual void PurgeDynaTextMapImage() {;}
|
||||
|
||||
|
@ -197,9 +197,9 @@ void pfGUIEditBoxMod::IUpdate( void )
|
||||
oldCursorPos = cursorPos;
|
||||
cursorPos -= (Int16)fScrollPos;
|
||||
|
||||
if( 4 + cursorPos > fDynTextMap->GetVisibleWidth() - 18 )
|
||||
if( 4 + cursorPos > fDynTextMap->GetVisibleWidth() - 4 - 2 )
|
||||
{
|
||||
fScrollPos += ( 4 + cursorPos ) - ( fDynTextMap->GetVisibleWidth() - 18 );
|
||||
fScrollPos += ( 4 + cursorPos ) - ( fDynTextMap->GetVisibleWidth() - 4 - 2 );
|
||||
}
|
||||
else if( 4 + cursorPos < 4 )
|
||||
{
|
||||
|
@ -180,6 +180,10 @@ hsBool pfGUIListBoxMod::MsgReceive( plMessage *msg )
|
||||
|
||||
void pfGUIListBoxMod::IPostSetUpDynTextMap( void )
|
||||
{
|
||||
pfGUIColorScheme *scheme = GetColorScheme();
|
||||
fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags,
|
||||
!HasFlag( kXparentBgnd ));
|
||||
|
||||
ICalcWrapStarts();
|
||||
ICalcScrollRange();
|
||||
fReadyToRoll = true;
|
||||
|
@ -216,6 +216,8 @@ class pfGUIMultiLineEditCtrl : public pfGUIControlMod
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
virtual void UpdateColorScheme() { fFontFlagsSet = 0; pfGUIControlMod::UpdateColorScheme(); }
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
|
@ -102,8 +102,6 @@ class pfGUITextBoxMod : public pfGUIControlMod
|
||||
void SetLocalizationPath(const wchar_t* path);
|
||||
void SetLocalizationPath(const char* path);
|
||||
void SetUseLocalizationPath(bool use);
|
||||
|
||||
virtual void UpdateColorScheme() { IPostSetUpDynTextMap(); IUpdate(); }
|
||||
};
|
||||
|
||||
#endif // _pfGUITextBoxMod_h
|
||||
|
@ -491,4 +491,10 @@ void pyDynamicText::AddPlasmaConstantsClasses(PyObject *m)
|
||||
PYTHON_ENUM_ELEMENT(PtJustify, kLeftJustify, plDynamicTextMap::Justify::kLeftJustify);
|
||||
PYTHON_ENUM_ELEMENT(PtJustify, kRightJustify, plDynamicTextMap::Justify::kRightJustify);
|
||||
PYTHON_ENUM_END(m, PtJustify);
|
||||
|
||||
PYTHON_ENUM_START(PtFontFlags);
|
||||
PYTHON_ENUM_ELEMENT(PtFontFlags, kFontBold, plDynamicTextMap::kFontBold);
|
||||
PYTHON_ENUM_ELEMENT(PtFontFlags, kFontItalic, plDynamicTextMap::kFontItalic);
|
||||
PYTHON_ENUM_ELEMENT(PtFontFlags, kFontShadowed, plDynamicTextMap::kFontShadowed);
|
||||
PYTHON_ENUM_END(m, PtFontFlags);
|
||||
}
|
@ -278,7 +278,7 @@ PyObject* pyGUIControl::GetOwnerDlg( void )
|
||||
}
|
||||
|
||||
// get color schemes
|
||||
PyObject* pyGUIControl::GetForeColor()
|
||||
PyObject* pyGUIControl::GetForeColor() const
|
||||
{
|
||||
if ( fGCkey )
|
||||
{
|
||||
@ -292,7 +292,7 @@ PyObject* pyGUIControl::GetForeColor()
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* pyGUIControl::GetSelColor()
|
||||
PyObject* pyGUIControl::GetSelColor() const
|
||||
{
|
||||
if ( fGCkey )
|
||||
{
|
||||
@ -306,7 +306,7 @@ PyObject* pyGUIControl::GetSelColor()
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* pyGUIControl::GetBackColor()
|
||||
PyObject* pyGUIControl::GetBackColor() const
|
||||
{
|
||||
if ( fGCkey )
|
||||
{
|
||||
@ -320,7 +320,7 @@ PyObject* pyGUIControl::GetBackColor()
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject* pyGUIControl::GetBackSelColor()
|
||||
PyObject* pyGUIControl::GetBackSelColor() const
|
||||
{
|
||||
if ( fGCkey )
|
||||
{
|
||||
@ -334,7 +334,7 @@ PyObject* pyGUIControl::GetBackSelColor()
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
UInt32 pyGUIControl::GetFontSize()
|
||||
UInt32 pyGUIControl::GetFontSize() const
|
||||
{
|
||||
if ( fGCkey )
|
||||
{
|
||||
@ -444,3 +444,34 @@ void pyGUIControl::SetFontSize(UInt32 fontsize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pyGUIControl::SetFontFlags(UInt8 fontFlags)
|
||||
{
|
||||
if (fGCkey)
|
||||
{
|
||||
// get the pointer to the modifier
|
||||
pfGUIControlMod* pdmod = pfGUIControlMod::ConvertNoRef(fGCkey->ObjectIsLoaded());
|
||||
if (pdmod)
|
||||
{
|
||||
pfGUIColorScheme* colorscheme = pdmod->GetColorScheme();
|
||||
colorscheme->fFontFlags = fontFlags;
|
||||
pdmod->UpdateColorScheme();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt8 pyGUIControl::GetFontFlags() const
|
||||
{
|
||||
if (fGCkey)
|
||||
{
|
||||
// get the pointer to the modifier
|
||||
pfGUIControlMod* pdmod = pfGUIControlMod::ConvertNoRef(fGCkey->ObjectIsLoaded());
|
||||
if (pdmod)
|
||||
{
|
||||
pfGUIColorScheme* colorscheme = pdmod->GetColorScheme();
|
||||
return colorscheme->fFontFlags;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -116,17 +116,19 @@ public:
|
||||
virtual PyObject* GetOwnerDlg( void ); // returns pyGUIDialog
|
||||
|
||||
// get color schemes
|
||||
virtual PyObject* GetForeColor(); // returns pyColor
|
||||
virtual PyObject* GetSelColor(); // returns pyColor
|
||||
virtual PyObject* GetBackColor(); // returns pyColor
|
||||
virtual PyObject* GetBackSelColor(); // returns pyColor
|
||||
virtual UInt32 GetFontSize();
|
||||
virtual PyObject* GetForeColor() const; // returns pyColor
|
||||
virtual PyObject* GetSelColor() const; // returns pyColor
|
||||
virtual PyObject* GetBackColor() const; // returns pyColor
|
||||
virtual PyObject* GetBackSelColor() const; // returns pyColor
|
||||
virtual UInt32 GetFontSize() const;
|
||||
virtual UInt8 GetFontFlags() const;
|
||||
// set color scheme
|
||||
virtual void SetForeColor( hsScalar r, hsScalar g, hsScalar b, hsScalar a );
|
||||
virtual void SetSelColor( hsScalar r, hsScalar g, hsScalar b, hsScalar a );
|
||||
virtual void SetBackColor( hsScalar r, hsScalar g, hsScalar b, hsScalar a );
|
||||
virtual void SetBackSelColor( hsScalar r, hsScalar g, hsScalar b, hsScalar a );
|
||||
virtual void SetFontSize(UInt32 fontsize);
|
||||
virtual void SetFontFlags(UInt8 fontflags);
|
||||
|
||||
};
|
||||
|
||||
|
@ -244,6 +244,23 @@ PYTHON_METHOD_DEFINITION_NOARGS(ptGUIControl, getFontSize)
|
||||
return PyLong_FromUnsignedLong(self->fThis->GetFontSize());
|
||||
}
|
||||
|
||||
PYTHON_METHOD_DEFINITION_NOARGS(ptGUIControl, getFontFlags)
|
||||
{
|
||||
return PyInt_FromLong(self->fThis->GetFontFlags());
|
||||
}
|
||||
|
||||
PYTHON_METHOD_DEFINITION(ptGUIControl, setFontFlags, args)
|
||||
{
|
||||
unsigned char fontflags;
|
||||
if (!PyArg_ParseTuple(args, "b", &fontflags))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "setFontFlags expects an unsigned 8-bit int");
|
||||
PYTHON_RETURN_ERROR;
|
||||
}
|
||||
self->fThis->SetFontFlags(fontflags);
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
PYTHON_METHOD_DEFINITION(ptGUIControl, setForeColor, args)
|
||||
{
|
||||
float r, g, b, a;
|
||||
@ -329,11 +346,13 @@ PYTHON_START_METHODS_TABLE(ptGUIControl)
|
||||
PYTHON_METHOD_NOARGS(ptGUIControl, getBackColor, "Returns the background color"),
|
||||
PYTHON_METHOD_NOARGS(ptGUIControl, getBackSelectColor, "Returns the background selection color"),
|
||||
PYTHON_METHOD_NOARGS(ptGUIControl, getFontSize, "Returns the font size"),
|
||||
PYTHON_METHOD_NOARGS(ptGUIControl, getFontFlags, "Returns the current fontflags"),
|
||||
PYTHON_METHOD(ptGUIControl, setForeColor, "Params: r,g,b,a\nSets the foreground color"),
|
||||
PYTHON_METHOD(ptGUIControl, setSelectColor, "Params: r,g,b,a\nSets the selection color"),
|
||||
PYTHON_METHOD(ptGUIControl, setBackColor, "Params: r,g,b,a\nSets the background color"),
|
||||
PYTHON_METHOD(ptGUIControl, setBackSelectColor, "Params: r,g,b,a\nSets the selection background color"),
|
||||
PYTHON_METHOD(ptGUIControl, setFontSize, "Params: fontSize\nSets the font size"),
|
||||
PYTHON_METHOD(ptGUIControl, setFontFlags, "Params: fontflags\nSets current fontflags"),
|
||||
PYTHON_END_METHODS_TABLE;
|
||||
|
||||
// Type structure definition
|
||||
|
@ -214,3 +214,4 @@ UInt8 pyGUIControlTextBox::GetJustify()
|
||||
}
|
||||
return pfGUIListText::kLeftJustify;
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
virtual void SetForeColor( pyColor& color );
|
||||
virtual void SetBackColor( pyColor& color );
|
||||
virtual void SetJustify( UInt8 justify );
|
||||
|
||||
virtual UInt8 GetJustify();
|
||||
virtual PyObject* GetForeColor(); // returns pyColor
|
||||
};
|
||||
|
@ -185,6 +185,8 @@ PYTHON_METHOD_DEFINITION(ptGUIControlTextBox, setStringJustify, args)
|
||||
PYTHON_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PYTHON_METHOD_DEFINITION_NOARGS(ptGUIControlTextBox, getStringJustify)
|
||||
{
|
||||
return PyInt_FromLong(self->fThis->GetJustify());
|
||||
|
@ -85,7 +85,8 @@ enum hsGMatBlendFlags {
|
||||
kBlendEnvBumpNext = 0x800000,
|
||||
kBlendSubtract = 0x1000000,
|
||||
kBlendRevSubtract = 0x2000000,
|
||||
kBlendAlphaTestHigh = 0x4000000
|
||||
kBlendAlphaTestHigh = 0x4000000,
|
||||
kBlendAlphaPremultiplied = 0x8000000
|
||||
};
|
||||
enum hsGMatClampFlags {
|
||||
|
||||
|
@ -75,20 +75,12 @@ plProfile_Extern(MemMipmaps);
|
||||
|
||||
//// Constructor & Destructor /////////////////////////////////////////////////
|
||||
|
||||
plDynamicTextMap::plDynamicTextMap() : plMipmap()
|
||||
plDynamicTextMap::plDynamicTextMap()
|
||||
: fVisWidth(0), fVisHeight(0), fHasAlpha(false), fPremultipliedAlpha(false), fJustify(kLeftJustify),
|
||||
fInitBuffer(nil), fFontFace(nil), fFontSize(0), fFontFlags(0),
|
||||
fFontAntiAliasRGB(false), fFontBlockRGB(false), fHasCreateBeenCalled(false)
|
||||
{
|
||||
fVisWidth = fVisHeight = 0;
|
||||
fHasAlpha = false;
|
||||
fJustify = kLeftJustify;
|
||||
fInitBuffer = nil;
|
||||
fFontFace = nil;
|
||||
fFontSize = 0;
|
||||
fFontFlags = 0;
|
||||
fFontAntiAliasRGB = false;
|
||||
fFontColor.Set( 0, 0, 0, 1 );
|
||||
fFontBlockRGB = false;
|
||||
fHasCreateBeenCalled = false;
|
||||
|
||||
fFontColor.Set(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
plDynamicTextMap::~plDynamicTextMap()
|
||||
@ -96,11 +88,10 @@ plDynamicTextMap::~plDynamicTextMap()
|
||||
Reset();
|
||||
}
|
||||
|
||||
plDynamicTextMap::plDynamicTextMap( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth, UInt32 extraHeight ) : plMipmap()
|
||||
plDynamicTextMap::plDynamicTextMap( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth, UInt32 extraHeight, hsBool premultipliedAlpha )
|
||||
: fInitBuffer(nil), fFontFace(nil)
|
||||
{
|
||||
fInitBuffer = nil;
|
||||
fFontFace = nil;
|
||||
Create( width, height, hasAlpha, extraWidth, extraHeight );
|
||||
Create( width, height, hasAlpha, extraWidth, extraHeight, premultipliedAlpha );
|
||||
}
|
||||
|
||||
//// SetNoCreate //////////////////////////////////////////////////////////////
|
||||
@ -122,7 +113,7 @@ void plDynamicTextMap::SetNoCreate( UInt32 width, UInt32 height, hsBool hasAlpha
|
||||
|
||||
//// Create ///////////////////////////////////////////////////////////////////
|
||||
|
||||
void plDynamicTextMap::Create( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth, UInt32 extraHeight )
|
||||
void plDynamicTextMap::Create( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth, UInt32 extraHeight, hsBool premultipliedAlpha )
|
||||
{
|
||||
SetConfig( hasAlpha ? kARGB32Config : kRGB32Config );
|
||||
|
||||
@ -130,6 +121,7 @@ void plDynamicTextMap::Create( UInt32 width, UInt32 height, hsBool hasAlpha, UIn
|
||||
fVisWidth = (UInt16)width;
|
||||
fVisHeight = (UInt16)height;
|
||||
fHasAlpha = hasAlpha;
|
||||
fPremultipliedAlpha = premultipliedAlpha;
|
||||
|
||||
for( fWidth = 1; fWidth < width + extraWidth; fWidth <<= 1 );
|
||||
for( fHeight = 1; fHeight < height + extraHeight; fHeight <<= 1 );
|
||||
@ -388,6 +380,17 @@ void plDynamicTextMap::IClearFromBuffer( UInt32 *clearBuffer )
|
||||
}
|
||||
}
|
||||
|
||||
//// IPropagateFlags //////////////////////////////////////////////////////////
|
||||
|
||||
void plDynamicTextMap::IPropagateFlags()
|
||||
{
|
||||
SetJustify(fJustify);
|
||||
fCurrFont->SetRenderFlag(plFont::kRenderShadow, fFontFlags & kFontShadowed);
|
||||
fCurrFont->SetRenderFlag(plFont::kRenderIntoAlpha, fFontBlockRGB);
|
||||
fCurrFont->SetRenderFlag(plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha);
|
||||
fCurrFont->SetRenderColor(fFontColor.ToARGB32());
|
||||
}
|
||||
|
||||
//// ClearToColor /////////////////////////////////////////////////////////////
|
||||
|
||||
void plDynamicTextMap::ClearToColor( hsColorRGBA &color )
|
||||
@ -395,7 +398,7 @@ void plDynamicTextMap::ClearToColor( hsColorRGBA &color )
|
||||
if( !IIsValid() )
|
||||
return;
|
||||
|
||||
UInt32 i, hex = color.ToARGB32();
|
||||
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||
UInt32 *data = (UInt32 *)fImage;
|
||||
|
||||
// Buffer is of size fVisWidth x fVisHeight, so we need a bit of work to do this right
|
||||
@ -462,6 +465,8 @@ void plDynamicTextMap::SetFont( const char *face, UInt16 size, UInt8 fontFlags,
|
||||
// This will be nil if we're just running the page optimizer.
|
||||
if (fCurrFont)
|
||||
{
|
||||
if (fFontFlags & kFontShadowed)
|
||||
fCurrFont->SetRenderFlag(plFont::kRenderShadow, true);
|
||||
fCurrFont->SetRenderYJustify( plFont::kRenderJustYTop );
|
||||
SetJustify( fJustify );
|
||||
}
|
||||
@ -515,10 +520,9 @@ void plDynamicTextMap::DrawString( UInt16 x, UInt16 y, const wchar_t *text )
|
||||
if( !IIsValid() )
|
||||
return;
|
||||
|
||||
SetJustify( fJustify );
|
||||
IPropagateFlags();
|
||||
fCurrFont->SetRenderFlag( plFont::kRenderWrap | plFont::kRenderClip, false );
|
||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||
fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight );
|
||||
fCurrFont->RenderString( this, x, y, text );
|
||||
}
|
||||
|
||||
@ -536,10 +540,8 @@ void plDynamicTextMap::DrawClippedString( Int16 x, Int16 y, const wchar_t *text,
|
||||
if( !IIsValid() )
|
||||
return;
|
||||
|
||||
SetJustify( fJustify );
|
||||
IPropagateFlags();
|
||||
fCurrFont->SetRenderClipping( x, y, width, height );
|
||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||
fCurrFont->RenderString( this, x, y, text );
|
||||
}
|
||||
|
||||
@ -557,9 +559,8 @@ void plDynamicTextMap::DrawClippedString( Int16 x, Int16 y, const wchar_t *text,
|
||||
if( !IIsValid() )
|
||||
return;
|
||||
|
||||
SetJustify( fJustify );
|
||||
IPropagateFlags();
|
||||
fCurrFont->SetRenderClipping( clipX, clipY, width, height );
|
||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||
fCurrFont->RenderString( this, x, y, text );
|
||||
}
|
||||
|
||||
@ -577,10 +578,8 @@ void plDynamicTextMap::DrawWrappedString( UInt16 x, UInt16 y, const wchar_t *tex
|
||||
if( !IIsValid() )
|
||||
return;
|
||||
|
||||
SetJustify( fJustify );
|
||||
IPropagateFlags();
|
||||
fCurrFont->SetRenderWrapping( x, y, width, height );
|
||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||
fCurrFont->RenderString( this, x, y, text, lastX, lastY );
|
||||
}
|
||||
|
||||
@ -664,7 +663,7 @@ void plDynamicTextMap::FillRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height
|
||||
width = (UInt16)(fWidth - x);
|
||||
|
||||
// Gee, how hard can it REALLY be?
|
||||
UInt32 i, hex = color.ToARGB32();
|
||||
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||
height += y;
|
||||
if( height > fHeight )
|
||||
height = (UInt16)fHeight;
|
||||
@ -689,7 +688,7 @@ void plDynamicTextMap::FrameRect( UInt16 x, UInt16 y, UInt16 width, UInt16 heigh
|
||||
height = (UInt16)(fHeight - y);
|
||||
|
||||
// Shouldn't be much harder
|
||||
UInt32 i, hex = color.ToARGB32();
|
||||
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||
UInt32 *dest1, *dest2;
|
||||
|
||||
dest1 = GetAddr32( x, y );
|
||||
@ -724,6 +723,9 @@ void plDynamicTextMap::DrawImage( UInt16 x, UInt16 y, plMipmap *image, DrawMetho
|
||||
else if( method == kImgSprite )
|
||||
opts.fFlags = plMipmap::kCopySrcAlpha;
|
||||
|
||||
if( fPremultipliedAlpha )
|
||||
opts.fFlags |= plMipmap::kDestPremultiplied;
|
||||
|
||||
Composite( image, x, y, &opts );
|
||||
|
||||
/// HACK for now, since the alpha in the mipmap gets copied straight into the
|
||||
@ -762,6 +764,9 @@ void plDynamicTextMap::DrawClippedImage( UInt16 x, UInt16 y, plMipmap *image,
|
||||
else if( method == kImgSprite )
|
||||
opts.fFlags = plMipmap::kCopySrcAlpha;
|
||||
|
||||
if( fPremultipliedAlpha )
|
||||
opts.fFlags |= plMipmap::kDestPremultiplied;
|
||||
|
||||
opts.fSrcClipX = srcClipX;
|
||||
opts.fSrcClipY = srcClipY;
|
||||
opts.fSrcClipWidth = srcClipWidth;
|
||||
@ -908,6 +913,7 @@ void plDynamicTextMap::Swap( plDynamicTextMap *other )
|
||||
|
||||
// Swap DTMap info
|
||||
SWAP_ME( hsBool, fHasAlpha, other->fHasAlpha );
|
||||
SWAP_ME( hsBool, fPremultipliedAlpha, other->fPremultipliedAlpha );
|
||||
SWAP_ME( hsBool, fShadowed, other->fShadowed );
|
||||
|
||||
SWAP_ME( Justify, fJustify, other->fJustify );
|
||||
|
@ -113,14 +113,14 @@ class plDynamicTextMap : public plMipmap
|
||||
|
||||
|
||||
plDynamicTextMap();
|
||||
plDynamicTextMap( UInt32 width, UInt32 height, hsBool hasAlpha = false, UInt32 extraWidth = 0, UInt32 extraHeight = 0 );
|
||||
plDynamicTextMap( UInt32 width, UInt32 height, hsBool hasAlpha = false, UInt32 extraWidth = 0, UInt32 extraHeight = 0, hsBool premultipliedAlpha = false );
|
||||
virtual ~plDynamicTextMap();
|
||||
|
||||
CLASSNAME_REGISTER( plDynamicTextMap );
|
||||
GETINTERFACE_ANY( plDynamicTextMap, plMipmap );
|
||||
|
||||
|
||||
void Create( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth = 0, UInt32 extraHeight = 0 );
|
||||
void Create( UInt32 width, UInt32 height, hsBool hasAlpha, UInt32 extraWidth = 0, UInt32 extraHeight = 0, hsBool premultipliedAlpha = false );
|
||||
void SetNoCreate( UInt32 width, UInt32 height, hsBool hasAlpha );
|
||||
|
||||
virtual void Reset( void );
|
||||
@ -222,7 +222,9 @@ class plDynamicTextMap : public plMipmap
|
||||
UInt32 *IAllocateOSSurface( UInt16 width, UInt16 height );
|
||||
void IDestroyOSSurface( void );
|
||||
|
||||
hsBool fHasAlpha, fShadowed;
|
||||
void IPropagateFlags();
|
||||
|
||||
hsBool fHasAlpha, fPremultipliedAlpha, fShadowed;
|
||||
|
||||
Justify fJustify;
|
||||
char *fFontFace;
|
||||
|
@ -345,7 +345,14 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
|
||||
{
|
||||
if( fRenderInfo.fFlags & kRenderIntoAlpha )
|
||||
{
|
||||
if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 )
|
||||
if( fRenderInfo.fFlags & kRenderAlphaPremultiplied )
|
||||
{
|
||||
if (fRenderInfo.fFlags & kRenderShadow)
|
||||
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremShadow;
|
||||
else
|
||||
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremultiplied;
|
||||
}
|
||||
else if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 )
|
||||
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32Alpha;
|
||||
else
|
||||
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32FullAlpha;
|
||||
@ -659,24 +666,27 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
|
||||
// Advance left past any clipping area
|
||||
CharRenderFunc oldFunc = fRenderInfo.fRenderFunc;
|
||||
fRenderInfo.fRenderFunc = &plFont::IRenderCharNull;
|
||||
while( fRenderInfo.fX < fRenderInfo.fClipRect.fX && *string != 0 )
|
||||
Int16 prevX;
|
||||
do
|
||||
{
|
||||
prevX = fRenderInfo.fX;
|
||||
IRenderLoop( string, 1 );
|
||||
string++;
|
||||
}
|
||||
while( fRenderInfo.fX <= fRenderInfo.fClipRect.fX && *++string != 0 );
|
||||
fRenderInfo.fMaxWidth += fRenderInfo.fX - prevX;
|
||||
fRenderInfo.fDestPtr -= (fRenderInfo.fX - prevX) * fRenderInfo.fDestBPP;
|
||||
fRenderInfo.fX = prevX;
|
||||
fRenderInfo.fRenderFunc = oldFunc;
|
||||
}
|
||||
|
||||
// Adjust for left kern
|
||||
if( ( fRenderInfo.fFlags & kRenderJustXMask ) == kRenderJustXForceLeft )
|
||||
{
|
||||
// See note at top of file
|
||||
plCharacter &ch = fCharacters[ (UInt16)string[ 0 ] - fFirstChar ];
|
||||
Int32 newX = x - (Int16)ch.fLeftKern;
|
||||
if( newX < 0 )
|
||||
newX = 0;
|
||||
fRenderInfo.fX = fRenderInfo.fFarthestX = (Int16)newX;
|
||||
}
|
||||
// There used to be an adjustment of the X coordinate by -ch.fLeftKern for the case
|
||||
// of kRenderJustXForceLeft here, but it was buggy in that it neglected to adjust
|
||||
// fRenderInfo.fDestPtr and therefore had no visible effect (or almost none - only
|
||||
// at the end of the line). Fixing the bug however (making kRenderJustXForceLeft
|
||||
// work as intended) causes the text shadow to be cut off in some places. To ensure
|
||||
// enough space for the shadow, and considering that all content was developed and
|
||||
// visually optimized with the bug in place, it seems better to preserve the buggy
|
||||
// behavior and make kRenderJustXForceLeft work exactly like kRenderJustXLeft.
|
||||
|
||||
fRenderInfo.fVolatileStringPtr = string; // Just so we can keep track of when we clip
|
||||
IRenderLoop( string, -1 );
|
||||
@ -715,9 +725,6 @@ void plFont::IRenderLoop( const wchar_t *string, Int32 maxCount )
|
||||
if( fRenderInfo.fFlags & kRenderScaleAA )
|
||||
thisWidth >>= 1;
|
||||
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
break;
|
||||
|
||||
(this->*(fRenderInfo.fRenderFunc))( fCharacters[ c ] );
|
||||
|
||||
fRenderInfo.fX += thisWidth;
|
||||
@ -848,8 +855,8 @@ void plFont::IRenderChar8To32( const plFont::plCharacter &c )
|
||||
{
|
||||
UInt8 *src = fBMapData + c.fBitmapOff;
|
||||
UInt32 *destPtr, *destBasePtr = (UInt32 *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride );
|
||||
UInt16 x, y;
|
||||
UInt32 srcAlpha, oneMinusAlpha, r, g, b, dR, dG, dB, destAlpha, thisWidth;
|
||||
Int16 x, y, thisHeight, xstart, thisWidth;
|
||||
UInt32 srcAlpha, oneMinusAlpha, r, g, b, dR, dG, dB, destAlpha;
|
||||
UInt8 srcR, srcG, srcB;
|
||||
|
||||
|
||||
@ -860,19 +867,35 @@ void plFont::IRenderChar8To32( const plFont::plCharacter &c )
|
||||
// difference, especially since the dest pixels that we end up overlapping
|
||||
// should already be in the cache. If it does, time to upgrade the font
|
||||
// format (again)
|
||||
thisWidth = fWidth;// + (Int32)c.fRightKern;
|
||||
thisWidth = (Int16)fWidth;// + (Int32)c.fRightKern;
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
thisWidth = fRenderInfo.fMaxWidth;
|
||||
|
||||
if( (Int32)c.fHeight - (Int32)c.fBaseline >= fRenderInfo.fMaxHeight || thisWidth >= fRenderInfo.fMaxWidth || c.fBaseline > fRenderInfo.fY )
|
||||
return;
|
||||
xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX;
|
||||
if( xstart < 0 )
|
||||
xstart = 0;
|
||||
|
||||
srcR = (UInt8)(( fRenderInfo.fColor >> 16 ) & 0x000000ff);
|
||||
srcG = (UInt8)(( fRenderInfo.fColor >> 8 ) & 0x000000ff);
|
||||
srcB = (UInt8)(( fRenderInfo.fColor ) & 0x000000ff);
|
||||
|
||||
for( y = 0; y < c.fHeight; y++ )
|
||||
y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline;
|
||||
if( y < 0 )
|
||||
y = 0;
|
||||
else
|
||||
{
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + y*fRenderInfo.fDestStride );
|
||||
src += y*fRenderInfo.fNumCols;
|
||||
}
|
||||
|
||||
thisHeight = fRenderInfo.fMaxHeight + (Int16)c.fBaseline;
|
||||
if( thisHeight > (Int16)c.fHeight )
|
||||
thisHeight = (Int16)c.fHeight;
|
||||
|
||||
for( ; y < thisHeight; y++ )
|
||||
{
|
||||
destPtr = destBasePtr;
|
||||
for( x = 0; x < thisWidth; x++ )
|
||||
for( x = xstart; x < thisWidth; x++ )
|
||||
{
|
||||
if( src[ x ] == 255 )
|
||||
destPtr[ x ] = fRenderInfo.fColor;
|
||||
@ -907,8 +930,8 @@ void plFont::IRenderChar8To32FullAlpha( const plFont::plCharacter &c )
|
||||
{
|
||||
UInt8 *src = fBMapData + c.fBitmapOff;
|
||||
UInt32 *destPtr, *destBasePtr = (UInt32 *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride );
|
||||
UInt16 x, y;
|
||||
UInt32 destColorOnly, thisWidth;
|
||||
Int16 x, y, thisHeight, xstart, thisWidth;
|
||||
UInt32 destColorOnly;
|
||||
|
||||
|
||||
// Unfortunately for some fonts, their right kern value actually is
|
||||
@ -918,17 +941,33 @@ void plFont::IRenderChar8To32FullAlpha( const plFont::plCharacter &c )
|
||||
// difference, especially since the dest pixels that we end up overlapping
|
||||
// should already be in the cache. If it does, time to upgrade the font
|
||||
// format (again)
|
||||
thisWidth = fWidth;// + (Int32)c.fRightKern;
|
||||
thisWidth = (Int16)fWidth;// + (Int32)c.fRightKern;
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
thisWidth = fRenderInfo.fMaxWidth;
|
||||
|
||||
if( (Int32)c.fHeight - (Int32)c.fBaseline >= fRenderInfo.fMaxHeight || thisWidth >= fRenderInfo.fMaxWidth || c.fBaseline > fRenderInfo.fY )
|
||||
return;
|
||||
xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX;
|
||||
if( xstart < 0 )
|
||||
xstart = 0;
|
||||
|
||||
destColorOnly = fRenderInfo.fColor & 0x00ffffff;
|
||||
|
||||
for( y = 0; y < c.fHeight; y++ )
|
||||
y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline;
|
||||
if( y < 0 )
|
||||
y = 0;
|
||||
else
|
||||
{
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + y*fRenderInfo.fDestStride );
|
||||
src += y*fRenderInfo.fNumCols;
|
||||
}
|
||||
|
||||
thisHeight = fRenderInfo.fMaxHeight + (Int16)c.fBaseline;
|
||||
if( thisHeight > (Int16)c.fHeight )
|
||||
thisHeight = (Int16)c.fHeight;
|
||||
|
||||
for( ; y < thisHeight; y++ )
|
||||
{
|
||||
destPtr = destBasePtr;
|
||||
for( x = 0; x < thisWidth; x++ )
|
||||
for( x = xstart; x < thisWidth; x++ )
|
||||
{
|
||||
if( src[ x ] != 0 )
|
||||
destPtr[ x ] = ( src[ x ] << 24 ) | destColorOnly;
|
||||
@ -942,8 +981,8 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c )
|
||||
{
|
||||
UInt8 val, *src = fBMapData + c.fBitmapOff;
|
||||
UInt32 *destPtr, *destBasePtr = (UInt32 *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride );
|
||||
UInt16 x, y;
|
||||
UInt32 destColorOnly, alphaMult, fullAlpha, thisWidth;
|
||||
Int16 x, y, thisHeight, xstart, thisWidth;
|
||||
UInt32 destColorOnly, alphaMult, fullAlpha;
|
||||
|
||||
|
||||
// Unfortunately for some fonts, their right kern value actually is
|
||||
@ -953,10 +992,13 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c )
|
||||
// difference, especially since the dest pixels that we end up overlapping
|
||||
// should already be in the cache. If it does, time to upgrade the font
|
||||
// format (again)
|
||||
thisWidth = fWidth;// + (Int32)c.fRightKern;
|
||||
thisWidth = (Int16)fWidth;// + (Int32)c.fRightKern;
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
thisWidth = fRenderInfo.fMaxWidth;
|
||||
|
||||
if( (Int32)c.fHeight - (Int32)c.fBaseline >= fRenderInfo.fMaxHeight || thisWidth >= fRenderInfo.fMaxWidth || c.fBaseline > fRenderInfo.fY )
|
||||
return;
|
||||
xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX;
|
||||
if( xstart < 0 )
|
||||
xstart = 0;
|
||||
|
||||
destColorOnly = fRenderInfo.fColor & 0x00ffffff;
|
||||
// alphaMult should come out to be a value to satisfy (fontAlpha * alphaMult >> 8) as the right alpha,
|
||||
@ -964,10 +1006,23 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c )
|
||||
fullAlpha = fRenderInfo.fColor & 0xff000000;
|
||||
alphaMult = fullAlpha / 255;
|
||||
|
||||
for( y = 0; y < c.fHeight; y++ )
|
||||
y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline;
|
||||
if( y < 0 )
|
||||
y = 0;
|
||||
else
|
||||
{
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + y*fRenderInfo.fDestStride );
|
||||
src += y*fRenderInfo.fNumCols;
|
||||
}
|
||||
|
||||
thisHeight = fRenderInfo.fMaxHeight + (Int16)c.fBaseline;
|
||||
if( thisHeight > (Int16)c.fHeight )
|
||||
thisHeight = (Int16)c.fHeight;
|
||||
|
||||
for( ; y < thisHeight; y++ )
|
||||
{
|
||||
destPtr = destBasePtr;
|
||||
for( x = 0; x < thisWidth; x++ )
|
||||
for( x = xstart; x < thisWidth; x++ )
|
||||
{
|
||||
val = src[ x ];
|
||||
if( val == 0xff )
|
||||
@ -982,6 +1037,145 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c )
|
||||
}
|
||||
}
|
||||
|
||||
void plFont::IRenderChar8To32AlphaPremultiplied( const plFont::plCharacter &c )
|
||||
{
|
||||
UInt8 *src = fBMapData + c.fBitmapOff;
|
||||
UInt32 *destPtr, *destBasePtr = (UInt32 *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride );
|
||||
Int16 x, y, thisHeight, xstart, thisWidth;
|
||||
UInt8 srcA, srcR, srcG, srcB;
|
||||
|
||||
|
||||
// Unfortunately for some fonts, their right kern value actually is
|
||||
// farther left than the right edge of the bitmap (think of overlapping
|
||||
// script fonts). Ideally, we should store the actual width of each char's
|
||||
// bitmap and use that here. However, it really shouldn't make too big of a
|
||||
// difference, especially since the dest pixels that we end up overlapping
|
||||
// should already be in the cache. If it does, time to upgrade the font
|
||||
// format (again)
|
||||
thisWidth = (Int16)fWidth;// + (Int32)c.fRightKern;
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
thisWidth = fRenderInfo.fMaxWidth;
|
||||
|
||||
xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX;
|
||||
if( xstart < 0 )
|
||||
xstart = 0;
|
||||
|
||||
srcA = (UInt8)(( fRenderInfo.fColor >> 24 ) & 0x000000ff);
|
||||
srcR = (UInt8)(( fRenderInfo.fColor >> 16 ) & 0x000000ff);
|
||||
srcG = (UInt8)(( fRenderInfo.fColor >> 8 ) & 0x000000ff);
|
||||
srcB = (UInt8)(( fRenderInfo.fColor ) & 0x000000ff);
|
||||
|
||||
y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline;
|
||||
if( y < 0 )
|
||||
y = 0;
|
||||
else
|
||||
{
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + y*fRenderInfo.fDestStride );
|
||||
src += y*fRenderInfo.fNumCols;
|
||||
}
|
||||
|
||||
thisHeight = fRenderInfo.fMaxHeight + (Int16)c.fBaseline;
|
||||
if( thisHeight > (Int16)c.fHeight )
|
||||
thisHeight = (Int16)c.fHeight;
|
||||
|
||||
for( ; y < thisHeight; y++ )
|
||||
{
|
||||
destPtr = destBasePtr;
|
||||
for( x = xstart; x < thisWidth; x++ )
|
||||
{
|
||||
UInt32 a = src[ x ];
|
||||
if (a != 0)
|
||||
{
|
||||
if (srcA != 0xff)
|
||||
a = (srcA*a + 127)/255;
|
||||
destPtr[ x ] = ( a << 24 ) | (((srcR*a + 127)/255) << 16) | (((srcG*a + 127)/255) << 8) | ((srcB*a + 127)/255);
|
||||
}
|
||||
}
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + fRenderInfo.fDestStride );
|
||||
src += fWidth;
|
||||
}
|
||||
}
|
||||
|
||||
void plFont::IRenderChar8To32AlphaPremShadow( const plFont::plCharacter &c )
|
||||
{
|
||||
UInt32 *destPtr, *destBasePtr = (UInt32 *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride );
|
||||
Int16 x, y, thisHeight, xstart, thisWidth;
|
||||
UInt8 srcA, srcR, srcG, srcB;
|
||||
|
||||
|
||||
// Unfortunately for some fonts, their right kern value actually is
|
||||
// farther left than the right edge of the bitmap (think of overlapping
|
||||
// script fonts). Ideally, we should store the actual width of each char's
|
||||
// bitmap and use that here. However, it really shouldn't make too big of a
|
||||
// difference, especially since the dest pixels that we end up overlapping
|
||||
// should already be in the cache. If it does, time to upgrade the font
|
||||
// format (again)
|
||||
thisWidth = (Int16)fWidth + 2;// + (Int32)c.fRightKern;
|
||||
if( thisWidth >= fRenderInfo.fMaxWidth )
|
||||
thisWidth = fRenderInfo.fMaxWidth;
|
||||
|
||||
xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX;
|
||||
if( xstart < -2 )
|
||||
xstart = -2;
|
||||
|
||||
srcA = (UInt8)(( fRenderInfo.fColor >> 24 ) & 0x000000ff);
|
||||
if (srcA == 0)
|
||||
return;
|
||||
srcR = (UInt8)(( fRenderInfo.fColor >> 16 ) & 0x000000ff);
|
||||
srcG = (UInt8)(( fRenderInfo.fColor >> 8 ) & 0x000000ff);
|
||||
srcB = (UInt8)(( fRenderInfo.fColor ) & 0x000000ff);
|
||||
|
||||
static const UInt32 kernel[5][5] = {
|
||||
{1, 2, 2, 2, 1},
|
||||
{1, 13, 13, 13, 1},
|
||||
{1, 10, 10, 10, 1},
|
||||
{1, 7, 7, 7, 1},
|
||||
{1, 1, 1, 1, 1}
|
||||
};
|
||||
|
||||
UInt32 clamp = 220 - ((2 * srcR + 4 * srcG + srcB) >> 4);
|
||||
|
||||
y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline;
|
||||
if( y < -2 )
|
||||
y = -2;
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + y*fRenderInfo.fDestStride );
|
||||
|
||||
thisHeight = fRenderInfo.fMaxHeight + (Int16)c.fBaseline;
|
||||
if( thisHeight > (Int16)c.fHeight + 2 )
|
||||
thisHeight = (Int16)c.fHeight + 2;
|
||||
|
||||
for( ; y < thisHeight; y++ )
|
||||
{
|
||||
destPtr = destBasePtr;
|
||||
for( x = xstart; x < thisWidth; x++ )
|
||||
{
|
||||
UInt32 sa = 0;
|
||||
for (Int32 i = -2; i <= 2; i++) {
|
||||
for (Int32 j = -2; j <= 2; j++) {
|
||||
UInt32 m = kernel[j+2][i+2];
|
||||
if (m != 0)
|
||||
sa += m * IGetCharPixel(c, x+i, y+j);
|
||||
}
|
||||
}
|
||||
sa = (sa * clamp) >> 13;
|
||||
if (sa > clamp)
|
||||
sa = clamp;
|
||||
UInt32 a = IGetCharPixel(c, x, y);
|
||||
if (srcA != 0xff)
|
||||
{
|
||||
a = (srcA * a + 127) / 255;
|
||||
sa = (srcA * sa + 127) / 255;
|
||||
}
|
||||
UInt32 ta = a + sa - ((a*sa + 127) / 255);
|
||||
if (ta > (destPtr[ x ] >> 24))
|
||||
destPtr[ x ] = ( ta << 24 ) | (((srcR * a + 127) / 255) << 16) |
|
||||
(((srcG * a + 127) / 255) << 8) |
|
||||
(((srcB * a + 127) / 255) << 0);
|
||||
}
|
||||
destBasePtr = (UInt32 *)( (UInt8 *)destBasePtr + fRenderInfo.fDestStride );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plFont::IRenderCharNull( const plCharacter &c )
|
||||
{
|
||||
|
@ -116,6 +116,8 @@ class plFont : public hsKeyedObject
|
||||
// value between the renderColor and the destColor and
|
||||
// leave the alpha as-is
|
||||
// This flag has no effect on monochrome fonts
|
||||
kRenderAlphaPremultiplied = 0x00001000, // Destination has color values premultiplied by alpha
|
||||
kRenderShadow = 0x00002000, // Render text shadows
|
||||
};
|
||||
|
||||
enum Flags
|
||||
@ -231,8 +233,16 @@ class plFont : public hsKeyedObject
|
||||
void IRenderChar8To32( const plCharacter &c );
|
||||
void IRenderChar8To32Alpha( const plCharacter &c );
|
||||
void IRenderChar8To32FullAlpha( const plCharacter &c );
|
||||
void IRenderChar8To32AlphaPremultiplied( const plCharacter &c );
|
||||
void IRenderChar8To32AlphaPremShadow( const plCharacter &c );
|
||||
void IRenderCharNull( const plCharacter &c );
|
||||
|
||||
UInt32 IGetCharPixel( const plCharacter &c, Int32 x, Int32 y )
|
||||
{
|
||||
// only for 8-bit characters
|
||||
return (x < 0 || y < 0 || (UInt32)x >= fWidth || (UInt32)y >= c.fHeight) ? 0 : *(fBMapData + c.fBitmapOff + y*fWidth + x);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
plFont();
|
||||
|
@ -1745,6 +1745,18 @@ void plMipmap::Composite( plMipmap *source, UInt16 x, UInt16 y, plMipmap::Compos
|
||||
for( pY = (UInt16)srcHeight; pY > 0; pY-- )
|
||||
{
|
||||
memcpy( dstPtr, srcPtr, srcRowBytesToCopy );
|
||||
if( options->fFlags & kDestPremultiplied )
|
||||
{
|
||||
// multiply color values by alpha
|
||||
for( pX = 0; pX < srcWidth; pX++ )
|
||||
{
|
||||
srcAlpha = ((dstPtr[ pX ] >> 24) & 0x000000ff);
|
||||
dstPtr[ pX ] = ( srcAlpha << 24 )
|
||||
| (((((dstPtr[ pX ] >> 16) & 0xff)*srcAlpha + 127)/255) << 16)
|
||||
| (((((dstPtr[ pX ] >> 8) & 0xff)*srcAlpha + 127)/255) << 8)
|
||||
| (((((dstPtr[ pX ] ) & 0xff)*srcAlpha + 127)/255) );
|
||||
}
|
||||
}
|
||||
dstPtr += dstRowBytes >> 2;
|
||||
srcPtr += srcRowBytes >> 2;
|
||||
}
|
||||
@ -1776,7 +1788,15 @@ void plMipmap::Composite( plMipmap *source, UInt16 x, UInt16 y, plMipmap::Compos
|
||||
{
|
||||
srcAlpha = options->fOpacity * ( ( srcPtr[ pX ] >> 16 ) & 0x0000ff00 ) / 255 / 256;
|
||||
if( srcAlpha != 0 )
|
||||
dstPtr[ pX ] = ( srcPtr[ pX ] & 0x00ffffff ) | ( srcAlpha << 24 );
|
||||
{
|
||||
if( options->fFlags & kDestPremultiplied )
|
||||
dstPtr[ pX ] = ( srcAlpha << 24 )
|
||||
| (((((srcPtr[ pX ] >> 16) & 0xff)*srcAlpha + 127)/255) << 16)
|
||||
| (((((srcPtr[ pX ] >> 8) & 0xff)*srcAlpha + 127)/255) << 8)
|
||||
| (((((srcPtr[ pX ] ) & 0xff)*srcAlpha + 127)/255) );
|
||||
else
|
||||
dstPtr[ pX ] = ( srcPtr[ pX ] & 0x00ffffff ) | ( srcAlpha << 24 );
|
||||
}
|
||||
}
|
||||
dstPtr += dstRowBytes >> 2;
|
||||
srcPtr += srcRowBytes >> 2;
|
||||
|
@ -233,11 +233,14 @@ class plMipmap : public plBitmap
|
||||
|
||||
enum CompositeFlags
|
||||
{
|
||||
kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque
|
||||
kCopySrcAlpha = 0x0002, // Copy the src pixels raw, including alphas, overwrite dest
|
||||
kBlendSrcAlpha = 0x0004, // Blend src pixels onto dest using src alpha, dest alpha = src alpha
|
||||
kMaskSrcAlpha = 0x0008, // Same as copySrcAlpha, but dest is untouched when src alpha = 0
|
||||
kBlendWriteAlpha= 0x0010 // Like default (0), but writes dest alpha values
|
||||
kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque
|
||||
kCopySrcAlpha = 0x0002, // Copy the src pixels raw, including alphas, overwrite dest
|
||||
kBlendSrcAlpha = 0x0004, // Blend src pixels onto dest using src alpha, dest alpha = src alpha
|
||||
kMaskSrcAlpha = 0x0008, // Same as copySrcAlpha, but dest is untouched when src alpha = 0
|
||||
kBlendWriteAlpha = 0x0010, // Like default (0), but writes dest alpha values
|
||||
|
||||
kDestPremultiplied = 0x0020, // Dest has color premultiplied by alpha
|
||||
// (src always assumed nonpremultiplied for now)
|
||||
};
|
||||
|
||||
class CompositeOptions
|
||||
|
@ -51,15 +51,26 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
#include "../pnMessage/plMessage.h"
|
||||
|
||||
class plPipeline;
|
||||
|
||||
class plDeviceRecreateMsg : public plMessage
|
||||
{
|
||||
plPipeline* fPipe;
|
||||
|
||||
public:
|
||||
plDeviceRecreateMsg() : plMessage( nil, nil, nil ) { SetBCastFlag( kBCastByExactType ); }
|
||||
plDeviceRecreateMsg(plPipeline* pipe=nil)
|
||||
: plMessage(nil, nil, nil), fPipe(pipe)
|
||||
{
|
||||
SetBCastFlag(kBCastByExactType);
|
||||
}
|
||||
|
||||
~plDeviceRecreateMsg() {}
|
||||
|
||||
CLASSNAME_REGISTER( plDeviceRecreateMsg );
|
||||
GETINTERFACE_ANY( plDeviceRecreateMsg, plMessage );
|
||||
|
||||
plPipeline* Pipeline() const { return fPipe; }
|
||||
|
||||
// IO
|
||||
void Read(hsStream* stream, hsResMgr* mgr) { plMessage::IMsgRead( stream, mgr ); }
|
||||
void Write(hsStream* stream, hsResMgr* mgr) { plMessage::IMsgWrite( stream, mgr ); }
|
||||
|
@ -2278,7 +2278,7 @@ hsBool plDXPipeline::IResetDevice()
|
||||
|
||||
/// Broadcast a message letting everyone know that we were recreated and that
|
||||
/// all device-specific stuff needs to be recreated
|
||||
plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg();
|
||||
plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg(this);
|
||||
plgDispatch::MsgSend(clean);
|
||||
}
|
||||
fDevWasLost = true;
|
||||
@ -2552,7 +2552,7 @@ void plDXPipeline::Resize( UInt32 width, UInt32 height )
|
||||
|
||||
/// Broadcast a message letting everyone know that we were recreated and that
|
||||
/// all device-specific stuff needs to be recreated
|
||||
plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg();
|
||||
plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg(this);
|
||||
plgDispatch::MsgSend(clean);
|
||||
}
|
||||
|
||||
@ -3834,7 +3834,7 @@ hsBool plDXPipeline::BeginRender()
|
||||
{
|
||||
/// Broadcast a message letting everyone know that we were recreated and that
|
||||
/// all device-specific stuff needs to be recreated
|
||||
// plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg();
|
||||
// plDeviceRecreateMsg* clean = TRACKED_NEW plDeviceRecreateMsg(this);
|
||||
// plgDispatch::MsgSend(clean);
|
||||
|
||||
fDevWasLost = false;
|
||||
@ -7229,12 +7229,26 @@ void plDXPipeline::IHandleFirstStageBlend()
|
||||
fD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
||||
if( fLayerState[0].fBlendFlags & hsGMatState::kBlendInvertFinalAlpha )
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA );
|
||||
if( fLayerState[0].fBlendFlags & hsGMatState::kBlendAlphaPremultiplied )
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA );
|
||||
}
|
||||
fD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
|
||||
}
|
||||
else
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
||||
if( fLayerState[0].fBlendFlags & hsGMatState::kBlendAlphaPremultiplied )
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
fD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
||||
}
|
||||
fD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
}
|
||||
break;
|
||||
|
Reference in New Issue
Block a user