2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-15 10:54:18 +00:00

Compare commits

..

14 Commits

Author SHA1 Message Date
21e2a6de7b Fix MSVC7 warnings. 2014-08-23 21:10:55 +02:00
9c609b9fd8 Modulate text shadow opacity by the alpha of the text color to make the player lists fade properly.
Also, the text of the faded-out player list is re-rendered with alpha == 0 every time the mouse enters its area, do a little less needless work in that case.
2014-06-07 18:22:41 +02:00
d1c86267b3 Const getters 2014-04-25 12:17:47 +02:00
6b2dedf547 Make font flags available to Python in PlasmaConstants. 2014-04-12 10:22:07 +02:00
192e4a252c Fix comment Hoikas 2014-04-25 11:57:33 +02:00
c0b63e4237 Fix ptGUIControl.setFontFlags().
Previous revision didn't work, many controls retained their shadows because they never got the new flags from the color scheme and put them into the dynamic text map. I haven't checked if any more of the many control classes are affected, but those that we need in the KI right now are covered.
2014-04-10 22:59:37 +02:00
020f8a1ba0 Move methods to pyGUIControl to pyGUIControlTextBox. 2014-04-09 11:21:28 +02:00
39ff487ca8 add python api to set flags
Clean up unwanted changes caused by IDE extension -.-

Reworked implementation
2014-04-01 16:38:12 +02:00
a0bbef1819 Undo the kRenderJustXForceLeft bugfix of 4 commits back.
The fix (adding adjustment of fRenderInfo.fDestPtr) made kRenderJustXForceLeft behave as intended (left-aligning the edge of the bitmap rather than the side bearing of the first character) but cuts off shadows in some places (e.g. at the left edges of "BUDDIES" and "NEIGHBORS" in the mini KI). 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.
2014-04-06 17:19:42 +02:00
3825317e5e Link shadowed text rendering to the plDynamicTextMap::kFontShadowed flag.
Conveniently enough, this existing but unimplemented flag is already set mostly the way we want it in the current PRPs.
2013-07-04 20:13:03 -04:00
b343e389ab Implement shadowed text rendering.
Intended to make KI text (player list and chat) better readable on light and patterned backgrounds. In this WIP, all text on GUI controls is rendered shadowed.
2012-01-25 22:16:19 +01:00
e02141055a Use premultiplied alpha for plDynamicTextMaps on GUI controls.
This fixes the irregular dark fringes around light text when not exactly pixel-aligned that are caused by independent interpolation of color and alpha. It also makes calculations simpler for things to come.
2011-12-30 15:10:47 +01:00
1f0277e3e0 Pixel-accurately clip characters to the available space instead of omitting whole characters that stick out.
In addition to being a prerequisite for shadowed text, this also fixes an issue sometimes seen at the bottom of the mini KI player list where characters with a descender were missing.
2014-04-03 22:17:45 +02:00
db5e451622 Fix #303 2013-07-04 18:14:58 -04:00
26 changed files with 473 additions and 241 deletions

View File

@ -114,7 +114,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plStatusLog/plStatusLog.h"
#include "../plProgressMgr/plProgressMgr.h"
#include "../plPipeline/plDTProgressMgr.h"
#ifdef USE_BINK_SDK
#include "../plPipeline/plBinkPlayer.h"
#endif
#include "../plMessage/plMovieMsg.h"
#include "../plSDL/plSDL.h"
@ -269,8 +271,10 @@ hsBool plClient::Shutdown()
// Let the resmanager know we're going to be shutting down.
hsgResMgr::ResMgr()->BeginShutdown();
#ifdef USE_BINK_SDK
// Must kill off all movies before shutting down audio.
IKillMovies();
#endif
plgAudioSys::Activate(false);
#ifdef USE_BINK_SDK
@ -818,11 +822,13 @@ hsBool plClient::MsgReceive(plMessage* msg)
}
return true;
}
#ifdef USE_BINK_SDK
plMovieMsg* mov = plMovieMsg::ConvertNoRef(msg);
if( mov )
{
return IHandleMovieMsg(mov);
}
#endif // USE_BINK_SDK
plLinkEffectsTriggerMsg* linkFX = plLinkEffectsTriggerMsg::ConvertNoRef(msg);
if (linkFX)
@ -869,6 +875,7 @@ hsBool plClient::MsgReceive(plMessage* msg)
return hsKeyedObject::MsgReceive(msg);
}
#ifdef USE_BINK_SDK
//============================================================================
hsBool plClient::IHandleMovieMsg(plMovieMsg* mov)
{
@ -949,6 +956,7 @@ hsBool plClient::IHandleMovieMsg(plMovieMsg* mov)
return true;
}
#endif // USE_BINK_SDK
int plClient::IFindRoomByLoc(const plLocation& loc)
{
@ -1521,8 +1529,8 @@ hsBool plClient::StartInit()
//if( GetDone() ) return false;
IPlayIntroBink("avi/intro1.bik", 0.f, 0.f, 0.f, 1.f, 1.f, 0.75);
if( GetDone() ) return false;
#endif // USE_BINK_SDK
plgDispatch::Dispatch()->RegisterForExactType(plMovieMsg::Index(), GetKey());
#endif // USE_BINK_SDK
//
// Init Net before loading things
@ -1928,9 +1936,11 @@ hsBool plClient::IDraw()
IProcessPostRenderRequests();
plProfile_EndTiming(PostRender);
#ifdef USE_BINK_SDK
plProfile_BeginTiming(Movies);
IServiceMovies();
plProfile_EndTiming(Movies);
#endif // USE_BINK_SDK
#ifndef PLASMA_EXTERNAL_RELEASE
plProfile_BeginTiming(Console);
@ -1961,6 +1971,7 @@ hsBool plClient::IDraw()
return false;
}
#ifdef USE_BINK_SDK
void plClient::IServiceMovies()
{
int i;
@ -1975,7 +1986,9 @@ void plClient::IServiceMovies()
}
}
}
#endif // USE_BINK_SDK
#ifdef USE_BINK_SDK
void plClient::IKillMovies()
{
int i;
@ -1983,6 +1996,7 @@ void plClient::IKillMovies()
delete fMovies[i];
fMovies.Reset();
}
#endif // USE_BINK_SDK
#ifdef USE_BINK_SDK
hsBool plClient::IPlayIntroBink(const char* movieName, hsScalar endDelay, hsScalar posX, hsScalar posY, hsScalar scaleX, hsScalar scaleY, hsScalar volume /* = 1.0 */)

View File

@ -78,7 +78,9 @@ class plFontCache;
class plClientMsg;
class plLocation;
class plMovieMsg;
#ifdef USE_BINK_SDK
class plBinkPlayer;
#endif
class plPreloaderMsg;
class plNetCommAuthMsg;
class plAgeLoaded2Msg;
@ -150,7 +152,9 @@ protected:
int fQuality;
hsBool fQuitIntro;
#ifdef USE_BINK_SDK
hsTArray<plBinkPlayer*> fMovies;
#endif
hsBool fPatchGlobalAges;
@ -193,10 +197,10 @@ protected:
#ifdef USE_BINK_SDK
hsBool IPlayIntroBink(const char* movieName, hsScalar endDelay, hsScalar posX, hsScalar posY, hsScalar scaleX, hsScalar scaleY, hsScalar volume = 1.0);
#endif // USE_BINK_SDK
hsBool IHandleMovieMsg(plMovieMsg* mov);
void IKillMovies();
void IServiceMovies();
#endif // USE_BINK_SDK
void IStartProgress( const char *title, hsScalar len );
void IIncProgress( hsScalar byHowMuch, const char *text );

View File

@ -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;

View File

@ -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();

View File

@ -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() {;}

View File

@ -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 )
{

View File

@ -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;

View File

@ -216,6 +216,8 @@ class pfGUIMultiLineEditCtrl : public pfGUIControlMod
virtual void PurgeDynaTextMapImage();
virtual void UpdateColorScheme() { fFontFlagsSet = 0; pfGUIControlMod::UpdateColorScheme(); }
// Extended event types
enum ExtendedEvents
{

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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

View File

@ -214,3 +214,4 @@ UInt8 pyGUIControlTextBox::GetJustify()
}
return pfGUIListText::kLeftJustify;
}

View File

@ -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
};

View File

@ -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());

View File

@ -85,7 +85,8 @@ enum hsGMatBlendFlags {
kBlendEnvBumpNext = 0x800000,
kBlendSubtract = 0x1000000,
kBlendRevSubtract = 0x2000000,
kBlendAlphaTestHigh = 0x4000000
kBlendAlphaTestHigh = 0x4000000,
kBlendAlphaPremultiplied = 0x8000000
};
enum hsGMatClampFlags {

View File

@ -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 );

View File

@ -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;

View File

@ -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 )
{

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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 ); }

View File

@ -1,132 +0,0 @@
/*==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==*/
#ifndef plBinkPlayer_inc
#define plBinkPlayer_inc
#include "HeadSpin.h"
#include "hsPoint2.h"
#include "hsTemplates.h"
struct D3DVertex;
class plDXPipeline;
struct IDirect3DTexture9;
class plMessage;
struct IDirectSound8;
class plBinkPlayer
{
public:
plBinkPlayer() : fFileName(nil) { }
~plBinkPlayer() { delete [] fFileName; }
static bool Init( hsWindowHndl hWnd) { return true; }
static bool DeInit() { return true; }
static void SetForeGroundTrack(UInt32 t) { }
static void SetBackGroundTrack(UInt32 t) { }
static UInt32 GetForeGroundTrack() { }
static UInt32 GetBackGroundTrack() { }
void SetDefaults() { }
bool Start(plPipeline* pipe, hsWindowHndl hWnd) { return false; }
bool NextFrame() {
// we have reached the end
return Stop();
}
bool Pause(bool on) { return false; }
bool Stop() {
for (int i = 0; i < fCallbacks.GetCount(); i++)
fCallbacks[i]->Send();
fCallbacks.Reset();
delete [] fFileName;
fFileName = nil;
return false;
}
void SetFileName(const char* filename) {
delete [] fFileName;
fFileName = hsStrcpy(filename);
}
void SetColor(const hsColorRGBA& c) { }
void SetPosition(float x, float y) { }
void SetScale(float x, float y) { }
void SetVolume(float v) { }
void SetForeVolume(float v) { }
void SetBackVolume(float v) { }
void SetPosition(const hsPoint2& p) { }
void SetScale(const hsPoint2& s) { }
const char* GetFileName() const { return fFileName; }
const hsColorRGBA GetColor() const { return hsColorRGBA(); }
const hsPoint2 GetPosition() const { return hsPoint2(); }
const hsPoint2 GetScale() const { return hsPoint2(); }
float GetBackVolume() const { return 0.0f; }
float GetForeVolume() const { return 0.0f; }
void AddCallback(plMessage* msg) { hsRefCnt_SafeRef(msg); fCallbacks.Append(msg); }
UInt32 GetNumCallbacks() const { return 0; }
plMessage* GetCallback(int i) const { return nil; }
void SetFadeFromTime(float secs) { }
void SetFadeFromColor(hsColorRGBA c) { }
void SetFadeToTime(float secs) { }
void SetFadeToColor(hsColorRGBA c) { }
float GetFadeFromTime() const { return 0.0f; }
hsColorRGBA GetFadeFromColor() const { return hsColorRGBA(); }
float GetFadeToTime() const { return 0.0f; }
hsColorRGBA GetFadeToColor() const { return hsColorRGBA(); }
private:
char* fFileName;
hsTArray<plMessage*> fCallbacks;
};
#endif // plBinkPlayer_inc

View File

@ -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;