diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H index bf611e1d8..31d27c92f 100644 --- a/FL/Fl_Device.H +++ b/FL/Fl_Device.H @@ -7,6 +7,7 @@ #define Fl_Device_H #include +#include #ifdef WIN32 #include #elif defined(__APPLE__) @@ -19,6 +20,7 @@ class Fl_RGB_Image; class Fl_Pixmap; class Fl_Bitmap; class Fl_Display; +class Fl_Virtual_Printer; extern Fl_Display *fl_display_device; typedef void (*Fl_Draw_Image_Cb)(void* ,int,int,int,uchar*); @@ -200,4 +202,18 @@ public: }; #endif +/* + This plugin socket allows the integration of new device drivers for special + window or screen types. It is currently used to provide an automated printing + service for OpenGL windows, if linked with fltk_gl. + */ +class Fl_Device_Plugin : public Fl_Plugin { +public: + Fl_Device_Plugin(const char *name) + : Fl_Plugin(klass(), name) { } + virtual const char *klass() { return "fltk:device"; } + virtual const char *name() = 0; + virtual int print(Fl_Virtual_Printer*, Fl_Widget*, int x, int y) { return 0; } +}; + #endif // Fl_Device_H diff --git a/FL/Fl_Gl_Window.H b/FL/Fl_Gl_Window.H index dac0a096f..9842aed41 100644 --- a/FL/Fl_Gl_Window.H +++ b/FL/Fl_Gl_Window.H @@ -205,6 +205,13 @@ public: */ void make_overlay_current(); + /** Returns an Fl_Gl_Window pointer if this widget is an Fl_Gl_Window. + \retval NULL if this widget is not derived from Fl_Gl_Window. + \note This method is provided to avoid dynamic_cast. + \todo More documentation ... + */ + virtual Fl_Gl_Window* as_gl_window() {return this;} + ~Fl_Gl_Window(); /** Creates a new Fl_Gl_Window widget using the given size, and label string. diff --git a/FL/Fl_Group.H b/FL/Fl_Group.H index 7e1630d0b..cde3e8cb2 100644 --- a/FL/Fl_Group.H +++ b/FL/Fl_Group.H @@ -182,7 +182,7 @@ public: \note This method is provided to avoid dynamic_cast. \todo More documentation ... */ - virtual Fl_Group* as_group() const { return (Fl_Group*)this; } + virtual Fl_Group* as_group() { return this; } // back compatibility functions: diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H index 95351f9f2..a3a2d6ad6 100644 --- a/FL/Fl_Widget.H +++ b/FL/Fl_Widget.H @@ -930,16 +930,23 @@ public: \note This method is provided to avoid dynamic_cast. \todo More documentation ... */ - virtual Fl_Group* as_group() const {return 0;} + virtual Fl_Group* as_group() {return 0;} /** Returns an Fl_Window pointer if this widget is an Fl_Window. - - \retval NULL if this widget is not derived from Fl_Window. - \note This method is provided to avoid dynamic_cast. - \todo More documentation ... + + \retval NULL if this widget is not derived from Fl_Window. + \note This method is provided to avoid dynamic_cast. + \todo More documentation ... */ - virtual Fl_Window* as_window() const {return 0;} - + virtual Fl_Window* as_window() {return 0;} + + /** Returns an Fl_Gl_Window pointer if this widget is an Fl_Gl_Window. + \retval NULL if this widget is not derived from Fl_Gl_Window. + \note This method is provided to avoid dynamic_cast. + \todo More documentation ... + */ + virtual class Fl_Gl_Window* as_gl_window() {return 0;} + /** For back compatibility only. \deprecated Use selection_color() instead. */ diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H index b2430e958..c9dd1af08 100644 --- a/FL/Fl_Window.H +++ b/FL/Fl_Window.H @@ -421,7 +421,7 @@ public: \note This method is provided to avoid dynamic_cast. \todo More documentation ... */ - virtual Fl_Window* as_window() const { return (Fl_Window*)this; } + virtual Fl_Window* as_window() { return this; } // for back-compatibility only: /** diff --git a/src/Fl_Device.cxx b/src/Fl_Device.cxx index 03e8367ac..642ddd22b 100644 --- a/src/Fl_Device.cxx +++ b/src/Fl_Device.cxx @@ -52,7 +52,16 @@ void Fl_Virtual_Printer::print_widget(Fl_Widget* widget, int delta_x, int delta_ #else _XGC *save_gc = fl_gc; // FIXME #endif - widget->draw(); + // we do some trickery to recognize OpenGL windows and draw them via a plugin + int drawn_by_plugin = 0; + if (widget->as_gl_window()) { + Fl_Plugin_Manager pm("fltk:device"); + Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org"); + if (pi) drawn_by_plugin = pi->print(this, widget, 0, 0); + } + if (!drawn_by_plugin) + widget->draw(); + fl_gc = save_gc; if (is_window) fl_pop_clip(); // find subwindows of widget and print them diff --git a/src/Fl_Gl_Printer.cxx b/src/Fl_Gl_Printer.cxx index 233327913..ac1892dde 100644 --- a/src/Fl_Gl_Printer.cxx +++ b/src/Fl_Gl_Printer.cxx @@ -89,3 +89,25 @@ void Fl_Gl_Printer::print_gl_window(Fl_Gl_Window *glw, int x, int y) free(baseAddress); #endif // __APPLE__ } + +/* + This class will make sure that OpenGL printing is availbale if fltk_gl + was linked to the programm. + */ +class Fl_Gl_Device_Plugin : public Fl_Device_Plugin { +public: + Fl_Gl_Device_Plugin() : Fl_Device_Plugin(name()) { } + virtual const char *name() { return "opengl.device.fltk.org"; } + virtual int print(Fl_Virtual_Printer *p, Fl_Widget *w, int x, int y) { + Fl_Gl_Window *glw = w->as_gl_window(); + if (!glw) return 0; + // FIXME: this is a dangerous cast! Remove Fl_Gl_Printer entirely and add + // FIXME: a static function (may be a friend of Fl_Printer). + Fl_Gl_Printer *glp = (Fl_Gl_Printer*)p; + glp->print_gl_window(glw, x, y); + return 1; + } +}; + +static Fl_Gl_Device_Plugin Gl_Device_Plugin; + diff --git a/test/cube.cxx b/test/cube.cxx index 42d998477..e726b0e8f 100644 --- a/test/cube.cxx +++ b/test/cube.cxx @@ -168,7 +168,7 @@ void print_cb(Fl_Widget *w, void *data) if(!win) return; if( printer.start_job(1) ) return; if( printer.start_page() ) return; - printer.scale(0.68,0.68); + printer.scale(0.5,0.5); printer.print_widget( win ); printer.print_gl_window( cube, cube->x(), cube->y() ); printer.print_gl_window( cube2, cube2->x(), cube2->y() );