diff --git a/CHANGES.txt b/CHANGES.txt index 97f1da18d..dead987d5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -18,6 +18,10 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2021 New Features and Extensions - (add new items here) + - The Windows platform now draws oblique and curved lines in antialiased + form. The new function void fl_antialias(int state); allows to turn off + or on such antialiased drawing. The new function int fl_antialias(); returns + whether line and curve drawing is currently antialiased. - The border radius of "rounded" box types can be limited and the shadow width of "shadow" box types can be configured (issue #130). See Fl::box_border_radius_max() and Fl::box_shadow_width(). @@ -104,6 +108,9 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2021 New Configuration Options (ABI Version) + - The new configure option --disable-gdiplus removes the possibility to draw + antialiased lines and curves on the Windows platform. The corresponding CMake + option is OPTION_USE_GDIPLUS. - The library can be built without support for reading SVG images or writing graphics in SVG format using the --disable-svg configure option or turning off OPTION_USE_SVG in CMake. diff --git a/CMake/fl_create_example.cmake b/CMake/fl_create_example.cmake index 22c418bc6..38ffe98e1 100644 --- a/CMake/fl_create_example.cmake +++ b/CMake/fl_create_example.cmake @@ -123,6 +123,9 @@ macro (CREATE_EXAMPLE NAME SOURCES LIBRARIES) target_link_directories (${TARGET_NAME} PRIVATE ${PKG_CAIRO_LIBRARY_DIRS}) endif() endif (FLTK_HAVE_CAIRO) + if (USE_GDIPLUS) # can only be true on Windows + target_link_libraries (${TARGET_NAME} gdiplus) + endif (USE_GDIPLUS) if (MAC_BUNDLE) if (PLIST) diff --git a/CMake/options.cmake b/CMake/options.cmake index cf50da6b8..e9e7a1db0 100644 --- a/CMake/options.cmake +++ b/CMake/options.cmake @@ -52,6 +52,16 @@ if (UNIX) list (APPEND FLTK_LDLIBS -lm) endif (UNIX) +if (WIN32) + option (OPTION_USE_GDIPLUS "use GDI+ when possible for antialiased graphics" ON) + if (OPTION_USE_GDIPLUS) + set (USE_GDIPLUS TRUE) + if (NOT MSVC) + list (APPEND FLTK_LDLIBS "-lgdiplus") + endif (NOT MSVC) + endif (OPTION_USE_GDIPLUS) +endif (WIN32) + ####################################################################### if (APPLE) option (OPTION_APPLE_X11 "use X11" OFF) diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 67b7a31bd..5d03e2c43 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -374,6 +374,8 @@ public: virtual float override_scale(); virtual void restore_scale(float); virtual PangoFontDescription* pango_font_description(Fl_Font fnum) { return NULL; } + virtual void antialias(int state); + virtual int antialias(); }; #ifndef FL_DOXYGEN diff --git a/FL/fl_draw.H b/FL/fl_draw.H index a84f310f8..9e2e4b3dd 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -238,6 +238,16 @@ enum { FL_JOIN_BEVEL = 0x3000 ///< join style: line join is tidied }; +/** + Turns ON or OFF antialiased line drawings, if supported by platform. + Currently, only the Windows platform allows to change whether line drawings are antialiased. + Turning it OFF may accelerate heavy drawing operations. + */ +inline void fl_antialias(int state) { fl_graphics_driver->antialias(state); } + +/** Returns whether line drawings are currently antialiased */ +inline int fl_antialias() { return fl_graphics_driver->antialias(); } + // rectangles tweaked to exactly fill the pixel rectangle: /** diff --git a/configh.cmake.in b/configh.cmake.in index b47774498..166687416 100644 --- a/configh.cmake.in +++ b/configh.cmake.in @@ -365,6 +365,14 @@ #cmakedefine FL_NO_PRINT_SUPPORT 1 +/* + * Do we use GDI+ to get antialiased graphics? + */ + +#ifdef _WIN32 +#cmakedefine01 USE_GDIPLUS +#endif + /* * Do we want filename handling and a filechooser? */ diff --git a/configh.in b/configh.in index f3133d7a2..3ef98ebae 100644 --- a/configh.in +++ b/configh.in @@ -358,6 +358,14 @@ #undef FL_NO_PRINT_SUPPORT +/* + * Do we use GDI+ to get antialiased graphics? + */ + +#ifdef _WIN32 +#define USE_GDIPLUS 0 +#endif + /* * Do we want filename handling and a filechooser? * *FIXME* Not yet implemented in configure ! diff --git a/configure.ac b/configure.ac index 9e36e685b..13dfe68f6 100644 --- a/configure.ac +++ b/configure.ac @@ -137,6 +137,21 @@ AC_ARG_ENABLE([xinerama], AS_HELP_STRING([--disable-xinerama], [turn off Xineram AC_ARG_ENABLE([xrender], AS_HELP_STRING([--disable-xrender], [turn off Xrender support])) +AS_CASE([$host_os], [cygwin* | mingw*], [ + AC_ARG_ENABLE([gdiplus], AS_HELP_STRING([--disable-gdiplus], [don't use GDI+ for antialiased graphics])) + + gdiplus_found=no + AS_IF([test x$enable_gdiplus != xno], [ + AC_CHECK_HEADERS([wtypes.h gdiplus.h], [ + AC_DEFINE([USE_GDIPLUS]) + LIBS="-lgdiplus $LIBS" + gdiplus_found=yes + ], [], + [[#include ]]) + ]) + +]) + AS_IF([test x$enable_pango = xyes -a x$enable_xft = xno], [ AC_MSG_ERROR([--disable-xft and --enable-pango are incompatible because Xft is necessary for Pango.]) ]) @@ -887,6 +902,7 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [ LDFLAGS="-mwindows $LDFLAGS" DSOFLAGS="-mwindows $DSOFLAGS" LIBS="$LIBS -lole32 -luuid -lcomctl32 -lws2_32" + BUILD="WIN" AS_IF([test "x$with_optim" = x], [ dnl Avoid -Os optimization on Cygwin/MinGW @@ -1522,7 +1538,7 @@ echo "Configuration Summary" echo "-------------------------------------------------------------------------" AS_CASE([$host_os_gui], [cygwin* | mingw*], [ - graphics="GDI" + AS_IF([test x$gdiplus_found = xyes], [graphics="GDI+"], [graphics="GDI"]) ], [darwin*], [ graphics="Quartz" ], [*], [ diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index 48df3eed8..2377d721f 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -78,6 +78,10 @@ if (FLTK_HAVE_CAIRO) endif() endif (FLTK_HAVE_CAIRO) +if (USE_GDIPLUS) # can only be true on Windows + target_link_libraries (fluid gdiplus) +endif (USE_GDIPLUS) + # install fluid if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL)) diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index d558b739b..8329355ba 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -676,6 +676,12 @@ void Fl_Graphics_Driver::transformed_vertex0(float x, float y) { } } +void Fl_Graphics_Driver::antialias(int state) {} + +int Fl_Graphics_Driver::antialias() { + return 0; +} + /** \} \endcond diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index 1ef76cb6c..3ca0744cc 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -613,6 +613,9 @@ public: // to work around it anyway. if (clipboard_wnd != NULL) fl_clipboard_notify_untarget(clipboard_wnd); +#if USE_GDIPLUS + Fl_GDIplus_Graphics_Driver::shutdown(); +#endif } }; static Fl_Win32_At_Exit win32_at_exit; diff --git a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx index 9ba2db85f..c1d845e6a 100644 --- a/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx @@ -42,7 +42,7 @@ Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_Surface_Driver(w, h) { - driver(new Fl_GDI_Graphics_Driver); + driver(Fl_Graphics_Driver::newMainGraphicsDriver()); oldgc = (HDC)Fl_Surface_Device::surface()->driver()->gc(); // exact computation of factor from screen units to EnhMetaFile units (0.01 mm) HDC hdc = GetDC(NULL); @@ -55,7 +55,7 @@ Fl_GDI_Copy_Surface_Driver::Fl_GDI_Copy_Surface_Driver(int w, int h) : Fl_Copy_S float factorh = (100.f * vmm) / vdots; // Global display scaling factor: 1, 1.25, 1.5, 1.75, etc... float scaling = Fl_Graphics_Driver::default_driver().scale(); - ((Fl_GDI_Graphics_Driver*)driver())->scale(scaling); + driver()->scale(scaling); RECT rect; rect.left = 0; rect.top = 0; rect.right = (LONG)((w*scaling) * factorw); rect.bottom = (LONG)((h*scaling) * factorh); gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); if (gc != NULL) { diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H index 76d9c5c01..824ad2fa7 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H @@ -26,6 +26,16 @@ #include #include #include +#include + +#if USE_GDIPLUS +# if defined(_MSC_VER) +# include +# else +# include // for PROPID needed with gcc 4.9.0 but not with 4.9.3 +# endif +# include +#endif /** \brief The Windows-specific graphics driver class. @@ -164,5 +174,42 @@ public: void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy); }; +#if USE_GDIPLUS + +class Fl_GDIplus_Graphics_Driver : public Fl_GDI_Graphics_Driver { +private: + Gdiplus::Color gdiplus_color_; + Gdiplus::Pen *pen_; + Gdiplus::SolidBrush *brush_; +public: + Fl_GDIplus_Graphics_Driver(); + virtual ~Fl_GDIplus_Graphics_Driver(); + bool active; + static void shutdown(void); +virtual void color(Fl_Color c); +virtual Fl_Color color() { return color_; } +virtual void color(uchar r, uchar g, uchar b); + virtual void line(int x, int y, int x1, int y1); + virtual void line(int x, int y, int x1, int y1, int x2, int y2); + void loop(int x0, int y0, int x1, int y1, int x2, int y2); + void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2); + void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3); + virtual void line_style(int style, int width, char* dashes); + virtual void arc_unscaled(int x, int y, int w, int h, double a1, double a2); + virtual void pie_unscaled(int x, int y, int w, int h, double a1, double a2); + virtual void transformed_vertex(double xf, double yf); + virtual void vertex(double x,double y); + virtual void end_points(); + virtual void end_line(); + virtual void end_loop(); + virtual void end_polygon(); + virtual void end_complex_polygon(); + virtual void circle(double x, double y, double r); + virtual void antialias(int state); + virtual int antialias(); +}; + +#endif // USE_GDIPLUS #endif // FL_GDI_GRAPHICS_DRIVER_H diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx index 3fe721907..0ee5cf99f 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx @@ -22,15 +22,58 @@ #include #include "../../Fl_Screen_Driver.H" +#if USE_GDIPLUS +static ULONG_PTR gdiplusToken = 0; + +Fl_GDIplus_Graphics_Driver::Fl_GDIplus_Graphics_Driver() : Fl_GDI_Graphics_Driver() { + if (!fl_current_xmap) color(FL_BLACK); + pen_ = new Gdiplus::Pen(gdiplus_color_, 1); + pen_->SetLineJoin(Gdiplus::LineJoinRound); + pen_->SetStartCap(Gdiplus::LineCapFlat); + pen_->SetEndCap(Gdiplus::LineCapFlat); + brush_ = new Gdiplus::SolidBrush(gdiplus_color_); + active = true; +} + +Fl_GDIplus_Graphics_Driver::~Fl_GDIplus_Graphics_Driver() { + delete pen_; + delete brush_; +} + +void Fl_GDIplus_Graphics_Driver::antialias(int state) { + active = state; +} + +int Fl_GDIplus_Graphics_Driver::antialias() { + return active; +} + +#endif + /* * By linking this module, the following static method will instantiate the * Windows GDI Graphics driver as the main display driver. */ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { +#if USE_GDIPLUS + // Initialize GDI+. + static Gdiplus::GdiplusStartupInput gdiplusStartupInput; + if (gdiplusToken == 0) GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + Fl_Graphics_Driver *driver = new Fl_GDIplus_Graphics_Driver(); + return driver; +#else return new Fl_GDI_Graphics_Driver(); +#endif } +#if USE_GDIPLUS +void Fl_GDIplus_Graphics_Driver::shutdown() { + Gdiplus::GdiplusShutdown(gdiplusToken); +} +#endif + // Code used to switch output to an off-screen window. See macros in // win32.H which save the old state in local variables. diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx index 32a5c1689..0c1e90064 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx @@ -61,3 +61,29 @@ void Fl_GDI_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } else Pie(gc_, int(x), int(y), int(x+w), int(y+h), xa, ya, xb, yb); } + +#if USE_GDIPLUS + +void Fl_GDIplus_Graphics_Driver::arc_unscaled(int x, int y, int w, int h, double a1, double a2) { + if (w <= 0 || h <= 0) return; + if (!active) return Fl_GDI_Graphics_Driver::arc_unscaled(x, y, w, h, a1, a2); + Gdiplus::Graphics graphics_(gc_); + pen_->SetColor(gdiplus_color_); + Gdiplus::REAL oldw = pen_->GetWidth(); + Gdiplus::REAL new_w = (line_width_ <= scale() ? 1 : line_width_) * scale(); + pen_->SetWidth(new_w); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.DrawArc(pen_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); + pen_->SetWidth(oldw); +} + +void Fl_GDIplus_Graphics_Driver::pie_unscaled(int x, int y, int w, int h, double a1, double a2) { + if (w <= 0 || h <= 0) return; + if (!active) return Fl_GDI_Graphics_Driver::pie_unscaled(x, y, w, h, a1, a2); + Gdiplus::Graphics graphics_(gc_); + brush_->SetColor(gdiplus_color_); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.FillPie(brush_, x, y, w, h, Gdiplus::REAL(-a1), Gdiplus::REAL(a1-a2)); +} + +#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx index 9e6466e92..c05a255d0 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx @@ -245,3 +245,15 @@ fl_select_palette(void) } #endif + +#if USE_GDIPLUS +void Fl_GDIplus_Graphics_Driver::color(uchar r, uchar g, uchar b) { + Fl_GDI_Graphics_Driver::color(r, g, b); + gdiplus_color_.SetFromCOLORREF(fl_RGB()); +} + +void Fl_GDIplus_Graphics_Driver::color(Fl_Color i) { + Fl_GDI_Graphics_Driver::color(i); + gdiplus_color_.SetFromCOLORREF(fl_RGB()); +} +#endif // USE_GDIPLUS diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx index 3371c4e08..140ddae63 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx @@ -14,6 +14,8 @@ // https://www.fltk.org/bugs.php // +#include + #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx index 91cfe2ca4..20418333b 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx @@ -59,3 +59,52 @@ void Fl_GDI_Graphics_Driver::line_style_unscaled(int style, int width, char* das DeleteObject(fl_current_xmap->pen); fl_current_xmap->pen = newpen; } + +#if USE_GDIPLUS + +void Fl_GDIplus_Graphics_Driver::line_style(int style, int width, char* dashes) { + if (!active) return Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); + int gdi_width = (width ? width : 1); + pen_->SetWidth(Gdiplus::REAL(gdi_width)); + int standard_dash = style & 0x7; + if (standard_dash == FL_DASH ) + pen_->SetDashStyle(Gdiplus::DashStyleDash); + else if (standard_dash == FL_DOT ) + pen_->SetDashStyle(Gdiplus::DashStyleDot); + else if (standard_dash == FL_DASHDOT ) + pen_->SetDashStyle(Gdiplus::DashStyleDashDot); + else if (standard_dash == FL_DASHDOTDOT ) + pen_->SetDashStyle(Gdiplus::DashStyleDashDotDot); + else if(!dashes || !*dashes) + pen_->SetDashStyle(Gdiplus::DashStyleSolid); + + if (style & FL_CAP_ROUND ) { + pen_->SetStartCap(Gdiplus::LineCapRound); + pen_->SetEndCap(Gdiplus::LineCapRound); + } else if (style & FL_CAP_SQUARE ) { + pen_->SetStartCap(Gdiplus::LineCapSquare); + pen_->SetEndCap(Gdiplus::LineCapSquare); + } else { + pen_->SetStartCap(Gdiplus::LineCapFlat); + pen_->SetEndCap(Gdiplus::LineCapFlat); + } + + if (style & FL_JOIN_MITER ) { + pen_->SetLineJoin(Gdiplus::LineJoinMiter); + } else if (style & FL_JOIN_BEVEL ) { + pen_->SetLineJoin(Gdiplus::LineJoinBevel); + } else { + pen_->SetLineJoin(Gdiplus::LineJoinRound); + } + + if (dashes && *dashes) { + int n = 0; while (dashes[n]) n++; + Gdiplus::REAL *gdi_dashes = new Gdiplus::REAL[n]; + for (int i = 0; i < n; i++) gdi_dashes[i] = dashes[i]/float(gdi_width); + pen_->SetDashPattern(gdi_dashes, n); + delete[] gdi_dashes; + } + Fl_Scalable_Graphics_Driver::line_style(style, width, dashes); +} + +#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx index e7aac901c..76b546092 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx @@ -211,3 +211,95 @@ void Fl_GDI_Graphics_Driver::restore_clip() { if (r) unscale_clip(r); } } + +#if USE_GDIPLUS + +void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1) { + if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1); + bool AA = !(x == x1 || y == y1); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + pen_->SetColor(gdiplus_color_); + if (AA) graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.DrawLine(pen_, x, y, x1, y1); +} + +void Fl_GDIplus_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { + if (!active) return Fl_Scalable_Graphics_Driver::line(x, y, x1, y1, x2, y2); + line(x, y, x1, y1); + line(x1, y1, x2, y2); +} + +void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) { + if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2); + Gdiplus::GraphicsPath path; + Gdiplus::Point gdi2_p[3] = {Gdiplus::Point(x0, y0), Gdiplus::Point(x1, y1), Gdiplus::Point(x2, y2)}; + path.AddLines(gdi2_p, 3); + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + pen_->SetColor(gdiplus_color_); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.DrawPath(pen_, &path); +} + +#define fl_min(a,b) (a < b ? a : b) +#define fl_max(a,b) (a > b ? a : b) +void Fl_GDIplus_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || + (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { // rectangular loop + int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); + int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); + int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); + int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); + rect(left, top, right-left+1, bottom-top+1); + } else { + if (!active) return Fl_Scalable_Graphics_Driver::loop(x0, y0, x1, y1, x2, y2, x3, y3); + Gdiplus::GraphicsPath path; + Gdiplus::PointF gdi2_p[4] = {Gdiplus::PointF(x0+1-line_width_/2.f, y0+1-line_width_/2.f), Gdiplus::PointF(x1+1-line_width_/2.f, y1+1-line_width_/2.f), Gdiplus::PointF(x2+1-line_width_/2.f, y2+1-line_width_/2.f), Gdiplus::PointF(x3+1-line_width_/2.f, y3+1-line_width_/2.f)}; + path.AddLines(gdi2_p, 4); + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + pen_->SetColor(gdiplus_color_); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.DrawPath(pen_, &path); + } +} + +void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2) { + if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2); + Gdiplus::GraphicsPath path; + path.AddLine(x0, y0, x1, y1); + path.AddLine(x1, y1, x2, y2); + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + brush_->SetColor(gdiplus_color_); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.FillPath(brush_, &path); +} + +void Fl_GDIplus_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + if ( (x0 == x3 && x1 == x2 && y0 == y1 && y3 == y2) || + (x0 == x1 && y1 == y2 && x2 == x3 && y3 == y0) ) { + int left = fl_min(x0, fl_min(x1, fl_min(x2, x3))); + int right = fl_max(x0, fl_max(x1, fl_max(x2, x3))); + int top = fl_min(y0, fl_min(y1, fl_min(y2, y3))); + int bottom = fl_max(y0, fl_max(y1, fl_max(y2, y3))); + rectf(left, top, right-left, bottom-top); + } else { + if (!active) return Fl_Scalable_Graphics_Driver::polygon(x0, y0, x1, y1, x2, y2, x3, y3); + Gdiplus::GraphicsPath path; + path.AddLine(x0, y0, x1, y1); + path.AddLine(x1, y1, x2, y2); + path.AddLine(x2, y2, x3, y3); + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + brush_->SetColor(gdiplus_color_); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + graphics_.FillPath(brush_, &path); + } +} +#endif diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx index 2f8e80232..8deb3f51d 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx @@ -98,3 +98,134 @@ void Fl_GDI_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, d } else Arc(gc_, llx, lly, llx+w, lly+h, 0,0, 0,0); } + +#if USE_GDIPLUS + +void Fl_GDIplus_Graphics_Driver::transformed_vertex(double xf, double yf) { + if (!active) return Fl_Scalable_Graphics_Driver::transformed_vertex(xf, yf); + transformed_vertex0(float(xf) , float(yf) ); +} + +void Fl_GDIplus_Graphics_Driver::vertex(double x,double y) { + if (!active) return Fl_Scalable_Graphics_Driver::vertex(x, y); + transformed_vertex0(float(x*m.a + y*m.c + m.x) , float(x*m.b + y*m.d + m.y) ); +} + +void Fl_GDIplus_Graphics_Driver::end_points() { + if (!active) return Fl_GDI_Graphics_Driver::end_points(); + for (int i = 0; i < n; i++) point(p[i].x, p[i].y); +} + +void Fl_GDIplus_Graphics_Driver::end_line() { + if (!active) return Fl_GDI_Graphics_Driver::end_line(); + if (n < 2) { + end_points(); + return; + } + if (n>1) { + Gdiplus::GraphicsPath path; + Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; + for (int i = 0; i < n; i++) { + gdi2_p[i] = Gdiplus::Point(p[i].x, p[i].y); + } + path.AddLines(gdi2_p, n); + delete[] gdi2_p; + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + pen_->SetColor(gdiplus_color_); + graphics_.DrawPath(pen_, &path); + } +} + +void Fl_GDIplus_Graphics_Driver::end_loop() { + if (!active) return Fl_GDI_Graphics_Driver::end_loop(); + fixloop(); + if (n>2) { + Gdiplus::GraphicsPath path; + Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; + for (int i = 0; i < n; i++) { + gdi2_p[i] = Gdiplus::Point(p[i].x, p[i].y); + } + path.AddLines(gdi2_p, n); + path.CloseFigure(); + delete[] gdi2_p; + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + pen_->SetColor(gdiplus_color_); + graphics_.DrawPath(pen_, &path); + } +} + +void Fl_GDIplus_Graphics_Driver::end_polygon() { + if (!active) return Fl_GDI_Graphics_Driver::end_polygon(); + fixloop(); + if (n < 3) { + end_line(); + return; + } + if (n>2) { + Gdiplus::GraphicsPath path; + Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; + for (int i = 0; i < n; i++) { + gdi2_p[i] = Gdiplus::Point(p[i].x, p[i].y); + } + path.AddPolygon(gdi2_p, n); + delete[] gdi2_p; + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + brush_->SetColor(gdiplus_color_); + graphics_.FillPath(brush_, &path); + } +} + +void Fl_GDIplus_Graphics_Driver::end_complex_polygon() { + if (!active) return Fl_GDI_Graphics_Driver::end_complex_polygon(); + gap(); + if (n < 3) { + end_line(); + return; + } + if (n>2) { + Gdiplus::GraphicsPath path; + Gdiplus::Point *gdi2_p = new Gdiplus::Point[n]; + for (int i = 0; i < n; i++) { + gdi2_p[i] = Gdiplus::Point(p[i].x, p[i].y); + } + path.AddPolygon(gdi2_p, n); + delete[] gdi2_p; + path.CloseFigure(); + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + brush_->SetColor(gdiplus_color_); + graphics_.FillPath(brush_, &path); + } +} + +void Fl_GDIplus_Graphics_Driver::circle(double x, double y, double r) { + if (!active) return Fl_Scalable_Graphics_Driver::circle(x, y, r); + double xt = transform_x(x,y); + double yt = transform_y(x,y); + double rx = r * (m.c ? sqrt(m.a*m.a+m.c*m.c) : fabs(m.a)); + double ry = r * (m.b ? sqrt(m.b*m.b+m.d*m.d) : fabs(m.d)); + int llx = (int)rint(xt-rx); + int w = (int)rint(xt+rx)-llx; + int lly = (int)rint(yt-ry); + int h = (int)rint(yt+ry)-lly; + Gdiplus::Graphics graphics_(gc_); + graphics_.ScaleTransform(scale(), scale()); + graphics_.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); + if (what==POLYGON) { + brush_->SetColor(gdiplus_color_); + graphics_.FillPie(brush_, llx, lly, w, h, 0, 360); + } else { + pen_->SetColor(gdiplus_color_); + graphics_.DrawArc(pen_, llx, lly, w, h, 0, 360); + } +} +#endif + diff --git a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx index a7b9f1e8c..09a1a7e2a 100644 --- a/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx +++ b/src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx @@ -51,7 +51,7 @@ Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_ HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc(); offscreen = off ? off : CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h); if (!offscreen) offscreen = CreateCompatibleBitmap(fl_GetDC(0), w, h); - driver(new Fl_GDI_Graphics_Driver); + driver(Fl_Graphics_Driver::newMainGraphicsDriver()); if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d); origin.x = origin.y = 0; } diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index 4f868238c..f59a39d79 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -172,6 +172,8 @@ protected: virtual void overlay_rect(int x, int y, int w , int h); virtual float override_scale(); virtual void restore_scale(float); + virtual void antialias(int state); + virtual int antialias(); }; class Fl_Quartz_Printer_Graphics_Driver : public Fl_Quartz_Graphics_Driver { diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx index 6dbad2684..c18f7c300 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx @@ -52,6 +52,13 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() return new Fl_Quartz_Graphics_Driver(); } +void Fl_Quartz_Graphics_Driver::antialias(int state) { +} + +int Fl_Quartz_Graphics_Driver::antialias() { + return 1; +} + Fl_Quartz_Graphics_Driver::Fl_Quartz_Graphics_Driver() : Fl_Graphics_Driver(), gc_(NULL) { quartz_line_width_ = 1.f; quartz_line_cap_ = kCGLineCapButt;