From b2b8e68046032f16bab4bbcf2a043e4c60a0fd62 Mon Sep 17 00:00:00 2001 From: Patrick Jakobsen Date: Thu, 28 Sep 2023 13:37:27 +0200 Subject: [PATCH] Started on clipping --- gui/gui.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 12 deletions(-) diff --git a/gui/gui.c b/gui/gui.c index 78efba3..08a0350 100644 --- a/gui/gui.c +++ b/gui/gui.c @@ -192,8 +192,7 @@ struct GUI_Subtree { RDIC_Context rdic; - // TODO(Zelaven): - // GUI_Rectangle cliprect; + GUI_Node_Reference clipnode; GUI_Node_Reference relative_to; int flat_offset_x; @@ -691,6 +690,7 @@ GUI_Node_Reference gui_push_subtree( //subtree->structural_parent = context->current_subtree; //context->current_subtree = subtree; subtree.node->relative_to = relative_to; + subtree.node->clipnode = relative_to; GUI_Node_Reference new_root_reference = { .rdic_ref = rdic_context_start_frame( @@ -1720,7 +1720,7 @@ void test_gui__subtree( context, middle_subtree, middle_subtree_root, GUI_LAYOUT_VERTICAL, &element_style, test_size, middle); { - static GUI_Color test_image_pixels[10*10] = { + static GUI_Color test_image_pixels[10*12] = { 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, @@ -1731,11 +1731,13 @@ void test_gui__subtree( ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, ~0, 0, + ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, + ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, }; static Pixel_Buffer test_image = { .pixels = test_image_pixels, .width = 10, - .height = 10, + .height = 12, }; static GUI_Node_Reference inner_top = {0}; inner_top = gui_dumb_block(context, inner_top, &outer_style, element_size); @@ -2072,6 +2074,7 @@ void draw_rect3( } } + #define SET_PIXEL(pixel_buffer, x, y, color) (pixel_buffer)->pixels[(y)*(pixel_buffer)->width + (x)] = (color) #define GET_PIXEL(pixel_buffer, x, y) (pixel_buffer)->pixels[(y)*(pixel_buffer)->width + (x)] @@ -3263,8 +3266,6 @@ void gui_draw_image( return; } - // TODO(Zelaven): Clipping. - int off_x = draw_command->rectangle.x0; int off_y = draw_command->rectangle.y0; Pixel_Buffer *image = draw_command->image; @@ -3284,7 +3285,109 @@ void gui_draw_image( } } +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +void gui_draw_image_clipped( + Pixel_Buffer *pixel_buffer, + GUI_Draw_Command *draw_command, + GUI_Rectangle *cliprect) +{ + if(draw_command->image == NULL) { + return; + } + + //int off_x = cliprect->x0; + //int off_y = cliprect->y0; + Pixel_Buffer *image = draw_command->image; + int w = image->width; + int clipwidth = cliprect->x1 - cliprect->x0; + w = MIN(w, clipwidth); + int h = image->height; + int clipheight = cliprect->y1 - cliprect->y0; + h = MIN(h, clipheight); + + int startx = cliprect->x0 - draw_command->rectangle.x0; + startx = MAX(startx, 0); + int starty = cliprect->y0 - draw_command->rectangle.y0; + starty = MAX(starty, 0); + int off_x = cliprect->x0 - startx; + int off_y = cliprect->y0 - starty; + + for(int j=starty; j < h; ++j) + { + for(int i=startx; i < w; ++i) + { + int image_x = i; + int image_y = j; + int image_index = image_y * w + image_x; + GUI_Color pixel = image->pixels[image_index]; + SET_PIXEL(pixel_buffer, off_x+i, off_y+j, pixel); + } + } +} + +GUI_Rectangle gui_intersect_rectangles( + GUI_Rectangle *r1, + GUI_Rectangle *r2) +{ + GUI_Rectangle r = { + .x0 = MAX(r1->x0, r2->x0), + .x1 = MIN(r1->x1, r2->x1), + .y0 = MAX(r1->y0, r2->y0), + .y1 = MIN(r1->y1, r2->y1), + }; + return r; + +} +void gui_draw_rect_clipped( + Pixel_Buffer *pixel_buffer, + GUI_Draw_Command *draw_command, + GUI_Rectangle *clip) +{ + if(clip->x0 <= draw_command->rectangle.x0 + && clip->y0 <= draw_command->rectangle.y0 + && clip->x1 <= draw_command->rectangle.x1 + && clip->y1 <= draw_command->rectangle.y1) + { + gui_draw_rect(pixel_buffer, draw_command); + } + else + { + if(draw_command->roundedness == 0) + { + GUI_Rectangle clipped_rect = gui_intersect_rectangles( + clip, + &draw_command->rectangle); + // TODO(Zelaven) Don't double-draw on the space covered by the inner + // rectangle. + draw_rect3( + pixel_buffer, clipped_rect, draw_command->border_color); + GUI_Rectangle inner = clipped_rect; + inner.x0 += draw_command->border_thickness; + inner.y0 += draw_command->border_thickness; + inner.x1 -= draw_command->border_thickness; + inner.y1 -= draw_command->border_thickness; + if(inner.x0 < inner.x1 && inner.y0 < inner.y1) + { + draw_rect3(pixel_buffer, inner, draw_command->color); + } + } + else + { + assert(!"TODO"); + if(draw_command->border_thickness == 0) + { + gui_draw_rounded_rect(pixel_buffer, draw_command); + } + else + { + gui_draw_rounded_rect_with_border(pixel_buffer, draw_command); + } + } + } +} //CURSOR void gui_layout_and_draw_subtree( GUI_Context *context, @@ -3299,12 +3402,26 @@ void gui_layout_and_draw_subtree( GUI_Draw_Command *draw_commands = (GUI_Draw_Command*)(context->draw_command_arena->memory); - for(int i = 0; i < context->num_draw_commands; i++) - { - GUI_Draw_Command *draw_command = draw_commands+i; - gui_draw_rect (pixel_buffer, draw_command); - gui_draw_image(pixel_buffer, draw_command); - gui_draw_text (pixel_buffer, draw_command); + GUI_Node_Reference clipnode = subtree->clipnode; + if(rdic_node_reference_valid(clipnode.rdic_ref)) { + GUI_Rectangle *cliprect = &clipnode.node->rect; + for(int i = 0; i < context->num_draw_commands; i++) + { + GUI_Draw_Command *draw_command = draw_commands+i; + gui_draw_rect_clipped(pixel_buffer, draw_command, cliprect); + //gui_draw_image(pixel_buffer, draw_command);//, cliprect); + gui_draw_image_clipped(pixel_buffer, draw_command, cliprect); + gui_draw_text (pixel_buffer, draw_command);//, cliprect); + } + } + else { + for(int i = 0; i < context->num_draw_commands; i++) + { + GUI_Draw_Command *draw_command = draw_commands+i; + gui_draw_rect (pixel_buffer, draw_command); + gui_draw_image(pixel_buffer, draw_command); + gui_draw_text (pixel_buffer, draw_command); + } } // TODO NOTE(Zelaven): There may arise an issue where the subtrees won't