diff options
| author | Manolo Gouy <Manolo> | 2011-04-15 21:38:05 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2011-04-15 21:38:05 +0000 |
| commit | 9ff9cf123046b64be860a48438566ed6a9f5c541 (patch) | |
| tree | e5d0ddae9a4d580082fba1c0f98190dc50595e4d | |
| parent | c473215f2a1ac2659e92973ff9ecaf1579ffc313 (diff) | |
Added Fl_Paged_Device::print_window() to print a window with its title bar and frame.
Added Fl_Window::decorated_w() and Fl_Window::decorated_h() that return the size
of a window with its title bar and frame.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@8593 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Paged_Device.H | 8 | ||||
| -rw-r--r-- | FL/Fl_Window.H | 12 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 89 | ||||
| -rw-r--r-- | src/Fl_win32.cxx | 65 | ||||
| -rw-r--r-- | src/Fl_x.cxx | 77 | ||||
| -rw-r--r-- | src/fl_read_image.cxx | 8 | ||||
| -rw-r--r-- | src/fl_read_image_win32.cxx | 23 |
7 files changed, 230 insertions, 52 deletions
diff --git a/FL/Fl_Paged_Device.H b/FL/Fl_Paged_Device.H index bdc448925..5ef4a1137 100644 --- a/FL/Fl_Paged_Device.H +++ b/FL/Fl_Paged_Device.H @@ -132,6 +132,14 @@ public: virtual void translate(int x, int y); virtual void untranslate(void); virtual void print_widget(Fl_Widget* widget, int delta_x = 0, int delta_y = 0); + /** Prints 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 print_widget() 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 + printed window. + */ + void print_window(Fl_Window *win, int x_offset = 0, int y_offset = 0); virtual void print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x = 0, int delta_y = 0); virtual int end_page (void); virtual void end_job (void); diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H index 1390f173e..ab7f43e16 100644 --- a/FL/Fl_Window.H +++ b/FL/Fl_Window.H @@ -443,6 +443,18 @@ public: void cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); // platform dependent void default_cursor(Fl_Cursor, Fl_Color=FL_BLACK, Fl_Color=FL_WHITE); static void default_callback(Fl_Window*, void* v); + + /** Returns the window width including any frame added by the window manager. + + Same as w() if applied to a subwindow. + */ + int decorated_w(); + /** Returns the window height including any window title bar and any frame + added by the window manager. + + Same as h() if applied to a subwindow. + */ + int decorated_h(); }; diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index eac031a28..0951e1c06 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -1417,12 +1417,20 @@ void fl_close_display() { // Gets the border sizes and the titlebar size static void get_window_frame_sizes(int &bx, int &by, int &bt) { - if (NSApp == nil) fl_open_display(); - NSRect inside = { {20,20}, {100,100} }; - NSRect outside = [NSWindow frameRectForContentRect:inside styleMask:NSTitledWindowMask]; - bx = int(outside.origin.x - inside.origin.x); - by = int(outside.origin.y - inside.origin.y); - bt = int(outside.size.height - inside.size.height - by); + static bool first = true; + static int top, left, bottom; + if (first) { + first = false; + if (NSApp == nil) fl_open_display(); + NSRect inside = { {20,20}, {100,100} }; + NSRect outside = [NSWindow frameRectForContentRect:inside styleMask:NSTitledWindowMask]; + left = int(outside.origin.x - inside.origin.x); + bottom = int(outside.origin.y - inside.origin.y); + top = int(outside.size.height - inside.size.height) - bottom; + } + bx = left; + by = bottom; + bt = top; } /* @@ -2861,7 +2869,7 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[]) { Fl_Printer printer; //Fl_PostScript_File_Device printer; - int w, h, wh; + int w, h, ww, wh; Fl_Window *win = Fl::first_window(); if(!win) return; if( printer.start_job(1) ) return; @@ -2869,13 +2877,9 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[]) // scale the printer device so that the window fits on the page float scale = 1; printer.printable_rect(&w, &h); - wh = win->h(); - int bx, by, bt = 0; - if (win->border()) { - get_window_frame_sizes(bx, by, bt); - wh += bt; - } - if (win->w()>w || wh>h) { + ww = win->decorated_w(); + wh = win->decorated_h(); + if (ww>w || wh>h) { scale = (float)w/win->w(); if ((float)h/wh < scale) scale = (float)h/wh; printer.scale(scale); @@ -2888,22 +2892,7 @@ int Fl_X::screen_init(XRectangle screens[], float dpi[]) printer.rotate(20.); printer.print_widget( win, - win->w()/2, - win->h()/2 ); #else - if (bt) { // print the window title bar - //printer.print_window_part(win, 0, -bt, win->w(), bt, 0, 1); - Fl_Display_Device::display_device()->set_current(); - win->show(); - fl_gc = NULL; - Fl::check(); - win->make_current(); - CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt); - printer.set_current(); - CGRect rect = { { 0, 1 }, { win->w(), bt } }; - Fl_X::q_begin_image(rect, 0, 0, win->w(), bt); - CGContextDrawImage(fl_gc, rect, img); - Fl_X::q_end_image(); - CGImageRelease(img); - } - printer.print_widget(win, 0, bt); + printer.print_window(win); #endif printer.end_page(); printer.end_job(); @@ -3401,6 +3390,46 @@ Window fl_xid(const Fl_Window* w) return Fl_X::i(w)->xid; } +int Fl_Window::decorated_w() +{ + if (this->parent() || !border()) return w(); + int bx, by, bt; + get_window_frame_sizes(bx, by, bt); + return w() + 2 * bx; +} + +int Fl_Window::decorated_h() +{ + if (this->parent() || !border()) return h(); + int bx, by, bt; + get_window_frame_sizes(bx, by, bt); + return h() + bt + by; +} + +void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset) +{ + if (win->parent() || !win->border()) { + this->print_widget(win, x_offset, y_offset); + return; + } + int bx, by, bt; + get_window_frame_sizes(bx, by, bt); + Fl_Display_Device::display_device()->set_current(); // send win to front and make it current + win->show(); + fl_gc = NULL; + Fl::check(); + win->make_current(); + // capture the window title bar from screen + CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt); + this->set_current(); // back to the Fl_Paged_Device + CGRect rect = { { 0, 1 }, { win->w(), bt } }; // print the title bar + Fl_X::q_begin_image(rect, 0, 0, win->w(), bt); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CGImageRelease(img); + this->print_widget(win, x_offset, y_offset + bt); // print the window inner part +} + #include <dlfcn.h> /* Returns the address of a Carbon function after dynamically loading the Carbon library if needed. diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 7ded352ef..20b9a2b00 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -38,6 +38,7 @@ #include <FL/fl_draw.H> #include <FL/Enumerations.H> #include <FL/Fl_Tooltip.H> +#include <FL/Fl_Paged_Device.H> #include "flstring.h" #include "Fl_Font.H" #include <stdio.h> @@ -1945,6 +1946,56 @@ Window fl_xid_(const Fl_Window *w) { return temp ? temp->xid : 0; } +int Fl_Window::decorated_w() +{ + if (parent() || !shown()) return w(); + int X, Y, bt, bx, by; + Fl_X::fake_X_wm(this, X, Y, bt, bx, by); + return w() + 2 * bx; +} + +int Fl_Window::decorated_h() +{ + if (this->parent() || !shown()) return h(); + int X, Y, bt, bx, by; + Fl_X::fake_X_wm(this, X, Y, bt, bx, by); + return h() + bt + 2 * by; +} + +void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset) +{ + if (win->parent() || !win->border()) { + this->print_widget(win, x_offset, y_offset); + return; + } + int X, Y, bt, bx, by, ww, wh; // compute the window border sizes + Fl_X::fake_X_wm(win, X, Y, bt, bx, by); + ww = win->w() + 2 * bx; + wh = win->h() + bt + 2 * by; + Fl_Display_Device::display_device()->set_current(); // make window current + win->show(); + Fl::check(); + win->make_current(); + // capture the 4 window sides from screen + // use negative 4th argument to allow negative 2nd or 3rd arguments + uchar *top_image = fl_read_image(NULL, -bx, - bt - by, -ww, bt + by); + uchar *left_image = fl_read_image(NULL, -bx, - bt - by, -bx, wh); + uchar *right_image = fl_read_image(NULL, win->w(), - bt - by, -bx, wh); + uchar *bottom_image = fl_read_image(NULL, -bx, win->h(), -ww, by); + this->set_current(); + // print the 4 window sides + fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3); + fl_draw_image(left_image, x_offset, y_offset, bx, wh, 3); + fl_draw_image(right_image, x_offset + win->w() + bx, y_offset, bx, wh, 3); + fl_draw_image(bottom_image, x_offset, y_offset + win->h() + bt + by, ww, by, 3); + delete[] top_image; + delete[] left_image; + delete[] right_image; + delete[] bottom_image; + // print the window inner part + this->print_widget(win, x_offset + bx, y_offset + bt + by); +} + #ifdef USE_PRINT_BUTTON // to test the Fl_Printer class creating a "Print front window" button in a separate window // contains also preparePrintFront call above @@ -1960,11 +2011,14 @@ void printFront(Fl_Widget *o, void *data) if( printer.start_job(1) ) { o->window()->show(); return; } if( printer.start_page() ) { o->window()->show(); return; } printer.printable_rect(&w,&h); + int wh, ww; + wh = win->decorated_h(); + ww = win->decorated_w(); // scale the printer device so that the window fits on the page float scale = 1; - if (win->w() > w || win->h() > h) { - scale = (float)w/win->w(); - if ((float)h/win->h() < scale) scale = (float)h/win->h(); + if (ww > w || wh > h) { + scale = (float)w/ww; + if ((float)h/wh < scale) scale = (float)h/wh; printer.scale(scale, scale); } // #define ROTATE 20.0 @@ -1975,9 +2029,8 @@ void printFront(Fl_Widget *o, void *data) printer.rotate(ROTATE); printer.print_widget( win, - win->w()/2, - win->h()/2 ); //printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 ); -#else - printer.print_widget( win ); - //printer.print_window_part( win, 0,0, win->w(), win->h() ); +#else + printer.print_window(win); #endif printer.end_page(); printer.end_job(); diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 282c10b60..45e4aa18f 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -42,6 +42,7 @@ # include <FL/fl_utf8.h> # include <FL/Fl_Tooltip.H> # include <FL/fl_draw.H> +# include <FL/Fl_Paged_Device.H> # include <stdio.h> # include <stdlib.h> # include "flstring.h" @@ -1890,6 +1891,69 @@ Window fl_xid_(const Fl_Window* w) return Fl_X::i(w)->xid; } + +int Fl_Window::decorated_h() +{ + if (parent() || !shown()) return h(); + Window root, parent, *children; + unsigned n; + XQueryTree(fl_display, i->xid, &root, &parent, &children, &n); if (n) XFree(children); + XWindowAttributes attributes; + XGetWindowAttributes(fl_display, parent, &attributes); + return attributes.height; +} + +int Fl_Window::decorated_w() +{ + if (parent() || !shown()) return w(); + Window root, parent, *children; + unsigned n; + XQueryTree(fl_display, i->xid, &root, &parent, &children, &n); if (n) XFree(children); + XWindowAttributes attributes; + XGetWindowAttributes(fl_display, parent, &attributes); + return attributes.width; +} + +void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset) +{ + if (win->parent() || !win->border()) { + this->print_widget(win, x_offset, y_offset); + return; + } + Fl_Display_Device::display_device()->set_current(); + win->show(); + Fl::check(); + win->make_current(); + Window root, parent, *children, child_win, from; + unsigned n; + int bx, bt; + from = fl_window; + XQueryTree(fl_display, fl_window, &root, &parent, &children, &n); if (n) XFree(children); + XTranslateCoordinates(fl_display, fl_window, parent, 0, 0, &bx, &bt, &child_win); + fl_window = parent; + uchar *top_image, *left_image, *right_image, *bottom_image; + top_image = fl_read_image(NULL, 0, 0, - (win->w() + 2 * bx), bt); + if (bx) { + left_image = fl_read_image(NULL, 0, bt, -bx, win->h() + bx); + right_image = fl_read_image(NULL, win->w() + bx, bt, -bx, win->h() + bx); + bottom_image = fl_read_image(NULL, 0, bt + win->h(), -(win->w() + 2*bx), bx); + } + fl_window = from; + this->set_current(); + fl_draw_image(top_image, x_offset, y_offset, win->w() + 2 * bx, bt, 3); + delete[] top_image; + if (bx) { + if (left_image) fl_draw_image(left_image, x_offset, y_offset + bt, bx, win->h() + bx, 3); + if (right_image) fl_draw_image(right_image, x_offset + win->w() + bx, y_offset + bt, bx, win->h() + bx, 3); + if (bottom_image) fl_draw_image(bottom_image, x_offset, y_offset + bt + win->h(), win->w() + 2*bx, bx, 3); + if (left_image) delete[] left_image; + if (right_image) delete[] right_image; + if (bottom_image) delete[] bottom_image; + } + this->print_widget( win, x_offset + bx, y_offset + bt ); +} + + #ifdef USE_PRINT_BUTTON // to test the Fl_Printer class creating a "Print front window" button in a separate window // contains also preparePrintFront call above @@ -1907,9 +1971,11 @@ void printFront(Fl_Widget *o, void *data) printer.printable_rect(&w,&h); // scale the printer device so that the window fits on the page float scale = 1; - if (win->w() > w || win->h() > h) { - scale = (float)w/win->w(); - if ((float)h/win->h() < scale) scale = (float)h/win->h(); + int ww = win->decorated_w(); + int wh = win->decorated_h(); + if (ww > w || wh > h) { + scale = (float)w/ww; + if ((float)h/wh < scale) scale = (float)h/wh; printer.scale(scale, scale); } @@ -1921,9 +1987,8 @@ void printFront(Fl_Widget *o, void *data) printer.rotate(ROTATE); printer.print_widget( win, - win->w()/2, - win->h()/2 ); //printer.print_window_part( win, 0,0, win->w(), win->h(), - win->w()/2, - win->h()/2 ); -#else - printer.print_widget( win ); - //printer.print_window_part( win, 0,0,win->w(), win->h() ); +#else + printer.print_window(win); #endif printer.end_page(); diff --git a/src/fl_read_image.cxx b/src/fl_read_image.cxx index 9475e2ec9..9597005e1 100644 --- a/src/fl_read_image.cxx +++ b/src/fl_read_image.cxx @@ -92,6 +92,7 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate int X, // I - Left position int Y, // I - Top position int w, // I - Width of area to read + // negative allows capture of window title bar and frame int h, // I - Height of area to read int alpha) { // I - Alpha value for image (0 for none) XImage *image; // Captured image @@ -118,6 +119,8 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate // ReadDisplay extension which does all of the really hard work for // us... // + int allow_outside = w < 0; // negative w allows negative X or Y, that is, window frame + if (w < 0) w = - w; # ifdef __sgi if (XReadDisplayQueryExtension(fl_display, &i, &i)) { @@ -131,7 +134,10 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate // fetch absolute coordinates int dx, dy, sx, sy, sw, sh; Window child_win; - Fl_Window *win = fl_find(fl_window); + + Fl_Window *win; + if (allow_outside) win = (Fl_Window*)1; + else win = fl_find(fl_window); if (win) { XTranslateCoordinates(fl_display, fl_window, RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win); diff --git a/src/fl_read_image_win32.cxx b/src/fl_read_image_win32.cxx index eb881d4a8..875b945a9 100644 --- a/src/fl_read_image_win32.cxx +++ b/src/fl_read_image_win32.cxx @@ -34,10 +34,13 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate int X, // I - Left position int Y, // I - Top position int w, // I - Width of area to read + // negative w means negative X or Y are allowed int h, // I - Height of area to read int alpha) { // I - Alpha value for image (0 for none) int d; // Depth of image + int allow_outside = w < 0; // negative w allows negative X or Y, that is, window border + if (w < 0) w = - w; // Allocate the image data array as needed... d = alpha ? 4 : 3; @@ -58,15 +61,17 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate int shift_x = 0; // X target shift if X modified int shift_y = 0; // Y target shift if X modified - if (X < 0) { - shift_x = -X; - w += X; - X = 0; - } - if (Y < 0) { - shift_y = -Y; - h += Y; - Y = 0; + if (!allow_outside) { + if (X < 0) { + shift_x = -X; + w += X; + X = 0; + } + if (Y < 0) { + shift_y = -Y; + h += Y; + Y = 0; + } } if (h < 1 || w < 1) return p; // nothing to copy |
