Fix alpha blitting once and for all
This commit is contained in:
parent
2d7a29d17e
commit
8e48ee8cfa
@ -725,6 +725,7 @@ FT_Face face_extra;
|
||||
FT_GlyphSlot slot;
|
||||
FT_UInt glyph_index;
|
||||
|
||||
|
||||
void drawChar(FT_Bitmap * bitmap, int x, int y, uint32_t fg, uint32_t bg) {
|
||||
int i, j, p, q;
|
||||
int x_max = x + bitmap->width;
|
||||
@ -732,7 +733,7 @@ void drawChar(FT_Bitmap * bitmap, int x, int y, uint32_t fg, uint32_t bg) {
|
||||
for (j = y, q = 0; j < y_max; j++, q++) {
|
||||
for ( i = x, p = 0; i < x_max; i++, p++) {
|
||||
uint32_t tmp = (fg & 0xFFFFFF) | 0x1000000 * bitmap->buffer[q * bitmap->width + p];
|
||||
term_set_point(i,j, alpha_blend_rgba(bg, tmp));
|
||||
term_set_point(i,j, alpha_blend_rgba(premultiply(bg), premultiply(tmp)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -802,13 +803,13 @@ term_write_char(
|
||||
if (val == 0xFFFF) { return; } /* Unicode, do not redraw here */
|
||||
for (uint8_t i = 0; i < char_height; ++i) {
|
||||
for (uint8_t j = 0; j < char_width; ++j) {
|
||||
term_set_point(x+j,y+i,_bg);
|
||||
term_set_point(x+j,y+i,premultiply(_bg));
|
||||
}
|
||||
}
|
||||
if (flags & ANSI_WIDE) {
|
||||
for (uint8_t i = 0; i < char_height; ++i) {
|
||||
for (uint8_t j = char_width; j < 2 * char_width; ++j) {
|
||||
term_set_point(x+j,y+i,_bg);
|
||||
term_set_point(x+j,y+i,premultiply(_bg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,23 @@
|
||||
#define PNG_DEBUG 3
|
||||
#include <png.h>
|
||||
|
||||
static inline int32_t min(int32_t a, int32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int32_t max(int32_t a, int32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint16_t min16(uint16_t a, uint16_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint16_t max16(uint16_t a, uint16_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Pointer to graphics memory */
|
||||
void flip(gfx_context_t * ctx) {
|
||||
@ -131,16 +148,34 @@ uint32_t alpha_blend(uint32_t bottom, uint32_t top, uint32_t mask) {
|
||||
return rgba(red,gre,blu, alp);
|
||||
}
|
||||
|
||||
#define DONT_USE_FLOAT_FOR_ALPHA 1
|
||||
|
||||
uint32_t alpha_blend_rgba(uint32_t bottom, uint32_t top) {
|
||||
uint8_t a = _ALP(top);
|
||||
uint8_t b = ((int)_ALP(bottom) * (255 - a)) / 255;
|
||||
uint8_t alp = a + b;
|
||||
uint8_t red = alp ? (int)(_RED(bottom) * (b) + _RED(top) * a) / (alp): 0;
|
||||
uint8_t gre = alp ? (int)(_GRE(bottom) * (b) + _GRE(top) * a) / (alp): 0;
|
||||
uint8_t blu = alp ? (int)(_BLU(bottom) * (b) + _BLU(top) * a) / (alp): 0;
|
||||
if (_ALP(bottom) == 0) return top;
|
||||
if (_ALP(top) == 255) return top;
|
||||
if (_ALP(top) == 0) return bottom;
|
||||
#if DONT_USE_FLOAT_FOR_ALPHA
|
||||
uint16_t a = _ALP(top);
|
||||
uint16_t c = 255 - a;
|
||||
uint16_t b = ((int)_ALP(bottom) * c) / 255;
|
||||
uint16_t alp = min16(a + b, 255);
|
||||
uint16_t red = min16((uint32_t)(_RED(bottom) * c + _RED(top) * 255) / 255, 255);
|
||||
uint16_t gre = min16((uint32_t)(_GRE(bottom) * c + _GRE(top) * 255) / 255, 255);
|
||||
uint16_t blu = min16((uint32_t)(_BLU(bottom) * c + _BLU(top) * 255) / 255, 255);
|
||||
return rgba(red,gre,blu,alp);
|
||||
#else
|
||||
double a = _ALP(top) / 255.0;
|
||||
double c = 1.0 - a;
|
||||
double b = (_ALP(bottom) / 255.0) * c;
|
||||
double alp = a + b; if (alp > 1.0) alp = 1.0;
|
||||
double red = (_RED(bottom) / 255.0) * c + (_RED(top) / 255.0); if (red > 1.0) red = 1.0;
|
||||
double gre = (_GRE(bottom) / 255.0) * c + (_GRE(top) / 255.0); if (gre > 1.0) gre = 1.0;
|
||||
double blu = (_BLU(bottom) / 255.0) * c + (_BLU(top) / 255.0); if (blu > 1.0) blu = 1.0;
|
||||
return rgba(red * 255, gre * 255, blu * 255, alp * 255);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint32_t premultiply(uint32_t color) {
|
||||
uint16_t a = _ALP(color);
|
||||
uint16_t r = _RED(color);
|
||||
@ -408,14 +443,6 @@ void context_to_png(FILE * file, gfx_context_t * ctx) {
|
||||
}
|
||||
|
||||
|
||||
static inline int32_t min(int32_t a, int32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int32_t max(int32_t a, int32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
void draw_sprite(gfx_context_t * ctx, sprite_t * sprite, int32_t x, int32_t y) {
|
||||
int32_t _left = max(x, 0);
|
||||
int32_t _top = max(y, 0);
|
||||
|
@ -76,4 +76,7 @@ void draw_sprite_scaled(gfx_context_t * ctx, sprite_t * sprite, int32_t x, int32
|
||||
|
||||
void context_to_png(FILE * file, gfx_context_t * ctx);
|
||||
|
||||
uint32_t premultiply(uint32_t color);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@ int main(int argc, char ** argv) {
|
||||
printf("\033[38;2;178;213;238mHello World\033[0m\n");
|
||||
|
||||
for (int i = 0; i < 256; i += 3) {
|
||||
printf("\033[48;6;30;30;30;%dmX\033[0m", i);
|
||||
printf("\033[48;6;255;0;0;%dmX\033[0m", i);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user