Unification of scaled coordinate calculations in class Fl_Scalable_Graphics_Driver

Most coordinate calculations are done with the new inline function
 int Fl_Scalable_Graphics_Driver::floor(int coord)
that is used by both the Windows and X11 platforms.
This commit is contained in:
ManoloFLTK 2021-03-11 16:05:20 +01:00
parent bd6c985434
commit 569fec25e0
18 changed files with 317 additions and 405 deletions

View File

@ -419,6 +419,11 @@ struct Fl_Fontdesc {
class FL_EXPORT Fl_Scalable_Graphics_Driver : public Fl_Graphics_Driver { class FL_EXPORT Fl_Scalable_Graphics_Driver : public Fl_Graphics_Driver {
public: public:
Fl_Scalable_Graphics_Driver(); Fl_Scalable_Graphics_Driver();
// This function aims to compute accurately int(x * s) in
// presence of rounding errors existing with floating point numbers
// and that sometimes differ between 32 and 64 bits.
static inline int floor(int x, float s) { return int(x * s + 0.001f); }
inline int floor(int x) { return Fl_Scalable_Graphics_Driver::floor(x, scale()); }
protected: protected:
int line_width_; int line_width_;
virtual Fl_Region scale_clip(float f); virtual Fl_Region scale_clip(float f);
@ -426,29 +431,24 @@ protected:
virtual void point(int x, int y); virtual void point(int x, int y);
virtual void point_unscaled(float x, float y); virtual void point_unscaled(float x, float y);
virtual void rect(int x, int y, int w, int h); virtual void rect(int x, int y, int w, int h);
virtual void rect_unscaled(float x, float y, float w, float h);
virtual void rectf(int x, int y, int w, int h); virtual void rectf(int x, int y, int w, int h);
virtual void rectf_unscaled(float x, float y, float w, float h); virtual void rectf_unscaled(int x, int y, int w, int h);
virtual void line(int x, int y, int x1, int y1); virtual void line(int x, int y, int x1, int y1);
virtual void line_unscaled(float x, float y, float x1, float y1); virtual void line_unscaled(int x, int y, int x1, int y1);
virtual void line(int x, int y, int x1, int y1, int x2, int y2); virtual void line(int x, int y, int x1, int y1, int x2, int y2);
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2); virtual void line_unscaled(int x, int y, int x1, int y1, int x2, int y2);
virtual void xyline(int x, int y, int x1); virtual void xyline(int x, int y, int x1);
virtual void xyline(int x, int y, int x1, int y2); virtual void xyline_unscaled(int x, int y, int x1);
virtual void xyline(int x, int y, int x1, int y2, int x3);
virtual void xyline_unscaled(float x, float y, float x1);
virtual void yxline(int x, int y, int y1); virtual void yxline(int x, int y, int y1);
virtual void yxline(int x, int y, int y1, int x2); virtual void yxline_unscaled(int x, int y, int y1);
virtual void yxline(int x, int y, int y1, int x2, int y3);
virtual void yxline_unscaled(float x, float y, float y1);
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2); virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2); virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void circle(double x, double y, double r); virtual void circle(double x, double y, double r);
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry); virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
virtual void font(Fl_Font face, Fl_Fontsize size); virtual void font(Fl_Font face, Fl_Fontsize size);
@ -475,12 +475,12 @@ protected:
virtual void rtl_draw_unscaled(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 arc(double x, double y, double r, double start, double end); virtual void arc(double x, double y, double r, double start, double end);
virtual void arc(int x, int y, int w, int h, double a1, double a2); virtual void arc(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 arc_unscaled(int x, int y, int w, int h, double a1, double a2);
virtual void pie(int x, int y, int w, int h, double a1, double a2); virtual void pie(int x, int y, int w, int h, double a1, double a2);
virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2); virtual void pie_unscaled(int x, int y, int w, int h, double a1, double a2);
virtual void line_style(int style, int width=0, char* dashes=0); virtual void line_style(int style, int width=0, char* dashes=0);
virtual void line_style_unscaled(int style, float width, char* dashes); virtual void line_style_unscaled(int style, int width, char* dashes);
void draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, int X, int Y, int W, int H, int D, int L, bool mono, float s); void draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, int X, int Y, int W, int H, int D, int L, bool mono);
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(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_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
@ -494,6 +494,8 @@ protected:
void vertex(double x, double y); void vertex(double x, double y);
virtual float override_scale(); virtual float override_scale();
virtual void restore_scale(float); virtual void restore_scale(float);
virtual void *change_pen_width(int lwidth);
virtual void reset_pen_width(void *data);
}; };
#endif // FL_DOXYGEN #endif // FL_DOXYGEN

View File

@ -345,14 +345,14 @@ void Fl_Graphics_Driver::xyline(int x, int y, int x1) {
} }
void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) { void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
line(x, y, x1, y); xyline(x, y, x1);
line(x1, y, x1, y2); yxline(x1, y, y2);
} }
void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
line(x, y, x1, y); xyline(x, y, x1);
line(x1, y, x1, y2); yxline(x1, y, y2);
line(x1, y2, x3, y2); xyline(x1, y2, x3);
} }
void Fl_Graphics_Driver::yxline(int x, int y, int y1) { void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
@ -360,14 +360,14 @@ void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
} }
void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) { void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
line(x, y, x, y1); yxline(x, y, y1);
line(x, y1, x2, y1); xyline(x, y1, x2);
} }
void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
line(x, y, x, y1); yxline(x, y, y1);
line(x, y1, x2, y1); xyline(x, y1, x2);
line(x2, y1, x2, y3); yxline(x2, y1, y3);
} }
void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
@ -692,72 +692,79 @@ Fl_Scalable_Graphics_Driver::Fl_Scalable_Graphics_Driver() : Fl_Graphics_Driver(
void Fl_Scalable_Graphics_Driver::rect(int x, int y, int w, int h) void Fl_Scalable_Graphics_Driver::rect(int x, int y, int w, int h)
{ {
if (int(scale()) == scale()) { if (w > 0 && h > 0) {
rect_unscaled(x * scale(), y * scale(), w * scale(), h * scale()); xyline(x, y, x+w-1);
} else { yxline(x, y, y+h-1);
if (w > 0 && h > 0) { yxline(x+w-1, y, y+h-1);
xyline(x, y, x+w-1); xyline(x, y+h-1, x+w-1);
yxline(x, y, y+h-1);
yxline(x+w-1, y, y+h-1);
xyline(x, y+h-1, x+w-1);
}
} }
} }
void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h) void Fl_Scalable_Graphics_Driver::rectf(int x, int y, int w, int h)
{ {
rectf_unscaled(x * scale(), y * scale(), w * scale(), h * scale()); if (w <= 0 || h <= 0) return;
rectf_unscaled(this->floor(x), this->floor(y),
this->floor(x + w) - this->floor(x), this->floor(y + h) - this->floor(y));
} }
void Fl_Scalable_Graphics_Driver::point(int x, int y) { void Fl_Scalable_Graphics_Driver::point(int x, int y) {
point_unscaled(x * scale(), y * scale()); rectf(x, y, 1, 1);
} }
void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1) { void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1) {
if (y == y1) xyline(x, y, x1); if (y == y1) xyline(x, y, x1);
else if (x == x1) yxline(x, y, y1); else if (x == x1) yxline(x, y, y1);
else line_unscaled( x*scale(), y*scale(), x1*scale(), y1*scale()); else line_unscaled(this->floor(x), this->floor(y), this->floor(x1), this->floor(y1));
} }
void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { void Fl_Scalable_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
if ( (y == y1 || x == x1) && (y2 == y1 || x2 == x1) ) { // only horizontal or vertical lines line_unscaled(this->floor(x), this->floor(y), this->floor(x1), this->floor(y1), this->floor(x2), this->floor(y2));
line(x, y, x1, y1);
line(x1, y1, x2, y2);
} else line_unscaled( x*scale(), y*scale(), x1*scale(), y1*scale(), x2*scale(), y2*scale());
} }
void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1) { void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1) {
xyline_unscaled(x*scale(), y*scale(), x1*scale()); if (y < 0) return;
} float s = scale(); int s_int = int(s);
int xx = (x < x1 ? x : x1);
void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2) { int xx1 = (x < x1 ? x1 : x);
xyline(x, y, x1); if (s != s_int && line_width_ <= s_int) {
yxline(x1, y, y2); int lwidth = this->floor((y+1)) - this->floor(y);
} bool need_change_width = (lwidth != s_int);
void *data = NULL;
void Fl_Scalable_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { if (need_change_width) data = change_pen_width(lwidth);
xyline(x, y, x1); xyline_unscaled(this->floor(xx), this->floor(y) + int(lwidth/2.f), this->floor(xx1+1)-1);
yxline(x1, y, y2); if (need_change_width) reset_pen_width(data);
xyline(x1, y2, x3); } else {
y = this->floor(y);
if (line_width_ <= s_int) y += int(s/2.f);
xyline_unscaled(this->floor(xx), y, this->floor(xx1+1) - 1);
}
} }
void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1) { void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1) {
yxline_unscaled(x*scale(), y*scale(), y1*scale()); if (x < 0) return;
float s = scale(); int s_int = int(s);
int yy = (y < y1 ? y : y1);
int yy1 = (y < y1 ? y1 : y);
if (s != s_int && line_width_ <= s_int) {
int lwidth = (this->floor((x+1)) - this->floor(x));
bool need_change_width = (lwidth != s_int);
void *data = NULL;
if (need_change_width) data = change_pen_width(lwidth);
yxline_unscaled(this->floor(x) + int(lwidth/2.f), this->floor(yy), this->floor(yy1+1) - 1);
if (need_change_width) reset_pen_width(data);
} else {
x = this->floor(x);
if (line_width_ <= s_int) x += int(s/2.f);
yxline_unscaled(x, this->floor(yy), this->floor(yy1+1) - 1);
}
} }
void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2) { void *Fl_Scalable_Graphics_Driver::change_pen_width(int lwidth) {return NULL;}
yxline(x, y, y1);
xyline(x, y1, x2);
}
void Fl_Scalable_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { void Fl_Scalable_Graphics_Driver::reset_pen_width(void *data){}
yxline(x, y, y1);
xyline(x, y1, x2);
yxline(x2, y1, y3);
}
void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
loop_unscaled(x0*scale(), y0*scale(), x1*scale(), y1*scale(), x2*scale(), y2*scale()); loop_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2));
} }
void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
@ -775,17 +782,16 @@ void Fl_Scalable_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, i
H = abs(y0 - y1); H = abs(y0 - y1);
rect(X, Y, W + 1, H + 1); rect(X, Y, W + 1, H + 1);
} else { } else {
float s = scale(); loop_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2), floor(x3), floor(y3));
loop_unscaled(x0*s, y0*s, x1*s, y1*s, x2*s, y2*s, x3*s, y3*s);
} }
} }
void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) {
polygon_unscaled(x0*scale(), y0*scale(), x1*scale(), y1*scale(), x2*scale(), y2*scale()); polygon_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2));
} }
void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { void Fl_Scalable_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {
polygon_unscaled(x0*scale(), y0*scale(), x1*scale(), y1*scale(), x2*scale(), y2*scale(), x3*scale(), y3*scale()); polygon_unscaled(floor(x0), floor(y0), floor(x1), floor(y1), floor(x2), floor(y2), floor(x3), floor(y3));
} }
void Fl_Scalable_Graphics_Driver::circle(double x, double y, double r) { void Fl_Scalable_Graphics_Driver::circle(double x, double y, double r) {
@ -837,7 +843,7 @@ int Fl_Scalable_Graphics_Driver::descent() {
void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) { void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, int x, int y) {
if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
Fl_Region r2 = scale_clip(scale()); Fl_Region r2 = scale_clip(scale());
draw_unscaled(str, n, int(x*scale()), int(y*scale())); draw_unscaled(str, n, floor(x), floor(y));
unscale_clip(r2); unscale_clip(r2);
} }
@ -848,7 +854,7 @@ void Fl_Scalable_Graphics_Driver::draw(const char *str, int n, float x, float y)
void Fl_Scalable_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) { void Fl_Scalable_Graphics_Driver::draw(int angle, const char *str, int n, int x, int y) {
if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE); if (!size_ || !font_descriptor()) font(FL_HELVETICA, FL_NORMAL_SIZE);
Fl_Region r2 = scale_clip(scale()); Fl_Region r2 = scale_clip(scale());
draw_unscaled(angle, str, n, int(x*scale()), int(y*scale())); draw_unscaled(angle, str, n, floor(x), floor(y));
unscale_clip(r2); unscale_clip(r2);
} }
@ -856,8 +862,13 @@ void Fl_Scalable_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y)
rtl_draw_unscaled(str, n, int(x * scale()), int(y * scale())); rtl_draw_unscaled(str, n, int(x * scale()), int(y * scale()));
} }
void Fl_Scalable_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) { void Fl_Scalable_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) {
arc_unscaled(x * scale(), y * scale(), w * scale(), h * scale(), a1, a2); float s = scale();
int xx = floor(x) + int((s-1)/2);
int yy = floor(y) + int((s-1)/2);
w = floor(x+w) - xx - 1 + line_width_/2 - int(s-1);
h = floor(y+h) - yy - 1 + line_width_/2 - int(s-1);
arc_unscaled(xx, yy, w, h, a1, a2);
} }
void Fl_Scalable_Graphics_Driver::arc(double x, double y, double r, double start, double end) { void Fl_Scalable_Graphics_Driver::arc(double x, double y, double r, double start, double end) {
@ -865,18 +876,22 @@ void Fl_Scalable_Graphics_Driver::arc(double x, double y, double r, double start
} }
void Fl_Scalable_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) { void Fl_Scalable_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
pie_unscaled(x * scale(), y * scale(), w * scale(), h * scale(), a1, a2); int xx = floor(x) - 1;
int yy = floor(y) - 1;
w = floor(x+w) - xx;
h = floor(y+h) - yy;
pie_unscaled(xx, yy, w, h, a1, a2);
} }
void Fl_Scalable_Graphics_Driver::line_style(int style, int width, char* dashes) { void Fl_Scalable_Graphics_Driver::line_style(int style, int width, char* dashes) {
if (width == 0) line_width_ = int(scale() < 2 ? 0 : scale()); if (width == 0) line_width_ = int(scale() < 2 ? 0 : scale());
else line_width_ = int(width>0 ? width*scale() : -width*scale()); else line_width_ = int(width>0 ? width*scale() : -width*scale());
line_style_unscaled(style, float(line_width_), dashes); line_style_unscaled(style, line_width_, dashes);
} }
/* read the image data from a pointer or with a callback, scale it, and draw it */ /* read the image data from a pointer or with a callback, scale it, and draw it */
void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb, void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb cb,
int X, int Y, int W, int H, int D, int L, bool mono, float s) { int X, int Y, int W, int H, int D, int L, bool mono) {
int aD = abs(D); int aD = abs(D);
if (L == 0) L = W*aD; if (L == 0) L = W*aD;
int depth = mono ? (aD%2==0?2:1) : aD; int depth = mono ? (aD%2==0?2:1) : aD;
@ -899,12 +914,12 @@ void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb
rgb->alloc_array = 1; rgb->alloc_array = 1;
Fl_RGB_Scaling keep = Fl_Image::RGB_scaling(); Fl_RGB_Scaling keep = Fl_Image::RGB_scaling();
Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm());
Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(int(ceil(W * s)), int(ceil(H * s))); Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(floor(X+W)-floor(X), floor(Y+H)-floor(Y));
Fl_Image::RGB_scaling(keep); Fl_Image::RGB_scaling(keep);
delete rgb; delete rgb;
if (scaled_rgb) { if (scaled_rgb) {
Fl_Region r2 = scale_clip(s); Fl_Region r2 = scale_clip(scale());
draw_image_unscaled(scaled_rgb->array, int(X * s), int(Y * s), scaled_rgb->w(), scaled_rgb->h(), depth); draw_image_unscaled(scaled_rgb->array, floor(X), floor(Y), scaled_rgb->w(), scaled_rgb->h(), depth);
unscale_clip(r2); unscale_clip(r2);
delete scaled_rgb; delete scaled_rgb;
} }
@ -914,7 +929,7 @@ void Fl_Scalable_Graphics_Driver::draw_image(const uchar* buf, int X,int Y,int W
if (scale() == 1) { if (scale() == 1) {
draw_image_unscaled(buf, X,Y,W,H,D,L); draw_image_unscaled(buf, X,Y,W,H,D,L);
} else { } else {
draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false, scale()); draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, false);
} }
} }
@ -922,7 +937,7 @@ void Fl_Scalable_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, in
if (scale() == 1) { if (scale() == 1) {
draw_image_unscaled(cb, data, X,Y,W,H,D); draw_image_unscaled(cb, data, X,Y,W,H,D);
} else { } else {
draw_image_rescale(data, cb, X, Y, W, H, D, 0, false, scale()); draw_image_rescale(data, cb, X, Y, W, H, D, 0, false);
} }
} }
@ -930,7 +945,7 @@ void Fl_Scalable_Graphics_Driver::draw_image_mono(const uchar* buf, int X,int Y,
if (scale() == 1) { if (scale() == 1) {
draw_image_mono_unscaled(buf, X,Y,W,H,D,L); draw_image_mono_unscaled(buf, X,Y,W,H,D,L);
} else { } else {
draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, true, scale()); draw_image_rescale((void*)buf, NULL, X, Y, W, H, D, L, true);
} }
} }
@ -938,7 +953,7 @@ void Fl_Scalable_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* dat
if (scale() == 1) { if (scale() == 1) {
draw_image_mono_unscaled(cb, data, X,Y,W,H,D); draw_image_mono_unscaled(cb, data, X,Y,W,H,D);
} else { } else {
draw_image_rescale(data, cb, X, Y, W, H, D, 0, true, scale()); draw_image_rescale(data, cb, X, Y, W, H, D, 0, true);
} }
} }
@ -961,25 +976,26 @@ Fl_Region Fl_Scalable_Graphics_Driver::scale_clip(float f) { return 0; }
void Fl_Scalable_Graphics_Driver::point_unscaled(float x, float y) {} void Fl_Scalable_Graphics_Driver::point_unscaled(float x, float y) {}
void Fl_Scalable_Graphics_Driver::rect_unscaled(float x, float y, float w, float h) {} void Fl_Scalable_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) {}
void Fl_Scalable_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) {} void Fl_Scalable_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) {}
void Fl_Scalable_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) {} void Fl_Scalable_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
line_unscaled(x, y, x1, y1);
line_unscaled(x1, y1, x2, y2);
}
void Fl_Scalable_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) {} void Fl_Scalable_Graphics_Driver::xyline_unscaled(int x, int y, int x1) {}
void Fl_Scalable_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {} void Fl_Scalable_Graphics_Driver::yxline_unscaled(int x, int y, int y1) {}
void Fl_Scalable_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {} void Fl_Scalable_Graphics_Driver::loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) {}
void Fl_Scalable_Graphics_Driver::loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2) {} void Fl_Scalable_Graphics_Driver::loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {}
void Fl_Scalable_Graphics_Driver::loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) {} void Fl_Scalable_Graphics_Driver::polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2) {}
void Fl_Scalable_Graphics_Driver::polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2) {} void Fl_Scalable_Graphics_Driver::polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) {}
void Fl_Scalable_Graphics_Driver::polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) {}
void Fl_Scalable_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {} void Fl_Scalable_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {}
@ -1003,11 +1019,11 @@ void Fl_Scalable_Graphics_Driver::draw_unscaled(int angle, const char *str, int
void Fl_Scalable_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {} void Fl_Scalable_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int y) {}
void Fl_Scalable_Graphics_Driver::arc_unscaled(float x, float y, float w, float h, double a1, double a2) {} void Fl_Scalable_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {}
void Fl_Scalable_Graphics_Driver::pie_unscaled(float x, float y, float w, float h, double a1, double a2) {} void Fl_Scalable_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) {}
void Fl_Scalable_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) {} void Fl_Scalable_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) {}
void Fl_Scalable_Graphics_Driver::draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D, int L) {} void Fl_Scalable_Graphics_Driver::draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D, int L) {}

View File

@ -75,7 +75,7 @@ Fl_GDI_Copy_Surface_Driver::~Fl_GDI_Copy_Surface_Driver() {
SetClipboardData (CF_ENHMETAFILE, hmf); SetClipboardData (CF_ENHMETAFILE, hmf);
// then put a BITMAP version of the graphics in the clipboard // then put a BITMAP version of the graphics in the clipboard
float scaling = driver()->scale(); float scaling = driver()->scale();
int W = Fl_GDI_Graphics_Driver::floor(width, scaling), H = Fl_GDI_Graphics_Driver::floor(height, scaling); int W = Fl_Scalable_Graphics_Driver::floor(width, scaling), H = Fl_Scalable_Graphics_Driver::floor(height, scaling);
RECT rect = {0, 0, W, H}; RECT rect = {0, 0, W, H};
Fl_Image_Surface *surf = new Fl_Image_Surface(W, H); Fl_Image_Surface *surf = new Fl_Image_Surface(W, H);
Fl_Surface_Device::push_current(surf); Fl_Surface_Device::push_current(surf);

View File

@ -57,11 +57,6 @@ public:
char can_do_alpha_blending(); char can_do_alpha_blending();
virtual void gc(void *ctxt) { gc_ = (HDC)ctxt; global_gc(); } virtual void gc(void *ctxt) { gc_ = (HDC)ctxt; global_gc(); }
virtual void *gc() {return gc_;} virtual void *gc() {return gc_;}
// This function aims to compute accurately int(x * s) in
// presence of rounding errors existing with floating point numbers
// and that sometimes differ between 32 and 64 bits.
static inline int floor(int x, float s) { return int(x * s + 0.001f); }
inline int floor(int x) { return Fl_GDI_Graphics_Driver::floor(x, scale()); }
// --- bitmap stuff // --- bitmap stuff
Fl_Bitmask create_bitmask(int w, int h, const uchar *array); Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
@ -101,21 +96,16 @@ protected:
void transformed_vertex0(float x, float y); void transformed_vertex0(float x, float y);
void fixloop(); void fixloop();
virtual void point(int x, int y); virtual void point(int x, int y);
virtual void rect(int x, int y, int w, int h);
void focus_rect(int x, int y, int w, int h); void focus_rect(int x, int y, int w, int h);
virtual void rectf(int x, int y, int w, int h); virtual void rectf_unscaled(int x, int y, int w, int h);
virtual void line_unscaled(float x, float y, float x1, float y1); virtual void line_unscaled(int x, int y, int x1, int y1);
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2); virtual void line_unscaled(int x, int y, int x1, int y1, int x2, int y2);
virtual void xyline(int x, int y, int x1); virtual void xyline_unscaled(int x, int y, int x1);
virtual void xyline(int x, int y, int x1, int y2); virtual void yxline_unscaled(int x, int y, int y1);
virtual void xyline(int x, int y, int x1, int y2, int x3); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void yxline(int x, int y, int y1); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void yxline(int x, int y, int y1, int x2); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void yxline(int x, int y, int y1, int x2, int y3); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int 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 // --- clipping
void push_clip(int x, int y, int w, int h); 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); int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
@ -131,14 +121,9 @@ protected:
void end_complex_polygon(); void end_complex_polygon();
void gap(); void gap();
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry); 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 virtual void arc_unscaled(int x, int y, int w, int h, double a1, double a2);
// using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end); virtual void pie_unscaled(int x, int y, int w, int h, double a1, double a2);
// --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx virtual void line_style_unscaled(int style, int width, char* dashes);
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
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); void color(Fl_Color c);
Fl_Color color() { return color_; } Fl_Color color() { return color_; }
void color(uchar r, uchar g, uchar b); void color(uchar r, uchar g, uchar b);
@ -153,6 +138,8 @@ protected:
void global_gc(); void global_gc();
virtual void overlay_rect(int x, int y, int w , int h); virtual void overlay_rect(int x, int y, int w , int h);
virtual void cache_size(Fl_Image *img, int &width, int &height); virtual void cache_size(Fl_Image *img, int &width, int &height);
virtual void* change_pen_width(int width);
virtual void reset_pen_width(void *data);
}; };

View File

@ -261,13 +261,13 @@ HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Drive
} }
RECT *rects = (RECT*)&(pdata->Buffer); RECT *rects = (RECT*)&(pdata->Buffer);
for (DWORD i = 0; i < pdata->rdh.nCount; i++) { for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
int x = Fl_GDI_Graphics_Driver::floor(rects[i].left, f) + pt.x; int x = Fl_Scalable_Graphics_Driver::floor(rects[i].left, f) + pt.x;
int y = Fl_GDI_Graphics_Driver::floor(rects[i].top, f) + pt.y; int y = Fl_Scalable_Graphics_Driver::floor(rects[i].top, f) + pt.y;
RECT R2; RECT R2;
R2.left = x; R2.left = x;
R2.top = y; R2.top = y;
R2.right = Fl_GDI_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left; R2.right = Fl_Scalable_Graphics_Driver::floor(rects[i].right, f) + pt.x - x + R2.left;
R2.bottom = Fl_GDI_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top; R2.bottom = Fl_Scalable_Graphics_Driver::floor(rects[i].bottom, f) + pt.y - y + R2.top;
rects[i] = R2; rects[i] = R2;
} }
r = ExtCreateRegion(NULL, size, pdata); r = ExtCreateRegion(NULL, size, pdata);

View File

@ -30,8 +30,9 @@
#include <FL/math.h> #include <FL/math.h>
#include <FL/platform.H> #include <FL/platform.H>
void Fl_GDI_Graphics_Driver::arc_unscaled(float x, float y, float w, float h, double a1, double a2) { void Fl_GDI_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {
if (w <= 0 || h <= 0) return; if (w <= 0 || h <= 0) return;
w++; h++;
int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) );
int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) );
int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) );
@ -42,9 +43,11 @@ void Fl_GDI_Graphics_Driver::arc_unscaled(float x, float y, float w, float h, do
} else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } else Arc(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb);
} }
void Fl_GDI_Graphics_Driver::pie_unscaled(float x, float y, float w, float h, double a1, double a2) { void Fl_GDI_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) {
if (w <= 0 || h <= 0) return; if (w <= 0 || h <= 0) return;
if (a1 == a2) return; if (a1 == a2) return;
x++; y++; w--; h--;
if (scale() >= 3) {x++; y++; w-=2; h-=2;}
int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) ); int xa = int( x+w/2+int(w*cos(a1/180.0*M_PI)) );
int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) ); int ya = int( y+h/2-int(h*sin(a1/180.0*M_PI)) );
int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) ); int xb = int( x+w/2+int(w*cos(a2/180.0*M_PI)) );

View File

@ -27,7 +27,7 @@
#include "Fl_GDI_Graphics_Driver.H" #include "Fl_GDI_Graphics_Driver.H"
void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) { void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) {
// According to Bill, the "default" cap and join should be the // According to Bill, the "default" cap and join should be the
// "fastest" mode supported for the platform. I don't know why // "fastest" mode supported for the platform. I don't know why
@ -45,11 +45,10 @@ void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, float width, char* d
} else { } else {
s1 |= style & 0xff; // allow them to pass any low 8 bits for style s1 |= style & 0xff; // allow them to pass any low 8 bits for style
} }
if ((style || n) && !width) width = scale(); // fix cards that do nothing for 0? if ((style || n) && !width) width = int(scale()); // fix cards that do nothing for 0?
if (!fl_current_xmap) color(FL_BLACK); if (!fl_current_xmap) color(FL_BLACK);
LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()? LOGBRUSH penbrush = {BS_SOLID,fl_RGB(),0}; // can this be fl_brush()?
int tw = ( width < 1.f ? 1 : int(width) ); HPEN newpen = ExtCreatePen(s1, width, &penbrush, n, n ? a : 0);
HPEN newpen = ExtCreatePen(s1, tw, &penbrush, n, n ? a : 0);
if (!newpen) { if (!newpen) {
Fl::error("fl_line_style(): Could not create GDI pen object."); Fl::error("fl_line_style(): Could not create GDI pen object.");
return; return;

View File

@ -47,16 +47,6 @@ void Fl_GDI_Graphics_Driver::overlay_rect(int x, int y, int w , int h) {
LineTo(gc_, x, y); LineTo(gc_, x, y);
} }
void Fl_GDI_Graphics_Driver::rect(int x, int y, int w, int h)
{
if (w > 0 && h > 0) {
xyline(x, y, (x+w-1));
yxline(x, y, (y+h-1));
yxline((x+w-1), y, (y+h-1));
xyline(x, (y+h-1), (x+w-1));
}
}
void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) { void Fl_GDI_Graphics_Driver::focus_rect(int x, int y, int w, int h) {
// Windows 95/98/ME do not implement the dotted line style, so draw // Windows 95/98/ME do not implement the dotted line style, so draw
// every other pixel around the focus area... // every other pixel around the focus area...
@ -71,127 +61,76 @@ 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) SetPixel(gc_, x, y+yy, c); for (yy = h; yy > 0; yy--, i++) if (i & 1) SetPixel(gc_, x, y+yy, c);
} }
void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) { void Fl_GDI_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) {
if (w<=0 || h<=0) return;
RECT rect; RECT rect;
rect.left = this->floor(x); rect.top = this->floor(y); rect.left = x; rect.top = y;
rect.right = this->floor(x + w); rect.bottom = this->floor(y + h); rect.right = (x + w); rect.bottom = (y + h);
FillRect(gc_, &rect, fl_brush()); FillRect(gc_, &rect, fl_brush());
} }
void Fl_GDI_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) { void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) {
MoveToEx(gc_, int(x), int(y), 0L); MoveToEx(gc_, x, y, 0L);
LineTo(gc_, int(x1), int(y1)); LineTo(gc_, x1, y1);
SetPixel(gc_, int(x1), int(y1), fl_RGB()); SetPixel(gc_, x1, y1, fl_RGB());
} }
void Fl_GDI_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) { void Fl_GDI_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
MoveToEx(gc_, int(x), int(y), 0L); MoveToEx(gc_, x, y, 0L);
LineTo(gc_, int(x1), int(y1)); LineTo(gc_, x1, y1);
LineTo(gc_, int(x2), int(y2)); LineTo(gc_, x2, y2);
SetPixel(gc_, int(x2), int(y2), fl_RGB()); SetPixel(gc_, x2, y2, fl_RGB());
} }
static HPEN change_pen_width(int width, HDC gc) { // set the width of the pen, return previous pen void* Fl_GDI_Graphics_Driver::change_pen_width(int width) { // set the width of the pen, return previous pen
LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0}; LOGBRUSH penbrush = {BS_SOLID, fl_RGB(), 0};
HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0); HPEN newpen = ExtCreatePen(PS_GEOMETRIC | PS_ENDCAP_FLAT | PS_JOIN_ROUND, width, &penbrush, 0, 0);
return (HPEN)SelectObject(gc, newpen); return SelectObject(gc_, newpen);
} }
void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1) { void Fl_GDI_Graphics_Driver::reset_pen_width(void *data) {
if (y < 0) return; DeleteObject(SelectObject(gc_, (HPEN)data));
float s = scale();
int xx = (x < x1 ? x : x1);
int xx1 = (x < x1 ? x1 : x);
if (s != int(s) && line_width_ <= int(s)) {
int lwidth = this->floor((y+1)) - this->floor(y);
bool need_pen = (lwidth != int(s));
HPEN oldpen = (need_pen ? change_pen_width(lwidth, gc_) : NULL);
MoveToEx(gc_, this->floor(xx), this->floor(y) + int(lwidth/2.f) , 0L);
LineTo(gc_, this->floor((xx1+1)), this->floor(y) + int(lwidth/2.f));
if (need_pen) {
DeleteObject(SelectObject(gc_, oldpen));
}
} else {
y = int((y + 0.5f) * s);
MoveToEx(gc_, this->floor(xx), y, 0L);
LineTo(gc_, this->floor(xx1) + int(s) , y);
}
} }
void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2) { void Fl_GDI_Graphics_Driver::xyline_unscaled(int x, int y, int x1) {
xyline(x, y, x1); MoveToEx(gc_, x, y, 0L);
yxline(x1, y, y2); LineTo(gc_, x1+1 , y);
} }
void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { void Fl_GDI_Graphics_Driver::yxline_unscaled(int x, int y, int y1) {
xyline(x, y, x1); MoveToEx(gc_, x, y, 0L);
yxline(x1, y, y2); LineTo(gc_, x, y1+1);
xyline(x1, y2, x3);
} }
void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1) { void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
if (x < 0) return; MoveToEx(gc_, x, y, 0L);
double s = scale(); LineTo(gc_, x1, y1);
int yy = (y < y1 ? y : y1); LineTo(gc_, x2, y2);
int yy1 = (y < y1 ? y1 : y); LineTo(gc_, x, y);
if (s != int(s) && line_width_ <= int(s)) {
int lwidth = (this->floor((x+1)) - this->floor(x));
bool need_pen = (lwidth != int(s));
HPEN oldpen = (need_pen ? change_pen_width(lwidth, gc_) : NULL);
MoveToEx(gc_, this->floor(x) + int(lwidth/2.f), this->floor(yy), 0L);
LineTo(gc_, this->floor(x) + int(lwidth/2.f), this->floor((yy1+1)) );
if (need_pen) {
DeleteObject(SelectObject(gc_, oldpen));
}
} else {
x = int((x + 0.5f) * s);
MoveToEx(gc_, x, this->floor(yy), 0L);
LineTo(gc_, x, this->floor(yy1) + int(s));
}
} }
void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2) { void Fl_GDI_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
yxline(x, y, y1); MoveToEx(gc_, x, y, 0L);
xyline(x, y1, x2); LineTo(gc_, x1, y1);
LineTo(gc_, x2, y2);
LineTo(gc_, x3, y3);
LineTo(gc_, x, y);
} }
void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
yxline(x, y, y1);
xyline(x, y1, x2);
yxline(x2, y1, y3);
}
void Fl_GDI_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
MoveToEx(gc_, int(x), int(y), 0L);
LineTo(gc_, int(x1), int(y1));
LineTo(gc_, int(x2), int(y2));
LineTo(gc_, int(x), int(y));
}
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_, int(x), int(y), 0L);
LineTo(gc_, int(x1), int(y1));
LineTo(gc_, int(x2), int(y2));
LineTo(gc_, int(x3), int(y3));
LineTo(gc_, int(x), int(y));
}
void Fl_GDI_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
POINT p[3]; POINT p[3];
p[0].x = int(x); p[0].y = int(y); p[0].x = x; p[0].y = y;
p[1].x = int(x1); p[1].y = int(y1); p[1].x = x1; p[1].y = y1;
p[2].x = int(x2); p[2].y = int(y2); p[2].x = x2; p[2].y = y2;
SelectObject(gc_, fl_brush()); SelectObject(gc_, fl_brush());
Polygon(gc_, p, 3); Polygon(gc_, p, 3);
} }
void Fl_GDI_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) { void Fl_GDI_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
POINT p[4]; POINT p[4];
p[0].x = int(x); p[0].y = int(y); p[0].x = x; p[0].y = y;
p[1].x = int(x1); p[1].y = int(y1); p[1].x = x1; p[1].y = y1;
p[2].x = int(x2); p[2].y = int(y2); p[2].x = x2; p[2].y = y2;
p[3].x = int(x3); p[3].y = int(y3); p[3].x = x3; p[3].y = y3;
SelectObject(gc_, fl_brush()); SelectObject(gc_, fl_brush());
Polygon(gc_, p, 4); Polygon(gc_, p, 4);
} }

View File

@ -501,12 +501,12 @@ Fl_WinAPI_Screen_Driver::read_win_rectangle(
int ws, hs; int ws, hs;
if (int(s) == s) { ws = w * int(s); hs = h * int(s);} if (int(s) == s) { ws = w * int(s); hs = h * int(s);}
else { else {
ws = Fl_GDI_Graphics_Driver::floor(w+1, s); // approximates what Fl_Graphics_Driver::cache_size() does ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Fl_Scalable_Graphics_Driver::floor(X, s),
hs = Fl_GDI_Graphics_Driver::floor(h+1, s); hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Fl_Scalable_Graphics_Driver::floor(Y, s);
if (ws < 1) ws = 1; if (ws < 1) ws = 1;
if (hs < 1) hs = 1; if (hs < 1) hs = 1;
} }
return read_win_rectangle_unscaled(Fl_GDI_Graphics_Driver::floor(X, s), Fl_GDI_Graphics_Driver::floor(Y, s), ws, hs, win); return read_win_rectangle_unscaled(Fl_Scalable_Graphics_Driver::floor(X, s), Fl_Scalable_Graphics_Driver::floor(Y, s), ws, hs, win);
} }
Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win) Fl_RGB_Image *Fl_WinAPI_Screen_Driver::read_win_rectangle_unscaled(int X, int Y, int w, int h, Fl_Window *win)

View File

@ -774,7 +774,8 @@ Fl_RGB_Image *Fl_X11_Screen_Driver::read_win_rectangle(int X, int Y, int w, int
Window xid = (win && !allow_outside ? fl_xid(win) : fl_window); Window xid = (win && !allow_outside ? fl_xid(win) : fl_window);
float s = allow_outside ? Fl::screen_driver()->scale(win->screen_num()) : Fl_Surface_Device::surface()->driver()->scale(); float s = allow_outside ? Fl::screen_driver()->scale(win->screen_num()) : Fl_Surface_Device::surface()->driver()->scale();
int ws = w * s, hs = h * s, Xs = X*s, Ys = Y*s; int Xs = Fl_Scalable_Graphics_Driver::floor(X, s), Ys = Fl_Scalable_Graphics_Driver::floor(Y, s),
ws = Fl_Scalable_Graphics_Driver::floor(X+w, s) - Xs, hs = Fl_Scalable_Graphics_Driver::floor(Y+h, s) - Ys;
# ifdef __sgi # ifdef __sgi
if (XReadDisplayQueryExtension(fl_display, &i, &i)) { if (XReadDisplayQueryExtension(fl_display, &i, &i)) {

View File

@ -57,7 +57,6 @@ private:
unsigned depth_; // depth of translation stack unsigned depth_; // depth of translation stack
int stack_x_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE]; // translation stack allowing cumulative translations int stack_x_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE]; // translation stack allowing cumulative translations
int stack_y_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE]; int stack_y_[FL_XLIB_GRAPHICS_TRANSLATION_STACK_SIZE];
int line_delta_;
virtual void set_current_(); virtual void set_current_();
int clip_max_; // +/- x/y coordinate limit (16-bit coordinate space) int clip_max_; // +/- x/y coordinate limit (16-bit coordinate space)
virtual void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); virtual void draw_fixed(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
@ -139,18 +138,17 @@ public:
protected: protected:
virtual void transformed_vertex0(float x, float y); virtual void transformed_vertex0(float x, float y);
void fixloop(); void fixloop();
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx virtual void focus_rect(int x, int y, int w, int h);
virtual void point_unscaled(float x, float y); virtual void rectf_unscaled(int x, int y, int w, int h);
virtual void rect_unscaled(float x, float y, float w, float h); virtual void line_unscaled(int x, int y, int x1, int y1);
virtual void rectf_unscaled(float x, float y, float w, float h); virtual void xyline_unscaled(int x, int y, int x1);
virtual void line_unscaled(float x, float y, float x1, float y1); virtual void *change_pen_width(int lwidth);
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2); virtual void reset_pen_width(void *data);
virtual void xyline_unscaled(float x, float y, float x1); virtual void yxline_unscaled(int x, int y, int y1);
virtual void yxline_unscaled(float x, float y, float y1); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2); virtual void loop_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2); virtual void polygon_unscaled(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
// Scaling and clipping stuff for internal usage. // Scaling and clipping stuff for internal usage.
// Currently specific to Fl_Xlib_Graphics_Driver (16-bit coordinate clipping) // Currently specific to Fl_Xlib_Graphics_Driver (16-bit coordinate clipping)
@ -194,10 +192,9 @@ protected:
void end_complex_polygon(); void end_complex_polygon();
void gap(); void gap();
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry); 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 virtual void arc_unscaled(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(int x, int y, int w, int 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, int width, char* dashes);
virtual void line_style_unscaled(int style, float width, char* dashes);
void color(Fl_Color c); void color(Fl_Color c);
void set_color(Fl_Color i, unsigned int c); void set_color(Fl_Color i, unsigned int c);
void free_color(Fl_Color i, int overlay); void free_color(Fl_Color i, int overlay);

View File

@ -50,7 +50,6 @@ GC fl_gc = 0;
Fl_Xlib_Graphics_Driver::Fl_Xlib_Graphics_Driver(void) { Fl_Xlib_Graphics_Driver::Fl_Xlib_Graphics_Driver(void) {
mask_bitmap_ = NULL; mask_bitmap_ = NULL;
p = NULL; p = NULL;
line_delta_ = 0;
#if USE_PANGO #if USE_PANGO
Fl_Graphics_Driver::font(0, 0); Fl_Graphics_Driver::font(0, 0);
#endif #endif
@ -76,17 +75,6 @@ void Fl_Xlib_Graphics_Driver::scale(float f) {
Fl_Graphics_Driver::scale(f); Fl_Graphics_Driver::scale(f);
//fprintf(stderr, "scale=%.2f\n", scale_); //fprintf(stderr, "scale=%.2f\n", scale_);
line_style(FL_SOLID); // scale also default line width 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.9/*1.75*/ ? 1 : 0);
} }
#endif #endif
} }
@ -109,8 +97,8 @@ void Fl_Xlib_Graphics_Driver::transformed_vertex0(float fx, float fy) {
p_size = p ? 2*p_size : 16; p_size = p ? 2*p_size : 16;
p = (XPOINT*)realloc((void*)p, p_size*sizeof(*p)); p = (XPOINT*)realloc((void*)p, p_size*sizeof(*p));
} }
p[n].x = x + line_delta_; p[n].x = x ;
p[n].y = y + line_delta_; p[n].y = y ;
n++; n++;
} }
} }
@ -242,15 +230,12 @@ void Fl_Xlib_Graphics_Driver::font_name(int num, const char *name) {
Region Fl_Xlib_Graphics_Driver::scale_clip(float f) { Region Fl_Xlib_Graphics_Driver::scale_clip(float f) {
Region r = rstack[rstackptr]; Region r = rstack[rstackptr];
if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0; if (r == 0 || (f == 1 && offset_x_ == 0 && offset_y_ == 0) ) return 0;
int deltaf = f/2;
Region r2 = XCreateRegion(); Region r2 = XCreateRegion();
for (int i = 0; i < r->numRects; i++) { for (int i = 0; i < r->numRects; i++) {
int x = (r->rects[i].x1 + offset_x_)*f; int x = floor(r->rects[i].x1 + offset_x_, f);
int y = (r->rects[i].y1 + offset_y_)*f; int y = floor(r->rects[i].y1 + offset_y_, f);
int w = int((r->rects[i].x2 + offset_x_) * f) - x; int w = floor((r->rects[i].x2 + offset_x_) , f) - x;
int h = int((r->rects[i].y2 + offset_y_) * f) - y; int h = floor((r->rects[i].y2 + offset_y_) , f) - y;
x += line_delta_ - deltaf;
y += line_delta_ - deltaf;
Region R = XRectangleRegion(x, y, w, h); Region R = XRectangleRegion(x, y, w, h);
XUnionRegion(R, r2, r2); XUnionRegion(R, r2, r2);
::XDestroyRegion(R); ::XDestroyRegion(R);

View File

@ -24,15 +24,18 @@
\brief Utility functions for drawing circles using integers \brief Utility functions for drawing circles using integers
*/ */
void Fl_Xlib_Graphics_Driver::arc_unscaled(float x,float y,float w,float h,double a1,double a2) { void Fl_Xlib_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) {
if (w <= 0 || h <= 0) return; if (w <= 0 || h <= 0) return;
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)); x += floor(offset_x_);
y += floor(offset_y_);
XDrawArc(fl_display, fl_window, gc_, x, y, w, h, int(a1*64),int((a2-a1)*64));
} }
void Fl_Xlib_Graphics_Driver::pie_unscaled(float x,float y,float w,float h,double a1,double a2) { void Fl_Xlib_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1,double a2) {
if (w <= 0 || h <= 0) return; if (w <= 2 || h <= 2) return;
x += offset_x_*scale(); x += floor(offset_x_);
y += offset_y_*scale(); y += floor(offset_y_);
XDrawArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64)); int extra = scale() >= 3 ? 1 : 0;
XFillArc(fl_display, fl_window, gc_, x,y,w-1,h-1, int(a1*64),int((a2-a1)*64)); XDrawArc(fl_display, fl_window, gc_, x+1+extra, y+1+extra, w-2-2*extra, h-2-2*extra, int(a1*64), int((a2-a1)*64));
XFillArc(fl_display, fl_window, gc_, x+1, y+1, w-2, h-2, int(a1*64), int((a2-a1)*64));
} }

View File

@ -779,8 +779,8 @@ void Fl_Xlib_Graphics_Driver::text_extents_unscaled(const char *c, int n, int &d
w = gi.width; w = gi.width;
h = gi.height; h = gi.height;
dx = -gi.x + line_delta_; dx = -gi.x ;
dy = -gi.y + line_delta_; dy = -gi.y ;
correct_extents(scale(), dx, dy, w, h); correct_extents(scale(), dx, dy, w, h);
} }
@ -788,10 +788,10 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int y
// transform coordinates and clip if outside 16-bit space (STR 2798) // transform coordinates and clip if outside 16-bit space (STR 2798)
int x1 = x + offset_x_ * scale() + line_delta_; int x1 = x + floor(offset_x_) ;
if (x1 < clip_min() || x1 > clip_max()) return; if (x1 < clip_min() || x1 > clip_max()) return;
int y1 = y + offset_y_ * scale() + line_delta_; int y1 = y + floor(offset_y_) ;
if (y1 < clip_min() || y1 > clip_max()) return; if (y1 < clip_min() || y1 > clip_max()) return;
#if USE_OVERLAY #if USE_OVERLAY
@ -870,7 +870,7 @@ void Fl_Xlib_Graphics_Driver::drawUCS4(const void *str, int n, int x, int y) {
color.color.blue = ((int)b)*0x101; color.color.blue = ((int)b)*0x101;
color.color.alpha = 0xffff; color.color.alpha = 0xffff;
XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+offset_x_*scale()+line_delta_, y+offset_y_*scale()+line_delta_, (FcChar32 *)str, n); XftDrawString32(draw_, &color, ((Fl_Xlib_Font_Descriptor*)font_descriptor())->font, x+floor(offset_x_), y+floor(offset_y_), (FcChar32 *)str, n);
} }
@ -1256,12 +1256,12 @@ void Fl_Xlib_Graphics_Driver::font_unscaled(Fl_Font fnum, Fl_Fontsize size) {
} }
void Fl_Xlib_Graphics_Driver::draw_unscaled(const char *str, int n, int x, int 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()); do_draw(0, str, n, x + floor(offset_x_), y + floor(offset_y_));
} }
void Fl_Xlib_Graphics_Driver::draw_unscaled(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 PangoMatrix mat = PANGO_MATRIX_INIT; // 1.6
pango_matrix_translate(&mat, x+offset_x_*scale(), y+offset_y_*scale()); // 1.6 pango_matrix_translate(&mat, x + floor(offset_x_), y + floor(offset_y_)); // 1.6
double l = width_unscaled(str, n); double l = width_unscaled(str, n);
pango_matrix_rotate(&mat, angle); // 1.6 pango_matrix_rotate(&mat, angle); // 1.6
pango_context_set_matrix(pctxt_, &mat); // 1.6 pango_context_set_matrix(pctxt_, &mat); // 1.6
@ -1275,7 +1275,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(int angle, const char *str, int n, i
} }
void Fl_Xlib_Graphics_Driver::rtl_draw_unscaled(const char* str, int n, int x, int 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()); do_draw(1, str, n, x+floor(offset_x_), y+floor(offset_y_));
} }
/* Compute dx, dy, w, h so that fl_rect(x+dx, y+dy, w, h) is the bounding box /* Compute dx, dy, w, h so that fl_rect(x+dx, y+dy, w, h) is the bounding box
@ -1343,8 +1343,8 @@ void Fl_Xlib_Graphics_Driver::do_draw(int from_right, const char *str, int n, in
if (from_right) { if (from_right) {
x -= w; x -= w;
} }
pango_xft_render_layout(draw_, &color, playout_, (x + line_delta_)*PANGO_SCALE, pango_xft_render_layout(draw_, &color, playout_, x * PANGO_SCALE,
(y - y_correction + line_delta_ - lheight + desc)*PANGO_SCALE ); // 1.8 (y - y_correction - lheight + desc) * PANGO_SCALE ); // 1.8
} }
double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) { double Fl_Xlib_Graphics_Driver::width_unscaled(const char* str, int n) {

View File

@ -580,7 +580,7 @@ void Fl_Xlib_Graphics_Driver::draw_image_unscaled(const uchar* buf, int x, int y
if (alpha) d ^= FL_IMAGE_WITH_ALPHA; if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
const int mono = (d>-3 && d<3); const int mono = (d>-3 && d<3);
innards(buf,x+offset_x_*scale(),y+offset_y_*scale(),w,h,d,l,mono,0,0,alpha,gc_); innards(buf,x+floor(offset_x_),y+floor(offset_y_),w,h,d,l,mono,0,0,alpha,gc_);
} }
void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data,
@ -590,16 +590,16 @@ void Fl_Xlib_Graphics_Driver::draw_image_unscaled(Fl_Draw_Image_Cb cb, void* dat
if (alpha) d ^= FL_IMAGE_WITH_ALPHA; if (alpha) d ^= FL_IMAGE_WITH_ALPHA;
const int mono = (d>-3 && d<3); const int mono = (d>-3 && d<3);
innards(0,x+offset_x_*scale(),y+offset_y_*scale(),w,h,d,0,mono,cb,data,alpha,gc_); innards(0,x+floor(offset_x_),y+floor(offset_y_),w,h,d,0,mono,cb,data,alpha,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){ 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_); innards(buf,x+floor(offset_x_),y+floor(offset_y_),w,h,d,l,1,0,0,0,gc_);
} }
void Fl_Xlib_Graphics_Driver::draw_image_mono_unscaled(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) { int x, int y, int w, int h,int d) {
innards(0,x+offset_x_*scale(),y+offset_y_*scale(),w,h,d,0,1,cb,data,0,gc_); innards(0,x+floor(offset_x_),y+floor(offset_y_),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) { void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
@ -623,8 +623,8 @@ void Fl_Xlib_Graphics_Driver::delete_bitmask(Fl_Bitmask bm) {
} }
void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) { void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Bitmap *bm, int X, int Y, int W, int H, int cx, int cy) {
X = (X+offset_x_)*scale(); X = floor(X)+floor(offset_x_);
Y = (Y+offset_y_)*scale(); Y = floor(Y)+floor(offset_y_);
cache_size(bm, W, H); cache_size(bm, W, H);
cx *= scale(); cy *= scale(); cx *= scale(); cy *= scale();
XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm)); XSetStipple(fl_display, gc_, *Fl_Graphics_Driver::id(bm));
@ -737,8 +737,8 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_RGB_Image *img) {
void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
X = (X+offset_x_)*scale(); X = floor(X)+floor(offset_x_);
Y = (Y+offset_y_)*scale(); Y = floor(Y)+floor(offset_y_);
cache_size(img, W, H); cache_size(img, W, H);
cx *= scale(); cy *= scale(); cx *= scale(); cy *= scale();
if (img->d() == 1 || img->d() == 3) { if (img->d() == 1 || img->d() == 3) {
@ -783,7 +783,8 @@ void Fl_Xlib_Graphics_Driver::draw_rgb(Fl_RGB_Image *rgb, int XP, int YP, int WP
} }
scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(),
rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull), rgb->data_w() / double(Wfull), rgb->data_h() / double(Hfull),
(XP-cx + offset_x_)*scale()-offset, (YP-cy + offset_y_)*scale()-offset, Wfull, Hfull); floor(XP-cx) + floor(offset_x_) - offset, floor(YP-cy) + floor(offset_y_) - offset,
Wfull, Hfull);
pop_clip(); pop_clip();
} }
@ -851,8 +852,8 @@ void Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) {
} }
void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) { void Fl_Xlib_Graphics_Driver::draw_fixed(Fl_Pixmap *pxm, int X, int Y, int W, int H, int cx, int cy) {
X = (X+offset_x_)*scale(); X = floor(X)+floor(offset_x_);
Y = (Y+offset_y_)*scale(); Y = floor(Y)+floor(offset_y_);
cache_size(pxm, W, H); cache_size(pxm, W, H);
cx *= scale(); cy *= scale(); cx *= scale(); cy *= scale();
Fl_Region r2 = scale_clip(scale()); Fl_Region r2 = scale_clip(scale());

View File

@ -26,7 +26,7 @@
#include "Fl_Xlib_Graphics_Driver.H" #include "Fl_Xlib_Graphics_Driver.H"
void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, float width, char* dashes) { void Fl_Xlib_Graphics_Driver::line_style_unscaled(int style, int width, char* dashes) {
int ndashes = dashes ? strlen(dashes) : 0; int ndashes = dashes ? strlen(dashes) : 0;
// emulate the Windows dash patterns on X // emulate the Windows dash patterns on X
@ -61,3 +61,19 @@ if (*dashes == 0) ndashes = 0;//against error with very small scaling
Cap[(style>>8)&3], Join[(style>>12)&3]); Cap[(style>>8)&3], Join[(style>>12)&3]);
if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes); if (ndashes) XSetDashes(fl_display, gc_, 0, dashes, ndashes);
} }
void *Fl_Xlib_Graphics_Driver::change_pen_width(int lwidth) {
XGCValues *gc_values = (XGCValues*)malloc(sizeof(XGCValues));
gc_values->line_width = lwidth;
XChangeGC(fl_display, gc_, GCLineWidth, gc_values);
gc_values->line_width = line_width_;
line_width_ = lwidth;
return gc_values;
}
void Fl_Xlib_Graphics_Driver::reset_pen_width(void *data) {
XGCValues *gc_values = (XGCValues*)data;
line_width_ = gc_values->line_width;
XChangeGC(fl_display, gc_, GCLineWidth, gc_values);
delete gc_values;
}

View File

@ -208,123 +208,86 @@ void Fl_Xlib_Graphics_Driver::XDestroyRegion(Fl_Region r) {
// --- line and polygon drawing // --- line and polygon drawing
// called only when scale_ has integer value void Fl_Xlib_Graphics_Driver::focus_rect(int x, int y, int w, int h)
void Fl_Xlib_Graphics_Driver::rect_unscaled(float fx, float fy, float fw, float fh) { {
if (fw<=0 || fh<=0) return; w = this->floor(x + w) - this->floor(x);
int deltaf = scale() >= 2 ? scale()-1 : 0; h = this->floor(y + h) - this->floor(y);
fx += offset_x_*scale(); fy += offset_y_*scale(); x = this->floor(x) + floor(offset_x_);
int x = fx; int y = fy; y = this->floor(y) + floor(offset_y_);
int w = int(fw) - 1 - deltaf; if (!clip_rect(x, y, w, h)) {
int h = int(fh) - 1 - deltaf; line_style(FL_DOT);
XDrawRectangle(fl_display, fl_window, gc_, x, y, w, h);
line_style(FL_SOLID);
}
}
void Fl_Xlib_Graphics_Driver::rectf_unscaled(int x, int y, int w, int h) {
x += floor(offset_x_);
y += floor(offset_y_);
if (!clip_rect(x, y, w, h)) if (!clip_rect(x, y, w, h))
XDrawRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, w, h); XFillRectangle(fl_display, fl_window, gc_, x, y, w, h);
} }
void Fl_Xlib_Graphics_Driver::rectf_unscaled(float fx, float fy, float fw, float fh) { void Fl_Xlib_Graphics_Driver::line_unscaled(int x, int y, int x1, int y1) {
if (fw<=0 || fh<=0) return; draw_clipped_line(x + this->floor(offset_x_) , y + this->floor(offset_y_) ,
int deltaf = scale() >= 2 ? scale()/2 : 0; x1 + this->floor(offset_x_) , y1 + this->floor(offset_y_) );
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_rect(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) { void Fl_Xlib_Graphics_Driver::xyline_unscaled(int x, int y, int x1) {
int deltaf = scale() >= 2 ? scale()/2 : 0; if (line_width_ >= 2) x1++;
int x = fx+offset_x_*scale()-deltaf; x += floor(offset_x_) ;
int y = fy+offset_y_*scale()-deltaf; y += floor(offset_y_) ;
int width = scale() >= 1 ? scale() : 1; x1 += floor(offset_x_) ;
// *FIXME* This needs X coordinate clipping: draw_clipped_line(x, y, x1, y);
XFillRectangle(fl_display, fl_window, gc_, x+line_delta_, y+line_delta_, width, width);
} }
void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1) { void Fl_Xlib_Graphics_Driver::yxline_unscaled(int x, int y, int y1) {
if (x == x1) yxline_unscaled(x, y, y1); if (line_width_ >= 2) y1++;
else if (y == y1) xyline_unscaled(x, y, x1); x += floor(offset_x_) ;
else draw_clipped_line(x+offset_x_*scale()+line_delta_, y+offset_y_*scale()+line_delta_, x1+offset_x_*scale()+line_delta_, y1+offset_y_*scale()+line_delta_); y += floor(offset_y_) ;
y1 += floor(offset_y_) ;
draw_clipped_line(x, y, x, y1);
} }
void Fl_Xlib_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1, float x2, float y2) { void Fl_Xlib_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
XPoint p[3];
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_;
// *FIXME* This needs X coordinate clipping!
XDrawLines(fl_display, fl_window, gc_, p, 3, 0);
}
void Fl_Xlib_Graphics_Driver::xyline_unscaled(float x, float y, float x1) {
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_xy(x+line_delta_); if (scale() >= 2) ix -= int(scale()/2);
int iy = clip_xy(y+line_delta_);
// make sure that line output by xyline(a,b,c) extends to pixel just at left of where xyline(c+1,b,d) begins
int ix1 = int(x1/scale()+1.5)*scale()-1;
ix1 += line_delta_; if (scale() >= 4) ix1 -= 1;
draw_clipped_line(ix, iy, ix1, iy);
// 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 )
draw_clipped_line(ix, iy+1, ix1, iy+1);
}
void Fl_Xlib_Graphics_Driver::yxline_unscaled(float x, float y, float y1) {
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_xy(x+line_delta_);
int iy = clip_xy(y+line_delta_); if (scale() >= 2) iy -= int(scale()/2);
int iy1 = int(y1/scale()+1.5)*scale()-1;
// make sure that line output by yxline(a,b,c) extends to pixel just above where yxline(a,c+1,d) begins
iy1 += line_delta_; if (scale() >= 4) iy1 -= 1;
draw_clipped_line(ix, iy, ix, iy1);
// 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)
draw_clipped_line(ix+1, iy, ix+1, iy1);
}
void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2) {
XPoint p[4]; XPoint p[4];
p[0].x = x +offset_x_*scale()+line_delta_; p[0].y = y +offset_y_*scale()+line_delta_; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ;
p[1].x = x1 +offset_x_*scale()+line_delta_; p[1].y = y1 +offset_y_*scale()+line_delta_; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ;
p[2].x = x2 +offset_x_*scale()+line_delta_; p[2].y = y2 +offset_y_*scale()+line_delta_; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ;
p[3].x = x +offset_x_*scale()+line_delta_; p[3].y = y +offset_y_*scale()+line_delta_; p[3].x = p[0].x; p[3].y = p[0].y;
// *FIXME* This needs X coordinate clipping! // *FIXME* This needs X coordinate clipping!
XDrawLines(fl_display, fl_window, gc_, p, 4, 0); XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
} }
void Fl_Xlib_Graphics_Driver::loop_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) { void Fl_Xlib_Graphics_Driver::loop_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
XPoint p[5]; XPoint p[5];
p[0].x = x+offset_x_*scale()+line_delta_; p[0].y = y+offset_y_*scale()+line_delta_; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ;
p[1].x = x1 +offset_x_*scale()+line_delta_; p[1].y = y1+offset_y_*scale()+line_delta_; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ;
p[2].x = x2+offset_x_*scale()+line_delta_; p[2].y = y2+offset_y_*scale()+line_delta_; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ;
p[3].x = x3+offset_x_*scale()+line_delta_; p[3].y = y3+offset_y_*scale()+line_delta_; p[3].x = x3 + floor(offset_x_) ; p[3].y = y3 + floor(offset_y_) ;
p[4].x = x+offset_x_*scale()+line_delta_; p[4].y = y+offset_y_*scale()+line_delta_; p[4].x = p[0].x; p[4].y = p[0].y;
// *FIXME* This needs X coordinate clipping! // *FIXME* This needs X coordinate clipping!
XDrawLines(fl_display, fl_window, gc_, p, 5, 0); XDrawLines(fl_display, fl_window, gc_, p, 5, 0);
} }
void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2) { void Fl_Xlib_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2) {
XPoint p[4]; XPoint p[4];
p[0].x = x+offset_x_*scale()+line_delta_; p[0].y = y+offset_y_*scale()+line_delta_; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ;
p[1].x = x1+offset_x_*scale()+line_delta_; p[1].y = y1+offset_y_*scale()+line_delta_; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ;
p[2].x = x2+offset_x_*scale()+line_delta_; p[2].y = y2+offset_y_*scale()+line_delta_; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ;
p[3].x = x+offset_x_*scale()+line_delta_; p[3].y = y+offset_y_*scale()+line_delta_; p[3].x = p[0].x; p[3].y = p[0].y;
// *FIXME* This needs X coordinate clipping! // *FIXME* This needs X coordinate clipping!
XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0); XFillPolygon(fl_display, fl_window, gc_, p, 3, Convex, 0);
XDrawLines(fl_display, fl_window, gc_, p, 4, 0); XDrawLines(fl_display, fl_window, gc_, p, 4, 0);
} }
void Fl_Xlib_Graphics_Driver::polygon_unscaled(float x, float y, float x1, float y1, float x2, float y2, float x3, float y3) { void Fl_Xlib_Graphics_Driver::polygon_unscaled(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
XPoint p[5]; XPoint p[5];
p[0].x = x+offset_x_*scale()+line_delta_; p[0].y = y+offset_y_*scale()+line_delta_; p[0].x = x + floor(offset_x_) ; p[0].y = y + floor(offset_y_) ;
p[1].x = x1+offset_x_*scale()+line_delta_; p[1].y = y1+offset_y_*scale()+line_delta_; p[1].x = x1 + floor(offset_x_) ; p[1].y = y1 + floor(offset_y_) ;
p[2].x = x2+offset_x_*scale()+line_delta_; p[2].y = y2+offset_y_*scale()+line_delta_; p[2].x = x2 + floor(offset_x_) ; p[2].y = y2 + floor(offset_y_) ;
p[3].x = x3+offset_x_*scale()+line_delta_; p[3].y = y3+offset_y_*scale()+line_delta_; p[3].x = x3 + floor(offset_x_) ; p[3].y = y3 + floor(offset_y_) ;
p[4].x = x+offset_x_*scale()+line_delta_; p[4].y = y+offset_y_*scale()+line_delta_; p[4].x = p[0].x; p[4].y = p[0].y;
// *FIXME* This needs X coordinate clipping! // *FIXME* This needs X coordinate clipping!
XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0); XFillPolygon(fl_display, fl_window, gc_, p, 4, Convex, 0);
XDrawLines(fl_display, fl_window, gc_, p, 5, 0); XDrawLines(fl_display, fl_window, gc_, p, 5, 0);

View File

@ -43,7 +43,7 @@ void Fl_Xlib_Graphics_Driver::end_line() {
void Fl_Xlib_Graphics_Driver::end_loop() { void Fl_Xlib_Graphics_Driver::end_loop() {
fixloop(); fixloop();
if (n>2) { if (n>2) {
transformed_vertex0(p[0].x - line_delta_, p[0].y - line_delta_); transformed_vertex0(p[0].x , p[0].y );
} }
end_line(); end_line();
} }
@ -60,7 +60,7 @@ void Fl_Xlib_Graphics_Driver::end_polygon() {
void Fl_Xlib_Graphics_Driver::gap() { 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--; while (n>gap_+2 && p[n-1].x == p[gap_].x && p[n-1].y == p[gap_].y) n--;
if (n > gap_+2) { if (n > gap_+2) {
transformed_vertex0(p[gap_].x - line_delta_, p[gap_].y - line_delta_); transformed_vertex0(p[gap_].x, p[gap_].y);
gap_ = n; gap_ = n;
} else { } else {
n = gap_; n = gap_;