image_widget.c (3242B)
1 /* 2 * Copyright (c) 2023-2024 lumidify <nobody@lumidify.org> 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <stddef.h> 18 19 #include "image_widget.h" 20 #include "graphics.h" 21 #include "memory.h" 22 #include "rect.h" 23 #include "util.h" 24 #include "widget.h" 25 26 /* FIXME: add padding, etc. */ 27 28 static void ltk_image_widget_draw( 29 ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip 30 ); 31 static void ltk_image_widget_destroy(ltk_widget *self, int shallow); 32 33 static struct ltk_widget_vtable vtable = { 34 .draw = <k_image_widget_draw, 35 .destroy = <k_image_widget_destroy, 36 .hide = NULL, 37 .resize = NULL, 38 .change_state = NULL, 39 .child_size_change = NULL, 40 .remove_child = NULL, 41 .get_child_at_pos = NULL, 42 .key_press = NULL, 43 .key_release = NULL, 44 .mouse_press = NULL, 45 .mouse_release = NULL, 46 .motion_notify = NULL, 47 .mouse_leave = NULL, 48 .mouse_enter = NULL, 49 .type = LTK_WIDGET_IMAGE, 50 /* FIXME: need to show that it is activated somehow in special mode */ 51 .flags = LTK_NEEDS_REDRAW | LTK_ACTIVATABLE_SPECIAL, 52 }; 53 54 static void 55 ltk_image_widget_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip) { 56 ltk_image_widget *img = LTK_CAST_IMAGE_WIDGET(self); 57 ltk_rect lrect = self->lrect; 58 ltk_rect clip_final = ltk_rect_intersect(clip, (ltk_rect){0, 0, lrect.w, lrect.h}); 59 if (clip_final.w <= 0 || clip_final.h <= 0) 60 return; 61 /* FIXME: maybe replace with integer operations */ 62 double scalex = self->ideal_w / (double)lrect.w; 63 double scaley = self->ideal_h / (double)lrect.h; 64 int src_x = (int)(clip_final.x * scalex); 65 int src_y = (int)(clip_final.y * scaley); 66 int src_w = (int)(clip_final.w * scalex); 67 int src_h = (int)(clip_final.h * scaley); 68 ltk_image_draw_cropped_scaled( 69 img->img, draw_surf, src_x, src_y, src_w, src_h, 70 x + clip_final.x, y + clip_final.y, clip_final.w, clip_final.h 71 ); 72 } 73 74 ltk_image_widget * 75 ltk_image_widget_create(ltk_window *window, ltk_image *img) { 76 ltk_image_widget *imw = ltk_malloc(sizeof(ltk_image_widget)); 77 imw->img = img; 78 int w = ltk_image_get_width(imw->img); 79 int h = ltk_image_get_height(imw->img); 80 ltk_fill_widget_defaults(&imw->widget, window, &vtable, w, h); 81 imw->widget.ideal_w = w; 82 imw->widget.ideal_h = h; 83 84 return imw; 85 } 86 87 static void 88 ltk_image_widget_destroy(ltk_widget *self, int shallow) { 89 (void)shallow; 90 ltk_image_widget *img = LTK_CAST_IMAGE_WIDGET(self); 91 /* FIXME: make warnings like this consistent across widgets */ 92 if (!img) { 93 ltk_warn("Tried to destroy NULL image widget.\n"); 94 return; 95 } 96 ltk_image_destroy(img->img); 97 ltk_free(img); 98 }