From b343e389abac3b04fd86305447ada2341e7cd7c5 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Wed, 25 Jan 2012 22:16:19 +0100 Subject: [PATCH] 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. --- .../Plasma/PubUtilLib/plGImage/plFont.cpp | 86 ++++++++++++++++++- .../Plasma/PubUtilLib/plGImage/plFont.h | 7 ++ 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp index ebc8fb6d..f5761216 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp +++ b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.cpp @@ -346,7 +346,12 @@ void plFont::IRenderString( plMipmap *mip, UInt16 x, UInt16 y, const wchar_t *st 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 @@ -1059,8 +1064,8 @@ void plFont::IRenderChar8To32AlphaPremultiplied( const plFont::plCharacter &c ) srcA = (UInt8)(( fRenderInfo.fColor >> 24 ) & 0x000000ff); srcR = (UInt8)(( fRenderInfo.fColor >> 16 ) & 0x000000ff); - srcG = (UInt8)(( fRenderInfo.fColor >> 8 ) & 0x000000ff); - srcB = (UInt8)(( fRenderInfo.fColor ) & 0x000000ff); + srcG = (UInt8)(( fRenderInfo.fColor >> 8 ) & 0x000000ff); + srcB = (UInt8)(( fRenderInfo.fColor ) & 0x000000ff); y = fRenderInfo.fClipRect.fY - fRenderInfo.fY + (Int16)c.fBaseline; if( y < 0 ) @@ -1093,6 +1098,81 @@ void plFont::IRenderChar8To32AlphaPremultiplied( const plFont::plCharacter &c ) } } +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 = 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); + 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; + 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 ) { diff --git a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.h b/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.h index 11e38ca3..ff69be5b 100644 --- a/MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plGImage/plFont.h +++ b/MOULOpenSourceClientPlugin/Plasma20/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 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();