# HG changeset patch # User Shai Ayal # Date 1203268842 -7200 # Node ID caab78e7e377261337a98d70de5cdbf3028cedc2 # Parent 8ff92634982dd582477f28aee1824c8705da7a98 added checks for fltk & freetype in configure script * * * added fltk_backend * * * the fltk_backend now works but that's about it * * * fltk_backend now working * * * updated ChangeLogs with all changes * * * reverted backend::close_figure to using __plot_stream__ moved OpenGL includes into gl-render.h removed check for FL/glu.h * * * configure.in: fix unquoted variable warn_graphics. * * * fixed fltk test in configure.in and also some minor style problems diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ +2008-06-04 Shai Ayal + + * configure.in: Remove check for Fl/glu.h header. + + * aclocal.m4 (AC_CHECK_FT2): New macro to check for freetype2. + + * configure.in: Check for FLTK and corresponding compiler flags. + 2008-06-04 Michael Goffioul + * configure.in: Double-quote warn_graphics variable. + * aclocal.m4 (OCTAVE_OPENGL): New function to detect OpenGL headers and libraries. * configure.in (OCTAVE_OPENGL): Use it. diff --git a/aclocal.m4 b/aclocal.m4 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1102,3 +1102,195 @@ fi AC_SUBST(OPENGL_LIBS) ]) +dnl +dnl Configure paths for FreeType2 +dnl Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor +dnl +dnl Copyright 2001, 2003 by +dnl David Turner, Robert Wilhelm, and Werner Lemberg. +dnl +dnl This file is part of the FreeType project, and may only be used, modified, +dnl and distributed under the terms of the FreeType project license, +dnl LICENSE.TXT. By continuing to use, modify, or distribute this file you +dnl indicate that you have read the license and understand and accept it +dnl fully. +dnl +dnl As a special exception to the FreeType project license, this file may be +dnl distributed as part of a program that contains a configuration script +dnl generated by Autoconf, under the same distribution terms as the rest of +dnl that program. +dnl +dnl serial 2 +dnl +dnl AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS. +dnl MINIMUM-VERSION is what libtool reports; the default is `7.0.1' (this is +dnl FreeType 2.0.4). +dnl +AC_DEFUN([AC_CHECK_FT2], + [dnl Get the cflags and libraries from the freetype-config script + dnl + AC_ARG_WITH([ft-prefix], + dnl don't quote AS_HELP_STRING! + AS_HELP_STRING([--with-ft-prefix=PREFIX], + [Prefix where FreeType is installed (optional)]), + [ft_config_prefix="$withval"], + [ft_config_prefix=""]) + + AC_ARG_WITH([ft-exec-prefix], + dnl don't quote AS_HELP_STRING! + AS_HELP_STRING([--with-ft-exec-prefix=PREFIX], + [Exec prefix where FreeType is installed (optional)]), + [ft_config_exec_prefix="$withval"], + [ft_config_exec_prefix=""]) + + AC_ARG_ENABLE([freetypetest], + dnl don't quote AS_HELP_STRING! + AS_HELP_STRING([--disable-freetypetest], + [Do not try to compile and run a test FreeType program]), + [], + [enable_fttest=yes]) + + if test x$ft_config_exec_prefix != x ; then + ft_config_args="$ft_config_args --exec-prefix=$ft_config_exec_prefix" + if test x${FT2_CONFIG+set} != xset ; then + FT2_CONFIG=$ft_config_exec_prefix/bin/freetype-config + fi + fi + + if test x$ft_config_prefix != x ; then + ft_config_args="$ft_config_args --prefix=$ft_config_prefix" + if test x${FT2_CONFIG+set} != xset ; then + FT2_CONFIG=$ft_config_prefix/bin/freetype-config + fi + fi + + AC_PATH_PROG([FT2_CONFIG], [freetype-config], [no]) + + min_ft_version=m4_if([$1], [], [7.0.1], [$1]) + AC_MSG_CHECKING([for FreeType -- version >= $min_ft_version]) + no_ft="" + if test "$FT2_CONFIG" = "no" ; then + no_ft=yes + else + FT2_CFLAGS=`$FT2_CONFIG $ft_config_args --cflags` + FT2_LIBS=`$FT2_CONFIG $ft_config_args --libs` + ft_config_major_version=`$FT2_CONFIG $ft_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + ft_config_minor_version=`$FT2_CONFIG $ft_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + ft_config_micro_version=`$FT2_CONFIG $ft_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + ft_min_major_version=`echo $min_ft_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + ft_min_minor_version=`echo $min_ft_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + ft_min_micro_version=`echo $min_ft_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test x$enable_fttest = xyes ; then + ft_config_is_lt="" + if test $ft_config_major_version -lt $ft_min_major_version ; then + ft_config_is_lt=yes + else + if test $ft_config_major_version -eq $ft_min_major_version ; then + if test $ft_config_minor_version -lt $ft_min_minor_version ; then + ft_config_is_lt=yes + else + if test $ft_config_minor_version -eq $ft_min_minor_version ; then + if test $ft_config_micro_version -lt $ft_min_micro_version ; then + ft_config_is_lt=yes + fi + fi + fi + fi + fi + if test x$ft_config_is_lt = xyes ; then + no_ft=yes + else + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $FT2_CFLAGS" + LIBS="$FT2_LIBS $LIBS" + + dnl + dnl Sanity checks for the results of freetype-config to some extent. + dnl + AC_RUN_IFELSE([ + AC_LANG_SOURCE([[ + +#include +#include FT_FREETYPE_H +#include +#include + +int +main() +{ + FT_Library library; + FT_Error error; + + error = FT_Init_FreeType(&library); + + if (error) + return 1; + else + { + FT_Done_FreeType(library); + return 0; + } +} + + ]]) + ], + [], + [no_ft=yes], + [echo $ECHO_N "cross compiling; assuming OK... $ECHO_C"]) + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi dnl test $ft_config_version -lt $ft_min_version + fi dnl test x$enable_fttest = xyes + fi dnl test "$FT2_CONFIG" = "no" + + if test x$no_ft = x ; then + AC_MSG_RESULT([yes]) + m4_if([$2], [], [:], [$2]) + else + AC_MSG_RESULT([no]) + if test "$FT2_CONFIG" = "no" ; then + AC_MSG_WARN([ + + The freetype-config script installed by FreeType 2 could not be found. + If FreeType 2 was installed in PREFIX, make sure PREFIX/bin is in + your path, or set the FT2_CONFIG environment variable to the + full path to freetype-config. + ]) + else + if test x$ft_config_is_lt = xyes ; then + AC_MSG_WARN([ + + Your installed version of the FreeType 2 library is too old. + If you have different versions of FreeType 2, make sure that + correct values for --with-ft-prefix or --with-ft-exec-prefix + are used, or set the FT2_CONFIG environment variable to the + full path to freetype-config. + ]) + else + AC_MSG_WARN([ + + The FreeType test program failed to run. If your system uses + shared libraries and they are installed outside the normal + system library path, make sure the variable LD_LIBRARY_PATH + (or whatever is appropiate for your system) is correctly set. + ]) + fi + fi + + FT2_CFLAGS="" + FT2_LIBS="" + m4_if([$3], [], [:], [$3]) + fi + + AC_SUBST([FT2_CFLAGS]) + AC_SUBST([FT2_LIBS])]) +dnl end of freetype2.m4 diff --git a/configure.in b/configure.in --- a/configure.in +++ b/configure.in @@ -636,6 +636,79 @@ fi +# --------------------------------------------------------------------- + +## libraries needed for graphics + +GRAPHICS_OPENGL= +OCTAVE_OPENGL +if test "x$OPENGL_LIBS" != "x"; then + GRAPHICS_OPENGL="opengl" +fi + + +GRAPHICS_LIBS= +GRAPHICS_CFLAGS= + +## fltk (www.fltk.org) +AC_ARG_WITH(fltk-prefix, + [ --with-fltk-prefix=PFX Prefix where FLTK is installed (optional)], + fltk_prefix="$withval", + fltk_prefix="") +AC_ARG_WITH(fltk-exec-prefix, + [ --with-fltk-exec-prefix=PFX Exec prefix where FLTK is installed (optional)], + fltk_exec_prefix="$withval", + fltk_exec_prefix="") + +if test "x$fltk_exec_prefix" != x ; then + fltk_args="$fltk_args --exec-prefix=$fltk_exec_prefix" + if test "x${FLTK_CONFIG+set}" != xset ; then + FLTK_CONFIG="$fltk_exec_prefix/bin/fltk-config" + fi +fi + +if test "x$fltk_prefix" != x ; then + fltk_args="$fltk_args --prefix=$fltk_prefix" + if test x${FLTK_CONFIG+set} != xset ; then + FLTK_CONFIG="$fltk_prefix/bin/fltk-config" + fi +fi + +AC_PATH_PROG(FLTK_CONFIG, fltk-config, no) + +warn_graphics="" +if test "$FLTK_CONFIG" = "no" ; then + warn_graphics="fltk library (www.fltk.org) not found. Native graphics will be disabled." +else + FLTK_CFLAGS="`$FLTK_CONFIG $fltkconf_args --use-gl --cflags`" + FLTK_LDFLAGS="`$FLTK_CONFIG $fltkconf_args --use-gl --ldflags`" + + AC_MSG_CHECKING(for OpenGL support in fltk) + cat > conftest.cc < + int nothing=0; +EOF + $CXX $CXXFLAGS $FLTK_CFLAGS -c conftest.cc || \ + warn_graphics="fltk does not have OpenGL support. Native graphics will be disabled." + + if test "x$warn_graphics" = "x" ; then + AC_MSG_RESULT(yes) + ## FTGL flags + AC_CHECK_FT2([9.0.3],[], + [warn_graphics="FreeType library not found. Native graphics will be disabled."]) + + GRAPHICS_CFLAGS="$FLTK_CFLAGS $FT2_CFLAGS" + GRAPHICS_LIBS="$FLTK_LDFLAGS $FT2_LIBS" + GRAPHICS_OPENGL="$GRAPHICS_OPENGL fltk_backend" + else + AC_MSG_RESULT(no) + fi +fi + +AC_SUBST(GRAPHICS_CFLAGS) +AC_SUBST(GRAPHICS_LIBS) +AC_SUBST(GRAPHICS_OPENGL) + OCTAVE_IEEE754_DATA_FORMAT # ---------------------------------------------------------------------- @@ -1613,15 +1686,6 @@ ;; esac -## Graphics related stuffs - -GRAPHICS_OPENGL= -OCTAVE_OPENGL -if test "x$OPENGL_LIBS" != "x"; then - GRAPHICS_OPENGL="opengl" -fi -AC_SUBST(GRAPHICS_OPENGL) - ### Checks for other programs used for building, testing, installing, ### and running Octave. @@ -1878,7 +1942,7 @@ libcruft/slatec-err/Makefile libcruft/villad/Makefile libcruft/blas-xtra/Makefile libcruft/lapack-xtra/Makefile src/graphics/Makefile src/graphics/Makerules - src/graphics/opengl/Makefile]) + src/graphics/opengl/Makefile src/graphics/fltk_backend/Makefile]) AC_OUTPUT AC_CONFIG_COMMANDS([default-1],[[chmod +x install-octave]],[[]]) @@ -1915,6 +1979,7 @@ CURL libraries: $CURL_LIBS REGEX libraries: $REGEX_LIBS QHULL libraries: $QHULL_LIBS + GRAPHICS libraries $GRAPHICS_LIBS LIBS: $LIBS Default pager: $DEFAULT_PAGER gnuplot: $GNUPLOT @@ -2117,6 +2182,17 @@ warn_msg_printed=true fi +if test -n "$warn_graphics"; then + AC_MSG_WARN($warn_graphics) + AC_MSG_WARN([]) + AC_MSG_WARN([I didn't find the necessary libraries to compile native]) + AC_MSG_WARN([graphics. It isn't necessary to have native graphics]) + AC_MSG_WARN([but you will have to use gnuplot or you won't be able]) + AC_MSG_WARN([to use any of Octave's plotting commands]) + AC_MSG_WARN([]) + warn_msg_printed=true +fi + if $warn_msg_printed; then AC_MSG_NOTICE([ diff --git a/src/graphics.h.in b/src/graphics.h.in --- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -1191,7 +1191,7 @@ virtual bool is_valid (void) const { return false; } - virtual void close_figure (const octave_value&) const + virtual void close_figure (const octave_value& pstream) const { gripe_invalid ("close_figure"); } virtual void redraw_figure (const graphics_handle&) const diff --git a/src/graphics/ChangeLog b/src/graphics/ChangeLog --- a/src/graphics/ChangeLog +++ b/src/graphics/ChangeLog @@ -1,3 +1,20 @@ +2008-02-21 Shai Ayal + + * opengl/gl-render.cc: remove OpenGL includes + * opengl/gl-render.h: add OpenGL includes + * fltk_backend/fltk_backend.cc: remove OpenGL includes + (__fltk_redraw__): put figure handle into the figure's + __plot_stream__ property for later + (fltk_backend::close_figure): use argument as figure handle to + close + +2008-02-20 Shai Ayal + + * fltk_backend/Makefile.in: initial import + + * fltk_backend/fltk_backend.cc: initial import + + 2008-02-20 Michael Goffioul * opengl/gl-render.h (opengl_renderer::draw(patch)): New method to diff --git a/src/graphics/fltk_backend/Makefile.in b/src/graphics/fltk_backend/Makefile.in new file mode 100644 --- /dev/null +++ b/src/graphics/fltk_backend/Makefile.in @@ -0,0 +1,70 @@ +# Makefile for octave's src/graphics/opengl directory +# +# Copyright (C) 1998, 2007 John W. Eaton +# +# This file is part of Octave. +# +# Octave 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 3 of the License, or (at +# your option) any later version. +# +# Octave 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 Octave; see the file COPYING. If not, see +# . + +TOPDIR = ../../.. +include $(TOPDIR)/Makeconf + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +GRAPHICS_LIBS = @GRAPHICS_LIBS@ + +FLTK_EXTRA_LIBS = $(OPENGL_LIBS) $(GRAPHICS_LIBS) +FLTK_EXTRA_CXXFLAGS = $(GRAPHICS_CFLAGS) -I../opengl + +FLTK_NAME = fltk_backend + +FLTK_SRC := fltk_backend.cc +FLTK_OBJ := $(patsubst %.cc, %.o, $(FLTK_SRC)) + +%.o : %.cc + $(CXX) -c $(CPPFLAGS) $(ALL_CXXFLAGS) $(FLTK_EXTRA_CXXFLAGS) $< -o $@ + +# Some stupid egreps don't like empty elements in alternation patterns, +# so we have to repeat ourselves because some stupid egreps don't like +# empty elements in alternation patterns. + +DEFUN_PATTERN = "^[ \t]*DEF(CONSTFUN|CMD|UN|UN_DLD|UNX_DLD|UN_TEXT|UN_MAPPER)[ \t]*\\(" + +DLD_DEF_FILES := $(patsubst %.cc, %.df, $(FLTK_SRC)) + +OCTAVE_LFLAGS = -L$(TOPDIR)/liboctave -L$(TOPDIR)/libcruft \ + -L$(TOPDIR)/src $(RLD_FLAG) + +ifeq ($(ENABLE_DYNAMIC_LINKING), true) + OCTAVE_LIBS = $(LIBOCTINTERP) $(LIBOCTAVE) \ + $(SPECIAL_MATH_LIB) $(LIBCRUFT) \ + $(LIBPLPLOT) $(LIBGLOB) +else + OCTAVE_LIBS = $(LIBOCTINTERP) $(LIBOCTAVE) $(QHULL_LIBS) \ + $(GLPK_LIBS) $(REGEX_LIBS) $(SPECIAL_MATH_LIB) $(LIBCRUFT) \ + $(LIBPLPLOT) $(LIBGLOB) +endif + +OCT_LINK_DEPS = \ + -L../../../libcruft $(LIBCRUFT) -L../../../liboctave $(LIBOCTAVE) \ + -L../../ $(LIBOCTINTERP) -L../opengl -loctgraphics_gl $(CHOLMOD_LIBS) $(UMFPACK_LIBS) $(AMD_LIBS) \ + $(CAMD_LIBS) $(COLAMD_LIBS) $(CCOLAMD_LIBS) $(CXSPARSE_LIBS) $(BLAS_LIBS) \ + $(FFTW_LIBS) $(LIBS) $(FLIBS) $(FLTK_EXTRA_LIBS) $(GRAPHICS_LIBS) + + +fltk_backend.oct : fltk_backend.o + $(DL_LD) $(DL_LDFLAGS) -o $@ $< $(OCT_LINK_DEPS) + diff --git a/src/graphics/fltk_backend/fltk_backend.cc b/src/graphics/fltk_backend/fltk_backend.cc new file mode 100644 --- /dev/null +++ b/src/graphics/fltk_backend/fltk_backend.cc @@ -0,0 +1,578 @@ +/* + +Copyright (C) 2007 Shai Ayal + +This file is part of Octave. + +Octave 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 3 of the License, or (at your +option) any later version. + +Octave 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 Octave; see the file COPYING. If not, see +. + +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "oct.h" +#include "parse.h" +#include "graphics.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gl-render.h" + + +const char* help_text = "\ +Keyboard Shortcuts\n\ +a - autoscale\n\ +g - toggle grid\n\ +\n\ +Mouse\n\ +left drag - zoom\n\ +right click - unzoom\n\ +double click - copy coordinates to clipboard\ +"; + +class OpenGL_fltk : public Fl_Gl_Window { +public: + OpenGL_fltk (int x, int y, int w, int h, double num) : + Fl_Gl_Window (x, y, w, h, 0), + number (num) + { + // ask for double buffering and a depth buffer + mode(FL_DEPTH | FL_DOUBLE ); + }; + ~OpenGL_fltk () {}; + +private: + double number; + opengl_renderer renderer; + + void setup_viewport (int _w, int _h) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport (0, 0, _w, _h); + // glOrtho (0.0, 1, 0.0, 1, -1.0, 1.0); + } + + void draw () { + if (!valid ()) { + valid (1); + setup_viewport (w (), h ()); + } + +#ifndef MESA + glDrawBuffer (GL_FRONT_AND_BACK); +#endif // !MESA + + renderer.draw (gh_manager::lookup (number)); + +#ifndef MESA + glDrawBuffer (GL_BACK); +#endif // !MESA + }; + + void resize (int _x,int _y,int _w,int _h) { + Fl_Gl_Window::resize (_x, _y, _w, _h); + setup_viewport (_w, _h); + redraw (); + }; + + int handle (int event) + { + int retval = Fl_Gl_Window::handle (event); + + switch (event) + { + case FL_ENTER: + window ()->cursor (FL_CURSOR_CROSS); + return 1; + + case FL_LEAVE: + window ()->cursor (FL_CURSOR_DEFAULT); + return 1; + } + + return retval; + }; + +}; + +class plot_window : public Fl_Window { +public: + plot_window (int _x, int _y, int _w, int _h, double num) : + Fl_Window (_x, _y, _w, _h, "octave"), + _number (num), + err_props (graphics_handle (), graphics_handle ()) + { + callback (window_close, static_cast (this)); + + begin(); + { + canvas = new + OpenGL_fltk (0, 0, _w , _h - status_h, num); + + autoscale = new + Fl_Button (0, + _h - status_h, + status_h, + status_h, + "A"); + autoscale->callback (button_callback, static_cast (this)); + + help = new + Fl_Button (status_h, + _h - status_h, + status_h, + status_h, + "H"); + help->callback (button_callback, static_cast (this)); + + status = new + Fl_Output (2*status_h, + _h - status_h, + _w > 2*status_h ? _w - status_h : 0, + status_h, ""); + + status->textcolor (FL_BLACK); + status->color (FL_GRAY); + status->textfont (FL_COURIER); + status->textsize (10); + status->box (FL_ENGRAVED_BOX); + + // This allows us to have a valid OpenGL context right away + canvas->mode (FL_DEPTH | FL_DOUBLE ); + show (); + canvas->show (); + canvas->make_current (); + } + end (); + + status->show (); + autoscale->show (); + + resizable (canvas); + size_range (4*status_h, 2*status_h); + + std::stringstream name; + name << "octave: figure " << number (); + label (name.str ().c_str ()); + } + + ~plot_window () { + canvas->hide(); + status->hide(); + this->hide(); + delete canvas; + delete status; + }; + + double number () { return _number;}; + + void mark_modified () { canvas->damage (FL_DAMAGE_ALL); } + +private: + // figure number + double _number; + figure::properties err_props; + + // status area height + static const int status_h = 20; + + // window callback + static void window_close (Fl_Widget* w, void* data) + { + octave_value_list args; + args(0) = static_cast (data)-> number (); + feval("close",args); + } + + // button callbacks + static void button_callback (Fl_Widget* w, void* data) { + static_cast (data)-> button_press (w); + }; + + void button_press (Fl_Widget* widg) { + if (widg == autoscale) std::cout << "AS " << number () << " pressed\n"; + if (widg == help) fl_message (help_text); + } + + OpenGL_fltk* canvas; + Fl_Button* autoscale; + Fl_Button* help; + Fl_Output* status; + + + figure::properties& get_figure_props () { + graphics_object obj = gh_manager::get_object (_number); + + if (obj && obj.isa ("figure")) + { + figure::properties& fprops = + dynamic_cast (obj.get_properties ()); + return fprops; + } + + error("OpenGL_fltk:: Internal error -- Not associated with figure!"); + return err_props; + }; + + void pixel2pos (int px, int py, double& x, double& y) const { + x = static_cast (px) / w (); + y = 1. - static_cast (py) / (h () - status_h); + } + + graphics_handle pixel2axes (int px, int py) { + + double x,y; + + pixel2pos (px, py, x, y); + + figure::properties pp = get_figure_props (); + Matrix children = (get_figure_props ()).get_children (); + for (octave_idx_type n = 0; n < children.numel (); n++) + { + graphics_object ax = gh_manager::get_object (children (n)); + if (ax) + { + if (ax.isa ("axes")) + { + axes::properties& props = + dynamic_cast (ax.get_properties ()); + Matrix pos = props.get_position (). matrix_value (); + + if (x >= pos(0) && x <= pos(0) + pos(2) + && + y >= pos(1) && y <= pos(1) + pos(3) ) + return props.get___myhandle__ (); + } + } + } + return graphics_handle (); + } + + void pixel2status (int px, int py) { + double x,y; + std::stringstream cbuf; + + pixel2pos (px, py, x, y); + cbuf << "[" << x << ", " << y <<"]"; + status->value (cbuf.str ().c_str ()); + status->redraw (); + } + + void resize (int _x,int _y,int _w,int _h) + { + Fl_Window::resize (_x, _y, _w, _h); + + Matrix pos (1,4,0); + pos(0) = _x; + pos(1) = _y; + pos(2) = _w; + pos(3) = _h; + + octave_value_list args; + args(0) = number (); + args(1) = "position"; + args(2) = pos; + feval("set",args); + } + + int handle (int event) { + static double x0,y0; + static graphics_handle h0 = graphics_handle (); + static bool in_drag = false; + + int retval = Fl_Window::handle (event); + + // we only handle events which are in the canvas area + if (Fl::event_y () >= h() - status_h) + return retval; + + switch (event) + { + + case FL_MOVE: + pixel2status (Fl::event_x (), Fl::event_y ()); + break; + + case FL_PUSH: + if (Fl::event_button () == 1) + { + pixel2pos (Fl::event_x (), Fl::event_y (), x0, y0); + h0 = pixel2axes (Fl::event_x (), Fl::event_y ()); + return 1; + } + break; + + case FL_DRAG: + pixel2status (Fl::event_x (), Fl::event_y ()); + if (Fl::event_button () == 1) + { + in_drag = true; + return 1; + } + break; + + case FL_RELEASE: + if (Fl::event_button () == 1) + { + // end of drag -- zoom + if (in_drag) + { + in_drag = false; + } + // one click -- select axes + else if ( Fl::event_clicks () == 0) + { + if (h0.ok ()) + get_figure_props ().set_currentaxes (h0. value()); + return 1; + } + } + break; + } + + return retval; + } + +}; + +class figure_manager { +public: + + static figure_manager& Instance () { + static figure_manager fm; + return fm; + } + + ~figure_manager () { + close_all (); + } + + void close_all () { + wm_iterator win; + for (win = windows.begin (); win != windows.end (); win++) + delete (*win).second; + windows.clear (); + } + + void new_window (double num) { + if (windows.find (num) != windows.end ()) + return; + + int x,y,w,h; + + default_size(x,y,w,h); + + windows[num] = new plot_window (x, y, w, h, num); + }; + + void delete_window (double num) { + wm_iterator win; + if ( (win=windows.find (num)) != windows.end ()) + { + delete (*win).second; + windows.erase (win); + } + }; + + void mark_modified (double num) { + wm_iterator win; + if ( (win=windows.find (num)) != windows.end ()) + { + (*win).second->mark_modified (); + } + }; + + Matrix get_size (double num) + { + Matrix sz (1, 2, 0.0); + + wm_iterator win; + if ( (win=windows.find (num)) != windows.end ()) + { + sz(0) = (*win).second->w (); + sz(1) = (*win).second->h (); + } + + return sz; + } + +private: + figure_manager () {}; + figure_manager (const figure_manager& ) {}; + figure_manager& operator = (const figure_manager&) {return *this;}; + // singelton -- hide all of the above + + + typedef std::map window_map; + typedef window_map::iterator wm_iterator;; + + window_map windows; + + void default_size (int& x, int& y, int& w, int& h) { + x = 10; + y = 10; + w = 400; + h = 300; + } + +}; + +#define FLTK_BACKEND_NAME "fltk" + +class fltk_backend : public base_graphics_backend +{ +public: + fltk_backend (void) + : base_graphics_backend (FLTK_BACKEND_NAME) { } + + ~fltk_backend (void) { } + + bool is_valid (void) const { return true; } + + void close_figure (const octave_value& fh) const + { + if (fh.is_real_scalar ()) + figure_manager::Instance ().delete_window (fh.double_value ()); + } + + void redraw_figure (const graphics_handle& fh) const + { + figure_manager::Instance ().mark_modified (fh.value ()); + } + + void print_figure (const graphics_handle& fh, const std::string& term, + const std::string& file, bool mono, + const std::string& debug_file) const + { + } + + Matrix get_canvas_size (const graphics_handle& fh) const + { + return figure_manager::Instance ().get_size (fh.value ()); + } + + double get_screen_resolution (void) const + { + // FLTK doesn't give this info + return 72.0; + } + + Matrix get_screen_size (void) const + { + Matrix sz (1, 2, 0.0); + sz(0) = Fl::w (); + sz(1) = Fl::h (); + return sz; + } +}; + +bool backend_registered = false; +// call this to init the fltk backend +DEFUN_DLD (__init_fltk__, args, nargout,"") +{ + graphics_backend::register_backend (new fltk_backend); + backend_registered = true; + + octave_value retval; + return retval; +} + +// call this to delete the fltk backend +DEFUN_DLD (__remove_fltk__, args, nargout,"") +{ + figure_manager::Instance ().close_all (); + graphics_backend::unregister_backend (FLTK_BACKEND_NAME); + backend_registered = false; + + + // give FLTK no more than 0.01 sec to do it's stuff + Fl::wait(1e-2); + octave_value retval; + return retval; +} + +// call this from the idle_callback to refresh windows +DEFUN_DLD (__fltk_redraw__, args, nargout,"internal function for the fltk backend") +{ + octave_value retval; + + if (!backend_registered) + return retval; + + // we scan all figures and add those which use FLTK as a backend + graphics_object obj = gh_manager::get_object (0); + if (obj && obj.isa ("root_figure")) + { + base_properties& props = obj.get_properties (); + Matrix children = props.get_children (); + + for (octave_idx_type n = 0; n < children.numel (); n++) + { + graphics_object fobj = gh_manager::get_object (children (n)); + if (fobj && fobj.isa ("figure")) + { + figure::properties& fp = + dynamic_cast (fobj.get_properties ()); + if (fp.get___backend__ () == FLTK_BACKEND_NAME) + { + figure_manager::Instance ().new_window (children (n)); + + // put figure handle in __plot_stream__ so we know + // which window to close. Only do this if necesarry + // since it modifies the figure and causes a redraw + octave_value ps = fp.get___plot_stream__ (); + if (ps.is_real_scalar ()) + if (ps.double_value () == fp.get___myhandle__ ().value ()) + continue; + + octave_value_list oargs; + oargs(0) = fp.get___myhandle__ ().value (); + oargs(1) = "__plot_stream__"; + oargs(2) = fp.get___myhandle__ ().value (); + feval ("set" , oargs); + } + } + } + } + + // give FLTK no more than 0.01 sec to do it's stuff + Fl::wait(1e-2); + + return retval; +} + +/* to init +autoload("__init_fltk__",[pwd(),"/fltk_backend.oct"]) +autoload("__remove_fltk__",[pwd(),"/fltk_backend.oct"]) +autoload("__fltk_redraw__",[pwd(),"/fltk_backend.oct"]) +input_event_hook ("__fltk_redraw__"); +__init_fltk__ (); +set(gcf(),"__backend__","fltk") + + +*/ diff --git a/src/graphics/opengl/gl-render.cc b/src/graphics/opengl/gl-render.cc --- a/src/graphics/opengl/gl-render.cc +++ b/src/graphics/opengl/gl-render.cc @@ -27,9 +27,6 @@ #include #include "gl-render.h" -#include -#include - #define LIGHT_MODE GL_FRONT_AND_BACK // Win32 API requires the CALLBACK attributes for diff --git a/src/graphics/opengl/gl-render.h b/src/graphics/opengl/gl-render.h --- a/src/graphics/opengl/gl-render.h +++ b/src/graphics/opengl/gl-render.h @@ -23,6 +23,9 @@ #if !defined (gl_render_h) #define gl_render_h 1 +#include +#include + #include "graphics.h" class