diff options
Diffstat (limited to 'src/Fl_Widget_Surface.cxx')
| -rw-r--r-- | src/Fl_Widget_Surface.cxx | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/Fl_Widget_Surface.cxx b/src/Fl_Widget_Surface.cxx new file mode 100644 index 000000000..f99a333fb --- /dev/null +++ b/src/Fl_Widget_Surface.cxx @@ -0,0 +1,210 @@ +// +// "$Id: Fl_Widget_Surface.cxx 11217 2016-02-25 17:56:48Z manolo $" +// +// Drivers code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2016 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Widget_Surface.H> +#include <FL/fl_draw.H> +#include <FL/Fl.H> +#include <FL/Fl_Shared_Image.H> + + +Fl_Widget_Surface::Fl_Widget_Surface(Fl_Graphics_Driver *d) : Fl_Surface_Device(d) { + x_offset = 0; + y_offset = 0; +} + +/** + @brief Draws the widget on the printed page. + * + The widget's position on the printed page is determined by the last call to origin() + and by the optional delta_x and delta_y arguments. + Its dimensions are in points unless there was a previous call to scale(). + @param[in] widget Any FLTK widget (e.g., standard, custom, window). + @param[in] delta_x Optional horizontal offset for positioning the widget relatively + to the current origin of graphics functions. + @param[in] delta_y Same as above, vertically. + */ +void Fl_Widget_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y) +{ + int old_x, old_y, new_x, new_y, is_window; + if ( ! widget->visible() ) return; + is_window = (widget->as_window() != NULL); + uchar old_damage = widget->damage(); + widget->damage(FL_DAMAGE_ALL); + // set origin to the desired top-left position of the widget + origin(&old_x, &old_y); + new_x = old_x + delta_x; + new_y = old_y + delta_y; + if (!is_window) { + new_x -= widget->x(); + new_y -= widget->y(); + } + if (new_x != old_x || new_y != old_y) { + translate(new_x - old_x, new_y - old_y ); + } + // if widget is a main window, clip all drawings to the window area + if (is_window && !widget->window()) { + fl_push_clip(0, 0, widget->w(), widget->h() ); +#ifdef __APPLE__ // for Mac OS X 10.6 and above, make window with rounded bottom corners + if ( fl_mac_os_version >= 100600 && driver()->has_feature(Fl_Graphics_Driver::NATIVE) ) { + Fl_X::clip_to_rounded_corners((CGContextRef)driver()->gc(), widget->w(), widget->h()); + } +#endif + } + // 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(widget, 0, 0, 0); + } + } + if (!drawn_by_plugin) { + widget->draw(); + } + if (is_window && !widget->window()) fl_pop_clip(); + // find subwindows of widget and print them + traverse(widget); + // reset origin to where it was + if (new_x != old_x || new_y != old_y) { + untranslate(); + } + if ((old_damage & FL_DAMAGE_CHILD) == 0) widget->clear_damage(old_damage); + else widget->damage(FL_DAMAGE_ALL); +} + + +void Fl_Widget_Surface::traverse(Fl_Widget *widget) +{ + Fl_Group *g = widget->as_group(); + if (!g) return; + int n = g->children(); + for (int i = 0; i < n; i++) { + Fl_Widget *c = g->child(i); + if ( !c->visible() ) continue; + if ( c->as_window() ) { + draw(c, c->x(), c->y()); + } + else traverse(c); + } +} + +/** + @brief Computes the page coordinates of the current origin of graphics functions. + * + @param[out] x If non-null, *x is set to the horizontal page offset of graphics origin. + @param[out] y Same as above, vertically. + */ +void Fl_Widget_Surface::origin(int *x, int *y) +{ + if (x) *x = x_offset; + if (y) *y = y_offset; +} + +/** + @brief Sets the position in page coordinates of the origin of graphics functions. + + Arguments should be expressed relatively to the result of a previous printable_rect() call. + That is, <tt>printable_rect(&w, &h); origin(w/2, 0);</tt> sets the graphics origin at the + top center of the page printable area. + Origin() calls are not affected by rotate() calls. + Successive origin() calls don't combine their effects. + @param[in] x Horizontal position in page coordinates of the desired origin of graphics functions. + @param[in] y Same as above, vertically. + */ +void Fl_Widget_Surface::origin(int x, int y) {} + +/** + @brief Prints a rectangular part of an on-screen window. + + @param win The window from where to capture. + @param x The rectangle left + @param y The rectangle top + @param w The rectangle width + @param h The rectangle height + @param delta_x Optional horizontal offset from current graphics origin where to print the captured rectangle. + @param delta_y As above, vertically. + */ +void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y) +{ + Fl_Surface_Device *current = Fl_Surface_Device::surface(); + Fl_Display_Device::display_device()->set_current(); + Fl_Window *save_front = Fl::first_window(); + win->show(); + Fl::check(); + win->make_current(); + uchar *image_data; + image_data = fl_read_image(NULL, x, y, w, h); +#ifdef __APPLE__ // PORTME: Fl_Surface_Driver - platform paged device + Fl_X::q_release_context(); // matches make_current() call above +#endif + if (save_front != win) save_front->show(); + current->set_current(); + fl_draw_image(image_data, delta_x, delta_y, w, h, 3); + delete[] image_data; +#ifdef WIN32 + HDC gc = GetDC(fl_xid(win)); + fl_graphics_driver->gc(gc); + ReleaseDC(fl_xid(win), gc); +#endif +} + +/** + @brief Computes the width and height of the printable area of the page. + + Values are in the same unit as that used by FLTK drawing functions, + are unchanged by calls to origin(), but are changed by scale() calls. + Values account for the user-selected paper type and print orientation. + @return 0 if OK, non-zero if any error + */ +int Fl_Widget_Surface::printable_rect(int *w, int *h) {return 1;} + +/** Draws a window with its title bar and frame if any. + + \p x_offset and \p y_offset are optional coordinates of where to position the window top left. + Equivalent to draw() if \p win is a subwindow or has no border. + Use Fl_Window::decorated_w() and Fl_Window::decorated_h() to get the size of the window. + */ +void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset) +{ + Fl_Shared_Image *top, *left, *bottom, *right; + win->capture_titlebar_and_borders(top, left, bottom, right); + int wsides = left ? left->w() : 0; + int toph = top ? top->h() : 0; + if (top) { + top->draw(x_offset, y_offset); + top->release(); + } + if (left) { + left->draw(x_offset, y_offset + toph); + left->release(); + } + if (right) { + right->draw(x_offset + wsides + win->w(), y_offset + toph); + right->release(); + } + if (bottom) { + bottom->draw(x_offset, y_offset + toph + win->h()); + bottom->release(); + } + this->draw(win, x_offset + wsides, y_offset + toph); +} + +// +// End of "$Id: Fl_Widget_Surface.cxx 11217 2016-02-25 17:56:48Z manolo $". +// |
