/* * Copyright (c) 2013 Martin Decky * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @addtogroup viewer * @{ */ /** @file */ #include #include #include #include #include #include #include #include #include #include #include #include #define NAME "viewer" #define WINDOW_WIDTH 1024 #define WINDOW_HEIGHT 768 #define DECORATION_WIDTH 8 #define DECORATION_HEIGHT 28 static size_t imgs_count; static size_t imgs_current = 0; static char **imgs; static window_t *main_window; static surface_t *surface = NULL; static canvas_t *canvas = NULL; static surface_coord_t img_width; static surface_coord_t img_height; static bool img_load(const char *, surface_t **); static bool img_setup(surface_t *); static void on_keyboard_event(widget_t *widget, void *data) { kbd_event_t *event = (kbd_event_t *) data; bool update = false; if ((event->type == KEY_PRESS) && (event->c == 'q')) exit(0); if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_DOWN)) { if (imgs_current == imgs_count - 1) imgs_current = 0; else imgs_current++; update = true; } if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_UP)) { if (imgs_current == 0) imgs_current = imgs_count - 1; else imgs_current--; update = true; } if (update) { surface_t *lsface; if (!img_load(imgs[imgs_current], &lsface)) { printf("Cannot load image \"%s\".\n", imgs[imgs_current]); exit(4); } if (!img_setup(lsface)) { printf("Cannot setup image \"%s\".\n", imgs[imgs_current]); exit(6); } } } static bool img_load(const char *fname, surface_t **p_local_surface) { int fd; errno_t rc = vfs_lookup_open(fname, WALK_REGULAR, MODE_READ, &fd); if (rc != EOK) return false; vfs_stat_t stat; rc = vfs_stat(fd, &stat); if (rc != EOK) { vfs_put(fd); return false; } void *tga = malloc(stat.size); if (tga == NULL) { vfs_put(fd); return false; } size_t nread; rc = vfs_read(fd, (aoff64_t []) { 0 }, tga, stat.size, &nread); if (rc != EOK || nread != stat.size) { free(tga); vfs_put(fd); return false; } vfs_put(fd); *p_local_surface = decode_tga(tga, stat.size, 0); if (*p_local_surface == NULL) { free(tga); return false; } free(tga); surface_get_resolution(*p_local_surface, &img_width, &img_height); return true; } static bool img_setup(surface_t *local_surface) { if (canvas != NULL) { if (!update_canvas(canvas, local_surface)) { surface_destroy(local_surface); return false; } } else { canvas = create_canvas(window_root(main_window), NULL, img_width, img_height, local_surface); if (canvas == NULL) { surface_destroy(local_surface); return false; } sig_connect(&canvas->keyboard_event, NULL, on_keyboard_event); } if (surface != NULL) surface_destroy(surface); surface = local_surface; return true; } static void print_syntax(void) { printf("Syntax: %s [-d ] ...\n", NAME); } int main(int argc, char *argv[]) { const char *display_svc = DISPLAY_DEFAULT; window_flags_t flags; surface_t *lsface; bool fullscreen; sysarg_t dwidth; sysarg_t dheight; int i; i = 1; while (i < argc && argv[i][0] == '-') { if (str_cmp(argv[i], "-d") == 0) { ++i; if (i >= argc) { printf("Argument missing.\n"); print_syntax(); return 1; } display_svc = argv[i++]; } else { printf("Invalid option '%s'.\n", argv[i]); print_syntax(); return 1; } } if (i >= argc) { printf("No image files specified.\n"); print_syntax(); return 1; } imgs_count = argc - i; imgs = calloc(imgs_count, sizeof(char *)); if (imgs == NULL) { printf("Out of memory.\n"); return 2; } for (int j = 0; j < argc - i; j++) { imgs[j] = str_dup(argv[i + j]); if (imgs[j] == NULL) { printf("Out of memory.\n"); return 3; } } if (!img_load(imgs[imgs_current], &lsface)) { printf("Cannot load image \"%s\".\n", imgs[imgs_current]); return 4; } fullscreen = ((img_width == WINDOW_WIDTH) && (img_height == WINDOW_HEIGHT)); flags = WINDOW_MAIN; if (!fullscreen) flags |= WINDOW_DECORATED; main_window = window_open(display_svc, NULL, flags, "viewer"); if (!main_window) { printf("Cannot open main window.\n"); return 5; } if (!img_setup(lsface)) { printf("Cannot setup image \"%s\".\n", imgs[imgs_current]); return 6; } if (!fullscreen) { dwidth = DECORATION_WIDTH; dheight = DECORATION_HEIGHT; } else { dwidth = 0; dheight = 0; } window_resize(main_window, 0, 0, img_width + dwidth, img_height + dheight, WINDOW_PLACEMENT_ANY); window_exec(main_window); task_retval(0); async_manager(); return 0; } /** @} */