mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-30 02:48:14 +03:00
Implement more DrawGraph/SACT2 functions
5 functions:
SACT2.SP_SetDrawMethod
DrawGraph.CopyStretch
DrawGraph.CopyStretchAmap
DrawGraph.CopyReduce
DrawGraph.CopyReduceAmap
SP_SetDrawMethod is not pixel-perfect to System40.exe, but its pretty
close.
I'm not sure what the difference between the Stretch/Reduce functions is
supposed to be. They seem to do the same thing.
Also, the ugly macros in sdl_draw.c are replaced by higher-order
functions.
With this commit, Sengoku Rance runs up to the menu without exiting due
to unimplemented HLL functions.
This commit is contained in:
+4
-4
@@ -98,21 +98,21 @@ hll_unimplemented(DrawGraph, CopyTextureWrap);
|
||||
//void CopyTextureWrapAlpha(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight, int nU, int nV, int nAlpha)
|
||||
hll_unimplemented(DrawGraph, CopyTextureWrapAlpha);
|
||||
//void CopyStretch(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyStretch);
|
||||
hll_defun_inline(CopyStretch, (DrawGraph_CopyStretch(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, a[9].i), 0));
|
||||
//void CopyStretchBlend(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight, int nAlpha)
|
||||
hll_unimplemented(DrawGraph, CopyStretchBlend);
|
||||
//void CopyStretchBlendAMap(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyStretchBlendAMap);
|
||||
//void CopyStretchAMap(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyStretchAMap);
|
||||
hll_defun_inline(CopyStretchAMap, (DrawGraph_CopyStretchAMap(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, a[9].i), 0));
|
||||
//void CopyStretchInterp(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyStretchInterp);
|
||||
//void CopyStretchAMapInterp(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyStretchAMapInterp);
|
||||
//void CopyReduce(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyReduce);
|
||||
hll_defun_inline(CopyReduce, (DrawGraph_CopyStretch(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, a[9].i), 0));
|
||||
//void CopyReduceAMap(int nDest, int nDx, int nDy, int nDWidth, int nDHeight, int nSrc, int nSx, int nSy, int nSWidth, int nSHeight)
|
||||
hll_unimplemented(DrawGraph, CopyReduceAMap);
|
||||
hll_defun_inline(CopyReduceAMap, (DrawGraph_CopyStretchAMap(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, a[9].i), 0));
|
||||
//void DrawTextToPMap(int nDest, int nX, int nY, string szText)
|
||||
hll_unimplemented(DrawGraph, DrawTextToPMap);
|
||||
//void DrawTextToAMap(int nDest, int nX, int nY, string szText)
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ hll_defun(SP_SetShow, args)
|
||||
}
|
||||
|
||||
// int SP_SetDrawMethod(int nSP, int nMethod)
|
||||
hll_unimplemented(SACT2, SP_SetDrawMethod);
|
||||
hll_defun_inline(SP_SetDrawMethod, sact_SP_SetDrawMethod(a[0].i, a[1].i));
|
||||
|
||||
// int SP_IsUsing(int nSP)
|
||||
hll_defun_inline(SP_IsUsing, sact_get_sprite(a[0].i) != NULL);
|
||||
|
||||
@@ -57,6 +57,7 @@ int sact_SP_Create(int sp, int width, int height, int r, int g, int b, int a);
|
||||
int sact_SP_CreatePixelOnly(int sp, int width, int height);
|
||||
int sact_SP_Delete(int sp);
|
||||
int sact_SP_SetZ(int sp, int z);
|
||||
int sact_SP_SetDrawMethod(int sp_no, int method);
|
||||
int sact_SP_ExistsAlpha(int sp_no);
|
||||
int sact_SP_TextDraw(int sp_no, struct string *text, union vm_value *tm);
|
||||
int sact_SP_TextClear(int sp_no);
|
||||
@@ -76,4 +77,7 @@ 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);
|
||||
|
||||
void DrawGraph_CopyStretch(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh);
|
||||
void DrawGraph_CopyStretchAMap(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh);
|
||||
|
||||
#endif /* SYSTEM4_SACT_H */
|
||||
|
||||
+44
-12
@@ -36,6 +36,18 @@ struct sact_sprite *sact_get_sprite(int sp)
|
||||
return sprites[sp];
|
||||
}
|
||||
|
||||
struct sact_sprite *get_surface(int no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(no);
|
||||
if (!sp)
|
||||
ERROR("Invalid sprite number: %d", no);
|
||||
if (!sp->cg->s)
|
||||
sp->cg->s = sdl_create_surface(sp->rect.w, sp->rect.h, &sp->color);
|
||||
if (!sp->cg->t)
|
||||
sp->cg->t = sdl_surface_to_texture(sp->cg->s);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static struct sact_sprite *alloc_sprite(int sp)
|
||||
{
|
||||
sprites[sp] = xcalloc(1, sizeof(struct sact_sprite));
|
||||
@@ -304,6 +316,28 @@ int sact_SP_SetZ(int sp_no, int z)
|
||||
|
||||
}
|
||||
|
||||
int sact_SP_SetDrawMethod(int sp_no, int method)
|
||||
{
|
||||
struct sact_sprite *sp = get_surface(sp_no);
|
||||
SDL_BlendMode mode;
|
||||
switch (method) {
|
||||
case 0:
|
||||
mode = SDL_BLENDMODE_BLEND;
|
||||
break;
|
||||
case 1:
|
||||
mode = SDL_BLENDMODE_ADD;
|
||||
break;
|
||||
case 2:
|
||||
mode = SDL_BLENDMODE_MOD;
|
||||
break;
|
||||
default:
|
||||
WARNING("SACT.SP_SetDrawMethod: unknown draw method: %d", method);
|
||||
return 0;
|
||||
}
|
||||
SDL_SetTextureBlendMode(sp->cg->t, mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sact_SP_ExistsAlpha(int sp_no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(sp_no);
|
||||
@@ -421,18 +455,6 @@ int sact_CG_GetMetrics(int cg_no, union vm_value *cgm)
|
||||
// --- DrawGraph.dll ---
|
||||
//
|
||||
|
||||
struct sact_sprite *get_surface(int no)
|
||||
{
|
||||
struct sact_sprite *sp = sact_get_sprite(no);
|
||||
if (!sp)
|
||||
ERROR("Invalid sprite number: %d", no);
|
||||
if (!sp->cg->s)
|
||||
sp->cg->s = sdl_create_surface(sp->rect.w, sp->rect.h, &sp->color);
|
||||
if (!sp->cg->t)
|
||||
sp->cg->t = sdl_surface_to_texture(sp->cg->s);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void DrawGraph_Copy(int dno, int dx, int dy, int sno, int sx, int sy, int w, int h)
|
||||
{
|
||||
sdl_copy(get_surface(dno)->cg, dx, dy, get_surface(sno)->cg, sx, sy, w, h);
|
||||
@@ -487,3 +509,13 @@ void DrawGraph_FillAMap(int sp_no, int x, int y, int w, int h, int a)
|
||||
{
|
||||
sdl_fill_amap(get_surface(sp_no)->cg, x, y, w, h, a);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyStretch(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh)
|
||||
{
|
||||
sdl_copy_stretch(get_surface(dst)->cg, dx, dy, dw, dh, get_surface(src)->cg, sx, sy, sw, sh);
|
||||
}
|
||||
|
||||
void DrawGraph_CopyStretchAMap(int dst, int dx, int dy, int dw, int dh, int src, int sx, int sy, int sw, int sh)
|
||||
{
|
||||
sdl_copy_stretch_amap(get_surface(dst)->cg, dx, dy, dw, dh, get_surface(src)->cg, sx, sy, sw, sh);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ void sdl_copy_amap_min(struct cg *dst, int dx, int dy, struct cg *src, int sx, i
|
||||
void sdl_fill(struct cg *dst, int x, int y, int w, int h, int r, int g, int b);
|
||||
void sdl_fill_alpha_color(struct cg *dst, int x, int y, int w, int h, int r, int g, int b, int a);
|
||||
void sdl_fill_amap(struct cg *dst, int x, int y, int w, int h, int a);
|
||||
void sdl_copy_stretch(struct cg *dst, int dx, int dy, int dw, int dh, struct cg *src, int sx, int sy, int sw, int sh);
|
||||
void sdl_copy_stretch_amap(struct cg *dst, int dx, int dy, int dw, int dh, struct cg *src, int sx, int sy, int sw, int sh);
|
||||
|
||||
enum font_weight {
|
||||
FW_NORMAL = 400,
|
||||
|
||||
+144
-83
@@ -68,6 +68,11 @@ static inline void PIXEL_SET_RGBA(uint32_t *p, uint8_t r, uint8_t g, uint8_t b,
|
||||
*p = (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT) | (a << A_SHIFT);
|
||||
}
|
||||
|
||||
static inline uint32_t PIXEL_MAP(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
return (r << R_SHIFT) | (g << G_SHIFT) | (b << B_SHIFT) | (a << A_SHIFT);
|
||||
}
|
||||
|
||||
// Clip src/dst rectangles in preparation for a copy.
|
||||
static void copy_clip_rects(int dw, int dh, int *dx, int *dy, int sw, int sh, int *sx, int *sy, int *w, int *h)
|
||||
{
|
||||
@@ -119,43 +124,61 @@ static inline uint32_t *get_pixel(SDL_Surface *s, int x, int y)
|
||||
return (uint32_t*)(((uint8_t*)s->pixels) + s->pitch*y + s->format->BytesPerPixel*x);
|
||||
}
|
||||
|
||||
typedef void(*pixel_op)(uint32_t *p, uint32_t data);
|
||||
typedef void(*pixel_op2)(uint32_t *dp, uint32_t *sp, uint32_t data);
|
||||
|
||||
// iterator for copy operations
|
||||
// FIXME: texture should be marked as dirty and updated later to avoid unnecessary copying
|
||||
#define copy_for_each_pixel(dcg, dx, dy, scg, sx, sy, w, h, dp, sp, expr) \
|
||||
do { \
|
||||
copy_clip_rects(dcg->s->w, dcg->s->h, &dx, &dy, scg->s->w, scg->s->h, &sx, &sy, &w, &h); \
|
||||
SDL_LockSurface(dcg->s); \
|
||||
SDL_LockSurface(scg->s); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *dp = get_pixel(dcg->s, dx, _row+dy); \
|
||||
uint32_t *sp = get_pixel(scg->s, sx, _row+sy); \
|
||||
for (int _col = 0; _col < w; _col++, dp++, sp++) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UpdateTexture(dcg->t, NULL, dcg->s->pixels, dcg->s->pitch); \
|
||||
SDL_UnlockSurface(scg->s); \
|
||||
SDL_UnlockSurface(dcg->s); \
|
||||
} while (0)
|
||||
static void for_each_pixel_pair(struct cg *dst, int dx, int dy, SDL_Surface *src, int sx, int sy, int w, int h, pixel_op2 op, uint32_t data)
|
||||
{
|
||||
copy_clip_rects(dst->s->w, dst->s->h, &dx, &dy, src->w, src->h, &sx, &sy, &w, &h);
|
||||
SDL_LockSurface(dst->s);
|
||||
SDL_LockSurface(src);
|
||||
for (int row = 0; row < h; row++) {
|
||||
uint32_t *dp = get_pixel(dst->s, dx, row+dy);
|
||||
uint32_t *sp = get_pixel(src, sx, row+sy);
|
||||
for (int col = 0; col < w; col++, dp++, sp++) {
|
||||
op(dp, sp, data);
|
||||
}
|
||||
}
|
||||
SDL_UpdateTexture(dst->t, NULL, dst->s->pixels, dst->s->pitch);
|
||||
SDL_UnlockSurface(src);
|
||||
SDL_UnlockSurface(dst->s);
|
||||
}
|
||||
|
||||
// iterator for fill operations
|
||||
#define fill_for_each_pixel(cg, x, y, w, h, p, expr) \
|
||||
do { \
|
||||
fill_clip_rect(&x, &y, cg->s->w, cg->s->h, &w, &h); \
|
||||
SDL_LockSurface(cg->s); \
|
||||
for (int _row = 0; _row < h; _row++) { \
|
||||
uint32_t *p = get_pixel(cg->s, x, _row+y); \
|
||||
for (int _col = 0; _col < w; _col++, p++) \
|
||||
expr; \
|
||||
} \
|
||||
SDL_UpdateTexture(cg->t, NULL, cg->s->pixels, cg->s->pitch); \
|
||||
SDL_UnlockSurface(cg->s); \
|
||||
} while(0);
|
||||
static void for_each_pixel(struct cg *dst, int x, int y, int w, int h, pixel_op op, uint32_t data)
|
||||
{
|
||||
fill_clip_rect(&x, &y, dst->s->w, dst->s->h, &w, &h);
|
||||
SDL_LockSurface(dst->s);
|
||||
for (int row = 0; row < h; row++) {
|
||||
uint32_t *p = get_pixel(dst->s, x, row+y);
|
||||
for (int col = 0; col < w; col++, p++) {
|
||||
op(p, data);
|
||||
}
|
||||
}
|
||||
SDL_UpdateTexture(dst->t, NULL, dst->s->pixels, dst->s->pitch);
|
||||
SDL_UnlockSurface(dst->s);
|
||||
}
|
||||
|
||||
static void sdl_blit(SDL_Surface *ds, int dx, int dy, SDL_Surface *ss, int sx, int sy, int w, int h)
|
||||
static void sdl_pixop_copy_color(uint32_t *dp, uint32_t *sp, possibly_unused uint32_t data)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
|
||||
static void sdl_pixop_copy_alpha(uint32_t *dp, uint32_t *sp, possibly_unused uint32_t data)
|
||||
{
|
||||
PIXEL_SET_A(dp, PIXEL_A(*sp));
|
||||
}
|
||||
|
||||
static void sdl_cg_blit(struct cg *dst, int dx, int dy, SDL_Surface *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
Rectangle src_rect = RECT(sx, sy, w, h);
|
||||
Rectangle dst_rect = RECT(dx, dy, w, h);
|
||||
SDL_BlitSurface(ss, &src_rect, ds, &dst_rect);
|
||||
SDL_BlitSurface(src, &src_rect, dst->s, &dst_rect);
|
||||
sdl_update_texture(dst->t, dst->s);
|
||||
}
|
||||
|
||||
void sdl_copy(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
@@ -163,7 +186,7 @@ void sdl_copy(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, in
|
||||
SDL_BlendMode mode;
|
||||
SDL_GetSurfaceBlendMode(src->s, &mode);
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
sdl_cg_blit(dst, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
}
|
||||
@@ -175,7 +198,7 @@ void sdl_copy_bright(struct cg *dst, int dx, int dy, struct cg *src, int sx, int
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
SDL_SetSurfaceColorMod(src->s, rate, rate, rate);
|
||||
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
sdl_cg_blit(dst, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetSurfaceColorMod(src->s, 255, 255, 255);
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
@@ -185,10 +208,7 @@ void sdl_copy_amap(struct cg *dst, int dx, int dy, struct cg *src, int sx, int s
|
||||
{
|
||||
if (!dst->has_alpha || !src->has_alpha)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
PIXEL_SET_A(dp, PIXEL_A(*sp));
|
||||
});
|
||||
for_each_pixel_pair(dst, dx, dy, src->s, sx, sy, w, h, sdl_pixop_copy_alpha, 0);
|
||||
}
|
||||
|
||||
void sdl_copy_sprite(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int r, int g, int b)
|
||||
@@ -199,99 +219,140 @@ void sdl_copy_sprite(struct cg *dst, int dx, int dy, struct cg *src, int sx, int
|
||||
SDL_SetSurfaceBlendMode(src->s, SDL_BLENDMODE_NONE);
|
||||
SDL_SetColorKey(src->s, SDL_TRUE, SDL_MapRGB(sdl.format, r, g, b));
|
||||
|
||||
sdl_blit(dst->s, dx, dy, src->s, sx, sy, w, h);
|
||||
sdl_cg_blit(dst, dx, dy, src->s, sx, sy, w, h);
|
||||
|
||||
SDL_SetColorKey(src->s, SDL_FALSE, 0);
|
||||
SDL_SetSurfaceBlendMode(src->s, mode);
|
||||
}
|
||||
|
||||
static void sdl_pixop_copy_use_amap_under(uint32_t *dp, uint32_t *sp, uint32_t threshold)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a <= threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_copy_use_amap_under(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
if (!src->has_alpha)
|
||||
return;
|
||||
for_each_pixel_pair(dst, dx, dy, src->s, sx, sy, w, h, sdl_pixop_copy_use_amap_under, a_threshold);
|
||||
}
|
||||
|
||||
static void sdl_pixop_copy_use_amap_border(uint32_t *dp, uint32_t *sp, uint32_t threshold)
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a <= a_threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
});
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a >= threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_copy_use_amap_border(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h, int a_threshold)
|
||||
{
|
||||
if (!src->has_alpha)
|
||||
return;
|
||||
for_each_pixel_pair(dst, dx, dy, src->s, sx, sy, w, h, sdl_pixop_copy_use_amap_border, a_threshold);
|
||||
}
|
||||
|
||||
uint8_t r, g, b, a;
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
SDL_GetRGBA(*sp, sdl.format, &r, &g, &b, &a);
|
||||
if (a >= a_threshold) {
|
||||
PIXEL_SET_RGB(dp, r, g, b);
|
||||
}
|
||||
});
|
||||
static void sdl_pixop_copy_amap_max(uint32_t *dp, uint32_t *sp, possibly_unused uint32_t data)
|
||||
{
|
||||
uint32_t d_a = PIXEL_A(*dp);
|
||||
uint32_t s_a = PIXEL_A(*sp);
|
||||
if (s_a > d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_copy_amap_max(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
if (!src->has_alpha || !dst->has_alpha)
|
||||
return;
|
||||
for_each_pixel_pair(dst, dx, dy, src->s, sx, sy, w, h, sdl_pixop_copy_amap_max, 0);
|
||||
}
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & sdl.format->Amask) >> sdl.format->Ashift;
|
||||
uint32_t s_a = (*sp & sdl.format->Amask) >> sdl.format->Ashift;
|
||||
if (s_a > d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
});
|
||||
static void sdl_pixop_copy_amap_min(uint32_t *dp, uint32_t *sp, possibly_unused uint32_t data)
|
||||
{
|
||||
uint32_t d_a = PIXEL_A(*dp);
|
||||
uint32_t s_a = PIXEL_A(*sp);
|
||||
if (s_a < d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_copy_amap_min(struct cg *dst, int dx, int dy, struct cg *src, int sx, int sy, int w, int h)
|
||||
{
|
||||
if (!src->has_alpha || !dst->has_alpha)
|
||||
return;
|
||||
|
||||
copy_for_each_pixel(dst, dx, dy, src, sx, sy, w, h, dp, sp, {
|
||||
uint32_t d_a = (*dp & A_MASK) >> A_SHIFT;
|
||||
uint32_t s_a = (*sp & A_MASK) >> A_SHIFT;
|
||||
if (s_a < d_a) {
|
||||
PIXEL_SET_A(dp, s_a);
|
||||
}
|
||||
});
|
||||
for_each_pixel_pair(dst, dx, dy, src->s, sx, sy, w, h, sdl_pixop_copy_amap_min, 0);
|
||||
}
|
||||
|
||||
static void blend_pixels(SDL_Color *dst, SDL_Color src)
|
||||
static uint32_t blend_pixels(uint32_t dst, uint32_t 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);
|
||||
uint32_t alpha = PIXEL_A(src) + 1;
|
||||
uint32_t inv_alpha = 256 - PIXEL_A(src);
|
||||
uint8_t r = (uint8_t)((alpha * PIXEL_R(src) + inv_alpha * PIXEL_R(dst)) >> 8);
|
||||
uint8_t g = (uint8_t)((alpha * PIXEL_G(src) + inv_alpha * PIXEL_G(dst)) >> 8);
|
||||
uint8_t b = (uint8_t)((alpha * PIXEL_B(src) + inv_alpha * PIXEL_B(dst)) >> 8);
|
||||
return PIXEL_MAP(r, g, b, PIXEL_A(dst));
|
||||
}
|
||||
|
||||
static void sdl_pixop_fill_rgb(uint32_t *p, uint32_t c)
|
||||
{
|
||||
PIXEL_SET_A(&c, PIXEL_A(*p));
|
||||
*p = c;
|
||||
}
|
||||
|
||||
void sdl_fill(struct cg *dst, int x, int y, int w, int h, int r, int g, int b)
|
||||
{
|
||||
fill_for_each_pixel(dst, x, y, w, h, p, {
|
||||
PIXEL_SET_RGBA(p, r, g, b, PIXEL_A(*p));
|
||||
});
|
||||
uint32_t c = SDL_MapRGB(sdl.format, r, g, b);
|
||||
for_each_pixel(dst, x, y, w, h, sdl_pixop_fill_rgb, c);
|
||||
}
|
||||
|
||||
static void sdl_pixop_fill_alpha_color(uint32_t *p, uint32_t c)
|
||||
{
|
||||
*p = blend_pixels(*p, c);
|
||||
}
|
||||
|
||||
// XXX: Despite being called a fill operation, this function actually performs blending.
|
||||
void sdl_fill_alpha_color(struct cg *cg, int x, int y, int w, int h, int r, int g, int b, int a)
|
||||
{
|
||||
SDL_Color dst;
|
||||
SDL_Color src = { .r = r, .g = g, .b = b, .a = a };
|
||||
fill_for_each_pixel(cg, x, y, w, h, p, {
|
||||
SDL_GetRGBA(*p, sdl.format, &dst.r, &dst.g, &dst.b, &dst.a);
|
||||
blend_pixels(&dst, src);
|
||||
PIXEL_SET_RGBA(p, dst.r, dst.g, dst.b, dst.a);
|
||||
});
|
||||
uint32_t c = SDL_MapRGBA(sdl.format, r, g, b, a);
|
||||
for_each_pixel(cg, x, y, w, h, sdl_pixop_fill_alpha_color, c);
|
||||
}
|
||||
|
||||
static void sdl_pixop_fill_alpha(uint32_t *p, uint32_t a)
|
||||
{
|
||||
PIXEL_SET_A(p, a);
|
||||
}
|
||||
|
||||
void sdl_fill_amap(struct cg *dst, int x, int y, int w, int h, int a)
|
||||
{
|
||||
fill_for_each_pixel(dst, x, y, w, h, p, {
|
||||
PIXEL_SET_A(p, a);
|
||||
});
|
||||
for_each_pixel(dst, x, y, w, h, sdl_pixop_fill_alpha, a);
|
||||
}
|
||||
|
||||
static SDL_Surface *sdl_stretch_surface(SDL_Surface *src, Rectangle *src_rect, int w, int h)
|
||||
{
|
||||
Rectangle dst_rect = RECT(0, 0, w, h);
|
||||
SDL_Surface *dst = sdl_create_surface(w, h, NULL);
|
||||
SDL_BlitScaled(src, src_rect, dst, &dst_rect);
|
||||
return dst;
|
||||
}
|
||||
|
||||
void sdl_copy_stretch(struct cg *dst, int dx, int dy, int dw, int dh, struct cg *src, int sx, int sy, int sw, int sh)
|
||||
{
|
||||
Rectangle s_rect = RECT(sx, sy, sw, sh);
|
||||
SDL_Surface *stretched = sdl_stretch_surface(src->s, &s_rect, dw, dh);
|
||||
for_each_pixel_pair(dst, dx, dy, stretched, 0, 0, dw, dh, sdl_pixop_copy_color, 0);
|
||||
SDL_FreeSurface(stretched);
|
||||
}
|
||||
|
||||
void sdl_copy_stretch_amap(struct cg *dst, int dx, int dy, int dw, int dh, struct cg *src, int sx, int sy, int sw, int sh)
|
||||
{
|
||||
Rectangle s_rect = RECT(sx, sy, sw, sh);
|
||||
SDL_Surface *stretched = sdl_stretch_surface(src->s, &s_rect, dw, dh);
|
||||
for_each_pixel_pair(dst, dx, dy, stretched, 0, 0, dw, dh, sdl_pixop_copy_alpha, 0);
|
||||
SDL_FreeSurface(stretched);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user