From 4cd2b2f7dd608637dc84091f3c54c2c6b0211cad Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 4 Jul 2013 18:14:58 -0400 Subject: [PATCH 01/12] Fix #303 --- .../pfGameGUIMgr/pfGUIControlMod.cpp | 23 ++++++++++++------- .../plMessage/plDeviceRecreateMsg.h | 13 ++++++++++- .../PubUtilLib/plPipeline/DX/plDXPipeline.cpp | 6 ++--- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp index 865bf184..0ca70560 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp @@ -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" @@ -572,14 +573,16 @@ plProfile_CreateTimer("Gui", "RenderSetup", GUITime); bool 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().c_str()); - // Only need it once - if( ISetUpDynTextMap( rend->Pipeline() ) ) - plgDispatch::Dispatch()->UnRegisterForExactType( plRenderMsg::Index(), GetKey() ); + ISetUpDynTextMap(pipe); plProfile_EndLap(GUITime, this->GetKey()->GetUoid().GetObjectName().c_str()); + + if (rend) + plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey()); return true; } @@ -591,12 +594,16 @@ bool 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; + { + fDynTextMap = nullptr; + plgDispatch::Dispatch()->UnRegisterForExactType( plDeviceRecreateMsg::Index(), GetKey() ); + } return true; } else if( refMsg->fType == kRefDynTextLayer ) diff --git a/Sources/Plasma/PubUtilLib/plMessage/plDeviceRecreateMsg.h b/Sources/Plasma/PubUtilLib/plMessage/plDeviceRecreateMsg.h index 1f11b8c6..6b7316bb 100644 --- a/Sources/Plasma/PubUtilLib/plMessage/plDeviceRecreateMsg.h +++ b/Sources/Plasma/PubUtilLib/plMessage/plDeviceRecreateMsg.h @@ -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=nullptr) + : plMessage(nullptr, nullptr, nullptr), 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 ); } diff --git a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp index 31de130a..b116d1ef 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp @@ -2264,7 +2264,7 @@ bool plDXPipeline::IResetDevice() /// Broadcast a message letting everyone know that we were recreated and that /// all device-specific stuff needs to be recreated - plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(); + plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(this); plgDispatch::MsgSend(clean); } fDevWasLost = true; @@ -2533,7 +2533,7 @@ void plDXPipeline::Resize( uint32_t width, uint32_t height ) /// Broadcast a message letting everyone know that we were recreated and that /// all device-specific stuff needs to be recreated - plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(); + plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(this); plgDispatch::MsgSend(clean); } @@ -3815,7 +3815,7 @@ bool plDXPipeline::BeginRender() { /// Broadcast a message letting everyone know that we were recreated and that /// all device-specific stuff needs to be recreated -// plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(); +// plDeviceRecreateMsg* clean = new plDeviceRecreateMsg(this); // plgDispatch::MsgSend(clean); fDevWasLost = false; From b34577103eedf5281d81a3d934d1dd826f95ccea Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Thu, 3 Apr 2014 22:17:45 +0200 Subject: [PATCH 02/12] 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. --- .../pfGameGUIMgr/pfGUIEditBoxMod.cpp | 4 +- .../PubUtilLib/plGImage/plDynamicTextMap.cpp | 1 + Sources/Plasma/PubUtilLib/plGImage/plFont.cpp | 104 +++++++++++++----- 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp index 6728b07a..d71843db 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIEditBoxMod.cpp @@ -138,9 +138,9 @@ void pfGUIEditBoxMod::IUpdate( void ) oldCursorPos = cursorPos; cursorPos -= (int16_t)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 ) { diff --git a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp index 96be7b57..c8424b60 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp @@ -497,6 +497,7 @@ void plDynamicTextMap::DrawString( uint16_t x, uint16_t y, const wchar_t *tex SetJustify( fJustify ); fCurrFont->SetRenderFlag( plFont::kRenderWrap | plFont::kRenderClip, false ); + fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight ); fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); fCurrFont->RenderString( this, x, y, text ); diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index 219a7da1..027de1c9 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -648,11 +648,16 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha // Advance left past any clipping area CharRenderFunc oldFunc = fRenderInfo.fRenderFunc; fRenderInfo.fRenderFunc = &plFont::IRenderCharNull; - while( fRenderInfo.fX < fRenderInfo.fClipRect.fX && *string != 0 ) + int16_t 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; } @@ -661,10 +666,10 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha { // See note at top of file plCharacter &ch = fCharacters[ (uint16_t)string[ 0 ] - fFirstChar ]; - int32_t newX = x - (int16_t)ch.fLeftKern; - if( newX < 0 ) - newX = 0; - fRenderInfo.fX = fRenderInfo.fFarthestX = (int16_t)newX; + fRenderInfo.fX -= (int16_t)ch.fLeftKern; + fRenderInfo.fMaxWidth += (int16_t)ch.fLeftKern; + fRenderInfo.fDestPtr -= (int16_t)ch.fLeftKern * fRenderInfo.fDestBPP; + fRenderInfo.fFarthestX = fRenderInfo.fX; } fRenderInfo.fVolatileStringPtr = string; // Just so we can keep track of when we clip @@ -704,9 +709,6 @@ void plFont::IRenderLoop( const wchar_t *string, int32_t maxCount ) if( fRenderInfo.fFlags & kRenderScaleAA ) thisWidth >>= 1; - if( thisWidth >= fRenderInfo.fMaxWidth ) - break; - (this->*(fRenderInfo.fRenderFunc))( fCharacters[ c ] ); fRenderInfo.fX += thisWidth; @@ -837,8 +839,8 @@ void plFont::IRenderChar8To32( const plFont::plCharacter &c ) { uint8_t *src = fBMapData + c.fBitmapOff; uint32_t *destPtr, *destBasePtr = (uint32_t *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride ); - uint16_t x, y; - uint32_t srcAlpha, oneMinusAlpha, r, g, b, dR, dG, dB, destAlpha, thisWidth; + int16_t x, y, thisHeight, xstart, thisWidth; + uint32_t srcAlpha, oneMinusAlpha, r, g, b, dR, dG, dB, destAlpha; uint8_t srcR, srcG, srcB; @@ -850,18 +852,34 @@ void plFont::IRenderChar8To32( const plFont::plCharacter &c ) // should already be in the cache. If it does, time to upgrade the font // format (again) thisWidth = fWidth;// + (int32_t)c.fRightKern; + if( thisWidth >= fRenderInfo.fMaxWidth ) + thisWidth = fRenderInfo.fMaxWidth; - if( (int32_t)c.fHeight - (int32_t)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_t)(( fRenderInfo.fColor >> 16 ) & 0x000000ff); srcG = (uint8_t)(( fRenderInfo.fColor >> 8 ) & 0x000000ff); srcB = (uint8_t)(( fRenderInfo.fColor ) & 0x000000ff); - for( y = 0; y < c.fHeight; y++ ) + y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (int16_t)c.fBaseline; + if( y < 0 ) + y = 0; + else + { + destBasePtr = (uint32_t *)( (uint8_t *)destBasePtr + y*fRenderInfo.fDestStride ); + src += y*fRenderInfo.fNumCols; + } + + thisHeight = fRenderInfo.fMaxHeight + (int16_t)c.fBaseline; + if( thisHeight > (int16_t)c.fHeight ) + thisHeight = (int16_t)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; @@ -896,8 +914,8 @@ void plFont::IRenderChar8To32FullAlpha( const plFont::plCharacter &c ) { uint8_t *src = fBMapData + c.fBitmapOff; uint32_t *destPtr, *destBasePtr = (uint32_t *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride ); - uint16_t x, y; - uint32_t destColorOnly, thisWidth; + int16_t x, y, thisHeight, xstart, thisWidth; + uint32_t destColorOnly; // Unfortunately for some fonts, their right kern value actually is @@ -908,16 +926,32 @@ void plFont::IRenderChar8To32FullAlpha( const plFont::plCharacter &c ) // should already be in the cache. If it does, time to upgrade the font // format (again) thisWidth = fWidth;// + (int32_t)c.fRightKern; + if( thisWidth >= fRenderInfo.fMaxWidth ) + thisWidth = fRenderInfo.fMaxWidth; - if( (int32_t)c.fHeight - (int32_t)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_t)c.fBaseline; + if( y < 0 ) + y = 0; + else + { + destBasePtr = (uint32_t *)( (uint8_t *)destBasePtr + y*fRenderInfo.fDestStride ); + src += y*fRenderInfo.fNumCols; + } + + thisHeight = fRenderInfo.fMaxHeight + (int16_t)c.fBaseline; + if( thisHeight > (int16_t)c.fHeight ) + thisHeight = (int16_t)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; @@ -931,8 +965,8 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c ) { uint8_t val, *src = fBMapData + c.fBitmapOff; uint32_t *destPtr, *destBasePtr = (uint32_t *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride ); - uint16_t x, y; - uint32_t destColorOnly, alphaMult, fullAlpha, thisWidth; + int16_t x, y, thisHeight, xstart, thisWidth; + uint32_t destColorOnly, alphaMult, fullAlpha; // Unfortunately for some fonts, their right kern value actually is @@ -943,9 +977,12 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c ) // should already be in the cache. If it does, time to upgrade the font // format (again) thisWidth = fWidth;// + (int32_t)c.fRightKern; + if( thisWidth >= fRenderInfo.fMaxWidth ) + thisWidth = fRenderInfo.fMaxWidth; - if( (int32_t)c.fHeight - (int32_t)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, @@ -953,10 +990,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_t)c.fBaseline; + if( y < 0 ) + y = 0; + else + { + destBasePtr = (uint32_t *)( (uint8_t *)destBasePtr + y*fRenderInfo.fDestStride ); + src += y*fRenderInfo.fNumCols; + } + + thisHeight = fRenderInfo.fMaxHeight + (int16_t)c.fBaseline; + if( thisHeight > (int16_t)c.fHeight ) + thisHeight = (int16_t)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 ) From 8c5286400a6110866dca3b32947401aca50e404b Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Fri, 30 Dec 2011 15:10:47 +0100 Subject: [PATCH 03/12] 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. --- Sources/Plasma/CoreLib/hsColorRGBA.h | 9 +++ .../pfGameGUIMgr/pfGUIControlMod.cpp | 3 +- Sources/Plasma/NucleusLib/inc/hsGMatState.h | 3 +- .../PubUtilLib/plGImage/plDynamicTextMap.cpp | 26 +++++--- .../PubUtilLib/plGImage/plDynamicTextMap.h | 6 +- Sources/Plasma/PubUtilLib/plGImage/plFont.cpp | 63 ++++++++++++++++++- Sources/Plasma/PubUtilLib/plGImage/plFont.h | 2 + .../Plasma/PubUtilLib/plGImage/plMipmap.cpp | 22 ++++++- Sources/Plasma/PubUtilLib/plGImage/plMipmap.h | 13 ++-- .../PubUtilLib/plPipeline/DX/plDXPipeline.cpp | 18 +++++- 10 files changed, 144 insertions(+), 21 deletions(-) diff --git a/Sources/Plasma/CoreLib/hsColorRGBA.h b/Sources/Plasma/CoreLib/hsColorRGBA.h index 21010db3..398acaf2 100644 --- a/Sources/Plasma/CoreLib/hsColorRGBA.h +++ b/Sources/Plasma/CoreLib/hsColorRGBA.h @@ -103,6 +103,7 @@ struct hsColorRGBA { hsColorRGBA& FromARGB32(uint32_t c); uint32_t ToARGB32() const; + uint32_t ToARGB32Premultiplied() const; void Read(hsStream *stream); void Write(hsStream *stream) const; @@ -141,6 +142,14 @@ inline uint32_t hsColorRGBA::ToARGB32() const | (uint32_t(b * 255.99f) << 0); } +inline uint32_t hsColorRGBA::ToARGB32Premultiplied() const +{ + return (uint32_t(a * 255.0f + 0.5f) << 24) + | (uint32_t(a * r * 255.0f + 0.5f) << 16) + | (uint32_t(a * g * 255.0f + 0.5f) << 8) + | (uint32_t(a * b * 255.0f + 0.5f) << 0); +} + inline hsColorRGBA operator+(const hsColorRGBA& s, const hsColorRGBA& t) { hsColorRGBA res; diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp index 0ca70560..75ee85d7 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.cpp @@ -683,7 +683,7 @@ bool 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 ); @@ -694,6 +694,7 @@ bool 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(); diff --git a/Sources/Plasma/NucleusLib/inc/hsGMatState.h b/Sources/Plasma/NucleusLib/inc/hsGMatState.h index d8a08c9c..aa6f1eb6 100644 --- a/Sources/Plasma/NucleusLib/inc/hsGMatState.h +++ b/Sources/Plasma/NucleusLib/inc/hsGMatState.h @@ -85,7 +85,8 @@ enum hsGMatBlendFlags { kBlendEnvBumpNext = 0x800000, kBlendSubtract = 0x1000000, kBlendRevSubtract = 0x2000000, - kBlendAlphaTestHigh = 0x4000000 + kBlendAlphaTestHigh = 0x4000000, + kBlendAlphaPremultiplied = 0x8000000 }; enum hsGMatClampFlags { diff --git a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp index c8424b60..ad869803 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp @@ -76,7 +76,7 @@ plProfile_Extern(MemMipmaps); //// Constructor & Destructor ///////////////////////////////////////////////// plDynamicTextMap::plDynamicTextMap() - : fVisWidth(0), fVisHeight(0), fHasAlpha(false), fJustify(kLeftJustify), + : fVisWidth(0), fVisHeight(0), fHasAlpha(false), fPremultipliedAlpha(false), fJustify(kLeftJustify), fInitBuffer(nullptr), fFontSize(0), fFontFlags(0), fFontAntiAliasRGB(false), fFontBlockRGB(false), fHasCreateBeenCalled(false) { @@ -88,10 +88,10 @@ plDynamicTextMap::~plDynamicTextMap() Reset(); } -plDynamicTextMap::plDynamicTextMap( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth, uint32_t extraHeight ) +plDynamicTextMap::plDynamicTextMap( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth, uint32_t extraHeight, bool premultipliedAlpha ) : fInitBuffer(nullptr) { - Create( width, height, hasAlpha, extraWidth, extraHeight ); + Create( width, height, hasAlpha, extraWidth, extraHeight, premultipliedAlpha ); } //// SetNoCreate ////////////////////////////////////////////////////////////// @@ -113,7 +113,7 @@ void plDynamicTextMap::SetNoCreate( uint32_t width, uint32_t height, bool has //// Create /////////////////////////////////////////////////////////////////// -void plDynamicTextMap::Create( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth, uint32_t extraHeight ) +void plDynamicTextMap::Create( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth, uint32_t extraHeight, bool premultipliedAlpha ) { SetConfig( hasAlpha ? kARGB32Config : kRGB32Config ); @@ -121,6 +121,7 @@ void plDynamicTextMap::Create( uint32_t width, uint32_t height, bool hasAlpha fVisWidth = (uint16_t)width; fVisHeight = (uint16_t)height; fHasAlpha = hasAlpha; + fPremultipliedAlpha = premultipliedAlpha; for( fWidth = 1; fWidth < width + extraWidth; fWidth <<= 1 ); for( fHeight = 1; fHeight < height + extraHeight; fHeight <<= 1 ); @@ -385,7 +386,7 @@ void plDynamicTextMap::ClearToColor( hsColorRGBA &color ) if( !IIsValid() ) return; - uint32_t i, hex = color.ToARGB32(); + uint32_t i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32(); uint32_t *data = (uint32_t *)fImage; // Buffer is of size fVisWidth x fVisHeight, so we need a bit of work to do this right @@ -500,6 +501,7 @@ void plDynamicTextMap::DrawString( uint16_t x, uint16_t y, const wchar_t *tex fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight ); fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); + fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -520,6 +522,7 @@ void plDynamicTextMap::DrawClippedString( int16_t x, int16_t y, const wchar_t fCurrFont->SetRenderClipping( x, y, width, height ); fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); + fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -539,6 +542,7 @@ void plDynamicTextMap::DrawClippedString( int16_t x, int16_t y, const wchar_t SetJustify( fJustify ); fCurrFont->SetRenderClipping( clipX, clipY, width, height ); fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); + fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -559,6 +563,7 @@ void plDynamicTextMap::DrawWrappedString( uint16_t x, uint16_t y, const wchar fCurrFont->SetRenderWrapping( x, y, width, height ); fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); + fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text, lastX, lastY ); } @@ -639,7 +644,7 @@ void plDynamicTextMap::FillRect( uint16_t x, uint16_t y, uint16_t width, uint width = (uint16_t)(fWidth - x); // Gee, how hard can it REALLY be? - uint32_t i, hex = color.ToARGB32(); + uint32_t i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32(); height += y; if( height > fHeight ) height = (uint16_t)fHeight; @@ -664,7 +669,7 @@ void plDynamicTextMap::FrameRect( uint16_t x, uint16_t y, uint16_t width, uin height = (uint16_t)(fHeight - y); // Shouldn't be much harder - uint32_t i, hex = color.ToARGB32(); + uint32_t i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32(); uint32_t *dest1, *dest2; dest1 = GetAddr32( x, y ); @@ -699,6 +704,9 @@ void plDynamicTextMap::DrawImage( uint16_t x, uint16_t y, plMipmap *image, Dr 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 @@ -737,6 +745,9 @@ void plDynamicTextMap::DrawClippedImage( uint16_t x, uint16_t y, plMipmap *im else if( method == kImgSprite ) opts.fFlags = plMipmap::kCopySrcAlpha; + if( fPremultipliedAlpha ) + opts.fFlags |= plMipmap::kDestPremultiplied; + opts.fSrcClipX = srcClipX; opts.fSrcClipY = srcClipY; opts.fSrcClipWidth = srcClipWidth; @@ -883,6 +894,7 @@ void plDynamicTextMap::Swap( plDynamicTextMap *other ) // Swap DTMap info SWAP_ME( bool, fHasAlpha, other->fHasAlpha ); + SWAP_ME( bool, fPremultipliedAlpha, other->fPremultipliedAlpha ); SWAP_ME( bool, fShadowed, other->fShadowed ); SWAP_ME( Justify, fJustify, other->fJustify ); diff --git a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h index eddf8c11..318238b8 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h @@ -113,14 +113,14 @@ class plDynamicTextMap : public plMipmap plDynamicTextMap(); - plDynamicTextMap( uint32_t width, uint32_t height, bool hasAlpha = false, uint32_t extraWidth = 0, uint32_t extraHeight = 0 ); + plDynamicTextMap( uint32_t width, uint32_t height, bool hasAlpha = false, uint32_t extraWidth = 0, uint32_t extraHeight = 0, bool premultipliedAlpha = false ); virtual ~plDynamicTextMap(); CLASSNAME_REGISTER( plDynamicTextMap ); GETINTERFACE_ANY( plDynamicTextMap, plMipmap ); - void Create( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth = 0, uint32_t extraHeight = 0 ); + void Create( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth = 0, uint32_t extraHeight = 0, bool premultipliedAlpha = false ); void SetNoCreate( uint32_t width, uint32_t height, bool hasAlpha ); virtual void Reset( void ); @@ -221,7 +221,7 @@ class plDynamicTextMap : public plMipmap uint32_t *IAllocateOSSurface( uint16_t width, uint16_t height ); void IDestroyOSSurface( void ); - bool fHasAlpha, fShadowed; + bool fHasAlpha, fPremultipliedAlpha, fShadowed; Justify fJustify; plString fFontFace; diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index 027de1c9..764c77f1 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -334,7 +334,9 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha { if( fRenderInfo.fFlags & kRenderIntoAlpha ) { - if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 ) + if( fRenderInfo.fFlags & kRenderAlphaPremultiplied ) + fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremultiplied; + else if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 ) fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32Alpha; else fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32FullAlpha; @@ -1021,6 +1023,65 @@ void plFont::IRenderChar8To32Alpha( const plFont::plCharacter &c ) } } +void plFont::IRenderChar8To32AlphaPremultiplied( const plFont::plCharacter &c ) +{ + uint8_t *src = fBMapData + c.fBitmapOff; + uint32_t *destPtr, *destBasePtr = (uint32_t *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride ); + int16_t x, y, thisHeight, xstart, thisWidth; + uint8_t 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 = fWidth;// + (int32_t)c.fRightKern; + if( thisWidth >= fRenderInfo.fMaxWidth ) + thisWidth = fRenderInfo.fMaxWidth; + + xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX; + if( xstart < 0 ) + xstart = 0; + + srcA = (uint8_t)(( fRenderInfo.fColor >> 24 ) & 0x000000ff); + srcR = (uint8_t)(( fRenderInfo.fColor >> 16 ) & 0x000000ff); + srcG = (uint8_t)(( fRenderInfo.fColor >> 8 ) & 0x000000ff); + srcB = (uint8_t)(( fRenderInfo.fColor ) & 0x000000ff); + + y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (int16_t)c.fBaseline; + if( y < 0 ) + y = 0; + else + { + destBasePtr = (uint32_t *)( (uint8_t *)destBasePtr + y*fRenderInfo.fDestStride ); + src += y*fRenderInfo.fNumCols; + } + + thisHeight = fRenderInfo.fMaxHeight + (int16_t)c.fBaseline; + if( thisHeight > (int16_t)c.fHeight ) + thisHeight = (int16_t)c.fHeight; + + for( ; y < thisHeight; y++ ) + { + destPtr = destBasePtr; + for( x = xstart; x < thisWidth; x++ ) + { + uint32_t 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_t *)( (uint8_t *)destBasePtr + fRenderInfo.fDestStride ); + src += fWidth; + } +} + void plFont::IRenderCharNull( const plCharacter &c ) { diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.h b/Sources/Plasma/PubUtilLib/plGImage/plFont.h index 7c971325..20dae743 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.h @@ -116,6 +116,7 @@ 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 }; enum Flags @@ -231,6 +232,7 @@ 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 IRenderCharNull( const plCharacter &c ); public: diff --git a/Sources/Plasma/PubUtilLib/plGImage/plMipmap.cpp b/Sources/Plasma/PubUtilLib/plGImage/plMipmap.cpp index 3a868836..9ec4a70a 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plMipmap.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plMipmap.cpp @@ -1746,6 +1746,18 @@ void plMipmap::Composite( plMipmap *source, uint16_t x, uint16_t y, plMipmap: for( pY = (uint16_t)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; } @@ -1777,7 +1789,15 @@ void plMipmap::Composite( plMipmap *source, uint16_t x, uint16_t y, plMipmap: { 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; diff --git a/Sources/Plasma/PubUtilLib/plGImage/plMipmap.h b/Sources/Plasma/PubUtilLib/plGImage/plMipmap.h index ebda5902..4e9769ee 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plMipmap.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plMipmap.h @@ -234,11 +234,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 diff --git a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp index b116d1ef..733297a1 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/DX/plDXPipeline.cpp @@ -7211,12 +7211,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; From 6b4739aec90d0497a6c54bda65f94f7402c68a80 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Wed, 25 Jan 2012 22:16:19 +0100 Subject: [PATCH 04/12] 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. --- Sources/Plasma/PubUtilLib/plGImage/plFont.cpp | 82 ++++++++++++++++++- Sources/Plasma/PubUtilLib/plGImage/plFont.h | 7 ++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index 764c77f1..ffa5468f 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -335,7 +335,12 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha if( fRenderInfo.fFlags & kRenderIntoAlpha ) { if( fRenderInfo.fFlags & kRenderAlphaPremultiplied ) - fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremultiplied; + { + if (1)//( ( fRenderInfo.fColor & 0x00ffffff ) == 0x00ffffff ) //FIXME + fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremShadow; + else + fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremultiplied; + } else if( ( fRenderInfo.fColor & 0xff000000 ) != 0xff000000 ) fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32Alpha; else @@ -1082,6 +1087,81 @@ void plFont::IRenderChar8To32AlphaPremultiplied( const plFont::plCharacter &c } } +void plFont::IRenderChar8To32AlphaPremShadow( const plFont::plCharacter &c ) +{ + uint32_t *destPtr, *destBasePtr = (uint32_t *)( fRenderInfo.fDestPtr - c.fBaseline * fRenderInfo.fDestStride ); + int16_t x, y, thisHeight, xstart, thisWidth; + uint8_t 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 = fWidth + 2;// + (int32_t)c.fRightKern; + if( thisWidth >= fRenderInfo.fMaxWidth ) + thisWidth = fRenderInfo.fMaxWidth; + + xstart = fRenderInfo.fClipRect.fX - fRenderInfo.fX; + if( xstart < -2 ) + xstart = -2; + + srcA = (uint8_t)(( fRenderInfo.fColor >> 24 ) & 0x000000ff); + srcR = (uint8_t)(( fRenderInfo.fColor >> 16 ) & 0x000000ff); + srcG = (uint8_t)(( fRenderInfo.fColor >> 8 ) & 0x000000ff); + srcB = (uint8_t)(( fRenderInfo.fColor ) & 0x000000ff); + + static const uint32_t 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_t clamp = 220 - ((2 * srcR + 4 * srcG + srcB) >> 4); + + y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (int16_t)c.fBaseline; + if( y < -2 ) + y = -2; + destBasePtr = (uint32_t *)( (uint8_t *)destBasePtr + y*fRenderInfo.fDestStride ); + + thisHeight = fRenderInfo.fMaxHeight + (int16_t)c.fBaseline; + if( thisHeight > (int16_t)c.fHeight + 2 ) + thisHeight = (int16_t)c.fHeight + 2; + + for( ; y < thisHeight; y++ ) + { + destPtr = destBasePtr; + for( x = xstart; x < thisWidth; x++ ) + { + uint32_t sa = 0; + for (int32_t i = -2; i <= 2; i++) { + for (int32_t j = -2; j <= 2; j++) { + uint32_t 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_t a = IGetCharPixel(c, x, y); + if (srcA != 0xff) + a = (srcA * a + 127) / 255; + uint32_t 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_t *)( (uint8_t *)destBasePtr + fRenderInfo.fDestStride ); + } +} + void plFont::IRenderCharNull( const plCharacter &c ) { diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.h b/Sources/Plasma/PubUtilLib/plGImage/plFont.h index 20dae743..4123fa56 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.h @@ -233,8 +233,15 @@ class plFont : public hsKeyedObject 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_t IGetCharPixel( const plCharacter &c, int32_t x, int32_t y ) + { + // only for 8-bit characters + return (x < 0 || y < 0 || (uint32_t)x >= fWidth || (uint32_t)y >= c.fHeight) ? 0 : *(fBMapData + c.fBitmapOff + y*fWidth + x); + } + public: plFont(); From 1967178e37b73a1797fe7d24b8655e0d68ca4dbb Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 4 Jul 2013 20:13:03 -0400 Subject: [PATCH 05/12] 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. --- .../PubUtilLib/plGImage/plDynamicTextMap.cpp | 32 ++++++++++--------- .../PubUtilLib/plGImage/plDynamicTextMap.h | 2 ++ Sources/Plasma/PubUtilLib/plGImage/plFont.cpp | 2 +- Sources/Plasma/PubUtilLib/plGImage/plFont.h | 1 + 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp index ad869803..f22e327e 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.cpp @@ -379,6 +379,17 @@ void plDynamicTextMap::IClearFromBuffer( uint32_t *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 ) @@ -450,6 +461,8 @@ void plDynamicTextMap::SetFont( const plString &face, uint16_t size, uint8_t // 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 ); } @@ -496,12 +509,9 @@ void plDynamicTextMap::DrawString( uint16_t x, uint16_t y, const wchar_t *tex if( !IIsValid() ) return; - SetJustify( fJustify ); + IPropagateFlags(); fCurrFont->SetRenderFlag( plFont::kRenderWrap | plFont::kRenderClip, false ); fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight ); - fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); - fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); - fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -518,11 +528,8 @@ void plDynamicTextMap::DrawClippedString( int16_t x, int16_t y, const wchar_t if( !IIsValid() ) return; - SetJustify( fJustify ); + IPropagateFlags(); fCurrFont->SetRenderClipping( x, y, width, height ); - fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); - fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); - fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -539,10 +546,8 @@ void plDynamicTextMap::DrawClippedString( int16_t x, int16_t y, const wchar_t if( !IIsValid() ) return; - SetJustify( fJustify ); + IPropagateFlags(); fCurrFont->SetRenderClipping( clipX, clipY, width, height ); - fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); - fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text ); } @@ -559,11 +564,8 @@ void plDynamicTextMap::DrawWrappedString( uint16_t x, uint16_t y, const wchar if( !IIsValid() ) return; - SetJustify( fJustify ); + IPropagateFlags(); fCurrFont->SetRenderWrapping( x, y, width, height ); - fCurrFont->SetRenderColor( fFontColor.ToARGB32() ); - fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB ); - fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha ); fCurrFont->RenderString( this, x, y, text, lastX, lastY ); } diff --git a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h index 318238b8..ad47bab3 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plDynamicTextMap.h @@ -221,6 +221,8 @@ class plDynamicTextMap : public plMipmap uint32_t *IAllocateOSSurface( uint16_t width, uint16_t height ); void IDestroyOSSurface( void ); + void IPropagateFlags(); + bool fHasAlpha, fPremultipliedAlpha, fShadowed; Justify fJustify; diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index ffa5468f..1766ef40 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -336,7 +336,7 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha { if( fRenderInfo.fFlags & kRenderAlphaPremultiplied ) { - if (1)//( ( fRenderInfo.fColor & 0x00ffffff ) == 0x00ffffff ) //FIXME + if (fRenderInfo.fFlags & kRenderShadow) fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremShadow; else fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32AlphaPremultiplied; diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.h b/Sources/Plasma/PubUtilLib/plGImage/plFont.h index 4123fa56..68a2f88f 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.h +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.h @@ -117,6 +117,7 @@ class plFont : public hsKeyedObject // 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 From 0c8fc6d559681f687d05c80d22f453d12c3cdb94 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sun, 6 Apr 2014 17:19:42 +0200 Subject: [PATCH 06/12] 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. --- Sources/Plasma/PubUtilLib/plGImage/plFont.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index 1766ef40..946359ee 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -668,16 +668,14 @@ void plFont::IRenderString( plMipmap *mip, uint16_t x, uint16_t y, const wcha fRenderInfo.fRenderFunc = oldFunc; } - // Adjust for left kern - if( ( fRenderInfo.fFlags & kRenderJustXMask ) == kRenderJustXForceLeft ) - { - // See note at top of file - plCharacter &ch = fCharacters[ (uint16_t)string[ 0 ] - fFirstChar ]; - fRenderInfo.fX -= (int16_t)ch.fLeftKern; - fRenderInfo.fMaxWidth += (int16_t)ch.fLeftKern; - fRenderInfo.fDestPtr -= (int16_t)ch.fLeftKern * fRenderInfo.fDestBPP; - fRenderInfo.fFarthestX = fRenderInfo.fX; - } + // 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 ); From 4e613d189970fc6717db15962f060e95945f11b6 Mon Sep 17 00:00:00 2001 From: Anne Marije v/d Meer Date: Tue, 1 Apr 2014 16:38:12 +0200 Subject: [PATCH 07/12] add python api to set flags Clean up unwanted changes caused by IDE extension -.- Reworked implementation --- .../pfPython/pyGUIControlTextBox.cpp | 30 +++++++++++++++++++ .../FeatureLib/pfPython/pyGUIControlTextBox.h | 2 ++ .../pfPython/pyGUIControlTextBoxGlue.cpp | 19 ++++++++++++ 3 files changed, 51 insertions(+) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp index 97527fa4..3043da52 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp @@ -212,3 +212,33 @@ uint8_t pyGUIControlTextBox::GetJustify() } return pfGUIListText::kLeftJustify; } + +void pyGUIControlTextBox::SetFontFlags(uint8_t fontFlags) +{ + if (fGCkey) + { + // get the pointer to the modifier + pfGUITextBoxMod* ptbmod = pfGUITextBoxMod::ConvertNoRef(fGCkey->ObjectIsLoaded()); + if (ptbmod) + { + pfGUIColorScheme* colorscheme = ptbmod->GetColorScheme(); + colorscheme->fFontFlags = fontFlags; + ptbmod->UpdateColorScheme(); + } + } +} + +uint8_t pyGUIControlTextBox::GetFontFlags() +{ + if (fGCkey) + { + // get the pointer to the modifier + pfGUITextBoxMod* ptbmod = pfGUITextBoxMod::ConvertNoRef(fGCkey->ObjectIsLoaded()); + if (ptbmod) + { + pfGUIColorScheme* colorscheme = ptbmod->GetColorScheme(); + return colorscheme->fFontFlags; + } + } + return 0; +} diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h index bd7b49a9..1a63a441 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h @@ -86,8 +86,10 @@ public: virtual void SetForeColor( pyColor& color ); virtual void SetBackColor( pyColor& color ); virtual void SetJustify( uint8_t justify ); + virtual void SetFontFlags(uint8_t fontflags); virtual uint8_t GetJustify(); virtual PyObject* GetForeColor(); // returns pyColor + virtual uint8_t GetFontFlags(); }; #endif // _pyGUIControlTextBox_h_ diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp index e96b09bd..9eda4d16 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp @@ -188,6 +188,23 @@ PYTHON_METHOD_DEFINITION(ptGUIControlTextBox, setStringJustify, args) PYTHON_RETURN_NONE; } +PYTHON_METHOD_DEFINITION(ptGUIControlTextBox, 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_NOARGS(ptGUIControlTextBox, getFontFlags) +{ + return PyInt_FromLong(self->fThis->GetFontFlags()); +} + PYTHON_METHOD_DEFINITION_NOARGS(ptGUIControlTextBox, getStringJustify) { return PyInt_FromLong(self->fThis->GetJustify()); @@ -207,8 +224,10 @@ PYTHON_START_METHODS_TABLE(ptGUIControlTextBox) PYTHON_METHOD(ptGUIControlTextBox, setForeColor, "Params: color\nSets the text forecolor to 'color', which is a ptColor object."), PYTHON_METHOD(ptGUIControlTextBox, setBackColor, "Params: color\nSets the text backcolor to 'color', which is a ptColor object."), PYTHON_METHOD(ptGUIControlTextBox, setStringJustify, "Params: justify\nSets current justify"), + PYTHON_METHOD(ptGUIControlTextBox, setFontFlags, "Params: fontflags\nSets current fontflags"), PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getStringJustify, "Returns current justify"), PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getForeColor, "Returns the current forecolor"), + PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getFontFlags, "Returns the current fontflags"), PYTHON_END_METHODS_TABLE; // Type structure definition From 664339a4bd4ecb594f26205ac7b81b1571ebdf38 Mon Sep 17 00:00:00 2001 From: Anne Marije v/d Meer Date: Wed, 9 Apr 2014 11:21:28 +0200 Subject: [PATCH 08/12] Move methods to pyGUIControl to pyGUIControlTextBox. --- .../FeatureLib/pfPython/pyGUIControl.cpp | 30 +++++++++++++++++++ .../Plasma/FeatureLib/pfPython/pyGUIControl.h | 4 ++- .../FeatureLib/pfPython/pyGUIControlGlue.cpp | 19 ++++++++++++ .../pfPython/pyGUIControlTextBox.cpp | 29 ------------------ .../FeatureLib/pfPython/pyGUIControlTextBox.h | 3 +- .../pfPython/pyGUIControlTextBoxGlue.cpp | 17 ----------- 6 files changed, 53 insertions(+), 49 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp index e22e57e1..69a82880 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp @@ -445,3 +445,33 @@ void pyGUIControl::SetFontSize(uint32_t fontsize) } } } + +void pyGUIControl::SetFontFlags(uint8_t fontFlags) +{ + if (fGCkey) + { + // get the pointer to the modifier + pfGUIControlMod* pdmod = pfGUIControlMod::ConvertNoRef(fGCkey->ObjectIsLoaded()); + if (pdmod) + { + pfGUIColorScheme* colorscheme = pdmod->GetColorScheme(); + colorscheme->fFontFlags = fontFlags; + } + } +} + +uint8_t pyGUIControl::GetFontFlags() +{ + 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; +} + diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h index bdf1f281..debb9faa 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h @@ -118,13 +118,15 @@ public: virtual PyObject* GetSelColor(); // returns pyColor virtual PyObject* GetBackColor(); // returns pyColor virtual PyObject* GetBackSelColor(); // returns pyColor - virtual uint32_t GetFontSize(); + virtual uint32_t GetFontSize(); + virtual uint8_t GetFontFlags(); // set color scheme virtual void SetForeColor( float r, float g, float b, float a ); virtual void SetSelColor( float r, float g, float b, float a ); virtual void SetBackColor( float r, float g, float b, float a ); virtual void SetBackSelColor( float r, float g, float b, float a ); virtual void SetFontSize(uint32_t fontsize); + virtual void SetFontFlags(uint8_t fontflags); }; diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlGlue.cpp index 9cb23024..7c51714f 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlGlue.cpp @@ -246,6 +246,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; @@ -331,11 +348,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 diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp index 3043da52..8236cc33 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.cpp @@ -213,32 +213,3 @@ uint8_t pyGUIControlTextBox::GetJustify() return pfGUIListText::kLeftJustify; } -void pyGUIControlTextBox::SetFontFlags(uint8_t fontFlags) -{ - if (fGCkey) - { - // get the pointer to the modifier - pfGUITextBoxMod* ptbmod = pfGUITextBoxMod::ConvertNoRef(fGCkey->ObjectIsLoaded()); - if (ptbmod) - { - pfGUIColorScheme* colorscheme = ptbmod->GetColorScheme(); - colorscheme->fFontFlags = fontFlags; - ptbmod->UpdateColorScheme(); - } - } -} - -uint8_t pyGUIControlTextBox::GetFontFlags() -{ - if (fGCkey) - { - // get the pointer to the modifier - pfGUITextBoxMod* ptbmod = pfGUITextBoxMod::ConvertNoRef(fGCkey->ObjectIsLoaded()); - if (ptbmod) - { - pfGUIColorScheme* colorscheme = ptbmod->GetColorScheme(); - return colorscheme->fFontFlags; - } - } - return 0; -} diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h index 1a63a441..b1bab838 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBox.h @@ -86,10 +86,9 @@ public: virtual void SetForeColor( pyColor& color ); virtual void SetBackColor( pyColor& color ); virtual void SetJustify( uint8_t justify ); - virtual void SetFontFlags(uint8_t fontflags); + virtual uint8_t GetJustify(); virtual PyObject* GetForeColor(); // returns pyColor - virtual uint8_t GetFontFlags(); }; #endif // _pyGUIControlTextBox_h_ diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp index 9eda4d16..c859255e 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControlTextBoxGlue.cpp @@ -188,22 +188,7 @@ PYTHON_METHOD_DEFINITION(ptGUIControlTextBox, setStringJustify, args) PYTHON_RETURN_NONE; } -PYTHON_METHOD_DEFINITION(ptGUIControlTextBox, 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_NOARGS(ptGUIControlTextBox, getFontFlags) -{ - return PyInt_FromLong(self->fThis->GetFontFlags()); -} PYTHON_METHOD_DEFINITION_NOARGS(ptGUIControlTextBox, getStringJustify) { @@ -224,10 +209,8 @@ PYTHON_START_METHODS_TABLE(ptGUIControlTextBox) PYTHON_METHOD(ptGUIControlTextBox, setForeColor, "Params: color\nSets the text forecolor to 'color', which is a ptColor object."), PYTHON_METHOD(ptGUIControlTextBox, setBackColor, "Params: color\nSets the text backcolor to 'color', which is a ptColor object."), PYTHON_METHOD(ptGUIControlTextBox, setStringJustify, "Params: justify\nSets current justify"), - PYTHON_METHOD(ptGUIControlTextBox, setFontFlags, "Params: fontflags\nSets current fontflags"), PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getStringJustify, "Returns current justify"), PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getForeColor, "Returns the current forecolor"), - PYTHON_METHOD_NOARGS(ptGUIControlTextBox, getFontFlags, "Returns the current fontflags"), PYTHON_END_METHODS_TABLE; // Type structure definition From bee6001b7800787939ef4ee4c53d71cf418fb196 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Thu, 10 Apr 2014 22:59:37 +0200 Subject: [PATCH 09/12] Fix ptGUIControl.setFontFlags(). --- Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.h | 2 ++ Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp | 4 ++++ .../Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h | 2 ++ Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.h | 2 -- Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.h b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.h index 96f8de7c..695e6ff3 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.h +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIControlMod.h @@ -246,6 +246,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() {;} diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp index b984ce80..bc46bc50 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp @@ -180,6 +180,10 @@ bool pfGUIListBoxMod::MsgReceive( plMessage *msg ) void pfGUIListBoxMod::IPostSetUpDynTextMap( void ) { + pfGUIColorScheme *scheme = GetColorScheme(); + fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags, + HasFlag( kXparentBgnd ) ? false : true ); + ICalcWrapStarts(); ICalcScrollRange(); fReadyToRoll = true; diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h index e9de267b..37f94849 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIMultiLineEditCtrl.h @@ -211,6 +211,8 @@ class pfGUIMultiLineEditCtrl : public pfGUIControlMod virtual void PurgeDynaTextMapImage(); + virtual void UpdateColorScheme() { fFontFlagsSet = 0; pfGUIControlMod::UpdateColorScheme(); } + // Extended event types enum ExtendedEvents { diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.h b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.h index bde8a374..9c442239 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.h +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.h @@ -101,8 +101,6 @@ class pfGUITextBoxMod : public pfGUIControlMod void SetLocalizationPath(const plString& path); void SetUseLocalizationPath(bool use); - - virtual void UpdateColorScheme() { IPostSetUpDynTextMap(); IUpdate(); } }; #endif // _pfGUITextBoxMod_h diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp index 69a82880..f3eb630d 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp @@ -456,6 +456,7 @@ void pyGUIControl::SetFontFlags(uint8_t fontFlags) { pfGUIColorScheme* colorscheme = pdmod->GetColorScheme(); colorscheme->fFontFlags = fontFlags; + pdmod->UpdateColorScheme(); } } } From 04647a1c9822e6d1bed2489a6ccf397b598c9b53 Mon Sep 17 00:00:00 2001 From: Anne Marije v/d Meer Date: Fri, 25 Apr 2014 11:57:33 +0200 Subject: [PATCH 10/12] Fix comment Hoikas --- Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp index bc46bc50..8ae40e98 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUIListBoxMod.cpp @@ -182,7 +182,7 @@ void pfGUIListBoxMod::IPostSetUpDynTextMap( void ) { pfGUIColorScheme *scheme = GetColorScheme(); fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags, - HasFlag( kXparentBgnd ) ? false : true ); + !HasFlag( kXparentBgnd )); ICalcWrapStarts(); ICalcScrollRange(); From e26f479bb54e669e030dd562fa159a77fbe77713 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sat, 12 Apr 2014 10:22:07 +0200 Subject: [PATCH 11/12] Make font flags available to Python in PlasmaConstants. --- Sources/Plasma/FeatureLib/pfPython/pyDynamicTextGlue.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyDynamicTextGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyDynamicTextGlue.cpp index ab7319b1..e6e6c4ce 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyDynamicTextGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyDynamicTextGlue.cpp @@ -493,4 +493,10 @@ void pyDynamicText::AddPlasmaConstantsClasses(PyObject *m) PYTHON_ENUM_ELEMENT(PtJustify, kLeftJustify, plDynamicTextMap::kLeftJustify); PYTHON_ENUM_ELEMENT(PtJustify, kRightJustify, plDynamicTextMap::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); } From 3fceb7652c5b931818f425535bd6175c39c63b36 Mon Sep 17 00:00:00 2001 From: Anne Marije v/d Meer Date: Fri, 25 Apr 2014 12:17:47 +0200 Subject: [PATCH 12/12] Const getters --- Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp | 12 ++++++------ Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp index f3eb630d..9aa775e6 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.cpp @@ -279,7 +279,7 @@ PyObject* pyGUIControl::GetOwnerDlg( void ) } // get color schemes -PyObject* pyGUIControl::GetForeColor() +PyObject* pyGUIControl::GetForeColor() const { if ( fGCkey ) { @@ -293,7 +293,7 @@ PyObject* pyGUIControl::GetForeColor() PYTHON_RETURN_NONE; } -PyObject* pyGUIControl::GetSelColor() +PyObject* pyGUIControl::GetSelColor() const { if ( fGCkey ) { @@ -307,7 +307,7 @@ PyObject* pyGUIControl::GetSelColor() PYTHON_RETURN_NONE; } -PyObject* pyGUIControl::GetBackColor() +PyObject* pyGUIControl::GetBackColor() const { if ( fGCkey ) { @@ -321,7 +321,7 @@ PyObject* pyGUIControl::GetBackColor() PYTHON_RETURN_NONE; } -PyObject* pyGUIControl::GetBackSelColor() +PyObject* pyGUIControl::GetBackSelColor() const { if ( fGCkey ) { @@ -335,7 +335,7 @@ PyObject* pyGUIControl::GetBackSelColor() PYTHON_RETURN_NONE; } -uint32_t pyGUIControl::GetFontSize() +uint32_t pyGUIControl::GetFontSize() const { if ( fGCkey ) { @@ -461,7 +461,7 @@ void pyGUIControl::SetFontFlags(uint8_t fontFlags) } } -uint8_t pyGUIControl::GetFontFlags() +uint8_t pyGUIControl::GetFontFlags() const { if (fGCkey) { diff --git a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h index debb9faa..8d4b1c36 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyGUIControl.h @@ -114,12 +114,12 @@ 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_t GetFontSize(); - virtual uint8_t GetFontFlags(); + 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_t GetFontSize() const; + virtual uint8_t GetFontFlags() const; // set color scheme virtual void SetForeColor( float r, float g, float b, float a ); virtual void SetSelColor( float r, float g, float b, float a );