From bf26f1b0c04716aed3b3e12fa6ff435154c2b30a Mon Sep 17 00:00:00 2001 From: kichikuou Date: Tue, 11 Feb 2025 12:19:44 +0900 Subject: [PATCH] Refactor clipping functions --- modules/lib/graph.c | 132 ++++---------------------------------------- src/ags.c | 28 ++++++++++ src/ags.h | 1 + src/sdl_draw.c | 22 +++----- 4 files changed, 50 insertions(+), 133 deletions(-) diff --git a/modules/lib/graph.c b/modules/lib/graph.c index 49e795c..bcb3e45 100644 --- a/modules/lib/graph.c +++ b/modules/lib/graph.c @@ -9,20 +9,13 @@ #include "surface.h" #include "graph.h" #include "ngraph.h" -#include "nact.h" +#include "ags.h" /* gr_xxxx はクリッピングあり gre_xxxx はクリッピングなし */ -#undef WARNING -#define WARNING(...) - -#undef NOTICE -#define NOTICE(...) - - /** * surface から surface にコピーなどをする際に、転送元と転送先のsurface * の大きさや、転送元・転送先座標、転送する領域の大きさなどから、実際に @@ -42,74 +35,10 @@ * それぞれの引数は適宜変更されている */ bool gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, int *dx, int *dy) { - int w, h; - - if (ss == NULL) { - WARNING("ss surface is null"); - return false; - } - if (ss == NULL) { - WARNING("ss surface is null"); - return false; - } - - if (*sx > ss->width) { - WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width); - return false; - } - if (*sy > ss->height) { - WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height); - return false; - } - - if (*sx < 0) { - WARNING("sx is too small (sx=%d)", *sx); - return false; - } - if (*sy < 0) { - WARNING("sy is too small (sy=%d)", *sy); - return false; - } - - if (*dx > ds->width) { - WARNING("dx is too large (dx=%d,width=%d)", *dx, ds->width); - return false; - } - if (*dy > ds->height) { - WARNING("dy is too large (dy=%d,height=%d)", *dy, ds->height); - return false; - } - - w = *sw; - h = *sh; - - if (*dx < 0) { - *sx -= *dx; *sw += *dx; *dx = 0; - } - if (*dy < 0) { - *sy -= *dy; *sh += *dy; *dy = 0; - } - - *sw = min(ss->width - *sx, min(ds->width - *dx, *sw)); - *sh = min(ss->height - *sy, min(ds->height - *dy, *sh)); - - if (*sw <= 0) { - WARNING("sw become <=0"); - return false; - } - if (*sh <= 0) { - WARNING("sh become <=0"); - return false; - } - - if (*sw != w) { - NOTICE("width change %d -> %d", w, *sw); - } - if (*sh != h) { - NOTICE("height change %d -> %d", h, *sh); - } - - return true; + if (!ss || !ds) return false; + MyRectangle src_window = { 0, 0, ss->width, ss->height }; + MyRectangle dst_window = { 0, 0, ds->width, ds->height }; + return ags_clipCopyRect(&src_window, &dst_window, sx, sy, dx, dy, sw, sh); } /** @@ -126,51 +55,14 @@ bool gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, i * それぞれの引数は適宜変更されている */ bool gr_clip_xywh(surface_t *ss, int *sx, int *sy, int *sw, int *sh) { - int w, h; - - if (ss == NULL) { - WARNING("ss surface is null"); + if (!ss) return false; + SDL_Rect rect = {*sx, *sy, *sw, *sh}; + if (!SDL_IntersectRect(&rect, &(SDL_Rect){ 0, 0, ss->width, ss->height }, &rect)) return false; - } - - if (*sx > ss->width) { - WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width); - return false; - } - if (*sy > ss->height) { - WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height); - return false; - } - - w = *sw; - h = *sh; - - if (*sx < 0) { - *sw += *sx; *sx = 0; - } - if (*sy < 0) { - *sh += *sy; *sy = 0; - } - - *sw = min(ss->width - *sx, *sw); - *sh = min(ss->height - *sy, *sh); - - if (*sw <= 0) { - WARNING("sw become <=0"); - return false; - } - if (*sh <= 0) { - WARNING("sh become <=0"); - return false; - } - - if (*sw != w) { - NOTICE("width change %d -> %d", w, *sw); - } - if (*sh != h) { - NOTICE("height change %d -> %d", h, *sh); - } - + *sx = rect.x; + *sy = rect.y; + *sw = rect.w; + *sh = rect.h; return true; } diff --git a/src/ags.c b/src/ags.c index 8b8e6f0..92a8ef7 100644 --- a/src/ags.c +++ b/src/ags.c @@ -785,3 +785,31 @@ agsurface_t *ags_getDIB() { void ags_autorepeat(bool enable) { sdl_setAutoRepeat(enable); } + +bool ags_clipCopyRect(const MyRectangle *sw, const MyRectangle *dw, int *sx, int *sy, int *dx, int *dy, int *w, int *h) { + // Clip source rectangle to source window + SDL_Rect sr = {*sx, *sy, *w, *h}; + if (!SDL_IntersectRect(&sr, sw, &sr)) + return false; + + // Shift destination rectangle if source origin has changed + int dx_ = *dx + (sr.x - *sx); + int dy_ = *dy + (sr.y - *sy); + + // Clip destination rectangle to destination window + SDL_Rect dr = {dx_, dy_, sr.w, sr.h}; + if (!SDL_IntersectRect(&dr, dw, &dr)) + return false; + + // Shift source rectangle if destination origin has changed + sr.x += dr.x - dx_; + sr.y += dr.y - dy_; + + *sx = sr.x; + *sy = sr.y; + *w = dr.w; + *h = dr.h; + *dx = dr.x; + *dy = dr.y; + return true; +} diff --git a/src/ags.h b/src/ags.h index 7fde10f..ddb136f 100644 --- a/src/ags.h +++ b/src/ags.h @@ -230,6 +230,7 @@ extern int ags_getCursorMoveTime(); extern void ags_setAntialiasedStringMode(bool mode); extern bool ags_getAntialiasedStringMode(); extern void ags_autorepeat(bool enable); +extern bool ags_clipCopyRect(const MyRectangle *sr, const MyRectangle *dr, int *sx, int *sy, int *dx, int *dy, int *w, int *h); typedef void (*ags_EffectStepFunc)(void *, float); void ags_runEffect(int duration_ms, bool cancelable, ags_EffectStepFunc step, void *arg); diff --git a/src/sdl_draw.c b/src/sdl_draw.c index dbfa2f2..0685499 100644 --- a/src/sdl_draw.c +++ b/src/sdl_draw.c @@ -104,22 +104,18 @@ void sdl_wait_vsync() { /* off-screen の指定領域を Main Window へ転送 */ void sdl_updateArea(MyRectangle *rect, MyPoint *dst) { - SDL_Rect rs = {0, 0, sdl_dib->w, sdl_dib->h}; - if (!SDL_IntersectRect(rect, &rs, &rs)) + SDL_Rect sw = {0, 0, sdl_dib->w, sdl_dib->h}; + SDL_Rect dw = {0, 0, view_w, view_h}; + SDL_Rect sr = {rect->x, rect->y, rect->w, rect->h}; + SDL_Rect dr = {dst->x, dst->y, rect->w, rect->h}; + if (!ags_clipCopyRect(&sw, &dw, &sr.x, &sr.y, &dr.x, &dr.y, &sr.w, &sr.h)) return; - int dx = dst->x + (rs.x - rect->x); - int dy = dst->y + (rs.y - rect->y); - SDL_Rect rd = {dx, dy, rs.w, rs.h}; - if (!SDL_IntersectRect(&rd, &(SDL_Rect){0, 0, view_w, view_h}, &rd)) - return; - rs.x += rd.x - dx; - rs.y += rd.y - dy; - rs.w = rd.w; - rs.h = rd.h; + dr.w = sr.w; + dr.h = sr.h; SDL_Surface *sf; - SDL_LockTextureToSurface(sdl_texture, &rd, &sf); - SDL_BlitSurface(sdl_dib, &rs, sf, NULL); + SDL_LockTextureToSurface(sdl_texture, &dr, &sf); + SDL_BlitSurface(sdl_dib, &sr, sf, NULL); SDL_UnlockTexture(sdl_texture); sdl_dirty = true;