Use clipping functions provided by SDL (#1426)

This commit is contained in:
Guldoman 2023-03-14 16:39:00 +01:00 committed by George Sokianos
parent ca29728e34
commit 94e2df991c
3 changed files with 21 additions and 30 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) {
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);
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;
const char* end = text + len;
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;
double last_pen_x = x;
@ -479,39 +480,28 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) {
void ren_draw_rect(RenWindow *window_renderer, RenRect rect, RenColor color) {
if (color.a == 0) { return; }
SDL_Surface *surface = renwin_get_surface(window_renderer);
const int surface_scale = renwin_surface_scale(window_renderer);
/* transforms coordinates in pixels. */
rect.x *= surface_scale;
rect.y *= surface_scale;
rect.width *= surface_scale;
rect.height *= surface_scale;
SDL_Rect dest_rect = { rect.x * surface_scale,
rect.y * surface_scale,
rect.width * 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) {
uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b);
SDL_Rect rect = { x1, y1, x2 - x1, y2 - y1 };
SDL_FillRect(surface, &rect, translated);
} else {
RenColor current_color;
RenColor blended_color;
for (int j = y1; j < y2; j++) {
for (int i = x1; i < x2; i++, d++) {
SDL_GetRGB(*d, surface->format, &current_color.r, &current_color.g, &current_color.b);
blended_color = blend_pixel(current_color, color);
*d = SDL_MapRGB(surface->format, blended_color.r, blended_color.g, blended_color.b);
}
d += dr;
}
// 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;
*pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a);
SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect);
}
}

View File

@ -73,12 +73,14 @@ static RenRect scaled_rect(const RenRect rect, const int scale) {
void renwin_clip_to_surface(RenWindow *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) {
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 {
SDL_Window *window;
RenRect clip; /* Clipping rect in pixel coordinates. */
#ifdef LITE_USE_SDL_RENDERER
SDL_Renderer *renderer;
SDL_Texture *texture;