Implement simple DrawGraph.Fill* functions

DrawGraph.Fill - fill solid color
DrawGraph.FillAlphaColor - blend solid color
DrawGraph.FillAMap - fill alpha channel
This commit is contained in:
Nunuhara Cabbage
2019-11-25 20:10:44 -08:00
parent a40467fe92
commit 36111e069c
3 changed files with 71 additions and 6 deletions
+3 -3
View File
@@ -64,11 +64,11 @@ hll_unimplemented(DrawGraph, BlendMultiply);
//void BlendScreenAlpha(int nDest, int nDx, int nDy, int nSrc, int nSx, int nSy, int nWidth, int nHeight, int nAlpha)
hll_unimplemented(DrawGraph, BlendScreenAlpha);
//void Fill(int nDest, int nX, int nY, int nWidth, int nHeight, int nR, int nG, int nB)
hll_unimplemented(DrawGraph, Fill);
hll_defun_inline(Fill, (DrawGraph_Fill(a[0].i, a[1].i, a[2].i, a[3].i, a[4].i, a[5].i, a[6].i, a[7].i), 0));
//void FillAlphaColor(int nDest, int nX, int nY, int nWidth, int nHeight, int nR, int nG, int nB, int nRate)
hll_unimplemented(DrawGraph, FillAlphaColor);
hll_defun_inline(FillAlphaColor, (DrawGraph_FillAlphaColor(a[0].i, a[1].i, a[2].i, a[3].i, a[4].i, a[5].i, a[6].i, a[7].i, a[8].i), 0));
//void FillAMap(int nDest, int nX, int nY, int nWidth, int nHeight, int nAlpha)
hll_unimplemented(DrawGraph, FillAMap);
hll_defun_inline(FillAMap, (DrawGraph_FillAMap(a[0].i, a[1].i, a[2].i, a[3].i, a[4].i, a[5].i), 0));
//void FillAMapOverBorder(int nDest, int nX, int nY, int nWidth, int nHeight, int nAlpha, int nBorder)
hll_unimplemented(DrawGraph, FillAMapOverBorder);
//void FillAMapUnderBorder(int nDest, int nX, int nY, int nWidth, int nHeight, int nAlpha, int nBorder)
+4
View File
@@ -65,4 +65,8 @@ void DrawGraph_CopyUseAMapBorder(int dno, int dx, int dy, int sno, int sx, int s
void DrawGraph_CopyAMapMax(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h);
void DrawGraph_CopyAMapMin(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h);
void DrawGraph_Fill(int sp_no, int x, int y, int w, int h, int r, int g, int b);
void DrawGraph_FillAMap(int sp_no, int x, int y, int w, int h, int a);
void DrawGraph_FillAlphaColor(int sp_no, int x, int y, int w, int h, int r, int g, int b, int a);
#endif /* SYSTEM4_SACT_H */
+64 -3
View File
@@ -125,11 +125,12 @@ int sact_SP_SetCG(int sp_no, int cg_no)
int sact_SP_Create(int sp_no, int width, int height, int r, int g, int b, int a)
{
struct sact_sprite *sp = sact_get_sprite(sp_no);
struct sact_sprite *sp;
if (!sp) {
if (sp_no < 0)
VM_ERROR("Invalid sprite number: %d", sp_no);
if (!(sp = sact_get_sprite(sp_no)))
sp = alloc_sprite(sp_no);
}
sp->color = (SDL_Color) { .r = r, .g = g, .b = b, .a = a };
sp->rect.w = width;
@@ -344,6 +345,17 @@ static inline void next_pixel(SDL_Surface *s, uint32_t **p)
SDL_UnlockSurface(ds); \
} while (0)
#define fill_for_each_pixel(s, x, y, w, h, p, expr) \
do { \
SDL_LockSurface(s); \
for (int _row = 0; _row < h; _row++) { \
uint32_t *p = get_pixel(s, x, _row+y); \
for (int _col = 0; _col < w; _col++, next_pixel(s, &p)) \
expr; \
} \
SDL_UnlockSurface(s); \
} while(0);
void DrawGraph_CopyAMap(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
{
SDL_Surface *ds = DrawGraph_get_sprite(dno)->cg->s;
@@ -450,3 +462,52 @@ void DrawGraph_CopyAMapMin(int dno, int dx, int dy, int sno, int sx, int sy, int
}
});
}
static void blend_pixels(SDL_Color *dst, SDL_Color src)
{
uint32_t alpha = src.a + 1;
uint32_t inv_alpha = 256 - src.a;
dst->r = (uint8_t)((alpha * src.r + inv_alpha * dst->r) >> 8);
dst->g = (uint8_t)((alpha * src.g + inv_alpha * dst->g) >> 8);
dst->b = (uint8_t)((alpha * src.b + inv_alpha * dst->b) >> 8);
}
void DrawGraph_Fill(int sp_no, int x, int y, int w, int h, int r, int g, int b)
{
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
fill_for_each_pixel(s, x, y, w, h, p, {
*p &= ~(s->format->Rmask | s->format->Gmask | s->format->Bmask);
*p |= (uint32_t)r << s->format->Rshift;
*p |= (uint32_t)g << s->format->Gshift;
*p |= (uint32_t)b << s->format->Bshift;
});
}
// XXX: Despite being called a fill operation, this function actually performs blending.
void DrawGraph_FillAlphaColor(int sp_no, int x, int y, int w, int h, int r, int g, int b, int a)
{
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
SDL_Color dst;
SDL_Color src = { .r = r, .g = g, .b = b, .a = a };
fill_for_each_pixel(s, x, y, w, h, p, {
SDL_GetRGBA(*p, s->format, &dst.r, &dst.g, &dst.b, &dst.a);
blend_pixels(&dst, src);
*p &= ~(s->format->Rmask | s->format->Gmask | s->format->Bmask | s->format->Amask);
*p |= (uint32_t)dst.r << s->format->Rshift;
*p |= (uint32_t)dst.g << s->format->Gshift;
*p |= (uint32_t)dst.b << s->format->Bshift;
*p |= (uint32_t)dst.a << s->format->Ashift;
});
}
void DrawGraph_FillAMap(int sp_no, int x, int y, int w, int h, int a)
{
SDL_Surface *s = DrawGraph_get_sprite(sp_no)->cg->s;
fill_for_each_pixel(s, x, y, w, h, p, {
*p &= ~s->format->Amask;
*p |= (uint32_t)a << s->format->Ashift;
});
}