image widget
many assumptions about X backed were made, to be refined if does not work properly in some setups
This commit is contained in:
@@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
|
|||||||
|
|
||||||
#CFLAGS += -O3 -ffast-math -fomit-frame-pointer
|
#CFLAGS += -O3 -ffast-math -fomit-frame-pointer
|
||||||
|
|
||||||
LIBS=-lX11 -lm
|
LIBS=-lX11 -lm -lpng
|
||||||
|
|
||||||
tracer_remote: remote_old.o plot.o database.o gui.o utils.o gui/gui.a
|
tracer_remote: remote_old.o plot.o database.o gui.o utils.o gui/gui.a
|
||||||
$(CC) $(CFLAGS) -o tracer_remote $^ $(LIBS)
|
$(CC) $(CFLAGS) -o tracer_remote $^ $(LIBS)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ CFLAGS=-Wall -g -pthread
|
|||||||
|
|
||||||
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
OBJS=init.o loop.o toplevel_window.o x.o container.o widget.o \
|
||||||
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
|
gui.o label.o event.o xy_plot.o textlist.o notify.o positioner.o \
|
||||||
timeline.o space.o
|
timeline.o space.o image.o
|
||||||
|
|
||||||
gui.a: $(OBJS)
|
gui.a: $(OBJS)
|
||||||
ar cr gui.a $(OBJS)
|
ar cr gui.a $(OBJS)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ widget *new_textlist(gui *gui, int width, int nlines, int background_color);
|
|||||||
widget *new_timeline(gui *gui, int width, int number_of_sublines,
|
widget *new_timeline(gui *gui, int width, int number_of_sublines,
|
||||||
int subline_height);
|
int subline_height);
|
||||||
widget *new_space(gui *gui, int width, int height);
|
widget *new_space(gui *gui, int width, int height);
|
||||||
|
widget *new_image(gui *gui, unsigned char *data, int length);
|
||||||
|
|
||||||
void label_set_clickable(gui *gui, widget *label, int clickable);
|
void label_set_clickable(gui *gui, widget *label, int clickable);
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ extern int volatile gui_logd;
|
|||||||
|
|
||||||
enum widget_type {
|
enum widget_type {
|
||||||
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
|
TOPLEVEL_WINDOW, CONTAINER, POSITIONER, TEXT_LIST, XY_PLOT, BUTTON, LABEL,
|
||||||
TIMELINE, SPACE
|
TIMELINE, SPACE, IMAGE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct widget_list;
|
struct widget_list;
|
||||||
@@ -154,6 +154,13 @@ struct space_widget {
|
|||||||
int wanted_height;
|
int wanted_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct image_widget {
|
||||||
|
struct widget common;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
void *x; /* opaque X data (type x_image), used in x.c */
|
||||||
|
};
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* events */
|
/* events */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
#include "gui.h"
|
||||||
|
#include "gui_defs.h"
|
||||||
|
#include "x.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
static void paint(gui *_gui, widget *_w)
|
||||||
|
{
|
||||||
|
struct gui *g = _gui;
|
||||||
|
struct image_widget *w = _w;
|
||||||
|
x_draw_image(g->x, g->xwin, w->x, w->common.x, w->common.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hints(gui *_gui, widget *_w, int *width, int *height)
|
||||||
|
{
|
||||||
|
struct image_widget *w = _w;
|
||||||
|
LOGD("HINTS image %p\n", w);
|
||||||
|
*width = w->width;
|
||||||
|
*height = w->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct png_reader {
|
||||||
|
unsigned char *data;
|
||||||
|
int size;
|
||||||
|
int pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void png_readfn(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
|
{
|
||||||
|
struct png_reader *r = png_get_io_ptr(png_ptr);
|
||||||
|
if (length > r->size - r->pos) png_error(png_ptr, "bad png image");
|
||||||
|
memcpy(data, r->data + r->pos, length);
|
||||||
|
r->pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_image(struct gui *g, struct image_widget *w,
|
||||||
|
unsigned char *data, int length)
|
||||||
|
{
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop info_ptr;
|
||||||
|
png_bytepp image;
|
||||||
|
int width, height, bit_depth, color_type, channels;
|
||||||
|
unsigned char *img_data;
|
||||||
|
struct png_reader r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* unpack PNG data */
|
||||||
|
|
||||||
|
r.data = data;
|
||||||
|
r.size = length;
|
||||||
|
r.pos = 0;
|
||||||
|
|
||||||
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||||
|
if (png_ptr == NULL) abort();
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (info_ptr == NULL) abort();
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) abort();
|
||||||
|
|
||||||
|
png_set_read_fn(png_ptr, &r, png_readfn);
|
||||||
|
|
||||||
|
png_read_png(png_ptr, info_ptr,
|
||||||
|
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING |
|
||||||
|
PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL);
|
||||||
|
|
||||||
|
image = png_get_rows(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||||
|
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||||
|
channels = png_get_channels(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
if (width < 1 || width > 1000 || height < 1 || height > 1000 ||
|
||||||
|
bit_depth != 8 || color_type != PNG_COLOR_TYPE_RGBA || channels != 4)
|
||||||
|
{ printf("bad image\n"); abort(); }
|
||||||
|
|
||||||
|
img_data = malloc(4 * width * height); if (img_data == NULL) abort();
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
memcpy(img_data+i*4*width, image[i], width*4);
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
||||||
|
/* create the X image */
|
||||||
|
w->x = x_create_image(g->x, img_data, width, height);
|
||||||
|
|
||||||
|
free(img_data);
|
||||||
|
|
||||||
|
w->width = width;
|
||||||
|
w->height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget *new_image(gui *_gui, unsigned char *data, int length)
|
||||||
|
{
|
||||||
|
struct gui *g = _gui;
|
||||||
|
struct image_widget *w;
|
||||||
|
|
||||||
|
glock(g);
|
||||||
|
|
||||||
|
w = new_widget(g, IMAGE, sizeof(struct image_widget));
|
||||||
|
|
||||||
|
load_image(g, w, data, length);
|
||||||
|
|
||||||
|
w->common.paint = paint;
|
||||||
|
w->common.hints = hints;
|
||||||
|
|
||||||
|
gunlock(g);
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
@@ -265,7 +265,7 @@ void widget_dirty(gui *_gui, widget *_this)
|
|||||||
|
|
||||||
static const char *names[] = {
|
static const char *names[] = {
|
||||||
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
|
"TOPLEVEL_WINDOW", "CONTAINER", "POSITIONER", "TEXT_LIST",
|
||||||
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE"
|
"XY_PLOT", "BUTTON", "LABEL", "TIMELINE", "SPACE", "IMAGE"
|
||||||
};
|
};
|
||||||
const char *widget_name(enum widget_type type)
|
const char *widget_name(enum widget_type type)
|
||||||
{
|
{
|
||||||
@@ -279,6 +279,7 @@ const char *widget_name(enum widget_type type)
|
|||||||
case LABEL:
|
case LABEL:
|
||||||
case TIMELINE:
|
case TIMELINE:
|
||||||
case SPACE:
|
case SPACE:
|
||||||
|
case IMAGE:
|
||||||
return names[type];
|
return names[type];
|
||||||
}
|
}
|
||||||
return "UNKNOWN (error)";
|
return "UNKNOWN (error)";
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "x_defs.h"
|
#include "x_defs.h"
|
||||||
#include "gui_defs.h"
|
#include "gui_defs.h"
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -111,6 +112,52 @@ x_window *x_create_window(x_connection *_x, int width, int height,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x_image *x_create_image(x_connection *_x, unsigned char *data,
|
||||||
|
int width, int height)
|
||||||
|
{
|
||||||
|
struct x_connection *x = _x;
|
||||||
|
struct x_image *ret;
|
||||||
|
XImage *ximage;
|
||||||
|
XVisualInfo *vs;
|
||||||
|
XVisualInfo template;
|
||||||
|
int nvs;
|
||||||
|
Visual *v;
|
||||||
|
|
||||||
|
ret = calloc(1, sizeof(struct x_image)); if (ret == NULL) OOM;
|
||||||
|
|
||||||
|
template.class = TrueColor;
|
||||||
|
template.depth = 24;
|
||||||
|
template.red_mask = 0xff0000;
|
||||||
|
template.green_mask = 0x00ff00;
|
||||||
|
template.blue_mask = 0x0000ff;
|
||||||
|
template.bits_per_rgb = 8;
|
||||||
|
|
||||||
|
vs = XGetVisualInfo(x->d, VisualDepthMask | VisualClassMask |
|
||||||
|
VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask |
|
||||||
|
VisualBitsPerRGBMask, &template, &nvs);
|
||||||
|
if (vs == NULL || nvs == 0) ERR("no good visual found\n");
|
||||||
|
v = vs[0].visual;
|
||||||
|
XFree(vs);
|
||||||
|
|
||||||
|
ximage = XCreateImage(x->d, v, 24, ZPixmap, 0,
|
||||||
|
(char*)data, width, height, 32, 0);
|
||||||
|
if (ximage == NULL) ERR("image creation failed\n");
|
||||||
|
|
||||||
|
ret->p = XCreatePixmap(x->d, DefaultRootWindow(x->d), width, height, 24);
|
||||||
|
|
||||||
|
XPutImage(x->d, ret->p, DefaultGC(x->d, DefaultScreen(x->d)),
|
||||||
|
ximage, 0, 0, 0, 0, width, height);
|
||||||
|
|
||||||
|
/* TODO: be sure it's fine to set data to NULL */
|
||||||
|
ximage->data = NULL;
|
||||||
|
XDestroyImage(ximage);
|
||||||
|
|
||||||
|
ret->width = width;
|
||||||
|
ret->height = height;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static struct toplevel_window_widget *find_x_window(struct gui *g, Window id)
|
static struct toplevel_window_widget *find_x_window(struct gui *g, Window id)
|
||||||
{
|
{
|
||||||
struct widget_list *cur;
|
struct widget_list *cur;
|
||||||
@@ -312,6 +359,16 @@ void x_draw_clipped_string(x_connection *_c, x_window *_w, int color,
|
|||||||
XSetClipMask(c->d, c->colors[color], None);
|
XSetClipMask(c->d, c->colors[color], None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void x_draw_image(x_connection *_c, x_window *_w, x_image *_img, int x, int y)
|
||||||
|
{
|
||||||
|
struct x_connection *c = _c;
|
||||||
|
struct x_window *w = _w;
|
||||||
|
struct x_image *img = _img;
|
||||||
|
|
||||||
|
XCopyArea(c->d, img->p, w->p, DefaultGC(c->d, DefaultScreen(c->d)),
|
||||||
|
0, 0, img->width, img->height, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
void x_draw(x_connection *_c, x_window *_w)
|
void x_draw(x_connection *_c, x_window *_w)
|
||||||
{
|
{
|
||||||
struct x_connection *c = _c;
|
struct x_connection *c = _c;
|
||||||
|
|||||||
@@ -5,12 +5,16 @@
|
|||||||
|
|
||||||
typedef void x_connection;
|
typedef void x_connection;
|
||||||
typedef void x_window;
|
typedef void x_window;
|
||||||
|
typedef void x_image;
|
||||||
|
|
||||||
x_connection *x_open(void);
|
x_connection *x_open(void);
|
||||||
|
|
||||||
x_window *x_create_window(x_connection *x, int width, int height,
|
x_window *x_create_window(x_connection *x, int width, int height,
|
||||||
char *title);
|
char *title);
|
||||||
|
|
||||||
|
x_image *x_create_image(x_connection *x, unsigned char *data,
|
||||||
|
int width, int height);
|
||||||
|
|
||||||
int x_connection_fd(x_connection *x);
|
int x_connection_fd(x_connection *x);
|
||||||
|
|
||||||
void x_flush(x_connection *x);
|
void x_flush(x_connection *x);
|
||||||
@@ -42,6 +46,8 @@ void x_draw_clipped_string(x_connection *_c, x_window *_w, int color,
|
|||||||
int x, int y, const char *t,
|
int x, int y, const char *t,
|
||||||
int clipx, int clipy, int clipwidth, int clipheight);
|
int clipx, int clipy, int clipwidth, int clipheight);
|
||||||
|
|
||||||
|
void x_draw_image(x_connection *c, x_window *w, x_image *img, int x, int y);
|
||||||
|
|
||||||
/* specials functions to plot many points
|
/* specials functions to plot many points
|
||||||
* you call several times x_add_point() then x_plot_points()
|
* you call several times x_add_point() then x_plot_points()
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,4 +23,10 @@ struct x_window {
|
|||||||
int resize, new_width, new_height;
|
int resize, new_width, new_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct x_image {
|
||||||
|
Pixmap p;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _X_DEFS_H_ */
|
#endif /* _X_DEFS_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user