mirror of https://github.com/fltk/fltk
Fix fl_read_image() under MacOS platform when GUI is rescaled.
This commit also simplifies the platform-dependent support of fl_read_image(): only Fl_XXX_Screen_Driver::read_win_rectangle() contains platform-specific code to capture pixels from the current window or from an offscreen buffer. Platform-independent function Fl_Screen_Driver::traverse_to_gl_subwindows() captures subwindows that intersect with the area fl_read_image() targets. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12653 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
b78b2f7f5f
commit
c472d5d8b7
|
@ -395,6 +395,12 @@ public:
|
|||
virtual void font_name(int num, const char *name) {}
|
||||
/** Support function for Fl_Shared_Image drawing */
|
||||
virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H);
|
||||
/** Support function for fl_overlay_rect() and scaled GUI.
|
||||
Defaut implementation may be enough */
|
||||
virtual bool overlay_rect_unscaled();
|
||||
/** Support function for fl_overlay_rect() and scaled GUI.
|
||||
Defaut implementation may be enough */
|
||||
virtual void overlay_rect(int x, int y, int w , int h) { loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1); }
|
||||
};
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// All screen related calls in a driver style class.
|
||||
//
|
||||
// Copyright 1998-2017 by Bill Spitzak and others.
|
||||
// Copyright 1998-2018 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
|
||||
|
@ -126,25 +126,23 @@ public:
|
|||
#if defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: implement code to read RGB data from screen"
|
||||
#endif
|
||||
/* Both member functions read_image() and read_win_rectangle() support
|
||||
the public function fl_read_image() which captures pixel data either from
|
||||
/* Member function read_win_rectangle() supports the public function
|
||||
fl_read_image() which captures pixel data either from
|
||||
the current window or from an offscreen buffer.
|
||||
|
||||
A platform re-implements either read_image() or read_win_rectangle().
|
||||
In the 1st case and for capture from a window, the returned pixel array
|
||||
With fl_read_image() and for capture from a window, the returned pixel array
|
||||
also contains data from any embedded sub-window.
|
||||
In the 2nd case and for capture from a window, only data from the current
|
||||
window is collected, and read_image()'s default implementation captures
|
||||
pixels from any subwindow.
|
||||
|
||||
In the case of read_win_rectangle() and for capture from a window, only data
|
||||
from the current window is collected.
|
||||
|
||||
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().
|
||||
*/
|
||||
virtual uchar *read_image(uchar *p, int x, int y, int w, int h, int alpha);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(uchar *p, int X, int Y, int w, int h, int alpha) {return NULL;}
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h) {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, uchar *p, int x, int y, int w, int h, int alpha,
|
||||
static Fl_RGB_Image *traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h,
|
||||
Fl_RGB_Image *full_img);
|
||||
// optional platform-specific key handling for Fl_Input widget
|
||||
// the default implementation may be enough
|
||||
|
|
|
@ -221,6 +221,11 @@ unsigned Fl_Graphics_Driver::font_desc_size() {
|
|||
return (unsigned)sizeof(Fl_Fontdesc);
|
||||
}
|
||||
|
||||
bool Fl_Graphics_Driver::overlay_rect_unscaled()
|
||||
{
|
||||
return (scale() == int(scale()));
|
||||
}
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) {
|
||||
next = 0;
|
||||
|
|
|
@ -141,45 +141,22 @@ void Fl_Screen_Driver::compose_reset() {
|
|||
Fl::compose_state = 0;
|
||||
}
|
||||
|
||||
uchar *Fl_Screen_Driver::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 = read_win_rectangle(p, X, Y, w, h, alpha);
|
||||
if (!img) {
|
||||
return NULL;
|
||||
}
|
||||
img->alloc_array = 1;
|
||||
} else {
|
||||
img = traverse_to_gl_subwindows(Fl_Window::current(), p, X, Y, w, h, alpha, NULL);
|
||||
}
|
||||
if (img) {
|
||||
if (img->w() != w) {
|
||||
Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
|
||||
delete img;
|
||||
img = img2;
|
||||
}
|
||||
img->alloc_array = 0;
|
||||
image_data = (uchar*)img->array;
|
||||
delete img;
|
||||
}
|
||||
return image_data;
|
||||
}
|
||||
|
||||
void Fl_Screen_Driver::write_image_inside(Fl_RGB_Image *to, Fl_RGB_Image *from, int to_x, int to_y)
|
||||
/* Copy the image "from" inside image "to" with its top-left angle at coordinates to_x, to_y.
|
||||
Image depth can differ between "to" and "from".
|
||||
Image depths can differ between "to" and "from".
|
||||
*/
|
||||
{
|
||||
int to_ld = (to->ld() == 0? to->w() * to->d() : to->ld());
|
||||
int from_ld = (from->ld() == 0? from->w() * from->d() : from->ld());
|
||||
uchar *tobytes = (uchar*)to->array + to_y * to_ld + to_x * to->d();
|
||||
const uchar *frombytes = from->array;
|
||||
int need_alpha = (from->d() == 3 && to->d() == 4);
|
||||
for (int i = 0; i < from->h(); i++) {
|
||||
if (from->d() == to->d()) memcpy(tobytes, frombytes, from->w() * from->d());
|
||||
else {
|
||||
for (int j = 0; j < from->w(); j++) {
|
||||
memcpy(tobytes + j * to->d(), frombytes + j * from->d(), from->d());
|
||||
if (need_alpha) *(tobytes + j * to->d() + 3) = 0xff;
|
||||
}
|
||||
}
|
||||
tobytes += to_ld;
|
||||
|
@ -193,45 +170,31 @@ Image depth can differ between "to" and "from".
|
|||
|
||||
Arguments when this function is initially called:
|
||||
g: a window or GL window
|
||||
p: as in fl_read_image()
|
||||
x,y,w,h: a rectangle in window g's coordinates
|
||||
alpha: as in fl_read_image()
|
||||
full_img: NULL
|
||||
|
||||
Arguments when this function recursively calls itself:
|
||||
g: an Fl_Group
|
||||
p: as above
|
||||
x,y,w,h: a rectangle in g's coordinates if g is a window, or in g's parent window coords if g is a group
|
||||
alpha: as above
|
||||
full_img: NULL, or a previously captured image that encompasses the x,y,w,h rectangle and that
|
||||
will be partially overwritten with the new capture
|
||||
|
||||
Return value:
|
||||
An Fl_RGB_Image* of depth 4 if alpha>0 or 3 if alpha = 0 containing the captured pixels.
|
||||
An Fl_RGB_Image*, the depth of which is platform-dependent, containing the captured pixels.
|
||||
*/
|
||||
Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, uchar *p, int x, int y, int w, int h, int alpha,
|
||||
Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, int x, int y, int w, int h,
|
||||
Fl_RGB_Image *full_img)
|
||||
{
|
||||
if ( g->as_gl_window() ) {
|
||||
Fl_Plugin_Manager pm("fltk:device");
|
||||
Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org");
|
||||
if (!pi) return full_img;
|
||||
Fl_RGB_Image *img = pi->rectangle_capture(g, x, y, w, h);
|
||||
if (full_img) full_img = img;
|
||||
else {
|
||||
uchar *data = ( p ? p : new uchar[img->w() * img->h() * (alpha?4:3)] );
|
||||
full_img = new Fl_RGB_Image(data, img->w(), img->h(), alpha?4:3);
|
||||
if (!p) full_img->alloc_array = 1;
|
||||
if (alpha) memset(data, alpha, img->w() * img->h() * 4);
|
||||
write_image_inside(full_img, img, 0, 0);
|
||||
delete img;
|
||||
}
|
||||
full_img = pi->rectangle_capture(g, x, y, w, h);
|
||||
}
|
||||
else if ( g->as_window() && (!full_img || (g->window() && g->window()->as_gl_window())) ) {
|
||||
// the starting window or one inside a GL window
|
||||
if (full_img) g->as_window()->make_current();
|
||||
int alloc_img = (full_img != NULL || p == NULL); // false means use p, don't alloc new memory for image
|
||||
full_img = Fl::screen_driver()->read_win_rectangle( (alloc_img ? NULL : p), x, y, w, h, alpha);
|
||||
full_img = Fl::screen_driver()->read_win_rectangle(x, y, w, h);
|
||||
}
|
||||
int n = g->children();
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
@ -249,8 +212,8 @@ Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, uchar *p,
|
|||
if (origin_y + height > c->y() + c->h()) height = c->y() + c->h() - origin_y;
|
||||
if (origin_y + height > y + h) height = y + h - origin_y;
|
||||
if (width > 0 && height > 0) {
|
||||
Fl_RGB_Image *img = traverse_to_gl_subwindows(c->as_window(), p, origin_x - c->x(),
|
||||
origin_y - c->y(), width, height, alpha, full_img);
|
||||
Fl_RGB_Image *img = traverse_to_gl_subwindows(c->as_window(), origin_x - c->x(),
|
||||
origin_y - c->y(), width, height, full_img);
|
||||
if (img == full_img) continue;
|
||||
int top;
|
||||
if (c->as_gl_window()) {
|
||||
|
@ -264,7 +227,7 @@ Fl_RGB_Image *Fl_Screen_Driver::traverse_to_gl_subwindows(Fl_Group *g, uchar *p,
|
|||
delete img;
|
||||
}
|
||||
}
|
||||
else traverse_to_gl_subwindows(c->as_group(), p, x, y, w, h, alpha, full_img);
|
||||
else traverse_to_gl_subwindows(c->as_group(), x, y, w, h, full_img);
|
||||
}
|
||||
return full_img;
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, i
|
|||
win->show();
|
||||
Fl::check();
|
||||
win->driver()->flush(); // makes the window current
|
||||
Fl_RGB_Image *img = Fl_Screen_Driver::traverse_to_gl_subwindows(win, NULL, x, y, w, h, 0, NULL);
|
||||
Fl_RGB_Image *img = Fl_Screen_Driver::traverse_to_gl_subwindows(win, x, y, w, h, NULL);
|
||||
Fl_Shared_Image *shared = Fl_Shared_Image::get(img);
|
||||
shared->scale(w, h, 1, 1);
|
||||
if (save_front != win) save_front->show();
|
||||
|
|
|
@ -2710,17 +2710,17 @@ void Fl_WinAPI_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image *&top
|
|||
// capture the 4 window sides from screen
|
||||
Fl_WinAPI_Screen_Driver *dr = (Fl_WinAPI_Screen_Driver *)Fl::screen_driver();
|
||||
if (htop) {
|
||||
r_top = dr->read_win_rectangle_unscaled(NULL, r.left, r.top, r.right - r.left, htop, 0);
|
||||
r_top = dr->read_win_rectangle_unscaled(r.left, r.top, r.right - r.left, htop);
|
||||
top = Fl_Shared_Image::get(r_top);
|
||||
if (DWMscaling != 1)
|
||||
top->scale(ww, htop / DWMscaling, 0, 1);
|
||||
}
|
||||
if (wsides) {
|
||||
r_left = dr->read_win_rectangle_unscaled(NULL, r.left, r.top + htop, wsides, h() * scaling, 0);
|
||||
r_left = dr->read_win_rectangle_unscaled(r.left, r.top + htop, wsides, h() * scaling);
|
||||
left = Fl_Shared_Image::get(r_left);
|
||||
r_right = dr->read_win_rectangle_unscaled(NULL, r.right - wsides, r.top + htop, wsides, h() * scaling, 0);
|
||||
r_right = dr->read_win_rectangle_unscaled(r.right - wsides, r.top + htop, wsides, h() * scaling);
|
||||
right = Fl_Shared_Image::get(r_right);
|
||||
r_bottom = dr->read_win_rectangle_unscaled(NULL, r.left, r.bottom - hbottom, ww, hbottom, 0);
|
||||
r_bottom = dr->read_win_rectangle_unscaled(r.left, r.bottom - hbottom, ww, hbottom);
|
||||
bottom = Fl_Shared_Image::get(r_bottom);
|
||||
if (scaling != 1) {
|
||||
left->scale(wsides, h(), 0, 1);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Definition of Apple Cocoa Screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2017 by Bill Spitzak and others.
|
||||
// Copyright 2010-2018 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
|
||||
|
@ -40,6 +40,7 @@
|
|||
|
||||
class Fl_Window;
|
||||
class Fl_Input;
|
||||
class Fl_RGB_Image;
|
||||
|
||||
class FL_EXPORT Fl_Cocoa_Screen_Driver : public Fl_Screen_Driver
|
||||
{
|
||||
|
@ -87,7 +88,6 @@ public:
|
|||
int insertion_point_location(int *px, int *py, int *pheight);
|
||||
virtual int dnd(int use_selection);
|
||||
virtual int compose(int &del);
|
||||
virtual uchar *read_image(uchar *p, int x, int y, int w, int h, int alpha);
|
||||
virtual int input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input);
|
||||
virtual int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
|
@ -100,6 +100,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 int run_also_windowless();
|
||||
virtual int wait_also_windowless(double delay);
|
||||
private:
|
||||
|
|
|
@ -256,70 +256,6 @@ int Fl_Cocoa_Screen_Driver::compose(int &del) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
uchar * // O - Pixel buffer or NULL if failed
|
||||
Fl_Cocoa_Screen_Driver::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
|
||||
int h, // I - Height of area to read
|
||||
int alpha)// I - Alpha value for image (0 for none)
|
||||
{
|
||||
uchar *base;
|
||||
int rowBytes, delta;
|
||||
float s = 1;
|
||||
int ori_w = w, ori_h = h;
|
||||
if (fl_window == NULL) { // reading from an offscreen buffer
|
||||
CGContextRef src = (CGContextRef)Fl_Surface_Device::surface()->driver()->gc(); // get bitmap context
|
||||
base = (uchar *)CGBitmapContextGetData(src); // get data
|
||||
if(!base) return NULL;
|
||||
int sw = CGBitmapContextGetWidth(src);
|
||||
int sh = CGBitmapContextGetHeight(src);
|
||||
if( (sw - x < w) || (sh - y < h) ) return NULL;
|
||||
rowBytes = CGBitmapContextGetBytesPerRow(src);
|
||||
delta = CGBitmapContextGetBitsPerPixel(src)/8;
|
||||
Fl_Image_Surface *imgs = (Fl_Image_Surface*)Fl_Surface_Device::surface();
|
||||
int fltk_w, fltk_h;
|
||||
imgs->printable_rect(&fltk_w, &fltk_h);
|
||||
s = sw / float(fltk_w);
|
||||
x *= s; y *= s; w *= s; h *= s;
|
||||
if (x + w > sw) w = sw - x;
|
||||
if (y + h > sh) h = sh - y;
|
||||
}
|
||||
else { // reading from current window
|
||||
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(Fl_Window::current());
|
||||
base = d->bitmap_from_window_rect(x,y,w,h,&delta);
|
||||
if (!base) return NULL;
|
||||
rowBytes = delta*w;
|
||||
x = y = 0;
|
||||
}
|
||||
// Allocate the image data array as needed...
|
||||
int d = alpha ? 4 : 3;
|
||||
if (!p) p = new uchar[w * h * d];
|
||||
// Initialize the default colors/alpha in the whole image...
|
||||
memset(p, alpha, w * h * d);
|
||||
// Copy the image from the off-screen buffer to the memory buffer.
|
||||
int idx, idy; // Current X & Y in image
|
||||
uchar *pdst, *psrc;
|
||||
for (idy = y, pdst = p; idy < h + y; idy ++) {
|
||||
for (idx = 0, psrc = base + idy * rowBytes + x * delta; idx < w; idx ++, psrc += delta, pdst += d) {
|
||||
pdst[0] = psrc[0]; // R
|
||||
pdst[1] = psrc[1]; // G
|
||||
pdst[2] = psrc[2]; // B
|
||||
}
|
||||
}
|
||||
if (fl_window != NULL) delete[] base;
|
||||
if (s != 1) {
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, alpha ? 4 : 3);
|
||||
rgb->alloc_array = 1;
|
||||
Fl_RGB_Image *rgb2 = (Fl_RGB_Image*)rgb->copy(ori_w, ori_h);
|
||||
rgb2->alloc_array = 0;
|
||||
delete rgb;
|
||||
p = (uchar*)rgb2->array;
|
||||
delete rgb2;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Cocoa_Screen_Driver::input_widget_handle_key(int key, unsigned mods, unsigned shift, Fl_Input *input)
|
||||
{
|
||||
|
@ -401,6 +337,67 @@ 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)
|
||||
{
|
||||
int bpp, bpr, depth = 4;
|
||||
uchar *base, *p;
|
||||
if (!fl_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
|
||||
if(!base) return NULL;
|
||||
int sw = CGBitmapContextGetWidth(src);
|
||||
int sh = CGBitmapContextGetHeight(src);
|
||||
if( (sw - X < w) || (sh - Y < h) ) return NULL;
|
||||
bpr = CGBitmapContextGetBytesPerRow(src);
|
||||
bpp = CGBitmapContextGetBitsPerPixel(src)/8;
|
||||
Fl_Image_Surface *imgs = (Fl_Image_Surface*)Fl_Surface_Device::surface();
|
||||
int fltk_w, fltk_h;
|
||||
imgs->printable_rect(&fltk_w, &fltk_h);
|
||||
s = sw / float(fltk_w);
|
||||
X *= s; Y *= s; w *= s; h *= s;
|
||||
if (X + w > sw) w = sw - X;
|
||||
if (Y + h > sh) h = sh - Y;
|
||||
// Copy the image from the off-screen buffer to the memory buffer.
|
||||
int idx, idy; // Current X & Y in image
|
||||
uchar *pdst, *psrc;
|
||||
p = new uchar[w * h * depth];
|
||||
for (idy = Y, pdst = p; idy < h + Y; idy ++) {
|
||||
for (idx = 0, psrc = base + idy * bpr + X * bpp; idx < w; idx ++, psrc += bpp, pdst += depth) {
|
||||
pdst[0] = psrc[0]; // R
|
||||
pdst[1] = psrc[1]; // G
|
||||
pdst[2] = psrc[2]; // B
|
||||
}
|
||||
}
|
||||
bpr = 0;
|
||||
} else { // read from window
|
||||
Fl_Cocoa_Window_Driver *d = Fl_Cocoa_Window_Driver::driver(Fl_Window::current());
|
||||
CGImageRef cgimg = d->CGImage_from_window_rect(X, Y, w, h);
|
||||
if (!cgimg) {
|
||||
return NULL;
|
||||
}
|
||||
w = CGImageGetWidth(cgimg);
|
||||
h = CGImageGetHeight(cgimg);
|
||||
Fl_Image_Surface *surf = new Fl_Image_Surface(w, h);
|
||||
Fl_Surface_Device::push_current(surf);
|
||||
((Fl_Quartz_Graphics_Driver*)fl_graphics_driver)->draw_CGImage(cgimg, 0, 0, w, h, 0, 0, w, h);
|
||||
CGContextRef gc = (CGContextRef)fl_graphics_driver->gc();
|
||||
w = CGBitmapContextGetWidth(gc);
|
||||
h = CGBitmapContextGetHeight(gc);
|
||||
bpr = CGBitmapContextGetBytesPerRow(gc);
|
||||
bpp = CGBitmapContextGetBitsPerPixel(gc)/8;
|
||||
base = (uchar*)CGBitmapContextGetData(gc);
|
||||
p = new uchar[bpr * h];
|
||||
memcpy(p, base, bpr * h);
|
||||
Fl_Surface_Device::pop_current();
|
||||
delete surf;
|
||||
CFRelease(cgimg);
|
||||
}
|
||||
Fl_RGB_Image *rgb = new Fl_RGB_Image(p, w, h, depth, bpr);
|
||||
rgb->alloc_array = 1;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
//
|
||||
// End of "$Id$".
|
||||
//
|
||||
|
|
|
@ -88,7 +88,6 @@ public:
|
|||
CGRect* subRect() { return subRect_; } // getter
|
||||
void subRect(CGRect *r) { subRect_ = r; } // setter
|
||||
static void destroy(FLWindow*);
|
||||
unsigned char *bitmap_from_window_rect(int x, int y, int w, int h, int *bytesPerPixel);
|
||||
CGImageRef CGImage_from_window_rect(int x, int y, int w, int h);
|
||||
|
||||
// --- window data
|
||||
|
|
|
@ -92,7 +92,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(NULL, 0, 0, width, height, 0);
|
||||
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,8 @@ protected:
|
|||
#else
|
||||
void descriptor_init(const char* name, Fl_Fontsize Size, Fl_Quartz_Font_Descriptor *d);
|
||||
#endif
|
||||
virtual bool overlay_rect_unscaled() {return false; }
|
||||
virtual void overlay_rect(int x, int y, int w , int h);
|
||||
};
|
||||
|
||||
class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver {
|
||||
|
|
|
@ -173,6 +173,30 @@ void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y
|
|||
if (quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(gc_, false);
|
||||
}
|
||||
|
||||
// returns y of horizontal line corresponding to pixels of current window
|
||||
// read by Fl_Cocoa_Screen_Driver::read_win_rectangle( -, y, -, 1)
|
||||
// when GUI is scaled by s
|
||||
static float overlay_y(int y, float s, int H) {
|
||||
int a, b, c;
|
||||
a = int(H*s) - (y+1)*s; // in Cocoa units from window bottom
|
||||
c = (s > 1 ? s : 1); // height of pixels read in Cocoa units
|
||||
b = H*s - (a+c); // top of read image from window top in Cocoa units
|
||||
return b/s; // top of read image from window top in FLTK units
|
||||
}
|
||||
|
||||
void Fl_Quartz_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
|
||||
float s = scale();
|
||||
CGContextSetLineWidth(gc_, 0.01);
|
||||
int H = Fl_Window::current()->h();
|
||||
CGContextMoveToPoint(gc_, x, overlay_y(y, s, H));
|
||||
CGContextAddLineToPoint(gc_, x+w-1, overlay_y(y, s, H));
|
||||
CGContextAddLineToPoint(gc_, x+w-1, overlay_y(y+h-1, s, H));
|
||||
CGContextAddLineToPoint(gc_, x, overlay_y(y+h-1, s, H));
|
||||
CGContextClosePath(gc_);
|
||||
CGContextStrokePath(gc_);
|
||||
CGContextSetLineWidth(gc_, quartz_line_width_);
|
||||
}
|
||||
|
||||
void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
|
||||
CGContextSetShouldAntialias(gc_, true);
|
||||
CGContextMoveToPoint(gc_, x, y);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Definition of MSWindows Win32/64 Screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 by Bill Spitzak and others.
|
||||
// Copyright 2010-2018 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
|
||||
|
@ -79,8 +79,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(uchar *p, int X, int Y, int w, int h, int alpha);
|
||||
Fl_RGB_Image *read_win_rectangle_unscaled(uchar *p, int X, int Y, int w, int h, int alpha);
|
||||
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 int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
virtual void disable_im();
|
||||
|
|
|
@ -496,24 +496,21 @@ int Fl_WinAPI_Screen_Driver::compose(int &del) {
|
|||
|
||||
|
||||
Fl_RGB_Image * // O - image or NULL if failed
|
||||
Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NULL to allocate
|
||||
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 alpha) // I - Alpha value for image (0 for none)
|
||||
int h) // I - Height of area to read
|
||||
{
|
||||
float s = Fl_Surface_Device::surface()->driver()->scale();
|
||||
return read_win_rectangle_unscaled(p, X*s, Y*s, w*s, h*s, alpha);
|
||||
return read_win_rectangle_unscaled(X*s, Y*s, w*s, h*s);
|
||||
}
|
||||
|
||||
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(uchar *p, int X, int Y, int w, int h, int alpha)
|
||||
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h)
|
||||
{
|
||||
int d; // Depth of image
|
||||
|
||||
// Allocate the image data array as needed...
|
||||
d = alpha ? 4 : 3;
|
||||
|
||||
int d = 3; // Depth of image
|
||||
int alpha = 0; uchar *p = NULL;
|
||||
// Allocate the image data array as needed...
|
||||
const uchar *oldp = p;
|
||||
if (!p) p = new uchar[w * h * d];
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Definition of X11 Screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2017 by Bill Spitzak and others.
|
||||
// Copyright 2010-2018 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
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
virtual int compose(int &del);
|
||||
virtual void compose_reset();
|
||||
virtual int text_display_can_leak();
|
||||
virtual Fl_RGB_Image *read_win_rectangle(uchar *p, int X, int Y, int w, int h, int alpha);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
|
||||
virtual int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
virtual void disable_im();
|
||||
|
|
|
@ -750,7 +750,7 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, int w, int h, int alpha)
|
||||
Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int h)
|
||||
{
|
||||
XImage *image; // Captured image
|
||||
int i, maxindex; // Looping vars
|
||||
|
@ -862,14 +862,14 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i
|
|||
printf("map_entries = %d\n", fl_visual->visual->map_entries);
|
||||
#endif // DEBUG
|
||||
|
||||
d = alpha ? 4 : 3;
|
||||
|
||||
d = 3;
|
||||
uchar *p = NULL;
|
||||
// Allocate the image data array as needed...
|
||||
const uchar *oldp = p;
|
||||
if (!p) p = new uchar[w * h * d];
|
||||
|
||||
// Initialize the default colors/alpha in the whole image...
|
||||
memset(p, alpha, w * h * d);
|
||||
memset(p, 0, w * h * d);
|
||||
|
||||
// Check that we have valid mask/shift values...
|
||||
if (!image->red_mask && image->bits_per_pixel > 12) {
|
||||
|
|
|
@ -413,22 +413,22 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, F
|
|||
htop /= s; wsides /= s;
|
||||
fl_window = parent;
|
||||
if (htop) {
|
||||
r_top = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, - (w() + 2 * wsides), htop, 0);
|
||||
r_top = Fl::screen_driver()->read_win_rectangle(0, 0, - (w() + 2 * wsides), htop);
|
||||
top = Fl_Shared_Image::get(r_top);
|
||||
top->scale(w() + 2 * wsides, htop, 0, 1);
|
||||
}
|
||||
if (wsides) {
|
||||
r_left = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop, -wsides, h(), 0);
|
||||
r_left = Fl::screen_driver()->read_win_rectangle(0, htop, -wsides, h());
|
||||
if (r_left) {
|
||||
left = Fl_Shared_Image::get(r_left);
|
||||
left->scale(wsides, h(), 0, 1);
|
||||
}
|
||||
r_right = Fl::screen_driver()->read_win_rectangle(NULL, w() + wsides, htop, -wsides, h(), 0);
|
||||
r_right = Fl::screen_driver()->read_win_rectangle(w() + wsides, htop, -wsides, h());
|
||||
if (r_right) {
|
||||
right = Fl_Shared_Image::get(r_right);
|
||||
right->scale(wsides, h(), 0, 1);
|
||||
}
|
||||
r_bottom = Fl::screen_driver()->read_win_rectangle(NULL, 0, htop + h(), -(w() + 2*wsides), hbottom, 0);
|
||||
r_bottom = Fl::screen_driver()->read_win_rectangle(0, htop + h(), -(w() + 2*wsides), hbottom);
|
||||
if (r_bottom) {
|
||||
bottom = Fl_Shared_Image::get(r_bottom);
|
||||
bottom->scale(w() + 2*wsides, wsides, 0, 1);
|
||||
|
|
|
@ -67,7 +67,7 @@ Fl_Xlib_Copy_Surface_Driver::~Fl_Xlib_Copy_Surface_Driver() {
|
|||
driver()->pop_clip();
|
||||
bool need_push = (Fl_Surface_Device::surface() != this);
|
||||
if (need_push) Fl_Surface_Device::push_current(this);
|
||||
Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
|
||||
Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(0, 0, width, height);
|
||||
if (need_push) Fl_Surface_Device::pop_current();
|
||||
Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
|
||||
delete rgb;
|
||||
|
|
|
@ -80,7 +80,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(NULL, 0, 0, width, height, 0);
|
||||
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(0, 0, width, height);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static void draw_current_rect() {
|
|||
int old = SetROP2(fl_graphics_driver->gc(), R2_NOT);
|
||||
fl_rect(px, py, pw, ph);
|
||||
SetROP2(fl_graphics_driver->gc(), old);
|
||||
# elif defined(__APPLE_) // PORTME: Fl_Window_Driver - platform overlay
|
||||
# elif defined(__APPLE__)
|
||||
// warning: Quartz does not support xor drawing
|
||||
// Use the Fl_Overlay_Window instead.
|
||||
fl_color(FL_WHITE);
|
||||
|
@ -66,8 +66,8 @@ static void draw_current_rect() {
|
|||
# error unsupported platform
|
||||
# endif
|
||||
#else
|
||||
float s = fl_graphics_driver->scale();
|
||||
if (s == int(s)) {
|
||||
bool unscaled = fl_graphics_driver->overlay_rect_unscaled();
|
||||
if (unscaled) {
|
||||
if (bgN) { free(bgN); bgN = 0L; }
|
||||
if (bgS) { free(bgS); bgS = 0L; }
|
||||
if (bgE) { free(bgE); bgE = 0L; }
|
||||
|
@ -79,29 +79,29 @@ static void draw_current_rect() {
|
|||
if (s_bgW) { s_bgW->release(); s_bgW = 0; }
|
||||
}
|
||||
if (pw>0 && ph>0) {
|
||||
if (s == int(s)) {
|
||||
if (unscaled) {
|
||||
bgE = fl_read_image(0L, px+pw-1, py, 1, ph);
|
||||
bgW = fl_read_image(0L, px, py, 1, ph);
|
||||
bgS = fl_read_image(0L, px, py+ph-1, pw, 1);
|
||||
bgN = fl_read_image(0L, px, py, pw, 1);
|
||||
} else {
|
||||
Fl_RGB_Image *tmp;
|
||||
tmp = Fl::screen_driver()->read_win_rectangle(NULL, px+pw-1, py, 1, ph, 0);
|
||||
tmp = Fl::screen_driver()->read_win_rectangle( px+pw-1, py, 1, ph);
|
||||
if(tmp && tmp->w() && tmp->h()) {
|
||||
s_bgE = Fl_Shared_Image::get(tmp);
|
||||
s_bgE->scale(1, ph,0,1);
|
||||
}
|
||||
tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py, 1, ph, 0);
|
||||
tmp = Fl::screen_driver()->read_win_rectangle( px, py, 1, ph);
|
||||
if(tmp && tmp->w() && tmp->h()) {
|
||||
s_bgW = Fl_Shared_Image::get(tmp);
|
||||
s_bgW->scale(1, ph,0,1);
|
||||
}
|
||||
tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py+ph-1, pw, 1, 0);
|
||||
tmp = Fl::screen_driver()->read_win_rectangle( px, py+ph-1, pw, 1);
|
||||
if(tmp && tmp->w() && tmp->h()) {
|
||||
s_bgS = Fl_Shared_Image::get(tmp);
|
||||
s_bgS->scale(pw, 1,0,1);
|
||||
}
|
||||
tmp = Fl::screen_driver()->read_win_rectangle(NULL, px, py, pw, 1, 0);
|
||||
tmp = Fl::screen_driver()->read_win_rectangle( px, py, pw, 1);
|
||||
if(tmp && tmp->w() && tmp->h()) {
|
||||
s_bgN = Fl_Shared_Image::get(tmp);
|
||||
s_bgN->scale(pw, 1,0,1);
|
||||
|
@ -112,12 +112,13 @@ static void draw_current_rect() {
|
|||
}
|
||||
fl_color(FL_WHITE);
|
||||
fl_line_style(FL_SOLID);
|
||||
if (s == int(s)) fl_rect(px, py, pw, ph);
|
||||
else fl_loop(px, py, px+pw-1, py, px+pw-1, py+ph-1, px, py+ph-1);
|
||||
if (unscaled) fl_rect(px, py, pw, ph);
|
||||
else fl_graphics_driver->overlay_rect(px, py, pw, ph);
|
||||
|
||||
fl_color(FL_BLACK);
|
||||
fl_line_style(FL_DOT);
|
||||
if (s == int(s)) fl_rect(px, py, pw, ph);
|
||||
else fl_loop(px, py, px+pw-1, py, px+pw-1, py+ph-1, px, py+ph-1);
|
||||
if (unscaled) fl_rect(px, py, pw, ph);
|
||||
else fl_graphics_driver->overlay_rect(px, py, pw, ph);
|
||||
fl_line_style(FL_SOLID);
|
||||
#endif // USE_XOR
|
||||
}
|
||||
|
@ -130,8 +131,8 @@ static void erase_current_rect() {
|
|||
draw_current_rect();
|
||||
# endif
|
||||
#else
|
||||
float s = fl_graphics_driver->scale();
|
||||
if (s == int(s)) {
|
||||
bool unscaled = fl_graphics_driver->overlay_rect_unscaled();
|
||||
if (unscaled) {
|
||||
if (bgN) fl_draw_image(bgN, bgx, bgy, bgw, 1);
|
||||
if (bgS) fl_draw_image(bgS, bgx, bgy+bgh-1, bgw, 1);
|
||||
if (bgW) fl_draw_image(bgW, bgx, bgy, 1, bgh);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// X11 image reading routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2016 by Bill Spitzak and others.
|
||||
// Copyright 1998-2018 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
|
||||
|
@ -17,6 +17,7 @@
|
|||
//
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl_Screen_Driver.H>
|
||||
|
||||
/**
|
||||
|
@ -36,8 +37,55 @@
|
|||
and the value that is placed in the alpha channel. If 0, no alpha
|
||||
channel is generated.
|
||||
*/
|
||||
uchar *fl_read_image(uchar *p, int X, int Y, int W, int H, int alpha) {
|
||||
return Fl::screen_driver()->read_image(p, X, Y, W, H, alpha);
|
||||
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);
|
||||
if (!img) {
|
||||
return NULL;
|
||||
}
|
||||
img->alloc_array = 1;
|
||||
} else {
|
||||
img = Fl::screen_driver()->traverse_to_gl_subwindows(Fl_Window::current(), X, Y, w, h, NULL);
|
||||
}
|
||||
int depth = alpha ? 4 : 3;
|
||||
if (img->d() != depth) {
|
||||
uchar *data = new uchar[img->w() * img->h() * depth];
|
||||
if (depth == 4) memset(data, alpha, img->w() * img->h() * depth);
|
||||
uchar *d = data;
|
||||
const uchar *q;
|
||||
int ld = img->ld() ? img->ld() : img->w() * img->d();
|
||||
for (int r = 0; r < img->h(); r++) {
|
||||
q = img->array + r * ld;
|
||||
for (int c = 0; c < img->w(); c++) {
|
||||
d[0] = q[0];
|
||||
d[1] = q[1];
|
||||
d[2] = q[2];
|
||||
d += depth; q += img->d();
|
||||
}
|
||||
}
|
||||
Fl_RGB_Image *img2 = new Fl_RGB_Image(data, img->w(), img->h(), depth);
|
||||
img2->alloc_array = 1;
|
||||
delete img;
|
||||
img = img2;
|
||||
}
|
||||
if (img) {
|
||||
if (img->w() != w || img->h() != h) {
|
||||
Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w, h);
|
||||
delete img;
|
||||
img = img2;
|
||||
}
|
||||
img->alloc_array = 0;
|
||||
image_data = (uchar*)img->array;
|
||||
delete img;
|
||||
}
|
||||
if (p && image_data) {
|
||||
memcpy(p, image_data, w * h * depth);
|
||||
delete[] image_data;
|
||||
image_data = p;
|
||||
}
|
||||
return image_data;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue