summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.H86
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx43
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx4
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx38
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx74
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx2
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx36
-rw-r--r--src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx22
-rw-r--r--src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx7
-rw-r--r--src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx10
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H7
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx4
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx8
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.H16
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.cxx313
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.H22
-rw-r--r--src/drivers/X11/Fl_X11_Window_Driver.cxx75
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx8
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H105
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx51
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx12
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx25
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx155
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx117
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx11
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx189
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx23
-rw-r--r--src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx14
28 files changed, 1031 insertions, 446 deletions
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
index 71a99b9b0..140e6acea 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H
@@ -34,7 +34,7 @@
*
This class is implemented only on the MSWindows platform.
*/
-class FL_EXPORT Fl_GDI_Graphics_Driver : public Fl_Graphics_Driver {
+class FL_EXPORT Fl_GDI_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
private:
BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch);
int depth; // to support translation
@@ -59,55 +59,58 @@ public:
// --- bitmap stuff
Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
void delete_bitmask(Fl_Bitmask bm);
- void draw(const char* str, int n, int x, int y);
- void draw(int angle, const char *str, int n, int x, int y);
- void rtl_draw(const char* str, int n, int x, int y);
- void font(Fl_Font face, Fl_Fontsize size);
- void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
+ virtual void draw_unscaled(const char* str, int n, int x, int y);
+ virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
+ virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
+ virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
+ void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy);
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
- void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
- void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
- void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
- void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+ virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+ virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+ virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+ virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
- double width(const char *str, int n);
- double width(unsigned int c);
- void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
- int height();
- int descent();
+ virtual double width_unscaled(const char *str, int n);
+ virtual double width_unscaled(unsigned int c);
+ void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
+ int height_unscaled();
+ int descent_unscaled();
+ Fl_Fontsize size_unscaled();
#if ! defined(FL_DOXYGEN)
void copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy);
#endif
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+ virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy);
void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
Fl_Region XRectangleRegion(int x, int y, int w, int h);
void XDestroyRegion(Fl_Region r);
void translate_all(int x, int y);
void untranslate_all(void);
+ static HRGN scale_region(HRGN r, float f, bool keep, bool inflate=false);
+ virtual void scale(float f);
protected:
- void transformed_vertex0(int x, int y);
+ void transformed_vertex0(float x, float y);
void fixloop();
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/gdi_rect.cxx
- void point(int x, int y);
- void rect(int x, int y, int w, int h);
+ virtual void point_unscaled(float x, float y);
+ void rect_unscaled(float x, float y, float w, float h);
void focus_rect(int x, int y, int w, int h);
- void rectf(int x, int y, int w, int h);
- void line(int x, int y, int x1, int y1);
- void line(int x, int y, int x1, int y1, int x2, int y2);
- void xyline(int x, int y, int x1);
- void xyline(int x, int y, int x1, int y2);
- void xyline(int x, int y, int x1, int y2, int x3);
- void yxline(int x, int y, int y1);
- void yxline(int x, int y, int y1, int x2);
- void yxline(int x, int y, int y1, int x2, int y3);
- void loop(int x0, int y0, int x1, int y1, int x2, int y2);
- void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+ void rectf_unscaled(float x, float y, float w, float h);
+ virtual void line_unscaled(float x, float y, float x1, float y1);
+ virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
+ virtual void xyline_unscaled(float x, float y, float x1);
+ virtual void xyline_unscaled(float x, float y, float x1, float y2);
+ virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3);
+ virtual void yxline_unscaled(float x, float y, float y1);
+ virtual void yxline_unscaled(float x, float y, float y1, float x2);
+ virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3);
+ virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+ virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+ virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+ virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
// --- clipping
void push_clip(int x, int y, int w, int h);
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
@@ -115,24 +118,23 @@ protected:
void push_no_clip();
void pop_clip();
void restore_clip();
+ virtual Fl_Region scale_clip(float f);
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
void begin_complex_polygon();
- void transformed_vertex(double xf, double yf);
- void vertex(double x, double y);
void end_points();
void end_line();
void end_loop();
void end_polygon();
void end_complex_polygon();
void gap();
- void circle(double x, double y, double r);
+ virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
// --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
// using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
// --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
- void arc(int x, int y, int w, int h, double a1, double a2);
- void pie(int x, int y, int w, int h, double a1, double a2);
+ virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
+ virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
- void line_style(int style, int width=0, char* dashes=0);
+ virtual void line_style_unscaled(int style, float width, char* dashes);
// --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
void color(Fl_Color c);
Fl_Color color() { return color_; }
@@ -162,8 +164,8 @@ private:
transparent_f_type TransparentBlt();
public:
virtual int has_feature(driver_feature mask) { return mask & (NATIVE | PRINTER); }
- void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
};
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
index 6649e3f3d..e211f1e3a 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
@@ -104,7 +104,7 @@ HDC fl_makeDC(HBITMAP bitmap) {
return new_gc;
}
-void Fl_GDI_Graphics_Driver::copy_offscreen(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
+void Fl_GDI_Graphics_Driver::copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen bitmap, float srcx, float srcy) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, bitmap);
@@ -162,7 +162,7 @@ void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y,
XDestroyRegion(R);
}
-void Fl_GDI_Graphics_Driver::transformed_vertex0(int x, int y) {
+void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) {
if (!n || x != p[n-1].x || y != p[n-1].y) {
if (n >= p_size) {
p_size = p ? 2*p_size : 16;
@@ -228,6 +228,45 @@ void Fl_GDI_Graphics_Driver::set_spot(int font, int size, int X, int Y, int W, i
}
+void Fl_GDI_Graphics_Driver::scale(float f) {
+ if (f != scale_) {
+ size_ = 0;
+ scale_ = f;
+ //line_style(FL_SOLID); // scale also default line width
+ }
+}
+
+
+/* Rescale region r with factor f and returns the scaled region.
+ The input region is deleted if keep is false.
+ The input region is inflated by 1 unit before rescaling if inflate is true.
+ Region r is returned unchanged if r is null or f is 1.
+ */
+HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, bool keep, bool inflate) {
+ if (r && f != 1) {
+ DWORD size = GetRegionData(r, 0, NULL);
+ RGNDATA *pdata = (RGNDATA*)malloc(size);
+ GetRegionData(r, size, pdata);
+ if (!keep) DeleteObject(r);
+ if (inflate) {
+ RECT *rects = (RECT*)&(pdata->Buffer);
+ for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
+ InflateRect(rects+i, 1, 1);
+ }
+ }
+ XFORM xform = {f, 0, 0, f, 0, 0};
+ r = ExtCreateRegion(&xform, size, pdata);
+ free(pdata);
+ }
+ return r;
+}
+
+
+Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
+ HRGN r = rstack[rstackptr];
+ HRGN r2 = scale_region(r, f, true);
+ return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
+}
//
// End of "$Id$".
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
index 77753139f..53ea13dcd 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
@@ -35,7 +35,7 @@
#include <FL/math.h>
#include <FL/x.H>
-void Fl_GDI_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+void Fl_GDI_Graphics_Driver::arc_unscaled(float x, float y, float w, float h, double a1, double a2) {
if (w <= 0 || h <= 0) return;
int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
int ya = y+h/2-int(h*sin(a1/180.0*M_PI));
@@ -47,7 +47,7 @@ void Fl_GDI_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
} else Arc(gc_, x, y, x+w, y+h, xa, ya, xb, yb);
}
-void Fl_GDI_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+void Fl_GDI_Graphics_Driver::pie_unscaled(float x, float y, float w, float h, double a1, double a2) {
if (w <= 0 || h <= 0) return;
if (a1 == a2) return;
int xa = x+w/2+int(w*cos(a1/180.0*M_PI));
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
index 6204929bd..5aea512f7 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
@@ -323,34 +323,40 @@ static void fl_font(Fl_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size,
driver->Fl_Graphics_Driver::font(0, 0);
return;
}
- if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && angle == fl_angle_) return;
+ if (fnum == driver->Fl_Graphics_Driver::font() && size == ((Fl_GDI_Graphics_Driver*)driver)->size_unscaled() && angle == fl_angle_) return;
fl_angle_ = angle;
driver->Fl_Graphics_Driver::font(fnum, size);
driver->font_descriptor( find(fnum, size, angle) );
}
-void Fl_GDI_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_GDI_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
fl_font(this, fnum, size, 0);
}
-int Fl_GDI_Graphics_Driver::height() {
+int Fl_GDI_Graphics_Driver::height_unscaled() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (fl_fontsize) return (fl_fontsize->metr.tmAscent + fl_fontsize->metr.tmDescent);
else return -1;
}
-int Fl_GDI_Graphics_Driver::descent() {
+int Fl_GDI_Graphics_Driver::descent_unscaled() {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (fl_fontsize) return fl_fontsize->metr.tmDescent;
else return -1;
}
+Fl_Fontsize Fl_GDI_Graphics_Driver::size_unscaled() {
+ if (font_descriptor()) return size_;
+ return -1;
+}
+
+
// Unicode string buffer
static unsigned short *wstr = NULL;
static int wstr_len = 0;
-double Fl_GDI_Graphics_Driver::width(const char* c, int n) {
+double Fl_GDI_Graphics_Driver::width_unscaled(const char* c, int n) {
int i = 0;
if (!font_descriptor()) return -1.0;
double w = 0.0;
@@ -362,13 +368,13 @@ double Fl_GDI_Graphics_Driver::width(const char* c, int n) {
// if (l < 1) l = 1;
i += l;
if (!fl_nonspacing(ucs)) {
- w += width(ucs);
+ w += width_unscaled(ucs);
}
}
return w;
}
-double Fl_GDI_Graphics_Driver::width(unsigned int c) {
+double Fl_GDI_Graphics_Driver::width_unscaled(unsigned int c) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
unsigned int r;
SIZE s;
@@ -466,7 +472,7 @@ static void on_printer_extents_update(int &dx, int &dy, int &w, int &h, HDC gc)
}
// Function to determine the extent of the "inked" area of the glyphs in a string
-void Fl_GDI_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_GDI_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
Fl_Font_Descriptor *fl_fontsize = font_descriptor();
if (!fl_fontsize) { // no valid font, nothing to measure
@@ -571,14 +577,14 @@ void Fl_GDI_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy
exit_error:
// some error here - just return fl_measure values
w = (int)width(c, n);
- h = height();
+ h = height_unscaled();
dx = 0;
- dy = descent() - h;
+ dy = descent_unscaled() - h;
EXTENTS_UPDATE(dx, dy, w, h, gc_);
return;
} // fl_text_extents
-void Fl_GDI_Graphics_Driver::draw(const char* str, int n, int x, int y) {
+void Fl_GDI_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y) {
COLORREF oldColor = SetTextColor(gc_, fl_RGB());
// avoid crash if no font has been set yet
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
@@ -593,8 +599,8 @@ void Fl_GDI_Graphics_Driver::draw(const char* str, int n, int x, int y) {
SetTextColor(gc_, oldColor); // restore initial state
}
-void Fl_GDI_Graphics_Driver::draw(int angle, const char* str, int n, int x, int y) {
- fl_font(this, Fl_Graphics_Driver::font(), size(), angle);
+void Fl_GDI_Graphics_Driver::draw_unscaled(int angle, const char* str, int n, int x, int y) {
+ fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), angle);
int wn = 0; // count of UTF16 cells to render full string
COLORREF oldColor = SetTextColor(gc_, fl_RGB());
SelectObject(gc_, font_descriptor()->fid);
@@ -606,10 +612,10 @@ void Fl_GDI_Graphics_Driver::draw(int angle, const char* str, int n, int x, int
}
TextOutW(gc_, x, y, (WCHAR*)wstr, wn);
SetTextColor(gc_, oldColor);
- fl_font(this, Fl_Graphics_Driver::font(), size(), 0);
+ fl_font(this, Fl_Graphics_Driver::font(), size_unscaled(), 0);
}
-void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_GDI_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
int wn;
wn = fl_utf8toUtf16(c, n, wstr, wstr_len);
if(wn >= wstr_len) {
@@ -634,7 +640,7 @@ void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
}
#else
UINT old_align = SetTextAlign(gc_, TA_RIGHT | TA_RTLREADING);
- TextOutW(gc_, x, y - height() + descent(), (WCHAR*)wstr, wn);
+ TextOutW(gc_, x, y - height_unscaled() + descent_unscaled(), (WCHAR*)wstr, wn);
SetTextAlign(gc_, old_align);
#endif
SetTextColor(gc_, oldColor);
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
index 7006bc429..4749ad14a 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx
@@ -42,6 +42,7 @@
#include <FL/Fl_Printer.H>
#include <FL/fl_draw.H>
#include <FL/x.H>
+#include <FL/Fl_Image_Surface.H>
#define MAXBUFFER 0x40000 // 256k
@@ -284,7 +285,7 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
}
}
-void Fl_GDI_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_GDI_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
d ^= FL_IMAGE_WITH_ALPHA;
innards(buf,x,y,w,h,d,l,fl_abs(d),0,0, gc_);
@@ -293,7 +294,7 @@ void Fl_GDI_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, i
}
}
-void Fl_GDI_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
+void Fl_GDI_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
d ^= FL_IMAGE_WITH_ALPHA;
@@ -303,7 +304,7 @@ void Fl_GDI_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
}
}
-void Fl_GDI_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
d ^= FL_IMAGE_WITH_ALPHA;
innards(buf,x,y,w,h,d,l,1,0,0, gc_);
@@ -312,7 +313,7 @@ void Fl_GDI_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int
}
}
-void Fl_GDI_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+void Fl_GDI_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
if (fl_abs(d)&FL_IMAGE_WITH_ALPHA) {
d ^= FL_IMAGE_WITH_ALPHA;
@@ -399,11 +400,15 @@ void Fl_GDI_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
DeleteObject((HGDIOBJ)bm);
}
-void Fl_GDI_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy) {
int X, Y, W, H;
if (Fl_Graphics_Driver::prepare(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
return;
}
+ X = X*s;
+ Y = Y*s;
+ cache_size(bm, W, H);
+ cx *= s; cy *= s;
HDC tempdc = CreateCompatibleDC(gc_);
int save = SaveDC(tempdc);
@@ -423,7 +428,7 @@ Fl_GDI_Printer_Graphics_Driver::transparent_f_type Fl_GDI_Printer_Graphics_Drive
return fpter;
}
-void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy) {
int X, Y, W, H;
transparent_f_type fl_TransparentBlt = TransparentBlt();
if (!fl_TransparentBlt) {
@@ -467,34 +472,33 @@ void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP,
static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask)
{
- Fl_Offscreen offs = fl_create_offscreen(img->w(), img->h());
+ Fl_Image_Surface *surface = new Fl_Image_Surface(img->w(), img->h());
+ Fl_Surface_Device::push_current(surface);
if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) {
- fl_begin_offscreen(offs);
fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
- fl_end_offscreen();
} else {
- fl_begin_offscreen(offs);
fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld());
- fl_end_offscreen();
if (img->d() == 2 || img->d() == 4) {
*pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array);
}
}
+ Fl_Surface_Device::pop_current();
+ Fl_Offscreen offs = surface->get_offscreen_before_delete();
+ delete surface;
return offs;
}
-void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- // Don't draw an empty image...
- if (!img->d() || !img->array) {
- Fl_Graphics_Driver::draw_empty(img, XP, YP);
- return;
- }
- if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
- return;
+void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, int Y, int W, int H, int cx, int cy) {
+ X = X*s;
+ Y = Y*s;
+ cache_size(img, W, H);
+ cx *= s; cy *= s;
+ if (!*Fl_Graphics_Driver::id(img)) {
+ *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)build_id(img, (void**)(Fl_Graphics_Driver::mask(img)));
+ *cache_scale(img) = 1;
}
- if (!*Fl_Graphics_Driver::id(img)) *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)build_id(img, (void**)(Fl_Graphics_Driver::mask(img)));
+ Fl_Region r2 = scale_clip(s);
if (*Fl_Graphics_Driver::mask(img)) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
@@ -509,6 +513,7 @@ void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int
} else {
copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(img), cx, cy);
}
+ unscale_clip(r2);
}
int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
@@ -525,21 +530,26 @@ int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, i
return 1;
}
+
int Fl_GDI_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
Fl_RGB_Image *rgb = img->as_rgb_image();
if (!rgb || !rgb->array) return 0; // for bitmaps and pixmaps
if ((rgb->d() % 2) == 0 && !can_do_alpha_blending()) return 0;
- if (!*Fl_Graphics_Driver::id(rgb)) *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)build_id(rgb,
+ if (!*Fl_Graphics_Driver::id(rgb)) {
+ *Fl_Graphics_Driver::id(rgb) = (fl_uintptr_t)build_id(rgb,
(void**)(Fl_Graphics_Driver::mask(rgb)));
+ *cache_scale(rgb) = 1;
+ }
+ cache_size(img, WP, HP);
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb));
if ( (rgb->d() % 2) == 0 ) {
- alpha_blend_(XP, YP, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h());
+ alpha_blend_(XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h());
} else {
SetStretchBltMode(gc_, HALFTONE);
- StretchBlt(gc_, XP, YP, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h(), SRCCOPY);
+ StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h(), SRCCOPY);
}
RestoreDC(new_gc, save);
DeleteDC(new_gc);
@@ -587,13 +597,17 @@ static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) {
return bm;
}
-fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+ *cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale();
return (fl_uintptr_t)fl_create_bitmap(w, h, array);
}
-void Fl_GDI_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return;
+void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) {
+ X = X*s;
+ Y = Y*s;
+ cache_size(pxm, W, H);
+ cx *= s; cy *= s;
+ Fl_Region r2 = scale_clip(s);
if (*Fl_Graphics_Driver::mask(pxm)) {
HDC new_gc = CreateCompatibleDC(gc_);
int save = SaveDC(new_gc);
@@ -606,10 +620,11 @@ void Fl_GDI_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP
} else {
copy_offscreen(X, Y, W, H, (Fl_Offscreen)*Fl_Graphics_Driver::id(pxm), cx, cy);
}
+ unscale_clip(r2);
}
-void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
+void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy) {
int X, Y, W, H;
if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return;
transparent_f_type fl_TransparentBlt = TransparentBlt();
@@ -642,6 +657,7 @@ fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const c
delete[] bitmap;
}
fl_end_offscreen();
+ *cache_scale(img) = Fl_Scalable_Graphics_Driver::scale();
return (fl_uintptr_t)id;
}
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
index 26dd842d9..35281265c 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
@@ -35,7 +35,7 @@
#include "Fl_GDI_Graphics_Driver.H"
-void Fl_GDI_Graphics_Driver::line_style(int style, int width, char* dashes) {
+void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) {
// According to Bill, the "default" cap and join should be the
// "fastest" mode supported for the platform. I don't know why
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
index 3ef206488..86698e386 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
@@ -35,11 +35,11 @@
// --- line and polygon drawing with integer coordinates
-void Fl_GDI_Graphics_Driver::point(int x, int y) {
+void Fl_GDI_Graphics_Driver::point_unscaled(float x, float y) {
SetPixel(gc_, x, y, fl_RGB());
}
-void Fl_GDI_Graphics_Driver::rect(int x, int y, int w, int h) {
+void Fl_GDI_Graphics_Driver::rect_unscaled(float x, float y, float w, float h) {
if (w<=0 || h<=0) return;
MoveToEx(gc_, x, y, 0L);
LineTo(gc_, x+w-1, y);
@@ -59,7 +59,7 @@ void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) {
for (yy = h; yy > 0; yy--, i++) if (i & 1) point(x, y + yy);
}
-void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) {
+void Fl_GDI_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) {
if (w<=0 || h<=0) return;
RECT rect;
rect.left = x; rect.top = y;
@@ -67,24 +67,24 @@ void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) {
FillRect(gc_, &rect, fl_brush());
}
-void Fl_GDI_Graphics_Driver::line(int x, int y, int x1, int y1) {
+void Fl_GDI_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) {
MoveToEx(gc_, x, y, 0L);
LineTo(gc_, x1, y1);
SetPixel(gc_, x1, y1, fl_RGB());
}
-void Fl_GDI_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_GDI_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
MoveToEx(gc_, x, y, 0L);
LineTo(gc_, x1, y1);
LineTo(gc_, x2, y2);
SetPixel(gc_, x2, y2, fl_RGB());
}
-void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1) {
+void Fl_GDI_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {
MoveToEx(gc_, x, y, 0L); LineTo(gc_, x1+1, y);
}
-void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+void Fl_GDI_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2) {
if (y2 < y) y2--;
else y2++;
MoveToEx(gc_, x, y, 0L);
@@ -92,7 +92,7 @@ void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
LineTo(gc_, x1, y2);
}
-void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+void Fl_GDI_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2, float x3) {
if(x3 < x1) x3--;
else x3++;
MoveToEx(gc_, x, y, 0L);
@@ -101,13 +101,13 @@ void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
LineTo(gc_, x3, y2);
}
-void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1) {
+void Fl_GDI_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {
if (y1 < y) y1--;
else y1++;
MoveToEx(gc_, x, y, 0L); LineTo(gc_, x, y1);
}
-void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+void Fl_GDI_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2) {
if (x2 > x) x2++;
else x2--;
MoveToEx(gc_, x, y, 0L);
@@ -115,7 +115,7 @@ void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
LineTo(gc_, x2, y1);
}
-void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+void Fl_GDI_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2, float y3) {
if(y3<y1) y3--;
else y3++;
MoveToEx(gc_, x, y, 0L);
@@ -124,14 +124,14 @@ void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
LineTo(gc_, x2, y3);
}
-void Fl_GDI_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_GDI_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
MoveToEx(gc_, x, y, 0L);
LineTo(gc_, x1, y1);
LineTo(gc_, x2, y2);
LineTo(gc_, x, y);
}
-void Fl_GDI_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_GDI_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
MoveToEx(gc_, x, y, 0L);
LineTo(gc_, x1, y1);
LineTo(gc_, x2, y2);
@@ -139,7 +139,7 @@ void Fl_GDI_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2,
LineTo(gc_, x, y);
}
-void Fl_GDI_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_GDI_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
POINT p[3];
p[0].x = x; p[0].y = y;
p[1].x = x1; p[1].y = y1;
@@ -148,7 +148,7 @@ void Fl_GDI_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y
Polygon(gc_, p, 3);
}
-void Fl_GDI_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_GDI_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
POINT p[4];
p[0].x = x; p[0].y = y;
p[1].x = x1; p[1].y = y1;
@@ -244,8 +244,10 @@ void Fl_GDI_Graphics_Driver::pop_clip() {
void Fl_GDI_Graphics_Driver::restore_clip() {
fl_clip_state_number++;
if (gc_) {
- Fl_Region r = rstack[rstackptr];
- SelectClipRgn(gc_, r); // if r is NULL, clip is automatically cleared
+ HRGN r = NULL;
+ if (rstack[rstackptr]) r = scale_clip(scale_);
+ SelectClipRgn(gc_, rstack[rstackptr]); // if region is NULL, clip is automatically cleared
+ if (r) unscale_clip(r);
}
}
diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
index e4ce856b1..ee817bf4f 100644
--- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
+++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
@@ -32,14 +32,6 @@
#include <FL/math.h>
-void Fl_GDI_Graphics_Driver::transformed_vertex(double xf, double yf) {
- transformed_vertex0(int(rint(xf)), int(rint(yf)));
-}
-
-void Fl_GDI_Graphics_Driver::vertex(double x,double y) {
- transformed_vertex0(int(x*m.a + y*m.c + m.x), int(x*m.b + y*m.d + m.y));
-}
-
void Fl_GDI_Graphics_Driver::end_points() {
for (int i=0; i<n; i++) SetPixel(gc_, p[i].x, p[i].y, fl_RGB());
}
@@ -54,7 +46,7 @@ void Fl_GDI_Graphics_Driver::end_line() {
void Fl_GDI_Graphics_Driver::end_loop() {
fixloop();
- if (n>2) transformed_vertex((int)p[0].x, (int)p[0].y);
+ if (n>2) transformed_vertex0(p[0].x, p[0].y);
end_line();
}
@@ -79,7 +71,7 @@ void Fl_GDI_Graphics_Driver::begin_complex_polygon() {
void Fl_GDI_Graphics_Driver::gap() {
while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
if (n > gap_+2) {
- transformed_vertex((int)p[gap_].x, (int)p[gap_].y);
+ transformed_vertex0(p[gap_].x, p[gap_].y);
counts[numcount++] = n-gap_;
gap_ = n;
} else {
@@ -99,15 +91,7 @@ void Fl_GDI_Graphics_Driver::end_complex_polygon() {
}
}
-// shortcut the closed circles so they use XDrawArc:
-// warning: these do not draw rotated ellipses correctly!
-// See fl_arc.c for portable version.
-
-void Fl_GDI_Graphics_Driver::circle(double x, double y,double r) {
- double xt = transform_x(x,y);
- double yt = transform_y(x,y);
- double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
- double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+void Fl_GDI_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
int llx = (int)rint(xt-rx);
int w = (int)rint(xt+rx)-llx;
int lly = (int)rint(yt-ry);
diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
index 5e0b636f5..e55e69583 100644
--- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
+++ b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
@@ -27,7 +27,6 @@
#include <windows.h>
class Fl_GDI_Image_Surface_Driver : public Fl_Image_Surface_Driver {
- friend class Fl_Image_Surface;
virtual void end_current_(Fl_Surface_Device*);
public:
Fl_Surface_Device *previous;
@@ -51,8 +50,14 @@ Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, i
Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, 0) {
previous = 0;
+ float d = fl_graphics_driver->scale();
+ if (!off && d != 1 && high_res) {
+ w = int(w*d);
+ h = int(h*d);
+ }
offscreen = off ? off : CreateCompatibleBitmap( (fl_graphics_driver->gc() ? (HDC)fl_graphics_driver->gc() : fl_GetDC(0) ) , w, h);
driver(new Fl_GDI_Graphics_Driver);
+ if (d != 1 && high_res) driver()->scale(d);
_sgc = NULL;
}
diff --git a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
index 21bcf65df..c65c6a3a1 100644
--- a/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
+++ b/src/drivers/OpenGL/Fl_OpenGL_Display_Device.cxx
@@ -3,7 +3,7 @@
//
// implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2014 by Bill Spitzak and others.
+// Copyright 2010-2017 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
@@ -94,6 +94,8 @@ Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window* glw,
# pragma message "FL_PORTING: check whether the default Fl_OpenGL_Display_Device::capture_gl_rectangle() works for your platform"
#endif
+#include <FL/Fl_Screen_Driver.H>
+#include <FL/Fl_Window_Driver.H>
Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w, int h)
/* captures a rectangle of a Fl_Gl_Window window, and returns it as a RGB image
*/
@@ -106,6 +108,12 @@ Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw,
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ //
+ int ns = glw->driver()->screen_num();
+ float s = Fl::screen_driver()->scale(ns);
+ if (s != 1) {
+ x *= s; y *= s; w *= s; h *= s;
+ }
// Read a block of pixels from the frame buffer
int mByteWidth = w * 3;
mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
index 5c016ce73..ff2688bcf 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
@@ -78,6 +78,13 @@ public:
virtual void disable_im();
virtual void open_display();
virtual void offscreen_size(Fl_Offscreen off, int &width, int &height);
+
+ 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 float desktop_scale_factor();
+private:
+ float scale_;
};
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index 219c1d1d6..e9ca9d2fb 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -617,6 +617,9 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(uchar *p, // I - Pixel buffer or NU
/** Returns the current desktop scaling factor (1.75 for example)
*/
float Fl_WinAPI_Screen_Driver::desktop_scaling_factor() {
+#ifdef FLTK_HIDPI_SUPPORT
+ return 1;// this becomes useless if FLTK app are made DPI-aware by calling SetProcessDpiAwareness()
+#else
// Compute the global desktop scaling factor: 1, 1.25, 1.5, 1.75, etc...
// This factor can be set in Windows 10 by
// "Change the size of text, apps and other items" in display settings.
@@ -636,6 +639,7 @@ float Fl_WinAPI_Screen_Driver::desktop_scaling_factor() {
float scaling = dhr/float(hr);
scaling = int(scaling * 100 + 0.5)/100.; // round to 2 digits after decimal point
return scaling;
+#endif // FLTK_HIDPI_SUPPORT
}
void Fl_WinAPI_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &height)
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
index eb8e13b33..1d496edff 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Window_Driver.cxx
@@ -261,10 +261,11 @@ static HRGN bitmap2region(Fl_Image* image) {
void Fl_WinAPI_Window_Driver::draw_begin()
{
if (shape_data_) {
- if ((shape_data_->lw_ != w() || shape_data_->lh_ != h()) && shape_data_->shape_) {
+ float s = Fl::screen_driver()->scale(screen_num());
+ if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) {
// size of window has changed since last time
- shape_data_->lw_ = w();
- shape_data_->lh_ = h();
+ shape_data_->lw_ = s*w();
+ shape_data_->lh_ = s*h();
Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
HRGN region = bitmap2region(temp);
SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed
@@ -385,6 +386,7 @@ void Fl_WinAPI_Window_Driver::make_current() {
#endif // USE_COLORMAP
fl_graphics_driver->clip_region(0);
+fl_graphics_driver->scale(Fl::screen_driver()->scale(0));
}
void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) {
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.H b/src/drivers/X11/Fl_X11_Screen_Driver.H
index 2be26a1ee..8ccf056da 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.H
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.H
@@ -4,7 +4,7 @@
// Definition of X11 Screen interface
// for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 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
@@ -39,13 +39,27 @@ protected:
short y_org;
short width;
short height;
+#if USE_XFT
+ float scale;
+#endif
} FLScreenInfo;
FLScreenInfo screens[MAX_SCREENS];
float dpi[MAX_SCREENS][2];
int poll_or_select();
int poll_or_select_with_delay(double time_to_wait);
+ int get_mouse_unscaled(int &xx, int &yy);
public:
+#if USE_XFT // scaling does not work without Xft
+ virtual APP_SCALING_CAPABILITY rescalable() { return PER_SCREEN_APP_SCALING; }
+ virtual float scale(int n) {return screens[n].scale;}
+ virtual void scale(int n, float f) { screens[n].scale = f;}
+ virtual float desktop_scale_factor();
+ int screen_num_unscaled(int x, int y);
+ int screen_num_unscaled(int x, int y, int w, int h);
+ virtual void screen_xywh(int &X, int &Y, int &W, int &H);
+#endif
+
static int ewmh_supported();
static void copy_image(const unsigned char* data, int W, int H, int destination);
// --- display management
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
index 7095ea948..490189673 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
@@ -3,7 +3,7 @@
//
// Definition of X11 Screen interface
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -20,9 +20,14 @@
#include "../../config_lib.h"
#include "Fl_X11_Screen_Driver.H"
#include "../Xlib/Fl_Font.H"
+#include "Fl_X11_Window_Driver.H"
+#include "../Xlib/Fl_Xlib_Graphics_Driver.H"
#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/fl_ask.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Image_Surface.H>
+#include <FL/Fl_Tooltip.H>
#include <sys/time.h>
@@ -229,10 +234,15 @@ void Fl_X11_Screen_Driver::init_workarea()
}
else
{
- fl_workarea_xywh[0] = (int)xywh[0];
- fl_workarea_xywh[1] = (int)xywh[1];
- fl_workarea_xywh[2] = (int)xywh[2];
- fl_workarea_xywh[3] = (int)xywh[3];
+#if USE_XFT
+ float s = screens[0].scale;
+#else
+ float s = 1;
+#endif
+ fl_workarea_xywh[0] = xywh[0] / s;
+ fl_workarea_xywh[1] = xywh[1] / s;
+ fl_workarea_xywh[2] = xywh[2] / s;
+ fl_workarea_xywh[3] = xywh[3] / s;
}
if ( xywh ) { XFree(xywh); xywh = 0; }
}
@@ -316,7 +326,9 @@ void Fl_X11_Screen_Driver::init() {
screens[i].y_org = xsi[i].y_org;
screens[i].width = xsi[i].width;
screens[i].height = xsi[i].height;
-
+#if USE_XFT
+ screens[i].scale = 1;
+#endif
if (dpi_by_randr) {
dpi[i][0] = dpih;
dpi[i][1] = dpiv;
@@ -341,7 +353,9 @@ void Fl_X11_Screen_Driver::init() {
screens[i].y_org = 0;
screens[i].width = DisplayWidth(fl_display, i);
screens[i].height = DisplayHeight(fl_display, i);
-
+#if USE_XFT
+ screens[i].scale = 1;
+#endif
if (dpi_by_randr) {
dpi[i][0] = dpih;
dpi[i][1] = dpiv;
@@ -353,6 +367,17 @@ void Fl_X11_Screen_Driver::init() {
}
}
}
+/*#if __APPLE_CC__ && USE_XFT // TMP simulate 2 screens under XQuartz
+ if (strstr(getenv("DISPLAY"), "xquartz")) {
+ num_screens = 2;
+ screens[1].x_org = screens[0].width/2;;
+ screens[1].y_org = screens[0].y_org;
+ screens[1].width = screens[0].width = screens[0].width/2;
+ screens[1].height = screens[0].height;
+ screens[1].scale = screens[0].scale = 1;
+ }
+#endif*/
+ init_workarea();
}
@@ -379,10 +404,15 @@ void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
n = 0;
if (num_screens > 0) {
- X = screens[n].x_org;
- Y = screens[n].y_org;
- W = screens[n].width;
- H = screens[n].height;
+#if USE_XFT
+ float s = screens[n].scale;
+#else
+ float s = 1;
+#endif
+ X = screens[n].x_org / s;
+ Y = screens[n].y_org / s;
+ W = screens[n].width / s;
+ H = screens[n].height / s;
}
}
@@ -765,26 +795,29 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i
image = 0;
# endif // __sgi
+ float s = Fl_Surface_Device::surface()->driver()->scale();
+
if (!image) {
// fetch absolute coordinates
int dx, dy, sx, sy, sw, sh;
Window child_win;
Fl_Window *win;
- if (allow_outside) win = (Fl_Window*)1;
+ if (allow_outside) win = Fl_Window::current();
else win = fl_find(fl_window);
if (win) {
XTranslateCoordinates(fl_display, fl_window,
- RootWindow(fl_display, fl_screen), X, Y, &dx, &dy, &child_win);
+ RootWindow(fl_display, fl_screen), X*s, Y*s, &dx, &dy, &child_win);
+ dx /= s; dy /= s;
// screen dimensions
- Fl::screen_xywh(sx, sy, sw, sh, fl_screen);
+ Fl::screen_xywh(sx, sy, sw, sh, win->driver()->screen_num());
}
if (!win || (dx >= sx && dy >= sy && dx + w <= sx+sw && dy + h <= sy+sh)) {
// the image is fully contained, we can use the traditional method
// 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, X, Y, w, h, AllPlanes, ZPixmap);
+ image = XGetImage(fl_display, fl_window, int(X*s), int(Y*s), w*s < 1 ? 1 : int(w*s), h*s < 1 ? 1 : int(h*s), AllPlanes, ZPixmap);
XSetErrorHandler(old_handler);
} else {
// image is crossing borders, determine visible region
@@ -795,17 +828,17 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i
// allocate the image
int bpp = fl_visual->depth + ((fl_visual->depth / 8) % 2) * 8;
- char* buf = (char*)malloc(bpp / 8 * w * h);
+ char* buf = (char*)malloc(bpp / 8 * int(w*s) * int(h*s));
image = XCreateImage(fl_display, fl_visual->visual,
- fl_visual->depth, ZPixmap, 0, buf, w, h, bpp, 0);
+ fl_visual->depth, ZPixmap, 0, buf, w*s, h*s, bpp, 0);
if (!image) {
if (buf) free(buf);
return 0;
}
XErrorHandler old_handler = XSetErrorHandler(xgetimageerrhandler);
- XImage *subimg = XGetSubImage(fl_display, fl_window, X + noffx, Y + noffy,
- nw, nh, AllPlanes, ZPixmap, image, noffx, noffy);
+ XImage *subimg = XGetSubImage(fl_display, fl_window, (X + noffx)*s, (Y + noffy)*s,
+ nw*s, nh*s, AllPlanes, ZPixmap, image, noffx*s, noffy*s);
XSetErrorHandler(old_handler);
if (!subimg) {
XDestroyImage(image);
@@ -815,6 +848,10 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(uchar *p, int X, int Y, i
}
if (!image) return 0;
+ if (s != 1) {
+ w = w*s < 1 ? 1 : int(w*s);
+ h = h*s < 1 ? 1 : int(h*s);
+ }
#ifdef DEBUG
printf("width = %d\n", image->width);
@@ -1154,6 +1191,244 @@ void Fl_X11_Screen_Driver::offscreen_size(Fl_Offscreen off, int &width, int &hei
height = (int)h;
}
+#if USE_XFT
+int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y)
+{
+ int screen = 0;
+ if (num_screens < 0) init();
+
+ for (int i = 0; i < num_screens; i ++) {
+ int sx = screens[i].x_org, sy = screens[i].y_org, sw = screens[i].width, sh = screens[i].height;
+ if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) {
+ screen = i;
+ break;
+ }
+ }
+ return screen;
+}
+
+int Fl_X11_Screen_Driver::screen_num_unscaled(int x, int y, int w, int h)
+{
+ int best_screen = 0;
+ float best_intersection = 0.;
+ if (num_screens < 0) init();
+ for (int i = 0; i < num_screens; i++) {
+ float sintersection = fl_intersection(x, y, w, h, screens[i].x_org, screens[i].y_org,
+ screens[i].width, screens[i].height);
+ if (sintersection > best_intersection) {
+ best_screen = i;
+ best_intersection = sintersection;
+ }
+ }
+ return best_screen;
+}
+#endif
+
+#if USE_XFT
+void Fl_X11_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H)
+{
+ int xx, yy;
+ int ns = get_mouse_unscaled(xx,yy);
+ float s = screens[ns].scale;
+ X = screens[ns].x_org / s;
+ Y = screens[ns].y_org / s;
+ W = screens[ns].width / s;
+ H = screens[ns].height / s;
+}
+
+
+#if HAVE_DLSYM && HAVE_DLFCN_H
+
+// returns true when schema is among the list of available schemas
+static bool is_schema_valid(const char *schema, const char **known) {
+ int i = 0;
+ while (known[i]) {
+ if (strcmp(known[i++], schema) == 0) return true;
+ }
+ return false;
+}
+
+
+/*
+ returns true under Ubuntu or Debian or FreeBSD and when the gnome scaling value has been found
+
+ Ubuntu:
+ Change the gnome scaling factor with:
+ System Settings ==> Displays ==> Scale for menu and title bars
+ Read the current gnome scaling factor with:
+ gsettings get com.ubuntu.user-interface scale-factor
+ Example value: {'VGA-0': 10}
+ Its type is "a{si}". This value should be divided by 8 to get the correct scaling factor.
+
+ Debian or FreeBSD :
+ Change the gnome scaling factor with:
+ Tweak tools ==> Windows ==> Window scaling
+ Read the current gnome scaling factor with:
+ gsettings get org.gnome.settings-daemon.plugins.xsettings overrides
+ Example value: {'Gdk/WindowScalingFactor': <2>}
+ Its type is "a{sv}" and v itself is of type i
+
+ It's also possible to use 'Tweak tools' under Ubuntu. With the standard Ubuntu desktop,
+ the modified value goes to "org.gnome.settings-daemon.plugins.xsettings" as above.
+
+ With Gnome session flashback under Ubuntu 'Tweak tools' puts the scaling value (1 or 2)
+ in "org.gnome.desktop.interface scaling-factor".
+ Read the current gnome scaling factor with:
+ gsettings get org.gnome.desktop.interface scaling-factor
+ Its type is "u"
+
+ Thus, under Ubuntu, we read the 3 possible factor values and
+ return the first value different from 1 to get the scaling factor.
+
+ =================================================================================================
+ Ubuntu | default ubuntu desktop | System Settings => Displays => Scale for menu and title bars
+ com.ubuntu.user-interface scale-factor
+ -----------------------
+ Tweak tools => Windows => Window scaling
+ org.gnome.settings-daemon.plugins.xsettings overrides
+ -----------------------
+ Gnome session flashback | System Settings => Displays => Scale for menu and title bars
+ no effect
+ -----------------------
+ Tweak tools => Windows => Window scaling
+ org.gnome.desktop.interface scaling-factor
+ =================================================================================================
+ Debian or FreeBSD | gnome | Tweak tools => Windows => Window scaling
+ org.gnome.settings-daemon.plugins.xsettings overrides
+ =================================================================================================
+ */
+static bool gnome_scale_factor(float& factor) {
+ // define types needed for dynamic lib functions
+ typedef const char** (*g_settings_list_schemas_ftype)(void);
+ typedef void* (*g_settings_new_ftype)(const char *);
+ typedef void* (*g_settings_get_value_ftype)(void *settings, const char *key);
+ typedef void (*g_variant_get_ftype)(void *value, const char *format_string, ...);
+ typedef bool (*g_variant_iter_loop_ftype)(void *iter, const char *format_string, ...);
+ typedef void (*pter_ftype)(void*);
+ //typedef void* (*g_variant_get_type_ftype)(void *variant);
+
+ // open dynamic libs
+ void *glib = dlopen("libglib-2.0.so", RTLD_LAZY);
+ void *gio = dlopen("libgio-2.0.so", RTLD_LAZY);
+ void *gobj = dlopen("libgobject-2.0.so", RTLD_LAZY);
+ //fprintf(stderr,"glib=%p gio=%p gobj=%p\n",glib,gio,gobj);
+ if (!glib || !gio || !gobj) return false;
+
+ bool ubuntu = false;
+ // determine whether we run Ubuntu
+ char line[400] = "";
+ FILE *in = fopen("/proc/version", "r");
+ if (in) {
+ fgets(line, sizeof(line), in);
+ fclose(in);
+ if (strstr(line, "Ubuntu")) ubuntu = true;
+ }
+
+ // define pters to used functions
+ g_settings_list_schemas_ftype g_settings_list_schemas_f = (g_settings_list_schemas_ftype)dlsym(gio, "g_settings_list_schemas"); // 2.26
+ g_settings_new_ftype g_settings_new_f = (g_settings_new_ftype)dlsym(gio, "g_settings_new"); // 2.26
+ g_settings_get_value_ftype g_settings_get_value_f =
+ (g_settings_get_value_ftype)dlsym(gio, "g_settings_get_value"); // 2.26
+ if (!g_settings_list_schemas_f || !g_settings_new_f || !g_settings_get_value_f) return false;
+ g_variant_get_ftype g_variant_get_f = (g_variant_get_ftype)dlsym(glib, "g_variant_get"); //2.24
+ g_variant_iter_loop_ftype g_variant_iter_loop_f = (g_variant_iter_loop_ftype)dlsym(glib, "g_variant_iter_loop"); // 2.24
+ pter_ftype g_variant_iter_free_f = (pter_ftype)dlsym(glib, "g_variant_iter_free"); // 2.24
+ pter_ftype g_object_unref_f = (pter_ftype)dlsym(gobj, "g_object_unref");
+ pter_ftype g_variant_unref_f = (pter_ftype)dlsym(glib, "g_variant_unref"); // 2.24
+ //g_variant_get_type_ftype g_variant_get_type_f = (g_variant_get_type_ftype)dlsym(glib, "g_variant_get_type"); // 2.24
+
+ // call dynamic lib functions
+ const char **known = g_settings_list_schemas_f(); // list of available GSettings schemas
+ const char *schema;
+ float ubuntu_f = 1, ubuntu_desktop_f = 1, gnome_f = 1;
+ bool found = false;
+
+ if (ubuntu) {
+ schema = "com.ubuntu.user-interface";
+ if (is_schema_valid(schema, known)) {
+ found = true;
+ void *gset = g_settings_new_f(schema);
+ void *gvar = g_settings_get_value_f(gset, "scale-factor");
+ void *iter;
+ char str[10], *str2; int v=8, v2;
+ g_variant_get_f(gvar, "a{si}", &iter);
+ while (g_variant_iter_loop_f(iter, "{si}", &str2, &v2)) { // read the last couple of values
+ strcpy(str, str2); v = v2;
+ }
+ ubuntu_f = v/8.;
+ printf("com.ubuntu.user-interface scale-factor name=%s value=%d factor=%g\n", str, v, ubuntu_f);
+ g_variant_iter_free_f(iter);
+ g_variant_unref_f(gvar);
+ g_object_unref_f(gset);
+ if (ubuntu_f != 1) {
+ factor = ubuntu_f;
+ return true;
+ }
+ }
+ schema = "org.gnome.desktop.interface";
+ if (is_schema_valid(schema, known)) {
+ found = true;
+ void *gset = g_settings_new_f(schema);
+ void *gvar = g_settings_get_value_f(gset, "scaling-factor");
+ unsigned v;
+ g_variant_get_f(gvar, "u", &v);
+ ubuntu_desktop_f = v;
+ printf("org.gnome.desktop.interface scaling-factor value=%u factor=%g\n", v, ubuntu_desktop_f);
+ g_variant_unref_f(gvar);
+ g_object_unref_f(gset);
+ if (ubuntu_desktop_f != 1) {
+ factor = ubuntu_desktop_f;
+ return true;
+ }
+ }
+ }
+ schema = "org.gnome.settings-daemon.plugins.xsettings";
+ if (is_schema_valid(schema, known)) {
+ void *gset = g_settings_new_f(schema);
+ void *gvar = g_settings_get_value_f(gset, "overrides");
+ void *iter;
+ char *str; int v;
+ //str = (char*)g_variant_get_type_f(gvar); // -> "a{sv}"
+ g_variant_get_f(gvar, "a{sv}", &iter);
+ g_variant_unref_f(gvar);
+ gvar = NULL;
+ while (g_variant_iter_loop_f(iter, "{sv}", &str, &gvar)) {
+ if (strstr(str, "WindowScalingFactor") == NULL) continue;
+ found = true;
+ //str = (char*)g_variant_get_type_f(gvar); // -> "i"
+ g_variant_get_f(gvar, "i", &v);
+ gnome_f = v;
+ printf("org.gnome.settings-daemon.plugins.xsettings overrides name=%s value=%d factor=%g\n", str, v, gnome_f);
+ free(str);
+ break;
+ }
+ g_variant_iter_free_f(iter);
+ if (gvar) g_variant_unref_f(gvar);
+ g_object_unref_f(gset);
+ }
+ if (!found) return false;
+ //factor = ubuntu_f * ubuntu_desktop_f * gnome_f;
+ factor = gnome_f;
+ return true;
+}
+#endif // HAVE_DLSYM && HAVE_DLFCN_H
+
+
+// return the desktop's default scaling value
+float Fl_X11_Screen_Driver::desktop_scale_factor()
+{
+ float factor = 1;
+#if HAVE_DLSYM && HAVE_DLFCN_H
+ gnome_scale_factor(factor);
+#endif
+ return factor;
+}
+
+
+
+
+#endif // USE_XFT
+
//
// End of "$Id$".
//
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H
index 4de4e3680..0893d28c0 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.H
+++ b/src/drivers/X11/Fl_X11_Window_Driver.H
@@ -4,7 +4,7 @@
// Definition of X11 window driver
// for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2016 by Bill Spitzak and others.
+// Copyright 2010-2017 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
@@ -27,6 +27,7 @@
#include <FL/Fl_Window_Driver.H>
#include <config.h> // for USE_XDBE
+#include <FL/x.H> // for Cursor
class Fl_Bitmap;
/*
@@ -56,6 +57,8 @@ struct Fl_Window_Driver::shape_data_type {
class FL_EXPORT Fl_X11_Window_Driver : public Fl_Window_Driver
{
friend class Fl_X;
+ friend class Fl_X11_Screen_Driver;
+ friend int fl_handle(const XEvent&);
private:
struct icon_data {
@@ -63,6 +66,17 @@ private:
Fl_RGB_Image **icons;
int count;
} *icon_;
+ Cursor current_cursor_;
+#if USE_XFT
+ // --- support for screen-specific scaling factors
+ struct type_for_resize_window_between_screens {
+ int screen;
+ bool busy;
+ };
+ static type_for_resize_window_between_screens data_for_resize_window_between_screens_;
+ int screen_num_;
+ void screen_num(int n) { screen_num_ = n; }
+#endif // USE_XFT
void decorated_win_size(int &w, int &h);
void combine_mask();
void shape_bitmap_(Fl_Image* b);
@@ -79,7 +93,11 @@ public:
Fl_X11_Window_Driver(Fl_Window*);
virtual ~Fl_X11_Window_Driver();
static inline Fl_X11_Window_Driver* driver(Fl_Window *w) {return (Fl_X11_Window_Driver*)w->driver();}
-
+#if USE_XFT
+ virtual int screen_num();
+ static void resize_after_screen_change(void *data);
+#endif // USE_XFT
+
// --- window data
virtual int decorated_w();
virtual int decorated_h();
diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx
index f10ed307a..a8952eed3 100644
--- a/src/drivers/X11/Fl_X11_Window_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx
@@ -3,7 +3,7 @@
//
// Definition of X11 window driver.
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -112,11 +112,11 @@ void Fl_X11_Window_Driver::destroy_double_buffer() {
#if USE_XDBE
if (can_xdbe()) {
XdbeDeallocateBackBufferName(fl_display, other_xid);
- other_xid = 0;
}
else
#endif // USE_XDBE
- Fl_Window_Driver::destroy_double_buffer();
+ fl_delete_offscreen(other_xid);
+ other_xid = 0;
}
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
@@ -130,6 +130,10 @@ Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win)
{
icon_ = new icon_data;
memset(icon_, 0, sizeof(icon_data));
+ current_cursor_ = None;
+#if USE_XFT
+ screen_num_ = -1;
+#endif
}
@@ -160,8 +164,10 @@ void Fl_X11_Window_Driver::decorated_win_size(int &w, int &h)
if (status == 0 || root == parent) return;
XWindowAttributes attributes;
XGetWindowAttributes(fl_display, parent, &attributes);
- w = attributes.width;
- h = attributes.height;
+ int nscreen = screen_num();
+ float s = Fl::screen_driver()->scale(nscreen);
+ w = attributes.width / s;
+ h = attributes.height / s;
}
@@ -196,7 +202,9 @@ void Fl_X11_Window_Driver::take_focus()
void Fl_X11_Window_Driver::draw_begin()
{
if (shape_data_) {
- if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) {
+ int nscreen = screen_num();
+ float s = Fl::screen_driver()->scale(nscreen);
+ if (( shape_data_->lw_ != int(s*w()) || shape_data_->lh_ != int(s*h()) ) && shape_data_->shape_) {
// size of window has changed since last time
combine_mask();
}
@@ -324,8 +332,9 @@ void Fl_X11_Window_Driver::combine_mask()
#endif
}
if (!XShapeCombineMask_f) return;
- shape_data_->lw_ = w();
- shape_data_->lh_ = h();
+ float s = Fl::screen_driver()->scale(screen_num());
+ shape_data_->lw_ = w()*s;
+ shape_data_->lh_ = h()*s;
Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(pWindow),
(const char*)*temp->data(),
@@ -400,25 +409,30 @@ void Fl_X11_Window_Driver::capture_titlebar_and_borders(Fl_Shared_Image*& top, F
if (n) XFree(children);
if (!do_it) wsides = htop = 0;
int hbottom = wsides;
+ float s = Fl::screen_driver()->scale(screen_num());
+ 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);
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);
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);
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);
if (r_bottom) {
bottom = Fl_Shared_Image::get(r_bottom);
- }
- }
+ bottom->scale(w() + 2*wsides, wsides, 0, 1);
+ } }
fl_window = from;
Fl_Surface_Device::pop_current();
}
@@ -432,6 +446,9 @@ void Fl_X11_Window_Driver::make_current() {
}
fl_window = fl_xid(pWindow);
fl_graphics_driver->clip_region(0);
+#if USE_XFT
+ ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num()));
+#endif
#ifdef FLTK_USE_CAIRO
// update the cairo_t context
@@ -460,6 +477,7 @@ void Fl_X11_Window_Driver::hide() {
if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
# if USE_XFT
Fl_Xlib_Graphics_Driver::destroy_xft_draw(ip->xid);
+ screen_num_ = -1;
# endif
// this test makes sure ip->xid has not been destroyed already
if (ip->xid) XDestroyWindow(fl_display, ip->xid);
@@ -650,8 +668,9 @@ void Fl_X11_Window_Driver::erase_menu() {
int Fl_X11_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
void (*draw_area)(void*, int,int,int,int), void* data)
{
+ float s = Fl::screen_driver()->scale(screen_num());
XCopyArea(fl_display, fl_window, fl_window, (GC)fl_graphics_driver->gc(),
- src_x, src_y, src_w, src_h, dest_x, dest_y);
+ int(src_x*s), int(src_y*s), int(src_w*s), int(src_h*s), int(dest_x*s), int(dest_y*s));
// we have to sync the display and get the GraphicsExpose events! (sigh)
for (;;) {
XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
@@ -670,6 +689,40 @@ Fl_X *Fl_X11_Window_Driver::makeWindow()
return Fl_X::i(pWindow);
}
+
+#if USE_XFT
+
+Fl_X11_Window_Driver::type_for_resize_window_between_screens Fl_X11_Window_Driver::data_for_resize_window_between_screens_ = {0, false};
+
+void Fl_X11_Window_Driver::resize_after_screen_change(void *data) {
+ Fl_Window *win = (Fl_Window*)data;
+ int oldx, oldy;
+ XWindowAttributes actual;
+ XGetWindowAttributes(fl_display, fl_xid(win), &actual);
+ Window cr;
+ XTranslateCoordinates(fl_display, fl_xid(win), actual.root, 0, 0, &oldx, &oldy, &cr);
+ win->hide();
+ float f = Fl::screen_driver()->scale(data_for_resize_window_between_screens_.screen);
+ Fl_X11_Window_Driver::driver(win)->screen_num(data_for_resize_window_between_screens_.screen);
+ win->position(oldx/f, oldy/f);
+ win->driver()->force_position(1);
+ Fl_Xlib_Graphics_Driver *d = (Fl_Xlib_Graphics_Driver*)Fl_Display_Device::display_device()->driver();
+ d->scale(f);
+ win->show();
+ win->wait_for_expose();
+ data_for_resize_window_between_screens_.busy = false;
+}
+
+
+int Fl_X11_Window_Driver::screen_num() {
+ if (pWindow->parent()) {
+ screen_num_ = pWindow->top_window()->driver()->screen_num();
+ }
+ return screen_num_ >= 0 ? screen_num_ : 0;
+}
+#endif // USE_XFT
+
+
//
// End of "$Id$".
//
diff --git a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
index 138564600..b96a4f410 100644
--- a/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Copy_Surface_Driver.cxx
@@ -51,6 +51,8 @@ Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int
Fl_Xlib_Copy_Surface_Driver::Fl_Xlib_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) {
driver(new Fl_Xlib_Graphics_Driver());
+ float s = Fl_Graphics_Driver::default_driver().scale();
+ ((Fl_Xlib_Graphics_Driver*)driver())->scale(s);
oldwindow = fl_window;
xid = fl_create_offscreen(w,h);
driver()->push_no_clip();
@@ -65,10 +67,10 @@ 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);
- unsigned char *data = fl_read_image(NULL,0,0,width,height,0);
+ Fl_RGB_Image *rgb = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
if (need_push) Fl_Surface_Device::pop_current();
- Fl_X11_Screen_Driver::copy_image(data, width, height, 1);
- delete[] data;
+ Fl_X11_Screen_Driver::copy_image(rgb->array, rgb->w(), rgb->h(), 1);
+ delete rgb;
fl_delete_offscreen(xid);
delete driver();
}
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
index e71eab3cf..d1f6f3fc9 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H
@@ -43,7 +43,7 @@ struct _XRegion {
#endif // HAVE_X11_XREGION_H
#if USE_PANGO
-#include <pango/pangoxft.h>
+#include <pango/pango.h>
#endif
@@ -52,11 +52,27 @@ struct _XRegion {
*
This class is implemented only on the Xlib platform.
*/
-class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Graphics_Driver {
+class FL_EXPORT Fl_Xlib_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
private:
int offset_x_, offset_y_; // translation between user and graphical coordinates: graphical = user + offset
unsigned depth_; // depth of translation stack
int stack_x_[20], stack_y_[20]; // translation stack allowing cumulative translations
+ int line_delta_;
+protected:
+ virtual void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ virtual void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ virtual void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy);
+ virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
+ virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
+ virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
+ virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
+#if HAVE_XRENDER
+ virtual int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
+ int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP);
+#endif
+ virtual int height_unscaled();
+ virtual int descent_unscaled();
+ virtual Region scale_clip(float f);
#if USE_XFT
void drawUCS4(const void *str, int n, int x, int y);
#endif
@@ -65,16 +81,11 @@ private:
static PangoContext *pctxt_;
static PangoFontMap *pfmap_;
static PangoLayout *playout_;
-protected:
PangoFontDescription *pfd_;
void do_draw(int from_right, const char *str, int n, int x, int y);
static PangoContext *context();
static void init_built_in_fonts();
#endif
-#if HAVE_XRENDER
- int scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP);
-#endif
-protected:
static GC gc_;
uchar **mask_bitmap_;
uchar **mask_bitmap() {return mask_bitmap_;}
@@ -93,6 +104,7 @@ public:
virtual ~Fl_Xlib_Graphics_Driver();
void translate_all(int dx, int dy);
void untranslate_all();
+ virtual void scale(float f);
virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
virtual void *gc() { return gc_; }
virtual void gc(void *value);
@@ -104,51 +116,43 @@ public:
// --- bitmap stuff
Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
void delete_bitmask(Fl_Bitmask bm);
- void draw(const char* str, int n, int x, int y);
- void draw(int angle, const char *str, int n, int x, int y);
- void rtl_draw(const char* str, int n, int x, int y);
- void font(Fl_Font face, Fl_Fontsize size);
- void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
- void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
- void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
- void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
- void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
-#if HAVE_XRENDER
- int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
-#endif
+ virtual void draw_unscaled(const char* str, int n, int x, int y);
+ virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
+ virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
+ virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
- double width(const char *str, int n);
- double width(unsigned int c);
- void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
- int height();
- int descent();
- void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+ virtual double width_unscaled(const char *str, int n);
+ virtual double width_unscaled(unsigned int c);
+ virtual void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
+ virtual Fl_Fontsize size_unscaled();
+ virtual void copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy);
+#if ! defined(FL_DOXYGEN)
+ void copy_offscreen_with_alpha(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
+#endif
void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
Fl_Region XRectangleRegion(int x, int y, int w, int h);
void XDestroyRegion(Fl_Region r);
protected:
- virtual void transformed_vertex0(short x, short y);
+ virtual void transformed_vertex0(float x, float y);
void fixloop();
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx
- void point(int x, int y);
- void rect(int x, int y, int w, int h);
- void rectf(int x, int y, int w, int h);
- void line(int x, int y, int x1, int y1);
- void line(int x, int y, int x1, int y1, int x2, int y2);
- void xyline(int x, int y, int x1);
- void xyline(int x, int y, int x1, int y2);
- void xyline(int x, int y, int x1, int y2, int x3);
- void yxline(int x, int y, int y1);
- void yxline(int x, int y, int y1, int x2);
- void yxline(int x, int y, int y1, int x2, int y3);
- void loop(int x0, int y0, int x1, int y1, int x2, int y2);
- void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
- void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
+ virtual void point_unscaled(float x, float y);
+ virtual void rect_unscaled(float x, float y, float w, float h);
+ virtual void rectf_unscaled(float x, float y, float w, float h);
+ virtual void line_unscaled(float x, float y, float x1, float y1);
+ virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
+ virtual void xyline_unscaled(float x, float y, float x1);
+ virtual void xyline_unscaled(float x, float y, float x1, float y2);
+ virtual void xyline_unscaled(float x, float y, float x1, float y2, float x3);
+ virtual void yxline_unscaled(float x, float y, float y1);
+ virtual void yxline_unscaled(float x, float y, float y1, float x2);
+ virtual void yxline_unscaled(float x, float y, float y1, float x2, float y3);
+ virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+ virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
+ virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
+ virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
// --- clipping
void push_clip(int x, int y, int w, int h);
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
@@ -156,25 +160,18 @@ protected:
void push_no_clip();
void pop_clip();
void restore_clip();
- // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
void begin_complex_polygon();
- void transformed_vertex(double xf, double yf);
- void vertex(double x, double y);
void end_points();
void end_line();
void end_loop();
void end_polygon();
void end_complex_polygon();
void gap();
- void circle(double x, double y, double r);
- // --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
- // using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
+ virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
// --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
- void arc(int x, int y, int w, int h, double a1, double a2);
- void pie(int x, int y, int w, int h, double a1, double a2);
- // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
- void line_style(int style, int width=0, char* dashes=0);
- // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
+ virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
+ virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
+ virtual void line_style_unscaled(int style, float width, char* dashes);
void color(Fl_Color c);
void set_color(Fl_Color i, unsigned int c);
void free_color(Fl_Color i, int overlay);
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
index 6d6cff681..741ceb89a 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.cxx
@@ -3,7 +3,7 @@
//
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -57,6 +57,7 @@ Fl_Xlib_Graphics_Driver::Fl_Xlib_Graphics_Driver(void) {
p_size = 0;
p = NULL;
line_width_ = 0;
+ line_delta_ = 0;
#if USE_PANGO
pfd_ = pango_font_description_new();
Fl_Graphics_Driver::font(0, 0);
@@ -78,8 +79,30 @@ void Fl_Xlib_Graphics_Driver::gc(void *value) {
fl_gc = gc_;
}
-void Fl_Xlib_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) {
- XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::scale(float f) {
+#if USE_XFT
+ if (f != scale_) {
+ size_ = 0;
+ scale_ = f;
+ //fprintf(stderr, "scale=%.2f\n", scale_);
+ line_style(FL_SOLID); // scale also default line width
+ /* Scaling >= 2 transforms 1-pixel wide lines into wider lines.
+ X11 draws 2-pixel wide lines so that half of the line width is above or at left
+ of a 1-pixel wide line that would be drawn with the same coordinates.
+ Thus, if the line starts at coordinates (0,0) half of the line width is invisible.
+ Similarly, if the line ends at w()-1 the last pixel of the window is not drawn.
+ What is wanted when scale_ == 2 is a visible 2-pixel wide line in the first case,
+ and a line at the window's edge in the 2nd case.
+ Setting line_delta_ to 1 and offsetting all line, rectangle, text and clip
+ coordinates by line_delta_ achieves what is wanted until scale_ <= 3.5.
+ */
+ line_delta_ = (scale_ > 1.75 ? 1 : 0);
+ }
+#endif
+}
+
+void Fl_Xlib_Graphics_Driver::copy_offscreen_unscaled(float x, float y, float w, float h, Fl_Offscreen pixmap, float srcx, float srcy) {
+ XCopyArea(fl_display, pixmap, fl_window, gc_, srcx, srcy, w, h, x+offset_x_*scale_, y+offset_y_*scale_);
}
void Fl_Xlib_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
@@ -88,7 +111,8 @@ void Fl_Xlib_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y,
XUnionRectWithRegion(&R, r, r);
}
-void Fl_Xlib_Graphics_Driver::transformed_vertex0(short x, short y) {
+void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) {
+ short x = short(fx), y = short(fy);
if (!n || x != p[n-1].x || y != p[n-1].y) {
if (n >= p_size) {
p_size = p ? 2*p_size : 16;
@@ -205,6 +229,25 @@ void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
s->first = 0;
}
+
+Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
+ Region r = rstack[rstackptr];
+ if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0;
+ float delta = (f >= 2 ? f/3 : 0);
+ Region r2 = XCreateRegion();
+ XRectangle R;
+ for (int i = 0; i < r->numRects; i++) {
+ R.x = short((r->rects[i].x1 + offset_x_)*f-delta + line_delta_);
+ R.y = short((r->rects[i].y1 + offset_y_)*f-delta + line_delta_);
+ R.width = short(r->rects[i].x2*f) - short(r->rects[i].x1*f);
+ R.height = short(r->rects[i].y2*f) - short(r->rects[i].y1*f);
+ XUnionRectWithRegion(&R, r2, r2);
+ }
+ rstack[rstackptr] = r2;
+ return r;
+}
+
+
void Fl_Xlib_Graphics_Driver::translate_all(int dx, int dy) { // reversibly adds dx,dy to the offset between user and graphical coordinates
stack_x_[depth_] = offset_x_;
stack_y_[depth_] = offset_y_;
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
index b1a8cd10d..cd0b7915f 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_arci.cxx
@@ -3,7 +3,7 @@
//
// Arc (integer) drawing functions for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -26,15 +26,15 @@
\brief Utility functions for drawing circles using integers
*/
-void Fl_Xlib_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
+void Fl_Xlib_Graphics_Driver::arc_unscaled(float x,float y,float w,float h,double a1,double a2) {
if (w <= 0 || h <= 0) return;
- XDrawArc(fl_display, fl_window, gc_, x+offset_x_,y+offset_y_,w-1,h-1, int(a1*64),int((a2-a1)*64));
+ XDrawArc(fl_display, fl_window, gc_, int(x+offset_x_*scale_), int(y+offset_y_*scale_), int(w-1), int(h-1), int(a1*64),int((a2-a1)*64));
}
-void Fl_Xlib_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
+void Fl_Xlib_Graphics_Driver::pie_unscaled(float x,float y,float w,float h,double a1,double a2) {
if (w <= 0 || h <= 0) return;
- x += offset_x_;
- y += offset_y_;
+ x += offset_x_*scale_;
+ y += offset_y_*scale_;
XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
XFillArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64));
}
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
index a1da5a585..5123f6e02 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_x.cxx
@@ -3,7 +3,7 @@
//
// X11 font utilities for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -596,7 +596,7 @@ XFontStruct* Fl_XFont_On_Demand::value() {
return ptr;
}
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
if (fnum==-1) {
Fl_Graphics_Driver::font(0, 0);
return;
@@ -611,27 +611,32 @@ void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
}
}
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
else return -1;
}
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->font->descent;
else return -1;
}
-double Fl_Xlib_Graphics_Driver::width(const char* c, int n) {
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+ if (font_descriptor()) return size_;
+ return -1;
+}
+
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* c, int n) {
if (font_descriptor()) return (double) XUtf8TextWidth(font_descriptor()->font, c, n);
else return -1;
}
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
if (font_descriptor()) return (double) XUtf8UcsWidth(font_descriptor()->font, c);
else return -1;
}
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &W, int &H) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &W, int &H) {
if (font_gc != gc_) {
if (!font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
@@ -649,7 +654,7 @@ void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &d
// dy = fl_descent() - H;
}
-void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char* c, int n, int x, int y) {
if (font_gc != gc_) {
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
@@ -658,7 +663,7 @@ void Fl_Xlib_Graphics_Driver::draw(const char* c, int n, int x, int y) {
if (gc_) XUtf8DrawString(fl_display, fl_window, font_descriptor()->font, gc_, x+offset_x_, y+offset_y_, c, n);
}
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
static char warning = 0; // issue warning only once
if (!warning && angle != 0) {
warning = 1;
@@ -669,7 +674,7 @@ void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int
this->draw(str, n, (int)x, (int)y);
}
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
if (font_gc != gc_) {
if (!font_descriptor()) this->font(FL_HELVETICA, FL_NORMAL_SIZE);
font_gc = gc_;
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
index 48771d0a2..a2c655455 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_font_xft.cxx
@@ -3,7 +3,7 @@
//
// More font utilities for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -125,6 +125,30 @@ static Fl_Fontdesc built_in_table[] = {
Fl_Fontdesc* fl_fonts = built_in_table;
+Fl_Fontsize Fl_Xlib_Graphics_Driver::size_unscaled() {
+ return (Fl_Fontsize)(size_);
+}
+
+static void correct_extents (float scale_, int &dx, int &dy, int &w, int &h) {
+ if (int(scale_) == scale_) { // correct for extents non divisible by integral scale_
+ int delta = dx - int(dx/scale_)*scale_;
+ if (delta) {
+ dx -= delta; w += delta;
+ }
+ delta = -dy - int((-dy)/scale_)*scale_;
+ if (delta) {
+ dy -= delta; h += delta;
+ }
+ delta = h - int(h/scale_)*scale_;
+ if (delta) {
+ h += delta;
+ }
+ delta = w - int(w/scale_)*scale_;
+ if (delta) {
+ w += delta;
+ }
+ }
+}
#if ! USE_PANGO
@@ -455,8 +479,8 @@ Fl_Font Fl_Xlib_Graphics_Driver::set_fonts(const char* pattern_name)
static const char* fl_encoding_ = "iso10646-1";
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
- fl_xft_font(this,fnum,size,0);
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
+ fl_xft_font(this, fnum, size, 0);
}
static XftFont* fontopen(const char* name, /*Fl_Fontsize*/double size, bool core, int angle) {
@@ -691,17 +715,17 @@ static void utf8extents(Fl_Font_Descriptor *desc, const char *str, int n, XGlyph
#endif
}
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->font->ascent + font_descriptor()->font->descent;
else return -1;
}
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->font->descent;
else return -1;
}
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
if (!font_descriptor()) return -1.0;
XGlyphInfo i;
utf8extents(font_descriptor(), str, n, &i);
@@ -715,11 +739,12 @@ static double fl_xft_width(Fl_Font_Descriptor *desc, FcChar32 *str, int n) {
return i.xOff;
}
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
+ if (!font_descriptor()) return -1.0;
return fl_xft_width(font_descriptor(), (FcChar32 *)(&c), 1);
}
-void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &dx, int &dy, int &w, int &h) {
if (!font_descriptor()) {
w = h = 0;
dx = dy = 0;
@@ -730,15 +755,12 @@ void Fl_Xlib_Graphics_Driver::text_extents(const char *c, int n, int &dx, int &d
w = gi.width;
h = gi.height;
- dx = -gi.x;
- dy = -gi.y;
-} // fl_text_extents
-
+ dx = -gi.x + line_delta_;
+ dy = -gi.y + line_delta_;
+ correct_extents(scale_, dx, dy, w, h);
+}
-void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
- if ( !this->font_descriptor() ) {
- this->font(FL_HELVETICA, FL_NORMAL_SIZE);
- }
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
#if USE_OVERLAY
XftDraw*& draw_ = fl_overlay ? draw_overlay : ::draw_;
if (fl_overlay) {
@@ -756,31 +778,32 @@ void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
XftDrawChange(draw_, draw_window = fl_window);
Region region = fl_clip_region();
- if (region && XEmptyRegion(region)) return;
- XftDrawSetClip(draw_, region);
-
- // Use fltk's color allocator, copy the results to match what
- // XftCollorAllocValue returns:
- XftColor color;
- color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
- uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
- color.color.red = ((int)r)*0x101;
- color.color.green = ((int)g)*0x101;
- color.color.blue = ((int)b)*0x101;
- color.color.alpha = 0xffff;
-
- const wchar_t *buffer = utf8reformat(str, n);
+ if (!(region && XEmptyRegion(region))) {
+ XftDrawSetClip(draw_, region);
+
+ // Use fltk's color allocator, copy the results to match what
+ // XftCollorAllocValue returns:
+ XftColor color;
+ color.pixel = fl_xpixel(Fl_Graphics_Driver::color());
+ uchar r,g,b; Fl::get_color(Fl_Graphics_Driver::color(), r,g,b);
+ color.color.red = ((int)r)*0x101;
+ color.color.green = ((int)g)*0x101;
+ color.color.blue = ((int)b)*0x101;
+ color.color.alpha = 0xffff;
+
+ const wchar_t *buffer = utf8reformat(str, n);
#ifdef __CYGWIN__
- XftDrawString16(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_y_, (XftChar16 *)buffer, n);
+ XftDrawString16(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar16 *)buffer, n);
#else
- XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_y_, (XftChar32 *)buffer, n);
+ XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (XftChar32 *)buffer, n);
#endif
+ }
}
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
- fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), angle);
- this->draw(str, n, (int)x, (int)y);
- fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size(), 0);
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
+ fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), angle);
+ this->draw_unscaled(str, n, x, y);
+ fl_xft_font(this, this->Fl_Graphics_Driver::font(), this->size_unscaled(), 0);
}
void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
@@ -814,11 +837,11 @@ void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
color.color.blue = ((int)b)*0x101;
color.color.alpha = 0xffff;
- XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_, y+offset_x_, (FcChar32 *)str, n);
+ XftDrawString32(draw_, &color, font_descriptor()->font, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, (FcChar32 *)str, n);
}
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* c, int n, int x, int y) {
#if defined(__GNUC__)
// FIXME: warning Need to improve this XFT right to left draw function
@@ -902,7 +925,7 @@ int Fl_Xlib_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep) {
float Fl_Xlib_Graphics_Driver::scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) {
// Xft font height is sometimes larger than the required size (see STR 2566).
// Increase the PostScript font size by 15% without exceeding the display font height
- int max = height();
+ int max = height_unscaled();
float ps_size = s * 1.15;
if (ps_size > max) ps_size = max;
return ps_size;
@@ -972,7 +995,7 @@ static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsi
return;
}
Fl_Font_Descriptor* f = driver->font_descriptor();
- if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size() && f && f->angle == angle)
+ if (fnum == driver->Fl_Graphics_Driver::font() && size == driver->size_unscaled() && f && f->angle == angle)
return;
driver->Fl_Graphics_Driver::font(fnum, size);
Fl_Fontdesc *font = fl_fonts + fnum;
@@ -1021,7 +1044,7 @@ static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsi
// well for the fltk "built-in" font names.
static XFontStruct* load_xfont_for_xft2(Fl_Graphics_Driver *driver) {
XFontStruct* xgl_font = 0;
- int size = driver->size();
+ int size = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled();
int fnum = driver->font();
const char *wt_med = "medium";
const char *wt_bold = "bold";
@@ -1112,10 +1135,10 @@ static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) {
static int glsize = 0;
static int glfont = -1;
// Do we need to load a new font?
- if ((!xgl_font) || (glsize != driver->size()) || (glfont != driver->font())) {
+ if ((!xgl_font) || (glsize != ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled()) || (glfont != driver->font())) {
// create a dummy XLFD for some font of the appropriate size...
if (xgl_font) XFreeFont(fl_display, xgl_font); // font already loaded, free it - this *might* be a Bad Idea
- glsize = driver->size(); // record current font size
+ glsize = ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(); // record current font size
glfont = driver->font(); // and face
xgl_font = load_xfont_for_xft2(driver);
}
@@ -1126,7 +1149,7 @@ static XFontStruct* fl_xxfont(Fl_Graphics_Driver *driver) {
}
static XftFont* xftfont;
if (xftfont) XftFontClose (fl_display, xftfont);
- xftfont = fontopen(fl_fonts[driver->font()].name, driver->size(), true, 0); // else request XFT to load a suitable "core" font instead.
+ xftfont = fontopen(fl_fonts[driver->font()].name, ((Fl_Xlib_Graphics_Driver*)driver)->size_unscaled(), true, 0); // else request XFT to load a suitable "core" font instead.
return xftfont->u.core.font;
# endif // XFT_MAJOR > 1
}
@@ -1161,9 +1184,13 @@ PangoContext *Fl_Xlib_Graphics_Driver::context() {
return pctxt_;
}
-void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
+void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
if (!size) return;
- if (this->Fl_Graphics_Driver::font() == fnum && this->size() == size) return;
+ if (size < 0) {
+ Fl_Graphics_Driver::font(0, 0);
+ return;
+ }
+ if (this->Fl_Graphics_Driver::font() == fnum && this->size_unscaled() == size) return;
fl_xft_font(this, fnum, size, 0);
init_built_in_fonts();
if (pfd_) pango_font_description_free(pfd_);
@@ -1180,21 +1207,21 @@ void Fl_Xlib_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
}
}
-void Fl_Xlib_Graphics_Driver::draw(const char *str, int n, int x, int y) {
- do_draw(0, str, n, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y) {
+ do_draw(0, str, n, x+offset_x_*scale_, y+offset_y_*scale_);
}
-void Fl_Xlib_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
+void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, int x, int y) {
PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6
- pango_matrix_translate(&mat, x+offset_x_, y+offset_y_); // 1.6
+ pango_matrix_translate(&mat, x+offset_x_*scale_, y+offset_y_*scale_); // 1.6
pango_matrix_rotate(&mat, angle); // 1.6
pango_context_set_matrix(pctxt_, &mat); // 1.6
do_draw(0, str, n, 0, 0);
pango_context_set_matrix(pctxt_, NULL); // 1.6
}
-void Fl_Xlib_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) {
- do_draw(1, str, n, x+offset_x_, y+offset_y_);
+void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {
+ do_draw(1, str, n, x+offset_x_*scale_, y+offset_y_*scale_);
}
void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, int x, int y) {
@@ -1245,12 +1272,13 @@ void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, in
else
XftDrawChange(draw_, draw_window = fl_window);
XftDrawSetClip(draw_, region);
- pango_xft_render_layout(draw_, &color, playout_, x*PANGO_SCALE, (y-height()+descent())*PANGO_SCALE ); // 1.8
-}
+ pango_xft_render_layout(draw_, &color, playout_, (x + line_delta_)*PANGO_SCALE,
+ (y+line_delta_-height_unscaled()+descent_unscaled())*PANGO_SCALE ); // 1.8
+ }
-double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {
if (!n) return 0;
- if (!fl_display || fl_size() == 0) return -1;
+ if (!fl_display || size_ == 0) return -1;
if (!playout_) context();
int width, height;
pango_layout_set_font_description(playout_, pfd_);
@@ -1259,30 +1287,31 @@ double Fl_Xlib_Graphics_Driver::width(const char* str, int n) {
return (double)width;
}
-void Fl_Xlib_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h) {
+void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *str, int n, int &dx, int &dy, int &w, int &h) {
if (!playout_) context();
pango_layout_set_font_description(playout_, pfd_);
pango_layout_set_text(playout_, str, n);
PangoRectangle ink_rect, logical_rect;
pango_layout_get_pixel_extents(playout_, &ink_rect, &logical_rect);
- dx = ink_rect.x;
- dy = ink_rect.y - height() + descent();
+ dx = ink_rect.x + line_delta_;
+ dy = ink_rect.y + line_delta_ - height_unscaled() + descent_unscaled();
w = ink_rect.width;
h = ink_rect.height;
+ correct_extents(scale_, dx, dy, w, h);
}
-int Fl_Xlib_Graphics_Driver::height() {
+int Fl_Xlib_Graphics_Driver::height_unscaled() {
if (font_descriptor()) return font_descriptor()->height_;
else return -1;
}
-double Fl_Xlib_Graphics_Driver::width(unsigned int c) {
+double Fl_Xlib_Graphics_Driver::width_unscaled(unsigned int c) {
char buf4[4];
int n = fl_utf8encode(c, buf4);
- return width(buf4, n);
+ return width_unscaled(buf4, n);
}
-int Fl_Xlib_Graphics_Driver::descent() {
+int Fl_Xlib_Graphics_Driver::descent_unscaled() {
if (font_descriptor()) return font_descriptor()->descent_;
else return -1;
}
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
index 44bd17a42..c7b298493 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx
@@ -47,10 +47,13 @@
#include <config.h>
#include "Fl_Xlib_Graphics_Driver.H"
+#include "../X11/Fl_X11_Screen_Driver.H"
+#include "../X11/Fl_X11_Window_Driver.H"
# include <FL/Fl.H>
# include <FL/fl_draw.H>
# include <FL/x.H>
# include <FL/Fl_Image_Surface.H>
+# include <FL/Fl_Screen_Driver.H>
# include "../../Fl_XColor.H"
# include "../../flstring.h"
#if HAVE_XRENDER
@@ -476,7 +479,6 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
if (w<=0 || h<=0) return;
dx -= X;
dy -= Y;
-
if (!bytes_per_pixel) figure_out_visual();
const unsigned oldbpp = bytes_per_pixel;
static GC gc32 = None;
@@ -574,32 +576,32 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
}
}
-void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
const int mono = (d>-3 && d<3);
- innards(buf,x+offset_x_,y+offset_y_,w,h,d,l,mono,0,0,alpha,gc_);
+ innards(buf,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,l,mono,0,0,alpha,gc_);
}
-void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
const bool alpha = !!(abs(d) & FL_IMAGE_WITH_ALPHA);
if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
const int mono = (d>-3 && d<3);
- innards(0,x+offset_x_,y+offset_y_,w,h,d,0,mono,cb,data,alpha,gc_);
+ innards(0,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,0,mono,cb,data,alpha,gc_);
}
-void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
- innards(buf,x+offset_x_,y+offset_y_,w,h,d,l,1,0,0,0,gc_);
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(const uchar* buf, int x, int y, int w, int h, int d, int l){
+ innards(buf,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,l,1,0,0,0,gc_);
}
-void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
+void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
- innards(0,x+offset_x_,y+offset_y_,w,h,d,0,1,cb,data,0,gc_);
+ innards(0,x+offset_x_*scale_,y+offset_y_*scale_,w,h,d,0,1,cb,data,0,gc_);
}
void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
@@ -622,15 +624,14 @@ void Fl_Xlib_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
XFreePixmap(fl_display, bm);
}
-void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (Fl_Graphics_Driver::prepare(bm, XP+offset_x_, YP+offset_y_, WP, HP, cx, cy, X, Y, W, H)) {
- return;
- }
-
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X, int Y, int W, int H, int cx, int cy) {
+ X = (X+offset_x_)*s;
+ Y = (Y+offset_y_)*s;
+ cache_size(bm, W, H);
+ cx *= s; cy *= s;
XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm));
- int ox = X-cx; if (ox < 0) ox += bm->w();
- int oy = Y-cy; if (oy < 0) oy += bm->h();
+ int ox = X-cx; if (ox < 0) ox += bm->w()*s;
+ int oy = Y-cy; if (oy < 0) oy += bm->h()*s;
XSetTSOrigin(fl_display, gc_, ox, oy);
XSetFillStyle(fl_display, gc_, FillStippled);
XFillRectangle(fl_display, fl_window, gc_, X, Y, W, H);
@@ -715,33 +716,42 @@ static Fl_Offscreen cache_rgb(Fl_RGB_Image *img) {
return off;
}
-void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- XP += offset_x_;
- YP += offset_y_;
- // Don't draw an empty image...
- if (!img->d() || !img->array) {
- Fl_Graphics_Driver::draw_empty(img, XP, YP);
- return;
- }
- if (start_image(img, XP, YP, WP, HP, cx, cy, X, Y, W, H)) {
- return;
- }
+// X,Y,W,H,cx,cy are in FLTK units
+// if s != 1 and id(img) != 0, the offscreen has been previously scaled by s
+// if s != 1 and id(img) == 0, img has been previously scaled by s
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, int Y, int W, int H, int cx, int cy) {
+ X = (X+offset_x_)*s;
+ Y = (Y+offset_y_)*s;
+ cache_size(img, W, H);
+ cx *= s; cy *= s;
if (!*Fl_Graphics_Driver::id(img)) {
*Fl_Graphics_Driver::id(img) = cache_rgb(img);
+ *cache_scale(img) = 1;
}
+ Fl_Region r2 = scale_clip(s);
if (*Fl_Graphics_Driver::id(img)) {
if (img->d() == 4 || img->d() == 2) {
#if HAVE_XRENDER
- scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), 4, 1, 1, cx, cy, X - offset_x_, Y - offset_y_, W, H);
+ scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), img->d(), 1, 1, cx, cy, X, Y, W, H);
#endif
} else {
- copy_offscreen(X - offset_x_, Y - offset_y_, W, H, *Fl_Graphics_Driver::id(img), cx, cy);
+ XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y);
}
} else {
// Composite image with alpha manually each time...
+ scale_ = 1;
+ int ox = offset_x_, oy = offset_y_;
+ offset_x_ = offset_y_ = 0;
+ Fl_X11_Screen_Driver *d = (Fl_X11_Screen_Driver*)Fl::screen_driver();
+ int nscreen = Fl_Window::current()->driver()->screen_num();
+ float keep = d->scale(nscreen);
+ d->scale(nscreen, 1);
alpha_blend(img, X, Y, W, H, cx, cy);
+ d->scale(nscreen, keep);
+ scale_ = s;
+ offset_x_ = ox; offset_y_ = oy;
}
+ unscale_clip(r2);
}
void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_)
@@ -752,13 +762,17 @@ void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintp
}
}
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) {
+ *cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale();
return (fl_uintptr_t)create_bitmask(w, h, array);
}
-void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) {
- int X, Y, W, H;
- if (Fl_Graphics_Driver::prepare(pxm, XP+offset_x_, YP+offset_y_, WP, HP, cx, cy, X, Y, W, H)) return;
+void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) {
+ X = (X+offset_x_)*s;
+ Y = (Y+offset_y_)*s;
+ cache_size(pxm, W, H);
+ cx *= s; cy *= s;
+ Fl_Region r2 = scale_clip(s);
if (*Fl_Graphics_Driver::mask(pxm)) {
// make X use the bitmap as a mask:
XSetClipMask(fl_display, gc_, *Fl_Graphics_Driver::mask(pxm));
@@ -781,21 +795,24 @@ void Fl_Xlib_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int H
Y1 = r->rects[i].y1;
W1 = r->rects[i].x2 - r->rects[i].x1;
H1 = r->rects[i].y2 - r->rects[i].y1;
- copy_offscreen(X1-offset_x_, Y1-offset_y_, W1, H1, *Fl_Graphics_Driver::id(pxm), cx + (X1 - X), cy + (Y1 - Y));
+ XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx + (X1 - X), cy + (Y1 - Y), W1, H1, X1, Y1);
}
XDestroyRegion(r);
} else {
- copy_offscreen(X-offset_x_, Y-offset_y_, W, H, *Fl_Graphics_Driver::id(pxm), cx, cy);
+ XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y);
}
// put the old clip region back
XSetClipOrigin(fl_display, gc_, 0, 0);
+ s = scale_; scale_ = 1;
restore_clip();
+ scale_ = s;
}
- else copy_offscreen(X-offset_x_, Y-offset_y_, W, H, *Fl_Graphics_Driver::id(pxm), cx, cy);
+ else XCopyArea(fl_display, *Fl_Graphics_Driver::id(pxm), fl_window, gc_, cx, cy, W, H, X, Y);
+ unscale_clip(r2);
}
-fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) {
+fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm, int w, int h, const char *const*data) {
Fl_Offscreen id;
id = fl_create_offscreen(w, h);
fl_begin_offscreen(id);
@@ -804,22 +821,26 @@ fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const
fl_draw_pixmap(data, 0, 0, FL_BLACK);
Fl_Surface_Device::surface()->driver()->mask_bitmap(0);
if (bitmap) {
- *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap);
+ *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(w * scale_, h * scale_, bitmap);
delete[] bitmap;
}
fl_end_offscreen();
+ *cache_scale(pxm) = Fl_Scalable_Graphics_Driver::scale();
return (fl_uintptr_t)id;
}
#if HAVE_XRENDER
+/* Draws with Xrender an Fl_Offscreen with optional scaling and accounting for transparency if necessary.
+ XP,YP,WP,HP are in drawing units
+ */
int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int depth, double scale_x, double scale_y, int srcx, int srcy, int XP, int YP, int WP, int HP) {
+ bool has_alpha = (depth == 2 || depth == 4);
XRenderPictureAttributes srcattr;
memset(&srcattr, 0, sizeof(XRenderPictureAttributes));
static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32);
static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24);
- Picture src = XRenderCreatePicture(fl_display, pixmap,
- depth%2 == 0 ?fmt32:fmt24, 0, &srcattr);
+ Picture src = XRenderCreatePicture(fl_display, pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr);
Picture dst = XRenderCreatePicture(fl_display, fl_window, fmt24, 0, &srcattr);
if (!src || !dst) {
fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst);
@@ -836,22 +857,24 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de
}};
XRenderSetPictureTransform(fl_display, src, &mat);
}
- XRenderComposite(fl_display, (depth%2 == 0 ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0,
- XP + offset_x_, YP + offset_y_, WP, HP);
+ XRenderComposite(fl_display, (has_alpha ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0,
+ XP, YP, WP, HP);
XRenderFreePicture(fl_display, src);
XRenderFreePicture(fl_display, dst);
return 1;
}
-
+// XP,YP,WP,HP are in FLTK units
int Fl_Xlib_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
Fl_RGB_Image *rgb = img->as_rgb_image();
if (!rgb || !can_do_alpha_blending()) return 0;
if (!*Fl_Graphics_Driver::id(rgb)) {
*Fl_Graphics_Driver::id(rgb) = cache_rgb(rgb);
+ *cache_scale(rgb) = 1;
}
- return scale_and_render_pixmap(*Fl_Graphics_Driver::id(rgb), rgb->d(), rgb->w()/double(WP), rgb->h()/double(HP),
- 0, 0, XP, YP, WP, HP);
+ cache_size(img, WP, HP);
+ return scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(),
+ rgb->w() / double(WP), rgb->h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP);
}
#endif // HAVE_XRENDER
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
index a10ce7972..6629d7bfa 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_line_style.cxx
@@ -3,7 +3,7 @@
//
// Line style code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -34,10 +34,9 @@
#include "Fl_Xlib_Graphics_Driver.H"
-void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
-
+void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) {
// save line width for X11 clipping
- if (width == 0) line_width_ = 1;
+ if (width == 0) line_width_ = scale_ < 2 ? 0 : scale_;
else line_width_ = width>0 ? width : -width;
int ndashes = dashes ? strlen(dashes) : 0;
@@ -63,10 +62,12 @@ void Fl_Xlib_Graphics_Driver::line_style(int style, int width, char* dashes) {
case FL_DASHDOTDOT: *p++ = dash; *p++ = gap; *p++ = dot; *p++ = gap; *p++ = dot; *p++ = gap; break;
}
ndashes = p-buf;
+if (*dashes == 0) ndashes = 0;//against error with very small scaling
}
static int Cap[4] = {CapButt, CapButt, CapRound, CapProjecting};
static int Join[4] = {JoinMiter, JoinMiter, JoinRound, JoinBevel};
- XSetLineAttributes(fl_display, gc_, width,
+ XSetLineAttributes(fl_display, gc_,
+ line_width_,
ndashes ? LineOnOffDash : LineSolid,
Cap[(style>>8)&3], Join[(style>>12)&3]);
if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes);
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
index 71395afdf..bc318a7e9 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_rect.cxx
@@ -3,7 +3,7 @@
//
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -161,112 +161,167 @@ void Fl_Xlib_Graphics_Driver::XDestroyRegion(Fl_Region r) {
::XDestroyRegion(r);
}
-// --- line and polygon drawing with integer coordinates
+// --- line and polygon drawing
-void Fl_Xlib_Graphics_Driver::point(int x, int y) {
- XDrawPoint(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_));
-}
-void Fl_Xlib_Graphics_Driver::rect(int x, int y, int w, int h) {
- if (w<=0 || h<=0) return;
- x+=offset_x_; y+=offset_y_;
+void Fl_Xlib_Graphics_Driver::rect_unscaled(float fx, float fy, float fw, float fh) {
+ if (fw<=0 || fh<=0) return;
+ int deltaf = scale_ >= 2 ? scale_-1 : 0;
+ fx += offset_x_*scale_; fy += offset_y_*scale_;
+ int x = fx; int y = fy;
+ int w = int(int(fx/scale_+fw/scale_+0.5)*scale_) - x - 1 - deltaf;
+ int h = int(int(fy/scale_+fh/scale_+0.5)*scale_) - y - 1 - deltaf;
if (!clip_to_short(x, y, w, h, line_width_))
- XDrawRectangle(fl_display, fl_window, gc_, x, y, w-1, h-1);
+ XDrawRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h);
}
-void Fl_Xlib_Graphics_Driver::rectf(int x, int y, int w, int h) {
- if (w<=0 || h<=0) return;
- x+=offset_x_; y+=offset_y_;
+void Fl_Xlib_Graphics_Driver::rectf_unscaled(float fx, float fy, float fw, float fh) {
+ if (fw<=0 || fh<=0) return;
+ int deltaf = scale_ >= 2 ? scale_/2 : 0;
+ fx += offset_x_*scale_; fy += offset_y_*scale_;
+ int x = fx-deltaf; int y = fy-deltaf;
+ // make sure no unfilled area lies between rectf(x,y,w,h) and rectf(x+w,y,1,h) or rectf(x,y+w,w,1)
+ int w = int(int(fx/scale_+fw/scale_+0.5)*scale_) - int(fx);
+ int h = int(int(fy/scale_+fh/scale_+0.5)*scale_) - int(fy);
if (!clip_to_short(x, y, w, h, line_width_))
- XFillRectangle(fl_display, fl_window, gc_, x, y, w, h);
+ XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h);
+}
+
+void Fl_Xlib_Graphics_Driver::point_unscaled(float fx, float fy) {
+ int deltaf = scale_ >= 2 ? scale_/2 : 0;
+ int x = fx+offset_x_*scale_-deltaf; int y = fy+offset_y_*scale_-deltaf;
+ int width = scale_ >= 1 ? scale_ : 1;
+ XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, width, width);
}
-void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1) {
- XDrawLine(fl_display, fl_window, gc_, x+offset_x_, y+offset_y_, x1+offset_x_, y1+offset_y_);
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) {
+ if (x == x1) yxline_unscaled(x, y, y1);
+ else if (y == y1) xyline_unscaled(x, y, x1);
+ else XDrawLine(fl_display, fl_window, gc_, x+offset_x_*scale_+line_delta_, y+offset_y_*scale_+line_delta_, x1+offset_x_*scale_+line_delta_, y1+offset_y_*scale_+line_delta_);
}
-void Fl_Xlib_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
XPoint p[3];
- p[0].x = x+offset_x_; p[0].y = y+offset_y_;
- p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
- p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
+ p[0].x = x+offset_x_*scale_+line_delta_; p[0].y = y+offset_y_*scale_+line_delta_;
+ p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+ p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
}
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1) {
- XDrawLine(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_), clip_x(x1+offset_x_), clip_x(y+offset_y_));
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {//OK
+ x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_;
+ int tw = line_width_ ? line_width_ : 1; // true line width
+ if (x > x1) { float exch = x; x = x1; x1 = exch; }
+ int ix = clip_x(x+line_delta_); if (scale_ >= 2) ix -= int(scale_/2);
+ int iy = clip_x(y+line_delta_);
+ int ix1 = int(x1/scale_+1.5)*scale_-1; if (scale_ >= 2) ix1 += int(scale_/2); if (scale_ >= 4) ix1 -= scale_/2;
+ XDrawLine(fl_display, fl_window, gc_, ix, iy, ix1, iy);
+ // try and make sure no unfilled area lies between xyline(x,y,x1) and xyline(x,y+1,x1)
+ if (y+line_delta_ + scale_ >= iy + tw+1 - 0.001 ) XDrawLine(fl_display, fl_window, gc_, ix, iy+1, ix1, iy+1);
}
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2) {//OK
+ x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_; y2+=offset_y_*scale_;
+ if (scale_ >= 2) {
+ int delta = int(scale_/2 + 0.5);
+ if (x > x1) x += delta; else x -= delta;
+ if (y2 > y) y2 += delta; else y2 -= delta;
+ }
XPoint p[3];
- p[0].x = clip_x(x+offset_x_); p[0].y = p[1].y = clip_x(y+offset_y_);
- p[1].x = p[2].x = clip_x(x1+offset_x_); p[2].y = clip_x(y2+offset_y_);
+ p[0].x = clip_x(x+line_delta_); p[0].y = p[1].y = clip_x(y+line_delta_);
+ p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = clip_x(y2+line_delta_);
XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
}
-void Fl_Xlib_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
+void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1, float y2, float x3) {
+ x+=offset_x_*scale_; y+=offset_y_*scale_; x1 += offset_x_*scale_; y2+=offset_y_*scale_; x3 += offset_x_*scale_;
+ if (scale_ >= 2) {
+ int delta = int(scale_/2 + 0.5);
+ if (x > x1) x += delta; else x -= delta;
+ if (x3 > x1) x3 += delta; else x3 -= delta;
+ }
XPoint p[4];
- p[0].x = clip_x(x+offset_x_); p[0].y = p[1].y = clip_x(y+offset_y_);
- p[1].x = p[2].x = clip_x(x1+offset_x_); p[2].y = p[3].y = clip_x(y2+offset_y_);
- p[3].x = clip_x(x3+offset_x_);
+ p[0].x = clip_x(x+line_delta_); p[0].y = p[1].y = clip_x(y+line_delta_);
+ p[1].x = p[2].x = clip_x(x1+line_delta_); p[2].y = p[3].y = clip_x(y2+line_delta_);
+ p[3].x = clip_x(x3+line_delta_);
XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
}
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1) {
- XDrawLine(fl_display, fl_window, gc_, clip_x(x+offset_x_), clip_x(y+offset_y_), clip_x(x+offset_x_), clip_x(y1+offset_y_));
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {//OK
+ x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_;
+ int tw = line_width_ ? line_width_ : 1; // true line width
+ if (y > y1) { float exch = y; y = y1; y1 = exch; }
+ int ix = clip_x(x+line_delta_);
+ int iy = clip_x(y+line_delta_); if (scale_ >= 2) iy -= int(scale_/2);
+ int iy1 = int(y1/scale_+1.5)*scale_-1; if (scale_ >= 2) iy1 += int(scale_/2); if (scale_ >= 4) iy1 -= scale_/2;
+ XDrawLine(fl_display, fl_window, gc_, ix, iy, ix, iy1);
+ // try and make sure no unfilled area lies between yxline(x,y,y1) and yxline(x+1,y,y1)
+ if (x+line_delta_+scale_ >= ix + tw+1 -0.001) XDrawLine(fl_display, fl_window, gc_, ix+1, iy, ix+1, iy1);
}
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2) {
+ x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_; x2+=offset_x_*scale_;
+ if (scale_ >= 2) {
+ int delta = int(scale_/2 + 0.5);
+ if (y > y1) y += delta; else y -= delta;
+ if (x2 > x) x2 += delta; else x2 -= delta;
+ }
XPoint p[3];
- p[0].x = p[1].x = clip_x(x+offset_x_); p[0].y = clip_x(y+offset_y_);
- p[1].y = p[2].y = clip_x(y1+offset_y_); p[2].x = clip_x(x2+offset_x_);
+ p[0].x = p[1].x = clip_x(x+line_delta_); p[0].y = clip_x(y+line_delta_);
+ p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = clip_x(x2+line_delta_);
XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
}
-void Fl_Xlib_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
+void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1, float x2, float y3) {
+ x+=offset_x_*scale_; y+=offset_y_*scale_; y1 += offset_y_*scale_; x2+=offset_x_*scale_; y3 += offset_y_*scale_;
+ if (scale_ >= 2) {
+ int delta = int(scale_/2 + 0.5);
+ if (y > y1) y += delta; else y -= delta;
+ if (y3 > y1) y3 += delta; else y3 -= delta;
+ }
XPoint p[4];
- p[0].x = p[1].x = clip_x(x+offset_x_); p[0].y = clip_x(y+offset_y_);
- p[1].y = p[2].y = clip_x(y1+offset_y_); p[2].x = p[3].x = clip_x(x2+offset_x_);
- p[3].y = clip_x(y3+offset_y_);
+ p[0].x = p[1].x = clip_x(x+line_delta_); p[0].y = clip_x(y+line_delta_);
+ p[1].y = p[2].y = clip_x(y1+line_delta_); p[2].x = p[3].x = clip_x(x2+line_delta_);
+ p[3].y = clip_x(y3+line_delta_);
XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
}
-void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
XPoint p[4];
- p[0].x = x+offset_x_; p[0].y = y+offset_y_;
- p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
- p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
- p[3].x = x+offset_x_; p[3].y = y+offset_y_;
+ p[0].x = x +offset_x_*scale_+line_delta_; p[0].y = y +offset_y_*scale_+line_delta_;
+ p[1].x = x1 +offset_x_*scale_+line_delta_; p[1].y = y1 +offset_y_*scale_+line_delta_;
+ p[2].x = x2 +offset_x_*scale_+line_delta_; p[2].y = y2 +offset_y_*scale_+line_delta_;
+ p[3].x = x +offset_x_*scale_+line_delta_; p[3].y = y +offset_y_*scale_+line_delta_;
XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
}
-void Fl_Xlib_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
XPoint p[5];
- p[0].x = x+offset_x_; p[0].y = y+offset_y_;
- p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
- p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
- p[3].x = x3+offset_x_; p[3].y = y3+offset_y_;
- p[4].x = x+offset_x_; p[4].y = y+offset_y_;
+ p[0].x = x+offset_x_*scale_+line_delta_; p[0].y = y+offset_y_*scale_+line_delta_;
+ p[1].x = x1 +offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+ p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+ p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_;
+ p[4].x = x+offset_x_*scale_+line_delta_; p[4].y = y+offset_y_*scale_+line_delta_;
XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
}
-void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
XPoint p[4];
- p[0].x = x+offset_x_; p[0].y = y+offset_y_;
- p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
- p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
- p[3].x = x+offset_x_; p[3].y = y+offset_y_;
+ p[0].x = x+offset_x_*scale_+line_delta_; p[0].y = y+offset_y_*scale_+line_delta_;
+ p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+ p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+ p[3].x = x+offset_x_*scale_+line_delta_; p[3].y = y+offset_y_*scale_+line_delta_;
XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0);
XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
}
-void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
+void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) {
XPoint p[5];
- p[0].x = x+offset_x_; p[0].y = y+offset_y_;
- p[1].x = x1+offset_x_; p[1].y = y1+offset_y_;
- p[2].x = x2+offset_x_; p[2].y = y2+offset_y_;
- p[3].x = x3+offset_x_; p[3].y = y3+offset_y_;
- p[4].x = x+offset_x_; p[4].y = y+offset_y_;
+ p[0].x = x+offset_x_*scale_+line_delta_; p[0].y = y+offset_y_*scale_+line_delta_;
+ p[1].x = x1+offset_x_*scale_+line_delta_; p[1].y = y1+offset_y_*scale_+line_delta_;
+ p[2].x = x2+offset_x_*scale_+line_delta_; p[2].y = y2+offset_y_*scale_+line_delta_;
+ p[3].x = x3+offset_x_*scale_+line_delta_; p[3].y = y3+offset_y_*scale_+line_delta_;
+ p[4].x = x+offset_x_*scale_+line_delta_; p[4].y = y+offset_y_*scale_+line_delta_;
XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0);
XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
}
@@ -276,7 +331,7 @@ void Fl_Xlib_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int
void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) {
Fl_Region r;
if (w > 0 && h > 0) {
- r = XRectangleRegion(x+offset_x_,y+offset_y_,w,h);
+ r = XRectangleRegion(x,y,w,h);
Fl_Region current = rstack[rstackptr];
if (current) {
Fl_Region temp = XCreateRegion();
@@ -294,8 +349,6 @@ void Fl_Xlib_Graphics_Driver::push_clip(int x, int y, int w, int h) {
int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
X = x; Y = y; W = w; H = h;
- x += offset_x_;
- y += offset_y_;
Fl_Region r = rstack[rstackptr];
if (!r) return 0;
switch (XRectInRegion(r, x, y, w, h)) {
@@ -312,15 +365,13 @@ int Fl_Xlib_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y
XIntersectRegion(r, rr, temp);
XRectangle rect;
XClipBox(temp, &rect);
- X = rect.x - offset_x_; Y = rect.y - offset_y_; W = rect.width; H = rect.height;
+ X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
XDestroyRegion(temp);
XDestroyRegion(rr);
return 1;
}
int Fl_Xlib_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
- x += offset_x_;
- y += offset_y_;
if (x+w <= 0 || y+h <= 0) return 0;
Fl_Region r = rstack[rstackptr];
if (!r) return 1;
@@ -348,8 +399,12 @@ void Fl_Xlib_Graphics_Driver::pop_clip() {
void Fl_Xlib_Graphics_Driver::restore_clip() {
fl_clip_state_number++;
if (gc_) {
- Fl_Region r = rstack[rstackptr];
- if (r) XSetRegion(fl_display, gc_, r);
+ Region r = rstack[rstackptr];
+ if (r) {
+ Region r2 = scale_clip(scale_);
+ XSetRegion(fl_display, gc_, rstack[rstackptr]);
+ unscale_clip(r2);
+ }
else XSetClipMask(fl_display, gc_, 0);
}
}
diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
index 05c58eb8d..d36b540e7 100644
--- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_vertex.cxx
@@ -3,7 +3,7 @@
//
// Portable drawing routines for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2016 by Bill Spitzak and others.
+// Copyright 1998-2017 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
@@ -30,14 +30,6 @@
#include <FL/math.h>
-void Fl_Xlib_Graphics_Driver::transformed_vertex(double xf, double yf) {
- transformed_vertex0(short(rint(xf)), short(rint(yf)));
-}
-
-void Fl_Xlib_Graphics_Driver::vertex(double x,double y) {
- transformed_vertex0(short(x*m.a + y*m.c + m.x), short(x*m.b + y*m.d + m.y));
-}
-
void Fl_Xlib_Graphics_Driver::end_points() {
if (n>1) XDrawPoints(fl_display, fl_window, gc_, (XPoint*)p, n, 0);
}
@@ -52,7 +44,9 @@ void Fl_Xlib_Graphics_Driver::end_line() {
void Fl_Xlib_Graphics_Driver::end_loop() {
fixloop();
- if (n>2) transformed_vertex((short)p[0].x, (short)p[0].y);
+ if (n>2) {
+ transformed_vertex0(p[0].x, p[0].y);
+ }
end_line();
}
@@ -73,7 +67,7 @@ void Fl_Xlib_Graphics_Driver::begin_complex_polygon() {
void Fl_Xlib_Graphics_Driver::gap() {
while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
if (n > gap_+2) {
- transformed_vertex((short)p[gap_].x, (short)p[gap_].y);
+ transformed_vertex0(p[gap_].x, p[gap_].y);
gap_ = n;
} else {
n = gap_;
@@ -92,12 +86,7 @@ void Fl_Xlib_Graphics_Driver::end_complex_polygon() {
// shortcut the closed circles so they use XDrawArc:
// warning: these do not draw rotated ellipses correctly!
// See fl_arc.c for portable version.
-
-void Fl_Xlib_Graphics_Driver::circle(double x, double y,double r) {
- double xt = transform_x(x,y);
- double yt = transform_y(x,y);
- double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a));
- double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d));
+void Fl_Xlib_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
int llx = (int)rint(xt-rx);
int w = (int)rint(xt+rx)-llx;
int lly = (int)rint(yt-ry);
diff --git a/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx b/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
index 49a84e7d8..fa2aaeb5d 100644
--- a/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
+++ b/src/drivers/Xlib/Fl_Xlib_Image_Surface_Driver.cxx
@@ -24,12 +24,13 @@
#include "Fl_Xlib_Graphics_Driver.H"
#include <FL/Fl_Image_Surface.H>
#include "Fl_Xlib_Graphics_Driver.H"
+#include <FL/Fl_Screen_Driver.H>
class Fl_Xlib_Image_Surface_Driver : public Fl_Image_Surface_Driver {
- friend class Fl_Image_Surface;
virtual void end_current_(Fl_Surface_Device *next_current);
public:
Window pre_window;
+ int was_high;
Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off);
~Fl_Xlib_Image_Surface_Driver();
void set_current();
@@ -44,11 +45,18 @@ Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, i
}
Fl_Xlib_Image_Surface_Driver::Fl_Xlib_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, off) {
+ float d = 1;
if (!off) {
fl_open_display();
+ d = fl_graphics_driver->scale();
+ if (d != 1 && high_res) {
+ w = int(w*d);
+ h = int(h*d);
+ }
offscreen = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), w, h, fl_visual->depth);
}
driver(new Fl_Xlib_Graphics_Driver());
+ if (d != 1 && high_res) ((Fl_Xlib_Graphics_Driver*)driver())->scale(d);
}
Fl_Xlib_Image_Surface_Driver::~Fl_Xlib_Image_Surface_Driver() {
@@ -73,9 +81,7 @@ void Fl_Xlib_Image_Surface_Driver::untranslate() {
Fl_RGB_Image* Fl_Xlib_Image_Surface_Driver::image()
{
- unsigned char *data = fl_read_image(NULL, 0, 0, width, height, 0);
- Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height);
- image->alloc_array = 1;
+ Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle(NULL, 0, 0, width, height, 0);
return image;
}