From d34974ace7d9beeb991ef387a0b2e6b981659e47 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Wed, 20 Jan 2016 15:21:11 +0000 Subject: Reorganized all integer line and polygon drawing functions git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11016 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 --- FL/Fl_Device.H | 67 +++-- src/Fl_Gl_Window.cxx | 77 ++++-- src/fl_rect.cxx | 737 +++++++++++++++++++++++++-------------------------- 3 files changed, 474 insertions(+), 407 deletions(-) diff --git a/FL/Fl_Device.H b/FL/Fl_Device.H index 5adf9483a..7a93bf690 100644 --- a/FL/Fl_Device.H +++ b/FL/Fl_Device.H @@ -250,21 +250,21 @@ protected: /** \brief see fl_line_style(int style, int width, char* dashes). */ virtual void line_style(int style, int width=0, char* dashes=0); /** \brief see fl_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) = 0; /** \brief see fl_xyline(int x, int y, int x1, int y2). */ - virtual void xyline(int x, int y, int x1, int y2); + virtual void xyline(int x, int y, int x1, int y2) = 0; /** \brief see fl_xyline(int x, int y, int x1, int y2, int x3). */ - virtual void xyline(int x, int y, int x1, int y2, int x3); + virtual void xyline(int x, int y, int x1, int y2, int x3) = 0; /** \brief see fl_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) = 0; /** \brief see fl_yxline(int x, int y, int y1, int x2). */ - virtual void yxline(int x, int y, int y1, int x2); + virtual void yxline(int x, int y, int y1, int x2) = 0; /** \brief see fl_yxline(int x, int y, int y1, int x2, int y3). */ - virtual void yxline(int x, int y, int y1, int x2, int y3); + virtual void yxline(int x, int y, int y1, int x2, int y3) = 0; /** \brief see fl_line(int x, int y, int x1, int y1). */ - virtual void line(int x, int y, int x1, int y1); + virtual void line(int x, int y, int x1, int y1) = 0; /** \brief see fl_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(int x, int y, int x1, int y1, int x2, int y2) = 0; /** \brief see fl_draw(const char *str, int n, int x, int y). */ virtual void draw(const char *str, int n, int x, int y) {} #ifdef __APPLE__ @@ -287,13 +287,13 @@ protected: /** \brief see fl_point(int x, int y). */ virtual void point(int x, int y) = 0; /** \brief see fl_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(int x0, int y0, int x1, int y1, int x2, int y2) = 0; /** \brief see fl_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(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; /** \brief see fl_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(int x0, int y0, int x1, int y1, int x2, int y2) = 0; /** \brief see fl_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(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) = 0; /** \brief see fl_begin_points(). */ virtual void begin_points(); /** \brief see fl_begin_line(). */ @@ -474,10 +474,22 @@ public: static Fl_Offscreen create_offscreen_with_alpha(int w, int h); #endif void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); - // --- recently moved implementations (see FL_PORTING efforts) + // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/quartz_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); }; // FIXME: add Fl_Quartz_Printer_Graphics_Driver @@ -515,10 +527,22 @@ public: 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); - // --- recently moved implementations (see FL_PORTING efforts) + // --- 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); 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); }; /** @@ -578,10 +602,22 @@ public: #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 - // --- recently moved implementations (see FL_PORTING efforts) + // --- 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); }; #endif @@ -637,6 +673,7 @@ public: There is no need to create any other object of this class. */ class FL_EXPORT Fl_Display_Device : public Fl_Surface_Device { + friend class Fl_Quartz_Graphics_Driver; static Fl_Display_Device *_display; // the platform display device #ifdef __APPLE__ friend class Fl_X; diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index 52f91ed18..0336238a4 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -66,6 +66,32 @@ public: unsigned int c = (r<<24)|(g<<16)|(b<<8); gl_color(c); } + // --- implementation will eventually be in src/fl_rect.cxx which includes src/cfg_gfx/xlib_rect.cxx + // --- line and polygon drawing with integer coordinates + void point(int x, int y) { + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); + } + void rect(int x, int y, int w, int h) { + glBegin(GL_LINE_LOOP); + glVertex2i(x, y); + glVertex2i(x+w, y); + glVertex2i(x+w, y+h); + glVertex2i(x, y+h); + glEnd(); + } + void rectf(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; + // OpenGL has the natural origin at the bottom left. Drawing in FLTK + // coordinates requires that we shift the rectangle one pixel up. + glBegin(GL_POLYGON); + glVertex2i(x, y-1); + glVertex2i(x+w, y-1); + glVertex2i(x+w, y+h-1); + glVertex2i(x, y+h-1); + glEnd(); + } void line(int x, int y, int x1, int y1) { glBegin(GL_LINE_STRIP); glVertex2i(x, y); @@ -73,6 +99,14 @@ public: glEnd(); point(x1, y1); } + void line(int x, int y, int x1, int y1, int x2, int y2) { + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); + point(x2, y2); + } void xyline(int x, int y, int x1) { glBegin(GL_LINE_STRIP); glVertex2i(x, y); @@ -121,29 +155,34 @@ public: glEnd(); point(x2, y3); } - // --- recently moved implementations (see FL_PORTING efforts) - void point(int x, int y) { - glBegin(GL_POINTS); - glVertex2i(x, y); + void loop(int x0, int y0, int x1, int y1, int x2, int y2) { + glBegin(GL_LINE_LOOP); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); glEnd(); } - void rect(int x, int y, int w, int h) { + void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { glBegin(GL_LINE_LOOP); - glVertex2i(x, y); - glVertex2i(x+w, y); - glVertex2i(x+w, y+h); - glVertex2i(x, y+h); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glVertex2i(x3, y3); glEnd(); } - void rectf(int x, int y, int w, int h) { - if (w<=0 || h<=0) return; - // OpenGL has the natural origin at the bottom left. Drawing in FLTK - // coordinates requires that we shift the rectangle one pixel up. + void polygon(int x0, int y0, int x1, int y1, int x2, int y2) { glBegin(GL_POLYGON); - glVertex2i(x, y-1); - glVertex2i(x+w, y-1); - glVertex2i(x+w, y+h-1); - glVertex2i(x, y+h-1); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); + } + void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + glBegin(GL_POLYGON); + glVertex2i(x0, y0); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glVertex2i(x3, y3); glEnd(); } }; @@ -681,7 +720,9 @@ void Fl_Gl_Window::draw() { glOrtho(-0.5, w()-0.5, h()-0.5, -0.5, -1, 1); // glOrtho(0, w(), h(), 0, -1, 1); glLineWidth(pixels_per_unit()); // should be 1 or 2 (2 if highres OpenGL) - + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // FIXME: push on state stack + glEnable(GL_BLEND); // FIXME: push on state stack + Fl_Window::draw(); glPopMatrix(); diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx index 7f495da62..2c34911d8 100644 --- a/src/fl_rect.cxx +++ b/src/fl_rect.cxx @@ -162,347 +162,6 @@ static int clip_x (int x) { #endif // USE_X11 -void Fl_Graphics_Driver::xyline(int x, int y, int x1) { -#if defined(USE_X11) - XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x1), clip_x(y)); -#elif defined(WIN32) - MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y); -#elif defined(__APPLE_QUARTZ__) - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit - (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles - of size one unit by line-width. - */ - CGContextFillRect(fl_gc, CGRectMake(x-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - CGContextFillRect(fl_gc, CGRectMake(x1-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement xyline" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) { -#if defined (USE_X11) - XPoint p[3]; - p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y); - p[1].x = p[2].x = clip_x(x1); p[2].y = clip_x(y2); - XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); -#elif defined(WIN32) - if (y2 < y) y2--; - else y2++; - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y); - LineTo(fl_gc, x1, y2); -#elif defined(__APPLE_QUARTZ__) - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y); - CGContextAddLineToPoint(fl_gc, x1, y2); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - CGContextFillRect(fl_gc, CGRectMake(x1 - fl_quartz_line_width_/2, y2-0.5, fl_quartz_line_width_, 1)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement xyline" -#else -#error unsupported platform -#endif -} - -void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { -#if defined(USE_X11) - XPoint p[4]; - p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y); - p[1].x = p[2].x = clip_x(x1); p[2].y = p[3].y = clip_x(y2); - p[3].x = clip_x(x3); - XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); -#elif defined(WIN32) - if(x3 < x1) x3--; - else x3++; - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y); - LineTo(fl_gc, x1, y2); - LineTo(fl_gc, x3, y2); -#elif defined(__APPLE_QUARTZ__) - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y); - CGContextAddLineToPoint(fl_gc, x1, y2); - CGContextAddLineToPoint(fl_gc, x3, y2); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - CGContextFillRect(fl_gc, CGRectMake(x3-0.5, y2 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement xyline" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::yxline(int x, int y, int y1) { -#if defined(USE_X11) - XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x), clip_x(y1)); -#elif defined(WIN32) - if (y1 < y) y1--; - else y1++; - MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1); -#elif defined(__APPLE_QUARTZ__) - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x, y1); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); - CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y1-0.5, fl_quartz_line_width_, 1)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement yxline" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) { -#if defined(USE_X11) - XPoint p[3]; - p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y); - p[1].y = p[2].y = clip_x(y1); p[2].x = clip_x(x2); - XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); -#elif defined(WIN32) - if (x2 > x) x2++; - else x2--; - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x, y1); - LineTo(fl_gc, x2, y1); -#elif defined(__APPLE_QUARTZ__) - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x, y1); - CGContextAddLineToPoint(fl_gc, x2, y1); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); - CGContextFillRect(fl_gc, CGRectMake(x2-0.5, y1 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement yxline" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { -#if defined(USE_X11) - XPoint p[4]; - p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y); - p[1].y = p[2].y = clip_x(y1); p[2].x = p[3].x = clip_x(x2); - p[3].y = clip_x(y3); - XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); -#elif defined(WIN32) - if(y3 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x, y1); - CGContextAddLineToPoint(fl_gc, x2, y1); - CGContextAddLineToPoint(fl_gc, x2, y3); - CGContextStrokePath(fl_gc); - if (Fl_Display_Device::high_resolution()) { - CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); - CGContextFillRect(fl_gc, CGRectMake(x2 - fl_quartz_line_width_/2, y3-0.5, fl_quartz_line_width_, 1)); - } - if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement yxline" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::line(int x, int y, int x1, int y1) { -#if defined(USE_X11) - XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1); -#elif defined(WIN32) - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y1); - // Draw the last point *again* because the GDI line drawing - // functions will not draw the last point ("it's a feature!"...) - SetPixel(fl_gc, x1, y1, fl_RGB()); -#elif defined(__APPLE_QUARTZ__) - if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextStrokePath(fl_gc); - if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement line" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { -#if defined(USE_X11) - XPoint p[3]; - p[0].x = x; p[0].y = y; - p[1].x = x1; p[1].y = y1; - p[2].x = x2; p[2].y = y2; - XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); -#elif defined(WIN32) - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y1); - LineTo(fl_gc, x2, y2); - // Draw the last point *again* because the GDI line drawing - // functions will not draw the last point ("it's a feature!"...) - SetPixel(fl_gc, x2, y2, fl_RGB()); -#elif defined(__APPLE_QUARTZ__) - if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextAddLineToPoint(fl_gc, x2, y2); - CGContextStrokePath(fl_gc); - if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement line" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) { -#if defined(USE_X11) - XPoint p[4]; - p[0].x = x; p[0].y = y; - p[1].x = x1; p[1].y = y1; - p[2].x = x2; p[2].y = y2; - p[3].x = x; p[3].y = y; - XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); -#elif defined(WIN32) - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y1); - LineTo(fl_gc, x2, y2); - LineTo(fl_gc, x, y); -#elif defined(__APPLE_QUARTZ__) - CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextAddLineToPoint(fl_gc, x2, y2); - CGContextClosePath(fl_gc); - CGContextStrokePath(fl_gc); - CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement loop" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { -#if defined(USE_X11) - XPoint p[5]; - p[0].x = x; p[0].y = y; - p[1].x = x1; p[1].y = y1; - p[2].x = x2; p[2].y = y2; - p[3].x = x3; p[3].y = y3; - p[4].x = x; p[4].y = y; - XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); -#elif defined(WIN32) - MoveToEx(fl_gc, x, y, 0L); - LineTo(fl_gc, x1, y1); - LineTo(fl_gc, x2, y2); - LineTo(fl_gc, x3, y3); - LineTo(fl_gc, x, y); -#elif defined(__APPLE_QUARTZ__) - CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextAddLineToPoint(fl_gc, x2, y2); - CGContextAddLineToPoint(fl_gc, x3, y3); - CGContextClosePath(fl_gc); - CGContextStrokePath(fl_gc); - CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement loop" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) { - XPoint p[4]; - p[0].x = x; p[0].y = y; - p[1].x = x1; p[1].y = y1; - p[2].x = x2; p[2].y = y2; -#if defined (USE_X11) - p[3].x = x; p[3].y = y; - XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0); - XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); -#elif defined(WIN32) - SelectObject(fl_gc, fl_brush()); - Polygon(fl_gc, p, 3); -#elif defined(__APPLE_QUARTZ__) - CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextAddLineToPoint(fl_gc, x2, y2); - CGContextClosePath(fl_gc); - CGContextFillPath(fl_gc); - CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement polygon" -#else -# error unsupported platform -#endif -} - -void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { - XPoint p[5]; - p[0].x = x; p[0].y = y; - p[1].x = x1; p[1].y = y1; - p[2].x = x2; p[2].y = y2; - p[3].x = x3; p[3].y = y3; -#if defined(USE_X11) - p[4].x = x; p[4].y = y; - XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0); - XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); -#elif defined(WIN32) - SelectObject(fl_gc, fl_brush()); - Polygon(fl_gc, p, 4); -#elif defined(__APPLE_QUARTZ__) - CGContextSetShouldAntialias(fl_gc, true); - CGContextMoveToPoint(fl_gc, x, y); - CGContextAddLineToPoint(fl_gc, x1, y1); - CGContextAddLineToPoint(fl_gc, x2, y2); - CGContextAddLineToPoint(fl_gc, x3, y3); - CGContextClosePath(fl_gc); - CGContextFillPath(fl_gc); - CGContextSetShouldAntialias(fl_gc, false); -#elif defined(FL_PORTING) -# pragma message "FL_PORTING: implement polygon" -#else -# error unsupported platform -#endif -} - //////////////////////////////////////////////////////////////// @@ -723,47 +382,192 @@ int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int #endif } -//////////////////////////////////////////////////////////////// - -/* - Matt: I wrote individual methods for every class. They are virtual, so the - correct function is called, depending on the active driver. - - By having individual methods, multiple drivers can co-exist, for example - Quartz, OpenGL, and a printer driver. - - The individual implementations should eventually go into files that are - included into this file, based on the configuration, for example: +//////////////////////////////////////////////////////////////// + +/* + Matt: I wrote individual methods for every class. They are virtual, so the + correct function is called, depending on the active driver. + + By having individual methods, multiple drivers can co-exist, for example + Quartz, OpenGL, and a printer driver. + + The individual implementations should eventually go into files that are + included into this file, based on the configuration, for example: + + src/cfg_gfx/quartz_rect.cxx + src/cfg_gfx/gdi_rect.cxx + src/cfg_gfx/xlib_rect.cxx + + Porting the graphics system to a new platform then requires to copy one of + these files and implement the virtual functions. point() is the only function + that *must* be implemented when deriving from 'Fl_Minimal_Graphics_Driver" + (which is still to be written) + */ + +//////////////////////////////////////////////////////////////// + +#ifdef FL_CFG_GFX_QUARTZ + +// --- line and polygon drawing with integer coordinates + +void Fl_Quartz_Graphics_Driver::point(int x, int y) { + CGContextFillRect(fl_gc, CGRectMake(x - 0.5, y - 0.5, 1, 1) ); +} + +void Fl_Quartz_Graphics_Driver::rect(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; + // FIXME: there should be a quartz graphics driver for the printer device that makes the USINGQUARTZPRINTER obsolete + if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGRect rect = CGRectMake(x, y, w-1, h-1); + CGContextStrokeRect(fl_gc, rect); + if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::rectf(int x, int y, int w, int h) { + if (w<=0 || h<=0) return; + CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h); + CGContextFillRect(fl_gc, rect); +} + +void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1) { + if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { + if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextStrokePath(fl_gc); + if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit + (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles + of size one unit by line-width. + */ + CGContextFillRect(fl_gc, CGRectMake(x-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + CGContextFillRect(fl_gc, CGRectMake(x1-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextAddLineToPoint(fl_gc, x1, y2); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + CGContextFillRect(fl_gc, CGRectMake(x1 - fl_quartz_line_width_/2, y2-0.5, fl_quartz_line_width_, 1)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y); + CGContextAddLineToPoint(fl_gc, x1, y2); + CGContextAddLineToPoint(fl_gc, x3, y2); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + CGContextFillRect(fl_gc, CGRectMake(x3-0.5, y2 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} + +void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); + CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y1-0.5, fl_quartz_line_width_, 1)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} - src/cfg_gfx/quartz_rect.cxx - src/cfg_gfx/gdi_rect.cxx - src/cfg_gfx/xlib_rect.cxx +void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextAddLineToPoint(fl_gc, x2, y1); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); + CGContextFillRect(fl_gc, CGRectMake(x2-0.5, y1 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} - Porting the graphics system to a new platform then requires to copy one of - these files and implement the virtual functions. point() is the only function - that *must* be implemented when deriving from 'Fl_Minimal_Graphics_Driver" - (which is still to be written) - */ +void Fl_Quartz_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x, y1); + CGContextAddLineToPoint(fl_gc, x2, y1); + CGContextAddLineToPoint(fl_gc, x2, y3); + CGContextStrokePath(fl_gc); + if (Fl_Display_Device::high_resolution()) { + CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1)); + CGContextFillRect(fl_gc, CGRectMake(x2 - fl_quartz_line_width_/2, y3-0.5, fl_quartz_line_width_, 1)); + } + if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +} -#ifdef FL_CFG_GFX_QUARTZ +void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) { + CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextClosePath(fl_gc); + CGContextStrokePath(fl_gc); + CGContextSetShouldAntialias(fl_gc, false); +} -void Fl_Quartz_Graphics_Driver::point(int x, int y) { - CGContextFillRect(fl_gc, CGRectMake(x - 0.5, y - 0.5, 1, 1) ); +void Fl_Quartz_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { + CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextAddLineToPoint(fl_gc, x3, y3); + CGContextClosePath(fl_gc); + CGContextStrokePath(fl_gc); + CGContextSetShouldAntialias(fl_gc, false); } -void Fl_Quartz_Graphics_Driver::rect(int x, int y, int w, int h) { - if (w<=0 || h<=0) return; - // FIXME: there should be a quartz graphics driver for the printer device that makes the USINGQUARTZPRINTER obsolete - if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); - CGRect rect = CGRectMake(x, y, w-1, h-1); - CGContextStrokeRect(fl_gc, rect); - if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); +void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) { + CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); + CGContextSetShouldAntialias(fl_gc, false); } -void Fl_Quartz_Graphics_Driver::rectf(int x, int y, int w, int h) { - if (w<=0 || h<=0) return; - CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h); - CGContextFillRect(fl_gc, rect); +void Fl_Quartz_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { + CGContextSetShouldAntialias(fl_gc, true); + CGContextMoveToPoint(fl_gc, x, y); + CGContextAddLineToPoint(fl_gc, x1, y1); + CGContextAddLineToPoint(fl_gc, x2, y2); + CGContextAddLineToPoint(fl_gc, x3, y3); + CGContextClosePath(fl_gc); + CGContextFillPath(fl_gc); + CGContextSetShouldAntialias(fl_gc, false); } #endif @@ -772,6 +576,8 @@ void Fl_Quartz_Graphics_Driver::rectf(int x, int y, int w, int h) { #ifdef FL_CFG_GFX_GDI +// --- line and polygon drawing with integer coordinates + void Fl_GDI_Graphics_Driver::point(int x, int y) { SetPixel(fl_gc, x, y, fl_RGB()); } @@ -793,12 +599,105 @@ void Fl_GDI_Graphics_Driver::rectf(int x, int y, int w, int h) { FillRect(fl_gc, &rect, fl_brush()); } +void Fl_GDI_Graphics_Driver::line(int x, int y, int x1, int y1) { + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + SetPixel(fl_gc, x1, y1, fl_RGB()); +} + +void Fl_GDI_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y1); + LineTo(fl_gc, x2, y2); + SetPixel(fl_gc, x2, y2, fl_RGB()); +} + +void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1) { + MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y); +} + +void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2) { + if (y2 < y) y2--; + else y2++; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y); + LineTo(fl_gc, x1, y2); +} + +void Fl_GDI_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { + if(x3 < x1) x3--; + else x3++; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x1, y); + LineTo(fl_gc, x1, y2); + LineTo(fl_gc, x3, y2); +} + +void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1) { + if (y1 < y) y1--; + else y1++; + MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1); +} + +void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2) { + if (x2 > x) x2++; + else x2--; + MoveToEx(fl_gc, x, y, 0L); + LineTo(fl_gc, x, y1); + LineTo(fl_gc, x2, y1); +} + +void Fl_GDI_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { + if(y3