Bitmap: Add font shadow rendering
This commit is contained in:
		
							parent
							
								
									9e64dff01c
								
							
						
					
					
						commit
						4a015c6397
					
				
					 2 changed files with 92 additions and 4 deletions
				
			
		| 
						 | 
					@ -7,10 +7,6 @@ It is licensed under the GNU General Public License v2+.
 | 
				
			||||||
## RGSS2 / RGSS3
 | 
					## 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.
 | 
					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:
 | 
					Missing RGSS3 functionality:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Text outline
 | 
					* Text outline
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -838,6 +838,93 @@ static std::string fixupString(const char *str)
 | 
				
			||||||
	return s;
 | 
						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)
 | 
					void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	guardDisposed();
 | 
						guardDisposed();
 | 
				
			||||||
| 
						 | 
					@ -870,6 +957,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888);
 | 
						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;
 | 
						int alignX = rect.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (align)
 | 
						switch (align)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue