From 2dd32c7adb7116f1ad9ab2632d9fcf57a31e9fa2 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 21 Nov 2011 08:44:10 +0000 Subject: Improve API to allow for RAM surfaces instead of direct blitting Improve and update tests Fix RAM surface Fix VNC surface svn path=/trunk/libnsfb/; revision=13158 --- Makefile | 8 + include/frontend.h | 47 ----- include/libnsfb.h | 94 ++++++--- include/libnsfb_event.h | 26 ++- include/libnsfb_plot.h | 2 +- include/nsfb.h | 28 ++- include/surface.h | 61 ++++++ src/Makefile | 2 +- src/cursor.c | 18 +- src/dump.c | 56 +++++ src/libnsfb.c | 91 +++++--- src/plot/api.c | 43 +++- src/plot/generic.c | 530 +++++++++++++++++++++++++---------------------- src/surface/Makefile | 6 +- src/surface/able.c | 12 +- src/surface/linux.c | 14 +- src/surface/ram.c | 71 ++++++- src/surface/sdl.c | 201 +++++++++--------- src/surface/surface.c | 139 +++++++------ src/surface/vnc.c | 536 ++++++++++++++++++++++++++++++++++++++++++++++-- src/surface/x.c | 45 ++-- test/Makefile | 2 +- test/bezier.c | 55 ++++- test/bitmap.c | 168 +++++++++++++++ test/frontend.c | 52 +++-- test/path.c | 59 ++++-- test/plottest.c | 106 +++++++--- test/polygon.c | 55 ++++- test/polystar.c | 56 ++++- test/polystar2.c | 56 ++++- test/runtest.sh | 17 +- 31 files changed, 1965 insertions(+), 691 deletions(-) delete mode 100644 include/frontend.h create mode 100644 include/surface.h create mode 100644 src/dump.c create mode 100644 test/bitmap.c diff --git a/Makefile b/Makefile index 4239425..db12d1c 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ CFLAGS := -g -std=c99 -D_BSD_SOURCE -I$(CURDIR)/include/ \ NSFB_XCB_PKG_NAMES := xcb xcb-icccm xcb-image xcb-keysyms +$(eval $(call pkg_config_package_available,NSFB_VNC_AVAILABLE,libvncserver)) $(eval $(call pkg_config_package_available,NSFB_SDL_AVAILABLE,sdl)) $(eval $(call pkg_config_package_available,NSFB_XCB_AVAILABLE,$(NSFB_XCB_PKG_NAMES))) @@ -43,6 +44,13 @@ ifeq ($(NSFB_XCB_AVAILABLE),yes) REQUIRED_PKGS := $(REQUIRED_PKGS) $(NSFB_XCB_PKG_NAMES) endif +ifeq ($(NSFB_VNC_AVAILABLE),yes) + $(eval $(call pkg_config_package_add_flags,libvncserver,CFLAGS)) + $(eval $(call pkg_config_package_add_flags,libvncserver,TESTCFLAGS,TESTLDFLAGS)) + + REQUIRED_PKGS := $(REQUIRED_PKGS) libvncserver +endif + TESTLDFLAGS := -Wl,--whole-archive -l$(COMPONENT) -Wl,--no-whole-archive $(TESTLDFLAGS) include build/makefiles/Makefile.top diff --git a/include/frontend.h b/include/frontend.h deleted file mode 100644 index fba407f..0000000 --- a/include/frontend.h +++ /dev/null @@ -1,47 +0,0 @@ -/* libnsfb framebuffer frontend support */ - -#include "libnsfb.h" -#include "libnsfb_plot.h" -#include "nsfb.h" - -/* frontend default options */ -typedef int (nsfb_fendfn_defaults_t)(nsfb_t *nsfb); -/* frontend init */ -typedef int (nsfb_fendfn_init_t)(nsfb_t *nsfb); -/* frontend finalise */ -typedef int (nsfb_fendfn_fini_t)(nsfb_t *nsfb); -/* frontend set geometry */ -typedef int (nsfb_fendfn_geometry_t)(nsfb_t *nsfb, int width, int height, int bpp); -/* frontend input */ -typedef bool (nsfb_fendfn_input_t)(nsfb_t *nsfb, nsfb_event_t *event, int timeout); -/* frontend area claim */ -typedef int (nsfb_fendfn_claim_t)(nsfb_t *nsfb, nsfb_bbox_t *box); -/* frontend area update */ -typedef int (nsfb_fendfn_update_t)(nsfb_t *nsfb, nsfb_bbox_t *box); -/* frontend cursor display */ -typedef int (nsfb_fendfn_cursor_t)(nsfb_t *nsfb, struct nsfb_cursor_s *cursor); - -typedef struct nsfb_frontend_rtns_s { - nsfb_fendfn_defaults_t *defaults; - nsfb_fendfn_init_t *initialise; - nsfb_fendfn_fini_t *finalise; - nsfb_fendfn_geometry_t *geometry; - nsfb_fendfn_input_t *input; - nsfb_fendfn_claim_t *claim; - nsfb_fendfn_update_t *update; - nsfb_fendfn_cursor_t *cursor; -} nsfb_frontend_rtns_t; - -void _nsfb_register_frontend(const enum nsfb_frontend_e type, const nsfb_frontend_rtns_t *rtns, const char *name); - - -/* macro which adds a builtin command with no argument limits */ -#define NSFB_FRONTEND_DEF(__name, __type, __rtns) \ - static void __name##_register_frontend(void) __attribute__((constructor)); \ - void __name##_register_frontend(void) { \ - _nsfb_register_frontend(__type, __rtns, #__name); \ - } - -/* Obtain routines for a frontend */ -nsfb_frontend_rtns_t *nsfb_frontend_get_rtns(enum nsfb_frontend_e type); - diff --git a/include/libnsfb.h b/include/libnsfb.h index 3f4a4e7..330c476 100644 --- a/include/libnsfb.h +++ b/include/libnsfb.h @@ -31,46 +31,60 @@ typedef struct nsfb_bbox_s { int y1; } nsfb_bbox_t; -/** The type of frontend for a framebuffer context. */ -enum nsfb_frontend_e { - NSFB_FRONTEND_NONE = 0, /**< Empty frontend. */ - NSFB_FRONTEND_SDL, /**< SDL frontend */ - NSFB_FRONTEND_LINUX, /**< Linux frontend */ - NSFB_FRONTEND_VNC, /**< VNC frontend */ - NSFB_FRONTEND_ABLE, /**< ABLE frontend */ - NSFB_FRONTEND_RAM, /**< RAM frontend */ - NSFB_FRONTEND_X /**< X windows frontend */ +/** The type of framebuffer surface. */ +enum nsfb_type_e { + NSFB_SURFACE_NONE = 0, /**< No surface */ + NSFB_SURFACE_RAM, /**< RAM surface */ + NSFB_SURFACE_SDL, /**< SDL surface */ + NSFB_SURFACE_LINUX, /**< Linux framebuffer surface */ + NSFB_SURFACE_VNC, /**< VNC surface */ + NSFB_SURFACE_ABLE, /**< ABLE framebuffer surface */ + NSFB_SURFACE_X /**< X windows surface */ }; -/** Initialise nsfb context. - * - * This initialises a framebuffer context. - * - * @param frontend The type of frontend to create a context for. +enum nsfb_format_e { + NSFB_FMT_ANY = 0, /* No specific format - use surface default */ + NSFB_FMT_XBGR8888, /* 32bpp Blue Green Red */ + NSFB_FMT_XRGB8888, /* 32bpp Red Green Blue */ + NSFB_FMT_ABGR8888, /* 32bpp Alpga Blue Green Red */ + NSFB_FMT_ARGB8888, /* 32bpp Alpga Red Green Blue */ + NSFB_FMT_RGB888, /* 24 bpp Alpga Red Green Blue */ + NSFB_FMT_ARGB1555, /* 16 bpp 555 */ + NSFB_FMT_RGB565, /* 16 bpp 565 */ + NSFB_FMT_I8, /* 8bpp indexed */ + NSFB_FMT_I4, /* 4bpp indexed */ + NSFB_FMT_I1, /* black and white */ +}; + +/** Select frontend type from a name. + * + * @param name The name to select a frontend. + * @return The surface type or NSFB_SURFACE_NONE if frontend with specified + * name was not available */ -nsfb_t *nsfb_init(enum nsfb_frontend_e frontend); +enum nsfb_type_e nsfb_type_from_name(const char *name); -/** Finalise nsfb. +/** Create a nsfb context. * - * This shuts down and releases all resources associated with an nsfb context. + * This creates a framebuffer surface context. * - * @param nsfb The context returned from ::nsfb_init tofinalise + * @param surface_type The type of surface to create a context for. */ -int nsfb_finalise(nsfb_t *nsfb); +nsfb_t *nsfb_new(const enum nsfb_type_e surface_type); -/** Initialise selected frontend. +/** Initialise selected surface context. * * @param nsfb The context returned from ::nsfb_init */ -int nsfb_init_frontend(nsfb_t *nsfb); +int nsfb_init(nsfb_t *nsfb); -/** Select frontend type from a name. - * - * @param name The name to select a frontend. - * @return The frontend type or NSFB_FRONTEND_NONE if frontend with specified - * name was not available +/** Free nsfb context. + * + * This shuts down and releases all resources associated with an nsfb context. + * + * @param nsfb The context returned from ::nsfb_new to free */ -enum nsfb_frontend_e nsfb_frontend_from_name(const char *name); +int nsfb_free(nsfb_t *nsfb); /** Claim an area of screen to be redrawn. * @@ -86,7 +100,7 @@ int nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box); /** Update an area of screen which has been redrawn. * * Informs the nsfb library that an area of screen has been directly - * updated by the user program. Some frontends only show the update on + * updated by the user program. Some surfaces only show the update on * notification. The area updated does not neccisarrily have to * corelate with a previous ::nsfb_claim bounding box, however if the * redrawn area is larger than the claimed area pointer plotting @@ -100,9 +114,9 @@ int nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box); * * @param width a variable to store the framebuffer width in or NULL * @param height a variable to store the framebuffer height in or NULL - * @param bpp a variable to store the framebuffer bpp in or NULL + * @param format a variable to store the framebuffer format in or NULL */ -int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp); +int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format); /** Alter the geometry of a framebuffer context * @@ -111,10 +125,24 @@ int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp); * @param height The new display height. * @param bpp The new display depth. */ -int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp); +int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format); -/** Obtain the framebuffer memory base and stride. +/** Obtain the buffer memory base and stride. + * + * @param nsfb The context to read. */ -int nsfb_get_framebuffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen); +int nsfb_get_buffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen); + +/** Dump the surface to fd in PPM format + */ +bool nsfb_dump(nsfb_t *nsfb, int fd); + #endif + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/include/libnsfb_event.h b/include/libnsfb_event.h index ea2b2bf..6944654 100644 --- a/include/libnsfb_event.h +++ b/include/libnsfb_event.h @@ -1,3 +1,16 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * This is the exported interface for the libnsfb graphics library. + */ + +#ifndef _LIBNSFB_EVENT_H +#define _LIBNSFB_EVENT_H 1 + enum nsfb_event_type_e { NSFB_EVENT_NONE, NSFB_EVENT_CONTROL, @@ -13,6 +26,7 @@ enum nsfb_key_code_e { NSFB_KEY_UNKNOWN = 0, NSFB_KEY_BACKSPACE = 8, NSFB_KEY_TAB = 9, + NSFB_KEY_LF = 10, NSFB_KEY_CLEAR = 12, NSFB_KEY_RETURN = 13, NSFB_KEY_PAUSE = 19, @@ -166,7 +180,8 @@ enum nsfb_key_code_e { enum nsfb_control_e { NSFB_CONTROL_NONE, - NSFB_CONTROL_QUIT, + NSFB_CONTROL_TIMEOUT, /* timeout event */ + NSFB_CONTROL_QUIT, /* surface handler quit event */ }; struct nsfb_event_s { @@ -193,3 +208,12 @@ struct nsfb_event_s { * @return If the /a event structure is updated true else false. */ bool nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout); + +#endif + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/include/libnsfb_plot.h b/include/libnsfb_plot.h index 931243d..b3f86d1 100644 --- a/include/libnsfb_plot.h +++ b/include/libnsfb_plot.h @@ -148,7 +148,7 @@ bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_pl * * Copy an area of the display. */ -bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox); +bool nsfb_plot_copy(nsfb_t *srcfb, nsfb_bbox_t *srcbox, nsfb_t *dstfb, nsfb_bbox_t *dstbox); /** Plot bitmap. */ diff --git a/include/nsfb.h b/include/nsfb.h index 7b28fcb..9b1619c 100644 --- a/include/nsfb.h +++ b/include/nsfb.h @@ -1,3 +1,13 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * + * This is the internal interface for the libnsfb graphics library. + */ + #ifndef _NSFB_H #define _NSFB_H 1 @@ -9,10 +19,13 @@ struct nsfb_s { int width; /**< Visible width. */ int height; /**< Visible height. */ - int bpp; /**< Bits per pixel. */ + + int bpp; + + enum nsfb_format_e format; /**< Framebuffer format */ int refresh; /**< Desired refresh rate for physical displays. */ - char *output_dev; /**> Path to output device for frontends that require it. */ + char *output_dev; /**> Path to output device for surfaces that require it. */ uint8_t *ptr; /**< Base of video memory. */ int linelen; /**< length of a video line. */ @@ -20,8 +33,8 @@ struct nsfb_s { nsfb_colour_t palette[256]; /**< palette for index modes */ nsfb_cursor_t *cursor; /**< cursor */ - struct nsfb_frontend_rtns_s *frontend_rtns; /**< frontend routines. */ - void *frontend_priv; /**< frontend opaque data. */ + struct nsfb_surface_rtns_s *surface_rtns; /**< surface routines. */ + void *surface_priv; /**< surface opaque data. */ nsfb_bbox_t clip; /**< current clipping rectangle for plotters */ struct nsfb_plotter_fns_s *plotter_fns; /**< Plotter methods */ @@ -29,3 +42,10 @@ struct nsfb_s { #endif + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/include/surface.h b/include/surface.h new file mode 100644 index 0000000..d0c6c5a --- /dev/null +++ b/include/surface.h @@ -0,0 +1,61 @@ +/* libnsfb framebuffer surface support */ + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "nsfb.h" + +/* surface default options */ +typedef int (nsfb_fendfn_defaults_t)(nsfb_t *nsfb); + +/* surface init */ +typedef int (nsfb_fendfn_init_t)(nsfb_t *nsfb); + +/* surface finalise */ +typedef int (nsfb_fendfn_fini_t)(nsfb_t *nsfb); + +/* surface set geometry */ +typedef int (nsfb_fendfn_geometry_t)(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format); + +/* surface input */ +typedef bool (nsfb_fendfn_input_t)(nsfb_t *nsfb, nsfb_event_t *event, int timeout); + +/* surface area claim */ +typedef int (nsfb_fendfn_claim_t)(nsfb_t *nsfb, nsfb_bbox_t *box); + +/* surface area update */ +typedef int (nsfb_fendfn_update_t)(nsfb_t *nsfb, nsfb_bbox_t *box); + +/* surface cursor display */ +typedef int (nsfb_fendfn_cursor_t)(nsfb_t *nsfb, struct nsfb_cursor_s *cursor); + +typedef struct nsfb_surface_rtns_s { + nsfb_fendfn_defaults_t *defaults; + nsfb_fendfn_init_t *initialise; + nsfb_fendfn_fini_t *finalise; + nsfb_fendfn_geometry_t *geometry; + nsfb_fendfn_input_t *input; + nsfb_fendfn_claim_t *claim; + nsfb_fendfn_update_t *update; + nsfb_fendfn_cursor_t *cursor; +} nsfb_surface_rtns_t; + +void _nsfb_register_surface(const enum nsfb_type_e type, const nsfb_surface_rtns_t *rtns, const char *name); + + +/* macro which adds a builtin command with no argument limits */ +#define NSFB_SURFACE_DEF(__name, __type, __rtns) \ + static void __name##_register_surface(void) __attribute__((constructor)); \ + void __name##_register_surface(void) { \ + _nsfb_register_surface(__type, __rtns, #__name); \ + } + +/** Obtain routines for a surface + * + * Obtain a vlist of methods for a surface type. + * + * @param type The surface type. + * @return A vtable of routines which teh caller must deallocate or + * NULL on error + */ +nsfb_surface_rtns_t *nsfb_surface_get_rtns(enum nsfb_type_e type); + diff --git a/src/Makefile b/src/Makefile index 24f412f..90cde9b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ # Sources -DIR_SOURCES := libnsfb.c cursor.c +DIR_SOURCES := libnsfb.c dump.c cursor.c include build/makefiles/Makefile.subdir diff --git a/src/cursor.c b/src/cursor.c index f1a3b58..bd9f04b 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -1,3 +1,15 @@ +/* + * Copyright 2010 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +/** \file + * cursor (implementation). + */ + #include #include @@ -8,7 +20,7 @@ #include "nsfb.h" #include "cursor.h" #include "plot.h" -#include "frontend.h" +#include "surface.h" bool nsfb_cursor_init(nsfb_t *nsfb) { @@ -36,7 +48,7 @@ bool nsfb_cursor_set(nsfb_t *nsfb, const nsfb_colour_t *pixel, int bmp_width, in nsfb->cursor->loc.x1 = nsfb->cursor->loc.x0 + nsfb->cursor->bmp_width; nsfb->cursor->loc.y1 = nsfb->cursor->loc.y0 + nsfb->cursor->bmp_height; - return nsfb->frontend_rtns->cursor(nsfb, nsfb->cursor); + return nsfb->surface_rtns->cursor(nsfb, nsfb->cursor); } bool nsfb_cursor_loc_set(nsfb_t *nsfb, const nsfb_bbox_t *loc) @@ -48,7 +60,7 @@ bool nsfb_cursor_loc_set(nsfb_t *nsfb, const nsfb_bbox_t *loc) nsfb->cursor->loc.x1 = nsfb->cursor->loc.x0 + nsfb->cursor->bmp_width; nsfb->cursor->loc.y1 = nsfb->cursor->loc.y0 + nsfb->cursor->bmp_height; - return nsfb->frontend_rtns->cursor(nsfb, nsfb->cursor); + return nsfb->surface_rtns->cursor(nsfb, nsfb->cursor); } bool nsfb_cursor_loc_get(nsfb_t *nsfb, nsfb_bbox_t *loc) diff --git a/src/dump.c b/src/dump.c new file mode 100644 index 0000000..ed56a00 --- /dev/null +++ b/src/dump.c @@ -0,0 +1,56 @@ +/* + * Copyright 2009 Vincent Sanders + * + * This file is part of libnsfb, http://www.netsurf-browser.org/ + * Licenced under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + */ + +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_event.h" +#include "nsfb.h" +#include "surface.h" + +/* exported interface documented in libnsfb.h */ +bool +nsfb_dump(nsfb_t *nsfb, int fd) +{ + FILE *outf; + int x; + int y; + + outf = fdopen(dup(fd), "w"); + if (outf == NULL) { + return false; + } + + fprintf(outf,"P3\n#libnsfb buffer dump\n%d %d\n255\n", + nsfb->width, nsfb->height); + for (y=0; y < nsfb->height; y++) { + for (x=0; x < nsfb->width; x++) { + fprintf(outf,"%d %d %d ", + *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 2), + *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 1), + *(nsfb->ptr + (((nsfb->width * y) + x) * 4) + 0)); + + } + fprintf(outf,"\n"); + } + + fclose(outf); + + return true; +} + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/libnsfb.c b/src/libnsfb.c index 405df2c..21661cd 100644 --- a/src/libnsfb.c +++ b/src/libnsfb.c @@ -14,60 +14,70 @@ #include "libnsfb_plot.h" #include "libnsfb_event.h" #include "nsfb.h" -#include "frontend.h" +#include "surface.h" -/* documented in libnsfb.h */ +/* exported interface documented in libnsfb.h */ nsfb_t* -nsfb_init(const enum nsfb_frontend_e frontend_type) +nsfb_new(const enum nsfb_type_e surface_type) { nsfb_t *newfb; newfb = calloc(1, sizeof(nsfb_t)); if (newfb == NULL) return NULL; - /* obtain frontend routines */ - newfb->frontend_rtns = nsfb_frontend_get_rtns(frontend_type); - if (newfb->frontend_rtns == NULL) { + /* obtain surface routines */ + newfb->surface_rtns = nsfb_surface_get_rtns(surface_type); + if (newfb->surface_rtns == NULL) { free(newfb); return NULL; } - newfb->frontend_rtns->defaults(newfb); + newfb->surface_rtns->defaults(newfb); return newfb; } -int nsfb_finalise(nsfb_t *nsfb) +/* exported interface documented in libnsfb.h */ +int +nsfb_init(nsfb_t *nsfb) { - int ret; - ret = nsfb->frontend_rtns->finalise(nsfb); - free(nsfb); - return ret; + return nsfb->surface_rtns->initialise(nsfb); } - -int -nsfb_init_frontend(nsfb_t *nsfb) +/* exported interface documented in libnsfb.h */ +int +nsfb_free(nsfb_t *nsfb) { - return nsfb->frontend_rtns->initialise(nsfb); + int ret; + ret = nsfb->surface_rtns->finalise(nsfb); + free(nsfb); + return ret; } -bool nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout) +/* exported interface documented in libnsfb.h */ +bool +nsfb_event(nsfb_t *nsfb, nsfb_event_t *event, int timeout) { - return nsfb->frontend_rtns->input(nsfb, event, timeout); + return nsfb->surface_rtns->input(nsfb, event, timeout); } -int nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box) +/* exported interface documented in libnsfb.h */ +int +nsfb_claim(nsfb_t *nsfb, nsfb_bbox_t *box) { - return nsfb->frontend_rtns->claim(nsfb, box); + return nsfb->surface_rtns->claim(nsfb, box); } -int nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box) +/* exported interface documented in libnsfb.h */ +int +nsfb_update(nsfb_t *nsfb, nsfb_bbox_t *box) { - return nsfb->frontend_rtns->update(nsfb, box); + return nsfb->surface_rtns->update(nsfb, box); } -int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +/* exported interface documented in libnsfb.h */ +int +nsfb_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { if (width <= 0) width = nsfb->width; @@ -75,13 +85,15 @@ int nsfb_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) if (height <= 0) height = nsfb->height; - if ((bpp != 32) && (bpp != 16) && (bpp != 8)) - bpp = nsfb->bpp; + if (format == NSFB_FMT_ANY) + format = nsfb->format; - return nsfb->frontend_rtns->geometry(nsfb, width, height, bpp); + return nsfb->surface_rtns->geometry(nsfb, width, height, format); } -int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp) +/* exported interface documented in libnsfb.h */ +int +nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, enum nsfb_format_e *format) { if (width != NULL) *width = nsfb->width; @@ -89,15 +101,30 @@ int nsfb_get_geometry(nsfb_t *nsfb, int *width, int *height, int *bpp) if (height != NULL) *height = nsfb->height; - if (bpp != NULL) - *bpp = nsfb->bpp; + if (format != NULL) + *format = nsfb->format; return 0; } -int nsfb_get_framebuffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen) +/* exported interface documented in libnsfb.h */ +int +nsfb_get_buffer(nsfb_t *nsfb, uint8_t **ptr, int *linelen) { - *ptr = nsfb->ptr; - *linelen = nsfb->linelen; + if (ptr != NULL) { + *ptr = nsfb->ptr; + } + if (linelen != NULL) { + *linelen = nsfb->linelen; + } return 0; } + + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ + diff --git a/src/plot/api.c b/src/plot/api.c index f5c16f3..77559cb 100644 --- a/src/plot/api.c +++ b/src/plot/api.c @@ -126,9 +126,41 @@ bool nsfb_plot_ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) return nsfb->plotter_fns->ellipse_fill(nsfb, ellipse, c); } -bool nsfb_plot_copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) +/* copy an area of surface from one location to another. + * + * @warning This implementation is woefully incomplete! + */ +bool +nsfb_plot_copy(nsfb_t *srcfb, + nsfb_bbox_t *srcbox, + nsfb_t *dstfb, + nsfb_bbox_t *dstbox) { - return nsfb->plotter_fns->copy(nsfb, srcbox, dstbox); + bool trans = false; + nsfb_colour_t srccol; + + if (srcfb == dstfb) { + return dstfb->plotter_fns->copy(srcfb, srcbox, dstbox); + } + + if (srcfb->format == NSFB_FMT_ABGR8888) { + trans = true; + } + + if ((srcfb->width == 1) && (srcfb->height == 1)) { + srccol = *(nsfb_colour_t *)(srcfb->ptr); + + /* check for completely transparent */ + if ((srccol & 0xff000000) == 0) + return true; + + /* completely opaque pixels can be replaced with fill */ + if ((srccol & 0xff000000) == 0xff) + return dstfb->plotter_fns->fill(dstfb, dstbox, srccol); + } + + return dstfb->plotter_fns->bitmap(dstfb, dstbox, (const nsfb_colour_t *)srcfb->ptr, srcfb->width, srcfb->height, (srcfb->linelen * 8) / srcfb->bpp, trans); + } bool nsfb_plot_bitmap(nsfb_t *nsfb, const nsfb_bbox_t *loc, const nsfb_colour_t *pixel, int bmp_width, int bmp_height, int bmp_stride, bool alpha) @@ -172,3 +204,10 @@ bool nsfb_plot_path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_pl { return nsfb->plotter_fns->path(nsfb, pathc, pathop, pen); } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/plot/generic.c b/src/plot/generic.c index 01a8587..63845e4 100644 --- a/src/plot/generic.c +++ b/src/plot/generic.c @@ -22,7 +22,7 @@ #include "nsfb.h" #include "plot.h" -#include "frontend.h" +#include "surface.h" extern const nsfb_plotter_fns_t _nsfb_1bpp_plotters; extern const nsfb_plotter_fns_t _nsfb_8bpp_plotters; @@ -97,20 +97,20 @@ static bool clg(nsfb_t *nsfb, nsfb_colour_t c) * evenness of the total. */ static bool establish_crossing_value(int x, int y, int x0, int y0, - int x1, int y1) + int x1, int y1) { - bool v1 = (x == x0 && y == y0); /* whether we're crossing 1st vertex */ - bool v2 = (x == x1 && y == y1); /* whether we're crossing 2nd vertex */ + bool v1 = (x == x0 && y == y0); /* whether we're crossing 1st vertex */ + bool v2 = (x == x1 && y == y1); /* whether we're crossing 2nd vertex */ - if ((v1 && (y0 < y1)) || (v2 && (y1 < y0))) { - /* crossing top vertex */ - return true; - } else if (!v1 && !v2) { - /* Intersection with current y level is not at a vertex. - * Normal crossing. */ - return true; - } - return false; + if ((v1 && (y0 < y1)) || (v2 && (y1 < y0))) { + /* crossing top vertex */ + return true; + } else if (!v1 && !v2) { + /* Intersection with current y level is not at a vertex. + * Normal crossing. */ + return true; + } + return false; } @@ -127,125 +127,125 @@ static bool establish_crossing_value(int x, int y, int x0, int y0, */ static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1) { - int i; - int p_x0, p_y0; - int p_x1, p_y1; - int x0_min, x1_min; - int x_new; - unsigned int x0c, x1c; /* counters for crossings at span end points */ - bool crossing_value; - bool found_span_start = false; - - x0_min = x1_min = INT_MIN; - x0c = x1c = 0; - *x0 = *x1 = INT_MAX; - - /* search row for next span, returning it if one exists */ - do { - /* reset endpoint info, if valid span endpoints not found */ - if (!found_span_start) - *x0 = INT_MAX; - *x1 = INT_MAX; - - /* search all lines in polygon */ - for (i = 0; i < n; i = i + 2) { - /* get line endpoints */ - if (i != n - 2) { - /* not the last line */ - p_x0 = p[i]; p_y0 = p[i + 1]; - p_x1 = p[i + 2]; p_y1 = p[i + 3]; - } else { - /* last line; 2nd endpoint is first vertex */ - p_x0 = p[i]; p_y0 = p[i + 1]; - p_x1 = p[0]; p_y1 = p[1]; - } - /* ignore horizontal lines */ - if (p_y0 == p_y1) - continue; - - /* ignore lines that don't cross this y level */ - if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1)) - continue; - - if (p_x0 == p_x1) { - /* vertical line, x is constant */ - x_new = p_x0; - } else { - /* find crossing (intersection of this line and - * current y level) */ - int num = (y - p_y0) * (p_x1 - p_x0); - int den = (p_y1 - p_y0); - - /* To round to nearest (rather than down) - * half the denominator is either added to - * or subtracted from the numerator, - * depending on whether the numerator and - * denominator have the same sign. */ - num = ((num < 0) == (den < 0)) ? - num + (den / 2) : - num - (den / 2); - x_new = p_x0 + num / den; - } - - /* ignore crossings before current x */ - if (x_new < x || - (!found_span_start && x_new < x0_min) || - (found_span_start && x_new < x1_min)) - continue; - - crossing_value = establish_crossing_value(x_new, y, - p_x0, p_y0, p_x1, p_y1); - - - /* set nearest intersections as filled area endpoints */ - if (!found_span_start && - x_new < *x0 && crossing_value) { - /* nearer than first endpoint */ - *x1 = *x0; - x1c = x0c; - *x0 = x_new; - x0c = 1; - } else if (!found_span_start && - x_new == *x0 && crossing_value) { - /* same as first endpoint */ - x0c++; - } else if (x_new < *x1 && crossing_value) { - /* nearer than second endpoint */ - *x1 = x_new; - x1c = 1; - } else if (x_new == *x1 && crossing_value) { - /* same as second endpoint */ - x1c++; - } - } - /* check whether the span endpoints have been found */ - if (!found_span_start && x0c % 2 == 1) { - /* valid fill start found */ - found_span_start = true; - - } - if (x1c % 2 == 1) { - /* valid fill endpoint found */ - if (!found_span_start) { - /* not got a start yet; use this as start */ - found_span_start = true; - x0c = x1c; - *x0 = *x1; - } else { - /* got valid end of span */ - return true; - } - } - /* if current positions aren't valid endpoints, set new - * minimums after current positions */ - if (!found_span_start) - x0_min = *x0 + 1; - x1_min = *x1 + 1; - - } while (*x1 != INT_MAX); - - /* no spans found */ - return false; + int i; + int p_x0, p_y0; + int p_x1, p_y1; + int x0_min, x1_min; + int x_new; + unsigned int x0c, x1c; /* counters for crossings at span end points */ + bool crossing_value; + bool found_span_start = false; + + x0_min = x1_min = INT_MIN; + x0c = x1c = 0; + *x0 = *x1 = INT_MAX; + + /* search row for next span, returning it if one exists */ + do { + /* reset endpoint info, if valid span endpoints not found */ + if (!found_span_start) + *x0 = INT_MAX; + *x1 = INT_MAX; + + /* search all lines in polygon */ + for (i = 0; i < n; i = i + 2) { + /* get line endpoints */ + if (i != n - 2) { + /* not the last line */ + p_x0 = p[i]; p_y0 = p[i + 1]; + p_x1 = p[i + 2]; p_y1 = p[i + 3]; + } else { + /* last line; 2nd endpoint is first vertex */ + p_x0 = p[i]; p_y0 = p[i + 1]; + p_x1 = p[0]; p_y1 = p[1]; + } + /* ignore horizontal lines */ + if (p_y0 == p_y1) + continue; + + /* ignore lines that don't cross this y level */ + if ((y < p_y0 && y < p_y1) || (y > p_y0 && y > p_y1)) + continue; + + if (p_x0 == p_x1) { + /* vertical line, x is constant */ + x_new = p_x0; + } else { + /* find crossing (intersection of this line and + * current y level) */ + int num = (y - p_y0) * (p_x1 - p_x0); + int den = (p_y1 - p_y0); + + /* To round to nearest (rather than down) + * half the denominator is either added to + * or subtracted from the numerator, + * depending on whether the numerator and + * denominator have the same sign. */ + num = ((num < 0) == (den < 0)) ? + num + (den / 2) : + num - (den / 2); + x_new = p_x0 + num / den; + } + + /* ignore crossings before current x */ + if (x_new < x || + (!found_span_start && x_new < x0_min) || + (found_span_start && x_new < x1_min)) + continue; + + crossing_value = establish_crossing_value(x_new, y, + p_x0, p_y0, p_x1, p_y1); + + + /* set nearest intersections as filled area endpoints */ + if (!found_span_start && + x_new < *x0 && crossing_value) { + /* nearer than first endpoint */ + *x1 = *x0; + x1c = x0c; + *x0 = x_new; + x0c = 1; + } else if (!found_span_start && + x_new == *x0 && crossing_value) { + /* same as first endpoint */ + x0c++; + } else if (x_new < *x1 && crossing_value) { + /* nearer than second endpoint */ + *x1 = x_new; + x1c = 1; + } else if (x_new == *x1 && crossing_value) { + /* same as second endpoint */ + x1c++; + } + } + /* check whether the span endpoints have been found */ + if (!found_span_start && x0c % 2 == 1) { + /* valid fill start found */ + found_span_start = true; + + } + if (x1c % 2 == 1) { + /* valid fill endpoint found */ + if (!found_span_start) { + /* not got a start yet; use this as start */ + found_span_start = true; + x0c = x1c; + *x0 = *x1; + } else { + /* got valid end of span */ + return true; + } + } + /* if current positions aren't valid endpoints, set new + * minimums after current positions */ + if (!found_span_start) + x0_min = *x0 + 1; + x1_min = *x1 + 1; + + } while (*x1 != INT_MAX); + + /* no spans found */ + return false; } @@ -260,87 +260,87 @@ static bool find_span(const int *p, int n, int x, int y, int *x0, int *x1) */ static bool polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t c) { - int poly_x0, poly_y0; /* Bounding box top left corner */ - int poly_x1, poly_y1; /* Bounding box bottom right corner */ - int i, j; /* indexes */ - int x0, x1; /* filled span extents */ - int y; /* current y coordinate */ - int y_max; /* bottom of plot area */ - nsfb_bbox_t fline; - nsfb_plot_pen_t pen; - - /* find no. of vertex values */ - int v = n * 2; - - /* Can't plot polygons with 2 or fewer vertices */ - if (n <= 2) - return true; + int poly_x0, poly_y0; /* Bounding box top left corner */ + int poly_x1, poly_y1; /* Bounding box bottom right corner */ + int i, j; /* indexes */ + int x0, x1; /* filled span extents */ + int y; /* current y coordinate */ + int y_max; /* bottom of plot area */ + nsfb_bbox_t fline; + nsfb_plot_pen_t pen; - pen.stroke_colour = c; - - /* Find polygon bounding box */ - poly_x0 = poly_x1 = *p; - poly_y0 = poly_y1 = p[1]; - for (i = 2; i < v; i = i + 2) { - j = i + 1; - if (p[i] < poly_x0) - poly_x0 = p[i]; - else if (p[i] > poly_x1) - poly_x1 = p[i]; - if (p[j] < poly_y0) - poly_y0 = p[j]; - else if (p[j] > poly_y1) - poly_y1 = p[j]; - } + /* find no. of vertex values */ + int v = n * 2; - /* Don't try to plot it if it's outside the clip rectangle */ - if (nsfb->clip.y1 < poly_y0 || - nsfb->clip.y0 > poly_y1 || - nsfb->clip.x1 < poly_x0 || - nsfb->clip.x0 > poly_x1) - return true; + /* Can't plot polygons with 2 or fewer vertices */ + if (n <= 2) + return true; - /* Find the top of the important area */ - if (poly_y0 > nsfb->clip.y0) - y = poly_y0; - else - y = nsfb->clip.y0; - - /* Find the bottom of the important area */ - if (poly_y1 < nsfb->clip.y1) - y_max = poly_y1; - else - y_max = nsfb->clip.y1; - - for (; y < y_max; y++) { - x1 = poly_x0 - 1; - /* For each row */ - while (find_span(p, v, x1 + 1, y, &x0, &x1)) { - /* don't draw anything outside clip region */ - if (x1 < nsfb->clip.x0) - continue; - else if (x0 < nsfb->clip.x0) - x0 = nsfb->clip.x0; - if (x0 > nsfb->clip.x1) - break; - else if (x1 > nsfb->clip.x1) - x1 = nsfb->clip.x1; - - fline.x0 = x0; - fline.y0 = y; - fline.x1 = x1; - fline.y1 = y; - - /* draw this filled span on current row */ - nsfb->plotter_fns->line(nsfb, 1, &fline, &pen); - - /* don't look for more spans if already at end of clip - * region or polygon */ - if (x1 == nsfb->clip.x1 || x1 == poly_x1) - break; - } - } + pen.stroke_colour = c; + + /* Find polygon bounding box */ + poly_x0 = poly_x1 = *p; + poly_y0 = poly_y1 = p[1]; + for (i = 2; i < v; i = i + 2) { + j = i + 1; + if (p[i] < poly_x0) + poly_x0 = p[i]; + else if (p[i] > poly_x1) + poly_x1 = p[i]; + if (p[j] < poly_y0) + poly_y0 = p[j]; + else if (p[j] > poly_y1) + poly_y1 = p[j]; + } + + /* Don't try to plot it if it's outside the clip rectangle */ + if (nsfb->clip.y1 < poly_y0 || + nsfb->clip.y0 > poly_y1 || + nsfb->clip.x1 < poly_x0 || + nsfb->clip.x0 > poly_x1) return true; + + /* Find the top of the important area */ + if (poly_y0 > nsfb->clip.y0) + y = poly_y0; + else + y = nsfb->clip.y0; + + /* Find the bottom of the important area */ + if (poly_y1 < nsfb->clip.y1) + y_max = poly_y1; + else + y_max = nsfb->clip.y1; + + for (; y < y_max; y++) { + x1 = poly_x0 - 1; + /* For each row */ + while (find_span(p, v, x1 + 1, y, &x0, &x1)) { + /* don't draw anything outside clip region */ + if (x1 < nsfb->clip.x0) + continue; + else if (x0 < nsfb->clip.x0) + x0 = nsfb->clip.x0; + if (x0 > nsfb->clip.x1) + break; + else if (x1 > nsfb->clip.x1) + x1 = nsfb->clip.x1; + + fline.x0 = x0; + fline.y0 = y; + fline.x1 = x1; + fline.y1 = y; + + /* draw this filled span on current row */ + nsfb->plotter_fns->line(nsfb, 1, &fline, &pen); + + /* don't look for more spans if already at end of clip + * region or polygon */ + if (x1 == nsfb->clip.x1 || x1 == poly_x1) + break; + } + } + return true; } static bool @@ -354,9 +354,9 @@ rectangle(nsfb_t *nsfb, nsfb_bbox_t *rect, pen.stroke_colour = c; pen.stroke_width = line_width; if (dotted || dashed) { - pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN; + pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN; } else { - pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; + pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID; } side[0] = *rect; @@ -543,7 +543,7 @@ static bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c) -/* copy an area of screen from one location to another. +/* copy an area of surface from one location to another. * * @warning This implementation is woefully incomplete! */ @@ -563,7 +563,7 @@ copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) nsfb_plot_add_rect(srcbox, dstbox, &allbox); - nsfb->frontend_rtns->claim(nsfb, &allbox); + nsfb->surface_rtns->claim(nsfb, &allbox); srcptr = (nsfb->ptr + (srcy * nsfb->linelen) + @@ -595,21 +595,23 @@ copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) } } - nsfb->frontend_rtns->update(nsfb, dstbox); + nsfb->surface_rtns->update(nsfb, dstbox); return true; } + + static bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1, int angle2, nsfb_colour_t c) { - nsfb=nsfb; - x = x; - y = y; - radius = radius; - c = c; - angle1=angle1; - angle2=angle2; - return true; + nsfb=nsfb; + x = x; + y = y; + radius = radius; + c = c; + angle1=angle1; + angle2=angle2; + return true; } #define N_SEG 30 @@ -654,14 +656,14 @@ cubic_points(unsigned int pointc, point[cur_point].y = y; if ((point[cur_point].x != point[cur_point - 1].x) || (point[cur_point].y != point[cur_point - 1].y)) - cur_point++; + cur_point++; } point[cur_point].x = curve->x1; point[cur_point].y = curve->y1; if ((point[cur_point].x != point[cur_point - 1].x) || (point[cur_point].y != point[cur_point - 1].y)) - cur_point++; + cur_point++; return cur_point; } @@ -711,14 +713,14 @@ quadratic_points(unsigned int pointc, point[cur_point].y = y; if ((point[cur_point].x != point[cur_point - 1].x) || (point[cur_point].y != point[cur_point - 1].y)) - cur_point++; + cur_point++; } point[cur_point].x = curve->x1; point[cur_point].y = curve->y1; if ((point[cur_point].x != point[cur_point - 1].x) || (point[cur_point].y != point[cur_point - 1].y)) - cur_point++; + cur_point++; return cur_point; } @@ -854,34 +856,57 @@ bool select_plotters(nsfb_t *nsfb) { const nsfb_plotter_fns_t *table = NULL; - switch (nsfb->bpp) { - /* case 1: - table = &_nsfb_1bpp_plotters; - break; - */ - case 8: - table = &_nsfb_8bpp_plotters; - break; - - case 16: - table = &_nsfb_16bpp_plotters; - break; - - /* - case 24: - table = &_nsfb_24bpp_plotters; - break; - */ - case 32: - table = &_nsfb_32bpp_plotters; - break; + switch (nsfb->format) { + case NSFB_FMT_XBGR8888: /* 32bpp Blue Green Red */ + case NSFB_FMT_ABGR8888: /* 32bpp Alpga Blue Green Red */ + table = &_nsfb_32bpp_plotters; + nsfb->bpp = 32; + break; + + case NSFB_FMT_XRGB8888: /* 32bpp Red Green Blue */ + case NSFB_FMT_ARGB8888: /* 32bpp Alpga Red Green Blue */ + table = &_nsfb_32bpp_plotters; + nsfb->bpp = 32; + break; + + + case NSFB_FMT_RGB888: /* 24 bpp Alpga Red Green Blue */ +#ifdef ENABLE_24_BPP + table = &_nsfb_24bpp_plotters; + nsfb->bpp = 24; + break; +#else + return false; +#endif + + case NSFB_FMT_ARGB1555: /* 16 bpp 555 */ + case NSFB_FMT_RGB565: /* 16 bpp 565 */ + table = &_nsfb_16bpp_plotters; + nsfb->bpp = 16; + break; + + case NSFB_FMT_I8: /* 8bpp indexed */ + table = &_nsfb_8bpp_plotters; + nsfb->bpp = 8; + break; + + case NSFB_FMT_I1: /* black and white */ +#ifdef ENABLE_1_BPP + table = &_nsfb_1bpp_plotters; + nsfb->bpp = 1 + break; +#else + return false; +#endif + + case NSFB_FMT_ANY: /* No specific format - use surface default */ default: - return false; + return false; } if (nsfb->plotter_fns != NULL) - free(nsfb->plotter_fns); + free(nsfb->plotter_fns); nsfb->plotter_fns = calloc(1, sizeof(nsfb_plotter_fns_t)); memcpy(nsfb->plotter_fns, table, sizeof(nsfb_plotter_fns_t)); @@ -909,3 +934,10 @@ bool select_plotters(nsfb_t *nsfb) return true; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/surface/Makefile b/src/surface/Makefile index 6eddcb6..21547a5 100644 --- a/src/surface/Makefile +++ b/src/surface/Makefile @@ -1,5 +1,5 @@ # Sources -DIR_SOURCES := surface.c vnc.c able.c ram.c linux.c +DIR_SOURCES := surface.c able.c ram.c linux.c ifeq ($(NSFB_SDL_AVAILABLE),yes) DIR_SOURCES := $(DIR_SOURCES) sdl.c @@ -9,4 +9,8 @@ ifeq ($(NSFB_XCB_AVAILABLE),yes) DIR_SOURCES := $(DIR_SOURCES) x.c endif +ifeq ($(NSFB_VNC_AVAILABLE),yes) + DIR_SOURCES := $(DIR_SOURCES) vnc.c +endif + include build/makefiles/Makefile.subdir diff --git a/src/surface/able.c b/src/surface/able.c index d7b9226..dd4c340 100644 --- a/src/surface/able.c +++ b/src/surface/able.c @@ -13,18 +13,18 @@ #include "libnsfb_plot.h" #include "libnsfb_event.h" #include "nsfb.h" -#include "frontend.h" +#include "surface.h" #define UNUSED(x) ((x) = (x)) -static int able_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static int able_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { - if (nsfb->frontend_priv != NULL) + if (nsfb->surface_priv != NULL) return -1; /* if were already initialised fail */ nsfb->width = width; nsfb->height = height; - nsfb->bpp = bpp; + nsfb->format = format; return 0; } @@ -49,11 +49,11 @@ static bool able_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) return false; } -const nsfb_frontend_rtns_t able_rtns = { +const nsfb_surface_rtns_t able_rtns = { .initialise = able_initialise, .finalise = able_finalise, .input = able_input, .geometry = able_set_geometry, }; -NSFB_FRONTEND_DEF(able, NSFB_FRONTEND_ABLE, &able_rtns) +NSFB_SURFACE_DEF(able, NSFB_SURFACE_ABLE, &able_rtns) diff --git a/src/surface/linux.c b/src/surface/linux.c index 3394f85..8c9ffec 100644 --- a/src/surface/linux.c +++ b/src/surface/linux.c @@ -16,20 +16,20 @@ #include "nsfb.h" #include "plot.h" -#include "frontend.h" +#include "surface.h" #include "cursor.h" #define UNUSED(x) ((x) = (x)) -static int linux_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static int linux_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { - if (nsfb->frontend_priv != NULL) + if (nsfb->surface_priv != NULL) return -1; /* if we are already initialised fail */ nsfb->width = width; nsfb->height = height; - nsfb->bpp = bpp; + nsfb->format = format; /* select default sw plotters for bpp */ select_plotters(nsfb); @@ -39,7 +39,7 @@ static int linux_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) static int linux_initialise(nsfb_t *nsfb) { - if (nsfb->frontend_priv != NULL) + if (nsfb->surface_priv != NULL) return -1; /* sanity checked depth. */ @@ -122,7 +122,7 @@ static int linux_update(nsfb_t *nsfb, nsfb_bbox_t *box) return 0; } -const nsfb_frontend_rtns_t linux_rtns = { +const nsfb_surface_rtns_t linux_rtns = { .initialise = linux_initialise, .finalise = linux_finalise, .input = linux_input, @@ -132,4 +132,4 @@ const nsfb_frontend_rtns_t linux_rtns = { .geometry = linux_set_geometry, }; -NSFB_FRONTEND_DEF(linux, NSFB_FRONTEND_LINUX, &linux_rtns) +NSFB_SURFACE_DEF(linux, NSFB_SURFACE_LINUX, &linux_rtns) diff --git a/src/surface/ram.c b/src/surface/ram.c index 0948a5d..4deabda 100644 --- a/src/surface/ram.c +++ b/src/surface/ram.c @@ -8,36 +8,77 @@ #include #include +#include #include "libnsfb.h" #include "libnsfb_plot.h" #include "libnsfb_event.h" + #include "nsfb.h" -#include "frontend.h" +#include "surface.h" +#include "plot.h" #define UNUSED(x) ((x) = (x)) -static int ram_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static int ram_defaults(nsfb_t *nsfb) { - if (nsfb->frontend_priv != NULL) - return -1; /* if were already initialised fail */ + nsfb->width = 0; + nsfb->height = 0; + nsfb->format = NSFB_FMT_ABGR8888; - nsfb->width = width; - nsfb->height = height; - nsfb->bpp = bpp; + /* select default sw plotters for bpp */ + select_plotters(nsfb); return 0; } + static int ram_initialise(nsfb_t *nsfb) { - UNUSED(nsfb); + size_t size = (nsfb->width * nsfb->height * nsfb->bpp) / 8; + + nsfb->ptr = realloc(nsfb->ptr, size); + nsfb->linelen = (nsfb->width * nsfb->bpp) / 8; + + return 0; +} + +static int ram_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) +{ + int startsize; + int endsize; + + startsize = (nsfb->width * nsfb->height * nsfb->bpp) / 8; + + if (width > 0) { + nsfb->width = width; + } + + if (height > 0) { + nsfb->height = height; + } + + if (format != NSFB_FMT_ANY) { + nsfb->format = format; + } + + /* select soft plotters appropriate for format */ + select_plotters(nsfb); + + endsize = (nsfb->width * nsfb->height * nsfb->bpp) / 8; + if ((nsfb->ptr != NULL) && (startsize != endsize)) { + nsfb->ptr = realloc(nsfb->ptr, endsize); + } + nsfb->linelen = (nsfb->width * nsfb->bpp) / 8; + return 0; } + static int ram_finalise(nsfb_t *nsfb) { - UNUSED(nsfb); + free(nsfb->ptr); + return 0; } @@ -49,11 +90,19 @@ static bool ram_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) return false; } -const nsfb_frontend_rtns_t ram_rtns = { +const nsfb_surface_rtns_t ram_rtns = { + .defaults = ram_defaults, .initialise = ram_initialise, .finalise = ram_finalise, .input = ram_input, .geometry = ram_set_geometry, }; -NSFB_FRONTEND_DEF(ram, NSFB_FRONTEND_RAM, &ram_rtns) +NSFB_SURFACE_DEF(ram, NSFB_SURFACE_RAM, &ram_rtns) + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/surface/sdl.c b/src/surface/sdl.c index f0f48af..2a905f5 100644 --- a/src/surface/sdl.c +++ b/src/surface/sdl.c @@ -16,7 +16,7 @@ #include "libnsfb_plot_util.h" #include "nsfb.h" -#include "frontend.h" +#include "surface.h" #include "plot.h" #include "cursor.h" @@ -350,7 +350,7 @@ enum nsfb_key_code_e sdl_nsfb_map[] = { static void set_palette(nsfb_t *nsfb) { - SDL_Surface *sdl_screen = nsfb->frontend_priv; + SDL_Surface *sdl_screen = nsfb->surface_priv; SDL_Color palette[256]; int rloop, gloop, bloop; int loop = 0; @@ -363,8 +363,8 @@ set_palette(nsfb_t *nsfb) palette[loop].g = (gloop << 5) | (gloop << 2) | (gloop >> 1); palette[loop].b = (bloop << 6) | (bloop << 4) | (bloop << 2) | (bloop); nsfb->palette[loop] = palette[loop].r | - palette[loop].g << 8 | - palette[loop].b << 16; + palette[loop].g << 8 | + palette[loop].b << 16; loop++; } } @@ -380,7 +380,7 @@ sdlcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) { SDL_Rect src; SDL_Rect dst; - SDL_Surface *sdl_screen = nsfb->frontend_priv; + SDL_Surface *sdl_screen = nsfb->surface_priv; nsfb_bbox_t allbox; struct nsfb_cursor_s *cursor = nsfb->cursor; @@ -416,16 +416,16 @@ sdlcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) } -static int sdl_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static int sdl_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { - if (nsfb->frontend_priv != NULL) - return -1; /* if were already initialised fail */ + if (nsfb->surface_priv != NULL) + return -1; /* fail if surface already initialised */ nsfb->width = width; nsfb->height = height; - nsfb->bpp = bpp; + nsfb->format = format; - /* select default sw plotters for bpp */ + /* select default sw plotters for format */ select_plotters(nsfb); nsfb->plotter_fns->copy = sdlcopy; @@ -437,7 +437,7 @@ static int sdl_initialise(nsfb_t *nsfb) { SDL_Surface *sdl_screen; - if (nsfb->frontend_priv != NULL) + if (nsfb->surface_priv != NULL) return -1; /* sanity checked depth. */ @@ -449,7 +449,6 @@ static int sdl_initialise(nsfb_t *nsfb) fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); return -1; } - atexit(SDL_Quit); sdl_screen = SDL_SetVideoMode(nsfb->width, nsfb->height, @@ -461,7 +460,7 @@ static int sdl_initialise(nsfb_t *nsfb) return -1; } - nsfb->frontend_priv = sdl_screen; + nsfb->surface_priv = sdl_screen; if (nsfb->bpp == 8) set_palette(nsfb); @@ -478,6 +477,7 @@ static int sdl_initialise(nsfb_t *nsfb) static int sdl_finalise(nsfb_t *nsfb) { nsfb=nsfb; + SDL_Quit(); return 0; } @@ -518,92 +518,98 @@ static bool sdl_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) SDL_RemoveTimer(tid); } } else { - got_event = SDL_WaitEvent(&sdlevent); + got_event = SDL_WaitEvent(&sdlevent); } } /* Do nothing if there was no event */ - if (got_event == 0) + if (got_event == 0) { return false; + } event->type = NSFB_EVENT_NONE; switch (sdlevent.type) { - case SDL_KEYDOWN: - event->type = NSFB_EVENT_KEY_DOWN; - event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym]; - break; - - case SDL_KEYUP: - event->type = NSFB_EVENT_KEY_UP; - event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym]; - break; - - case SDL_MOUSEBUTTONDOWN: - event->type = NSFB_EVENT_KEY_DOWN; - - switch (sdlevent.button.button) { - - case SDL_BUTTON_LEFT: - event->value.keycode = NSFB_KEY_MOUSE_1; - break; - - case SDL_BUTTON_MIDDLE: - event->value.keycode = NSFB_KEY_MOUSE_2; - break; - - case SDL_BUTTON_RIGHT: - event->value.keycode = NSFB_KEY_MOUSE_3; - break; - - case SDL_BUTTON_WHEELUP: - event->value.keycode = NSFB_KEY_MOUSE_4; - break; - - case SDL_BUTTON_WHEELDOWN: - event->value.keycode = NSFB_KEY_MOUSE_5; - break; - } - break; - - case SDL_MOUSEBUTTONUP: - event->type = NSFB_EVENT_KEY_UP; - - switch (sdlevent.button.button) { - - case SDL_BUTTON_LEFT: - event->value.keycode = NSFB_KEY_MOUSE_1; - break; - - case SDL_BUTTON_MIDDLE: - event->value.keycode = NSFB_KEY_MOUSE_2; - break; - - case SDL_BUTTON_RIGHT: - event->value.keycode = NSFB_KEY_MOUSE_3; - break; - - case SDL_BUTTON_WHEELUP: - event->value.keycode = NSFB_KEY_MOUSE_4; - break; - - case SDL_BUTTON_WHEELDOWN: - event->value.keycode = NSFB_KEY_MOUSE_5; - break; - } - break; - - case SDL_MOUSEMOTION: - event->type = NSFB_EVENT_MOVE_ABSOLUTE; - event->value.vector.x = sdlevent.motion.x; - event->value.vector.y = sdlevent.motion.y; - event->value.vector.z = 0; - break; - - case SDL_QUIT: - event->type = NSFB_EVENT_CONTROL; - event->value.controlcode = NSFB_CONTROL_QUIT; - break; + case SDL_KEYDOWN: + event->type = NSFB_EVENT_KEY_DOWN; + event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym]; + break; + + case SDL_KEYUP: + event->type = NSFB_EVENT_KEY_UP; + event->value.keycode = sdl_nsfb_map[sdlevent.key.keysym.sym]; + break; + + case SDL_MOUSEBUTTONDOWN: + event->type = NSFB_EVENT_KEY_DOWN; + + switch (sdlevent.button.button) { + + case SDL_BUTTON_LEFT: + event->value.keycode = NSFB_KEY_MOUSE_1; + break; + + case SDL_BUTTON_MIDDLE: + event->value.keycode = NSFB_KEY_MOUSE_2; + break; + + case SDL_BUTTON_RIGHT: + event->value.keycode = NSFB_KEY_MOUSE_3; + break; + + case SDL_BUTTON_WHEELUP: + event->value.keycode = NSFB_KEY_MOUSE_4; + break; + + case SDL_BUTTON_WHEELDOWN: + event->value.keycode = NSFB_KEY_MOUSE_5; + break; + } + break; + + case SDL_MOUSEBUTTONUP: + event->type = NSFB_EVENT_KEY_UP; + + switch (sdlevent.button.button) { + + case SDL_BUTTON_LEFT: + event->value.keycode = NSFB_KEY_MOUSE_1; + break; + + case SDL_BUTTON_MIDDLE: + event->value.keycode = NSFB_KEY_MOUSE_2; + break; + + case SDL_BUTTON_RIGHT: + event->value.keycode = NSFB_KEY_MOUSE_3; + break; + + case SDL_BUTTON_WHEELUP: + event->value.keycode = NSFB_KEY_MOUSE_4; + break; + + case SDL_BUTTON_WHEELDOWN: + event->value.keycode = NSFB_KEY_MOUSE_5; + break; + } + break; + + case SDL_MOUSEMOTION: + event->type = NSFB_EVENT_MOVE_ABSOLUTE; + event->value.vector.x = sdlevent.motion.x; + event->value.vector.y = sdlevent.motion.y; + event->value.vector.z = 0; + break; + + case SDL_QUIT: + event->type = NSFB_EVENT_CONTROL; + event->value.controlcode = NSFB_CONTROL_QUIT; + break; + + case SDL_USEREVENT: + event->type = NSFB_EVENT_CONTROL; + event->value.controlcode = NSFB_CONTROL_TIMEOUT; + break; } @@ -625,7 +631,7 @@ static int sdl_claim(nsfb_t *nsfb, nsfb_bbox_t *box) static int sdl_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) { - SDL_Surface *sdl_screen = nsfb->frontend_priv; + SDL_Surface *sdl_screen = nsfb->surface_priv; nsfb_bbox_t redraw; nsfb_bbox_t fbarea; @@ -659,7 +665,7 @@ sdl_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) static int sdl_update(nsfb_t *nsfb, nsfb_bbox_t *box) { - SDL_Surface *sdl_screen = nsfb->frontend_priv; + SDL_Surface *sdl_screen = nsfb->surface_priv; struct nsfb_cursor_s *cursor = nsfb->cursor; if ((cursor != NULL) && @@ -676,7 +682,7 @@ static int sdl_update(nsfb_t *nsfb, nsfb_bbox_t *box) return 0; } -const nsfb_frontend_rtns_t sdl_rtns = { +const nsfb_surface_rtns_t sdl_rtns = { .initialise = sdl_initialise, .finalise = sdl_finalise, .input = sdl_input, @@ -686,4 +692,11 @@ const nsfb_frontend_rtns_t sdl_rtns = { .geometry = sdl_set_geometry, }; -NSFB_FRONTEND_DEF(sdl, NSFB_FRONTEND_SDL, &sdl_rtns) +NSFB_SURFACE_DEF(sdl, NSFB_SURFACE_SDL, &sdl_rtns) + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/surface/surface.c b/src/surface/surface.c index 6fa65a8..b2cf769 100644 --- a/src/surface/surface.c +++ b/src/surface/surface.c @@ -12,40 +12,41 @@ #include #include -#include "frontend.h" +#include "surface.h" #include "plot.h" -#define MAX_FRONTENDS 16 +#define MAX_SURFACES 16 -struct nsfb_frontend_s { - enum nsfb_frontend_e type; - const nsfb_frontend_rtns_t *rtns; +struct nsfb_surface_s { + enum nsfb_type_e type; + const nsfb_surface_rtns_t *rtns; const char *name; }; -static struct nsfb_frontend_s frontends[MAX_FRONTENDS]; -static int frontend_count = 0; +static struct nsfb_surface_s surfaces[MAX_SURFACES]; +static int surface_count = 0; -/* internal routine which lets frontends register their presence at runtime */ -void _nsfb_register_frontend(const enum nsfb_frontend_e type, - const nsfb_frontend_rtns_t *rtns, +/* internal routine which lets surfaces register their presence at runtime */ +void _nsfb_register_surface(const enum nsfb_type_e type, + const nsfb_surface_rtns_t *rtns, const char *name) { - if (frontend_count >= MAX_FRONTENDS) - return; /* no space for additional frontends */ + if (surface_count >= MAX_SURFACES) + return; /* no space for additional surfaces */ - frontends[frontend_count].type = type; - frontends[frontend_count].rtns = rtns; - frontends[frontend_count].name = name; - frontend_count++; + surfaces[surface_count].type = type; + surfaces[surface_count].rtns = rtns; + surfaces[surface_count].name = name; + surface_count++; } -/* default frontend implementations */ -static int frontend_defaults(nsfb_t *nsfb) +/* default surface implementations */ + +static int surface_defaults(nsfb_t *nsfb) { nsfb->width = 800; nsfb->height = 600; - nsfb->bpp = 32; + nsfb->format = NSFB_FMT_XRGB8888; /* select default sw plotters for bpp */ select_plotters(nsfb); @@ -53,75 +54,93 @@ static int frontend_defaults(nsfb_t *nsfb) return 0; } -static int frontend_claim(nsfb_t *nsfb, nsfb_bbox_t *box) +static int surface_claim(nsfb_t *nsfb, nsfb_bbox_t *box) { nsfb=nsfb; box=box; return 0; } -static int frontend_update(nsfb_t *nsfb, nsfb_bbox_t *box) +static int surface_update(nsfb_t *nsfb, nsfb_bbox_t *box) { nsfb=nsfb; box=box; return 0; } -static int frontend_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) +static int surface_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) { nsfb=nsfb; cursor=cursor; return 0; } -nsfb_frontend_rtns_t *nsfb_frontend_get_rtns(enum nsfb_frontend_e type) +/* exported interface documented in surface.h */ +nsfb_surface_rtns_t * +nsfb_surface_get_rtns(enum nsfb_type_e type) { int fend_loop; - nsfb_frontend_rtns_t *rtns = NULL; - - for (fend_loop = 0; fend_loop < frontend_count; fend_loop++) { - if (frontends[fend_loop].type == type) { - rtns = malloc(sizeof(nsfb_frontend_rtns_t)); - memcpy(rtns, - frontends[fend_loop].rtns, - sizeof(nsfb_frontend_rtns_t)); - - /* frontend must have an initialisor, finaliser and input method */ - if ((rtns->initialise == NULL) || - (rtns->finalise == NULL) || - (rtns->input == NULL) ) { - free(rtns); - rtns = NULL; - } else { - /* The rest may be empty but to avoid the null check every time - * provide default implementations. - */ - if (rtns->defaults == NULL) - rtns->defaults = frontend_defaults; - - if (rtns->claim == NULL) - rtns->claim = frontend_claim; - - if (rtns->update == NULL) - rtns->update = frontend_update; - - if (rtns->cursor == NULL) - rtns->cursor = frontend_cursor; - } - + nsfb_surface_rtns_t *rtns = NULL; + + for (fend_loop = 0; fend_loop < surface_count; fend_loop++) { + /* surface type must match and have a initialisor, finaliser + * and input method + */ + if ((surfaces[fend_loop].type == type) && + (surfaces[fend_loop].rtns->initialise != NULL) && + (surfaces[fend_loop].rtns->finalise != NULL) && + (surfaces[fend_loop].rtns->input != NULL) ) { + + rtns = malloc(sizeof(nsfb_surface_rtns_t)); + if (rtns == NULL) { + continue; + } + + memcpy(rtns, + surfaces[fend_loop].rtns, + sizeof(nsfb_surface_rtns_t)); + + /* The rest may be empty but to avoid the null check every time + * provide default implementations. + */ + if (rtns->defaults == NULL) { + rtns->defaults = surface_defaults; + } + + if (rtns->claim == NULL) { + rtns->claim = surface_claim; + } + + if (rtns->update == NULL) { + rtns->update = surface_update; + } + + if (rtns->cursor == NULL) { + rtns->cursor = surface_cursor; + } + break; } } return rtns; } -enum nsfb_frontend_e nsfb_frontend_from_name(const char *name) +/* exported interface defined in libnsfb.h */ +enum nsfb_type_e +nsfb_type_from_name(const char *name) { int fend_loop; - for (fend_loop = 0; fend_loop < frontend_count; fend_loop++) { - if (strcmp(frontends[fend_loop].name, name) == 0) - return frontends[fend_loop].type; + for (fend_loop = 0; fend_loop < surface_count; fend_loop++) { + if (strcmp(surfaces[fend_loop].name, name) == 0) + return surfaces[fend_loop].type; } - return NSFB_FRONTEND_NONE; + return NSFB_SURFACE_NONE; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/surface/vnc.c b/src/surface/vnc.c index eb6d6ff..eb32560 100644 --- a/src/surface/vnc.c +++ b/src/surface/vnc.c @@ -9,51 +9,559 @@ #include #include +#include +#include + #include "libnsfb.h" #include "libnsfb_event.h" #include "libnsfb_plot.h" + #include "nsfb.h" -#include "frontend.h" +#include "surface.h" +#include "plot.h" +#include "cursor.h" #define UNUSED(x) ((x) = (x)) -static int vnc_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static nsfb_event_t *gevent; + +/* vnc special set codes */ +static enum nsfb_key_code_e vnc_nsfb_map[256] = { + NSFB_KEY_UNKNOWN, /* 0x00 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_BACKSPACE, /* 0x08 */ + NSFB_KEY_TAB, + NSFB_KEY_LF, + NSFB_KEY_CLEAR, + NSFB_KEY_UNKNOWN, + NSFB_KEY_RETURN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x10 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_RETURN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x18 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_ESCAPE, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_COMPOSE, /* 0x20 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x28 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x30 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x38 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x40 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x48 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_HOME, /* 0x50 */ + NSFB_KEY_LEFT, + NSFB_KEY_UP, + NSFB_KEY_RIGHT, + NSFB_KEY_DOWN, + NSFB_KEY_PAGEUP, + NSFB_KEY_PAGEDOWN, + NSFB_KEY_END, + NSFB_KEY_HOME, /* 0x58 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x60 */ + NSFB_KEY_PRINT, + NSFB_KEY_HELP, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNDO, + NSFB_KEY_UNKNOWN, + NSFB_KEY_MENU, + NSFB_KEY_UNKNOWN, /* 0x68 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_BREAK, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x70 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x78 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_MODE, + NSFB_KEY_NUMLOCK, + NSFB_KEY_UNKNOWN, /* 0x80 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x88 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_KP_ENTER, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x90 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0x98 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xA0 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xA8 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_KP_MULTIPLY, + NSFB_KEY_KP_PLUS, + NSFB_KEY_UNKNOWN, + NSFB_KEY_KP_MINUS, + NSFB_KEY_KP_PERIOD, + NSFB_KEY_KP_DIVIDE, + NSFB_KEY_KP0, /* 0xB0 */ + NSFB_KEY_KP1, + NSFB_KEY_KP2, + NSFB_KEY_KP3, + NSFB_KEY_KP4, + NSFB_KEY_KP5, + NSFB_KEY_KP6, + NSFB_KEY_KP7, + NSFB_KEY_KP8, /* 0xB8 */ + NSFB_KEY_KP9, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_KP_EQUALS, + NSFB_KEY_F1, + NSFB_KEY_F2, + NSFB_KEY_F3, /* 0xC0 */ + NSFB_KEY_F4, + NSFB_KEY_F5, + NSFB_KEY_F6, + NSFB_KEY_F7, + NSFB_KEY_F8, + NSFB_KEY_F9, + NSFB_KEY_F10, + NSFB_KEY_F11, /* 0xC8 */ + NSFB_KEY_F12, + NSFB_KEY_F13, + NSFB_KEY_F14, + NSFB_KEY_F15, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xD0 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xD8 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xE0 */ + NSFB_KEY_LSHIFT, + NSFB_KEY_RSHIFT, + NSFB_KEY_LCTRL, + NSFB_KEY_RCTRL, + NSFB_KEY_CAPSLOCK, + NSFB_KEY_SCROLLOCK, + NSFB_KEY_LMETA, + NSFB_KEY_RMETA, /* 0xE8 */ + NSFB_KEY_LALT, + NSFB_KEY_RALT, + NSFB_KEY_LSUPER, + NSFB_KEY_RSUPER, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xF0 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, /* 0xF8 */ + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_UNKNOWN, + NSFB_KEY_DELETE, +}; + + +static void vnc_doptr(int buttonMask,int x,int y,rfbClientPtr cl) +{ + static int prevbuttonMask = 0; + + UNUSED(cl); + + if (prevbuttonMask != buttonMask) { + /* button click */ + if (((prevbuttonMask ^ buttonMask) & 0x01) == 0x01) { + if ((buttonMask & 0x01) == 0x01) { + gevent->type = NSFB_EVENT_KEY_DOWN; + } else { + gevent->type = NSFB_EVENT_KEY_UP; + } + gevent->value.keycode = NSFB_KEY_MOUSE_1; + } else if (((prevbuttonMask ^ buttonMask) & 0x02) == 0x02) { + if ((buttonMask & 0x01) == 0x01) { + gevent->type = NSFB_EVENT_KEY_DOWN; + } else { + gevent->type = NSFB_EVENT_KEY_UP; + } + gevent->value.keycode = NSFB_KEY_MOUSE_2; + } else if (((prevbuttonMask ^ buttonMask) & 0x04) == 0x04) { + if ((buttonMask & 0x01) == 0x01) { + gevent->type = NSFB_EVENT_KEY_DOWN; + } else { + gevent->type = NSFB_EVENT_KEY_UP; + } + gevent->value.keycode = NSFB_KEY_MOUSE_3; + } else if (((prevbuttonMask ^ buttonMask) & 0x08) == 0x08) { + if ((buttonMask & 0x01) == 0x01) { + gevent->type = NSFB_EVENT_KEY_DOWN; + } else { + gevent->type = NSFB_EVENT_KEY_UP; + } + gevent->value.keycode = NSFB_KEY_MOUSE_4; + } else if (((prevbuttonMask ^ buttonMask) & 0x10) == 0x10) { + if ((buttonMask & 0x01) == 0x01) { + gevent->type = NSFB_EVENT_KEY_DOWN; + } else { + gevent->type = NSFB_EVENT_KEY_UP; + } + gevent->value.keycode = NSFB_KEY_MOUSE_5; + } + prevbuttonMask = buttonMask; + } else { + gevent->type = NSFB_EVENT_MOVE_ABSOLUTE; + gevent->value.vector.x = x; + gevent->value.vector.y = y; + gevent->value.vector.z = 0; + } + +} + + +static void vnc_dokey(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + enum nsfb_key_code_e keycode = NSFB_KEY_UNKNOWN; + + UNUSED(cl); + + if ((key >= XK_space) && (key <= XK_asciitilde)) { + /* ascii codes line up */ + keycode = key; + } else if ((key & 0xff00) == 0xff00) { + /* bottom 8bits of keysyms in this range map via table */ + keycode = vnc_nsfb_map[(key & 0xff)]; + } + + if (down == 0) { + /* key up */ + gevent->type = NSFB_EVENT_KEY_UP; + } else { + /* key down */ + gevent->type = NSFB_EVENT_KEY_DOWN; + } + gevent->value.keycode = keycode; + +} + + +static int vnc_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { - if (nsfb->frontend_priv != NULL) - return -1; /* if were already initialised fail */ + if (nsfb->surface_priv != NULL) + return -1; /* fail if surface already initialised */ + + if (width > 0) { + nsfb->width = width; + } + + if (height > 0) { + nsfb->height = height; + } + + if (format != NSFB_FMT_ANY) { + nsfb->format = format; + } - nsfb->width = width; - nsfb->height = height; - nsfb->bpp = bpp; + /* select soft plotters appropriate for format */ + select_plotters(nsfb); return 0; } static int vnc_initialise(nsfb_t *nsfb) { - UNUSED(nsfb); + rfbScreenInfoPtr vncscreen; + int argc = 0; + char **argv = NULL; + + if (nsfb->surface_priv != NULL) + return -1; /* fail if surface already initialised */ + + /* sanity checked depth. */ + if (nsfb->bpp != 32) + return -1; + + /* create vnc screen with 8bits per sample, three samples per + * pixel and 4 bytes per pixel. */ + vncscreen = rfbGetScreen(&argc, argv, + nsfb->width, nsfb->height, + 8, 3, (nsfb->bpp / 8)); + + if (vncscreen == NULL) { + /* Note libvncserver does not check its own allocations/error + * paths so the faliure mode of the rfbGetScreen is to segfault. + */ + return -1; + } + + vncscreen->frameBuffer = malloc(nsfb->width * nsfb->height * (nsfb->bpp / 8)); + + if (vncscreen->frameBuffer == NULL) { + rfbScreenCleanup(vncscreen); + return -1; + } + + + switch (nsfb->bpp) { + case 8: + break; + + case 16: + vncscreen->serverFormat.trueColour=TRUE; + vncscreen->serverFormat.redShift = 11; + vncscreen->serverFormat.greenShift = 5; + vncscreen->serverFormat.blueShift = 0; + vncscreen->serverFormat.redMax = 31; + vncscreen->serverFormat.greenMax = 63; + vncscreen->serverFormat.blueMax = 31; + break; + + case 32: + vncscreen->serverFormat.trueColour=TRUE; + vncscreen->serverFormat.redShift = 16; + vncscreen->serverFormat.greenShift = 8; + vncscreen->serverFormat.blueShift = 0; + break; + } + + vncscreen->alwaysShared = TRUE; + vncscreen->autoPort = 1; + vncscreen->ptrAddEvent = vnc_doptr; + vncscreen->kbdAddEvent = vnc_dokey; + + rfbInitServer(vncscreen); + + /* keep parameters */ + nsfb->surface_priv = vncscreen; + nsfb->ptr = (uint8_t *)vncscreen->frameBuffer; + nsfb->linelen = (nsfb->width * nsfb->bpp) / 8; + return 0; } static int vnc_finalise(nsfb_t *nsfb) { - UNUSED(nsfb); + rfbScreenInfoPtr vncscreen = nsfb->surface_priv; + + if (vncscreen != NULL) { + rfbScreenCleanup(vncscreen); + } + + return 0; +} + + +static int vnc_update(nsfb_t *nsfb, nsfb_bbox_t *box) +{ + rfbScreenInfoPtr vncscreen = nsfb->surface_priv; + + rfbMarkRectAsModified(vncscreen, box->x0, box->y0, box->x1, box->y1); + return 0; } + static bool vnc_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) { - UNUSED(nsfb); - UNUSED(event); - UNUSED(timeout); + rfbScreenInfoPtr vncscreen = nsfb->surface_priv; + int ret; + + if (vncscreen != NULL) { + + gevent = event; /* blergh - have to use global state to pass data */ + + /* set default to timeout */ + event->type = NSFB_EVENT_CONTROL; + event->value.controlcode = NSFB_CONTROL_TIMEOUT; + + ret = rfbProcessEvents(vncscreen, timeout * 1000); + return true; + } + return false; } -const nsfb_frontend_rtns_t vnc_rtns = { +static int +vnc_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) +{ + rfbScreenInfoPtr vncscreen = nsfb->surface_priv; + rfbCursorPtr vnccursor = calloc(1,sizeof(rfbCursor)); + int rwidth; /* rounded width */ + int row; + int col; + const nsfb_colour_t *pixel; + uint8_t bit; + + rwidth = (cursor->bmp_width + 7) / 8; + + vnccursor->cleanup = 1; /* rfb lib will free this allocation */ + vnccursor->width = cursor->bmp_width; + vnccursor->height = cursor->bmp_height; + vnccursor->foreRed = vnccursor->foreGreen = vnccursor->foreBlue = 0xffff; + + vnccursor->source = calloc(rwidth, vnccursor->height); + vnccursor->cleanupSource = 1; /* rfb lib will free this allocation */ + vnccursor->mask = calloc(rwidth, vnccursor->height); + vnccursor->cleanupMask = 1; /* rfb lib will free this allocation */ + + for (row = 0, pixel = cursor->pixel; row < vnccursor->height; row++) { + for (col = 0, bit = 0x80; + col < vnccursor->width; + col++, bit = (bit & 1)? 0x80 : bit>>1, pixel++) { + + /* pixel luminance more than 50% */ + if ((((((*pixel) & 0xff) * 77) + + ((((*pixel) & 0xff00) >> 8) * 151) + + ((((*pixel) & 0xff0000) >> 16) * 28)) / 256) > 128) { + + vnccursor->source[row * rwidth + col/8] |= bit; + } + if (((*pixel) & 0xff000000) != 0) { + vnccursor->mask[row * rwidth + col/8] |= bit; + } + } + } + + rfbSetCursor(vncscreen, vnccursor); + return true; +} + +const nsfb_surface_rtns_t vnc_rtns = { .initialise = vnc_initialise, .finalise = vnc_finalise, .input = vnc_input, + .update = vnc_update, + .cursor = vnc_cursor, .geometry = vnc_set_geometry, }; -NSFB_FRONTEND_DEF(vnc, NSFB_FRONTEND_VNC, &vnc_rtns) +NSFB_SURFACE_DEF(vnc, NSFB_SURFACE_VNC, &vnc_rtns) + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/src/surface/x.c b/src/surface/x.c index a8c06ee..ccefacf 100644 --- a/src/surface/x.c +++ b/src/surface/x.c @@ -29,7 +29,7 @@ #include "libnsfb_plot_util.h" #include "nsfb.h" -#include "frontend.h" +#include "surface.h" #include "plot.h" #include "cursor.h" @@ -390,7 +390,7 @@ xkeysym_to_nsfbkeycode(xcb_keysym_t ks) static void set_palette(nsfb_t *nsfb) { - X_Surface *x_screen = nsfb->frontend_priv; + X_Surface *x_screen = nsfb->surface_priv; X_Color palette[256]; int rloop, gloop, bloop; int loop = 0; @@ -469,7 +469,7 @@ update_and_redraw_pixmap(xstate_t *xstate, int x, int y, int width, int height) static bool xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) { - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; nsfb_bbox_t allbox; struct nsfb_cursor_s *cursor = nsfb->cursor; uint8_t *srcptr; @@ -564,16 +564,17 @@ xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox) } -static int x_set_geometry(nsfb_t *nsfb, int width, int height, int bpp) +static int +x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format) { - if (nsfb->frontend_priv != NULL) + if (nsfb->surface_priv != NULL) return -1; /* if were already initialised fail */ nsfb->width = width; nsfb->height = height; - nsfb->bpp = bpp; + nsfb->format = format; - /* select default sw plotters for bpp */ + /* select default sw plotters for format */ select_plotters(nsfb); nsfb->plotter_fns->copy = xcopy; @@ -588,6 +589,7 @@ find_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp) const xcb_setup_t *setup = xcb_get_setup(c); xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup); + for(; fmt != fmtend; ++fmt) { if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) { return fmt; @@ -756,7 +758,7 @@ static int x_initialise(nsfb_t *nsfb) uint32_t mask; uint32_t values[3]; xcb_size_hints_t *hints; - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; xcb_cursor_t blank_cursor; if (xstate != NULL) @@ -801,7 +803,7 @@ static int x_initialise(nsfb_t *nsfb) } /* ensure plotting information is stored */ - nsfb->frontend_priv = xstate; + nsfb->surface_priv = xstate; nsfb->ptr = xstate->image->data; nsfb->linelen = xstate->image->stride; @@ -867,7 +869,7 @@ static int x_initialise(nsfb_t *nsfb) static int x_finalise(nsfb_t *nsfb) { - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; if (xstate == NULL) return 0; @@ -890,7 +892,7 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) xcb_button_press_event_t *ebp; xcb_key_press_event_t *ekp; xcb_key_press_event_t *ekr; - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; if (xstate == NULL) return false; @@ -916,8 +918,10 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout) retval = select(confd + 1, &rfds, NULL, NULL, &tv); if (retval == 0) { - return false; /* timeout, nothing happened */ - + /* timeout, nothing happened */ + event->type = NSFB_EVENT_CONTROL; + event->value.controlcode = NSFB_CONTROL_TIMEOUT; + return true; } } e = xcb_wait_for_event(xstate->connection); @@ -1051,7 +1055,7 @@ static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box) static int x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) { - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; nsfb_bbox_t redraw; nsfb_bbox_t fbarea; @@ -1083,7 +1087,7 @@ x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor) static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box) { - xstate_t *xstate = nsfb->frontend_priv; + xstate_t *xstate = nsfb->surface_priv; struct nsfb_cursor_s *cursor = nsfb->cursor; if ((cursor != NULL) && @@ -1096,7 +1100,7 @@ static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box) return 0; } -const nsfb_frontend_rtns_t x_rtns = { +const nsfb_surface_rtns_t x_rtns = { .initialise = x_initialise, .finalise = x_finalise, .input = x_input, @@ -1106,4 +1110,11 @@ const nsfb_frontend_rtns_t x_rtns = { .geometry = x_set_geometry, }; -NSFB_FRONTEND_DEF(x, NSFB_FRONTEND_X, &x_rtns) +NSFB_SURFACE_DEF(x, NSFB_SURFACE_X, &x_rtns) + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/Makefile b/test/Makefile index b2320e3..7f2d40e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,3 +1,3 @@ -DIR_TEST_ITEMS := plottest:plottest.c;nsglobe.c frontend:frontend.c bezier:bezier.c path:path.c polygon:polygon.c polystar:polystar.c polystar2:polystar2.c +DIR_TEST_ITEMS := plottest:plottest.c bitmap:bitmap.c;nsglobe.c frontend:frontend.c bezier:bezier.c path:path.c polygon:polygon.c polystar:polystar.c polystar2:polystar2.c include build/makefiles/Makefile.subdir diff --git a/test/bezier.c b/test/bezier.c index d686349..630c4a8 100644 --- a/test/bezier.c +++ b/test/bezier.c @@ -13,8 +13,12 @@ int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; nsfb_event_t event; + int waitloop = 3; + nsfb_bbox_t box; nsfb_bbox_t box2; uint8_t *fbptr; @@ -24,25 +28,35 @@ int main(int argc, char **argv) int loop; nsfb_plot_pen_t pen; - UNUSED(argc); - UNUSED(argv); + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); /* claim the whole screen for update */ nsfb_claim(nsfb, &box); @@ -115,8 +129,29 @@ int main(int argc, char **argv) nsfb_update(nsfb, &box); - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/bitmap.c b/test/bitmap.c new file mode 100644 index 0000000..b14f2f6 --- /dev/null +++ b/test/bitmap.c @@ -0,0 +1,168 @@ +/* libnsfb plotter test program */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libnsfb.h" +#include "libnsfb_plot.h" +#include "libnsfb_event.h" + +#define UNUSED(x) ((x) = (x)) + +extern const struct { + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ + unsigned char pixel_data[132 * 135 * 4 + 1]; +} nsglobe; + +static bool +dump(nsfb_t *nsfb, const char *filename) +{ + int fd; + + if (filename == NULL) + return false; + + fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); + if (fd < 0) + return false; + + nsfb_dump(nsfb, fd); + + close(fd); + + return true; +} + +int main(int argc, char **argv) +{ + const char *fename; + enum nsfb_type_e fetype; + nsfb_t *nsfb; + nsfb_t *bmp; + nsfb_event_t event; + int waitloop = 3; + + nsfb_bbox_t box; + nsfb_bbox_t box2; + nsfb_bbox_t box3; + uint8_t *fbptr; + int fbstride; + const char *dumpfile = NULL; + + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + if (argc >= 3) { + dumpfile = argv[2]; + } + } + + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); + return 1; + } + + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); + return 2; + } + + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + + + bmp = nsfb_new(NSFB_SURFACE_RAM); + nsfb_set_geometry(bmp, nsglobe.width, nsglobe.height, NSFB_FMT_ABGR8888); + nsfb_init(bmp); + nsfb_get_buffer(bmp, &fbptr, &fbstride); + + memcpy(fbptr, nsglobe.pixel_data, nsglobe.width * nsglobe.height * 4); + + /* get the geometry of the whole screen */ + box.x0 = box.y0 = 0; + nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); + + /* claim the whole screen for update */ + nsfb_claim(nsfb, &box); + + nsfb_plot_clg(nsfb, 0xffffffff); + + box3.x0 = 0; + box3.y0 = 0; + box3.x1 = 132; + box3.y1 = 135; + + nsfb_plot_copy(bmp, &box3, nsfb, &box3); + + box3.x0 = 132; + box3.y0 = 135; + box3.x1 = box3.x0 + 264; + box3.y1 = box3.y0 + 135; + + nsfb_plot_copy(bmp, &box3, nsfb, &box3); + + box3.x0 = 396; + box3.y0 = 270; + box3.x1 = box3.x0 + 264; + box3.y1 = box3.y0 + 270; + + nsfb_plot_copy(bmp, &box3, nsfb, &box3); + + box2.x0 = 64; + box2.y0 = 64; + box2.x1 = 128; + box2.y1 = 128; + + box3.x0 = 270; + box3.y0 = 270; + box3.x1 = box3.x0 + 64; + box3.y1 = box3.y0 + 64; + + nsfb_plot_copy(nsfb, &box2, nsfb, &box3); + + nsfb_update(nsfb, &box); + + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + dump(nsfb, dumpfile); + + nsfb_free(bmp); + + nsfb_free(nsfb); + + return 0; +} + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/frontend.c b/test/frontend.c index 3d72229..5cf0651 100644 --- a/test/frontend.c +++ b/test/frontend.c @@ -4,12 +4,16 @@ #include #include "libnsfb.h" +#include "libnsfb_event.h" int main(int argc, char **argv) { nsfb_t *nsfb; const char *fename; - enum nsfb_frontend_e fetype; + enum nsfb_type_e fetype; + nsfb_event_t event; + + int waitloop = 3; if (argc < 2) { fename="sdl"; @@ -17,32 +21,52 @@ int main(int argc, char **argv) fename = argv[1]; } - fetype = nsfb_frontend_from_name(fename); - if (fetype == NSFB_FRONTEND_NONE) { - fprintf(stderr, "Unable to initialise nsfb with %s frontend\n", fename); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - nsfb = nsfb_init(fetype); + nsfb = nsfb_new(fetype); if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with %s frontend\n", fename); + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } - if (nsfb_set_geometry(nsfb, 0, 0, 32) == -1) { - fprintf(stderr, "Unable to set geometry\n"); - nsfb_finalise(nsfb); + if (nsfb_set_geometry(nsfb, 0, 0, NSFB_FMT_ANY) == -1) { + fprintf(stderr, "Unable to set surface geometry\n"); + nsfb_free(nsfb); return 3; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); - nsfb_finalise(nsfb); + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); return 4; } - sleep(2); + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } - nsfb_finalise(nsfb); + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/path.c b/test/path.c index 16a8ce2..7f1c6d1 100644 --- a/test/path.c +++ b/test/path.c @@ -39,7 +39,12 @@ static int fill_shape(nsfb_plot_pathop_t *path, int xoff, int yoff) int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; + + int waitloop = 3; + nsfb_event_t event; nsfb_bbox_t box; uint8_t *fbptr; @@ -47,25 +52,35 @@ int main(int argc, char **argv) nsfb_plot_pen_t pen; nsfb_plot_pathop_t path[20]; - UNUSED(argc); - UNUSED(argv); + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); /* claim the whole screen for update */ nsfb_claim(nsfb, &box); @@ -87,11 +102,31 @@ int main(int argc, char **argv) nsfb_plot_path(nsfb, fill_shape(path, 100, 350), path, &pen); - nsfb_update(nsfb, &box); - - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/plottest.c b/test/plottest.c index 74134c4..a4cde36 100644 --- a/test/plottest.c +++ b/test/plottest.c @@ -1,8 +1,12 @@ -/* libnsfb plotetr test program */ +/* libnsfb plotter test program */ #include #include #include +#include +#include +#include +#include #include "libnsfb.h" #include "libnsfb_plot.h" @@ -10,13 +14,6 @@ #define UNUSED(x) ((x) = (x)) -extern const struct { - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ - unsigned char pixel_data[132 * 135 * 4 + 1]; -} nsglobe; - const struct { unsigned int w; unsigned int h; @@ -67,11 +64,34 @@ const struct { } }; + +static bool +dump(nsfb_t *nsfb, const char *filename) +{ + int fd; + + if (filename == NULL) + return false; + + fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); + if (fd < 0) + return false; + + nsfb_dump(nsfb, fd); + + close(fd); + + return true; +} + int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; - int bpp; nsfb_event_t event; + int waitloop = 3; + nsfb_bbox_t box; nsfb_bbox_t box2; nsfb_bbox_t box3; @@ -80,37 +100,40 @@ int main(int argc, char **argv) int p[] = { 300,300, 350,350, 400,300, 450,250, 400,200}; int loop; nsfb_plot_pen_t pen; + const char *dumpfile = NULL; if (argc < 2) { - bpp = 32; + fename="sdl"; } else { - bpp = atoi(argv[1]); - if (bpp == 0) - bpp = 32; + fename = argv[1]; + if (argc >= 3) { + dumpfile = argv[2]; + } } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_set_geometry(nsfb, 0, 0, bpp) == -1) { - fprintf(stderr, "Unable to set geometry\n"); - nsfb_finalise(nsfb); - return 3; + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); + return 2; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); - return 2; + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; } /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); /* claim the whole screen for update */ nsfb_claim(nsfb, &box); @@ -219,14 +242,7 @@ int main(int argc, char **argv) box3.x1 = 700; box3.y1 = 300; - nsfb_plot_copy(nsfb, &box2, &box3); - - box3.x0 = 50; - box3.x1 = 200; - box3.y0 = 300; - box3.y1 = 500; - - nsfb_plot_bitmap(nsfb, &box3, (nsfb_colour_t *)nsglobe.pixel_data, nsglobe.width, nsglobe.height, nsglobe.width, true); + nsfb_plot_copy(nsfb, &box2, nsfb, &box3); /* test glyph plotting */ for (loop = 100; loop < 200; loop+= Mglyph1.w) { @@ -270,9 +286,31 @@ int main(int argc, char **argv) nsfb_update(nsfb, &box2); } + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + dump(nsfb, dumpfile); + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/polygon.c b/test/polygon.c index cd7efd8..e91846f 100644 --- a/test/polygon.c +++ b/test/polygon.c @@ -14,8 +14,12 @@ int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; nsfb_event_t event; + int waitloop = 3; + nsfb_bbox_t box; uint8_t *fbptr; int fbstride; @@ -26,25 +30,35 @@ int main(int argc, char **argv) int loop; // nsfb_plot_pen_t pen; - UNUSED(argc); - UNUSED(argv); + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); /* claim the whole screen for update */ nsfb_claim(nsfb, &box); @@ -72,8 +86,29 @@ int main(int argc, char **argv) nsfb_update(nsfb, &box); - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/polystar.c b/test/polystar.c index 6963cfb..c71ba41 100644 --- a/test/polystar.c +++ b/test/polystar.c @@ -24,7 +24,12 @@ static void sleepMilli(long ms) int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; + + int waitloop = 3; + nsfb_event_t event; nsfb_bbox_t box; uint8_t *fbptr; @@ -38,25 +43,35 @@ int main(int argc, char **argv) double rotate; - UNUSED(argc); - UNUSED(argv); + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); pen.stroke_colour = 0xff000000; @@ -99,8 +114,29 @@ int main(int argc, char **argv) sleepMilli(100); } - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/polystar2.c b/test/polystar2.c index 479a45b..afff5a0 100644 --- a/test/polystar2.c +++ b/test/polystar2.c @@ -25,7 +25,12 @@ static void sleepMilli(long ms) int main(int argc, char **argv) { + const char *fename; + enum nsfb_type_e fetype; nsfb_t *nsfb; + + int waitloop = 3; + nsfb_event_t event; nsfb_bbox_t box; uint8_t *fbptr; @@ -38,24 +43,34 @@ int main(int argc, char **argv) int counter; int colour; - UNUSED(argc); - UNUSED(argv); + if (argc < 2) { + fename="sdl"; + } else { + fename = argv[1]; + } - nsfb = nsfb_init(NSFB_FRONTEND_SDL); - if (nsfb == NULL) { - fprintf(stderr, "Unable to initialise nsfb with SDL frontend\n"); + fetype = nsfb_type_from_name(fename); + if (fetype == NSFB_SURFACE_NONE) { + fprintf(stderr, "Unable to convert \"%s\" to nsfb surface type\n", fename); return 1; } - if (nsfb_init_frontend(nsfb) == -1) { - fprintf(stderr, "Unable to initialise nsfb frontend\n"); + nsfb = nsfb_new(fetype); + if (nsfb == NULL) { + fprintf(stderr, "Unable to allocate \"%s\" nsfb surface\n", fename); return 2; } + if (nsfb_init(nsfb) == -1) { + fprintf(stderr, "Unable to initialise nsfb surface\n"); + nsfb_free(nsfb); + return 4; + } + /* get the geometry of the whole screen */ box.x0 = box.y0 = 0; nsfb_get_geometry(nsfb, &box.x1, &box.y1, NULL); - nsfb_get_framebuffer(nsfb, &fbptr, &fbstride); + nsfb_get_buffer(nsfb, &fbptr, &fbstride); radius = (box.x1 / 3); sides = 5; @@ -92,8 +107,29 @@ int main(int argc, char **argv) sleepMilli(400); } - while (event.type != NSFB_EVENT_CONTROL) - nsfb_event(nsfb, &event, -1); + /* wait for quit event or timeout */ + while (waitloop > 0) { + if (nsfb_event(nsfb, &event, 1000) == false) { + break; + } + if (event.type == NSFB_EVENT_CONTROL) { + if (event.value.controlcode == NSFB_CONTROL_TIMEOUT) { + /* timeout */ + waitloop--; + } else if (event.value.controlcode == NSFB_CONTROL_QUIT) { + break; + } + } + } + + nsfb_free(nsfb); return 0; } + +/* + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ diff --git a/test/runtest.sh b/test/runtest.sh index f2eb0a4..5d131ab 100755 --- a/test/runtest.sh +++ b/test/runtest.sh @@ -2,11 +2,14 @@ TEST_PATH=$1 -${TEST_PATH}/test_frontend -${TEST_PATH}/test_plottest -${TEST_PATH}/test_bezier -${TEST_PATH}/test_path -${TEST_PATH}/test_polygon -${TEST_PATH}/test_polystar -${TEST_PATH}/test_polystar2 +TEST_FRONTEND=x + +${TEST_PATH}/test_frontend ${TEST_FRONTEND} +${TEST_PATH}/test_plottest ${TEST_FRONTEND} +${TEST_PATH}/test_bitmap ${TEST_FRONTEND} +${TEST_PATH}/test_bezier ${TEST_FRONTEND} +${TEST_PATH}/test_path ${TEST_FRONTEND} +${TEST_PATH}/test_polygon ${TEST_FRONTEND} +${TEST_PATH}/test_polystar ${TEST_FRONTEND} +${TEST_PATH}/test_polystar2 ${TEST_FRONTEND} -- cgit v1.2.3