diff --git a/journal/journal.pro b/journal/journal.pro index 6fab2f8..140d5c3 100644 --- a/journal/journal.pro +++ b/journal/journal.pro @@ -1,12 +1,66 @@ -TEMPLATE = app -CONFIG += c++11 -CONFIG -= app_bundle -CONFIG -= qt - -SOURCES += main.cpp \ - niko.cpp \ - journal.cpp - -LIBS += -lgdi32 -lshlwapi - -RC_FILE = resources.rc +TEMPLATE = app +CONFIG -= app_bundle qt +QMAKE_CFLAGS += -std=gnu11 + +# Linux +unix:!macx { + SOURCES += \ + linux/main.c \ + linux/niko.c \ + linux/journal.c \ + linux/image/niko1.c \ + linux/image/niko2.c \ + linux/image/niko3.c \ + linux/image/default.c \ + linux/image/c1.c \ + linux/image/c2.c \ + linux/image/c3.c \ + linux/image/c4.c \ + linux/image/c5.c \ + linux/image/c6.c \ + linux/image/c7.c \ + linux/image/s1.c \ + linux/image/s2.c \ + linux/image/s3.c \ + linux/image/s4.c \ + linux/image/t1.c \ + linux/image/t2.c \ + linux/image/t3.c \ + linux/image/t4.c \ + linux/image/t5.c \ + linux/image/t6.c \ + linux/image/t7.c \ + linux/image/t8.c \ + linux/image/t9.c \ + linux/image/t10.c \ + linux/image/t11.c \ + linux/image/t12.c \ + linux/image/t13.c \ + linux/image/t14.c \ + linux/image/t15.c \ + linux/image/t16.c \ + linux/image/final.c \ + linux/image/save.c + + HEADERS += \ + linux/display.h \ + linux/image.h + + LIBS += -lxcb -lxcb-util -lxcb-image -lxcb-shape +} + +# OS X +macx { +} + +# Windows +win32 { + SOURCES += \ + w32/main.c \ + w32/niko.c \ + w32/journal.c + + LIBS += -lgdi32 -lshlwapi + + RC_FILE = w32/resources.rc +} diff --git a/journal/linux/display.h b/journal/linux/display.h new file mode 100644 index 0000000..6825d6c --- /dev/null +++ b/journal/linux/display.h @@ -0,0 +1,15 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include +#include + +struct Display { + xcb_connection_t *c; + xcb_screen_t *screen; +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#endif // DISPLAY_H diff --git a/journal/linux/image.h b/journal/linux/image.h new file mode 100644 index 0000000..f6f34f7 --- /dev/null +++ b/journal/linux/image.h @@ -0,0 +1,113 @@ +#ifndef EMBED_H +#define EMBED_H + +#include +#include +#include + +static inline xcb_pixmap_t create_mask(xcb_connection_t *c, + xcb_window_t win, + unsigned char *bits, + uint32_t width, + uint32_t height) +{ + return xcb_create_pixmap_from_bitmap_data(c, win, bits, width, height, 1, 0, 0, NULL); +} + +static inline xcb_pixmap_t create_image(xcb_connection_t *c, + xcb_window_t win, + unsigned char *bytes, + uint32_t width, + uint32_t height) +{ + xcb_image_t *image = xcb_image_create_native( + c, width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 24, NULL, width * height * 4, bytes); + xcb_pixmap_t pixmap = xcb_generate_id(c); + xcb_create_pixmap(c, 24, pixmap, win, width, height); + xcb_gcontext_t gc = xcb_generate_id(c); + xcb_create_gc(c, gc, pixmap, 0, NULL); + xcb_image_put(c, pixmap, gc, image, 0, 0, 0); + xcb_image_destroy(image); + xcb_free_gc(c, gc); + return pixmap; + +} + +static inline void set_shape(xcb_connection_t *c, xcb_window_t win, xcb_pixmap_t mask) +{ + xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, mask); +} + +#define NIKO_WIDTH 48 +#define NIKO_HEIGHT 64 +extern unsigned char niko1_mask[]; +extern unsigned char niko1_rgb[]; +extern unsigned char niko2_mask[]; +extern unsigned char niko2_rgb[]; +extern unsigned char niko3_mask[]; +extern unsigned char niko3_rgb[]; + +#define JOURNAL_WIDTH 800 +#define JOURNAL_HEIGHT 600 +extern unsigned char default_mask[]; +extern unsigned char default_rgb[]; +extern unsigned char c1_mask[]; +extern unsigned char c1_rgb[]; +extern unsigned char c2_mask[]; +extern unsigned char c2_rgb[]; +extern unsigned char c3_mask[]; +extern unsigned char c3_rgb[]; +extern unsigned char c4_mask[]; +extern unsigned char c4_rgb[]; +extern unsigned char c5_mask[]; +extern unsigned char c5_rgb[]; +extern unsigned char c6_mask[]; +extern unsigned char c6_rgb[]; +extern unsigned char c7_mask[]; +extern unsigned char c7_rgb[]; +extern unsigned char s1_mask[]; +extern unsigned char s1_rgb[]; +extern unsigned char s2_mask[]; +extern unsigned char s2_rgb[]; +extern unsigned char s3_mask[]; +extern unsigned char s3_rgb[]; +extern unsigned char s4_mask[]; +extern unsigned char s4_rgb[]; +extern unsigned char t1_mask[]; +extern unsigned char t1_rgb[]; +extern unsigned char t2_mask[]; +extern unsigned char t2_rgb[]; +extern unsigned char t3_mask[]; +extern unsigned char t3_rgb[]; +extern unsigned char t4_mask[]; +extern unsigned char t4_rgb[]; +extern unsigned char t5_mask[]; +extern unsigned char t5_rgb[]; +extern unsigned char t6_mask[]; +extern unsigned char t6_rgb[]; +extern unsigned char t7_mask[]; +extern unsigned char t7_rgb[]; +extern unsigned char t8_mask[]; +extern unsigned char t8_rgb[]; +extern unsigned char t9_mask[]; +extern unsigned char t9_rgb[]; +extern unsigned char t10_mask[]; +extern unsigned char t10_rgb[]; +extern unsigned char t11_mask[]; +extern unsigned char t11_rgb[]; +extern unsigned char t12_mask[]; +extern unsigned char t12_rgb[]; +extern unsigned char t13_mask[]; +extern unsigned char t13_rgb[]; +extern unsigned char t14_mask[]; +extern unsigned char t14_rgb[]; +extern unsigned char t15_mask[]; +extern unsigned char t15_rgb[]; +extern unsigned char t16_mask[]; +extern unsigned char t16_rgb[]; +extern unsigned char final_mask[]; +extern unsigned char final_rgb[]; +extern unsigned char save_mask[]; +extern unsigned char save_rgb[]; + +#endif // EMBED_H diff --git a/journal/linux/image/.gitignore b/journal/linux/image/.gitignore new file mode 100644 index 0000000..064a8d8 --- /dev/null +++ b/journal/linux/image/.gitignore @@ -0,0 +1 @@ +*.c diff --git a/journal/linux/image/pixmapper.sh b/journal/linux/image/pixmapper.sh new file mode 100755 index 0000000..546258d --- /dev/null +++ b/journal/linux/image/pixmapper.sh @@ -0,0 +1,12 @@ +#!/bin/bash +if [ $# -lt 1 ]; then + echo "usage: pixmapper.sh " + exit 1 +fi +basename="$(basename "$1" | tr '[:upper:]' '[:lower:]')" +name="${basename%.*}" +cfile="$name.c" +convert "$1" -alpha on -transparent '#00ff00' -alpha extract -negate xbm:- | sed "/^#define/d;s/-_bits/${name}_mask/g;s/^static char/unsigned char/" > "$cfile" +echo "unsigned char ${name}_rgb[] = {" >> "$cfile" +convert "$1" -alpha on -transparent '#00ff00' -depth 8 bgra:- | xxd -i >> "$cfile" +echo "};" >> "$cfile" diff --git a/journal/linux/journal.c b/journal/linux/journal.c new file mode 100644 index 0000000..3c80d0d --- /dev/null +++ b/journal/linux/journal.c @@ -0,0 +1,6 @@ +#include "display.h" + +int do_journal(struct Display *dpy) +{ + return 0; +} diff --git a/journal/linux/main.c b/journal/linux/main.c new file mode 100644 index 0000000..d68837d --- /dev/null +++ b/journal/linux/main.c @@ -0,0 +1,26 @@ +#include "display.h" + +extern int do_niko(struct Display *dpy, int x, int y); +extern int do_journal(struct Display *dpy); + +int main(int argc, char **argv) +{ + // Connect + struct Display dpy; + dpy.c = xcb_connect(NULL, NULL); + dpy.screen = xcb_setup_roots_iterator(xcb_get_setup(dpy.c)).data; + + int result; + if (argc == 3) { + // argc == 3, assume niko + int x = atoi(argv[1]); + int y = atoi(argv[2]); + result = do_niko(&dpy, x, y); + } else { + // argc == 3, assume journal + result = do_journal(&dpy); + } + + xcb_disconnect(dpy.c); + return result; +} diff --git a/journal/linux/niko.c b/journal/linux/niko.c new file mode 100644 index 0000000..1265d1f --- /dev/null +++ b/journal/linux/niko.c @@ -0,0 +1,113 @@ +#include + +#include "display.h" +#include "image.h" + +static uint64_t getticks() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000; +} + +static void draw_niko(xcb_connection_t *c, + xcb_window_t win, + xcb_gcontext_t gc, + xcb_pixmap_t masks[3], + xcb_pixmap_t images[3], + int x, int y, int w, int h, + int offset) +{ + int frame; + if (offset % 32 >= 16) { + frame = 1; + } else { + if ((offset / 32) % 2) + frame = 0; + else + frame = 2; + } + xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, masks[frame]); + xcb_copy_area(c, images[frame], win, gc, x, y, x, y, w, h); + +} + +int do_niko(struct Display *dpy, int x, int y) +{ + // Create window + uint32_t values[] = { + true, // override_redirect + XCB_EVENT_MASK_EXPOSURE, // event mask + }; + xcb_window_t window = xcb_generate_id(dpy->c); + xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root, + x, y, NIKO_WIDTH, NIKO_HEIGHT, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual, + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, &values); + + // Stick window on top + xcb_stack_mode_t stack = XCB_STACK_MODE_ABOVE; + xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_STACK_MODE, &stack); + + // Create pixmaps + xcb_pixmap_t niko_masks[] = { + create_mask(dpy->c, window, niko1_mask, NIKO_WIDTH, NIKO_HEIGHT), + create_mask(dpy->c, window, niko2_mask, NIKO_WIDTH, NIKO_HEIGHT), + create_mask(dpy->c, window, niko3_mask, NIKO_WIDTH, NIKO_HEIGHT), + }; + xcb_pixmap_t niko_images[] = { + create_image(dpy->c, window, niko1_rgb, NIKO_WIDTH, NIKO_HEIGHT), + create_image(dpy->c, window, niko2_rgb, NIKO_WIDTH, NIKO_HEIGHT), + create_image(dpy->c, window, niko3_rgb, NIKO_WIDTH, NIKO_HEIGHT), + }; + + // Create graphics context + xcb_gcontext_t gc = xcb_generate_id(dpy->c); + xcb_create_gc(dpy->c, gc, window, 0, NULL); + + // Map! + xcb_map_window(dpy->c, window); + xcb_flush(dpy->c); + + // Niko movement info + int niko_offset = 0; + + uint64_t ticks = getticks(); + for (;;) { + // Handle events + for (;;) { + xcb_generic_event_t *e = xcb_poll_for_event(dpy->c); + if (e) { + switch (e->response_type) { + case XCB_EXPOSE: { + xcb_expose_event_t *ee = (xcb_expose_event_t*)e; + draw_niko(dpy->c, window, gc, niko_masks, niko_images, + ee->x, ee->y, ee->width, ee->height, niko_offset); + xcb_flush(dpy->c); + } break; + } + } else if (getticks() - ticks >= 1000 / 60) { + break; + } + } + + // Move niko + niko_offset += 2; + int new_y = y + niko_offset; + if (new_y > dpy->screen->height_in_pixels) + break; + xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_Y, &new_y); + draw_niko(dpy->c, window, gc, niko_masks, niko_images, 0, 0, NIKO_WIDTH, NIKO_HEIGHT, niko_offset); + xcb_flush(dpy->c); + ticks = getticks(); + } + + // Free up stuff + xcb_free_gc(dpy->c, gc); + for (int i = 0; i < 3; ++i) { + xcb_free_pixmap(dpy->c, niko_masks[i]); + xcb_free_pixmap(dpy->c, niko_images[i]); + } + + return 0; +} diff --git a/journal/icon.ico b/journal/w32/icon.ico similarity index 100% rename from journal/icon.ico rename to journal/w32/icon.ico diff --git a/journal/journal.cpp b/journal/w32/journal.c similarity index 98% rename from journal/journal.cpp rename to journal/w32/journal.c index a7838db..af64c51 100644 --- a/journal/journal.cpp +++ b/journal/w32/journal.c @@ -157,7 +157,7 @@ int do_journal() ShowWindow(window, SW_SHOWNOACTIVATE); UpdateWindow(window); - image_mutex = CreateMutexW(NULL, NULL, NULL); + image_mutex = CreateMutexW(NULL, FALSE, NULL); HANDLE thread = CreateThread(NULL, 0, ipc_thread, NULL, 0, NULL); // Dispatch messages diff --git a/journal/main.cpp b/journal/w32/main.c similarity index 100% rename from journal/main.cpp rename to journal/w32/main.c diff --git a/journal/niko.cpp b/journal/w32/niko.c similarity index 100% rename from journal/niko.cpp rename to journal/w32/niko.c diff --git a/journal/resources.rc b/journal/w32/resources.rc similarity index 100% rename from journal/resources.rc rename to journal/w32/resources.rc