Bitmap: Add font shadow rendering

This commit is contained in:
Jonas Kulla 2014-09-29 10:30:41 +02:00
parent 9e64dff01c
commit 4a015c6397
2 changed files with 92 additions and 4 deletions

View File

@ -7,10 +7,6 @@ It is licensed under the GNU General Public License v2+.
## RGSS2 / RGSS3
Support for these RGSS versions is experimental. A lot is implemented (to the point that you can play the VX Ace sample game, with caveats), but not everything is in place yet.
Missing RGSS2 functionality:
* Text shadow
Missing RGSS3 functionality:
* Text outline

View File

@ -838,6 +838,93 @@ static std::string fixupString(const char *str)
return s;
}
static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_Color &c)
{
SDL_Surface *out = SDL_CreateRGBSurface
(0, in->w+1, in->h+1, fm.BitsPerPixel, fm.Rmask, fm.Gmask, fm.Bmask, fm.Amask);
float fr = c.r / 255.0;
float fg = c.g / 255.0;
float fb = c.b / 255.0;
/* We allocate an output surface one pixel wider and higher than the input,
* (implicitly) blit a copy of the input with RGB values set to black into
* it with x/y offset by 1, then blend the input surface over it at origin
* (0,0) using the bitmap blit equation (see shader/bitmapBlit.frag) */
for (int y = 0; y < in->h+1; ++y)
for (int x = 0; x < in->w+1; ++x)
{
/* src: input pixel, shd: shadow pixel */
uint32_t src = 0, shd = 0;
/* Output pixel location */
uint32_t *outP = ((uint32_t*) ((uint8_t*) out->pixels + y*out->pitch)) + x;
if (y < in->h && x < in->w)
src = ((uint32_t*) ((uint8_t*) in->pixels + y*in->pitch))[x];
if (y > 0 && x > 0)
shd = ((uint32_t*) ((uint8_t*) in->pixels + (y-1)*in->pitch))[x-1];
/* Set shadow pixel RGB values to 0 (black) */
shd &= fm.Amask;
if (x == 0 || y == 0)
{
*outP = src;
continue;
}
if (x == in->w || y == in->h)
{
*outP = shd;
continue;
}
/* Input and shadow alpha values */
uint8_t srcA, shdA;
srcA = (src & fm.Amask) >> fm.Ashift;
shdA = (shd & fm.Amask) >> fm.Ashift;
if (srcA == 255 || shdA == 0)
{
*outP = src;
continue;
}
if (srcA == 0 && shdA == 0)
{
*outP = 0;
continue;
}
float fSrcA = srcA / 255.0;
float fShdA = shdA / 255.0;
/* Because opacity == 1, co1 == fSrcA */
float co2 = fShdA * (1.0 - fSrcA);
/* Result alpha */
float fa = fSrcA + co2;
/* Temp value to simplify arithmetic below */
float co3 = fSrcA / fa;
/* Result colors */
uint8_t r, g, b, a;
r = clamp<float>(fr * co3, 0, 1) * 255;
g = clamp<float>(fg * co3, 0, 1) * 255;
b = clamp<float>(fb * co3, 0, 1) * 255;
a = clamp<float>(fa, 0, 1) * 255;
*outP = SDL_MapRGBA(&fm, r, g, b, a);
}
/* Store new surface in the input pointer */
SDL_FreeSurface(in);
in = out;
}
void Bitmap::drawText(const IntRect &rect, const char *str, int align)
{
guardDisposed();
@ -870,6 +957,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888);
// While real outlining is not yet here, use shadow
// as a replacement to at least make text legible
if (p->font->getShadow() || p->font->getOutline())
applyShadow(txtSurf, *p->format, c);
int alignX = rect.x;
switch (align)