Bitmap: Add font shadow rendering
This commit is contained in:
parent
9e64dff01c
commit
4a015c6397
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue