author | francesco-ST <francesco.abbate@st.com> | 2010年07月16日 13:35:58 +0200 |
---|---|---|
committer | francesco-ST <francesco.abbate@st.com> | 2010年07月16日 13:35:58 +0200 |
commit | 990d860748748a2ef39856c1e3f93089f316110c (patch) | |
tree | 48126771627c072990dcb4a756891e87b6b119b4 /agg-plot | |
parent | e3aa215ce35cc6952dd90cf55c7cd627d9be2a5f (diff) | |
parent | 4a52c75c22bb6ccffa25bb296ad0e5fda7742027 (diff) | |
download | gsl-shell-990d860748748a2ef39856c1e3f93089f316110c.tar.gz |
-rw-r--r-- | agg-plot/Makefile | 5 | ||||
-rw-r--r-- | agg-plot/agg-parse-trans.cpp | 201 | ||||
-rw-r--r-- | agg-plot/agg-parse-trans.h | 16 | ||||
-rw-r--r-- | agg-plot/agg_platform_support_win32.cpp | 4 | ||||
-rw-r--r-- | agg-plot/agg_platform_support_x11.cpp | 2522 | ||||
-rw-r--r-- | agg-plot/colors.cpp | 24 | ||||
-rw-r--r-- | agg-plot/colors.h | 5 | ||||
-rw-r--r-- | agg-plot/lua-draw.cpp | 54 | ||||
-rw-r--r-- | agg-plot/lua-plot.cpp | 232 | ||||
-rw-r--r-- | agg-plot/plot-window.cpp | 345 | ||||
-rw-r--r-- | agg-plot/plot-window.h | 16 | ||||
-rw-r--r-- | agg-plot/trans.h | 22 | ||||
-rw-r--r-- | agg-plot/xwin-show.cpp | 4 |
diff --git a/agg-plot/Makefile b/agg-plot/Makefile index e1945ae2..de471055 100644 --- a/agg-plot/Makefile +++ b/agg-plot/Makefile @@ -44,7 +44,7 @@ endif INCLUDES += $(AGG_INCLUDES) -I$(GSH_BASE_DIR) -I$(LUADIR)/src -AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) utils.cpp units.cpp colors.cpp lua-draw.cpp lua-plot.cpp xwin-show.cpp +AGGPLOT_SRC_FILES = $(PLATSUP_SRC_FILES) utils.cpp units.cpp colors.cpp lua-draw.cpp lua-plot.cpp agg-parse-trans.cpp xwin-show.cpp plot-window.cpp AGGPLOT_OBJ_FILES := $(AGGPLOT_SRC_FILES:%.cpp=%.o) @@ -58,9 +58,6 @@ TARGETS = libaggplot.a all: $(TARGETS) -#test.exe: $(AGGPLOT_OBJ_FILES) -# gcc -o test.exe $(AGGPLOT_OBJ_FILES) $(AGG_LIBS) - libaggplot.a: $(AGGPLOT_OBJ_FILES) $(AR) $@ $? $(RANLIB) $@ diff --git a/agg-plot/agg-parse-trans.cpp b/agg-plot/agg-parse-trans.cpp new file mode 100644 index 00000000..30657622 --- /dev/null +++ b/agg-plot/agg-parse-trans.cpp @@ -0,0 +1,201 @@ + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +} + +#include "agg-parse-trans.h" +#include "lua-cpp-utils.h" +#include "lua-utils.h" +#include "gs-types.h" +#include "trans.h" + +struct property_reg { + int id; + const char *name; +}; + +struct builder_reg { + const char *name; + vertex_source *(*func)(lua_State *, int, vertex_source *); +}; + +static vertex_source * build_stroke (lua_State *L, int i, vertex_source *s); +static vertex_source * build_curve (lua_State *L, int i, vertex_source *s); +static vertex_source * build_marker (lua_State *L, int i, vertex_source *s); +static vertex_source * build_dash (lua_State *L, int i, vertex_source *s); +static vertex_source * build_extend (lua_State *L, int i, vertex_source *s); +static vertex_source * build_translate (lua_State *L, int i, vertex_source *s); +static vertex_source * build_rotate (lua_State *L, int i, vertex_source *s); + +struct property_reg line_cap_properties[] = { + {(int) agg::butt_cap, "butt" }, + {(int) agg::square_cap, "square"}, + {(int) agg::round_cap, "round" }, + {0, NULL} +}; + +struct property_reg line_join_properties[] = { + {(int) agg::miter_join, "miter" }, + {(int) agg::miter_join_revert, "miter.rev" }, + {(int) agg::round_join, "round" }, + {(int) agg::bevel_join, "bevel" }, + {(int) agg::miter_join_round, "miter.round"}, + {0, NULL} +}; + +const builder_reg builder_table[] = { + {"stroke", build_stroke }, + {"dash", build_dash}, + {"curve", build_curve}, + {"marker", build_marker}, + {"extend", build_extend}, + {"translate", build_translate}, + {"rotate", build_rotate}, + {NULL, NULL} +}; + +static int +property_lookup (struct property_reg *prop, const char *key) +{ + int default_value = prop->id; + + if (key == NULL) + return default_value; + + for ( ; prop->name; prop++) + { + if (strcmp (prop->name, key) == 0) + return prop->id; + } + + return default_value; +} + +vertex_source * +build_stroke (lua_State *L, int specindex, vertex_source *obj) +{ + double width = mlua_named_optnumber (L, specindex, "width", 1.0); + const char *cap_str = mlua_named_optstring (L, specindex, "cap", NULL); + const char *join_str = mlua_named_optstring (L, specindex, "join", NULL); + + trans::stroke *stroke = new trans::stroke(obj, width); + + if (cap_str) + { + int cap = property_lookup (line_cap_properties, cap_str); + stroke->line_cap((agg::line_cap_e) cap); + } + + if (join_str) + { + int join = property_lookup (line_join_properties, join_str); + stroke->line_join((agg::line_join_e) join); + } + + return (vertex_source *) stroke; +} + +vertex_source * +build_curve (lua_State *L, int specindex, vertex_source *obj) +{ + trans::curve *c = new trans::curve(obj); + return (vertex_source *) c; +} + +vertex_source * +build_marker (lua_State *L, int specindex, vertex_source *obj) +{ + double size = mlua_named_optnumber (L, specindex, "size", 3.0); + return (vertex_source *) new trans::marker(obj, size); +} + +vertex_source * +build_dash (lua_State *L, int specindex, vertex_source *obj) +{ + double a = mlua_named_optnumber (L, specindex, "a", 10.0); + double b = mlua_named_optnumber (L, specindex, "b", a); + + trans::dash *dash = new trans::dash(obj); + dash->add_dash(a, b); + + return (vertex_source *) dash; +} + +vertex_source * +build_extend (lua_State *L, int specindex, vertex_source *obj) +{ + double width = mlua_named_optnumber (L, specindex, "width", 1.0); + return (vertex_source *) new trans::extend(obj, width); +} + +vertex_source * +build_translate (lua_State *L, int specindex, vertex_source *obj) +{ + double x = mlua_named_number (L, specindex, "x"); + double y = mlua_named_number (L, specindex, "y"); + + trans::affine *t = new trans::affine(obj); + t->translate(x, y); + + return (vertex_source *) t; +} + +vertex_source * +build_rotate (lua_State *L, int specindex, vertex_source *obj) +{ + double a = mlua_named_number (L, specindex, "angle"); + + trans::affine *t = new trans::affine(obj); + t->rotate(a); + + return (vertex_source *) t; +} + +vertex_source * +parse_spec (lua_State *L, int specindex, vertex_source *obj) +{ + const char *tag; + + lua_rawgeti (L, specindex, 1); + if (! lua_isstring (L, -1)) + { + luaL_error (L, "the tag of the transformation is invalid"); + return NULL; + } + + tag = lua_tostring (L, -1); + lua_pop (L, 1); + + for (const builder_reg *b = builder_table; b->name != NULL; b++) + { + if (strcmp (b->name, tag) == 0) + return b->func (L, specindex, obj); + } + + luaL_error (L, "invalid trasformation tag"); + return NULL; +} + +vertex_source * +parse_spec_pipeline (lua_State *L, int index, vertex_source *obj) +{ + size_t k, nb; + + if (lua_type (L, index) == LUA_TTABLE) + nb = lua_objlen (L, index); + else + { + luaL_error (L, "post transform argument should be a table"); + return NULL; + } + + for (k = nb; k > 0; k--) + { + lua_rawgeti (L, index, k); + obj = parse_spec (L, index+1, obj); + lua_pop (L, 1); + } + + return obj; +} diff --git a/agg-plot/agg-parse-trans.h b/agg-plot/agg-parse-trans.h new file mode 100644 index 00000000..87973582 --- /dev/null +++ b/agg-plot/agg-parse-trans.h @@ -0,0 +1,16 @@ +#ifndef AGG_PARSE_TRANS_H +#define AGG_PARSE_TRANS_H + +extern "C" { +#include "lua.h" +} + +#include "vertex-source.h" + +extern vertex_source * parse_spec (lua_State *L, int specindex, + vertex_source *obj); + +extern vertex_source * parse_spec_pipeline (lua_State *L, int index, + vertex_source *obj); + +#endif diff --git a/agg-plot/agg_platform_support_win32.cpp b/agg-plot/agg_platform_support_win32.cpp index 71589048..3a8f52a9 100644 --- a/agg-plot/agg_platform_support_win32.cpp +++ b/agg-plot/agg_platform_support_win32.cpp @@ -1056,8 +1056,6 @@ namespace agg { MSG msg; - pthread_mutex_lock (m_specific->m_mutex); - for(;;) { if(m_wait_mode) @@ -1093,8 +1091,6 @@ namespace agg } } - pthread_mutex_unlock (m_specific->m_mutex); - return (int)msg.wParam; } diff --git a/agg-plot/agg_platform_support_x11.cpp b/agg-plot/agg_platform_support_x11.cpp index 567f8e44..8e9152a7 100644 --- a/agg-plot/agg_platform_support_x11.cpp +++ b/agg-plot/agg_platform_support_x11.cpp @@ -1,1263 +1,1259 @@ -//----------------------------------------------------------------------------
-// Anti-Grain Geometry (AGG) - Version 2.5
-// A high quality rendering engine for C++
-// Copyright (C) 2002-2006 Maxim Shemanarev
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://antigrain.com
-//
-// AGG is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// AGG is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with AGG; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-// MA 02110-1301, USA.
-//----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <time.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <pthread.h>
-#include "agg_basics.h"
-#include "util/agg_color_conv_rgb8.h"
-#include "platform/agg_platform_support.h"
-
-
-namespace agg
-{
- //------------------------------------------------------------------------
- class platform_specific
- {
- public:
- platform_specific(pix_format_e format, bool flip_y);
- ~platform_specific();
-
- void caption(const char* capt);
- void put_image(const rendering_buffer* src);
-
- pix_format_e m_format;
- pix_format_e m_sys_format;
- int m_byte_order;
- bool m_flip_y;
- unsigned m_bpp;
- unsigned m_sys_bpp;
- Display* m_display;
- int m_screen;
- int m_depth;
- Visual* m_visual;
- Window m_window;
- GC m_gc;
- XImage* m_ximg_window;
- XSetWindowAttributes m_window_attributes;
- Atom m_close_atom;
- unsigned char* m_buf_window;
- unsigned char* m_buf_img[platform_support::max_images];
- unsigned m_keymap[256];
-
- bool m_update_flag;
- bool m_resize_flag;
- bool m_initialized;
- bool m_is_mapped;
- clock_t m_sw_start;
-
- pthread_mutex_t m_mutex[1];
-
- };
-
-
-
- //------------------------------------------------------------------------
- platform_specific::platform_specific(pix_format_e format, bool flip_y) :
- m_format(format),
- m_sys_format(pix_format_undefined),
- m_byte_order(LSBFirst),
- m_flip_y(flip_y),
- m_bpp(0),
- m_sys_bpp(0),
- m_display(0),
- m_screen(0),
- m_depth(0),
- m_visual(0),
- m_window(0),
- m_gc(0),
- m_ximg_window(0),
- m_close_atom(0),
-
- m_buf_window(0),
-
- m_update_flag(true),
- m_resize_flag(true),
- m_initialized(false),
- m_is_mapped(false)
- {
- memset(m_buf_img, 0, sizeof(m_buf_img));
-
- unsigned i;
- for(i = 0; i < 256; i++)
- {
- m_keymap[i] = i;
- }
-
- m_keymap[XK_Pause&0xFF] = key_pause;
- m_keymap[XK_Clear&0xFF] = key_clear;
-
- m_keymap[XK_KP_0&0xFF] = key_kp0;
- m_keymap[XK_KP_1&0xFF] = key_kp1;
- m_keymap[XK_KP_2&0xFF] = key_kp2;
- m_keymap[XK_KP_3&0xFF] = key_kp3;
- m_keymap[XK_KP_4&0xFF] = key_kp4;
- m_keymap[XK_KP_5&0xFF] = key_kp5;
- m_keymap[XK_KP_6&0xFF] = key_kp6;
- m_keymap[XK_KP_7&0xFF] = key_kp7;
- m_keymap[XK_KP_8&0xFF] = key_kp8;
- m_keymap[XK_KP_9&0xFF] = key_kp9;
-
- m_keymap[XK_KP_Insert&0xFF] = key_kp0;
- m_keymap[XK_KP_End&0xFF] = key_kp1;
- m_keymap[XK_KP_Down&0xFF] = key_kp2;
- m_keymap[XK_KP_Page_Down&0xFF] = key_kp3;
- m_keymap[XK_KP_Left&0xFF] = key_kp4;
- m_keymap[XK_KP_Begin&0xFF] = key_kp5;
- m_keymap[XK_KP_Right&0xFF] = key_kp6;
- m_keymap[XK_KP_Home&0xFF] = key_kp7;
- m_keymap[XK_KP_Up&0xFF] = key_kp8;
- m_keymap[XK_KP_Page_Up&0xFF] = key_kp9;
- m_keymap[XK_KP_Delete&0xFF] = key_kp_period;
- m_keymap[XK_KP_Decimal&0xFF] = key_kp_period;
- m_keymap[XK_KP_Divide&0xFF] = key_kp_divide;
- m_keymap[XK_KP_Multiply&0xFF] = key_kp_multiply;
- m_keymap[XK_KP_Subtract&0xFF] = key_kp_minus;
- m_keymap[XK_KP_Add&0xFF] = key_kp_plus;
- m_keymap[XK_KP_Enter&0xFF] = key_kp_enter;
- m_keymap[XK_KP_Equal&0xFF] = key_kp_equals;
-
- m_keymap[XK_Up&0xFF] = key_up;
- m_keymap[XK_Down&0xFF] = key_down;
- m_keymap[XK_Right&0xFF] = key_right;
- m_keymap[XK_Left&0xFF] = key_left;
- m_keymap[XK_Insert&0xFF] = key_insert;
- m_keymap[XK_Home&0xFF] = key_delete;
- m_keymap[XK_End&0xFF] = key_end;
- m_keymap[XK_Page_Up&0xFF] = key_page_up;
- m_keymap[XK_Page_Down&0xFF] = key_page_down;
-
- m_keymap[XK_F1&0xFF] = key_f1;
- m_keymap[XK_F2&0xFF] = key_f2;
- m_keymap[XK_F3&0xFF] = key_f3;
- m_keymap[XK_F4&0xFF] = key_f4;
- m_keymap[XK_F5&0xFF] = key_f5;
- m_keymap[XK_F6&0xFF] = key_f6;
- m_keymap[XK_F7&0xFF] = key_f7;
- m_keymap[XK_F8&0xFF] = key_f8;
- m_keymap[XK_F9&0xFF] = key_f9;
- m_keymap[XK_F10&0xFF] = key_f10;
- m_keymap[XK_F11&0xFF] = key_f11;
- m_keymap[XK_F12&0xFF] = key_f12;
- m_keymap[XK_F13&0xFF] = key_f13;
- m_keymap[XK_F14&0xFF] = key_f14;
- m_keymap[XK_F15&0xFF] = key_f15;
-
- m_keymap[XK_Num_Lock&0xFF] = key_numlock;
- m_keymap[XK_Caps_Lock&0xFF] = key_capslock;
- m_keymap[XK_Scroll_Lock&0xFF] = key_scrollock;
-
- switch(m_format)
- {
- default: break;
- case pix_format_gray8:
- m_bpp = 8;
- break;
-
- case pix_format_rgb565:
- case pix_format_rgb555:
- m_bpp = 16;
- break;
-
- case pix_format_rgb24:
- case pix_format_bgr24:
- m_bpp = 24;
- break;
-
- case pix_format_bgra32:
- case pix_format_abgr32:
- case pix_format_argb32:
- case pix_format_rgba32:
- m_bpp = 32;
- break;
- }
- m_sw_start = clock();
-
- pthread_mutex_init (m_mutex, NULL);
- }
-
- //------------------------------------------------------------------------
- platform_specific::~platform_specific()
- {
- pthread_mutex_destroy (m_mutex);
- }
-
- //------------------------------------------------------------------------
- void platform_specific::caption(const char* capt)
- {
- // Fixed by Enno Fennema (in original AGG library)
- XStoreName(m_display, m_window, capt);
- XSetIconName(m_display, m_window, capt);
- }
-
-
- //------------------------------------------------------------------------
- void platform_specific::put_image(const rendering_buffer* src)
- {
- if(m_ximg_window == 0) return;
- m_ximg_window->data = (char*)m_buf_window;
-
- if(m_format == m_sys_format)
- {
- XPutImage(m_display,
- m_window,
- m_gc,
- m_ximg_window,
- 0, 0, 0, 0,
- src->width(),
- src->height());
- }
- else
- {
- int row_len = src->width() * m_sys_bpp / 8;
- unsigned char* buf_tmp =
- new unsigned char[row_len * src->height()];
-
- rendering_buffer rbuf_tmp;
- rbuf_tmp.attach(buf_tmp,
- src->width(),
- src->height(),
- m_flip_y ? -row_len : row_len);
-
- switch(m_sys_format)
- {
- default: break;
- case pix_format_rgb555:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb555()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb555()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb555()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb555()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb555()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb555()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb555()); break;
- }
- break;
-
- case pix_format_rgb565:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb565()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb565()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb565()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb565()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb565()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb565()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb565()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb565()); break;
- }
- break;
-
- case pix_format_rgba32:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgba32()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgba32()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgba32()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgba32()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgba32()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgba32()); break;
- }
- break;
-
- case pix_format_abgr32:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_abgr32()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_abgr32()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_abgr32()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_abgr32()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_abgr32()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_abgr32()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_abgr32()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_abgr32()); break;
- }
- break;
-
- case pix_format_argb32:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_argb32()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_argb32()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_argb32()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_argb32()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_argb32()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); break;
- }
- break;
-
- case pix_format_bgra32:
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break;
- case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break;
- case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgra32()); break;
- case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_bgra32()); break;
- case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); break;
- case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); break;
- case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); break;
- case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_bgra32()); break;
- }
- break;
- }
-
- m_ximg_window->data = (char*)buf_tmp;
- XPutImage(m_display,
- m_window,
- m_gc,
- m_ximg_window,
- 0, 0, 0, 0,
- src->width(),
- src->height());
-
- delete [] buf_tmp;
- }
- }
-
- //------------------------------------------------------------------------
- platform_support::platform_support(pix_format_e format, bool flip_y) :
- m_specific(new platform_specific(format, flip_y)),
- m_format(format),
- m_bpp(m_specific->m_bpp),
- m_window_flags(0),
- m_wait_mode(true),
- m_flip_y(flip_y),
- m_initial_width(10),
- m_initial_height(10)
- {
- strcpy(m_caption, "AGG Application");
- }
-
- //------------------------------------------------------------------------
- platform_support::~platform_support()
- {
- delete m_specific;
- }
-
-
-
- //------------------------------------------------------------------------
- void platform_support::caption(const char* cap)
- {
- strcpy(m_caption, cap);
- if(m_specific->m_initialized)
- {
- m_specific->caption(cap);
- }
- }
-
-
- //------------------------------------------------------------------------
- enum xevent_mask_e
- {
- xevent_mask =
- PointerMotionMask|
- ButtonPressMask|
- ButtonReleaseMask|
- ExposureMask|
- KeyPressMask|
- StructureNotifyMask
- };
-
-
- //------------------------------------------------------------------------
- bool platform_support::init(unsigned width, unsigned height, unsigned flags)
- {
- m_window_flags = flags;
-
- m_specific->m_display = XOpenDisplay(NULL);
- if(m_specific->m_display == 0)
- {
- fprintf(stderr, "Unable to open DISPLAY!\n");
- return false;
- }
-
- m_specific->m_screen = XDefaultScreen(m_specific->m_display);
- m_specific->m_depth = XDefaultDepth(m_specific->m_display,
- m_specific->m_screen);
- m_specific->m_visual = XDefaultVisual(m_specific->m_display,
- m_specific->m_screen);
- unsigned long r_mask = m_specific->m_visual->red_mask;
- unsigned long g_mask = m_specific->m_visual->green_mask;
- unsigned long b_mask = m_specific->m_visual->blue_mask;
-
- if(m_specific->m_depth < 15 ||
- r_mask == 0 || g_mask == 0 || b_mask == 0)
- {
- fprintf(stderr,
- "There's no Visual compatible with minimal AGG requirements:\n"
- "At least 15-bit color depth and True- or DirectColor class.\n\n");
- XCloseDisplay(m_specific->m_display);
- return false;
- }
-
- int t = 1;
- int hw_byte_order = LSBFirst;
- if(*(char*)&t == 0) hw_byte_order = MSBFirst;
-
- // Perceive SYS-format by mask
- switch(m_specific->m_depth)
- {
- case 15:
- m_specific->m_sys_bpp = 16;
- if(r_mask == 0x7C00 && g_mask == 0x3E0 && b_mask == 0x1F)
- {
- m_specific->m_sys_format = pix_format_rgb555;
- m_specific->m_byte_order = hw_byte_order;
- }
- break;
-
- case 16:
- m_specific->m_sys_bpp = 16;
- if(r_mask == 0xF800 && g_mask == 0x7E0 && b_mask == 0x1F)
- {
- m_specific->m_sys_format = pix_format_rgb565;
- m_specific->m_byte_order = hw_byte_order;
- }
- break;
-
- case 24:
- case 32:
- m_specific->m_sys_bpp = 32;
- if(g_mask == 0xFF00)
- {
- if(r_mask == 0xFF && b_mask == 0xFF0000)
- {
- switch(m_specific->m_format)
- {
- case pix_format_rgba32:
- m_specific->m_sys_format = pix_format_rgba32;
- m_specific->m_byte_order = LSBFirst;
- break;
-
- case pix_format_abgr32:
- m_specific->m_sys_format = pix_format_abgr32;
- m_specific->m_byte_order = MSBFirst;
- break;
-
- default:
- m_specific->m_byte_order = hw_byte_order;
- m_specific->m_sys_format =
- (hw_byte_order == LSBFirst) ?
- pix_format_rgba32 :
- pix_format_abgr32;
- break;
- }
- }
-
- if(r_mask == 0xFF0000 && b_mask == 0xFF)
- {
- switch(m_specific->m_format)
- {
- case pix_format_argb32:
- m_specific->m_sys_format = pix_format_argb32;
- m_specific->m_byte_order = MSBFirst;
- break;
-
- case pix_format_bgra32:
- m_specific->m_sys_format = pix_format_bgra32;
- m_specific->m_byte_order = LSBFirst;
- break;
-
- default:
- m_specific->m_byte_order = hw_byte_order;
- m_specific->m_sys_format =
- (hw_byte_order == MSBFirst) ?
- pix_format_argb32 :
- pix_format_bgra32;
- break;
- }
- }
- }
- break;
- }
-
- if(m_specific->m_sys_format == pix_format_undefined)
- {
- fprintf(stderr,
- "RGB masks are not compatible with AGG pixel formats:\n"
- "R=%08x, R=%08x, B=%08x\n",
- (unsigned)r_mask, (unsigned)g_mask, (unsigned)b_mask);
- XCloseDisplay(m_specific->m_display);
- return false;
- }
-
-
-
- memset(&m_specific->m_window_attributes,
- 0,
- sizeof(m_specific->m_window_attributes));
-
- m_specific->m_window_attributes.border_pixel =
- XBlackPixel(m_specific->m_display, m_specific->m_screen);
-
- m_specific->m_window_attributes.background_pixel =
- XWhitePixel(m_specific->m_display, m_specific->m_screen);
-
- m_specific->m_window_attributes.override_redirect = 0;
-
- unsigned long window_mask = CWBackPixel | CWBorderPixel;
-
- m_specific->m_window =
- XCreateWindow(m_specific->m_display,
- XDefaultRootWindow(m_specific->m_display),
- 0, 0,
- width,
- height,
- 0,
- m_specific->m_depth,
- InputOutput,
- CopyFromParent,
- window_mask,
- &m_specific->m_window_attributes);
-
-
- m_specific->m_gc = XCreateGC(m_specific->m_display,
- m_specific->m_window,
- 0, 0);
- m_specific->m_buf_window =
- new unsigned char[width * height * (m_bpp / 8)];
-
- memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8));
-
- m_rbuf_window.attach(m_specific->m_buf_window,
- width,
- height,
- m_flip_y ? -width * (m_bpp / 8) : width * (m_bpp / 8));
-
- m_specific->m_ximg_window =
- XCreateImage(m_specific->m_display,
- m_specific->m_visual, //CopyFromParent,
- m_specific->m_depth,
- ZPixmap,
- 0,
- (char*)m_specific->m_buf_window,
- width,
- height,
- m_specific->m_sys_bpp,
- width * (m_specific->m_sys_bpp / 8));
- m_specific->m_ximg_window->byte_order = m_specific->m_byte_order;
-
- m_specific->caption(m_caption);
- m_initial_width = width;
- m_initial_height = height;
-
- if(!m_specific->m_initialized)
- {
- on_init();
- m_specific->m_initialized = true;
- }
-
- trans_affine_resizing(width, height);
- on_resize(width, height);
- m_specific->m_update_flag = true;
-
- XSizeHints *hints = XAllocSizeHints();
- if(hints)
- {
- if(flags & window_resize)
- {
- hints->min_width = 32;
- hints->min_height = 32;
- hints->max_width = 4096;
- hints->max_height = 4096;
- }
- else
- {
- hints->min_width = width;
- hints->min_height = height;
- hints->max_width = width;
- hints->max_height = height;
- }
- hints->flags = PMaxSize | PMinSize;
-
- XSetWMNormalHints(m_specific->m_display,
- m_specific->m_window,
- hints);
-
- XFree(hints);
- }
-
-
- XMapWindow(m_specific->m_display,
- m_specific->m_window);
-
- XSelectInput(m_specific->m_display,
- m_specific->m_window,
- xevent_mask);
-
-
- m_specific->m_close_atom = XInternAtom(m_specific->m_display,
- "WM_DELETE_WINDOW",
- false);
-
- XSetWMProtocols(m_specific->m_display,
- m_specific->m_window,
- &m_specific->m_close_atom,
- 1);
-
- return true;
- }
-
-
-
- //------------------------------------------------------------------------
- void platform_support::update_window()
- {
- if (! m_specific->m_is_mapped)
- return;
-
- m_specific->put_image(&m_rbuf_window);
-
- // When m_wait_mode is true we can discard all the events
- // came while the image is being drawn. In this case
- // the X server does not accumulate mouse motion events.
- // When m_wait_mode is false, i.e. we have some idle drawing
- // we cannot afford to miss any events
- XSync(m_specific->m_display, m_wait_mode);
- }
-
-
- //------------------------------------------------------------------------
- int platform_support::run()
- {
- pthread_mutex_lock (m_specific->m_mutex);
-
- XFlush(m_specific->m_display);
-
- bool quit = false;
- unsigned flags;
- int cur_x;
- int cur_y;
-
- while(!quit)
- {
- if(m_specific->m_update_flag && m_specific->m_is_mapped)
- {
- on_draw();
- update_window();
- m_specific->m_update_flag = false;
- }
-
- if(!m_wait_mode)
- {
- if(XPending(m_specific->m_display) == 0)
- {
- on_idle();
- continue;
- }
- }
-
- XEvent x_event;
- pthread_mutex_unlock (m_specific->m_mutex);
- XNextEvent(m_specific->m_display, &x_event);
- pthread_mutex_lock (m_specific->m_mutex);
-
- // In the Idle mode discard all intermediate MotionNotify events
- if(!m_wait_mode && x_event.type == MotionNotify)
- {
- XEvent te = x_event;
- for(;;)
- {
- if(XPending(m_specific->m_display) == 0) break;
- XNextEvent(m_specific->m_display, &te);
- if(te.type != MotionNotify) break;
- }
- x_event = te;
- }
-
- switch(x_event.type)
- {
- case MapNotify:
- {
- on_draw();
- update_window();
- m_specific->m_is_mapped = true;
- m_specific->m_update_flag = false;
- }
- break;
-
- case ConfigureNotify:
- {
- if(x_event.xconfigure.width != int(m_rbuf_window.width()) ||
- x_event.xconfigure.height != int(m_rbuf_window.height()))
- {
- int width = x_event.xconfigure.width;
- int height = x_event.xconfigure.height;
-
- delete [] m_specific->m_buf_window;
- m_specific->m_ximg_window->data = 0;
- XDestroyImage(m_specific->m_ximg_window);
-
- m_specific->m_buf_window =
- new unsigned char[width * height * (m_bpp / 8)];
-
- m_rbuf_window.attach(m_specific->m_buf_window,
- width,
- height,
- m_flip_y ?
- -width * (m_bpp / 8) :
- width * (m_bpp / 8));
-
- m_specific->m_ximg_window =
- XCreateImage(m_specific->m_display,
- m_specific->m_visual, //CopyFromParent,
- m_specific->m_depth,
- ZPixmap,
- 0,
- (char*)m_specific->m_buf_window,
- width,
- height,
- m_specific->m_sys_bpp,
- width * (m_specific->m_sys_bpp / 8));
- m_specific->m_ximg_window->byte_order = m_specific->m_byte_order;
-
- trans_affine_resizing(width, height);
- on_resize(width, height);
- on_draw();
- update_window();
- }
- }
- break;
-
- case Expose:
- m_specific->put_image(&m_rbuf_window);
- XFlush(m_specific->m_display);
- XSync(m_specific->m_display, false);
- break;
-
- case KeyPress:
- {
- KeySym key = XLookupKeysym(&x_event.xkey, 0);
- flags = 0;
- if(x_event.xkey.state & Button1Mask) flags |= mouse_left;
- if(x_event.xkey.state & Button3Mask) flags |= mouse_right;
- if(x_event.xkey.state & ShiftMask) flags |= kbd_shift;
- if(x_event.xkey.state & ControlMask) flags |= kbd_ctrl;
-
- bool left = false;
- bool up = false;
- bool right = false;
- bool down = false;
-
- switch(m_specific->m_keymap[key & 0xFF])
- {
- case key_left:
- left = true;
- break;
-
- case key_up:
- up = true;
- break;
-
- case key_right:
- right = true;
- break;
-
- case key_down:
- down = true;
- break;
-
- case key_f2:
- copy_window_to_img(max_images - 1);
- save_img(max_images - 1, "screenshot");
- break;
- }
-
- if(m_ctrls.on_arrow_keys(left, right, down, up))
- {
- on_ctrl_change();
- force_redraw();
- }
- else
- {
- on_key(x_event.xkey.x,
- m_flip_y ?
- m_rbuf_window.height() - x_event.xkey.y :
- x_event.xkey.y,
- m_specific->m_keymap[key & 0xFF],
- flags);
- }
- }
- break;
-
-
- case ButtonPress:
- {
- flags = 0;
- if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift;
- if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl;
- if(x_event.xbutton.button == Button1) flags |= mouse_left;
- if(x_event.xbutton.button == Button3) flags |= mouse_right;
-
- cur_x = x_event.xbutton.x;
- cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y :
- x_event.xbutton.y;
-
- if(flags & mouse_left)
- {
- if(m_ctrls.on_mouse_button_down(cur_x, cur_y))
- {
- m_ctrls.set_cur(cur_x, cur_y);
- on_ctrl_change();
- force_redraw();
- }
- else
- {
- if(m_ctrls.in_rect(cur_x, cur_y))
- {
- if(m_ctrls.set_cur(cur_x, cur_y))
- {
- on_ctrl_change();
- force_redraw();
- }
- }
- else
- {
- on_mouse_button_down(cur_x, cur_y, flags);
- }
- }
- }
- if(flags & mouse_right)
- {
- on_mouse_button_down(cur_x, cur_y, flags);
- }
- //m_specific->m_wait_mode = m_wait_mode;
- //m_wait_mode = true;
- }
- break;
-
-
- case MotionNotify:
- {
- flags = 0;
- if(x_event.xmotion.state & Button1Mask) flags |= mouse_left;
- if(x_event.xmotion.state & Button3Mask) flags |= mouse_right;
- if(x_event.xmotion.state & ShiftMask) flags |= kbd_shift;
- if(x_event.xmotion.state & ControlMask) flags |= kbd_ctrl;
-
- cur_x = x_event.xbutton.x;
- cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y :
- x_event.xbutton.y;
-
- if(m_ctrls.on_mouse_move(cur_x, cur_y, (flags & mouse_left) != 0))
- {
- on_ctrl_change();
- force_redraw();
- }
- else
- {
- if(!m_ctrls.in_rect(cur_x, cur_y))
- {
- on_mouse_move(cur_x, cur_y, flags);
- }
- }
- }
- break;
-
- case ButtonRelease:
- {
- flags = 0;
- if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift;
- if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl;
- if(x_event.xbutton.button == Button1) flags |= mouse_left;
- if(x_event.xbutton.button == Button3) flags |= mouse_right;
-
- cur_x = x_event.xbutton.x;
- cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y :
- x_event.xbutton.y;
-
- if(flags & mouse_left)
- {
- if(m_ctrls.on_mouse_button_up(cur_x, cur_y))
- {
- on_ctrl_change();
- force_redraw();
- }
- }
- if(flags & (mouse_left | mouse_right))
- {
- on_mouse_button_up(cur_x, cur_y, flags);
- }
- }
- //m_wait_mode = m_specific->m_wait_mode;
- break;
-
- case ClientMessage:
- if((x_event.xclient.format == 32) &&
- (x_event.xclient.data.l[0] == int(m_specific->m_close_atom)))
- {
- quit = true;
- }
- break;
- }
- }
-
-
- unsigned i = platform_support::max_images;
- while(i--)
- {
- if(m_specific->m_buf_img[i])
- {
- delete [] m_specific->m_buf_img[i];
- }
- }
-
- delete [] m_specific->m_buf_window;
- m_specific->m_ximg_window->data = 0;
- XDestroyImage(m_specific->m_ximg_window);
- XFreeGC(m_specific->m_display, m_specific->m_gc);
- XDestroyWindow(m_specific->m_display, m_specific->m_window);
- XCloseDisplay(m_specific->m_display);
-
- pthread_mutex_unlock (m_specific->m_mutex);
-
- return 0;
- }
-
-
-
- //------------------------------------------------------------------------
- const char* platform_support::img_ext() const { return ".ppm"; }
-
- //------------------------------------------------------------------------
- const char* platform_support::full_file_name(const char* file_name)
- {
- return file_name;
- }
-
- //------------------------------------------------------------------------
- bool platform_support::load_img(unsigned idx, const char* file)
- {
- if(idx < max_images)
- {
- char buf[1024];
- strcpy(buf, file);
- int len = strlen(buf);
- if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0)
- {
- strcat(buf, ".ppm");
- }
-
- FILE* fd = fopen(buf, "rb");
- if(fd == 0) return false;
-
- if((len = fread(buf, 1, 1022, fd)) == 0)
- {
- fclose(fd);
- return false;
- }
- buf[len] = 0;
-
- if(buf[0] != 'P' && buf[1] != '6')
- {
- fclose(fd);
- return false;
- }
-
- char* ptr = buf + 2;
-
- while(*ptr && !isdigit(*ptr)) ptr++;
- if(*ptr == 0)
- {
- fclose(fd);
- return false;
- }
-
- unsigned width = atoi(ptr);
- if(width == 0 || width > 4096)
- {
- fclose(fd);
- return false;
- }
- while(*ptr && isdigit(*ptr)) ptr++;
- while(*ptr && !isdigit(*ptr)) ptr++;
- if(*ptr == 0)
- {
- fclose(fd);
- return false;
- }
- unsigned height = atoi(ptr);
- if(height == 0 || height > 4096)
- {
- fclose(fd);
- return false;
- }
- while(*ptr && isdigit(*ptr)) ptr++;
- while(*ptr && !isdigit(*ptr)) ptr++;
- if(atoi(ptr) != 255)
- {
- fclose(fd);
- return false;
- }
- while(*ptr && isdigit(*ptr)) ptr++;
- if(*ptr == 0)
- {
- fclose(fd);
- return false;
- }
- ptr++;
- fseek(fd, long(ptr - buf), SEEK_SET);
-
- create_img(idx, width, height);
- bool ret = true;
-
- if(m_format == pix_format_rgb24)
- {
- fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd);
- }
- else
- {
- unsigned char* buf_img = new unsigned char [width * height * 3];
- rendering_buffer rbuf_img;
- rbuf_img.attach(buf_img,
- width,
- height,
- m_flip_y ?
- -width * 3 :
- width * 3);
-
- fread(buf_img, 1, width * height * 3, fd);
-
- switch(m_format)
- {
- case pix_format_rgb555:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb555());
- break;
-
- case pix_format_rgb565:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb565());
- break;
-
- case pix_format_bgr24:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgr24());
- break;
-
- case pix_format_rgba32:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgba32());
- break;
-
- case pix_format_argb32:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_argb32());
- break;
-
- case pix_format_bgra32:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgra32());
- break;
-
- case pix_format_abgr32:
- color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_abgr32());
- break;
-
- default:
- ret = false;
- }
- delete [] buf_img;
- }
-
- fclose(fd);
- return ret;
- }
- return false;
- }
-
-
-
-
- //------------------------------------------------------------------------
- bool platform_support::save_img(unsigned idx, const char* file)
- {
- if(idx < max_images && rbuf_img(idx).buf())
- {
- char buf[1024];
- strcpy(buf, file);
- int len = strlen(buf);
- if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0)
- {
- strcat(buf, ".ppm");
- }
-
- FILE* fd = fopen(buf, "wb");
- if(fd == 0) return false;
-
- unsigned w = rbuf_img(idx).width();
- unsigned h = rbuf_img(idx).height();
-
- fprintf(fd, "P6\n%d %d\n255\n", w, h);
-
- unsigned y;
- unsigned char* tmp_buf = new unsigned char [w * 3];
- for(y = 0; y < rbuf_img(idx).height(); y++)
- {
- const unsigned char* src = rbuf_img(idx).row_ptr(m_flip_y ? h - 1 - y : y);
- switch(m_format)
- {
- default: break;
- case pix_format_rgb555:
- color_conv_row(tmp_buf, src, w, color_conv_rgb555_to_rgb24());
- break;
-
- case pix_format_rgb565:
- color_conv_row(tmp_buf, src, w, color_conv_rgb565_to_rgb24());
- break;
-
- case pix_format_bgr24:
- color_conv_row(tmp_buf, src, w, color_conv_bgr24_to_rgb24());
- break;
-
- case pix_format_rgb24:
- color_conv_row(tmp_buf, src, w, color_conv_rgb24_to_rgb24());
- break;
-
- case pix_format_rgba32:
- color_conv_row(tmp_buf, src, w, color_conv_rgba32_to_rgb24());
- break;
-
- case pix_format_argb32:
- color_conv_row(tmp_buf, src, w, color_conv_argb32_to_rgb24());
- break;
-
- case pix_format_bgra32:
- color_conv_row(tmp_buf, src, w, color_conv_bgra32_to_rgb24());
- break;
-
- case pix_format_abgr32:
- color_conv_row(tmp_buf, src, w, color_conv_abgr32_to_rgb24());
- break;
- }
- fwrite(tmp_buf, 1, w * 3, fd);
- }
- delete [] tmp_buf;
- fclose(fd);
- return true;
- }
- return false;
- }
-
-
-
- //------------------------------------------------------------------------
- bool platform_support::create_img(unsigned idx, unsigned width, unsigned height)
- {
- if(idx < max_images)
- {
- if(width == 0) width = rbuf_window().width();
- if(height == 0) height = rbuf_window().height();
- delete [] m_specific->m_buf_img[idx];
- m_specific->m_buf_img[idx] =
- new unsigned char[width * height * (m_bpp / 8)];
-
- m_rbuf_img[idx].attach(m_specific->m_buf_img[idx],
- width,
- height,
- m_flip_y ?
- -width * (m_bpp / 8) :
- width * (m_bpp / 8));
- return true;
- }
- return false;
- }
-
-
- //------------------------------------------------------------------------
- void platform_support::force_redraw()
- {
- m_specific->m_update_flag = true;
- }
-
-
- //------------------------------------------------------------------------
- void platform_support::message(const char* msg)
- {
- fprintf(stderr, "%s\n", msg);
- }
-
- //------------------------------------------------------------------------
- void platform_support::start_timer()
- {
- m_specific->m_sw_start = clock();
- }
-
- //------------------------------------------------------------------------
- double platform_support::elapsed_time() const
- {
- clock_t stop = clock();
- return double(stop - m_specific->m_sw_start) * 1000.0 / CLOCKS_PER_SEC;
- }
-
-
- //------------------------------------------------------------------------
- void platform_support::on_init() {}
- void platform_support::on_resize(int sx, int sy) {}
- void platform_support::on_idle() {}
- void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
- void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
- void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
- void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
- void platform_support::on_ctrl_change() {}
- void platform_support::on_draw() {}
- void platform_support::on_post_draw(void* raw_handler) {}
-
-
-
-}
-
-
-void platform_support_prepare()
-{
-}
-
-void platform_support_lock(agg::platform_support *app)
-{
- pthread_mutex_lock (app->m_specific->m_mutex);
-}
-
-void platform_support_unlock(agg::platform_support *app)
-{
- pthread_mutex_unlock (app->m_specific->m_mutex);
-}
-
-bool platform_support_is_mapped(agg::platform_support *app)
-{
- return app->m_specific->m_is_mapped;
-}
+//---------------------------------------------------------------------------- +// Anti-Grain Geometry (AGG) - Version 2.5 +// A high quality rendering engine for C++ +// Copyright (C) 2002-2006 Maxim Shemanarev +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://antigrain.com +// +// AGG is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// AGG is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with AGG; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +// MA 02110-1301, USA. +//---------------------------------------------------------------------------- + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <time.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> +#include <pthread.h> +#include "agg_basics.h" +#include "util/agg_color_conv_rgb8.h" +#include "platform/agg_platform_support.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + ~platform_specific(); + + void caption(const char* capt); + void put_image(const rendering_buffer* src); + + pix_format_e m_format; + pix_format_e m_sys_format; + int m_byte_order; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + Display* m_display; + int m_screen; + int m_depth; + Visual* m_visual; + Window m_window; + GC m_gc; + XImage* m_ximg_window; + XSetWindowAttributes m_window_attributes; + Atom m_close_atom; + unsigned char* m_buf_window; + unsigned char* m_buf_img[platform_support::max_images]; + unsigned m_keymap[256]; + + bool m_update_flag; + bool m_resize_flag; + bool m_initialized; + bool m_is_mapped; + clock_t m_sw_start; + + pthread_mutex_t m_mutex[1]; + + }; + + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_byte_order(LSBFirst), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_display(0), + m_screen(0), + m_depth(0), + m_visual(0), + m_window(0), + m_gc(0), + m_ximg_window(0), + m_close_atom(0), + + m_buf_window(0), + + m_update_flag(true), + m_resize_flag(true), + m_initialized(false), + m_is_mapped(false) + { + memset(m_buf_img, 0, sizeof(m_buf_img)); + + unsigned i; + for(i = 0; i < 256; i++) + { + m_keymap[i] = i; + } + + m_keymap[XK_Pause&0xFF] = key_pause; + m_keymap[XK_Clear&0xFF] = key_clear; + + m_keymap[XK_KP_0&0xFF] = key_kp0; + m_keymap[XK_KP_1&0xFF] = key_kp1; + m_keymap[XK_KP_2&0xFF] = key_kp2; + m_keymap[XK_KP_3&0xFF] = key_kp3; + m_keymap[XK_KP_4&0xFF] = key_kp4; + m_keymap[XK_KP_5&0xFF] = key_kp5; + m_keymap[XK_KP_6&0xFF] = key_kp6; + m_keymap[XK_KP_7&0xFF] = key_kp7; + m_keymap[XK_KP_8&0xFF] = key_kp8; + m_keymap[XK_KP_9&0xFF] = key_kp9; + + m_keymap[XK_KP_Insert&0xFF] = key_kp0; + m_keymap[XK_KP_End&0xFF] = key_kp1; + m_keymap[XK_KP_Down&0xFF] = key_kp2; + m_keymap[XK_KP_Page_Down&0xFF] = key_kp3; + m_keymap[XK_KP_Left&0xFF] = key_kp4; + m_keymap[XK_KP_Begin&0xFF] = key_kp5; + m_keymap[XK_KP_Right&0xFF] = key_kp6; + m_keymap[XK_KP_Home&0xFF] = key_kp7; + m_keymap[XK_KP_Up&0xFF] = key_kp8; + m_keymap[XK_KP_Page_Up&0xFF] = key_kp9; + m_keymap[XK_KP_Delete&0xFF] = key_kp_period; + m_keymap[XK_KP_Decimal&0xFF] = key_kp_period; + m_keymap[XK_KP_Divide&0xFF] = key_kp_divide; + m_keymap[XK_KP_Multiply&0xFF] = key_kp_multiply; + m_keymap[XK_KP_Subtract&0xFF] = key_kp_minus; + m_keymap[XK_KP_Add&0xFF] = key_kp_plus; + m_keymap[XK_KP_Enter&0xFF] = key_kp_enter; + m_keymap[XK_KP_Equal&0xFF] = key_kp_equals; + + m_keymap[XK_Up&0xFF] = key_up; + m_keymap[XK_Down&0xFF] = key_down; + m_keymap[XK_Right&0xFF] = key_right; + m_keymap[XK_Left&0xFF] = key_left; + m_keymap[XK_Insert&0xFF] = key_insert; + m_keymap[XK_Home&0xFF] = key_delete; + m_keymap[XK_End&0xFF] = key_end; + m_keymap[XK_Page_Up&0xFF] = key_page_up; + m_keymap[XK_Page_Down&0xFF] = key_page_down; + + m_keymap[XK_F1&0xFF] = key_f1; + m_keymap[XK_F2&0xFF] = key_f2; + m_keymap[XK_F3&0xFF] = key_f3; + m_keymap[XK_F4&0xFF] = key_f4; + m_keymap[XK_F5&0xFF] = key_f5; + m_keymap[XK_F6&0xFF] = key_f6; + m_keymap[XK_F7&0xFF] = key_f7; + m_keymap[XK_F8&0xFF] = key_f8; + m_keymap[XK_F9&0xFF] = key_f9; + m_keymap[XK_F10&0xFF] = key_f10; + m_keymap[XK_F11&0xFF] = key_f11; + m_keymap[XK_F12&0xFF] = key_f12; + m_keymap[XK_F13&0xFF] = key_f13; + m_keymap[XK_F14&0xFF] = key_f14; + m_keymap[XK_F15&0xFF] = key_f15; + + m_keymap[XK_Num_Lock&0xFF] = key_numlock; + m_keymap[XK_Caps_Lock&0xFF] = key_capslock; + m_keymap[XK_Scroll_Lock&0xFF] = key_scrollock; + + switch(m_format) + { + default: break; + case pix_format_gray8: + m_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_bpp = 16; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + m_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + m_bpp = 32; + break; + } + m_sw_start = clock(); + + pthread_mutex_init (m_mutex, NULL); + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + pthread_mutex_destroy (m_mutex); + } + + //------------------------------------------------------------------------ + void platform_specific::caption(const char* capt) + { + // Fixed by Enno Fennema (in original AGG library) + XStoreName(m_display, m_window, capt); + XSetIconName(m_display, m_window, capt); + } + + + //------------------------------------------------------------------------ + void platform_specific::put_image(const rendering_buffer* src) + { + if(m_ximg_window == 0) return; + m_ximg_window->data = (char*)m_buf_window; + + if(m_format == m_sys_format) + { + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + } + else + { + int row_len = src->width() * m_sys_bpp / 8; + unsigned char* buf_tmp = + new unsigned char[row_len * src->height()]; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(buf_tmp, + src->width(), + src->height(), + m_flip_y ? -row_len : row_len); + + switch(m_sys_format) + { + default: break; + case pix_format_rgb555: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb555()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb555()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb555()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb555()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb555()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb555()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb565()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb565()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb565()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb565()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb565()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb565()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb565()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb565()); break; + } + break; + + case pix_format_rgba32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgba32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgba32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgba32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgba32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgba32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgba32()); break; + } + break; + + case pix_format_abgr32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_abgr32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_abgr32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_abgr32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_abgr32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_abgr32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_abgr32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_abgr32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_abgr32()); break; + } + break; + + case pix_format_argb32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_argb32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_argb32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_argb32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_argb32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_argb32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); break; + } + break; + + case pix_format_bgra32: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgra32()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_bgra32()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_bgra32()); break; + } + break; + } + + m_ximg_window->data = (char*)buf_tmp; + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + + delete [] buf_tmp; + } + } + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "AGG Application"); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_initialized) + { + m_specific->caption(cap); + } + } + + + //------------------------------------------------------------------------ + enum xevent_mask_e + { + xevent_mask = + PointerMotionMask| + ButtonPressMask| + ButtonReleaseMask| + ExposureMask| + KeyPressMask| + StructureNotifyMask + }; + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_window_flags = flags; + + m_specific->m_display = XOpenDisplay(NULL); + if(m_specific->m_display == 0) + { + fprintf(stderr, "Unable to open DISPLAY!\n"); + return false; + } + + m_specific->m_screen = XDefaultScreen(m_specific->m_display); + m_specific->m_depth = XDefaultDepth(m_specific->m_display, + m_specific->m_screen); + m_specific->m_visual = XDefaultVisual(m_specific->m_display, + m_specific->m_screen); + unsigned long r_mask = m_specific->m_visual->red_mask; + unsigned long g_mask = m_specific->m_visual->green_mask; + unsigned long b_mask = m_specific->m_visual->blue_mask; + + if(m_specific->m_depth < 15 || + r_mask == 0 || g_mask == 0 || b_mask == 0) + { + fprintf(stderr, + "There's no Visual compatible with minimal AGG requirements:\n" + "At least 15-bit color depth and True- or DirectColor class.\n\n"); + XCloseDisplay(m_specific->m_display); + return false; + } + + int t = 1; + int hw_byte_order = LSBFirst; + if(*(char*)&t == 0) hw_byte_order = MSBFirst; + + // Perceive SYS-format by mask + switch(m_specific->m_depth) + { + case 15: + m_specific->m_sys_bpp = 16; + if(r_mask == 0x7C00 && g_mask == 0x3E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb555; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 16: + m_specific->m_sys_bpp = 16; + if(r_mask == 0xF800 && g_mask == 0x7E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb565; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 24: + case 32: + m_specific->m_sys_bpp = 32; + if(g_mask == 0xFF00) + { + if(r_mask == 0xFF && b_mask == 0xFF0000) + { + switch(m_specific->m_format) + { + case pix_format_rgba32: + m_specific->m_sys_format = pix_format_rgba32; + m_specific->m_byte_order = LSBFirst; + break; + + case pix_format_abgr32: + m_specific->m_sys_format = pix_format_abgr32; + m_specific->m_byte_order = MSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == LSBFirst) ? + pix_format_rgba32 : + pix_format_abgr32; + break; + } + } + + if(r_mask == 0xFF0000 && b_mask == 0xFF) + { + switch(m_specific->m_format) + { + case pix_format_argb32: + m_specific->m_sys_format = pix_format_argb32; + m_specific->m_byte_order = MSBFirst; + break; + + case pix_format_bgra32: + m_specific->m_sys_format = pix_format_bgra32; + m_specific->m_byte_order = LSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == MSBFirst) ? + pix_format_argb32 : + pix_format_bgra32; + break; + } + } + } + break; + } + + if(m_specific->m_sys_format == pix_format_undefined) + { + fprintf(stderr, + "RGB masks are not compatible with AGG pixel formats:\n" + "R=%08x, R=%08x, B=%08x\n", + (unsigned)r_mask, (unsigned)g_mask, (unsigned)b_mask); + XCloseDisplay(m_specific->m_display); + return false; + } + + + + memset(&m_specific->m_window_attributes, + 0, + sizeof(m_specific->m_window_attributes)); + + m_specific->m_window_attributes.border_pixel = + XBlackPixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.background_pixel = + XWhitePixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.override_redirect = 0; + + unsigned long window_mask = CWBackPixel | CWBorderPixel; + + m_specific->m_window = + XCreateWindow(m_specific->m_display, + XDefaultRootWindow(m_specific->m_display), + 0, 0, + width, + height, + 0, + m_specific->m_depth, + InputOutput, + CopyFromParent, + window_mask, + &m_specific->m_window_attributes); + + + m_specific->m_gc = XCreateGC(m_specific->m_display, + m_specific->m_window, + 0, 0); + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8)); + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? -width * (m_bpp / 8) : width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + m_specific->caption(m_caption); + m_initial_width = width; + m_initial_height = height; + + if(!m_specific->m_initialized) + { + on_init(); + m_specific->m_initialized = true; + } + + trans_affine_resizing(width, height); + on_resize(width, height); + m_specific->m_update_flag = true; + + XSizeHints *hints = XAllocSizeHints(); + if(hints) + { + if(flags & window_resize) + { + hints->min_width = 32; + hints->min_height = 32; + hints->max_width = 4096; + hints->max_height = 4096; + } + else + { + hints->min_width = width; + hints->min_height = height; + hints->max_width = width; + hints->max_height = height; + } + hints->flags = PMaxSize | PMinSize; + + XSetWMNormalHints(m_specific->m_display, + m_specific->m_window, + hints); + + XFree(hints); + } + + + XMapWindow(m_specific->m_display, + m_specific->m_window); + + XSelectInput(m_specific->m_display, + m_specific->m_window, + xevent_mask); + + + m_specific->m_close_atom = XInternAtom(m_specific->m_display, + "WM_DELETE_WINDOW", + false); + + XSetWMProtocols(m_specific->m_display, + m_specific->m_window, + &m_specific->m_close_atom, + 1); + + return true; + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + if (! m_specific->m_is_mapped) + return; + + m_specific->put_image(&m_rbuf_window); + + // When m_wait_mode is true we can discard all the events + // came while the image is being drawn. In this case + // the X server does not accumulate mouse motion events. + // When m_wait_mode is false, i.e. we have some idle drawing + // we cannot afford to miss any events + XSync(m_specific->m_display, m_wait_mode); + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + XFlush(m_specific->m_display); + + bool quit = false; + unsigned flags; + int cur_x; + int cur_y; + + while(!quit) + { + if(m_specific->m_update_flag && m_specific->m_is_mapped) + { + on_draw(); + update_window(); + m_specific->m_update_flag = false; + } + + if(!m_wait_mode) + { + if(XPending(m_specific->m_display) == 0) + { + on_idle(); + continue; + } + } + + XEvent x_event; + pthread_mutex_unlock (m_specific->m_mutex); + XNextEvent(m_specific->m_display, &x_event); + pthread_mutex_lock (m_specific->m_mutex); + + // In the Idle mode discard all intermediate MotionNotify events + if(!m_wait_mode && x_event.type == MotionNotify) + { + XEvent te = x_event; + for(;;) + { + if(XPending(m_specific->m_display) == 0) break; + XNextEvent(m_specific->m_display, &te); + if(te.type != MotionNotify) break; + } + x_event = te; + } + + switch(x_event.type) + { + case MapNotify: + { + on_draw(); + update_window(); + m_specific->m_is_mapped = true; + m_specific->m_update_flag = false; + } + break; + + case ConfigureNotify: + { + if(x_event.xconfigure.width != int(m_rbuf_window.width()) || + x_event.xconfigure.height != int(m_rbuf_window.height())) + { + int width = x_event.xconfigure.width; + int height = x_event.xconfigure.height; + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + trans_affine_resizing(width, height); + on_resize(width, height); + on_draw(); + update_window(); + } + } + break; + + case Expose: + m_specific->put_image(&m_rbuf_window); + XFlush(m_specific->m_display); + XSync(m_specific->m_display, false); + break; + + case KeyPress: + { + KeySym key = XLookupKeysym(&x_event.xkey, 0); + flags = 0; + if(x_event.xkey.state & Button1Mask) flags |= mouse_left; + if(x_event.xkey.state & Button3Mask) flags |= mouse_right; + if(x_event.xkey.state & ShiftMask) flags |= kbd_shift; + if(x_event.xkey.state & ControlMask) flags |= kbd_ctrl; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(m_specific->m_keymap[key & 0xFF]) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + case key_f2: + copy_window_to_img(max_images - 1); + save_img(max_images - 1, "screenshot"); + break; + } + + if(m_ctrls.on_arrow_keys(left, right, down, up)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_key(x_event.xkey.x, + m_flip_y ? + m_rbuf_window.height() - x_event.xkey.y : + x_event.xkey.y, + m_specific->m_keymap[key & 0xFF], + flags); + } + } + break; + + + case ButtonPress: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_down(cur_x, cur_y)) + { + m_ctrls.set_cur(cur_x, cur_y); + on_ctrl_change(); + force_redraw(); + } + else + { + if(m_ctrls.in_rect(cur_x, cur_y)) + { + if(m_ctrls.set_cur(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(cur_x, cur_y, flags); + } + } + } + if(flags & mouse_right) + { + on_mouse_button_down(cur_x, cur_y, flags); + } + //m_specific->m_wait_mode = m_wait_mode; + //m_wait_mode = true; + } + break; + + + case MotionNotify: + { + flags = 0; + if(x_event.xmotion.state & Button1Mask) flags |= mouse_left; + if(x_event.xmotion.state & Button3Mask) flags |= mouse_right; + if(x_event.xmotion.state & ShiftMask) flags |= kbd_shift; + if(x_event.xmotion.state & ControlMask) flags |= kbd_ctrl; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(m_ctrls.on_mouse_move(cur_x, cur_y, (flags & mouse_left) != 0)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + if(!m_ctrls.in_rect(cur_x, cur_y)) + { + on_mouse_move(cur_x, cur_y, flags); + } + } + } + break; + + case ButtonRelease: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_up(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + if(flags & (mouse_left | mouse_right)) + { + on_mouse_button_up(cur_x, cur_y, flags); + } + } + //m_wait_mode = m_specific->m_wait_mode; + break; + + case ClientMessage: + if((x_event.xclient.format == 32) && + (x_event.xclient.data.l[0] == int(m_specific->m_close_atom))) + { + quit = true; + } + break; + } + } + + + unsigned i = platform_support::max_images; + while(i--) + { + if(m_specific->m_buf_img[i]) + { + delete [] m_specific->m_buf_img[i]; + } + } + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + XFreeGC(m_specific->m_display, m_specific->m_gc); + XDestroyWindow(m_specific->m_display, m_specific->m_window); + XCloseDisplay(m_specific->m_display); + + return 0; + } + + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "rb"); + if(fd == 0) return false; + + if((len = fread(buf, 1, 1022, fd)) == 0) + { + fclose(fd); + return false; + } + buf[len] = 0; + + if(buf[0] != 'P' && buf[1] != '6') + { + fclose(fd); + return false; + } + + char* ptr = buf + 2; + + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + + unsigned width = atoi(ptr); + if(width == 0 || width > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + unsigned height = atoi(ptr); + if(height == 0 || height > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(atoi(ptr) != 255) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + ptr++; + fseek(fd, long(ptr - buf), SEEK_SET); + + create_img(idx, width, height); + bool ret = true; + + if(m_format == pix_format_rgb24) + { + fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd); + } + else + { + unsigned char* buf_img = new unsigned char [width * height * 3]; + rendering_buffer rbuf_img; + rbuf_img.attach(buf_img, + width, + height, + m_flip_y ? + -width * 3 : + width * 3); + + fread(buf_img, 1, width * height * 3, fd); + + switch(m_format) + { + case pix_format_rgb555: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb555()); + break; + + case pix_format_rgb565: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb565()); + break; + + case pix_format_bgr24: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_rgba32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgba32()); + break; + + case pix_format_argb32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_argb32()); + break; + + case pix_format_bgra32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_bgra32()); + break; + + case pix_format_abgr32: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_abgr32()); + break; + + default: + ret = false; + } + delete [] buf_img; + } + + fclose(fd); + return ret; + } + return false; + } + + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images && rbuf_img(idx).buf()) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "wb"); + if(fd == 0) return false; + + unsigned w = rbuf_img(idx).width(); + unsigned h = rbuf_img(idx).height(); + + fprintf(fd, "P6\n%d %d\n255\n", w, h); + + unsigned y; + unsigned char* tmp_buf = new unsigned char [w * 3]; + for(y = 0; y < rbuf_img(idx).height(); y++) + { + const unsigned char* src = rbuf_img(idx).row_ptr(m_flip_y ? h - 1 - y : y); + switch(m_format) + { + default: break; + case pix_format_rgb555: + color_conv_row(tmp_buf, src, w, color_conv_rgb555_to_rgb24()); + break; + + case pix_format_rgb565: + color_conv_row(tmp_buf, src, w, color_conv_rgb565_to_rgb24()); + break; + + case pix_format_bgr24: + color_conv_row(tmp_buf, src, w, color_conv_bgr24_to_rgb24()); + break; + + case pix_format_rgb24: + color_conv_row(tmp_buf, src, w, color_conv_rgb24_to_rgb24()); + break; + + case pix_format_rgba32: + color_conv_row(tmp_buf, src, w, color_conv_rgba32_to_rgb24()); + break; + + case pix_format_argb32: + color_conv_row(tmp_buf, src, w, color_conv_argb32_to_rgb24()); + break; + + case pix_format_bgra32: + color_conv_row(tmp_buf, src, w, color_conv_bgra32_to_rgb24()); + break; + + case pix_format_abgr32: + color_conv_row(tmp_buf, src, w, color_conv_abgr32_to_rgb24()); + break; + } + fwrite(tmp_buf, 1, w * 3, fd); + } + delete [] tmp_buf; + fclose(fd); + return true; + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = rbuf_window().width(); + if(height == 0) height = rbuf_window().height(); + delete [] m_specific->m_buf_img[idx]; + m_specific->m_buf_img[idx] = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_img[idx].attach(m_specific->m_buf_img[idx], + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_update_flag = true; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + fprintf(stderr, "%s\n", msg); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->m_sw_start = clock(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + clock_t stop = clock(); + return double(stop - m_specific->m_sw_start) * 1000.0 / CLOCKS_PER_SEC; + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + + +} + + +void platform_support_prepare() +{ +} + +void platform_support_lock(agg::platform_support *app) +{ + pthread_mutex_lock (app->m_specific->m_mutex); +} + +void platform_support_unlock(agg::platform_support *app) +{ + pthread_mutex_unlock (app->m_specific->m_mutex); +} + +bool platform_support_is_mapped(agg::platform_support *app) +{ + return app->m_specific->m_is_mapped; +} diff --git a/agg-plot/colors.cpp b/agg-plot/colors.cpp index e4ea0807..1b16be47 100644 --- a/agg-plot/colors.cpp +++ b/agg-plot/colors.cpp @@ -50,3 +50,27 @@ rgba8_push_lookup (lua_State *L, const char *color_str) return new(L, GS_RGBA_COLOR) agg::rgba8(r, g, b, a); } + +agg::rgba8 * +color_arg_lookup (lua_State *L, int index) +{ + agg::rgba8 *c; + + if (lua_isnil (L, index)) + { + c = rgba8_push_default (L); + lua_replace (L, index); + } + else if (lua_isstring (L, index)) + { + const char *cstr = lua_tostring (L, index); + c = rgba8_push_lookup (L, cstr); + lua_replace (L, index); + } + else + { + c = (agg::rgba8 *) gs_check_userdata (L, index, GS_RGBA_COLOR); + } + + return c; +} diff --git a/agg-plot/colors.h b/agg-plot/colors.h index 6add76f2..6e9263d6 100644 --- a/agg-plot/colors.h +++ b/agg-plot/colors.h @@ -8,7 +8,8 @@ extern "C" { #include "defs.h" #include "agg_color_rgba.h" -extern agg::rgba8 * rgba8_push_lookup(lua_State *L, const char *color_str); -extern agg::rgba8 * rgba8_push_default(lua_State *L); +extern agg::rgba8 * rgba8_push_lookup (lua_State *L, const char *color_str); +extern agg::rgba8 * rgba8_push_default (lua_State *L); +extern agg::rgba8 * color_arg_lookup (lua_State *L, int index); #endif diff --git a/agg-plot/lua-draw.cpp b/agg-plot/lua-draw.cpp index d812d7ea..48e9580f 100644 --- a/agg-plot/lua-draw.cpp +++ b/agg-plot/lua-draw.cpp @@ -45,6 +45,9 @@ static int agg_text_set_point (lua_State *L); static int agg_text_rotate (lua_State *L); static int agg_rgba_free (lua_State *L); +static int agg_rgba_add (lua_State *L); +static int agg_rgba_mul (lua_State *L); +static int agg_rgba_set_alpha (lua_State *L); static void path_cmd (my::path *p, int cmd, struct cmd_call_stack *stack); @@ -74,6 +77,9 @@ static const struct luaL_Reg agg_path_methods[] = { static const struct luaL_Reg rgba_methods[] = { {"__gc", agg_rgba_free}, + {"__add", agg_rgba_add }, + {"__mul", agg_rgba_mul }, + {"alpha", agg_rgba_set_alpha }, {NULL, NULL} }; @@ -240,7 +246,7 @@ agg_text_new (lua_State *L) { double size = luaL_optnumber (L, 1, 10.0); double width = luaL_optnumber (L, 2, 1.0); - my::text *txt = new(L, GS_DRAW_TEXT) my::text(size, width); + new(L, GS_DRAW_TEXT) my::text(size, width); return 1; } @@ -321,6 +327,50 @@ agg_rgb_new (lua_State *L) } int +agg_rgba_set_alpha (lua_State *L) +{ + agg::rgba8 *c = (agg::rgba8 *) gs_check_userdata (L, 1, GS_RGBA_COLOR); + double a = luaL_checknumber (L, 2); + c->a = agg::rgba8::base_mask * a; + return 0; +} + +int +agg_rgba_add (lua_State *L) +{ + agg::rgba8 *c1 = (agg::rgba8 *) gs_check_userdata (L, 1, GS_RGBA_COLOR); + agg::rgba8 *c2 = (agg::rgba8 *) gs_check_userdata (L, 2, GS_RGBA_COLOR); + + unsigned int r = c1->r + c2->r; + unsigned int g = c1->g + c2->g; + unsigned int b = c1->b + c2->b; + + new(L, GS_RGBA_COLOR) agg::rgba8(r, g, b); + + return 1; +} + +int +agg_rgba_mul (lua_State *L) +{ + int is = 1, ic = 2; + + if (gs_is_userdata (L, 1, GS_RGBA_COLOR)) + { + ic = 1; + is = 2; + } + + double f = luaL_checknumber (L, is); + agg::rgba8 *c = (agg::rgba8 *) gs_check_userdata (L, ic, GS_RGBA_COLOR); + + unsigned int r = f * c->r, g = f * c->g, b = f * c->b; + + new(L, GS_RGBA_COLOR) agg::rgba8(r, g, b); + return 1; +} + +int agg_rgba_free (lua_State *L) { typedef agg::rgba8 rgba_t; @@ -345,6 +395,8 @@ draw_register (lua_State *L) lua_pop (L, 1); luaL_newmetatable (L, GS_METATABLE(GS_RGBA_COLOR)); + lua_pushvalue (L, -1); + lua_setfield (L, -2, "__index"); luaL_register (L, NULL, rgba_methods); lua_pop (L, 1); } diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp index f0993db9..0d59a5e7 100644 --- a/agg-plot/lua-plot.cpp +++ b/agg-plot/lua-plot.cpp @@ -17,6 +17,7 @@ extern "C" { #include "trans.h" #include "colors.h" #include "xwin-show.h" +#include "agg-parse-trans.h" __BEGIN_DECLS @@ -33,25 +34,12 @@ static int agg_plot_title_get (lua_State *L); static int agg_plot_units_set (lua_State *L); static int agg_plot_units_get (lua_State *L); -static vertex_source * build_stroke (lua_State *L, int index, vertex_source *obj); -static vertex_source * build_dash (lua_State *L, int index, vertex_source *obj); -static vertex_source * build_curve (lua_State *L, int index, vertex_source *obj); -static vertex_source * build_marker (lua_State *L, int index, vertex_source *obj); -static vertex_source * build_rotate (lua_State *L, int index, vertex_source *obj); -static vertex_source * build_translate (lua_State *L, int index, vertex_source *obj); - -/* DEBUG DEBUG DEBUG */ -static int window_debug_list (lua_State *L); -static int obj_getfenv (lua_State *L); - static const struct luaL_Reg plot_functions[] = { {"path", agg_path_new}, {"text", agg_text_new}, {"rgba", agg_rgba_new}, {"rgb", agg_rgb_new}, {"plot", agg_plot_new}, - {"windows", window_debug_list}, - {"objgetfenv", obj_getfenv}, {NULL, NULL} }; @@ -78,61 +66,7 @@ static const struct luaL_Reg agg_plot_properties_set[] = { {NULL, NULL} }; -struct property_reg { - int id; - const char *name; -}; - -struct builder_reg { - const char *name; - vertex_source *(*func)(lua_State *, int, vertex_source *); -}; - __END_DECLS - - -struct property_reg line_cap_properties[] = { - {(int) agg::butt_cap, "butt" }, - {(int) agg::square_cap, "square"}, - {(int) agg::round_cap, "round" }, - {0, NULL} -}; - -struct property_reg line_join_properties[] = { - {(int) agg::miter_join, "miter" }, - {(int) agg::miter_join_revert, "miter.rev" }, - {(int) agg::round_join, "round" }, - {(int) agg::bevel_join, "bevel" }, - {(int) agg::miter_join_round, "miter.round"}, - {0, NULL} -}; - -const builder_reg builder_table[] = { - {"stroke", build_stroke }, - {"dash", build_dash}, - {"curve", build_curve}, - {"marker", build_marker}, - {"translate", build_translate}, - {"rotate", build_rotate}, - {NULL, NULL} -}; - -static int -property_lookup (struct property_reg *prop, const char *key) -{ - int default_value = prop->id; - - if (key == NULL) - return default_value; - - for ( ; prop->name; prop++) - { - if (strcmp (prop->name, key) == 0) - return prop->id; - } - - return default_value; -} void agg_plot::wait_update() { @@ -237,151 +171,6 @@ agg_plot_newindex (lua_State *L) return mlua_newindex_with_properties (L, agg_plot_properties_set); } -vertex_source * -build_stroke (lua_State *L, int specindex, vertex_source *obj) -{ - double width = mlua_named_optnumber (L, specindex, "width", 1.0); - const char *cap_str = mlua_named_optstring (L, specindex, "cap", NULL); - const char *join_str = mlua_named_optstring (L, specindex, "join", NULL); - - trans::stroke *stroke = new trans::stroke(obj, width); - - if (cap_str) - { - int cap = property_lookup (line_cap_properties, cap_str); - stroke->line_cap((agg::line_cap_e) cap); - } - - if (join_str) - { - int join = property_lookup (line_join_properties, join_str); - stroke->line_join((agg::line_join_e) join); - } - - return (vertex_source *) stroke; -} - -vertex_source * -build_curve (lua_State *L, int specindex, vertex_source *obj) -{ - trans::curve *c = new trans::curve(obj); - return (vertex_source *) c; -} - -vertex_source * -build_marker (lua_State *L, int specindex, vertex_source *obj) -{ - double size = mlua_named_optnumber (L, specindex, "size", 3.0); - return (vertex_source *) new trans::marker(obj, size); -} - -vertex_source * -build_dash (lua_State *L, int specindex, vertex_source *obj) -{ - double a = mlua_named_optnumber (L, specindex, "a", 10.0); - double b = mlua_named_optnumber (L, specindex, "b", a); - - trans::dash *dash = new trans::dash(obj); - dash->add_dash(a, b); - - return (vertex_source *) dash; -} - -vertex_source * -build_translate (lua_State *L, int specindex, vertex_source *obj) -{ - double x = mlua_named_number (L, specindex, "x"); - double y = mlua_named_number (L, specindex, "y"); - - trans::affine *t = new trans::affine(obj); - t->translate(x, y); - - return (vertex_source *) t; -} - -vertex_source * -build_rotate (lua_State *L, int specindex, vertex_source *obj) -{ - double a = mlua_named_number (L, specindex, "angle"); - - trans::affine *t = new trans::affine(obj); - t->rotate(a); - - return (vertex_source *) t; -} - -vertex_source * -parse_spec (lua_State *L, int specindex, vertex_source *obj) -{ - const char *tag; - - lua_rawgeti (L, specindex, 1); - if (! lua_isstring (L, -1)) - { - luaL_error (L, "the tag of the transformation is invalid"); - return NULL; - } - - tag = lua_tostring (L, -1); - lua_pop (L, 1); - - for (const builder_reg *b = builder_table; b->name != NULL; b++) - { - if (strcmp (b->name, tag) == 0) - return b->func (L, specindex, obj); - } - - luaL_error (L, "invalid trasformation tag"); - return NULL; -} - -vertex_source * -lparse_spec_pipeline (lua_State *L, int index, vertex_source *obj) -{ - size_t k, nb; - - if (lua_type (L, index) == LUA_TTABLE) - nb = lua_objlen (L, index); - else - { - luaL_error (L, "post transform argument should be a table"); - return NULL; - } - - for (k = nb; k > 0; k--) - { - lua_rawgeti (L, index, k); - obj = parse_spec (L, index+1, obj); - lua_pop (L, 1); - } - - return obj; -} - -static agg::rgba8 * -color_arg_lookup (lua_State *L, int index) -{ - agg::rgba8 *c; - - if (lua_isnil (L, index)) - { - c = rgba8_push_default (L); - lua_replace (L, index); - } - else if (lua_isstring (L, index)) - { - const char *cstr = lua_tostring (L, index); - c = rgba8_push_lookup (L, cstr); - lua_replace (L, index); - } - else - { - c = check_agg_rgba8 (L, index); - } - - return c; -} - static int agg_plot_add_gener (lua_State *L, bool as_line) { @@ -401,7 +190,7 @@ agg_plot_add_gener (lua_State *L, bool as_line) if (narg > 4) { - curr = lparse_spec_pipeline (L, 5, curr); + curr = parse_spec_pipeline (L, 5, curr); lua_pop (L, 1); } @@ -412,7 +201,7 @@ agg_plot_add_gener (lua_State *L, bool as_line) if (narg > 3) { - curr = lparse_spec_pipeline (L, 4, curr); + curr = parse_spec_pipeline (L, 4, curr); lua_pop (L, 1); } @@ -469,6 +258,7 @@ agg_plot_show (lua_State *L) pthread_attr_destroy (attr); mlua_window_unref(L, p->id); p->id = -1; + AGG_UNLOCK(); return luaL_error(L, "error creating thread."); } @@ -481,20 +271,6 @@ agg_plot_show (lua_State *L) return 0; } -int -window_debug_list(lua_State *L) -{ - lua_getfield (L, LUA_REGISTRYINDEX, "GSL.windows"); - return 1; -} - -int -obj_getfenv(lua_State *L) -{ - lua_getfenv (L, 1); - return 1; -} - void plot_register (lua_State *L) { diff --git a/agg-plot/plot-window.cpp b/agg-plot/plot-window.cpp new file mode 100644 index 00000000..d16688b3 --- /dev/null +++ b/agg-plot/plot-window.cpp @@ -0,0 +1,345 @@ + +extern "C" { +#include "lua.h" +#include "lauxlib.h" +} + +#include "platform/agg_platform_support.h" + +#include "defs.h" +#include "resource-manager.h" +#include "gsl-shell.h" +#include "plot-window.h" +#include "agg-parse-trans.h" +#include "lua-cpp-utils.h" +#include "lua-utils.h" +#include "lua-draw.h" +#include "gs-types.h" +#include "colors.h" +#include "canvas.h" +#include "trans.h" + +extern void platform_support_prepare (); +extern void platform_support_lock (agg::platform_support *app); +extern void platform_support_unlock (agg::platform_support *app); +extern bool platform_support_is_mapped (agg::platform_support *app); + + +__BEGIN_DECLS + +static void * win_thread_function (void *_win); + +static int plot_window_new (lua_State *L); +static int plot_window_free (lua_State *L); +static int plot_window_index (lua_State *L); +static int plot_window_draw (lua_State *L); +static int plot_window_clear (lua_State *L); +static int plot_window_update (lua_State *L); +static int plot_window_size (lua_State *L); +static int plot_window_set_transform (lua_State *L); + +static const struct luaL_Reg plotwin_functions[] = { + {"window", plot_window_new}, + {NULL, NULL} +}; + +static const struct luaL_Reg plot_window_methods[] = { + {"__gc", plot_window_free}, + {"__index", plot_window_index}, + {NULL, NULL} +}; + +static const struct luaL_Reg plot_window_methods_protected[] = { + {"draw", plot_window_draw}, + {"clear", plot_window_clear}, + {"update", plot_window_update}, + {"size", plot_window_size}, + {"transform", plot_window_set_transform}, + {NULL, NULL} +}; + +__END_DECLS + +class plot_window : public agg::platform_support { +private: + canvas *m_canvas; + agg::rgba m_bgcolor; + +public: + agg::trans_affine m_trans; + + enum win_status_e { not_ready, starting, running, error, closed }; + + int id; + enum win_status_e status; + + plot_window(agg::rgba& bgcol) : + agg::platform_support(agg::pix_format_bgr24, true), + m_canvas(NULL), m_bgcolor(bgcol), m_trans(), id(-1), status(not_ready) + { }; + + virtual ~plot_window() + { + if (m_canvas) + delete m_canvas; + }; + + virtual void on_init(); + virtual void on_resize(int sx, int sy); + + void start(); + void clear() { if (m_canvas) m_canvas->clear(); }; + + bool draw(vertex_source *obj, agg::rgba8 *color) + { + if (! m_canvas) + return false; + + m_canvas->draw(*obj, *color); + return true; + }; + + void set_transform(double sx, double sy, double x0, double y0) + { + m_trans = agg::trans_affine(sx, 0.0, 0.0, sy, x0, y0); + }; + + static plot_window *check (lua_State *L, int index); +}; + +void +plot_window::on_init() +{ + if (m_canvas) + delete m_canvas; + + m_canvas = new canvas(rbuf_window(), width(), height(), m_bgcolor); +} + +void +plot_window::on_resize(int sx, int sy) +{ + if (m_canvas) + delete m_canvas; + + m_canvas = new canvas(rbuf_window(), sx, sy, m_bgcolor); +} + +void +plot_window::start() +{ + this->caption("GSL shell plot"); + if (this->init(480, 480, agg::window_resize)) + { + this->status = plot_window::running; + + this->run(); + + this->status = plot_window::closed; + + GSL_SHELL_LOCK(); + gsl_shell_unref_plot (this->id); + GSL_SHELL_UNLOCK(); + } + + platform_support_unlock (this); +} + +void * +win_thread_function (void *_win) +{ + platform_support_prepare(); + + plot_window *win = (plot_window *) _win; + win->start(); + return NULL; +} + +plot_window * +plot_window::check (lua_State *L, int index) +{ + return (plot_window *) gs_check_userdata (L, index, GS_AGG_WINDOW); +} + +int +plot_window_new (lua_State *L) +{ + agg::rgba8 *c8; + + if (lua_gettop (L) == 0) + c8 = rgba8_push_default (L); + else + c8 = color_arg_lookup (L, 1); + + const double bs = (double) agg::rgba8::base_mask; + agg::rgba color(c8->r / bs, c8->g / bs, c8->b / bs, c8->a / bs); + + plot_window *win = new(L, GS_AGG_WINDOW) plot_window(color); + + win->id = mlua_window_ref(L, lua_gettop (L)); + + pthread_attr_t attr[1]; + pthread_t win_thread[1]; + + pthread_attr_init (attr); + pthread_attr_setdetachstate (attr, PTHREAD_CREATE_DETACHED); + + platform_support_lock (win); + + if (pthread_create(win_thread, attr, win_thread_function, (void*) win)) + { + mlua_window_unref(L, win->id); + + pthread_attr_destroy (attr); + win->status = plot_window::error; + + luaL_error(L, "error creating thread"); + } + + pthread_attr_destroy (attr); + win->status = plot_window::starting; + + return 1; +} + +int +plot_window_free (lua_State *L) +{ + plot_window *win = plot_window::check (L, 1); + win->~plot_window(); + return 0; +} + +int +plot_window_draw (lua_State *L) +{ + plot_window *win = plot_window::check (L, 1); + int narg = lua_gettop (L); + agg::rgba8 *color; + + if (narg <= 2) + color = rgba8_push_default (L); + else + color = color_arg_lookup (L, 3); + + vertex_source *curr = check_agg_obj (L, 2); + + trans::affine *to = new trans::affine(curr); + to->set_matrix(win->m_trans); + curr = to; + + if (narg > 3) + { + curr = parse_spec_pipeline (L, 4, curr); + lua_pop (L, 1); + } + + bool success = win->draw(curr, color); + + lua_management::dispose(curr); + + if (! success) + return luaL_error (L, "canvas not ready"); + + return 0; +} + +int +plot_window_clear (lua_State *L) +{ + plot_window *win = plot_window::check (L, 1); + win->clear(); + return 0; +} + +int +plot_window_update (lua_State *L) +{ + plot_window *win = plot_window::check (L, 1); + win->update_window(); + return 0; +} + +static int +plot_window_index_protected (lua_State *L) +{ + plot_window *win = plot_window::check(L, lua_upvalueindex(2)); + + platform_support_lock (win); + + if (win->status != plot_window::running) + { + platform_support_unlock (win); + return luaL_error (L, "window is not active"); + } + + int narg = lua_gettop (L); + + lua_pushvalue (L, lua_upvalueindex(1)); + lua_insert (L, 1); + + if (lua_pcall (L, narg, LUA_MULTRET, 0) != 0) + { + platform_support_unlock (win); + return lua_error (L); + } + + platform_support_unlock (win); + return lua_gettop (L); +} + +int +plot_window_index (lua_State *L) +{ + const char *key = luaL_checkstring (L, 2); + + const struct luaL_Reg *r = mlua_find_method (plot_window_methods, key); + if (r) + { + lua_pushcfunction (L, r->func); + return 1; + } + + r = mlua_find_method (plot_window_methods_protected, key); + if (r) + { + lua_pushcfunction (L, r->func); + lua_pushvalue (L, 1); + lua_pushcclosure (L, plot_window_index_protected, 2); + return 1; + } + + return 0; +} + +int +plot_window_size (lua_State *L) +{ + plot_window *win = plot_window::check(L, 1); + lua_pushinteger (L, win->width()); + lua_pushinteger (L, win->height()); + return 2; +} + +int +plot_window_set_transform (lua_State *L) +{ + plot_window *win = plot_window::check(L, 1); + double sx = luaL_checknumber (L, 2); + double sy = luaL_checknumber (L, 3); + double x0 = luaL_optnumber (L, 4, 0.0); + double y0 = luaL_optnumber (L, 5, 0.0); + win->set_transform(sx, sy, x0, y0); + return 0; +} + +void +plot_window_register (lua_State *L) +{ + luaL_newmetatable (L, GS_METATABLE(GS_AGG_WINDOW)); + luaL_register (L, NULL, plot_window_methods); + lua_pop (L, 1); + + /* gsl module registration */ + luaL_register (L, NULL, plotwin_functions); +} diff --git a/agg-plot/plot-window.h b/agg-plot/plot-window.h new file mode 100644 index 00000000..18a21a0a --- /dev/null +++ b/agg-plot/plot-window.h @@ -0,0 +1,16 @@ +#ifndef PLOT_WINDOW_H +#define PLOT_WINDOW_H + +__BEGIN_DECLS +#include "lua.h" +__END_DECLS + +#include "defs.h" + +__BEGIN_DECLS + +extern void plot_window_register (lua_State *L); + +__END_DECLS + +#endif diff --git a/agg-plot/trans.h b/agg-plot/trans.h index 6110263d..35dec2a7 100644 --- a/agg-plot/trans.h +++ b/agg-plot/trans.h @@ -6,6 +6,7 @@ #include "agg_conv_curve.h" #include "agg_conv_dash.h" #include "agg_conv_transform.h" +#include "agg_conv_contour.h" #include "agg_vcgen_markers_term.h" #include "agg_arrowhead.h" #include "agg_bounding_rect.h" @@ -59,6 +60,7 @@ typedef vs_trans_proxy<agg::conv_stroke<vertex_source> > vs_stroke; typedef vs_trans_proxy<agg::conv_curve<vertex_source> > vs_curve; typedef vs_trans_proxy<agg::conv_dash<vertex_source> > vs_dash; typedef vs_trans_proxy<agg::conv_transform<vertex_source> > vs_transform; +typedef vs_trans_proxy<agg::conv_contour<vertex_source> > vs_contour; namespace trans { @@ -127,6 +129,24 @@ namespace trans { m_source->apply_transform(m, as); }; }; + + class extend : public vs_contour { + public: + typedef agg::conv_contour<vertex_source> base_type; + + extend(vertex_source* src, double width): vs_contour(src) + { + base_type& v = self(); + v.width(width); + v.auto_detect_orientation(true); + }; + + virtual void apply_transform(agg::trans_affine& m, double as) + { + m_output.approximation_scale(as); + m_source->apply_transform(m, as); + }; + }; class resize : public vs_transform { agg::trans_affine m_matrix; @@ -161,6 +181,8 @@ namespace trans { const trans_affine& rotate(double a) { return m_matrix.rotate(a); }; const trans_affine& translate(double x, double y) { return m_matrix.translate(x, y); }; + + void set_matrix(const agg::trans_affine& m) { m_matrix = m; }; }; } diff --git a/agg-plot/xwin-show.cpp b/agg-plot/xwin-show.cpp index 25cd6bee..f96c401c 100644 --- a/agg-plot/xwin-show.cpp +++ b/agg-plot/xwin-show.cpp @@ -77,6 +77,8 @@ xwin_thread_function (void *_plot) the_application app(agg::pix_format_bgr24, flip_y, p); app.caption("GSL shell plot"); + platform_support_lock (&app); + if(app.init(780, 400, agg::window_resize)) { p->window = (void *) &app; @@ -95,5 +97,7 @@ xwin_thread_function (void *_plot) GSL_SHELL_UNLOCK(); } + platform_support_unlock (&app); + return NULL; } |