[master] b027d2b - Windows platform: use GDI+ to antialias oblique lines and curves.

FLTK matrix user chat room
(using Element browser app)   FLTK gitter user chat room   GitHub FLTK Project   FLTK News RSS Feed  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 All Forums  |  Back to fltk.commit  ]
 
Previous Message ]Next Message ]

[master] b027d2b - Windows platform: use GDI+ to antialias oblique lines and curves. "ManoloFLTK" May 30, 2021 top right image
 
commit b027d2ba57a8e0d6f0862e0a891ddd5dee4b02e2
Author:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
AuthorDate: Fri Feb 26 18:00:07 2021 +0100
Commit:     ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>
CommitDate: Mon May 31 08:28:06 2021 +0200

    Windows platform: use GDI+ to antialias oblique lines and curves.

 CHANGES.txt                                        |   7 ++
 CMake/fl_create_example.cmake                      |   3 +
 CMake/options.cmake                                |  10 ++
 FL/Fl_Graphics_Driver.H                            |   2 +
 FL/fl_draw.H                                       |  10 ++
 configh.cmake.in                                   |   8 ++
 configh.in                                         |   8 ++
 configure.ac                                       |  18 ++-
 fluid/CMakeLists.txt                               |   4 +
 src/Fl_Graphics_Driver.cxx                         |   6 +
 src/Fl_win32.cxx                                   |   3 +
 src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx     |   4 +-
 src/drivers/GDI/Fl_GDI_Graphics_Driver.H           |  47 ++++++++
 src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx         |  43 +++++++
 src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx    |  26 ++++
 src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx   |  12 ++
 src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx    |   2 +
 .../GDI/Fl_GDI_Graphics_Driver_line_style.cxx      |  49 ++++++++
 src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx    |  92 +++++++++++++++
 src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx  | 131 +++++++++++++++++++++
 src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx    |   2 +-
 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H     |   2 +
 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx   |   7 ++
 23 files changed, 492 insertions(+), 4 deletions(-)

diff --git CHANGES.txt CHANGES.txt
index 97f1da1..dead987 100644
--- CHANGES.txt
+++ 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 CMake/fl_create_example.cmake CMake/fl_create_example.cmake
index 22c418b..38ffe98 100644
--- CMake/fl_create_example.cmake
+++ 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 CMake/options.cmake CMake/options.cmake
index cf50da6..e9e7a1d 100644
--- CMake/options.cmake
+++ 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 FL/Fl_Graphics_Driver.H FL/Fl_Graphics_Driver.H
index 67b7a31..5d03e2c 100644
--- FL/Fl_Graphics_Driver.H
+++ 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 FL/fl_draw.H FL/fl_draw.H
index a84f310..9e2e4b3 100644
--- FL/fl_draw.H
+++ 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 configh.cmake.in configh.cmake.in
index b477744..1666874 100644
--- configh.cmake.in
+++ configh.cmake.in
@@ -366,6 +366,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 configh.in configh.in
index f3133d7..3ef98eb 100644
--- configh.in
+++ configh.in
@@ -359,6 +359,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 configure.ac configure.ac
index 9e36e68..13dfe68 100644
--- configure.ac
+++ 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 <wtypes.h>]])
+    ])
+
+])
+
 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 fluid/CMakeLists.txt fluid/CMakeLists.txt
index 48df3ee..2377d72 100644
--- fluid/CMakeLists.txt
+++ 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 src/Fl_Graphics_Driver.cxx src/Fl_Graphics_Driver.cxx
index d558b73..8329355 100644
--- src/Fl_Graphics_Driver.cxx
+++ 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 src/Fl_win32.cxx src/Fl_win32.cxx
index 1ef76cb..3ca0744 100644
--- src/Fl_win32.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
index 9ba2db8..c1d845e 100644
--- src/drivers/GDI/Fl_GDI_Copy_Surface_Driver.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Graphics_Driver.H src/drivers/GDI/Fl_GDI_Graphics_Driver.H
index 76d9c5c..824ad2f 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.H
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.H
@@ -26,6 +26,16 @@
 #include <FL/Fl_Graphics_Driver.H>
 #include <windows.h>
 #include <stdlib.h>
+#include <config.h>
+
+#if USE_GDIPLUS
+#  if defined(_MSC_VER)
+#    include <objidl.h>
+#  else
+#    include <wtypes.h> // for PROPID needed with gcc 4.9.0 but not with 4.9.3
+#  endif
+#  include <gdiplus.h>
+#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 src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
index 3fe7219..0ee5cf9 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver.cxx
@@ -22,15 +22,58 @@
 #include <FL/fl_draw.H>
 #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 src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
index 32a5c16..0c1e900 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_arci.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
index 9e6466e..c05a255 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_color.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
index 3371c4e..140ddae 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
+++ src/drivers/GDI/Fl_GDI_Graphics_Driver_font.cxx
@@ -14,6 +14,8 @@
 //     https://www.fltk.org/bugs.php
 //
 
+#include <config.h>
+
 #ifndef WIN32_LEAN_AND_MEAN
 # define WIN32_LEAN_AND_MEAN
 #endif
diff --git src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
index 91cfe2c..2041833 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_line_style.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
index e7aac90..76b5460 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_rect.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
index 2f8e802..8deb3f5 100644
--- src/drivers/GDI/Fl_GDI_Graphics_Driver_vertex.cxx
+++ 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 src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
index a7b9f1e..09a1a7e 100644
--- src/drivers/GDI/Fl_GDI_Image_Surface_Driver.cxx
+++ 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 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
index 4f86823..f59a39d 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H
+++ 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 src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
index 6dbad26..c18f7c3 100644
--- src/drivers/Quartz/Fl_Quartz_Graphics_Driver.cxx
+++ 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;
Direct Link to Message ]
 
bottom left image   bottom right image
Previous Message ]Next Message ]
 
 

Comments are owned by the poster. All other content is copyright 1998-2022 by Bill Spitzak and others. This project is hosted by The FLTK Team. Please report site problems to 'erco@seriss.com'.