mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
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.
This commit is contained in:
@ -71,6 +71,7 @@ struct hsColorRGBA {
|
|||||||
|
|
||||||
hsColorRGBA& FromARGB32(UInt32 c);
|
hsColorRGBA& FromARGB32(UInt32 c);
|
||||||
UInt32 ToARGB32() const;
|
UInt32 ToARGB32() const;
|
||||||
|
UInt32 ToARGB32Premultiplied() const;
|
||||||
|
|
||||||
void Read(hsStream *stream);
|
void Read(hsStream *stream);
|
||||||
void Write(hsStream *stream) const;
|
void Write(hsStream *stream) const;
|
||||||
@ -109,6 +110,14 @@ inline UInt32 hsColorRGBA::ToARGB32() const
|
|||||||
| (UInt32(b * 255.99f) << 0);
|
| (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)
|
inline hsColorRGBA operator+(const hsColorRGBA& s, const hsColorRGBA& t)
|
||||||
{
|
{
|
||||||
hsColorRGBA res;
|
hsColorRGBA res;
|
||||||
|
@ -695,7 +695,7 @@ hsBool pfGUIControlMod::ISetUpDynTextMap( plPipeline *pipe )
|
|||||||
extraH -= height;
|
extraH -= height;
|
||||||
|
|
||||||
fDynTextMap->Reset();
|
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,
|
fDynTextMap->SetFont( GetColorScheme()->fFontFace, GetColorScheme()->fFontSize, GetColorScheme()->fFontFlags,
|
||||||
HasFlag( kXparentBgnd ) ? false : true );
|
HasFlag( kXparentBgnd ) ? false : true );
|
||||||
@ -706,6 +706,7 @@ hsBool pfGUIControlMod::ISetUpDynTextMap( plPipeline *pipe )
|
|||||||
// out with 1:1 mapping from textel to pixel
|
// out with 1:1 mapping from textel to pixel
|
||||||
plLayer *layer = (plLayer *)fDynTextLayer;
|
plLayer *layer = (plLayer *)fDynTextLayer;
|
||||||
layer->SetTransform( fDynTextMap->GetLayerTransform() );
|
layer->SetTransform( fDynTextMap->GetLayerTransform() );
|
||||||
|
layer->SetBlendFlags( layer->GetBlendFlags() | hsGMatState::kBlendAlphaPremultiplied );
|
||||||
|
|
||||||
// Let the derived classes do their things
|
// Let the derived classes do their things
|
||||||
IPostSetUpDynTextMap();
|
IPostSetUpDynTextMap();
|
||||||
|
@ -85,7 +85,8 @@ enum hsGMatBlendFlags {
|
|||||||
kBlendEnvBumpNext = 0x800000,
|
kBlendEnvBumpNext = 0x800000,
|
||||||
kBlendSubtract = 0x1000000,
|
kBlendSubtract = 0x1000000,
|
||||||
kBlendRevSubtract = 0x2000000,
|
kBlendRevSubtract = 0x2000000,
|
||||||
kBlendAlphaTestHigh = 0x4000000
|
kBlendAlphaTestHigh = 0x4000000,
|
||||||
|
kBlendAlphaPremultiplied = 0x8000000
|
||||||
};
|
};
|
||||||
enum hsGMatClampFlags {
|
enum hsGMatClampFlags {
|
||||||
|
|
||||||
|
@ -75,20 +75,12 @@ plProfile_Extern(MemMipmaps);
|
|||||||
|
|
||||||
//// Constructor & Destructor /////////////////////////////////////////////////
|
//// 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;
|
fFontColor.Set(0, 0, 0, 1);
|
||||||
fHasAlpha = false;
|
|
||||||
fJustify = kLeftJustify;
|
|
||||||
fInitBuffer = nil;
|
|
||||||
fFontFace = nil;
|
|
||||||
fFontSize = 0;
|
|
||||||
fFontFlags = 0;
|
|
||||||
fFontAntiAliasRGB = false;
|
|
||||||
fFontColor.Set( 0, 0, 0, 1 );
|
|
||||||
fFontBlockRGB = false;
|
|
||||||
fHasCreateBeenCalled = false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plDynamicTextMap::~plDynamicTextMap()
|
plDynamicTextMap::~plDynamicTextMap()
|
||||||
@ -96,11 +88,10 @@ plDynamicTextMap::~plDynamicTextMap()
|
|||||||
Reset();
|
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;
|
Create( width, height, hasAlpha, extraWidth, extraHeight, premultipliedAlpha );
|
||||||
fFontFace = nil;
|
|
||||||
Create( width, height, hasAlpha, extraWidth, extraHeight );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//// SetNoCreate //////////////////////////////////////////////////////////////
|
//// SetNoCreate //////////////////////////////////////////////////////////////
|
||||||
@ -122,7 +113,7 @@ void plDynamicTextMap::SetNoCreate( UInt32 width, UInt32 height, hsBool hasAlpha
|
|||||||
|
|
||||||
//// Create ///////////////////////////////////////////////////////////////////
|
//// 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 );
|
SetConfig( hasAlpha ? kARGB32Config : kRGB32Config );
|
||||||
|
|
||||||
@ -130,6 +121,7 @@ void plDynamicTextMap::Create( UInt32 width, UInt32 height, hsBool hasAlpha, UIn
|
|||||||
fVisWidth = (UInt16)width;
|
fVisWidth = (UInt16)width;
|
||||||
fVisHeight = (UInt16)height;
|
fVisHeight = (UInt16)height;
|
||||||
fHasAlpha = hasAlpha;
|
fHasAlpha = hasAlpha;
|
||||||
|
fPremultipliedAlpha = premultipliedAlpha;
|
||||||
|
|
||||||
for( fWidth = 1; fWidth < width + extraWidth; fWidth <<= 1 );
|
for( fWidth = 1; fWidth < width + extraWidth; fWidth <<= 1 );
|
||||||
for( fHeight = 1; fHeight < height + extraHeight; fHeight <<= 1 );
|
for( fHeight = 1; fHeight < height + extraHeight; fHeight <<= 1 );
|
||||||
@ -395,7 +387,7 @@ void plDynamicTextMap::ClearToColor( hsColorRGBA &color )
|
|||||||
if( !IIsValid() )
|
if( !IIsValid() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UInt32 i, hex = color.ToARGB32();
|
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||||
UInt32 *data = (UInt32 *)fImage;
|
UInt32 *data = (UInt32 *)fImage;
|
||||||
|
|
||||||
// Buffer is of size fVisWidth x fVisHeight, so we need a bit of work to do this right
|
// Buffer is of size fVisWidth x fVisHeight, so we need a bit of work to do this right
|
||||||
@ -520,6 +512,7 @@ void plDynamicTextMap::DrawString( UInt16 x, UInt16 y, const wchar_t *text )
|
|||||||
fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight );
|
fCurrFont->SetRenderClipRect( 0, 0, fVisWidth, fVisHeight );
|
||||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||||
|
fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha );
|
||||||
fCurrFont->RenderString( this, x, y, text );
|
fCurrFont->RenderString( this, x, y, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,6 +534,7 @@ void plDynamicTextMap::DrawClippedString( Int16 x, Int16 y, const wchar_t *text,
|
|||||||
fCurrFont->SetRenderClipping( x, y, width, height );
|
fCurrFont->SetRenderClipping( x, y, width, height );
|
||||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||||
|
fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha );
|
||||||
fCurrFont->RenderString( this, x, y, text );
|
fCurrFont->RenderString( this, x, y, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,6 +555,7 @@ void plDynamicTextMap::DrawClippedString( Int16 x, Int16 y, const wchar_t *text,
|
|||||||
SetJustify( fJustify );
|
SetJustify( fJustify );
|
||||||
fCurrFont->SetRenderClipping( clipX, clipY, width, height );
|
fCurrFont->SetRenderClipping( clipX, clipY, width, height );
|
||||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||||
|
fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha );
|
||||||
fCurrFont->RenderString( this, x, y, text );
|
fCurrFont->RenderString( this, x, y, text );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,6 +577,7 @@ void plDynamicTextMap::DrawWrappedString( UInt16 x, UInt16 y, const wchar_t *tex
|
|||||||
fCurrFont->SetRenderWrapping( x, y, width, height );
|
fCurrFont->SetRenderWrapping( x, y, width, height );
|
||||||
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
fCurrFont->SetRenderColor( fFontColor.ToARGB32() );
|
||||||
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
fCurrFont->SetRenderFlag( plFont::kRenderIntoAlpha, fFontBlockRGB );
|
||||||
|
fCurrFont->SetRenderFlag( plFont::kRenderAlphaPremultiplied, fPremultipliedAlpha );
|
||||||
fCurrFont->RenderString( this, x, y, text, lastX, lastY );
|
fCurrFont->RenderString( this, x, y, text, lastX, lastY );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +661,7 @@ void plDynamicTextMap::FillRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height
|
|||||||
width = (UInt16)(fWidth - x);
|
width = (UInt16)(fWidth - x);
|
||||||
|
|
||||||
// Gee, how hard can it REALLY be?
|
// Gee, how hard can it REALLY be?
|
||||||
UInt32 i, hex = color.ToARGB32();
|
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||||
height += y;
|
height += y;
|
||||||
if( height > fHeight )
|
if( height > fHeight )
|
||||||
height = (UInt16)fHeight;
|
height = (UInt16)fHeight;
|
||||||
@ -690,7 +686,7 @@ void plDynamicTextMap::FrameRect( UInt16 x, UInt16 y, UInt16 width, UInt16 heigh
|
|||||||
height = (UInt16)(fHeight - y);
|
height = (UInt16)(fHeight - y);
|
||||||
|
|
||||||
// Shouldn't be much harder
|
// Shouldn't be much harder
|
||||||
UInt32 i, hex = color.ToARGB32();
|
UInt32 i, hex = fPremultipliedAlpha ? color.ToARGB32Premultiplied() : color.ToARGB32();
|
||||||
UInt32 *dest1, *dest2;
|
UInt32 *dest1, *dest2;
|
||||||
|
|
||||||
dest1 = GetAddr32( x, y );
|
dest1 = GetAddr32( x, y );
|
||||||
@ -725,6 +721,9 @@ void plDynamicTextMap::DrawImage( UInt16 x, UInt16 y, plMipmap *image, DrawMetho
|
|||||||
else if( method == kImgSprite )
|
else if( method == kImgSprite )
|
||||||
opts.fFlags = plMipmap::kCopySrcAlpha;
|
opts.fFlags = plMipmap::kCopySrcAlpha;
|
||||||
|
|
||||||
|
if( fPremultipliedAlpha )
|
||||||
|
opts.fFlags |= plMipmap::kDestPremultiplied;
|
||||||
|
|
||||||
Composite( image, x, y, &opts );
|
Composite( image, x, y, &opts );
|
||||||
|
|
||||||
/// HACK for now, since the alpha in the mipmap gets copied straight into the
|
/// HACK for now, since the alpha in the mipmap gets copied straight into the
|
||||||
@ -763,6 +762,9 @@ void plDynamicTextMap::DrawClippedImage( UInt16 x, UInt16 y, plMipmap *image,
|
|||||||
else if( method == kImgSprite )
|
else if( method == kImgSprite )
|
||||||
opts.fFlags = plMipmap::kCopySrcAlpha;
|
opts.fFlags = plMipmap::kCopySrcAlpha;
|
||||||
|
|
||||||
|
if( fPremultipliedAlpha )
|
||||||
|
opts.fFlags |= plMipmap::kDestPremultiplied;
|
||||||
|
|
||||||
opts.fSrcClipX = srcClipX;
|
opts.fSrcClipX = srcClipX;
|
||||||
opts.fSrcClipY = srcClipY;
|
opts.fSrcClipY = srcClipY;
|
||||||
opts.fSrcClipWidth = srcClipWidth;
|
opts.fSrcClipWidth = srcClipWidth;
|
||||||
@ -909,6 +911,7 @@ void plDynamicTextMap::Swap( plDynamicTextMap *other )
|
|||||||
|
|
||||||
// Swap DTMap info
|
// Swap DTMap info
|
||||||
SWAP_ME( hsBool, fHasAlpha, other->fHasAlpha );
|
SWAP_ME( hsBool, fHasAlpha, other->fHasAlpha );
|
||||||
|
SWAP_ME( hsBool, fPremultipliedAlpha, other->fPremultipliedAlpha );
|
||||||
SWAP_ME( hsBool, fShadowed, other->fShadowed );
|
SWAP_ME( hsBool, fShadowed, other->fShadowed );
|
||||||
|
|
||||||
SWAP_ME( Justify, fJustify, other->fJustify );
|
SWAP_ME( Justify, fJustify, other->fJustify );
|
||||||
|
@ -113,14 +113,14 @@ class plDynamicTextMap : public plMipmap
|
|||||||
|
|
||||||
|
|
||||||
plDynamicTextMap();
|
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();
|
virtual ~plDynamicTextMap();
|
||||||
|
|
||||||
CLASSNAME_REGISTER( plDynamicTextMap );
|
CLASSNAME_REGISTER( plDynamicTextMap );
|
||||||
GETINTERFACE_ANY( plDynamicTextMap, plMipmap );
|
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 );
|
void SetNoCreate( UInt32 width, UInt32 height, hsBool hasAlpha );
|
||||||
|
|
||||||
virtual void Reset( void );
|
virtual void Reset( void );
|
||||||
@ -222,7 +222,7 @@ class plDynamicTextMap : public plMipmap
|
|||||||
UInt32 *IAllocateOSSurface( UInt16 width, UInt16 height );
|
UInt32 *IAllocateOSSurface( UInt16 width, UInt16 height );
|
||||||
void IDestroyOSSurface( void );
|
void IDestroyOSSurface( void );
|
||||||
|
|
||||||
hsBool fHasAlpha, fShadowed;
|
hsBool fHasAlpha, fPremultipliedAlpha, fShadowed;
|
||||||
|
|
||||||
Justify fJustify;
|
Justify fJustify;
|
||||||
char *fFontFace;
|
char *fFontFace;
|
||||||
|
@ -345,7 +345,9 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st
|
|||||||
{
|
{
|
||||||
if( fRenderInfo.fFlags & kRenderIntoAlpha )
|
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;
|
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32Alpha;
|
||||||
else
|
else
|
||||||
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32FullAlpha;
|
fRenderInfo.fRenderFunc = &plFont::IRenderChar8To32FullAlpha;
|
||||||
@ -1032,6 +1034,65 @@ 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 = 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::IRenderCharNull( const plCharacter &c )
|
void plFont::IRenderCharNull( const plCharacter &c )
|
||||||
{
|
{
|
||||||
|
@ -116,6 +116,7 @@ class plFont : public hsKeyedObject
|
|||||||
// value between the renderColor and the destColor and
|
// value between the renderColor and the destColor and
|
||||||
// leave the alpha as-is
|
// leave the alpha as-is
|
||||||
// This flag has no effect on monochrome fonts
|
// This flag has no effect on monochrome fonts
|
||||||
|
kRenderAlphaPremultiplied = 0x00001000, // Destination has color values premultiplied by alpha
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Flags
|
enum Flags
|
||||||
@ -231,6 +232,7 @@ class plFont : public hsKeyedObject
|
|||||||
void IRenderChar8To32( const plCharacter &c );
|
void IRenderChar8To32( const plCharacter &c );
|
||||||
void IRenderChar8To32Alpha( const plCharacter &c );
|
void IRenderChar8To32Alpha( const plCharacter &c );
|
||||||
void IRenderChar8To32FullAlpha( const plCharacter &c );
|
void IRenderChar8To32FullAlpha( const plCharacter &c );
|
||||||
|
void IRenderChar8To32AlphaPremultiplied( const plCharacter &c );
|
||||||
void IRenderCharNull( const plCharacter &c );
|
void IRenderCharNull( const plCharacter &c );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -1745,6 +1745,18 @@ void plMipmap::Composite( plMipmap *source, UInt16 x, UInt16 y, plMipmap::Compos
|
|||||||
for( pY = (UInt16)srcHeight; pY > 0; pY-- )
|
for( pY = (UInt16)srcHeight; pY > 0; pY-- )
|
||||||
{
|
{
|
||||||
memcpy( dstPtr, srcPtr, srcRowBytesToCopy );
|
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;
|
dstPtr += dstRowBytes >> 2;
|
||||||
srcPtr += srcRowBytes >> 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;
|
srcAlpha = options->fOpacity * ( ( srcPtr[ pX ] >> 16 ) & 0x0000ff00 ) / 255 / 256;
|
||||||
if( srcAlpha != 0 )
|
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;
|
dstPtr += dstRowBytes >> 2;
|
||||||
srcPtr += srcRowBytes >> 2;
|
srcPtr += srcRowBytes >> 2;
|
||||||
|
@ -233,11 +233,14 @@ class plMipmap : public plBitmap
|
|||||||
|
|
||||||
enum CompositeFlags
|
enum CompositeFlags
|
||||||
{
|
{
|
||||||
kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque
|
kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque
|
||||||
kCopySrcAlpha = 0x0002, // Copy the src pixels raw, including alphas, overwrite dest
|
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
|
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
|
kMaskSrcAlpha = 0x0008, // Same as copySrcAlpha, but dest is untouched when src alpha = 0
|
||||||
kBlendWriteAlpha= 0x0010 // Like default (0), but writes dest alpha values
|
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
|
class CompositeOptions
|
||||||
|
@ -7229,12 +7229,26 @@ void plDXPipeline::IHandleFirstStageBlend()
|
|||||||
fD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
fD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
||||||
if( fLayerState[0].fBlendFlags & hsGMatState::kBlendInvertFinalAlpha )
|
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 );
|
fD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
|
||||||
}
|
}
|
||||||
else
|
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 );
|
fD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user