ltk

Socket-based GUI for X11 (WIP)
git clone git://lumidify.org/ltk.git (fast, but not encrypted)
git clone https://lumidify.org/git/ltk.git (encrypted, but very slow)
Log | Files | Refs | README | LICENSE

image_widget.c (4835B)


      1 /*
      2  * Copyright (c) 2023 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 <stdio.h>
     18 #include <stdlib.h>
     19 #include <stdint.h>
     20 #include <string.h>
     21 #include <stdarg.h>
     22 
     23 #include "event.h"
     24 #include "memory.h"
     25 #include "color.h"
     26 #include "rect.h"
     27 #include "widget.h"
     28 #include "ltk.h"
     29 #include "util.h"
     30 #include "image_widget.h"
     31 #include "graphics.h"
     32 #include "cmd.h"
     33 
     34 /* FIXME: add padding, etc. */
     35 
     36 static void ltk_image_widget_draw(
     37     ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip
     38 );
     39 static ltk_image_widget *ltk_image_widget_create(
     40     ltk_window *window, const char *id, const char *path, const char *data, size_t len
     41 );
     42 static void ltk_image_widget_destroy(ltk_widget *self, int shallow);
     43 
     44 static struct ltk_widget_vtable vtable = {
     45 	.draw = &ltk_image_widget_draw,
     46 	.destroy = &ltk_image_widget_destroy,
     47 	.hide = NULL,
     48 	.resize = NULL,
     49 	.change_state = NULL,
     50 	.child_size_change = NULL,
     51 	.remove_child = NULL,
     52 	.get_child_at_pos = NULL,
     53 	.key_press = NULL,
     54 	.key_release = NULL,
     55 	.mouse_press = NULL,
     56 	.mouse_release = NULL,
     57 	.motion_notify = NULL,
     58 	.mouse_leave = NULL,
     59 	.mouse_enter = NULL,
     60 	.type = LTK_WIDGET_IMAGE,
     61 	.flags = LTK_NEEDS_REDRAW | LTK_ACTIVATABLE_SPECIAL,
     62 };
     63 
     64 static void
     65 ltk_image_widget_draw(ltk_widget *self, ltk_surface *draw_surf, int x, int y, ltk_rect clip) {
     66 	ltk_image_widget *img = (ltk_image_widget *)self;
     67 	ltk_rect lrect = self->lrect;
     68 	ltk_rect clip_final = ltk_rect_intersect(clip, (ltk_rect){0, 0, lrect.w, lrect.h});
     69 	if (clip_final.w <= 0 || clip_final.h <= 0)
     70 		return;
     71 	/* FIXME: maybe replace with integer operations */
     72 	double scalex = self->ideal_w / (double)lrect.w;
     73 	double scaley = self->ideal_h / (double)lrect.h;
     74 	int src_x = (int)(clip_final.x * scalex);
     75 	int src_y = (int)(clip_final.y * scaley);
     76 	int src_w = (int)(clip_final.w * scalex);
     77 	int src_h = (int)(clip_final.h * scaley);
     78 	ltk_image_draw_cropped_scaled(
     79 	    img->img, draw_surf, src_x, src_y, src_w, src_h,
     80 	    x + clip_final.x, y + clip_final.y, clip_final.w, clip_final.h
     81 	);
     82 }
     83 
     84 static ltk_image_widget *
     85 ltk_image_widget_create(ltk_window *window, const char *id, const char *path, const char *data, size_t len) {
     86 	ltk_image_widget *img = ltk_malloc(sizeof(ltk_image_widget));
     87 	img->img = ltk_image_create_from_mem(path, data, len);
     88 	if (!img->img)
     89 		return NULL;
     90 	int w = ltk_image_get_width(img->img);
     91 	int h = ltk_image_get_height(img->img);
     92 	ltk_fill_widget_defaults(&img->widget, id, window, &vtable, w, h);
     93 	img->widget.ideal_w = w;
     94 	img->widget.ideal_h = h;
     95 
     96 	return img;
     97 }
     98 
     99 static void
    100 ltk_image_widget_destroy(ltk_widget *self, int shallow) {
    101 	(void)shallow;
    102 	ltk_image_widget *img = (ltk_image_widget *)self;
    103 	if (!img) {
    104 		ltk_warn("Tried to destroy NULL image widget.\n");
    105 		return;
    106 	}
    107 	ltk_image_destroy(img->img);
    108 	ltk_free(img);
    109 }
    110 
    111 /* image <image id> create <filename> <data> */
    112 static int
    113 ltk_image_widget_cmd_create(
    114     ltk_window *window,
    115     ltk_image_widget *img_unneeded,
    116     ltk_cmd_token *tokens,
    117     size_t num_tokens,
    118     ltk_error *err) {
    119 	(void)img_unneeded;
    120 	ltk_cmdarg_parseinfo cmd[] = {
    121 		{.type = CMDARG_IGNORE, .optional = 0},
    122 		{.type = CMDARG_STRING, .optional = 0},
    123 		{.type = CMDARG_IGNORE, .optional = 0},
    124 		{.type = CMDARG_STRING, .optional = 0},
    125 		{.type = CMDARG_DATA, .optional = 0},
    126 	};
    127 	if (ltk_parse_cmd(window, tokens, num_tokens, cmd, LENGTH(cmd), err))
    128 		return 1;
    129 	if (!ltk_widget_id_free(cmd[1].val.str)) {
    130 		err->type = ERR_WIDGET_ID_IN_USE;
    131 		err->arg = 1;
    132 		return 1;
    133 	}
    134 	ltk_image_widget *img = ltk_image_widget_create(window, cmd[1].val.str, cmd[3].val.str, cmd[4].val.data, cmd[4].len);
    135 	if (!img) {
    136 		/* FIXME: more sensible error name */
    137 		err->type = ERR_UNKNOWN;
    138 		err->arg = -1;
    139 		return 1;
    140 	}
    141 	ltk_set_widget((ltk_widget *)img, cmd[1].val.str);
    142 
    143 	return 0;
    144 }
    145 
    146 static struct image_widget_cmd {
    147 	char *name;
    148 	int (*func)(ltk_window *, ltk_image_widget *, ltk_cmd_token *, size_t, ltk_error *);
    149 	int needs_all;
    150 } image_widget_cmds[] = {
    151 	{"create", &ltk_image_widget_cmd_create, 1},
    152 };
    153 
    154 GEN_CMD_HELPERS(ltk_image_widget_cmd, LTK_WIDGET_IMAGE, ltk_image_widget, image_widget_cmds, struct image_widget_cmd)