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

This commit is contained in:
ManoloFLTK 2021-02-26 18:00:07 +01:00
parent d95dd7acc4
commit b027d2ba57
23 changed files with 492 additions and 4 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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:
/**

View File

@ -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?
*/

View File

@ -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 !

View File

@ -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"
], [*], [

View File

@ -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))

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include <config.h>
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;