Browse Source

Add one argument to Fl_Screen_Driver::read_win_rectangle()

The new argument gives the window to be captured, or NULL to indicate capture
from the current offscreen.
Calling this function becomes easier because less dependent on global variables.
pull/30/head
ManoloFLTK 6 years ago
parent
commit
94fffb701c
  1. 4
      src/Fl_Screen_Driver.H
  2. 3
      src/Fl_Screen_Driver.cxx
  3. 8
      src/Fl_win32.cxx
  4. 2
      src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
  5. 6
      src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
  6. 2
      src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
  7. 4
      src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
  8. 8
      src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
  9. 2
      src/drivers/X11/Fl_X11_Screen_Driver.H
  10. 17
      src/drivers/X11/Fl_X11_Screen_Driver.cxx
  11. 16
      src/drivers/X11/Fl_X11_Window_Driver.cxx
  12. 2
      src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
  13. 2
      src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
  14. 8
      src/fl_overlay.cxx
  15. 2
      src/fl_read_image.cxx

4
src/Fl_Screen_Driver.H

@ -150,8 +150,10 @@ public: @@ -150,8 +150,10 @@ public:
A platform may also use its read_win_rectangle() implementation to capture
window decorations (e.g., title bar). In that case, it is called by
Fl_XXX_Window_Driver::capture_titlebar_and_borders().
win is the window to capture from, or NULL to capture from the current offscreen
*/
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h) {return NULL;}
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win) {return NULL;}
static void write_image_inside(Fl_RGB_Image *to, Fl_RGB_Image *from, int to_x, int to_y);
static Fl_RGB_Image *traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h,
Fl_RGB_Image *full_img);

3
src/Fl_Screen_Driver.cxx

@ -196,8 +196,7 @@ Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, int x, in @@ -196,8 +196,7 @@ Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, int x, in
full_img = plugin->rectangle_capture(g, x, y, w, h);
}
else if ( g->as_window() ) {
if (Fl_Window::current() != g) g->as_window()->make_current();
full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h);
full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h, g->as_window());
}
if (!full_img) return NULL;
float full_img_scale = (full_img && w > 0 ? float(full_img->data_w())/w : 1);

8
src/Fl_win32.cxx

@ -2719,14 +2719,14 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image *&top, F @@ -2719,14 +2719,14 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image *&top, F
// capture the 4 window sides from screen
Fl_WinAPI_Screen_Driver *dr = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver();
if (htop) {
top = dr->read_win_rectangle_unscaled(r.left, r.top, r.right - r.left, htop);
top = dr->read_win_rectangle_unscaled(r.left, r.top, r.right - r.left, htop, 0);
if (scaling != 1)
top->scale(ww, htop / scaling, 0, 1);
}
if (wsides) {
left = dr->read_win_rectangle_unscaled(r.left, r.top + htop, wsides, h() * scaling);
right = dr->read_win_rectangle_unscaled(r.right - wsides, r.top + htop, wsides, h() * scaling);
bottom = dr->read_win_rectangle_unscaled(r.left, r.bottom - hbottom, ww, hbottom);
left = dr->read_win_rectangle_unscaled(r.left, r.top + htop, wsides, h() * scaling, 0);
right = dr->read_win_rectangle_unscaled(r.right - wsides, r.top + htop, wsides, h() * scaling, 0);
bottom = dr->read_win_rectangle_unscaled(r.left, r.bottom - hbottom, ww, hbottom, 0);
if (scaling != 1) {
left->scale(wsides, h(), 0, 1);
right->scale(wsides, h(), 0, 1);

2
src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H

@ -99,7 +99,7 @@ public: @@ -99,7 +99,7 @@ public:
virtual APP_SCALING_CAPABILITY rescalable() { return SYSTEMWIDE_APP_SCALING; }
virtual float scale(int n) {return scale_;}
virtual void scale(int n, float f) { scale_ = f;}
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
private:
float scale_;
};

6
src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx

@ -339,11 +339,11 @@ void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &h @@ -339,11 +339,11 @@ void Fl_Cocoa_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &h
height = CGBitmapContextGetHeight(off);
}
Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h)
Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *window)
{
int bpp, bpr, depth = 4;
uchar *base, *p;
if (!fl_window) { // read from offscreen buffer
if (!window) { // read from offscreen buffer
float s = 1;
CGContextRef src = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); // get bitmap context
base = (uchar *)CGBitmapContextGetData(src); // get data
@ -373,7 +373,7 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in @@ -373,7 +373,7 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in
}
bpr = 0;
} else { // read from window
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(Fl_Window::current());
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(window);
CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h, false);
if (!cgimg) {
return NULL;

2
src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx

@ -89,7 +89,7 @@ void Fl_GDI_Image_Surface_Driver::untranslate() { @@ -89,7 +89,7 @@ void Fl_GDI_Image_Surface_Driver::untranslate() {
Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
{
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height);
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height, 0);
return image;
}

4
src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H

@ -75,8 +75,8 @@ public: @@ -75,8 +75,8 @@ public:
virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
virtual int dnd(int unused);
virtual int compose(int &del);
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h);
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win);
virtual int get_mouse(int &x, int &y);
virtual void enable_im();
virtual void disable_im();

8
src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx

@ -501,7 +501,8 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle( @@ -501,7 +501,8 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
int X, // I - Left position
int Y, // I - Top position
int w, // I - Width of area to read
int h) // I - Height of area to read
int h, // I - Height of area to read
Fl_Window *win) // I - window to capture from or NULL to capture from current offscreen
{
float s = Fl_Surface_Device::surface()->driver()->scale();
int ws, hs;
@ -512,10 +513,10 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle( @@ -512,10 +513,10 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
if (ws < 1) ws = 1;
if (hs < 1) hs = 1;
}
return read_win_rectangle_unscaled(X*s, Y*s, ws, hs);
return read_win_rectangle_unscaled(X*s, Y*s, ws, hs, win);
}
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h)
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win)
{
int d = 3; // Depth of image
int alpha = 0; uchar *p = NULL;
@ -569,6 +570,7 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, @@ -569,6 +570,7 @@ Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y,
bi.bmiHeader.biClrImportant = 0;
// copy bitmap from original DC (Window, Fl_Offscreen, ...)
if (win && Fl_Window::current() != win) win->make_current();
HDC gc = (HDC)fl_graphics_driver->gc();
HDC hdc = CreateCompatibleDC(gc);
HBITMAP hbm = CreateCompatibleBitmap(gc,w,h);

2
src/drivers/X11/Fl_X11_Screen_Driver.H

@ -95,7 +95,7 @@ public: @@ -95,7 +95,7 @@ public:
virtual int compose(int &del);
virtual void compose_reset();
virtual int text_display_can_leak();
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win);
virtual int get_mouse(int &x, int &y);
virtual void enable_im();
virtual void disable_im();

17
src/drivers/X11/Fl_X11_Screen_Driver.cxx

@ -745,7 +745,7 @@ extern "C" { @@ -745,7 +745,7 @@ extern "C" {
}
}
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h)
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win)
{
XImage *image; // Captured image
int i, maxindex; // Looping vars
@ -772,12 +772,14 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -772,12 +772,14 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
int allow_outside = w < 0; // negative w allows negative X or Y, that is, window frame
if (w < 0) w = - w;
float s = allow_outside ? Fl::screen_driver()->scale(Fl_Window::current()->screen_num()) : Fl_Surface_Device::surface()->driver()->scale();
Window xid = (win && !allow_outside ? fl_xid(win) : fl_window);
float s = allow_outside ? Fl::screen_driver()->scale(win->screen_num()) : Fl_Surface_Device::surface()->driver()->scale();
int ws = w * s, hs = h * s, Xs = X*s, Ys = Y*s;
# ifdef __sgi
if (XReadDisplayQueryExtension(fl_display, &i, &i)) {
image = XReadDisplay(fl_display, fl_window, Xs, Ys, ws, hs, 0, NULL);
image = XReadDisplay(fl_display, xid, Xs, Ys, ws, hs, 0, NULL);
} else
# else
image = 0;
@ -788,11 +790,8 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -788,11 +790,8 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
int dx, dy, sx, sy, sw, sh;
Window child_win;
Fl_Window *win;
if (allow_outside) win = Fl_Window::current();
else win = fl_find(fl_window);
if (win) {
XTranslateCoordinates(fl_display, fl_window,
XTranslateCoordinates(fl_display, xid,
RootWindow(fl_display, fl_screen), Xs, Ys, &dx, &dy, &child_win);
// screen dimensions
Fl::screen_xywh(sx, sy, sw, sh, Fl_Window_Driver::driver(win)->screen_num());
@ -811,7 +810,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -811,7 +810,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
// however, if the window is obscured etc. the function will still fail. Make sure we
// catch the error and continue, otherwise an exception will be thrown.
XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
image = XGetImage(fl_display, fl_window, Xs, Ys, ws, hs, AllPlanes, ZPixmap);
image = XGetImage(fl_display, xid, Xs, Ys, ws, hs, AllPlanes, ZPixmap);
XSetErrorHandler(old_handler);
} else {
// image is crossing borders, determine visible region
@ -831,7 +830,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int @@ -831,7 +830,7 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
}
XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
XImage *subimg = XGetSubImage(fl_display, fl_window, Xs + noffx, Ys + noffy,
XImage *subimg = XGetSubImage(fl_display, xid, Xs + noffx, Ys + noffy,
nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
XSetErrorHandler(old_handler);
if (!subimg) {

16
src/drivers/X11/Fl_X11_Window_Driver.cxx

@ -392,16 +392,14 @@ void Fl_X11_Window_Driver::free_icons() { @@ -392,16 +392,14 @@ void Fl_X11_Window_Driver::free_icons() {
This function exploits a feature of Fl_X11_Screen_Driver::read_win_rectangle() which,
when called with negative 3rd argument, captures the window decoration.
Other requirements to capture the window decoration:
- fl_window is the parent window of the top window
- Fl_Window::current() is the top window
Other requirement to capture the window decoration:
fl_window is the parent window of the top window
*/
void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_RGB_Image*& left, Fl_RGB_Image*& bottom, Fl_RGB_Image*& right)
{
top = left = bottom = right = NULL;
if (pWindow->decorated_h() == h()) return;
Window from = fl_window;
Fl_Window *oldcurrent = Fl_Window::current();
Window root, parent, *children, child_win, xid = fl_xid(pWindow);
unsigned n = 0;
int do_it;
@ -414,25 +412,23 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_R @@ -414,25 +412,23 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_RGB_Image*& top, Fl_R
float s = Fl::screen_driver()->scale(screen_num());
htop /= s; wsides /= s;
fl_window = parent;
current(pWindow);
if (htop) {
top = Fl::screen_driver()->read_win_rectangle(0, 0, - (w() + 2 * wsides), htop);
top = Fl::screen_driver()->read_win_rectangle(0, 0, - (w() + 2 * wsides), htop, pWindow);
if (top) top->scale(w() + 2 * wsides, htop, 0, 1);
}
if (wsides) {
left = Fl::screen_driver()->read_win_rectangle(0, htop, -wsides, h());
left = Fl::screen_driver()->read_win_rectangle(0, htop, -wsides, h(), pWindow);
if (left) {
left->scale(wsides, h(), 0, 1);
}
right = Fl::screen_driver()->read_win_rectangle(w() + wsides, htop, -wsides, h());
right = Fl::screen_driver()->read_win_rectangle(w() + wsides, htop, -wsides, h(), pWindow);
if (right) {
right->scale(wsides, h(), 0, 1);
}
bottom = Fl::screen_driver()->read_win_rectangle(0, htop + h(), -(w() + 2*wsides), hbottom);
bottom = Fl::screen_driver()->read_win_rectangle(0, htop + h(), -(w() + 2*wsides), hbottom, pWindow);
if (bottom) {
bottom->scale(w() + 2*wsides, wsides, 0, 1);
} }
current(oldcurrent);
fl_window = from;
}

2
src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx

@ -64,7 +64,7 @@ Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() { @@ -64,7 +64,7 @@ Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() {
driver()->pop_clip();
bool need_push = !is_current();
if (need_push) Fl_Surface_Device::push_current(this);
Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(0, 0, width, height);
Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(0, 0, width, height, 0);
if (need_push) Fl_Surface_Device::pop_current();
Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
delete rgb;

2
src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx

@ -74,7 +74,7 @@ void Fl_Xlib_Image_Surface_Driver::untranslate() { @@ -74,7 +74,7 @@ void Fl_Xlib_Image_Surface_Driver::untranslate() {
Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image()
{
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(0, 0, width, height);
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(0, 0, width, height, 0);
return image;
}

8
src/fl_overlay.cxx

@ -68,19 +68,19 @@ static void draw_current_rect() { @@ -68,19 +68,19 @@ static void draw_current_rect() {
if (s_bgE) { delete s_bgE; s_bgE = 0; }
if (s_bgW) { delete s_bgW; s_bgW = 0; }
if (pw>0 && ph>0) {
s_bgE = Fl::screen_driver()->read_win_rectangle( px+pw-1, py, 1, ph);
s_bgE = Fl::screen_driver()->read_win_rectangle( px+pw-1, py, 1, ph, Fl_Window::current());
if(s_bgE && s_bgE->w() && s_bgE->h()) {
s_bgE->scale(1, ph,0,1);
}
s_bgW = Fl::screen_driver()->read_win_rectangle( px, py, 1, ph);
s_bgW = Fl::screen_driver()->read_win_rectangle( px, py, 1, ph, Fl_Window::current());
if(s_bgW && s_bgW->w() && s_bgW->h()) {
s_bgW->scale(1, ph,0,1);
}
s_bgS = Fl::screen_driver()->read_win_rectangle( px, py+ph-1, pw, 1);
s_bgS = Fl::screen_driver()->read_win_rectangle( px, py+ph-1, pw, 1, Fl_Window::current());
if(s_bgS && s_bgS->w() && s_bgS->h()) {
s_bgS->scale(pw, 1,0,1);
}
s_bgN = Fl::screen_driver()->read_win_rectangle( px, py, pw, 1);
s_bgN = Fl::screen_driver()->read_win_rectangle( px, py, pw, 1, Fl_Window::current());
if(s_bgN && s_bgN->w() && s_bgN->h()) {
s_bgN->scale(pw, 1,0,1);
}

2
src/fl_read_image.cxx

@ -43,7 +43,7 @@ uchar *fl_read_image(uchar *p, int X, int Y, int w, int h, int alpha) { @@ -43,7 +43,7 @@ uchar *fl_read_image(uchar *p, int X, int Y, int w, int h, int alpha) {
uchar *image_data = NULL;
Fl_RGB_Image *img;
if (fl_find(fl_window) == 0) { // read from off_screen buffer
img = Fl::screen_driver()->read_win_rectangle(X, Y, w, h);
img = Fl::screen_driver()->read_win_rectangle(X, Y, w, h, 0);
if (!img) {
return NULL;
}

Loading…
Cancel
Save