Refactor clipping functions

This commit is contained in:
kichikuou
2025-02-11 12:36:21 +09:00
parent f4f1a99372
commit bf26f1b0c0
4 changed files with 50 additions and 133 deletions
+12 -120
View File
@@ -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;
}
+28
View File
@@ -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;
}
+1
View File
@@ -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);
+9 -13
View File
@@ -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;