Use clipping functions provided by SDL (#1426)

This commit is contained in:
Guldoman 2023-03-14 16:39:00 +01:00 committed by takase1121
parent 1d0725f904
commit a61531dbf0
No known key found for this signature in database
GPG Key ID: 60EEFFC68EB3031B
3 changed files with 18 additions and 20 deletions

View File

@ -378,7 +378,8 @@ double ren_font_group_get_width(RenWindow *window_renderer, RenFont **fonts, con
double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) { double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) {
SDL_Surface *surface = renwin_get_surface(window_renderer); SDL_Surface *surface = renwin_get_surface(window_renderer);
const RenRect clip = window_renderer->clip; SDL_Rect clip;
SDL_GetClipRect(surface, &clip);
const int surface_scale = renwin_surface_scale(window_renderer); const int surface_scale = renwin_surface_scale(window_renderer);
double pen_x = x * surface_scale; double pen_x = x * surface_scale;
@ -386,7 +387,7 @@ double ren_draw_text(RenWindow *window_renderer, RenFont **fonts, const char *te
int bytes_per_pixel = surface->format->BytesPerPixel; int bytes_per_pixel = surface->format->BytesPerPixel;
const char* end = text + len; const char* end = text + len;
uint8_t* destination_pixels = surface->pixels; uint8_t* destination_pixels = surface->pixels;
int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height; int clip_end_x = clip.x + clip.w, clip_end_y = clip.y + clip.h;
RenFont* last = NULL; RenFont* last = NULL;
double last_pen_x = x; double last_pen_x = x;
@ -479,28 +480,24 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) {
void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) { void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) {
if (color.a == 0) { return; } if (color.a == 0) { return; }
SDL_Surface *surface = renwin_get_surface(window_renderer);
const int surface_scale = renwin_surface_scale(window_renderer); const int surface_scale = renwin_surface_scale(window_renderer);
/* transforms coordinates in pixels. */ SDL_Rect dest_rect = { rect.x * surface_scale,
rect.x *= surface_scale; rect.y * surface_scale,
rect.y *= surface_scale; rect.width * surface_scale,
rect.width *= surface_scale; rect.height * surface_scale };
rect.height *= surface_scale;
const RenRect clip = window_renderer->clip;
int x1 = rect.x < clip.x ? clip.x : rect.x;
int y1 = rect.y < clip.y ? clip.y : rect.y;
int x2 = rect.x + rect.width;
int y2 = rect.y + rect.height;
x2 = x2 > clip.x + clip.width ? clip.x + clip.width : x2;
y2 = y2 > clip.y + clip.height ? clip.y + clip.height : y2;
SDL_Surface *surface = renwin_get_surface(window_renderer);
SDL_Rect dest_rect = { x1, y1, x2 - x1, y2 - y1 };
if (color.a == 0xff) { if (color.a == 0xff) {
uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b); uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b);
SDL_FillRect(surface, &dest_rect, translated); SDL_FillRect(surface, &dest_rect, translated);
} else { } else {
// Seems like SDL doesn't handle clipping as we expect when using
// scaled blitting, so we "clip" manually.
SDL_Rect clip;
SDL_GetClipRect(surface, &clip);
if (!SDL_IntersectRect(&clip, &dest_rect, &dest_rect)) return;
uint32_t *pixel = (uint32_t *)draw_rect_surface->pixels; uint32_t *pixel = (uint32_t *)draw_rect_surface->pixels;
*pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a); *pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a);
SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect); SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect);

View File

@ -61,12 +61,14 @@ static RenRect scaled_rect(const RenRect rect, const int scale) {
void renwin_clip_to_surface(RenWindow *ren) { void renwin_clip_to_surface(RenWindow *ren) {
SDL_Surface *surface = renwin_get_surface(ren); SDL_Surface *surface = renwin_get_surface(ren);
ren->clip = (RenRect) {0, 0, surface->w, surface->h}; SDL_SetClipRect(surface, NULL);
} }
void renwin_set_clip_rect(RenWindow *ren, RenRect rect) { void renwin_set_clip_rect(RenWindow *ren, RenRect rect) {
ren->clip = scaled_rect(rect, renwin_surface_scale(ren)); SDL_Surface *surface = renwin_get_surface(ren);
RenRect sr = scaled_rect(rect, renwin_surface_scale(ren));
SDL_SetClipRect(surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height});
} }

View File

@ -3,7 +3,6 @@
struct RenWindow { struct RenWindow {
SDL_Window *window; SDL_Window *window;
RenRect clip; /* Clipping rect in pixel coordinates. */
#ifdef LITE_USE_SDL_RENDERER #ifdef LITE_USE_SDL_RENDERER
SDL_Renderer *renderer; SDL_Renderer *renderer;
SDL_Texture *texture; SDL_Texture *texture;